Hi, I'm new Arduino and was trying to design this interesting alarm for my bike in storage. The design is relatively simple; the alarm is self contained, battery operated and uses a motion (vibration) sensor from Signal Quest (SQ-SEN-200). The sensor is pulled high (or low) with high value resistor and basically sends fast pulses to interrupt input of Arduino in deep sleep. After waking up, the Arduino carries out a noise rejection algorithm ( see the app note attached) and activates the siren if the algorithm satisfied that there is an actual movement. If not, goes back into the deep sleep.
There is initial exit delay of 60 seconds, accompanied by a blinking LED, so it woundn't sound the siren during this time.
I tested this code, but it seems the device is stuck on the initial exit delay and the LED never stops blinking, and never goes into the deep sleep. I asked Chat GPT, which supposed to be good with this stuff, it changed the code but the issue still exists. The issue might be in Void Set UP. I'd appreciate the help reviewing this code.
EDIT: This code has been corrected and working properly now.
#include "LowPower.h"
const int sensorPin = 2; // Sensor connected to interrupt pin
const int alarmPin = 3; // Alarm or output to trigger when motion is detected
const int ledPin = 4; // External LED pin to indicate arming
volatile int pulseCount = 0; // Variable to store pulse count
volatile bool sensorTriggered = false; // Flag for sensor interrupt
unsigned long lastInterruptTime = 0; // Debounce control for interrupts
unsigned long wakeTime = 0; // Time when device woke up
// Constants for counting and logic
const int incVal = 5; // Value to increment Pulse_Count by
const int decVal = 1; // Value to decrement Pulse_Count by
const int maxPulseCount = 50; // Max value for pulse count to prevent overflow
const int threshold = 25; // Threshold for detecting motion (pulse count)
const int decayInterval = 500; // Time interval for pulse count decay (in ms)
const int debounceInterval = 200; // Time interval for the software one-shot (in ms)
const long startupDelay = 10000; // Startup delay in ms (1 minute)
const int alarmDuration = 5000; // How long alarm stays on (5 seconds)
const int stayAwakeTime = 2000; // Time to stay awake after waking up (2 seconds)
// Variables for startup delay and timing
unsigned long startupTime = 0;
unsigned long lastDecayTime = 0;
void setup() {
pinMode(sensorPin, INPUT); // Set sensor pin as input
pinMode(alarmPin, OUTPUT); // Set alarm pin as output
pinMode(ledPin, OUTPUT); // Set LED pin as output
Serial.begin(9600); // Start serial communication for debugging
startupTime = millis(); // Capture the start time for the 1-minute delay
digitalWrite(alarmPin, LOW); // Ensure alarmPin is firmly LOW during startup delay
digitalWrite(ledPin, LOW); // Ensure LED is OFF initially
Serial.println("Starting 60-second initialization delay...");
// Startup delay: Skip alarm triggering for the first 1 minute
while (millis() - startupTime < startupDelay) {
// Blink the LED every second during startup delay
digitalWrite(ledPin, HIGH); // Turn on the LED
delay(500); // Wait for 500ms
digitalWrite(ledPin, LOW); // Turn off the LED
delay(500); // Wait for 500ms
Serial.println("Startup delay active, alarm disabled.");
}
// After startup delay, attach interrupt and prepare for sleep
digitalWrite(ledPin, LOW); // Ensure LED is off
digitalWrite(alarmPin, LOW); // Ensure alarm is off
attachInterrupt(digitalPinToInterrupt(sensorPin), sensorInterrupt, RISING);
Serial.println("Startup complete, entering deep sleep mode.");
Serial.flush();
delay(100);
}
void loop() {
// Check if sensor was triggered (woke from sleep)
if (sensorTriggered) {
sensorTriggered = false; // Reset flag
wakeTime = millis(); // Record wake time
lastDecayTime = millis(); // Reset decay timer
Serial.print("Woke from sleep. Pulse count: ");
Serial.println(pulseCount);
Serial.println("Staying awake for decay monitoring...");
}
// Stay awake for the specified time to allow pulse decay
while (millis() - wakeTime < stayAwakeTime) {
// Apply pulse decay every decay interval
if (millis() - lastDecayTime >= decayInterval) {
if (pulseCount > 0) {
pulseCount -= decVal; // Decay pulse count
if (pulseCount < 0) pulseCount = 0; // Prevent negative values
Serial.print("Pulse count decayed to: ");
Serial.println(pulseCount);
}
lastDecayTime = millis();
}
// Check if alarm threshold is reached during wake period
if (pulseCount >= threshold) {
triggerAlarm();
wakeTime = millis(); // Reset wake time after alarm
break; // Exit the while loop after alarm
}
delay(50); // Small delay to prevent excessive loop cycling
}
// Reset pulse count to zero before going back to sleep
pulseCount = 0;
Serial.println("Pulse count reset to zero before sleep.");
Serial.print("Final pulse count before sleep: ");
Serial.println(pulseCount);
Serial.println("Going back to deep sleep...");
Serial.flush();
delay(100);
// Enter deep sleep mode
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}
void sensorInterrupt() {
// Debounce: Only allow one interrupt every 500ms (software one-shot)
unsigned long currentTime = millis();
if (currentTime - lastInterruptTime > debounceInterval) {
lastInterruptTime = currentTime;
// Only increment pulse count if it won't cause an overflow
if (pulseCount < (maxPulseCount - incVal)) {
pulseCount += incVal; // Increment pulse count by the defined increment value
}
// Set flag to indicate sensor was triggered (device woke up)
sensorTriggered = true;
}
}
void triggerAlarm() {
Serial.println("*** ALARM TRIGGERED! ***");
// Turn on alarm and LED
digitalWrite(alarmPin, HIGH);
digitalWrite(ledPin, HIGH);
// Keep alarm active for specified duration
delay(alarmDuration);
// Turn off alarm and LED
digitalWrite(alarmPin, LOW);
digitalWrite(ledPin, LOW);
// Reset pulse count after alarm
pulseCount = 0;
Serial.println("Alarm completed. Pulse count reset.");
Digital Filter and Motion Estimation Algorithm (SQ-SEN-200, SQ-MIN-200).pdf (244.3 KB)


