MinIMU-9 board outputs stop less than one hour

Hi,

I bought MinIMU-9 (not v2) IMU. The sensors on the board are LSM303DLM and L3G4200D. I tried to do a calibration for these sensors. So I wrote a simple program to let the sensors output readings in 100Hz through serial port. I set the gyro in 2000 dps mode, the accelerometer in 8g mode, and the magnetometer in 1.3 gauss mode with 220 output data rate.

The code is compiled and uploaded to the Arduino uno board. After I opening the serial monitor in Ardunio IDE, I found the print statements in setup() can be corrected executed. But the in loop(), no sensor data are output. If I comment out the register setting in setup(), then the sensor readings in loop() are correctly output. However, the readings only last for tens of minutes (sometimes it continuously outputs for 1 hour), after that it is stuck (no data is output in the serial monitor). I dont know what the problem is. Could you please take a look at my code? Do I make any mistake? What I want is to collect 12 hours data at the frequency of 100Hz for my calibration and analysis. Thanks!

#include <Wire.h>
#include <L3G.h>
#include <LSM303.h>

LSM303 compass;
L3G gyro;

String sample;
unsigned long counter;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  
  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
  compass.init();
  compass.enableDefault();

  //set gyro range to 2000dps
  gyro.writeReg(L3G_CTRL_REG4, 0x20);

  //set acc sensor range to +-8g
  compass.writeAccReg(LSM303_CTRL_REG4_A, 0x30);
  
  //set mag rate 220Hz
  compass.writeMagReg(LSM303_CRA_REG_M, 0x1C);

  Serial.print("Gyro mode (L3G_CTRL_REG1): ");
  Serial.println(gyro.readReg(L3G_CTRL_REG1));
  Serial.print("Gyro Scaling status (L3G_CTRL_REG4): ");
  Serial.println(gyro.readReg(L3G_CTRL_REG4));

  Serial.print("Acc mode (LSM303_CTRL_REG1_A): ");
  Serial.println(compass.readAccReg(LSM303_CTRL_REG1_A));
  Serial.print("Acc Scaling status (LSM303_CTRL_REG4_A): ");
  Serial.println(compass.readAccReg(LSM303_CTRL_REG4_A));

  Serial.print("Mag mode (LSM303_MR_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_MR_REG_M));
  Serial.print("Mag Scaling status(A) (LSM303_CRA_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_CRA_REG_M));
  Serial.print("Mag Scaling status(B) (LSM303_CRB_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_CRB_REG_M));

  sample = String("");
  counter = 0;
 }

void loop() {
  gyro.read();
  compass.read();
  counter = counter+1;

  sample = "";	
  sample +=(int)gyro.g.x;
  sample += " ";
  sample +=(int)gyro.g.y;
  sample += " ";
  sample +=(int)gyro.g.z;
  sample += " ";

  sample +=(int)compass.a.x;
  sample += " ";
  sample +=(int)compass.a.y;
  sample += " ";
  sample +=(int)compass.a.z;
  sample += " ";

  sample +=(int)compass.m.x;
  sample += " ";
  sample +=(int)compass.m.y;
  sample += " ";
  sample +=(int)compass.m.z;

  sample += " ";
  sample += counter;
  
  Serial.println(sample);
  
  delay(10);
}

sampling01.ino (1.9 KB)

Hello.

I see you are using the Arduino’s String class. I wouldn’t be surprised if that class had some memory leak that was slowly filling up your RAM. Could you try re-writing your sketch to not use the String class?

What version of the Arduino IDE are you using? You should be able to use the example code code from our Arduino libraries without modification if you download the latest version of the Arduino IDE.

–David

Thank you David. The abnormality is caused by the String object. After I replacing with a series of Serial.print() statements, the problem is solved.

BTW, I have another question about the output rate. In my current code, I delay for 10ms in each loop, so the output data rate should be 100Hz. After I running my program for around 1 hour and 40 mins, I only get 159622 lines (it is supposed to be 600000 lines). Do you know the problem? Following is my code.

Another issues is: what is the meaning of the term “cut-off” in the datasheet?

#include <Wire.h>
#include <L3G.h>
#include <LSM303.h>

LSM303 compass;
L3G gyro;

unsigned long counter;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  
  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
  compass.init();
  compass.enableDefault();

  //set gyro range to 2000dps
  gyro.writeReg(L3G_CTRL_REG4, 0x20);
  //set gyro in normal power mode, with 100Hz rate, 12.5 cut-off
  gyro.writeReg(L3G_CTRL_REG1, 0x0F);

  //set acc sensor range to +-8g
  compass.writeAccReg(LSM303_CTRL_REG4_A, 0x30);
  //set acc in normal power mode, with 100Hz rate, 74 cut-off
  compass.writeAccReg(LSM303_CTRL_REG1_A, 0x2F);
  
  //set mag rate 220Hz
  compass.writeMagReg(LSM303_CRA_REG_M, 0x1C);
  //set mag range 1.3 gauss, x/y 1100 LSB/Gauss, Z 980 LSB/Gauss
  compass.writeMagReg(LSM303_CRB_REG_M, 0x20);
  //set mag in continuous-conversion mode
  compass.writeMagReg(LSM303_MR_REG_M, 0x00);

  Serial.print("Gyro mode (L3G_CTRL_REG1): ");
  Serial.println(gyro.readReg(L3G_CTRL_REG1));
  Serial.print("Gyro Scaling status (L3G_CTRL_REG4): ");
  Serial.println(gyro.readReg(L3G_CTRL_REG4));

  Serial.print("Acc mode (LSM303_CTRL_REG1_A): ");
  Serial.println(compass.readAccReg(LSM303_CTRL_REG1_A));
  Serial.print("Acc Scaling status (LSM303_CTRL_REG4_A): ");
  Serial.println(compass.readAccReg(LSM303_CTRL_REG4_A));

  Serial.print("Mag mode (LSM303_MR_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_MR_REG_M));
  Serial.print("Mag Scaling status(A) (LSM303_CRA_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_CRA_REG_M));
  Serial.print("Mag Scaling status(B) (LSM303_CRB_REG_M): ");
  Serial.println(compass.readMagReg(LSM303_CRB_REG_M));

  counter = 0;
 }

void loop() {
  gyro.read();
  compass.read();
  counter = counter+1;

  Serial.print((int)gyro.g.x);
  Serial.print(" ");
  Serial.print((int)gyro.g.y);
  Serial.print(" ");
  Serial.print((int)gyro.g.z);
  Serial.print(" ");

  Serial.print((int)compass.a.x);
  Serial.print(" ");
  Serial.print((int)compass.a.y);
  Serial.print(" ");
  Serial.print((int)compass.a.z);
  Serial.print(" ");

  Serial.print((int)compass.m.x);
  Serial.print(" ");
  Serial.print((int)compass.m.y );
  Serial.print(" ");
  Serial.print((int)compass.m.z);
  Serial.print(" ");

  Serial.println(counter);
  
  delay(10);
}

I’m glad you were able to get it working. Reading the data from I2C and sending it on the UART at 9600 baud is not going to be instantaneous so that would probably account for the discrepancy. You should probably use 115200 baud, and use the millis() function to get more accurate timing. The Wire library probably has some option to increase the speed and you could try that too.

Even at 115200 baud, it will be tricky to have a 10ms period. You can only send 115.2 bits per millisecond, so that means you are limited to 115.2 bytes every 10 ms. You might be able to push the baud rate higher if the Arduino’s USB-to-serial chip can handle it.

–David

Sorry, I forgot to address your question about “cut-off”. It is hard for me to answer this question because I don’t know what datasheet you are referring to or what page you saw those words on. Please provide more context for this question or check out the ongoing discussion about the cut-off in this other thread:

–David

Yes, my question is as same as the thread you gave me. Actually, there are several terms in datasheet I do not understand. I will create a new thread later. Thanks!