Pages: 1 [2] 3   Go Down
Author Topic: Due I2C not working  (Read 10888 times)
0 Members and 1 Guest are viewing this topic.
West Yorkshre UK
Offline Offline
Newbie
*
Karma: 0
Posts: 17
faster, smaller, more beautiful
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ive captured the SCL and SDA and I DO see the Ack and levels are good. But for some reason the Due is not seeing it . This is with the wire library. Ive since used the MPU6050 code with the I2Cdev library and it works. But I would like to get to the heart of the problem. Trying scan by using  error=I2Cdev::readbyte(addr++,0,buff);  in a loop still doesnt work find the Ack.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am also experiencing problems with I2C between two Dues. Nothing working at all so far, I even went back to the basic examples and nothing happened. Are the designers aware of this potential issue with either the pullups or the library (I hope it's the latter!!)? Please acknowledge.
Logged

White River Junction, Vermont USA
Offline Offline
Full Member
***
Karma: 5
Posts: 106
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ive captured the SCL and SDA and I DO see the Ack and levels are good. But for some reason the Due is not seeing it . This is with the wire library. Ive since used the MPU6050 code with the I2Cdev library and it works. But I would like to get to the heart of the problem. Trying scan by using  error=I2Cdev::readbyte(addr++,0,buff);  in a loop still doesnt work find the Ack.
The heart of the problem is that each time the wire library checks the TWI status register, the NACK bit is automatically cleared by hardware (34.11.6 TWI Status Register, page 748 in the SAM3X8E datasheet).  The wire library is broken in this regard.  If you need to detect NACK's, you will need to wait for updates, or spin your own interface.

However, it looks like you have trouble detecting ACK's.  I suspect that you probably have some other issue going on.  Try posting your code...

Do not connect two Due's together on a common I2C bus without a buffer of some sort.  The combination of both boards, and their pull-up resistors in parallel, will unnecessarily stress the DUE's TWI pins.  I recommend that the on-board pull-ups be removed from the DUE's pcb by default.  Use larger external pull-up resistors.

How big?  Check this out:
http://www.edn.com/design/analog/4371297/Design-calculations-for-robust-I2C-communications

-Chris
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I also have some trouble with the I2C: I am very new to this communication protocol, So I was trying to see how it works, and I tried making my Due and my Uno talk to each other. It worked, but when I send charters from the Due to the Uno, half is lost.
Here are my codes:
for the Uno (slave):
Code:
#include <Wire.h>
char buffer[64];
byte serialpos=0, wirepos=0;
void setup() {
  // put your setup code here, to run once:
   Wire.begin(0x02);
   Serial.begin(115200);
   Serial.println("I2C test Starting...");
   Wire.onRequest(handler);
   Wire.onReceive(receiver);
}

void loop() {
  if(Serial.available())
  {
    buffer[serialpos]=Serial.read();
    serialpos++;if(serialpos>64)serialpos=0;
  }
  // put your main code here, to run repeatedly:
 
}
void handler()
{
  if(wirepos<serialpos)
  {
  Wire.write(buffer[wirepos]);
  wirepos++;if(wirepos>64)wirepos=0;
  }
}
void receiver(int num)
{
  while(Wire.available())
  {
    char c=Wire.read();
    Serial.println(c);
  }
}
and for the Due (master):
Code:
#include <Wire.h>
int old, now;
void setup() {
  // put your setup code here, to run once:
   Wire.begin();
   Serial.begin(115200);
   Serial.println("I2C test starting...");
   old=millis();now=millis();
}

void loop() {
  if(Serial.available())
  {
    Wire.beginTransmission(0x02);
    Wire.write(Serial.read());
    Wire.endTransmission();
  }
  now=millis();
  if(now-old>1001)
  {
    old=now;
    Wire.requestFrom(0x02,1);
    delay(10);
    while(Wire.available())
    {
      char c=Wire.read();
      if(c>31)Serial.println(c);
    }
  }
  // put your main code here, to run repeatedly:
 
}

Any help will be appreciated. Thanks.
Logged

L.C.

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not even getting a clock signal on SCL1, just running the example file "master reader"! SCL1 just sits low at 0V (referenced to a gnd pin) and SCL(21) does the opposite (3.3V). I was surprised by how easy it was to pull SCL1 high even with a 100k resistor, as though it is not trying to pull down the line at all, ever. Is my Due faulty? Is there some special way that SCL should be terminated that I missed which is causing this behaviour? I would really appreciate a developer looking into this as my current project was designed around lots of Dues talking I2C.... oh dear :-( The previous posts suggest that both the Wire library is in error AND that the hardware has been badly designed with too small pullup resistors and that Dues therefore cannot be connected on a single I2C bus. Please confirm. This is such a fundamental (and disappointing) issue!
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually, it's my code which was bad, I modified it and all worked fine for me smiley Sorry for disturbing.
Logged

L.C.

Germany
Offline Offline
Full Member
***
Karma: 10
Posts: 230
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually, it's my code which was bad, I modified it and all worked fine for me smiley Sorry for disturbing.
It would be nice if you share your new code with us.
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yep sorry. here it goes: for the Due (master)
Code:
#include <Wire.h>
int old, now;
void setup() {
  // put your setup code here, to run once:
   Wire.begin();
   Serial.begin(115200);
   Serial.println("I2C test starting...");
   old=millis();now=millis();
}

void loop() {
  if(Serial.available())
  {
    Wire.beginTransmission(0x02);
    Wire.write(Serial.read());
    Wire.endTransmission();
  }
    old=now;
    Wire.requestFrom(0x02,1);
    //delay(1);
    while(Wire.available())
    {
      char c=Wire.read();
      if(c>31)Serial.println(c);
    }
  // put your main code here, to run repeatedly:
 
}
and for the Uno:
Code:
#include <Wire.h>
char buffer[256];
byte serialpos=0, wirepos=0;
void setup() {
  // put your setup code here, to run once:
   Wire.begin(0x02);
   Serial.begin(115200);
   Serial.println("I2C test Starting...");
   Wire.onRequest(handler);
   Wire.onReceive(receiver);
}

void loop() {  // put your main code here, to run repeatedly:
 
}
void handler()
{
  if(Serial.available())
  {
    char c=Serial.read();
    Wire.write(c);
  }
}
void receiver(int num)
{
  while(Wire.available())
  {
    char c=Wire.read();
    Serial.println(c);
  }
}
Hope this helps smiley
Logged

L.C.

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Finally some good news that you've got I2C working..

I recently got my Due about a day back and tried using I2C, by sending a byte over to my target external ADC (that communicates using I2C). The device address is 0x0D, target register address is 0x80 and the byte to be sent is 0xA0.

Code:
#include <Wire.h>
byte result=0;
void setup()
{
  // put your setup code here, to run once:
 
  Serial.begin(9600);
  Wire.begin(0x0D);                                                  //device address
  delay(10);
}

void loop()
{
  //main code here, to run over and over again
  Wire.beginTransmission(0x80);                                                   //target register address
  delay(1);
  Wire.write(0xA0);                                                                       //data byte to be transmitted
  delay(1);
  result=Wire.endTransmission();                                                  //wanted to print the status of transmission as i cannot program my                                     
  delay(1);                                                                                             target IC (external ADC)
  Serial.write(result);
  Serial.println(" ");
  delay(100);
   
}

Im getting the following message on my serial monitor:

assertion "(address & 0x80) == 0" failed: file "../source/twi.c", line 261, function: TWI_StartWrite
Exiting with status 1.

I will be really grateful to anyone who can analyze Patouf's code in the previous post and point out the error (if any) in mine.

Thanks a lot guys.
Logged

Pisa
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Electronics Engineer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello, guys.

I am experiencing the same issues with the TWI interface with Arduino DUE. I am trying to read data from a MMA8452Q accelerometer. It's a 3.3V powered sensor. The strange things are the following:

  • Using the sensor with Arduino UNO with two 330 ohm resistor on the TWI wires (as suggested by the code example provided on GitHub) works perfectly, the sensor is readable.
  • Connecting the same way Arduino UNO and Arduino DUE and scanning the TWI devices works for the Arduino UNO, it finds the DUE board, but the DUE board can't find the UNO board.
  • The accelerometer with the DUE board does not work at all

It seems to be a software problem for the Wire library on Arduino DUE isn't it?
Logged

Daniele Faugiana

Offline Offline
Jr. Member
**
Karma: 1
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

WIfAU
Did you ever figure out how to get the Due i2c to work?
Logged

Pisa
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Electronics Engineer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, I haven't. I think I'll use a oscilloscope to understand what is the issue and then I'll try to fix it.
Logged

Daniele Faugiana

Offline Offline
Jr. Member
**
Karma: 1
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Update: I got the my I2C devices working with the Due on both channels. 2.2K pullups on SDA1/SCL1. Haven't fully tested yet, but Due finds the device addresses. Used Newhobby's Wire library: http://forum.arduino.cc/index.php?topic=217442.msg1697527#msg1697527
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I had the same problem with the GY-521.

Use the fix also worked for me.

Specifically:

Download:

https://raw.githubusercontent.com/bluesign2k/Arduino/d8d6d62853a5308c21b95dad4bdd64e358e857cc/hardware/arduino/sam/libraries/Wire/Wire.cpp

And overwrite in your arduino installation: hardware/arduino/sam/libraries/Wire/Wire.cpp

For me, this just fixed i2c.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do not connect two Due's together on a common I2C bus without a buffer of some sort.  The combination of both boards, and their pull-up resistors in parallel, will unnecessarily stress the DUE's TWI pins.  I recommend that the on-board pull-ups be removed from the DUE's pcb by default.  Use larger external pull-up resistors.

How big?  Check this out:
http://www.edn.com/design/analog/4371297/Design-calculations-for-robust-I2C-communications

Hi Chris,

Great link! Someone pointed me to this post recently in concern about the 1.5K pullups I'd used in a Due-compatible design (the Freetronics EtherDue). The 1.5K values I'd used were the same as the Due reference design. I calculate that under normal circumstances (including connecting two Dues together over i2c) the onboard pullup selection is fine, no need to remove them.

According to the SAM3X8E datasheet Table 46-2, the TWI pins on the Due (ports PB12,13 & PA17,18) can individually sink 6mA for VOL = 0.4V, or sink 9mA in "Relaxed" mode for VOL=0.6V.

Pulling 3.3V down to 0.4V through a 1.5K resistor means sinking 1.93mA. So you can connect three Dues to the same i2c bus, if you needed to, for a combined super low 500 ohm pullup resistance, before you risk the low level voltage floating above 0.4V.

If you're feeling adventurous you could add a fourth and probably a fifth Due to a common i2c bus and push the low voltage up to 0.6V ("relaxed mode") before you risk damaging anything by sinking more than 9mA (the Dues will still be able to talk to each other, as their VIL is maximum 1V.)

It is definitely worth checking any other i2c device's specifications though, to make sure they can sink at least 2mA at 0.4V. This should be well within the limit for most devices, though. Mixing more than one Due on a single i2c bus with multiple other devices also on the bus is perhaps potentially risky, as by this point you have relatively high currents (4mA, 6mA) which may exceed some device limits. The only way to be sure would be to check each device's datasheet.

Why are the comparatively low resistance values on the Due design useful, when most i2c pullups are 4.7k or 10k? The reason is probably to deal with situations of high bus capacitance, especially when using fast mode (400kHz.) This is discussed in the excellent PDF you linked above. At 400kHz it's probably not as essential as it would be if the Due supported 1Mbit or 3.4Mbit "Faster" TWI, but it's still helpful to have the bus return to a "high" value as quickly as possible.

TLDR: Unless I missed something (and please tell me if I did), I wouldn't worry about removing the Due's standard pullups under normal conditions.
Logged

Pages: 1 [2] 3   Go Up
Jump to: