H3LIS331DL Sample Rate and G force Range

Hello! I am trying to adjust the sample rate and range on my H3LIS331DL but I am having difficulty implementing the code provided on the accelerometer’s info page into my code correctly. I am running it using I2C with an Arduino Pro Mini and a RTC also using I2C on the same wires. I would like to use the 200g setting with as high of a sample rate as possible, so hopefully the 1000Hz that is advertised on the products spec sheet. I have tried putting the “LIS331::DR_1000HZ” line of code in the setup and loop sections of the code separately but it never seems to have an effect on the sample rate. If anyone has any experience with this issue, your help would be greatly appreciated.

Here is my code:

(Edited by moderator to include code tags.)

#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
RTC_PCF8523 rtc;
#include "SparkFun_LIS331.h"
#include <Wire.h>
LIS331 xl;

File myFile;
//const int delaytime = 5; // Time between readings, counted as milliseconds
float scaledReadings [3][3]; //Storage for the data collected by the accelerometer
const int button = 2; // pushbutton pin
int buttonState; // for reading the pushbutton state
int state = 0; //For deciding if the system is starting or going into another loop



void setup() {
    Wire.begin();
  xl.setI2CAddr(0x19);    // This MUST be called BEFORE .begin() so 
                          //  .begin() can communicate with the chip
  xl.begin(LIS331::USE_I2C); // Selects the bus to be used and sets
                          //  the power up bit on the accelerometer.
                          //  Also zeroes out all accelerometer
                          //  registers that are user writable.
  // Initialize serial communication at 115200 baud
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect.
  }
  
  // Initialized the pushbutton as input
  pinMode(button, INPUT_PULLUP);
  
  //initialize Real Time Clock (RTC)
  if (! rtc.begin()) {
  Serial.println("Couldn't find RTC");
   Serial.flush();
   abort();
  }
  
 if(! rtc.initialized() || rtc.lostPower()) {
    Serial.println("RTC is NOT initialized, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
 }

  // see if the card is present
  if (!SD.begin(10)) {
    Serial.println("Card init. failed!");
  }

  Serial.println("Starting data collection.");
}

void loop()
{
  buttonState = digitalRead(button);
  if(buttonState == 0 && state == 0){
        //Create a file name for the data to be stored
  char filename[15];
  strcpy(filename, "DATA00.CSV");
  for (uint8_t i = 0; i < 100; i++) {
    filename[4] = '0' + i / 10;
    filename[5] = '0' + i % 10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

  myFile = SD.open(filename, FILE_WRITE);
  if ( ! myFile ) {
   Serial.print("Couldnt create ");
    Serial.println(filename);
  }
  
  //get the last filename
  strcpy(filename, "DATA00.CSV");
  for (uint8_t i = 0; i < 100; i++) {
    filename[4] = '0' + i / 10;
    filename[5] = '0' + i % 10;
    if (!SD.exists(filename)) {
      filename[4] = '0' + (i - 1) / 10;
      filename[5] = '0' + (i - 1) % 10;
      break;
    }
  }
    //Initialize SD card and make sure it has opened correctly
  Serial.println("Initializing SD card...");
 
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("successful!");
  myFile = SD.open(filename, FILE_WRITE);
  delay(1000);
  }
  
  if (myFile) {
    Serial.println("Your file has opened, beginning to record data.");
    //Take readings from the accelerometer
    
    if (buttonState == 0) {
      do {
        readWrite();
        buttonState = digitalRead(button);
      } while (buttonState == 0);
      state = 1;
    }
    if (buttonState == 1 && state == 1){
    myFile.close();
    Serial.println("Data Saved");
    state = 0;
 }
    } 
else {
  Serial.println("Waiting for system to be turned on");
}
}



void readWrite() {
    int16_t x, y, z;
    String dataString = "";
    xl.readAxes(x, y, z);  // The readAxes() function transfers the
                           //  current axis readings into the three
                           //  parameter variables passed to it.
    DateTime now = rtc.now();
    dataString += String(now.hour());
    dataString += ":";
    dataString += String(now.minute());
    dataString += ":";
    dataString += String(now.second());
    dataString += ",";

    scaledReadings[0][0] = xl.convertToG(200,x);
    dataString += String(scaledReadings[0][0]);
    dataString += ",";
    scaledReadings[1][0] = xl.convertToG(200,y);
    dataString += String(scaledReadings[1][0]);
    dataString += ",";
    scaledReadings[2][0] = xl.convertToG(200,z);
    dataString += String(scaledReadings[2][0]);
    //For debugging of the sensor readings
    Serial.println(dataString); 
    myFile.println(dataString);
    //delay(delaytime);
  }

// Same functionality as Arduino's standard map function, except using floats
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

I have tried putting the “LIS331::DR_1000HZ” line of code in the setup and loop sections

Post the code you tried.

All the file search, creation and open actions must be in setup(), not in loop(). For high speed data collection, the loop function should only read data and write to the SD card, and you may need to use SPI mode for the SD, as that is much faster than I2C. Finally, for fastest output, send only raw, binary (not ASCII formatted) values to the SD card and process them later.

Use of Strings causes memory problems and unpredictable program crashes on small Arduinos like the Pro Mini. Strings are completely unnecessary, so get rid of them. Just use Serial.print() or myFile.print() (for binary data, myFile.write()) to output values.

Thanks for the reply! While I was testing the sample rate of the system, I found out that every time I used the “myFile.print” function, it slowed down the sample rate. My solution was to use a string with all of the information I needed to write and the just write to the card once. Without using the string method, my code would look like the following:

myFile.print(now.hour());

myFile.print(“:”);

myFile.print(now.minute());

myFile.print(“:”);

myFile.print(now.second());

myFile.print(“,”);

myFile.print(xl.convertToG(200,x));

myFile.print(“,”);

myFile.print(xl.convertToG(200,y));

myFile.print(“,”);

myFile.println(xl.convertToG(200,z));

Unless I am missing something, this seems to be the only way to write in CSV (comma separated variable) format using the Arduino. You also mention only putting the file name portion of the code in setup(). The reason I have it in loop() is because I have a switch that toggles the system between recording data and sitting idle. Whenever I switch from recording data to idle and then begin a new recording, I want to save the previous data and start a new .csv file. Its messy but I couldn’t find a way to accomplish this while putting the file creating/search in the setup only.

Finally, when I tried to use the “LIS331::DR_1000HZ” code, I put it right below this section in setup() from the code I originally posted:

xl.begin(LIS331::USE_I2C); // Selects the bus to be used and sets

// the power up bit on the accelerometer.

// Also zeroes out all accelerometer

// registers that are user writable.

Obviously, I am asking a lot from whoever is willing to guide me through any of these issues. I really appreciate the help!

this seems to be the only way to write in CSV (comma separated variable) format using the Arduino

No, there are many other ways to format the data, like using the function snprintf(), but that will work well. To save time and program space, you can write the raw accelerometer readings to the SD card and convert them later. My approach for that would be something like:
char buf[30];
snprintf(buf,sizeof(buf),"%lu,%d,%d,%d",millis(), x, y, z);
myFile.println(buf);

MyFile.print() writes to the internal SD card buffer, and should be very fast, unless the buffer is full and needs to be written to the SD card.

Post the revised code, if you have questions about it. Please use code tags.

Hey jremington, thank you again for the help. I was able to create a struct with the readings in it and then write that to an sd card as binary. I am currently still working on the matlab code to extract the data correctly. This is the link I found to an article that was really helpful: https://hackingmajenkoblog.wordpress.co … n-arduino/. Thank you for pointing me in the right direction, hopefully I am on my way towards finishing this project.