sandeepmistry / arduino-nRF5

Arduino Core for Nordic Semiconductor nRF5 based boards
Other
890 stars 277 forks source link

Wire.requestForm additional clocks generated #176

Open rogerclarkmelbourne opened 7 years ago

rogerclarkmelbourne commented 7 years ago

When I try to use Wire.requestfrom on the nRF52 there appear to be 1 bytes worth of additional clocks sent after the last byte I requested.

Has anyone else seen this effect.?

Note. Some I2C slave devices did not have a problem with this, but one particular device (a iqs263 touch screen controller) does not like the additional clocks

As far as I can tell, using Nordic's high level API for I2C does not have this problem

The operation of this I2C device is that you write the register number and the read 1 or more bytes from that register, depending on how many bytes are in that register

The device ID is 0x44 and I'm reading register 0x00 which is 1 byte long

Wire.beginTransmission(0x44); Wire.write(0x01); Wire.endTransmission(false); Wire.requestFrom(0x44,1,false);

Note. The value returned by the read in these 2 images is different as the device is a touch sensor and is detecting the movement of my finger on the display, hence the value is different

However the value 0xFF should not be returned as it was not requested, and this eventually causes problems when I'm doing a multi-register read, as the slave device gets confused and generates a NAK which takes it off-line until its read the touch screen again (which takes several milliseconds)

This is what I see when using the Wire lib wire_extra_clocks

And this is basically the same thing using the SDK - Note the extra clocks that send back 0xFF are not present and consequentially the rest of the transfer may be a bit different as the slave is getting messed up by the additional clocks

image

kriswiner commented 7 years ago

I didn't look in quite this level of detail but what I saw when I tried to use the nRF52 Wire.h library was that all of the bytes were read but were shifted by one byte, in other words, I would have to discard either the first or last byte (can't remember) of a multi-byte read and shift the array by one in order to get sensible data. Anyway, I simply replaced the Wire.h library with the one from the nRF51 and everything works now. There is definitely at least one bug in the nRF52 Wire.h API.

rogerclarkmelbourne commented 7 years ago

I'm not seeing the issue with the data being byte shifted, but if the nRF51 lib works with the nRF52, I will give it a try.

I would have thought that the hardware inside the MCU is different between these two different devices, but perhaps they are close enough to work in most instances

sandeepmistry commented 7 years ago

@rogerclarkmelbourne have you had a chance to dive into the library and spot anything that looked odd?

@carlosperate fixed something in the nRF51 version with PR https://github.com/sandeepmistry/arduino-nRF5/pull/137. Maybe something similar is needed?

rogerclarkmelbourne commented 7 years ago

@sandeepmistry

I did look in the library, but I did not see anything which would cause this.

I have not tried the nRF51 library, as suggested by @kriswiner

I was thinking of posting a question to the Nordic devzone forum about this, but I've not had time to do it.

micooke commented 7 years ago

I don't know if this is related, but when using this wire library with the nrf51822 and the kx022 im getting garbled data. I haven't analysed it with my saleae logic, but the same hardware works fine with the seeed studio SortwareI2C library. Is anyone else getting this?

micooke commented 7 years ago

Never mind, my issues are caused by a competing library.

BrunDog commented 6 years ago

I am not technically capable to identify where the problem is, but I have have problems using code on the Primo which works properly on ATMEGA 2560 & 328, Curie, SAMD21, and ESP8266 based boards communicating with two devices over i2c.

For example the following simple test for a present device doesn't work on Primo ( stops executing permanently) without the additional code which sends an arbitrary byte. :

Wire.begin();
Wire.beginTransmission(32);

#if defined(ARDUINO_PRIMO)
Wire.write(2);                        // Primo needs arbitrary byte sent, otherwise locks up
#endif 

if (Wire.endTransmission() == 0)
{
  lcdAttached = true;
}
micooke commented 6 years ago

If anyone is interested i have a version of SoftwareI2C that works for the devices in using, but note that there is no comm throttling so it runs at about 400kHz on the nRF52 and 30kHz on an AtMega32u4.

I need/ed an additional i2c for my sportwatches, and have tested it with the SSD1306, an accelerometer, and a current measurement device on both the nRF52 and nRF51.

https://github.com/micooke/SoftwareI2C

micooke commented 6 years ago

@rogerclarkmelbourne - this library gives me incorrect data, so i have a different issue.

For your issue, try the following modifications to Wire_nRF52.cpp

L145:_p_twim->ADDRESS = address;
   if (stopBit) { _p_twim->SHORTS |= NRF_TWIM_SHORT_LASTRX_STOP_MASK;} 

L164:else
  {
    while(!_p_twim->EVENTS_LASTRX)
    { if (_p_twim->EVENTS_ERROR) { _p_twim->TASKS_STOP = 0x1UL; break; } } 
    _p_twim->TASKS_SUSPEND = 0x1UL;
    while(!_p_twim->EVENTS_SUSPENDED);
    _p_twim->EVENTS_SUSPENDED = 0x0UL;
  }
L206:
if(stopBit)
    //trigger stop task immidiately after received last data
     _p_twim->SHORTS |= NRF_TWIM_SHORT_LASTTX_STOP_MASK;
  else
    //suspend twi instead of stop it so no stop bit will be trasmitted
    _p_twim->SHORTS |= NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK;
micooke commented 6 years ago

My test case is to request 1 byte from register 0 on a ssd1306 (address 0x3C).

Using my interactive demo (note the required libraries) here https://github.com/micooke/SoftwareI2C/blob/master/examples/SoftwareI2C_Interactive/SoftwareI2C_Interactive.ino which works with my SoftwareI2C library, as well as Wire.h, the syntax is RX 3C 0 1.

The expected result is 0x70, which is what i get with the nrf51822, AtMega32u4, AtMega328, using the Wire library. The SoftwareI2C library returns this result for these chips as well as for the nrf52832.

The nrf52832 with this core using the standard Wire library, or using the Wire library from arduino-org (https://github.com/arduino-org/arduino-core-nrf52/tree/master/libraries/Wire) give 0x65 as the result.

I haven't heard of anyone else seeing this, so It works be a great sanity check if someone could verify or refute this behaviour. Until then ill put my investigation on the back burner.