Folks, I cringe to bring this up as it has been discussed frequently, but I am at a loss.
Background: I have a Raspberry project with about 3000 lines of Python3 code and want to add a wireless Arduino sensor. I seem to have all the individual parts working - the Arduino sensor board with transmitter and Arduino receiver board hooked up to the Pi via I2C. Reading and writing individual bytes works in both directions, as do the radios using SPI. But when I try to get a full block of data I fall flat on my face.
Some details:
uname -a
Linux pietester 4.14.52-v7+ #1123 SMP Wed Jun 27 17:35:49 BST 2018 armv7l GNU/Linux
cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
What is working: The Arduino attached to the Pi has a callback: void sendData() { Wire.write("Hello from Arduino"); }
On the Pi side it appears the data is available on the wire:
i2cdump -y 1 0X08 i
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 48 65 6c 6c 6f 20 66 72 6f 6d 20 41 72 64 75 69 Hello from Ardui
10: 6e 6f ff ff ff ff ff ff ff ff ff ff ff ff ff ff no..............
20: 48 65 6c 6c 6f 20 66 72 6f 6d 20 41 72 64 75 69 Hello from Ardui
30: 6e 6f ff ff ff ff ff ff ff ff ff ff ff ff ff ff no..............
On the Pi side, a loop call to: def writeNumber(value):
my_bus.write_byte(slave_address, value)
will blink an LED on the Arduino - the number of blinks is "value".
A callback obtains the number for blinking:
void receiveData(int byteCount){ if ( Wire.available() ) { number = Wire.read(); } }
So at this point everything seems to be working fine, LEDs flash as expected, the radios work, voltages and connections seem fine. But now the bad news.
I need more than just one byte of data so I try:
my_bus.read_i2c_block_data(slave_address, 0, 32) ###(addr, cmd, # of bytes)
and at run time get the "usual" error: OSError: [Errno 121] Remote I/O error.
Believe me, I have spent many hours searching for an answer. The best guess I have at this point is the second parameter - the "command" parameter - is somehow the bad guy.
So, if someone can point me to enlightenment, I will take that path. But please remember, I have 3000 lines of Python3 already written.
Here is the Pi code:
#!/usr/bin/python3
import time
import smbus as smbus
my_bus = smbus.SMBus(1) # On RPi only bus 1 exists for our use
block_data = [32]
slave_address = 0x08
def writeNumber(value):
my_bus.write_byte(slave_address, value)
return
def readNumber():
# number = my_bus.read_byte(slave_address) ### This works.
block_data = my_bus.read_i2c_block_data(slave_address, 0, 32)# (addr, cmd, # of bytes)
return number
while(1):
writeNumber(3) #Blink the Arduino LED this many times. ### This works.
time.sleep(1/100)
print("from Read: ")
print(readNumber())
time.sleep(3)
Here is the Arduino code - with radio code removed for clarity:
#include <Wire.h>
#define SLAVE_ADDRESS 0x08
byte number = 0;
void flash_data(int loops) {
for (int i = 0; i < loops; i++) {...flashing code...}
void flash_good(int loops) {
for (int i = 0; i < loops; i++) {... flashing code ...}
void flash_bad( int loops ) { ... more flashing code...}
// callback for received data
void receiveData(int byteCount){
if ( Wire.available() ) {
number = Wire.read();
}
}
void sendData() {
Wire.write("Hello from Arduino");
}
void setup() {
Wire.begin(SLAVE_ADDRESS); // an address makes this unit a Slave
// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
void loop() {
if ( number > 0 ) { // If the RPi is sending a value, flash it.
flash_data(number);
number = 0;
} else {
flash_good(1);
}
delay(10);
}
Many thanks to the person who comes up with the obvious fix that I completely overlooked!!!