Go Down

Topic: DUE i2c not stable (Read 7569 times) previous topic - next topic

supershiye

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.

RayLivingston

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.

supershiye

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;
}

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.)
"The problem is in the code you didn't post."

supershiye

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.

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!

supershiye

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.

bbx10node

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.

RayLivingston

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.

davidreeves20

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.

MrAl

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 ?

bbx10node

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".

MorganS

This is exactly what #define was intended for.
Code: [Select]
#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.
"The problem is in the code you didn't post."

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!

MrAl

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.



Go Up