W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計《地圖》

既已渡河,若是缺少地圖,怕會走許多冤枉路。在此略作整理 GrovePi 的官方文件,以為嚮導︰

【程式篇】

 

【派生 API 界面篇】

Python Library Documentation

The python library (Available at github) for grove pi has three types of functions:

  1. Basic Arduino Functions
  2. Grove Specific Functions
  3. Private Functions for Communication

………

 

【韌體 I2C 通訊篇】

GrovePi Protocol and Adding Custom Sensors

tl;dr- For each operation that you want to do on the GrovePi, the Raspberry Pi sends a command via I2C to the GrovePi and waits for a response for the command from the GrovePi. When it receives the response, it interprets the data and returns the desired output.

Explanation in depth

We will look into how the working of the GrovePi with an example of the Ultrasonic Ranger. The Ultrasonic ranger connects to a digital port and gives out the range in cm.

working_python1

If you look at the above code, the function ultrasonicRead(pin), is repeatedly called to print the distance measured by the ranger.

The ultrasonicRead() is defined in GrovePi.py and is called every time. The Raspberry Pi sends the command to the GrovePi, waits for some time and requests the data back.

In the main python library, the RaspberryPi writes a block of data to the GrovePi whose address is 0x04 and the block which is sent has the following format(5 bytes).

dataformat

For a new sensor, you can create a new unique id and send the required data to the Grove Pi.

working_python1

In the main loop of the GrovePi, there is a case for each of the unique id. When a unique id is received the relevant code is executed and the data is stores in the b[] buffer(b[0] is dummy and should not be used). The Raspberry Pi then asks for the data to be returned back and the Grove Pi sends the bytes depending on the last command executed.

The processing and interpretation of the data is performed by the Python code on the Raspberry Pi and the output is returned back to the calling function.

………

 

初步瀏覽比對,發現『 GrovePi.py 』當是『 grovepi.py』。若思『範例』能講的清楚明白,或應補足

GrovePi/Software/Python/grovepi.py

程式主架構說明︰

# grovepi 主架構

# 命令碼
67 # Command Format
68 # digitalRead() command format header
69 dRead_cmd = [1]
70 # digitalWrite() command format header
71 dWrite_cmd = [2]
72 # analogRead() command format header
73 aRead_cmd = [3]
74 # analogWrite() command format header
75 aWrite_cmd = [4]
76 # pinMode() command format header
77 pMode_cmd = [5]
78 # Ultrasonic read
79 uRead_cmd = [7]

# 與 Arduino 韌體 I2C 讀寫通訊
162 # Write I2C block
163 def write_i2c_block(address, block):
164         try:
165                 return bus.write_i2c_block_data(address, 1, block)
166         except IOError:
167                 if debug:
168                         print ("IOError")
169                 return -1
170
171 # Read I2C byte
172 def read_i2c_byte(address):
173         try:
174                 return bus.read_byte(address)
175         except IOError:
176                 if debug:
177                         print ("IOError")
178                 return -1
179
180
181 # Read I2C block
182 def read_i2c_block(address):
183         try:
184                 return bus.read_i2c_block_data(address, 1)
185         except IOError:
186                 if debug:
187                         print ("IOError")
188                 return -1

# 派生 API 界面
243 # Read value from Grove Ultrasonic
244 def ultrasonicRead(pin):
245         write_i2c_block(address, uRead_cmd + [pin, unused, unused])
246         time.sleep(.2)
247         read_i2c_byte(address)
248         number = read_i2c_block(address)
249         return (number[1] * 256 + number[2])

 

欲創寫新裝置驅動者,務須知『韌體端』之對應面︰

# GrovePi V1.2.5 韌體

125  //Ultrasonic Read
126  else if(cmd[0]==7)
127  {
128    pin=cmd[1];
129    pinMode(pin, OUTPUT);
130    digitalWrite(pin, LOW);
131    delayMicroseconds(2);
132    digitalWrite(pin, HIGH);
133    delayMicroseconds(5);
134    digitalWrite(pin,LOW);
135    pinMode(pin,INPUT);
136    dur = pulseIn(pin,HIGH);
137    RangeCm = dur/29/2;
138    b[1]=RangeCm/256;
139    b[2]=RangeCm%256;
140    //Serial.println(b[1]);
141    //Serial.println(b[2]);
142  }