I am working with I2C for the first time and having an issue with a very simple problem.
I want to send 2 bytes from an Arduino and nvidia jetson orin.
On the Arduino, my code looks like this:
#include <Wire.h> int distance; byte array2send[2]; int i2c_addr = 0x30; void setup(){ //… other code Wire.begin(i2c_addr); Wire.onRequest(sendData); } // other code void sendData(){ array2send[0] = distance >> 8; array2send[1] = distance & 0xFF; Wire.write(array2send, 2); }And on the jetson I simple use python smbus library:
import smbus bus = smbus.SMBus(7) bus.read_i2c_block_data(0x30,0,2)This results in anTimeOutError and I can’t figure out why.On the hardware side, everything should be fine and sending/receiving a single byte (withbus.read_byte(0x30)) works just fine.
- what is your specific question? ... please edit your post ... add a focused, answerable question to your postjsotola– jsotola2025-11-19 22:54:45 +00:00CommentedNov 19 at 22:54
- "I want to send 2 bytes from an Arduino"... Your Arduino code is not sending anything, it waits for a REQUEST from an I2C master before sending the data. i.e. your Arduino code configure itself as a Slave Receiver. And your Jetson code is also just reading data from I2C bus. If you want to send data, look at the [master_writer](I want to send 2 bytes from an Arduino) example.hcheung– hcheung2025-11-20 01:24:40 +00:00CommentedNov 20 at 1:24
- One more thing, since you are connecting two hosts directly, make sure you have pull-up resistors on both SDA and SCL lines.hcheung– hcheung2025-11-20 01:39:03 +00:00CommentedNov 20 at 1:39
- @hcheung: On the Jetson, both
bus.read_byte()andbus.read_i2c_block_data()are "master reader" actions.Dave Tweed– Dave Tweed2025-11-20 12:39:16 +00:00CommentedNov 20 at 12:39
1 Answer1
I know a lot about I2C in general, but very little about the Arduino libraries that implement it. So this might not answer your question, but perhaps it will shed a little light on the situation. (And it's too long for a comment.)
I think that the key difference betweenbus.read_byte() andbus.read_i2c_block_data() is that the former does a simple I2C bus read cycle, while the latter is doing a more complex sequence involving a write cycle, a repeated start and then a read cycle. This is becausebus.read_i2c_block_data() is assuming that the slave device (your Arduino in this case) has "registers", and it needs to transmit the register number before it tries to read data from the register.
I spent some time looking at the source code for theWire library for the Arduino, and it appears to me that this should Just Work. There is a default handler for the write cycle, which should simply stuff the register address into a buffer (which you never look at), and then the read cycle should complete as usual, with the callback to yoursendData() function. But perhaps there's some subtlety in the either the library code or the Arduino hardware that's preventing that from happening.
Another issue is that you have basically only one I2C clock cycle (i.e., 10 µs, assuming that the Jetson is adhering to the 100 kHz SMBus clock speed) to prepare the data to transmit on the Arduino side. It's possible that the software overhead in the library and in your callback before you actually callWire.write() exceeds this, resulting in no data transmitted to the Jetson at all, causing the timeout.
The library documentation is not at all helpful regarding more complex scenarios like this one. And I really don't have time right now to dig into the hardware documentation to see how the hardware would handle this sequence.
Explore related questions
See similar questions with these tags.
