How to make an LED turn on for 60 seconds after ADXL345 experiences abrupt stop

Hey everyone,

I am quite new to Arduino world. I have a project that requires Accelerometer ADXL345 and Nano Arduino to turn an led when the ADXL345 experiences abrupt stop or sudden stop due to a blockage of stationary object in X-direction. I have been able to learn the accelerometer and I have come up with this code as follows. I have done some test to acquire the acceleration in terms of g where the accelerometer faces abrupt stop. I found it to be more than or equal to 3g.

#include <Wire.h> //Wire library used for I2C communication

int ADXL345 = 0x53; //The ADXL345 sensor I2C address

float Xa, Ya, Za; //Outputs at each 3-axis directions
int ledPin1 = 9;  //State leds with respect to digital pin

void setup() {
  Serial.begin(9600); //Initiate serial communication for printing the result on the serial
  pinMode(ledPin1, OUTPUT);
  Wire.begin(); //Initiate the Wire library
  //These lines below is to set ADXL in measuring mode
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2C);
  Wire.write(0x0A);
  Wire.endTransmission();
  Wire.beginTransmission(ADXL345); //Start communicating with the device
  Wire.write(0x2D); //Access or talk to POWER?CTL Register - 0x2D
  Wire.write(8); //Enable measurement //(8decimal -> 0000 1000 binary) Bit D3 High for measuring enable
  Wire.endTransmission();
  Wire.beginTransmission(ADXL345); 
  Wire.write(0x31);// Select data format register to start range setting option
  Wire.write(0x12); //Full resolution, Range = +/- 8g
  Wire.endTransmission();
  delay(10);

//This is to be activated when the ADXL345 needs to be calibrated
  //Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E); //From datasheet
  Wire.write(0); 
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F);
  Wire.write(2); 
  Wire.endTransmission();
  delay(10);
  //Z-Axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); 
  Wire.write(4);
  Wire.endTransmission();
  delay(10);
}

void loop() {
  //Read accelerometer data
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); //Start with register 0x32 (ACCEL_XA_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); //Read 6 registers total, each axis is stored in 2 registers
  Xa = ( Wire.read()| Wire.read() << 8); //X-axis value
  Xa = Xa/64; //For a range of +/-8g, we need to divide the raw values by 64 according to the datasheet
  Ya = ( Wire.read()| Wire.read() << 8); //Y-axis value
  Ya = Ya/64; 
  Za = ( Wire.read()| Wire.read() << 8); //Z-axis value
  Za = Za/64; 

  Serial.print("Xa= ");
  Serial.println(Xa);
  Serial.print("   Ya= ");
  Serial.println(Ya);
  Serial.print("      Za= ");
  Serial.println(Za); 

  Activate heating coils when pig experiences sudden stop
  if (Xa >= 3) {
    digitalWrite(ledPin1, HIGH);
    delay(60000)} 
  else {
    digitalWrite(heatingCoil, LOW);}

}

This is what I have attempted:

Activate heating coils when pig experiences sudden stop
  if (Xa >= 3) {
    digitalWrite(ledPin1, HIGH);
    delay(60000)} 
  else {
    digitalWrite(heatingCoil, LOW);}

I need y’all expertise to correct what I have attempted because I don’t think this is how it should be coded. On another side note, the acceleration change from 0g to 3g and return back to 0g really fast. How do I write the code that allow the arduino to turn on the led for a long time i.e. 60 s when the accelerometer only gets to 3g for a very short time and the acceleration at x-axis goes to negative and goes back to its datum which is 0g shortly after collision with the stationary object?

Good job using code tags on your first post.

Ypour requirements are somewhat unclear. I’m not sure why you are turning on an led and turning off a heating coil. When does the heating coil turn back on? When does the led turn off?

If you intended for the heating coil to be turned on for a minute and then turned off, the basic template for a timed interval is

 if (Xa >= 3 && !heaterTiming) 
  {
    digitalWrite(heatingCoil, HIGH);
    heaterTiming = true;
    startTime = millis();
    //delay(60000)} 
 // else {
 if(heaterTiming && millis()-startTime>= 60000UL)
   {
    digitalWrite(heatingCoil, LOW);
    heaterTiming = false;
   }

If you're only interested in X axis, why read and print Y and Z? What if the pig stops between reads?

cattledog, that was a mistake on my part. We tested the code on an led, but the actual project utilizes heating coils. Thank you for your help. So, by using the code that you've written, the heating coils will be turned on for 60 seconds even though Xa reaches 3 for a short period of time and goes back to 0?

You are right, I guess I don't need to print acceleration in Y and Z direction. if its not a sudden stop or abrupt stop, the acceleration will not get to 3g and so the heating coils will not be turned on

So, by using the code that you've written, the heating coils will be turned on for 60 seconds even though Xa reaches 3 for a short period of time and goes back to 0?

Yes. That's what the heaterTiming boolean control variable does.

Once heaterTiming becomes true when Xa initially reaches 3, the value of Xa is no longer involved in the running time of the heater.

Cattledog, thank you so much for taking the time to help me with this.

Cattledog, I tried your code and it said 'heaterTiming' was not declared in this scope. do I need to declare it using int or const int?

Cattledog, I tried your code and it said ‘heaterTiming’ was not declared in this scope. do I need to declare it using int or const int?

Certainly the new variables in the code fragment I provided need to be declared in your code. heaterTiming is a boolean (bool) variable with values true and false.

Make the new variables global

boolean heaterTiming = false;
unsigned long startTime;