W!o+ 認為一個『實驗』的『結束』,也只是『探索』之『開始』。或許舊的疑惑未解!新的疑惑又生!!因此『分析』結果,『整理 』資料 ,『思辨』要點,『綜合』通盤 …… ,『準備』下次『實驗 』計畫 ,正是『科學求知』的方法。………
固然總有『不知』的時候?總有『不能』的情況??此時恰好困知勉行乎!也許終有『知之』的一天吧!?
之前的實驗結果,一起頭就叫人訝異︰
# 關閉電源,重新開機。確定 Arduino 在 Hard Reset 狀態。 pi@raspberrypi ~/example $ python Python 2.7.9 (default, Mar 8 2015, 00:52:26) [GCC 4.9.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import grovepi >>> addr = 0x05 # 韌體 Wire 程式庫,如何處理『未下指令』之 I2C 『讀取』 # 位元組讀取 >>> grovepi.read_i2c_byte(addr) 0 # 區塊讀取 >>> grovepi.read_i2c_block(addr) [11, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255] # 長度 32 ? >>> len(grovepi.read_i2c_block(addr)) 32 # Grove – Rotary Angle Sensor 測試。命令 3 >>> potentiometer = 0 # 設定 pinMode 為輸入。命令 5 >>> grovepi.pinMode(potentiometer,"INPUT") 1 # 讀取值 >>> sensor_value = grovepi.analogRead(potentiometer) 0 [11, 2, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255] # 傳回值 >>> sensor_value 703 ………
。就讓我們從此處展開探索之旅耶!!
先匯總『問題』如下︰
‧ 為什麼『未下指令』,還能無誤讀取?
‧ 為什麼『位元組讀取』,傳回值為 0 ?
‧ 為什麼『區塊讀取』,傳回長度是 32 ?
‧ 為什麼『Grove – Rotary Angle Sensor』測試,序列埠沒有輸出?
‧………
經過多次查詢以及閱讀,『整理』與之相關資料如下︰
☆【 ATmega CPU DataSheet 】
ATmega48A/PA/88A/PA/168A/PA/328/P
第二零六頁
22. 2-wire Serial Interface
22.1 Features
‧ Simple Yet Powerful and Flexible Communication Interface, only ‧ ‧ ‧ ‧ two Bus Lines Needed
‧ Both Master and Slave Operation Supported
‧ Device can Operate as Transmitter or Receiver
‧ 7-bit Address Space Allows up to 128 Different Slave Addresses
‧ Multi-master Arbitration Support
‧ Up to 400kHz Data Transfer Speed
‧ Slew-rate Limited Output Drivers
‧ Noise Suppression Circuitry Rejects Spikes on Bus Lines
‧ Fully Programmable Slave Address with General Call Support
‧ Address Recognition Causes Wake-up When AVR is in Sleep Mode
‧ Compatible with Philips’ I2C protocol
……
從屬接收模式
從屬傳送模式
☆ pi@raspberrypi /usr/share/arduino/libraries/Wire/utility $ ls
twi.c twi.h
pi@raspberrypi /usr/share/arduino/libraries/Wire/utility $ pwd
/usr/share/arduino/libraries/Wire/utility
/* twi.c - TWI/I2C library for Wiring & Arduino Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ // Slave Receiver case TW_SR_SLA_ACK: // addressed, returned ack case TW_SR_GCALL_ACK: // addressed generally, returned ack case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack // enter slave receiver mode twi_state = TWI_SRX; // indicate that rx buffer can be overwritten and ack twi_rxBufferIndex = 0; twi_reply(1); break; case TW_SR_DATA_ACK: // data received, returned ack case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack // if there is still room in the rx buffer if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ // put byte in buffer and ack twi_rxBuffer[twi_rxBufferIndex++] = TWDR; twi_reply(1); }else{ // otherwise nack twi_reply(0); } break; case TW_SR_STOP: // stop or repeated start condition received // put a null char after data if there's room if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ twi_rxBuffer[twi_rxBufferIndex] = '\0'; } // sends ack and stops interface for clock stretching twi_stop(); # 重點 // callback to user defined callback twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); // since we submit rx buffer to "wire" library, we can reset it twi_rxBufferIndex = 0; // ack future responses and leave slave receiver state twi_releaseBus(); break; case TW_SR_DATA_NACK: // data received, returned nack case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack // nack back at master twi_reply(0); break; // Slave Transmitter case TW_ST_SLA_ACK: // addressed, returned ack case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack // enter slave transmitter mode twi_state = TWI_STX; // ready the tx buffer index for iteration twi_txBufferIndex = 0; // set tx buffer length to be zero, to verify if user changes it twi_txBufferLength = 0; // request for txBuffer to be filled and length to be set # 重點 // note: user must call twi_transmit(bytes, length) to do this twi_onSlaveTransmit(); # 要點 // if they didn't change buffer & length, initialize it if(0 == twi_txBufferLength){ twi_txBufferLength = 1; twi_txBuffer[0] = 0x00; } // transmit first byte from buffer, fall case TW_ST_DATA_ACK: // byte sent, ack returned // copy data to output register TWDR = twi_txBuffer[twi_txBufferIndex++]; // if there is more to send, ack, otherwise nack if(twi_txBufferIndex < twi_txBufferLength){ twi_reply(1); }else{ twi_reply(0); } break; /* * Function twi_attachSlaveRxEvent * Desc sets function called before a slave read operation * Input function: callback function to use * Output none */ void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) { twi_onSlaveReceive = function; } /* * Function twi_attachSlaveTxEvent * Desc sets function called before a slave write operation * Input function: callback function to use * Output none */ void twi_attachSlaveTxEvent( void (*function)(void) ) { twi_onSlaveTransmit = function; }
☆ 【 Arduino Wire 程式庫】深度闡釋
:: Wire Library, Explored
An indepth reference to the Arduino Wire library.
☆ 『 Linux/Documentation/i2c/smbus-protocol 』
I2C Block Transactions
======================
The following I2C block transactions are supported by the SMBus layer and are described here for completeness. They are *NOT* defined by the SMBus specification.
I2C block transactions do not limit the number of bytes transferred but the SMBus layer places a limit of 32 bytes.
I2C Block Read: i2c_smbus_read_i2c_block_data()
================================================
This command reads a block of bytes from a device, from a designated register that is specified through the Comm byte.
S Addr Wr [A] Comm [A]
S Addr Rd [A] [Data] A [Data] A … A [Data] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK
I2C Block Write: i2c_smbus_write_i2c_block_data()
==================================================
The opposite of the Block Read command, this writes bytes to a device, to a designated register that is specified through the Comm byte. Note that command lengths of 0, 2, or more bytes are supported as they are indistinguishable from data.
S Addr Wr [A] Comm [A] Data [A] Data [A] … [A] Data [A] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
☆ 『 i2c-tools_3.1.0.orig.tar.bz2 』
/* * smbusmodule.c - Python bindings for Linux SMBus access through i2c-dev * Copyright (C) 2005-2007 Mark M. Hoffman <mhoffman@lightlink.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ PyDoc_STRVAR(SMBus_read_i2c_block_data_doc, "read_i2c_block_data(addr, cmd, len=32) -> results\n\n" "Perform I2C Block Read transaction.\n"); static PyObject * SMBus_read_i2c_block_data(SMBus *self, PyObject *args) { # 要點 int addr, cmd, len=32; union i2c_smbus_data data; if (!PyArg_ParseTuple(args, "ii|i:read_i2c_block_data", &addr, &cmd, &len)) return NULL; SMBus_SET_ADDR(self, addr); data.block[0] = len; /* save a bit of code by calling the access function directly */ if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd, len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN: I2C_SMBUS_I2C_BLOCK_DATA, &data)) { PyErr_SetFromErrno(PyExc_IOError); return NULL; } /* first byte of the block contains (remaining) data length */ return SMBus_buf_to_list(&data.block[1], data.block[0]); } PyDoc_STRVAR(SMBus_write_i2c_block_data_doc, "write_i2c_block_data(addr, cmd, [vals])\n\n" "Perform I2C Block Write transaction.\n"); static PyObject * SMBus_write_i2c_block_data(SMBus *self, PyObject *args) { int addr, cmd; union i2c_smbus_data data; if (!PyArg_ParseTuple(args, "iiO&:write_i2c_block_data", &addr, &cmd, SMBus_list_to_data, &data)) return NULL; SMBus_SET_ADDR(self, addr); /* save a bit of code by calling the access function directly */ if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd, I2C_SMBUS_I2C_BLOCK_BROKEN, &data)) { PyErr_SetFromErrno(PyExc_IOError); return NULL; } Py_INCREF(Py_None); return Py_None; }
同時也參考他人之討論︰
☆ 『 [I2C] onRequest and onReceive as slave with Raspberry Pi Master 』
I discovered a big Problem for my Project today. I try to connect a few Arduinos to a Raspberry Pi with I2C. I have a onRequest and a onReceive function (code below). On my Raspberry Pi I use smbus with python.My onReceive function works fine and well, every “bus.write[…]” function calls my onReceive function as it should.
But not onRequest. Only when i call “read_byte(addr)” in my python script, the Arduino will call the onRequest function. But it is necessary that I can use at least “byte read_byte_data(addr,cmd)” or “long[] read_block_data(addr,cmd)”. These functions call the onReceive Method, whyever.So I thought “no Problem”, just use onReceive like onRequest and write data there. But then the BUS is corrupted and the Python on Raspberry Pi gets an I/O Error.I just recognized that with the command “print bus.read_i2c_block_data(0x04, 0x01)” it prints nearly the right output (take a look in my log below), but on my Arduino Serial connection the “dataRequest() called with command” is not printed. I just don’t understand o_OI don’t know what I’m doing wrong o_O. Can someone explain this?Best regards
brainvoid
───
請判斷,這是否足以『回答』上述『問題』?能夠『準備』新實驗『計劃』的呢??