Polling loop versus Interrupts for a newbie

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


image

Consider how you would handle the potential contact bounce.

A relay is a very slow device… I personally would use the polling, but remember DO NOT USE DELAY() in your program, or you’ll lose events.

It’s a good test for you as a programmer!

Please keep in mind that you can’t usually drive horns or relays directly from an Arduino.

Why are capacitors labelled as Rx. (resistors) ?
I’m not sure why you’re putting 12V into D2 (bottom right)

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.

Thanks for the comments. I'll look into the Bounce2 Lib. I'll get rid of the digitalWrite(Input_Alarm_Signal , LOW);.

Thanks for the comments. I'm not sure how I will get around using delay to time the relay on timing.

Thanks for the comments. cattledog suggested using the Bounce2 lib. I will look at that.

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


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.