DUE i2c not stable

I am working on a project with DUE for a long time. After upgrading IDE 1.6.6, I'd have wished the wire library is better. This time it's still unstable. Firstly, as usual, if I want to read from i2c, I couldn't write the register address, and have to read all registers from 0x00 to pick those I need. Secondly, it's the restart function. Every time I restart the serial connection, a physical shut should be given to my i2c chip to restart it. Otherwise, it would give all 0 or 1. Hope anyone could give a better solution.

Either there is a problem with 1.6.6 (it is, after all, beta...), or there is a problem in your code. I've been using v1.6.5 running BOTH I2C interfaces, with multiple devices, very extensively for over a year, with clock rates up to 2MHz, with ZERO problems of any kind. I suggest you back off to v1.6.5, and see what happens. If you still have problems, then it's your code, or your hardware.

Regards, Ray L.

Thanks for reply. I am using AD7746 i2c interfaces. My codes run well on UNO. But when it runs on DUE, problems come. Following is my code while doing i2c reading.

#define AD7746 0x48
unsigned long i2cRead(unsigned char add, int num)
{
// add: sub-address
// num: number of bytes to read
unsigned long a,b;
a=0;
b=0;
Wire.beginTransmission(AD7746);
Wire.write(add);
Wire.endTransmission(0);
Wire.requestFrom(AD7746,num);
while (! Wire.available() == num)
{
//wait for the device
}
for (int x = 1; x <= num; x++)
{
a = Wire.read();
b = a << (8*(num - x)) | b;
}
return b;
}

What happens when num is more than 4 or less than 1?

The code needs more guards in it to ensure that it's not waiting forever for a chip that doesn't send exactly the requested number of bytes. A glitch on the line or anything you didn't plan for will break this code in a very bad way (infinite loop, most probably.)

MorganS:
What happens when num is more than 4 or less than 1?

The code needs more guards in it to ensure that it’s not waiting forever for a chip that doesn’t send exactly the requested number of bytes. A glitch on the line or anything you didn’t plan for will break this code in a very bad way (infinite loop, most probably.)

Thank you for the advice about break. But till now, I haven’t meet this kind problem. The problem now is, after I write the address, whatever address I wrote, it starts reading from the initial 0x00 address. I found it caused by dis-function of Wire.endTransmission. Another issue is about the restart, when I restart the arduino, the wire part didn’t restart and kept sending 1s in 1.6.6 0s in 1.6.5. Actually, I never use this function with num <1 or num >4. It’s not designed for universal usage.

Wow great to hear that someone has success with I2C on DUE! I have 1.6.5 (so understand not the issue with 1.6.6 beta discussed here) and too much experience with I2C on ATR but on DUE can't get anything to work. Trying to use SCL1/SDA1. Have tried both scanners with modes for wire1. Updated the wire lib etc. Tried multiple external pullups to 3.3v - 2k2, 4k7, 1k, 10k. What's the trick?

Thank you!

davidreeves20: Wow great to hear that someone has success with I2C on DUE! I have 1.6.5 (so understand not the issue with 1.6.6 beta discussed here) and too much experience with I2C on ATR but on DUE can't get anything to work. Trying to use SCL1/SDA1. Have tried both scanners with modes for wire1. Updated the wire lib etc. Tried multiple external pullups to 3.3v - 2k2, 4k7, 1k, 10k. What's the trick?

Thank you!

I tried all the tracks you mentioned. Now my solution is to read all the registers, then pick what I need. But it consumes more time. I am really looking forward to anyone has practice I2C experience on DUE.

An i2c BME280 temp, humidity, and pressure sensor works fine on the Due. IDE 1.6.6, Due board package 1.6.6. Pins: SDA/20 and SCL/21. The Adafruit BME280 library works as well as Arduino code provided by the breakout board vendor.

davidreeves20: Wow great to hear that someone has success with I2C on DUE! I have 1.6.5 (so understand not the issue with 1.6.6 beta discussed here) and too much experience with I2C on ATR but on DUE can't get anything to work. Trying to use SCL1/SDA1. Have tried both scanners with modes for wire1. Updated the wire lib etc. Tried multiple external pullups to 3.3v - 2k2, 4k7, 1k, 10k. What's the trick?

Thank you!

Other than having to put pull-ups on SCL1/SDA1, there is no "trick". It just works. I've been using BOTH I2C interfaces, with multiple devices, up to 2MHz clock, with 1.6.5, for the last year with ZERO problems of any kind.

Regards, Ray L.

Well with RayLivingston's successful reports regarding the I2C on DUE I went back to the drawing board and now have success also!

In the process I determined:

  1. the i2cscanner does or did not support wire1 by default so had to make some changes there
  2. this allowed me to identify some hardware/connection issues
  3. with 3.3v got good results with 2k2 resistors
  4. libraries all use wire without handling wire1 so have to be addressed

I think this would be much more straight forward for the DUE designers to have used the same sda/scl pin locations as the Uno rather than move them and add sda1/scl1 in the same place as the old sda/scl. In retrospect it probably would have been easier for me to move the hardware around (pin locations to 20/21) then to figure out all of the software changes. Although I have not yet gone back and done that because I was trying to use a shield in addition to other i2c.

Also I was initially trying to hook up all of my i2c devices at once and reverted back to the one at a time approach.

Hope this helps others.

Hi,

So what are the issues then, if any?

What we have so far: 1. Put 2.2k resistors on pins 20 and 21 both to +3.3 volts. 2. ??what else here

Anything else to be done to get it to work ?

The BME280 breakout board I am using does not require additional pull up resistors when connected to SDA(20)/SCL(21). They are required when the device is connected to SDA1/SCL1.

Based on my experience with the BME280 on Due, both i2c ports work as expected. The lack of pull up resistors on SDA1/SCL1 is documented so I do not see any issues.

Here is my $0.02. If you have an i2c device and code working on an Uno, try the device first connected to Due SDA(20)/SCL(21). It should "just work" assuming it works at 3.3V. Additional pull up resistors are not needed.

If the i2c device is connected to Due SDA1/SCL1, pull up resistors are needed. And the code must be modified. Every occurrence of Wire (for example, Wire.begin, Wire.write, Wire.read, etc) must be changed to Wire1 (for example, Wire1.begin, Wire1.write, Wire1.read, etc.). Use global find & replace with caution because the include file name must remain "Wire.h".

This is exactly what #define was intended for. #define I2C Wire1works well and it's easy to switcho-changeo on different Arduinos.

There's also other nice #define's defined by Arduino that let you use USB serial interchangeably on different Arduinos. For example a Micro calls its USB serial "Serial". Look them up in the pins.h file for your board.

MrAl - bbx10node said it very well - the 2.2k resistors are needed on Due SDA1/SCL1 but the built in 1.5ks on sda/scl 20/21 seem fine. The libraries that use wire would have to be changed to use wire1 if you use sda1/scl1 but no software or hardware changes should be required if you use 20/21 instead.

Wouldn't it be great if somebody with a scope could check these

Bbx10node - VERY WELL SAID! I used #ifdef AVR (for uno) and #else for DUE so the UNO code would continue to work...now that I'm thinking about it there has to be a better way...

MorganS - will have to try that! I'm not totally clear on exactly how to make it work with libraries that use wire but sounds great! Do you have any examples? Do you code it I2C.begin? Thanks for the suggestion! Will definitely have to try that!

davidreeves20: MrAl - bbx10node said it very well - the 2.2k resistors are needed on Due SDA1/SCL1 but the built in 1.5ks on sda/scl 20/21 seem fine. The libraries that use wire would have to be changed to use wire1 if you use sda1/scl1 but no software or hardware changes should be required if you use 20/21 instead.

Wouldn't it be great if somebody with a scope could check these

Bbx10node - VERY WELL SAID! I used #ifdef AVR (for uno) and #else for DUE so the UNO code would continue to work...now that I'm thinking about it there has to be a better way...

MorganS - will have to try that! I'm not totally clear on exactly how to make it work with libraries that use wire but sounds great! Do you have any examples? Do you code it I2C.begin? Thanks for the suggestion! Will definitely have to try that!

Hi David,

What would you want to check with the scope, to see if there are any internal pullups or something?

The ARM data sheet shows two external resistors to be added for pullups and these resistors are said to have to "conform to the I2C specification". I thought that spec was 10k for each though. Or maybe it varies with the number of devices connected? Did anyone try 10k resistors?

They might have those weak pullups on those pins so maybe that's not enough for most applications. I guess we would have to load the pins with maybe 10k to ground to test for any pullups with the scope, and maybe having a device that worked connected to the pins too.

First, I'm certainly not a hardware guy so I probably have this all wrong ...and I probably have some of this confused with one wire(ds18b20s) which I've also been working with also... but I'm willing to put it out there in hopes that somebody will correct my misunderstandings.

My understanding of I2C is that the pullup resistor values impact how fast the signals or voltage on the lines (SDA and SCL) returns to "on" and how fast the value can be pulled to "off". The required resistance needed varies with the voltage (5v or 3.3v) and with the length of the bus and what other devices are attached. My biggest issues were resolved by no longer using breadboards and jumper wires! I think some i2c devices also have built in pullup resistors. I have been trying to minimize the length of the connections to the other i2c devices and from other's suggestions came to try 2k2 with 3.3v with the DUE and have used 4k7 with 5v ok...but I only KNOW what has worked for me and what shows up with the i2cscanner and i2cmultispeedscanner code. I don't have access to a scope at the moment so I haven't been able to look at the operation of the lines to see if they are showing a good digital signal or if it is really marginal with these resistor values. I THINK that with a scope on the SDA and SCL lines you should see whether the voltage was returning to the correct "on" voltage quickly enough and whether it was reaching the correct "off" value sufficiently to work reliably.

I'm sure someone else could better explain how a higher or lower resistance will affect the signal.

As for 10k...my understanding is that most people have better luck with 4k7 additional pullup resistors with the UNO and 5v i2c...because the UNO also has built in pullups and I did try them with the UNO and DUE but they didn't work well for me and after reading more there seemed to be more success with 2k2 with the DUE and I got my application to work with that. I've been more trial and error but I think that with a scope you could eliminate the guess work.

The pullup resistors are supposed to be connected between each SDA/SCL and Vcc not ground.

I was talking about putting a scope on the SDA and SCL lines with the i2c devices during (attempted) operation.

Hello again David,

I do happen to be a hardware guy :-) So i took your advice and looked into the hardware aspect a little more.

You are right that a scope would help here as then we could look at the rise and fall times and see that they are adequate. You may want to note however that would still not be a blanket solution, but rather would have to be performed on a per-application basis. Part of the reason for that is the type of transmission line (jumpers, traces, etc.) and part is due to the total capacitance of the line and device being operated. For example, with 100pf 10k might be ok, but with 200pf 5k would be more like it, and with 300 to 400pf 2.5k would have to be used. Interestingly, there is a min too, not just a max like that. The min is about 1k for a 3.3v pin and about 1.8k for a 5v pin. This i think is so that the pin is not stressed too much. If we draw more current than allowed out of the pin we risk early failure.

There is more to read in the specification if anyone cares to look at that too, but that's the basic idea. So looking at it with the scope might help one application but not the other because the capacitance is different, so each application unless exactly the same as the other would have to be scope'd individually. It couldnt hurt though to test using a standard LCD like the 1602 just to see what it looks like. The rise and fall times would have to be gleaned from the specification for IC2 which notes those values.

A workaround, not having a scope, could be done like other workarounds in analog design. That is, start with 10k, and if that doesnt work, go down to 5k, and if that doesnt work go down to 2.5k, etc., until reaching the min of course. If we obtain success with 5k, then go up to 7k, and if still successful we know that 5k is probably good. If not successful, then go down to 6k. If that still doesnt work then we might be marginal with 5k, so go down to 4k and that is probably good because we already know that 5k works. So the idea is to test with several values, and find the value that is lower than the last value that is found to work by say 20 to 25 percent. It also goes the other way too, if we find that 2k doesnt work but 2.5k works, then we might try to find the upper limit as well then choose the value right between the two values. So if 2k doesnt work but 2.2k works, and 4k also works but 4.2k works, then half way between 2k and 4k is 3k so that would be the best choice. If it turns out that all values down to 1.5k works, then we could go with a value 25 percent less than the highest value that works, or maybe even a little lower. So it becomes trial and error but in a very ordered manner.

Hi David,

Even I am planning to use two I2C ports in Due board.

But I am able to get only one senor I2C data at a time and not stable.

Can you suggest some example code with schematics

I have a rtc module hooked to SCL/SDA which works great. I Just got a temp. sensor which runs perfect on the mega. It will not work on the Due, actually I tried two different Due boards.

The I2C looks like a big issue on the DUE. Is there an I2C software library available that anyone knows of.

scanfff:
I have a rtc module hooked to SCL/SDA which works great. I Just got a temp. sensor which runs perfect on the mega. It will not work on the Due, actually I tried two different Due boards.

The I2C looks like a big issue on the DUE. Is there an I2C software library available that anyone knows of.

It appears that the AVRs have 50ns glitch filters and falling edge slew limiters built into the TWI hardware.

From the Atmega 1280 datasheet:

24.5.1 SCL and SDA Pins
These pins interface the AVR TWI with the rest of the MCU system. The output drivers contain a slew-rate limiter in
order to conform to the TWI specification. The input stages contain a spike suppression unit removing spikes
shorter than 50ns.

The ARMs have nothing. So if you have a long I2C bus, you have ringing on the falling edges, and the clocks coming into your board will have glitches on the order of 50ns, and your clocks leaving your board will generate these glitches as well. This leads to double clock counts and devices falling out of sync, pulling SDA low to ACK at the wrong times, eventually colliding with another device trying to let SDA go high and the bus will lock up with SDA held low. Seems the AVR was specifically designed to cover this, whereas the ARM was not.

Meanwhile, I have had great success running I2C using the Wire library on a SAM3 at even 400kHz on a short I2C layout. No problems whatsoever. There is nothing wrong with the TWI library (v1.5.8 anyway) and nothing wrong with the Due.

If you have long I2C wires, and are not planning on interfacing more than one Due to your I2C bus, add a 200pF cap to ground on both SDA and SCL. This will take care of the glitches coming into your Due. Also consider 10 or 20 ohm series resistors between the Due and the bus. This will attenuate the glitches leaving your Due.

Doug