Hello everyone,
I am currently working on a project to monitor vibrations up to 1kHZ. For that, I need to take at least 2k samples a second. I am using an Arduino Nano 33 BLE with an Adafruit LIS3DH accelerometer (Overview | Adafruit LIS3DH Triple-Axis Accelerometer Breakout | Adafruit Learning System) and an Adafruit MicroSD card board (MicroSD card breakout board+ : ID 254 : $7.50 : Adafruit Industries, Unique & fun DIY electronics and kits). Both are wired to the Arduino via SPI. I am currently only getting around 600 samples per second written on the microSD card. How can I increase the write speed?
Code:
/*Running the LIS3DH accelerometer and writing the data to a microSD card
* by willish32
* Created 6/29/20
*/
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
//ACCELEROMETER SPI SETUP
// Used for hardware & software SPI
#define LIS3DH_CS 10
// hardware SPI
Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS);
//SD CARD SETUP
File myFile; //file name on SD
unsigned long timer; //timer var to track the datapoints per second... Plan on adding an RTC module later on to keep track of time
#define SIZE 100 //size of array 400 gets 2000 samples/sec ... sadly not anymore
double samples[SIZE][4]; //declare variable for sample storage
//FUNCTIONS
//Retrieve the data from the sensor
void getData() {
//Collect data from the sensor
for(int i=0; i<SIZE; i++){
lis.read(); // get X Y and Z data at once
// Then print out the raw data
/*Serial.print("X: "); Serial.print(lis.x);
Serial.print(" \tY: "); Serial.print(lis.y);
Serial.print(" \tZ: "); Serial.print(lis.z);
*/
/* Or....get a new sensor event, normalized */
sensors_event_t event;
lis.getEvent(&event);
/* Display the results (acceleration is measured in m/s^2) */
/*Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
Serial.print(" \tY: "); Serial.print(event.acceleration.y);
Serial.print(" \tZ: "); Serial.print(event.acceleration.z);
Serial.println(" m/s^2 ");
Serial.println();
*/
//collect the data in blocks
samples[i][0] = timer;
samples[i][1] = event.acceleration.x;
samples[i][2] = event.acceleration.y;
samples[i][3] = event.acceleration.z;
}
}
//Write the data to the MicroSD card
void writeData() {
//write data to the MicroSD
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
for(int i=0; i<SIZE; i++) {
myFile.print(samples[i][0]);
myFile.print(" ms \t X: ");
myFile.print(samples[i][1]);
myFile.print("\t Y: ");
myFile.print(samples[i][2]);
myFile.print("\t Z: ");
myFile.print(samples[i][3]);
myFile.print("\n");
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void setup() {
//setup the MicroSD card
Serial.begin(115200);
while (!Serial) {
; //wait for the serial port to connect before proceding
}
Serial.print("Initializing SD card...");
pinMode(9, OUTPUT); //set pin 9 as the output
if (!SD.begin(9)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
//setup the sensor
Serial.println("LIS3DH test!");
if (! lis.begin(0x18)) { // change this to 0x19 for alternative i2c address
Serial.println("Couldnt start");
while (1) yield();
}
Serial.println("LIS3DH found!");
// lis.setRange(LIS3DH_RANGE_4_G); // 2, 4, 8 or 16 G!
Serial.print("Range = "); Serial.print(2 << lis.getRange());
Serial.println("G");
lis.setDataRate(LIS3DH_DATARATE_LOWPOWER_5KHZ);
Serial.print("Data rate set to: ");
switch (lis.getDataRate()) {
case LIS3DH_DATARATE_1_HZ: Serial.println("1 Hz"); break;
case LIS3DH_DATARATE_10_HZ: Serial.println("10 Hz"); break;
case LIS3DH_DATARATE_25_HZ: Serial.println("25 Hz"); break;
case LIS3DH_DATARATE_50_HZ: Serial.println("50 Hz"); break;
case LIS3DH_DATARATE_100_HZ: Serial.println("100 Hz"); break;
case LIS3DH_DATARATE_200_HZ: Serial.println("200 Hz"); break;
case LIS3DH_DATARATE_400_HZ: Serial.println("400 Hz"); break;
case LIS3DH_DATARATE_POWERDOWN: Serial.println("Powered Down"); break;
case LIS3DH_DATARATE_LOWPOWER_5KHZ: Serial.println("5 Khz Low Power"); break;
case LIS3DH_DATARATE_LOWPOWER_1K6HZ: Serial.println("16 Khz Low Power"); break;
}
}
void loop() {
//start the timer
timer = millis();
getData();
writeData();
//test for shutdown command
int incomingByte = 0;
if(Serial.available() >= 0){
incomingByte=Serial.read();
}
//shutdown
if(incomingByte == '0'){
myFile.close();
Serial.print("The process has ended");
}
}