Why can't the Wire library support repeated start condition?

Since Arduino Wire library is quite mature, why can't it support repeated start condition? Are there special reasons why repeated start is not supported?

Your should not believe everything on the Internet :wink: It is supported since a few years, read the reference.

1 Like

Koepel:
Your should not believe everything on the Internet :wink: It is supported since a few years, read the reference.
Wire - Arduino Reference
Wire - Arduino Reference

Thanks! One karma to you. I guess there is no reason to use other I2C libraries except Wire library today.

Hi all,

I am not so sure that repeated start has been implemented in the last release of the library. I am having trouble communicating with an I2C slave implemented in an FPGA, so I checked what was going on in the SDA and SCL lines with a logic analiser.

In the attached image, between the vertical lines of the analyser cursors, you can see the "repeated start" condition of the function:

Wire.endTransmission(false);

while communicating with a LIS3MDL magnetometer.

Now, let's go to the I2C reference here: Repeated Start Condition – I2C Bus
In the picture below you will see the specification of the repeated start:

Do you see the difference? Exactly, in the specification, the SDA line goes high when the SCL line is low, and then, when SCL is high, SDA line goes low.

On the other hand, Wire library "repeated start" is implemented as follows: The SDA line goes high and low when the SCL line is high. This is not a repeated start, this is a stop followed by a start!

However, this is probably not an issue for most I2C slaves (but for mine :frowning: ).

Jusep:
Hi all,

I am not so sure that repeated start has been implemented in the last release of the library. I am having trouble communicating with an I2C slave implemented in an FPGA, so I checked what was going on in the SDA and SCL lines with a logic analiser.

In the attached image, between the vertical lines of the analyser cursors, you can see the "repeated start" condition of the function:

Wire.endTransmission(false);

while communicating with a LIS3MDL magnetometer.

Now, let's go to the I2C reference here: Repeated Start Condition - I2C Bus
In the picture below you will see the specification of the repeated start:

Do you see the difference? Exactly, in the specification, the SDA line goes high when the SCL line is low, and then, when SCL is high, SDA line goes low.

On the other hand, Wire library "repeated start" is implemented as follows: The SDA line goes high and low when the SCL line is high. This is not a repeated start, this is a stop followed by a start!

However, this is probably not an issue for most I2C slaves (but for mine :frowning: ).

A repeated start is actually a non Stop.

After the Ack clock period, the master does not pull the bus low during the next low period.

I would look at your device, when is your device releasing the ACK signal?

I would question your device. I don't see any separation between the ACK and the STOP?

included is a screen grab of a ACK, STOP, and Start.

At 20us is the Clock High for the ACK,
the Device(24LC512 EEPROM) releases SDA at 23us
the Ardunio Drives SDA at 28us (for a Stop condition),
at 37us the Arduino release SDA, (Causing a STOP)
at 63us the Arduino Drives SDA, (causing a Start)

You should see a blip between the ACK and the STOP.

If you specified a RESTART, when the device releases SDA it should go high.

From your screen grab I don't see the device Releasing SDA until your first vertical marker?

Try slowing down the I2C, if it is really a problem with Wire.h you should see your device releasing SDA after the ACK.

Here is another capture of a Write/Restart with a MCP79410 RTCC using Restart:

Chuck.

Have a look at this alternative I2C library.

I haven't used it for repeated starts, but it may be what you're looking for.

Hi all!

First of all, thanks for your help and comments.

chucktodd:
From your screen grab I don't see the device Releasing SDA until your first vertical marker?

Try slowing down the I2C, if it is really a problem with Wire.h you should see your device releasing SDA after the ACK.

I have simulated the I2C slave implemented on the FPGA. It releases the SDA line during the falling edge of SCL clock corresponding to the ackowledge. Therefore, I should see how the SDA line goes momentarily high, but I don't.

I have given a try to a different device I have on my board: a LIS3MDL magnetometer. I can correctly read data from this one, even though I have the same issue when I look the SDA and SCL lines. See the picture attached. In this case, I think I was using a 400 kHz clock. The image in my previous post was made when using 50 kHz.

Here I should say that I am using the "second" I2C in an Arduino Due, so maybe this issue is only found in this especific case.

I tried to use this library, but it seems that it does not support due.

Jusep:
Hi all!

First of all, thanks for your help and comments.

I have simulated the I2C slave implemented on the FPGA. It releases the SDA line during the falling edge of SCL clock corresponding to the ackowledge. Therefore, I should see how the SDA line goes momentarily high, but I don't.

I have given a try to a different device I have on my board: a LIS3MDL magnetometer. I can correctly read data from this one, even though I have the same issue when I look the SDA and SCL lines. See the picture attached. In this case, I think I was using a 400 kHz clock. The image in my previous post was made when using 50 kHz.

Here I should say that I am using the "second" I2C in an Arduino Due, so maybe this issue is only found in this especific case.

I tried to use this library, but it seems that it does not support due.

I have no experience with The DUE, My examples are for the UNO, MEGA. So the DUE might have an error.

You should be able to walk through the Wire.h code for the DUE and see when it sets the byte end status.

Chuck.

chucktodd:
I have no experience with The DUE, My examples are for the UNO, MEGA. So the DUE might have an error.

You should be able to walk through the Wire.h code for the DUE and see when it sets the byte end status.

Chuck.

I think I found out which was the issue. Around 2014 the repeated start on I2C was fixed in the Wire library. However, at the beginning of 2015 some Arduino Due developers noticed that the repeated start didn't work for this board:
Original Adafruit forum about this issue

AmLimit later came with a solution that was later implemented in the SAM boards libraries (I think it was implemented in version 1.6.5).

As it is explained in the second link I have attached, the solution consists in replacing the typical I2C read request:

Wire.beginTransmission(LIS3MDL_ADDRESS);     // Slave addres
Wire.write(LIS3MDL_OUT_X_L);                             // Register to read
Wire.endTransmission(false);                       // Sending data in a burst and doing a repeated start (not working for Due)
Wire.requestFrom(LIS3MDL_ADDRESS, 6, true);   // Requesting the data

With the following elegant code:

Wire.requestFrom(FPGA_ADDRESS, 1, FPGA_REG, 1, true);

Where the parameters are, in this order, the slave address, the number of consecutive registers to read, the first register to read, the length of the data (in bytes) and the stop signal at the end (if true).

This function, however, cannot be found in the documentation:

http://playground.arduino.cc/Main/WireLibraryDetailedReference#requestFrom

In fact, the documentation is a bit out of date as it still considers the send() function.

I tested it, and on the oscilloscope the repeated start works fine.

I hope it is useful!