Hi all,
I found an excellent home alarm system wrote by Steven Bell at the following site:https://create.arduino.cc/projecthub/thestevenbell/arduino-alarm-system-db084a
The problem I have though, is that the alarm alerts only for as long as the PIR outputs a high signal. Ideally, in a home alarm the alarm should alert for a fixed period of time (eg. 5 minutes), or until manually deactivated with a code within the 5 minute period.
What I thus need is for the alarm to latch onto a alerting state for a fixed period of time. I have tried using the millis function, but as a newcomer to that function, I have not been able to make it work (after a week of trying different ways) I realize the sketch employs advanced programming techniques, thus I am at a loss to figure out exactly where to use the millis function, as it should start counting when the alarm is triggered.
I have considered using a discrete timer (555 timer, controlled by the Arduino), but that adds too much complexity to the project, a programmatical method is simpler.
The use of Delay is not practical in this case, as it blocks the disarming of the alarm by entering a code.
All advice will be greatly appreciated.
[code]
/*
LCD backpack SDA pin to analog pin A4 (on Nano)
LCD backpack SDL pin to analog pin A5 (on Nano)
LCD VCC pin to 5V
LCD GND pin to GND
*/
#include <TwiLiquidCrystal.h>
TwiLiquidCrystal lcd(0x27);
//#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
// LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
//LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
boolean doInitilizeLCD = true;
// --KEY PAD START ----------------------------------------------------
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the symbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
char customKey;
char accessCode[] = "9113";
char keyPadInput[] = "zzzz";
unsigned char inputCounter = 0;
unsigned char inputMaxCount = 4;
// --KEY PAD END ------------------------------------------------------
int ledPin = 11; // LED on Pin 11, lights up when PIR is active and armed.
int powerledPin = 13; // LED on Pin 13, indicates power on, always HIGH
int pirPin = 10; // Input for HC-S501
int pirValue; // Place to store read PIR Value
int doorPin = A0; // door magnetic switch
int doorValue; // Place to store read magnetic switch Value
int alarmPin = A2; // Relay to switch siren
int statusPin = A3; // LED on Pin A3, lights up when PIR is active, must be off before arming.
// --Active Buzzer START ----------------------------------------------
int buzzer = 12;//the pin of the active buzzer
boolean shouldBeAlerting = false;
// --Active Buzzer END ------------------------------------------------------
enum ArmedStates {ARMED, DISARMED};
ArmedStates armedState = DISARMED;
short armedTimerInterval = 5;
unsigned long armedTimer = millis();
unsigned long previousMillis1 = 0;
unsigned long startMillis = 0;
unsigned long currentMillis;
//const unsigned long delayTime = 600000;
bool debug = false;
void setup() {
Serial.begin(9600);
while (!Serial); // wait for Serial to connect
Serial.println("ready");
pinMode(buzzer, OUTPUT); // set up pin as output
pinMode(ledPin, OUTPUT); // set up pin as output
pinMode(powerledPin, OUTPUT); // set pin as output
pinMode(alarmPin, OUTPUT); // set pin as output
pinMode(pirPin, INPUT); // set pin as input
pinMode(doorPin, INPUT); // set pin as input
pinMode(statusPin, OUTPUT); // set pin as output
lcd.begin(16, 2); // set up and register the LCD
lcd.backlight();
//startMillis = millis(); //initial start time
}
void loop() {
digitalWrite(powerledPin, HIGH);
if (pirValue == HIGH) {
digitalWrite(statusPin, HIGH);
} else {
digitalWrite(statusPin, LOW);
}
initilizeLCD();
handleKeyPadInput();
handlePIR();
alert();
//handleAlarm;
}
const char* getStateString(enum ArmedStates armedState) {
switch (armedState)
{
case ARMED: return "ARMED";
case DISARMED: return "DISARMED";
}
}
//
void initilizeLCD() {
if (doInitilizeLCD) {
doInitilizeLCD = false;
lcd.clear();
String a = getStateString(armedState);
if (debug) {
Serial.println("armedState: " + a);
}
lcd.setCursor(0, 0);
lcd.print(a);
lcd.setCursor(0, 1);
lcd.print("PRESS * to ARM.");
}
}
void handleLCD(bool shouldClearLCD) {
if (shouldClearLCD) {
lcd.clear();
}
String a = getStateString(armedState);
if (debug) {
Serial.println("armedState: " + a);
}
lcd.setCursor(0, 0);
lcd.print(a);
lcd.setCursor(0, 1);
lcd.print("DISARM KEY:");
uint8_t cursorStart = 11;
lcd.setCursor(cursorStart, 1);
lcd.cursor();
// overwrites the LCD screen positions with blank space or keypad input
for (int i = 0; i < 4; i++) {
if (keyPadInput[i] == 'z') {
lcd.setCursor(cursorStart + i, 1);
lcd.print(" ");
} else {
lcd.setCursor(cursorStart + i, 1);
lcd.print(keyPadInput[i]);
}
}
}
void handleKeyPadInput() {
customKey = customKeypad.getKey();
if (customKey) {
Serial.print("customKey: ");
Serial.println(customKey);
if (armedState == DISARMED ) {
if (customKey == '*') {
armedState = ARMED;
handleLCD(true);
//delay (30000);
}
} else {
if (customKey == '*') {
resetCodeInput();
} else if (customKey == '#') {
if (strcmp(keyPadInput, accessCode) == 0 ) {
Serial.println("Keypad input matches access code");
// Disarm the system
resetCodeInput();
armedState = DISARMED;
doInitilizeLCD = true;
initilizeLCD();
} else {
resetCodeInput();
}
} else {
if (inputCounter <= 3) {
keyPadInput[inputCounter] = customKey;
inputCounter++;
handleLCD(true);
} else {
// do nothing
}
}
}
}
}
void resetCodeInput() {
Serial.println("reseting keyPadInput");
for (int i = 0; i < 4; i++) {
keyPadInput[i] = 'z';
}
inputCounter = 0;
handleLCD(true);
}
void handlePIR() {
pirValue = digitalRead(pirPin);
doorValue = digitalRead(doorPin);
}
void alert() {
if ((pirValue > 0 && armedState == ARMED ) || (doorValue == LOW && armedState == ARMED )) {
shouldBeAlerting = true;
//startMillis = millis;
}
//else if (doorValue == LOW && armedState == ARMED ) {
//shouldBeAlerting = true;
//}
else {
shouldBeAlerting = false;
}
if (shouldBeAlerting) {
Serial.println("shouldBeAlerting");
}
handleLed();
handleBuzz();
handleAlarm();
}
void handleLed () {
// handle the alarm LED
if (shouldBeAlerting) {
Serial.println("setting LED HIGH");
digitalWrite(ledPin, HIGH);
} else {
// Serial.println("setting LED LOW");
digitalWrite(ledPin, LOW);
}
}
void handleBuzz() {
if (shouldBeAlerting) {
unsigned char i;
for (i = 0; i < 10; i++)
{
digitalWrite(buzzer, HIGH);
delay(1);//wait for 1ms
digitalWrite(buzzer, LOW);
delay(1);//wait for 1ms
}
//output another frequency
for (i = 0; i < 20; i++)
{
digitalWrite(buzzer, HIGH);
delay(2);//wait for 2ms
digitalWrite(buzzer, LOW);
delay(2);//wait for 2ms
}
}
}
void handleAlarm () {
// handle the siren
if (shouldBeAlerting) {
Serial.println("siren on");
startMillis = millis;
const unsigned long delayTime = 600000;
if (currentMillis - startMillis >= delayTime); // Alarm to sound for 5 minutes, or until disarmed
digitalWrite(alarmPin, HIGH);
}
else {
digitalWrite(alarmPin, LOW);
}
}
//}
[/code]