This is my first attempt at a sketch on an Anduino. My question is, in the attached code I am using a polling loop to catch an off-board controlled relay closure. I want to have a timed closure of an output based on the number of pulses received. Should I change this to use a leading edge Int to catch the start of the off-board relay to turn on the specific output and then a falling edge Int to turn off the output? This will eliminate the need to time the output HIGH time and use the timed rate of the off-board relay as the timing source which is about 1 sec on and 1 second off when signaling. Code compiles without errors. I hope I am posting the code correctly (newbie). Thank you in advance!
// Arduino Nano Every
//This program sounds two different alarms based on a relay triggered by the car. Realy has an approx 1 sec On/1 sec off rate.
// Pulse 1-3 itsounds the Unlock (1) and Lock (3) , alert tone, if the Pulse_count > 3 the theft alarm has been
// triggered and the louder alert tone is sounded. After 1000 pulses the count starts over. If the theft
// alarm is still triggered 3 lower tones will sound and then return to the louder alert tone.
// Initialize Variables
const int Input_Alarm_Signal = 2; // Relay input from car that flashes headlights when Unlock/lock and alarm
const int Output_Relay_1 = 4; // Soft tone alert
const int Output_Relay_2 = 5; // Loud alert tone
int Loop_count = 0; // Number of times we have looped in the wait for signal loop
int Pulse_count = 0; // keep track of number of pulses from car alarm
int Exit_loop = false; // while loop exit condition
void setup() {
pinMode(Input_Alarm_Signal, INPUT);
pinMode(Output_Relay_1 , OUTPUT);
pinMode(Output_Relay_2 , OUTPUT);
digitalWrite(Output_Relay_1 , LOW);
digitalWrite(Output_Relay_2 , LOW);
} // End Setup
void loop() {
if (digitalRead(Input_Alarm_Signal) == HIGH) { // watch for alarm relay to close
Pulse_count++; // Inc pulse count
Loop_count++; // Inc loop count
digitalWrite(Input_Alarm_Signal , LOW);
switch (Pulse_count) {
case 1 : //1 pulse indicates unlock or 1st pulse of unlock signal
case 2 : //2nd pulse of unlock signal, or theft alarm
case 3 : //3rd pulse of unlock signal, or theft alarm
// Turn on relay 1 (soft tone) for 1/2 second,
digitalWrite(Output_Relay_1, HIGH);
delay (500);
digitalWrite(Output_Relay_1, LOW);
break;
case 1000 :
// start over if we reach 1000 pulses, alarm has been on for ~8 minutes
Loop_count = 0; //
Pulse_count = 0;
break;
default : // Theft alarm has been triggered
// Turn on relay 2 (loud tone) for 1/2 second
digitalWrite(Output_Relay_2, HIGH);
delay (500);
digitalWrite(Output_Relay_2, LOW);
break;
} // End Switch (Pulse_Count) // Received alarm pulse, service the signal
} // End if
else {
// Housekeeping routine
Loop_count++ ;
} // End else
} // Void loop end
if (digitalRead(Input_Alarm_Signal) == HIGH) { // watch for alarm relay to close
Pulse_count++; // Inc pulse count
Loop_count++; // Inc loop count
digitalWrite(Input_Alarm_Signal , LOW);
There are a couple of things wrong here.
To count pulses, you need to detect changes in state from LOW to HIGH or HIGH to LOW. Take a look at the State Change Detection example in the 02>Digital examples. As suggested in the example it will be easier to use the Bounce2 library. You can count debounced edges easily using the library.
digitalWrite(Input_Alarm_Signal , LOW);
Writing an input pin low is simple turning off the internal pullup resistor. The line is doing nothing.
My rule is don't use interrupts unless you have to for performance or other reasons. They are much easier to mess up than polling. Many people think they "have to" when a little more design effort would be better.
That said, I do sometimes use interrupts. Follow what other posts have said. Keep the routine short. Don't call other routines - particularly ones that use interrupts (like Serial and delay()). Remember to use volatile. etc...
Thanks for the comments. I am an old relay logic guy so, R's are Relays and the "cap" is the contact on said relay. R3 (cap) is the contact on relay 3 that closes when the alarm relay on the car closes. There is 5 VDC from board going to d2. Label +12 VDC is a ghost label, should have been deleted. Horns are driven by Relay 1 and 2 contacts.
You will use millis() to time events without using delay(). If you don't wish to learn the coding techniques there are several libraries you can use to run the relay timing without using delay().
Revised code to eliminate delay() and use tone() for soft alarm, debounce relay contact.
// Arduino Nano Every
//This program sounds two different alarms based on a relay triggered by the car. Realy has an approx 1 sec On/1 sec off rate.
// Pulse 1-3 itsounds the Unlock (1) and Lock (3) , alert tone, if the Pulse_count > 3 the theft alarm has been
// triggered and the louder alert tone is sounded. After 1000 pulses the count starts over. If the theft
// alarm is still triggered 3 lower tones will sound and then return to the louder alert tone.
// Initialize Variables
const int Input_Alarm_Signal = 2; // Relay input from car that flashes headlights when Unlock/lock and alarm
const int Tone_Out = 4; // Soft tone alert
const int Output_Relay_2 = 5; // Loud alert tone
const int Preset_Delay = 1000; // Time const for delay
unsigned long previousMillis = 0; // Alarm relay timer
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
int Loop_count = 0; // Number of times we have looped in the wait for signal loop
int Pulse_count = 1; // keep track of number of pulses from car alarm
int Alarm_Relay_State = LOW;
int Last_Alarm_Relay_State = LOW;
int frequency = 247; // B 247 Hz
void setup() {
pinMode(Input_Alarm_Signal, INPUT);
pinMode(Output_Relay_2 , OUTPUT);
} // End Setup
void loop() {
Alarm_Relay_State = digitalRead(Input_Alarm_Signal);
// check to see if you just pressed the button
// (i.e. the input went from HIGH to LOW), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (Alarm_Relay_State != Last_Alarm_Relay_State) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (Alarm_Relay_State != Last_Alarm_Relay_State) {
Last_Alarm_Relay_State = Alarm_Relay_State;
}
}
if (Alarm_Relay_State == LOW) { // watch for alarm relay to close (go low as it is pulled down)
Loop_count++; // Inc loop count
switch (Pulse_count) {
case 1 : //1 pulse indicates unlock or 1st pulse of unlock signal
case 2 : //2nd pulse of unlock signal, or theft alarm
case 3 : //3rd pulse of unlock signal, or theft alarm
// Turn on relay 1 (soft tone)
tone(Tone_Out, frequency);
if (millis() - previousMillis >= Preset_Delay) {
noTone (Tone_Out);
previousMillis = millis();
Pulse_count++;
}
break;
case 1000 :
// start over if we reach 10000 loops through void loop,
Loop_count = 0; //
Pulse_count = 1;
break;
default : // Theft alarm has been triggered
// Turn on relay 2 (loud tone) make sure soft alarm is stopped
noTone(Tone_Out);
digitalWrite(Output_Relay_2, HIGH);
if (millis() - previousMillis >= Preset_Delay) {
digitalWrite(Output_Relay_2, LOW);
previousMillis = millis();
Pulse_count++;
break;
}
} // End Switch (Pulse_Count) // Received alarm pulse, service the signal
} // End if
} // Void loop end