-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wire.requestFrom() with zero bytes reads many bytes. #421
Comments
@Koepel |
This is a file from PulseView. Open the *.zip in PulseView. Same test as before:
May I counter your question ? Do you have a capture with zero bytes requested that stops after the I2C address ? Please show it and tell everything (hardware and software). Perhaps I can try to reproduce that. |
Sorry, have phrased that badly. Thank you for the traces, i will take a look at them. |
@Koepel |
I noticed that as well. I should have captured the first I2C data after power up. |
I don't see how that would have made a difference. I have to ask, does the i2c standard even allow for 0 bytes to be read in a transaction? The way i understand how addressing works, there must at least be one byte transmitted. How is your "i2c read scanner" coming along? |
The Slave should ACK to its I2C address and the Master should send a NACK after reading the last data byte. Then the Master can send a STOP. That means that sending a STOP after the ACK of the Slave is not according to the I2C protocol. At least one data byte should be read. In my opinion, it is not 100% clear if this situation is allowed. When using a software I2C library, anything can be done, and it will work. I don't know if there is a I2C sensor that enters a erroneous state. |
I see what you mean and i'm not sure how to go about this. I have looked into it a bit and have no clue where the code goes wrong and starts reading 37 bytes. |
The error is in the
When passing 0 as the length of the received data, the unsigned
In this case, we will go beyond the boundaries of Let's look at the map file.
ArduinoCore-avr/libraries/Wire/src/utility/twi.c Lines 555 to 559 in 321fca0
Total read 32 + 5 = 37 bytes (magic) This is confirmed by the logic analyzer. If we change the value of I think it should be possible to "get" 0 bytes of data, i.e. a read request and then a stop signal. |
If zero number of bytes are requested from any existing device on the I2C bus with
Wire.requestFrom( i2c_address, 0);
then the acknowledge from that device makes the Wire library read 37 bytes.The return value of
Wire.requestFrom( i2c_address, 0);
is zero.Request zero bytes:
Result:
As far as I can tell, the data is real data from the sensor. There is also a NACK after the last data byte just before the STOP condition. Everything is according to a standard I2C session, except that 37 bytes don't fit in a 32 byte buffer and there should be no reading of data at all.
If the device does not exist, then the NACK will stop the I2C session.
Background
The "I2C Scanner" sketch uses a 'write' command with zero bytes to check the acknowledge. There are however some capacitive touch sensors that don't have the hardware for the 'write' command. They do acknowledge to the 'read' command.
Therefor I was testing a "I2C Read Scanner" and was comparing the behavior of the AVR Wire library against the SoftwareWire library with
requestFrom( i2c_address, 0);
in the Wokwi simulator with a simulated logic analyzer. The Arduino Uno with DS1307 (in Wokwi) issued this bug.I confirmed this with real hardware with a Arduino Mega 2560 and a BMP085 and also a Arduino Uno as a Slave.
The screendumps above are with real hardware and a LHT00SU1 logic analyzer with PulseView/sigrok.
The text was updated successfully, but these errors were encountered: