How to slow down data output rate from IMU?

Hey all,

I’m super new to the arduino environment, and the project I’m currently working on is for my University’s Space Grant Consortium rocket challenge. Part of the competition requirements is that you must record rotational data (XYZ axes) over the duration of the flight. Currently I am stuck trying to slow down the data output rate of the IMU I’m using (Pololu - L3GD20H 3-Axis Gyro Carrier with Voltage Regulator) combined with my arduino pro micro (Pro Micro - 3.3V/8MHz - DEV-12587 - SparkFun Electronics). I need to slow down the data output rate because my max array size is like 200, and the flight duration is 25 seconds (roughly). My code is made so that once I hit the 1st button, a delay will start and then after the delay, there is a launch detect system code written. Once the launch is detected, then the arduino will read pitch, roll, and yaw data off the IMU. However, it appears as though the array fills up within a second or two, and I want it to sample slowly so that it fills up after 20 seconds and therefore my array will be filled upon completion. Once data is gathered, I have another button that once pressed, outputs the data to my computer and onto the serial port. Here is my code. Any help or advice would be appreciated!

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

L3G gyro;

const double convFactor = 8.75 / 1000;
double dc_offsetX = 0;
double dc_offsetY = 0;
double dc_offsetZ = 0;
int StartButton = 7;
int OutputButton = 8;
const int RXLED = 17;

void setup() {
  pinMode(StartButton, INPUT_PULLUP);
  pinMode(OutputButton, INPUT_PULLUP);
  pinMode(RXLED, OUTPUT);
  gyro.writeReg(L3G::LOW_ODR, 0x01); //enables low ODR
  gyro.writeReg(L3G::CTRL_REG4, 0x10); //changed to 500 dps
  gyro.writeReg(L3G::CTRL_REG1, 0x2F); //changed to 12.5 Hz ODR
  Serial.println("Initializing Setup ");
  delay(3000);     //30,000 milliseconds = 30 seconds (time delay before dc offset is calculated)
  int sampleNum = 500;

  //Calculate initial DC offset and noise level of gyro
  for (int n = 0; n < sampleNum; n++) {;
    dc_offsetX += (int)gyro.g.x;
    dc_offsetY += (int)gyro.g.y;
    dc_offsetZ += (int)gyro.g.z;
  dc_offsetX = convFactor * (dc_offsetX / sampleNum);
  //print dc offsetX and noise level
  Serial.print("DC OffsetX: ");

  dc_offsetY = convFactor * (dc_offsetY / sampleNum);
  //print dc offsetY and noise level
  Serial.print("DC OffsetY: ");

  dc_offsetZ = convFactor * (dc_offsetZ / sampleNum);
  //print dc offsetZ and noise level
  Serial.print("DC OffsetZ: ");

  Serial.println("Waiting For Button To Be Pressed");
  while (digitalRead(StartButton) == HIGH) true;      //Sit here until button pressed
  Serial.println("Delay Starting After 5th Blink");


  for (int k = 1; k <= 5; k = k + 1) {
    digitalWrite(RXLED, LOW);
    delay (500);
    digitalWrite(RXLED, HIGH);
void loop() {;
  long totalI;
  long totalF;
  long totalA;
  long total;
  int AverageTotalI = 500;
  int AverageTotalF = 500;
  int counterPos = 0; //Position in sample array
  int counterMax = 100;    //Total Number of samples to store (40)...5 samples/sec * 20 seconds of flight data needed = 100
  int vectorX[counterMax];
  int vectorY[counterMax];
  int vectorZ[counterMax];

  // Insert Delay Here....delay(600000) = 10 minute delay

  for (int m = 0; m < AverageTotalI; m++) {    //Calculate Average Value for Total (Initial);
    totalI = abs(gyro.g.x) + abs(gyro.g.y) + abs(gyro.g.z);
  Serial.print("Value for total (Initial) = ");

  do {
    for (int p = 0; p < AverageTotalF; p++) {    //Calculate Average Value for Total (Final);
      totalF = abs(gyro.g.x) + abs(gyro.g.y) + abs(gyro.g.z);

    totalA = totalF - totalI;
    total = abs(totalA);

    Serial.print("Value for total (Final) = ");
    Serial.print("Difference Value is: ");
  } while (total <= 8000);

  if (total >= 8000) {
    Serial.println("Data Collection Starting");
    //Data collection
    //while (digitalRead(OutputButton) == HIGH) {  //Button Not Pressed
    if (counterPos >= counterMax) {
      return; //Stop recording samples.;
      vectorX[counterPos] = int(gyro.g.x);
      vectorY[counterPos] = int(gyro.g.y);
      vectorZ[counterPos] = int(gyro.g.z);
      delay(5000);      //SAMPLE DELAY BETWEEN SAMPLES (500)
      ++counterPos;  //increment counter
      for (int jjj = 0; jjj <= counterMax; jjj++) {
        Serial.print((vectorX[jjj]*convFactor) - dc_offsetX);
        Serial.print((vectorY[jjj]*convFactor) - dc_offsetY);
        Serial.println((vectorZ[jjj]*convFactor) - dc_offsetZ);
      Serial.println("Arry Values Printed, Looping");
      // delay(5000);

code.txt (3.9 KB)

if (counterPos >= counterMax) {
return; //Stop recording samples.;
The code after return will never execute! Missing } after return.

for (int jjj = 0; jjj <= counterMax; jjj++) {
Replace counterMax by counterPos.

Note: these hints are free, every further diagnose of such simple errors costs a beer :wink:

Just an idea, but you could get more samples (and raise the sample rate, maybe) by doing the offset removal and averaging after the flight. The memory saved can be used to store more samples. Can you trigger acquisition, say, 5 or 10 seconds before launch? Those samples can be your zeros. All of those print statements take SRAM so using the F macro to move them to flash will save SRAM.

Serial.print("Value for total (Initial) = ");

Using the F macro:

Serial.print(F("Value for total (Initial) = "));

will save about 27 bytes of SRAM.

Learn the blink without delay method for timing (to set your sample rate). Doing the same thing with delay() will take fiddling to get precise and if you change the code, more fiddling. If you are not saving timestamps the timing must be precise or the data is garbage. Look in the IDE examples. It probably won't save memory, but the sooner you quit using delay() the better.