arduino / Arduino

Arduino IDE 1.x
https://www.arduino.cc/en/software
Other
14.14k stars 7.01k forks source link

I2C lockup using MPU6050 and XBee #4717

Open antonro1 opened 8 years ago

antonro1 commented 8 years ago

I have been able to consistently reproduce a problem using an arduino zero, MPU6050 and XBee. MPU6050 is connected via I2C and XBee on pins 0 &1.

Using the following sketch I am able to get the I2C to lockup when sending data to the XBee from the PC. Note the XBee serial port has not been opened. I2C can lockup at "B" or "R":

#include <MPU6050.h>

MPU6050 accelgyro;

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

unsigned long Hz100Loop = 0;
unsigned long Hz10Loop = 0;
unsigned long Hz20Loop = 0;

const int MPU_addr=0x68; 

void loop10Hz()
{
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);

}

void readMPU()
{
    int8_t buffer[15];

    Serial.println("B");
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Serial.println("R");
    Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers}

    Serial.println("L");

    int count = 0;
    while (Wire.available() && count<14)
    {
        Serial.print("S");
        Serial.println(count);
        buffer[count] = Wire.read();
        Serial.println("E");
        count++;
    }

    Serial.println("F");

}

void loop100Hz()
{
    int16_t ax,ay,az,gx,gy,gz;

    //accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    readMPU();
}

void setup() {
    Wire.begin();

    Serial.begin(115200);

    Serial.println("initializing");
    accelgyro.initialize();
    accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);

    if (accelgyro.testConnection())
    {
        Serial.println("test ok");
    }

    pinMode(LED_PIN, OUTPUT);

}

// the loop function runs over and over again until power down or reset
void loop() {

    int delta100Hz = millis()-Hz100Loop;
    int delta10Hz = millis()-Hz10Loop;

    if (delta100Hz>=10) 
    {
        loop100Hz();
        Hz100Loop=millis();
    }

    if (delta10Hz>=100) 
    {
        loop10Hz();
        Hz10Loop=millis();
    }

}

To generate serial data from the PC I am using a simple .Net application which is basically on a timer sending a few bytes of data:

                serial = new SerialPort("COM4", 57600);
                serial.DataReceived += new SerialDataReceivedEventHandler(HandleSerialData);
                serial.Open();
...
            dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0,0,20);
...

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            if (serial != null)
            {
                serial.WriteLine(string.Format("B:{0:F0}", 50));
            }

        }

Arduino SDK version 1.6.7. The issue will occur using just the I2CDev library as well - but that just calls Wire anyway. I have also reproduced this on a Leonardo.

As far as I can tell, without sending any data to the XBee port from the PC, the code will run indefinitely.

facchinm commented 8 years ago

Hi @antonro1, I can't understand what is happening here; you are sending a string every 20 milliseconds to the Due without reading it, right? The XBee is not used at all so it should not break anything. I've tested with an I2C accelerometer and your sketch (more or less) and nothing is breaking. Can you post here a simplified PC program which triggers the lock?

antonro1 commented 8 years ago

Note, the board is the Zero and Leonardo , not the Due. Which accelerometer did you test with? This is specifically the MPU6050 I haven't tried with any other IMU. I'll update with the full .Net code for the serial output later.

facchinm commented 8 years ago

Sorry, I meant the Zero, I was testing another issue in the meanwhile and confused the boards :smile: The IMU I have tested is the LSM9DS0

antonro1 commented 8 years ago

Here's the .Net code. Dies pretty quickly using this.

class Program
    {
        static void Main(string[] args)
        {
            SerialPort serial = new SerialPort("COM4", 57600);
            serial.Open();

            while (true)
            {
                serial.WriteLine(string.Format("B:{0:F0}", 50));
                Thread.Sleep(20);
            }
        }
    }
antonro1 commented 8 years ago

FYI the MPU6050 board I'm using is this one:

http://www.robotshop.com/uk/6-dof-gyro-accelerometer-imu-mpu6050.html