I want to build an simple alarm system for my basement, and i use Blynk for turning alarm on/of etc. (the code is not 100% finish regards to on/off button)
I need help to one thing i just not understand.
When PIR sensor detect movement and goes high for 1-2 seconds i want to turn on a siren for 2 minutes. I want the siren to keep on going until i turn off with button in Blynk app or resets the board with physical switch.
Here is my code:
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
int siren = 18;
int pirSensor = 4;
int orangeLED = 27;
int otherLED = 26;
int pirValue = 0;
int durationValue = 0;
//---SET THE AMOUNT OF LED BLINK ON STARTUP--------------
int LEDblink = 5;
int fastBlink = 10;
//-------------------------------------------------------
//---WIFI CRIDENTIALS FOR CONNECTING TO BLYNK SERVER-----
char auth[] = *****";
char ssid[] = "*****";
char pass[] = "*****";
//-------------------------------------------------------
//---DECLARATION OF BLYNK TIMER -------------------------
BlynkTimer timer;
//-------------------------------------------------------
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(siren, OUTPUT);
pinMode(pirSensor, INPUT);
pinMode(orangeLED, OUTPUT);
pinMode(otherLED, OUTPUT);
digitalWrite(siren, LOW);
Sequence();
timer.setInterval(100L, alarm);
}
void Sequence() {
for (int i=0; i<LEDblink; i++) {
digitalWrite(orangeLED, HIGH);
delay(1000);
digitalWrite(orangeLED, LOW);
delay(1000);
}
for (int b=0; b<fastBlink; b++) {
digitalWrite(orangeLED, HIGH);
delay(150);
digitalWrite(orangeLED, LOW);
delay(150);
}
digitalWrite(otherLED, HIGH);
digitalWrite(orangeLED, LOW);
alarm();
}
void alarm() {
pirValue = digitalRead(pirSensor);
Serial.println(pirValue);
if (pirValue == 1) {
digitalWrite(siren, HIGH);
Blynk.virtualWrite(V1, "ALARM AKTIVERT!");
}
else {
digitalWrite(siren, LOW);
Blynk.virtualWrite(V1, " ");
}
}
void loop() {
Blynk.run();
timer.run();
}
When PIR sensor detect movement and goes high for 1-2 seconds
are you sure it's configured to stay high only for 1 or 2 seconds ? won't it stay high as long as presence is detected ?
One way to do this type of code is what is called a "state machine".
You need to maintain in a variable the state of your system (alarmOff, alarmOn, alarmExpired for example) and detect the events that will let you change from one state to the other.
for example the start state is alarmOff
if your PIR is triggered, then you start the alarm, take note of the current time, and go to state alarmOn
in the state alarmOn, you monitor the Blynk event or if 2 minutes have elapsed.
if you get the Blynk event, then you turn off the alarm and go back to alarmOff state.
if 2 minutes have gone by since you started the alarm, you turn off the alarm and go to alarmExpired state
in the alarmExpired state, you await for the Blynk event again to go back to alarmOff state (and possibly check your PIR if you want to re-trigger).
PS: Note that in many countries alarms are regulated and can't go on forever if the siren can be heard from outside your property
to not let you without some structure for a state machine, here is what a simple code could be (without all your bells and whistles)
enum : byte {alarmOFF, alarmON, alarmExpired} currentState = alarmOFF;
const byte pirPin = 4;
const byte sirenPin = 18;
unsigned long sirenStartTime;
const unsigned long maxSirenDuration = 120000ul; // 2 minutes in ms
bool deactivationReceived = false;
void checkCommunication()
{
/* some code that would set deactivationReceived to true if you get the message */
if (random(0, 100) > 90) deactivationReceived = true; // just random stuff here
}
void checkAlarm()
{
switch (currentState) {
case alarmOFF: // alarm is OFF, we check if it needs to be turned on
if (digitalRead(pirPin) == HIGH) {
digitalWrite(sirenPin, HIGH); // start siren
sirenStartTime = millis();
deactivationReceived = false;
currentState = alarmON;
}
break;
case alarmON: // alarm is ON, we check if it's being deactivated or max time elapsed
if (deactivationReceived) {
// we received the notification to turn the siren off
digitalWrite(sirenPin, LOW); // turn off siren
currentState = alarmOFF;
} else if (millis() - sirenStartTime >= maxSirenDuration) {
digitalWrite(sirenPin, LOW); // turn off siren
currentState = alarmExpired;
}
break;
case alarmExpired: // alarm sounded and was not deactivated in due time
if (deactivationReceived) {
// we received the notification to turn the siren off
currentState = alarmOFF;
}
break;
}
}
void setup() {
pinMode(sirenPin, OUTPUT);
pinMode(pirPin, INPUT);
}
void loop() {
checkAlarm();
checkCommunication();
// here you can do other stuff if needed if it's not too long (and non blocking of course)
}
The millisDelay class in How to write Timers and Delays in Arduino will reduce the number of states you have to handle because it keeps track of if the timer is running or not.
the millisDelay timer is also easy to stop when you get the override, just use the stop() method