Go Down

Topic: I2C hangs (Read 50791 times) previous topic - next topic

kaor

I use I2C to communicate with DOF6 ITG3200/ADXL345.
Also arduino should drive single brushed motor (via simple H-bridge driver using pwm).
When motor is disconnected, everything is ok, but when I power the motor, arduino hangs during few seconds.
I discovered that I2C protocol freezes.
Tried pullup resistors, capacitors for power filtering, nothing helps.
Actually hardware isn't main problem for me, I understand that noise overrides I2C signal, ok, but why arduino hangs?
I need some code modification to get I2C not hangs even during high noise, better I have wrong reading from the sensor, that freeze controller (that means my quadcopter crashes). 
Is there any new versions of WIRE and TWI libraries?
?????? ?????? ?????, ??? ??? - ??????????!

PaulS

Quote
I need some code modification to get I2C not hangs even during high noise, better I have wrong reading from the sensor, that freeze controller (that means my quadcopter crashes). 

Change line 37 to:
Code: [Select]
if(hang)unfreeze();

Or post your code. Perhaps we can spot the issue.
The art of getting good answers lies in asking good questions.

wayneft

Quote
Change line 37 to:
Code:

if(hang)unfreeze();

Thanks...that made my day!  XD

Grumpy_Mike

Quote
Tried pullup resistors, capacitors for power filtering, nothing helps.

You haven't tryed hard enough especially if you have now removed them. You need external pull up resistors and you need decoupling capacitors. If it still hangs and you are not doing anything silly in the software then you haven't got enough of either.
The only way I2C can hang is if you attempt a multi master configuration and you don't do that with this processor.

Jonnym

i'll post here as i'm having a similar problem with a noisy i2c bus... i have external pull-up resistors (5k), and a de-coupling cap. i have attached a pic, what do you guys think this is amount of noise? acceptable and normal, or not. my application is not quadcopter sensors, but it is next on the project list.

i have seen another version of the Wire library that is a bit more forgiving with timings, i haven't tried it yet - any feed back from anyone?? (blinkM i think)

cheers
jon

retrolefty

Quote
acceptable and normal, or not.


That looks pretty good to me, nice straight rise and fall times.

Lefty

kaor

I tried itg3200 example. Hangs the same way.
I want to explain once again. Of course lowering noise is my goal (pullups, capacitors, shields etc...),
BUT! the main goal is to be sure - there is no hardware model that can hang code!
If I can somehow get the code hang, that means there is something supposed to be improved in it.
Lowering noise via pullups and other hardware helps to get more clear signal without errors but nobody can guarantee that some parasite impulse can override any that hardware and get the device stuck! I need guarantee, even nosy signal doesn't drive the code to infinity cycle.

Code: [Select]

// ITG-3200_test
// Copyright 2010-2011 Filipe Vieira & various contributors.
// http://code.google.com/p/itg-3200driver
// Simple test of gyro sensors output using default settings.

#include <Wire.h>
#include <ITG3200.h>

ITG3200 gyro = ITG3200();
float  x,y,z;
int ix, iy, iz;

void setup(void) {
  Serial.begin(9600);
  Wire.begin();      // if experiencing gyro problems/crashes while reading XYZ values
                     // please read class constructor comments for further info.
  delay(1000);
  // Use ITG3200_ADDR_AD0_HIGH or ITG3200_ADDR_AD0_LOW as the ITG3200 address
  // depending on how AD0 is connected on your breakout board, check its schematics for details
  gyro.init(ITG3200_ADDR_AD0_HIGH);
 
  Serial.print("zeroCalibrating...");
  gyro.zeroCalibrate(2500, 2);
  Serial.println("done.");
}

void loop(void) {
    while (gyro.isRawDataReady()) {
    /*
    // Reads uncalibrated raw values from the sensor
    gyro.readGyroRaw(&ix,&iy,&iz);
    Serial.print("X1:");
    Serial.print(ix);
    Serial.print("  Y:");
    Serial.print(iy);
    Serial.print("  Z:");
    Serial.println(iz);
    */
     
    /*
    // Reads calibrated raw values from the sensor
    gyro.readGyroRawCal(&ix,&iy,&iz);
    Serial.print("X2:");
    Serial.print(ix);
    Serial.print("  Y:");
    Serial.print(iy);
    Serial.print("  Z:");
    Serial.println(iz);
    */
     
    // Reads calibrated values in deg/sec   
    gyro.readGyro(&x,&y,&z);
    Serial.print("X3:");
    Serial.print(x);
    Serial.print("  Y:");
    Serial.print(y);
    Serial.print("  Z:");
    Serial.println(z);
  }
}





Btw, the ADXL345 doesn't hangs.
the one difference I find in it's driver is checking that all the bytes are read

Code: [Select]

  if(i != num){
    status = ADXL345_ERROR;
    error_code = ADXL345_READ_ERROR;
  }
  Wire.endTransmission();         // end transmission


status and error_code are class public variables and there is no action in this class for such situation. So I suppose this part of code doesn't play any role in freezing situation.
?????? ?????? ?????, ??? ??? - ??????????!

Grumpy_Mike

What you need to find out is where it hangs and in what way.
Is it an infinite loop somewhere Or is it crashing or reaseting the processor. You will have to investigate with some debug print or LEDs.
There is nothing in the code you posted that looks like a problem so it must be in the libraries.

kaor

#8
Jul 14, 2011, 10:31 am Last Edit: Jul 14, 2011, 10:35 am by kaor Reason: 1

What you need to find out is where it hangs and in what way.
Is it an infinite loop somewhere Or is it crashing or reaseting the processor. You will have to investigate with some debug print or LEDs.
There is nothing in the code you posted that looks like a problem so it must be in the libraries.


No crash or resetting processor, just infinite loop.
debug via leds is good idea but I don't know when do I have enough time to do it. I just wonder, maybe someone else had the same problem and found a way out.
?????? ?????? ?????, ??? ??? - ??????????!

Grumpy_Mike

Quote
I just wonder, maybe someone else had the same problem

I don't recall this ever cropping up on this forum sorry.

I2C hanging has been a problem of mine professionally at work, but that involved FPGAs and multi master buses and was caused by noise spikes locking up the FPGA because it thought another master wanted the bus so not very relevant to your situation.

Jonnym

@ lefty  -- thanks..

@kaor -- to me it looks strange that you code is loop() and directly into a while(). a well placed delay(10); at the end of the loop() outside of the while() may be some sort of 'hack' to make it more stable. thats what i would try, i feel your pain with things that sometimes work and sometimes not.  good luck.

_J

borref


If I can somehow get the code hang, that means there is something supposed to be improved in it.

There are issues with the wire library implementation that can cause a sketch to hang and anyone using it for real applications is likely to run into this problem sooner or later. In twi.c the following loop may in some cases (such as a bus issue) run forever:

Code: [Select]

  // wait until twi is ready, become master receiver
  while(TWI_READY != twi_state){
    continue;
  }


There are a number of those in twi.c and they all need to be changed in order to avoid hangs. One possibility is to add a timeout and call twi_init if the timer expires. I believe a number of users (me included) have submitted patches, but the official version still has this issue.

Here is one thread with some more information on this issue:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283887406

kaor

@BenF, thanks, good point to work on.
?????? ?????? ?????, ??? ??? - ??????????!

kaor

Today I played with leds to debug and figured out that freezes the twi function twi_readFrom.
There is few points in this function, that is unreachable during high noise, not a special one.
I see few loops in this function, that are potential freeze point.
For example this one
Code: [Select]

  // wait until twi is ready, become master receiver
  while(TWI_READY != twi_state){
    continue;
  }
?????? ?????? ?????, ??? ??? - ??????????!

kaor

Setting the CLK_SEL to 0 (Internal oscillator) improved stability but problem still remains.
In the ITG_3200 default init set this register to 1 (PLL with X Gyro reference) as recommended in ITG manual.
?????? ?????? ?????, ??? ??? - ??????????!

Go Up