Conditional data storing to Micro SD card from ADXL 345 sensor via Arduino Uno

Hi,

I am developing a low-cost accelerometer to measure seismic activity in an area. I have used Arduino Uno, MEMS ADXL 345, Micro SD card Module with a 16 GB SD card and I will possibly add a RTC module such as DS3231.

There is a trigger mechanism involved. If the resultant acceleration in the XY plane exceeds a certain value the accelerometer will record the data into the SD card at 100 samples per second (txt or CSV format) and if the measured data is below the threshold for a minute, the device will save data data in the name format of the DD:MM: YYYY HH:MM:SS of the start of the data storing.

The problem is the trigger mechanism is not working. I have tried thresholds like 0.05 g, 0.1 g 0.5 g, etc., but either it gives gibberish results or it gives nothing at all. what might cause the problem?

Due to that problem, I am measuring the data continuously, which gives rise to storage issues.

I am attaching the connections and the code here:

Connections:

MicroSD Card Module

VCC - Arduino Uno 5V pin.
GND - Arduino Uno GND pin.
CS - Arduino Uno pin 4.
MOSI - Arduino Uno pin 11.
MISO - Arduino Uno pin 12.
SCK - Arduino Uno pin 13.

ADXL345 Module:

VCC - 3.3V power supply of Arduino Uno.
GND - GND pin of Arduino Uno.
SDA - analog input pin A4
SCL - analog input pin A5

The Code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h> 
// Constants for accelerometer
#define ADXL345_ADDRESS (0x53)
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

// Constants for SD card
const int chipSelect = 4;
File dataFile;
unsigned long lastDataTime = 0;
unsigned long noReadingStartTime = 0;
bool recordingData = false;
const unsigned long noReadingTimeout = 60000; // 1 minute

// Variables for data
float accelerationX, accelerationY, accelerationZ;
float prevMagnitude = 0.0;
const float threshold = 0.5; // 0.0981 m/s²

void setup() {
  Serial.begin(115200);

  // Initialize accelerometer
  if (!accel.begin()) {
    Serial.println("Could not find a valid ADXL345 sensor, check wiring!");
    while (1);
  }

  // Initialize SD card
  if (!SD.begin(chipSelect)) {
    Serial.println("SD card initialization failed!");
    while (1);
  }
}

void loop() {
  unsigned long currentTime = millis();
  sensors_event_t event;
  accel.getEvent(&event);
  accelerationX = event.acceleration.x;
  accelerationY = event.acceleration.y;
  accelerationZ = event.acceleration.z;

  float magnitude = sqrt(sq(accelerationX) + sq(accelerationY));
  float deltaMagnitude = abs(magnitude - prevMagnitude);
  
  if (deltaMagnitude > threshold) {
    // Reset noReadingStartTime when threshold is exceeded
    noReadingStartTime = currentTime;
    
    if (!recordingData) {
      // Start recording data
      startRecording();
    }
    
    if (recordingData) {
      // Store data on SD card
      String dataString = String(currentTime) + "," + String(accelerationX) + "," + String(accelerationY) + "," + String(accelerationZ);
      dataFile.println(dataString);
    }
  } else {
    if (recordingData && (currentTime - noReadingStartTime >= noReadingTimeout)) {
      // Stop recording and save data
      stopRecording();
    }
  }
  
  prevMagnitude = magnitude;
  
  // Maintain data measurement frequency
  unsigned long timeSinceLastData = currentTime - lastDataTime;
  if (timeSinceLastData >= 10) { // 10 milliseconds for 100 samples per second
    lastDataTime = currentTime;
  }
}

void startRecording() {
  String fileName = getFormattedDateTime() + ".csv";
  dataFile = SD.open(fileName, FILE_WRITE);
  
  if (dataFile) {
    recordingData = true;
    Serial.println("Recording data...");
  }
}

void stopRecording() {
  if (recordingData) {
    dataFile.close();
    recordingData = false;
    Serial.println("Stopped recording data.");
  }
}

String getFormattedDateTime() {
  char buffer[20];
  sprintf(buffer, "Data_%02d-%02d-%04d_%02d-%02d-%02d", 
          day(), month(), year(), hour(), minute(), second());
  return String(buffer);
}

The UNO is a 5 volt output device and the ADXL is a 3.3 volt device. Signals from the UNO to the ADXL need to be level shifted. Else damages can be expected. Hard to say if this is the case or not but correct the build on that point.

Good catch!

The ADXL365 can also do I2C is doing I2C - so you could use that, and have the pullups to 3.3V (3.6V max):

EDIT: I misread the OP, and thought the ADXL was being used on SPI. :man_facepalming: :man_facepalming:

It provides acceleration values though when I use serial monitor or ArduSpreadsheet to collect live data. It just isn’t working when it comes to the triggering issue.

I am new in using Arduino, so I thought I may have made a silly mistake. I have used a threshold trigger before, to send messages via SIM 900 GPRS module, that worked too. Although I had set the threshold to 0.5 to 1.0 g ( 5-10 m/s/s) for that which are significantly greater than the values I am using now.

Can it be a sensitivity issue?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.