#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include "LIS2DH12.h" //the library
LIS2DH12 accel; //Create instance
File myFile; //File name to be saved
IntervalTimer myTimer;
#define Fs 1024
uint32_t totalSamples = 10*Fs + 50; // no. of samples
long int samplesCollected = 0;
char filename[26]="";
const int chipSelect = BUILTIN_SDCARD; // Builtin function for SD card
#define DEBUGPRINT true
volatile uint16_t saveidx = 0;
volatile int16_t writebuffnum = -1;
volatile uint16_t savebuffnum = 0;
volatile uint32_t filestartmilli = 0;
struct dataRec {
uint32_t ltime;
float x, y, z;
uint16_t spare;
};
#define BUFFSIZE Fs
// allocate two buffers, each of which holds Fs records
struct dataRec dBuff0[BUFFSIZE];
struct dataRec dBuff1[BUFFSIZE];
const int ledpin = 13;
#define LEDON digitalWriteFast(ledpin, HIGH);
#define LEDOFF digitalWriteFast(ledpin, LOW);
const char compileTime [] = "Simple Data Logger Compiled on " __DATE__ " " __TIME__;
void setup()
{
pinMode(ledpin, OUTPUT);
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect.
}
Serial.println(compileTime);
Wire.begin();
Wire.setClock(1000000); // For MaxOutput
if (accel.begin() == false)
{
Serial.println("Accelerometer not detected. Check address jumper and wiring. Freezing...");
while (1)
;
}
/////////////////////////////
// Select g Scale, // no. of bits, // and frequency
//accel.setScale(LIS2DH12_2g);
//accel.setScale(LIS2DH12_4g);
//accel.setScale(LIS2DH12_8g);
accel.setScale(LIS2DH12_16g);
int currentScale = accel.getScale();
Serial.print("Current scale (0 to 3 = 2g, 4g, 8g, 16g): ");
Serial.println(currentScale);
//accel.setMode(LIS2DH12_LP_8bit);
//accel.setMode(LIS2DH12_NM_10bit);
accel.setMode(LIS2DH12_HR_12bit);
int currentMode = accel.getMode();
Serial.print("Current mode (0 to 2 = 8bits, 10bits, 12bits): ");
Serial.println(currentMode);
//Sensor output rate ranges from 1 to 5.376kHz
//The lower the output rate the lower the power consumption
//accel.setDataRate(LIS2DH12_POWER_DOWN);
//accel.setDataRate(LIS2DH12_ODR_1Hz);
//accel.setDataRate(LIS2DH12_ODR_10Hz);
//accel.setDataRate(LIS2DH12_ODR_25Hz);
//accel.setDataRate(LIS2DH12_ODR_50Hz);
//accel.setDataRate(LIS2DH12_ODR_100Hz);
//accel.setDataRate(LIS2DH12_ODR_200Hz);
//accel.setDataRate(LIS2DH12_ODR_400Hz);
accel.setDataRate(LIS2DH12_ODR_1kHz620_LP);
//accel.setDataRate(LIS2DH12_ODR_5kHz376_LP_1kHz344_NM_HP);
int currentRate = accel.getDataRate();
Serial.print("Current rate (0 to 9 = Powe_Down, 1Hz, 10Hz, 25Hz, 50Hz, 100Hz, 200Hz, 400Hz, 1kHz, 5kHz): ");
Serial.println(currentRate);
// accel.disableTemperature();
/////////////////////////////////////////
Serial.print("Initializing SD card...");
// Make the file name with timestamp and extension
char fname[] = "DL";
char tmstmp[] = "1G8G5A60";
// char tmstmp[21];
// sprintf(tmstmp,"%4d%02d%02d",year(),month(),day()); // not working (dynamic name of the .csv file)
char fext[] = ".csv";
strcat(filename, fname);
strcat(filename, &tmstmp[2]);
strcat(filename, fext);
Serial.println(filename);
if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
Serial.println("Enter command.! (r, q, p) for (RequestLogging, QuitLogging, PlaybackLog");
}
long measurements = 0; // For MaxOutput
///////////////////////////////////////////////////
void loop()
{
char ch;
if (Serial.available()) {
ch = Serial.read();
if (ch == 'r') RequestLogging();
if (ch == 'q') QuitLogging();
if (ch == 'p') PlaybackLog();
}
if (samplesCollected == totalSamples){
PlaybackLog();
}
if (writebuffnum == 0) { //is dbuff0 ready?
LEDON
writebuffnum = -1;
if (myFile) { //if the file is open write dbuff0
WriteCSV(&dBuff0[0], BUFFSIZE);
if (DEBUGPRINT) {
Serial.print("Writing dBuff0 to data file. tmilli = ");
Serial.printf(" %lu\n", dBuff0[0].ltime);
}
}
LEDOFF
}
if (writebuffnum == 1) { // is dbuff1 ready?
LEDON
writebuffnum = -1;
if (myFile) { //if the file is open write dbuff0
WriteCSV(&dBuff1[0], BUFFSIZE);
if (DEBUGPRINT) {
Serial.print("Writing dBuff1 to data file. tmilli = ");
Serial.printf(" %lu \n", dBuff1[0].ltime);
}
}
LEDOFF
}
delay(5);
}
////////////////////////////////
void WriteCSV(volatile struct dataRec *drp, size_t numlines){
uint16_t i;
char dataString[100];
for(i= 0; i< numlines; i++){
sprintf(dataString,"%5u, %2f, %2f, %2f\n", drp->ltime,drp->x,drp->y, drp->z);
myFile.print(dataString);
drp++; // advance pointer to next record in buffer
}
}
///////////////////////////////
void fillBuffer(void) {
if(samplesCollected >= totalSamples) return; // no more collection when all samples taken
uint32_t tmilli;
tmilli = millis() - filestartmilli;
// save in the proper buffer--defined by savebuffnum
if (accel.available()) {
if (savebuffnum == 0) { // put data in dbuff0
dBuff0[saveidx].ltime = tmilli;
dBuff0[saveidx].x = accel.getX();
dBuff0[saveidx].y = accel.getY();
dBuff0[saveidx].z = accel.getZ();
samplesCollected++;
measurements++;
saveidx++;
if (measurements % Fs == 0) {
int hertz = measurements * Fs / millis();
Serial.print("measurements: ");
Serial.print(measurements);
Serial.print(" time: ");
Serial.print(millis());
Serial.print(" Measurement rate: ");
Serial.print(hertz);
Serial.print("Hz");
Serial.println();
}
if (saveidx >= BUFFSIZE) { // mark buffer for write to SD
writebuffnum = 0;
savebuffnum = 1; // start saving in other buffer on next interrupt
saveidx = 0; // start at beginning of next buffer
}
}
else { // must be saving to dbuff1
dBuff1[saveidx].ltime = tmilli;
////////////////////////////////////////////////
// float to buffer storage ?
// float accelX = accel.getX();
// float accelY = accel.getY();
// float accelZ = accel.getZ();
// char dtostrfbuffer1[2];
// char dtostrfbuffer2[2];
// char dtostrfbuffer3[2];
//dtostrf(accelX, 1, 0, dtostrfbuffer1);
//dtostrf(accelY, 1, 0, dtostrfbuffer2);
//dtostrf(accelZ, 1, 0, dtostrfbuffer3);
// dBuff1[saveidx].x = dtostrfbuffer1;
// dBuff1[saveidx].y = dtostrfbuffer2;
// dBuff1[saveidx].z = dtostrfbuffer3;
///////////////////////////////////////////////
// just uncomment to go previous mode
dBuff1[saveidx].x = accel.getX();
dBuff1[saveidx].y = accel.getY();
dBuff1[saveidx].z = accel.getZ();
////////////////////////////////////////////////
//This was used just to compare the values
//Serial.println(accelX);
//Serial.println(dtostrfbuffer1);
//Serial.println(dBuff1[saveidx].x);
//Serial.println(accelY);
//Serial.println(dtostrfbuffer2);
//Serial.println(dBuff1[saveidx].y);
//Serial.println(accelZ);
//Serial.println(dtostrfbuffer3);
//Serial.println(dBuff1[saveidx].z);
////////////////////////////////////////////////
samplesCollected++;
measurements++;
saveidx++;
if (measurements % Fs == 0) {
int hertz = measurements * Fs / millis();
Serial.print("measurements: ");
Serial.print(measurements);
Serial.print(" time: ");
Serial.print(millis());
Serial.print(" Measurement rate: ");
Serial.print(hertz);
Serial.print("Hz");
Serial.println();
}
if (saveidx >= BUFFSIZE) { // mark buffer for write to SD
writebuffnum = 1;
savebuffnum = 0; // start saving in other buffer on next interrupt
saveidx = 0; // start at beginning of next buffer
}
}
}
}
//////////////////////////////////////////////////////////
void RequestLogging(void) {
if (myFile) {
Serial.println("Already collecting!");
return;
}
// we open in a mode that creates a new file each time
// instead of appending as in the Arduino example
if(SD.exists(filename)) SD.remove(filename);
myFile = SD.open(filename, FILE_WRITE);
// if the file can't be opened, say so
if (!myFile) {
Serial.println("Could not open output file!");
return;
}
Serial.println("Requested ... Starting Logging");
myFile.println(" TIME, X, Y, Z"); // put header line in file
// initialize some variables for the buffers
saveidx = 0; // start saving at beginning of buffer
savebuffnum = 0; // start saving in dbuff0
writebuffnum = -1; // indicates no buffer ready yet
// start the interval timer to begin logging
filestartmilli = millis();
myTimer.begin(fillBuffer, 1e6/Fs); //begin() expects timer period in microseconds
}
////////////////////////////////////////////////////////
void QuitLogging(void) {
Serial.println("Quit ... Stopping Logging");
myTimer.end();
if (DEBUGPRINT) Serial.println("myTimer halted");
delay(10);
if (myFile) {
Serial.println("Data file closed.");
myFile.close(); // if file was open, close it.
} else {
if (DEBUGPRINT) Serial.println("myFile was not open!");
}
writebuffnum = -1;
// in the interest of simplicity, we ignore any partial buffer at the end
}
//////////////////////////////////////////////////////////
void PlaybackLog(void) {
String datline;
if(myFile) QuitLogging(); // if still recording, stop and close file
myFile = SD.open(filename, FILE_READ);
if(!myFile){
Serial.println("Could not open data file for reading.");
return;
}
while (myFile.available()) {
datline = myFile.readStringUntil('\n');
Serial.println(datline);
}
myFile.close();
Serial.println("\nPlayback complete.");
}