Skip to content

Commit

Permalink
Update sensor code with speed and filespace improvements. (#3)
Browse files Browse the repository at this point in the history
* Update sensor code with speed and filespace improvements.

* Clean up comments. Write data using G instead of meters-per-sec-squared.

* Use actual G values for acceleration instead of raw values.
  • Loading branch information
erichiggins authored Feb 19, 2019
1 parent dbfd192 commit f8a7a0d
Showing 1 changed file with 118 additions and 135 deletions.
253 changes: 118 additions & 135 deletions accelerometer/sensor_logger.ino
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
/**
* Created by Ammolytics
* License: MIT
* Version: 1.0.0
* Version: 2.0.0
* URL: https://github.com/ammolytics/projects/
* Inexpensive firearm accelerometer based on the Adafruit LIS3DH breakout board.
*/

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include "RTClib.h"
#include "SdFat.h"

// Used for software SPI
#define LIS3DH_CLK 13
#define LIS3DH_MISO 12
#define LIS3DH_MOSI 11
// Used for hardware & software SPI
#define LIS3DH_CS 10

// Battery pin
#define VBATPIN A7

// I2C clock speed
#define I2C_SPEED 1000000

// Enable debug logger.
// Note: Comment out before running in real-world.
#define DEBUG
Expand All @@ -39,19 +37,18 @@ RTC_PCF8523 rtc;
// change this to match your SD shield or module;
// Adafruit SD shields and modules: pin 10
const int chipSelect = 10;
// 19 digits plus the null char
char DateTimeString[20];

// Filename format: 20180710.csv
char filename[13];

char dataRow[10000];
String strRow;
int counter = 0;
// Filename format: YYYYMMDDHHmm.csv
char filename[17];


int lastX;
unsigned long begin_us;
unsigned long begin_epoch;
unsigned long start_us;
unsigned long stop_us;
unsigned long counter = 0;

File dataFile;

// software SPI
//Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS, LIS3DH_MOSI, LIS3DH_MISO, LIS3DH_CLK);
Expand All @@ -60,29 +57,30 @@ File dataFile;
// I2C
Adafruit_LIS3DH lis = Adafruit_LIS3DH();

// set up variables using the SD utility library functions:
// File system object.
SdFat sd;
// Log file.
SdFile dataFile;


void setup() {
#ifdef DEBUG
Serial.begin(9600);
Serial.begin(115200);
while (!Serial); // will pause Zero, Leonardo, etc until serial console opens
#endif

float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
DEBUG_PRINT("VBat: " ); DEBUG_PRINTLN(measuredvbat);

DEBUG_PRINTLN("Initializing SD card...");

if (!SD.begin(chipSelect)) {
DEBUG_PRINTLN("Card failed, or not present");
// don't do anything more:
while (1);
}
DEBUG_PRINTLN("Card initialized.");
#ifdef DEBUG
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
DEBUG_PRINT("VBat: " ); DEBUG_PRINTLN(measuredvbat);
#endif


/**
* Initialize the Real Time Clock.
*/
DEBUG_PRINTLN("Initializing RTC...");
if (! rtc.begin()) {
DEBUG_PRINTLN("Couldn't find RTC");
Expand All @@ -92,127 +90,112 @@ void setup() {
DEBUG_PRINTLN("RTC is NOT running!");
}
DEBUG_PRINTLN("RTC initialized.");
begin_us = micros();
DateTime now = rtc.now();
begin_epoch = now.unixtime();


DEBUG_PRINTLN("Initializing LIS3DH Sensor...");
if (! lis.begin(0x18)) { // change this to 0x19 for alternative i2c address
DEBUG_PRINTLN("Couldnt start");
/**
* Initialize the SD card and log file.
*/
DEBUG_PRINTLN("Initializing SD card...");
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
DEBUG_PRINTLN("Card failed, or not present");
// don't do anything more:
while (1);
}
lis.setRange(LIS3DH_RANGE_4_G); // 2, 4, 8 or 16 G!
DEBUG_PRINTLN("LIS3DH initialized.");


DEBUG_PRINTLN("Ready!");

DateTime now = rtc.now();
sprintf_P(DateTimeString, PSTR("%4d-%02d-%02d %d:%02d:%02d"),
now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
sprintf_P(filename, PSTR("%4d%02d%02d.csv"), now.year(), now.month(), now.day());

DEBUG_PRINTLN(DateTimeString);
DEBUG_PRINTLN("Card initialized.");

// Set filename based on timestamp.
sprintf_P(filename, PSTR("%4d%02d%02d%02d%02d.csv"), now.year(), now.month(), now.day(), now.hour(), now.minute());
DEBUG_PRINT("Filename: ");
DEBUG_PRINTLN(filename);

dataFile = SD.open(filename, O_CREAT | O_WRITE);
dataFile.println("timestamp, accel x, accel y, accel z, accel unit, sensor range, millis, micros, voltage");
DEBUG_PRINTLN(dataFile);
if (! dataFile) {
if (! dataFile.open(filename, O_CREAT | O_APPEND | O_WRITE)) {
DEBUG_PRINTLN("Could not open file...");
while (1);
}
dataFile.close();

DEBUG_PRINTLN("timestamp (s), start (µs), delta (µs), accel x (G), accel y (G), accel z (G)");
// Write header row to file.
dataFile.println("timestamp (s), start (µs), delta (µs), accel x (G), accel y (G), accel z (G)");
dataFile.flush();

// Check to see if the file exists:
if (SD.exists(filename)) {
DEBUG_PRINTLN("Log file exists.");
} else {
if (! sd.exists(filename)) {
DEBUG_PRINTLN("Log file doesn't exist.");
while (1);
}

/**
* Initialize the accelerometer.
*/
DEBUG_PRINTLN("Initializing LIS3DH Sensor...");
if (! lis.begin(LIS3DH_DEFAULT_ADDRESS)) { // change this to 0x19 for alternative i2c address
DEBUG_PRINTLN("Couldnt start");
while (1);
}
// Set I2C high speedmode
Wire.setClock(I2C_SPEED);
// Set range to 8G
lis.setRange(LIS3DH_RANGE_8_G);
// 5khz data rate
lis.setDataRate(LIS3DH_DATARATE_LOWPOWER_5KHZ);
DEBUG_PRINTLN("LIS3DH initialized.");

// Leave the file open for writing.
dataFile = SD.open(filename, O_CREAT | O_APPEND | O_WRITE);
DEBUG_PRINTLN("Ready!");
}



// Main Loop
void loop() {
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
//DEBUG_PRINT("VBat: " ); DEBUG_PRINTLN(measuredvbat);
// Read from the accelerometer sensor and measure how long the op takes.
start_us = micros();
lis.read();
stop_us = micros();

// Roughly equivalent to calling rtc.now().unixtime(), without 1ms latency.
DEBUG_PRINT(begin_epoch + ((stop_us - begin_us) / 1000000));
DEBUG_PRINT(',');
// Write timestamp to file.
dataFile.print(begin_epoch + ((stop_us - begin_us) / 1000000));
dataFile.print(',');

DEBUG_PRINT(start_us);
DEBUG_PRINT(',');
DEBUG_PRINT(stop_us - start_us);
DEBUG_PRINT(',');
// Write timers to file.
dataFile.print(start_us);
dataFile.print(',');
dataFile.print(stop_us - start_us);
dataFile.print(',');

lis.read(); // get X Y and Z data at once
// Then print out the raw data
/*
DEBUG_PRINT(lis.x); DEBUG_PRINT(", ");
DEBUG_PRINT(lis.y); DEBUG_PRINT(", ");
DEBUG_PRINT(lis.z); DEBUG_PRINT(", ");
*/

/* Or....get a new sensor event, normalized */
sensors_event_t event;
lis.getEvent(&event);

int rangeVal = 2 << lis.getRange();

DateTime now = rtc.now();

/*
sprintf_P(dataRow, PSTR("%d, %d, %d, %d, %s, %s, %d"),
now.unixtime(), event.acceleration.x, event.acceleration.y, event.acceleration.z, "m/s^2", rangeVal, millis());
DEBUG_PRINTLN(dataRow);
*/

/* Display the results (acceleration is measured in m/s^2) */
strRow = String(now.unixtime()) + ", ";
strRow += String(event.acceleration.x) + ", ";
strRow += String(event.acceleration.y) + ", ";
strRow += String(event.acceleration.z) + ", ";
strRow += "m/s^2, ";
strRow += String(rangeVal) + ", ";
strRow += String(millis()) + ", ";
strRow += String(micros()) + ", ";
strRow += String(measuredvbat);

DEBUG_PRINTLN(strRow);

// Open the file if it's closed.
if (!dataFile) {
dataFile = SD.open(filename, O_CREAT | O_APPEND | O_WRITE);
}
// if the file is available, write to it:
if (dataFile) {
dataFile.println(strRow);
} else {
// if the file isn't open, pop up an error:
DEBUG_PRINTLN("error opening file");
}

// Determine if the unit is actively recording important motion to prevent delays from writing ops.
// X-Axis is inline with bore. Least likely to detect acceleration of gravity.
bool inMotion = false;
if (max(event.acceleration.x, lastX) > 1.0 || min(event.acceleration.x, lastX) < -1.0) {
inMotion = true;
}

DEBUG_PRINT(lis.x_g);
DEBUG_PRINT(',');
DEBUG_PRINT(lis.y_g);
DEBUG_PRINT(',');
DEBUG_PRINT(lis.z_g);
// Write acceleration to file.
dataFile.print(lis.x_g);
dataFile.print(',');
dataFile.print(lis.y_g);
dataFile.print(',');
dataFile.print(lis.z_g);

DEBUG_PRINTLN();
// Write newline.
dataFile.println();
counter++;
// write the data to prevent loss.
if (counter >= 20 && !inMotion) {
DEBUG_PRINTLN("Data file write/flush.");

/**
* Flush buffer, actually write to disk.
* This can take between 9 and 26 milliseconds. Or ~10ms with SDfat.
*/
if (counter >= 800) {
DEBUG_PRINTLN("Writing to SD card");
unsigned long pre_write = micros();
dataFile.flush();
unsigned long post_write = micros();
DEBUG_PRINT("Write ops took: "); DEBUG_PRINTLN(post_write - pre_write);
counter = 0;
} else {
DEBUG_PRINTLN(inMotion);
}
if (counter >= 100) {
DEBUG_PRINTLN("Data file write/close.");
dataFile.close();
counter = 0;
}

lastX = event.acceleration.x;

//delay(1);
}

0 comments on commit f8a7a0d

Please sign in to comment.