Is this possible with Interrupts in arduino MEGA?

Hello! I'm trying to put together a 3 sensor alarm controlled by google's Firebase. The logic is as follows:

  1. With a mobile app I select an option that changes the value of a firebase variable. 6 possible combinations: Activated, Activated silently, Deactivated, Turn on the siren, turn it off and Reset.

  2. This variable data is received by the ESP-8266-01, which connects to an Arduino MEGA and it saves this data in a "state" variable.

  3. With that variable "state", configure the interrupts "live" (activating or deactivating them).
    I have 3 sensors, which in case the state is activated or activated silently I need their interrupt to be activated (the only difference between them is that the siren sounds or not). And in case of deactivated I need that the interruption of the sensors is deactivated.

My problem occurs in item 3, I don't know if it's okay to use the function a**ttachInterrupt(digitalPinToInterrupt(ESB),DETECCION , HIGH); / detachInterrupt(digitalPinToInterrupt(ESB)); to disable / enable interrupts accordingly.

You can see my problem in the function: "Desactivar()" and "ActivarTotalmente()"

I apologize from the start, English is not my first language. Thank you very much for understanding


some names:
PC, SB, PG: Sensor
LPC, LSB, LPG: Sensor LEDs
RPC, RSB, RPG: Sensor relay

void loop() {
  Lectura();
}
 
 
// -----------------------------------------------------------------------------------
// Serial port reading stage, the data received is stored in the variable 'data'
void Lectura(){ 
  while(1){
   while (Serial.available())
   {
      char character = Serial.read();
      if (character != '\n')
      {
         data.concat(character);
      }
      else
      {
         Serial.println(data);
         data = "";
      }
   }
      if (data == "ACTIVATOTAL"){
        estado == 'A';            // It indicates that the status is A = Activated
        ActivarTotalmente();
        }
       if (data == "ACTIVASILENCIO"){
        estado == 'S';            // It indicates that the status is S = Silenty Activated
        ActivarSilenciada();
       }
       if (data == "DESACTIVADA"){
        estado == 'D';            // It indicates that the status is D = Deactivated
        Desactivar();
      }
       if (data == "DISUADIRON"){ // Turn on just the siren
        digitalWrite(RSIR,HIGH);
       }
       if (data == "DISUADIROFF"){ // Turn off just the siren
        digitalWrite(RSIR,LOW);
       }
       if (data == "RESET"){
        Reset();
       }
    }
} // up to this point I'm sure it works

// -----------------------------------------------------------------------------------
//  Activation States Activated, Silenced or Deactivated
void ActivarTotalmente(){
    attachInterrupt(digitalPinToInterrupt(ESB),DETECCION , HIGH);  // Enable interrupt de SB (one of the sensors gives '1' when it is triggered) 
    attachInterrupt(digitalPinToInterrupt(EPG),DETECCION , LOW);  // Enable interrupcion de PG (others work with '0' when triggered)
    attachInterrupt(digitalPinToInterrupt(EPC),DETECCION , LOW);  // Enable interrupcion de PC
    int a = 2;
    Pestaneo(a); // towards a blink function, I had no problems with this so I did not include it
    Lecture();
  }
// -----------------------------------------------------------------------------------
void ActivarSilenciada(){
    attachInterrupt(digitalPinToInterrupt(ESB),DETECCION , HIGH); // Enable interrupt SB (The 'E' is for 'Entrada' OR 'Input')
    attachInterrupt(digitalPinToInterrupt(EPG),DETECCION , LOW);  // Enable interrupt PG
    attachInterrupt(digitalPinToInterrupt(EPC),DETECCION , LOW);  // Enable interrupt PC
    int a = 1;
    Pestaneo(a);
    Lectura();
  }
// -----------------------------------------------------------------------------------
void Desactivar(){
    detachInterrupt(digitalPinToInterrupt(ESB));   // Remove the interrupt on pin SB
    detachInterrupt(digitalPinToInterrupt(EPG));   // Remove the interrupt on pin PG
    detachInterrupt(digitalPinToInterrupt(EPC));   // Remove the interrupt on pin PC
    int a = 3;
    Pestaneo(a);
    digitalWrite(RPC,LOW); // I turn off the relays after disabling the interruptions, in order to save energy
    digitalWrite(RPG,LOW);
    digitalWrite(RSB,LOW);
    delay(500);
    Lectura();
  } 
// -----------------------------------------------------------------------------------
void DETECCION(){ //In the detection stage, I check which sensors are triggered and based on that I return to firebase a change of variable (which for now is only a serialprint), plus activate or not the siren based on it
   if (EPC == LOW){
           digitalWrite(LPC, HIGH);
           Serial.println("PCDIS");     // Warns that PC has been triggered
           if (estado == 'A'){       // Activates siren if it is 'Activated', for 1 minute
            digitalWrite(RSIR,HIGH);  
            delay(1000); 
           }
       }
   if (EPG == LOW){
           digitalWrite(LPG, HIGH);
           Serial.println("PGDIS");     // same logic as in the previous case
           if (estado == 'A'){       // same logic as in the previous case
            digitalWrite(RSIR,HIGH);  
            delay(1000); 
           }
       }
    if (ESB == HIGH){
           digitalWrite(LSB, HIGH);
           Serial.println("SBDIS");     // same logic as in the previous case
           if (estado == 'A'){       // same logic as in the previous case
            digitalWrite(RSIR,HIGH);  
            delay(1000); 
           }
       }       
}
// -----------------------------------------------------------------------------------
void Reset(){
    digitalWrite(RSIR,LOW);   // Turn off Siren
    digitalWrite(LPC,LOW);    // Turn off LED
    digitalWrite(LPG,LOW);
    digitalWrite(LSB,LOW);
    int a=0;
    Pestaneo(a);
    Lectura();
}

Code running on an ATmega can turn on or off any interrupt, at any time, without using attach/detach.

All that is involved is setting or clearing a single bit. Check the interrupt section of the data sheet for the details.

Always post ALL the code. It is not possible to completely understand what you are doing from the fragment you posted.

attachInterrupt(digitalPinToInterrupt(ESB),DETECCION , HIGH); 
attachInterrupt(digitalPinToInterrupt(EPG),DETECCION , LOW); 
attachInterrupt(digitalPinToInterrupt(EPC),DETECCION , LOW);

HIGH is not a valid interrupt mode on the Mega. It actually is the same as CHANGE.

Your LOW mode usage is also suspect, as it will lead to multiple interrupts while the pin is LOW. FALLING will only trigger once as the pin goes LOW.

From the attachInterrupt() documentation

mode: defines when the interrupt should be triggered. Four constants are predefined as valid values:

LOW to trigger the interrupt whenever the pin is low,

CHANGE to trigger the interrupt whenever the pin changes value

RISING to trigger when the pin goes from low to high,

FALLING for when the pin goes from high to low.

The Due, Zero and MKR1000 boards allow also:

HIGH to trigger the interrupt whenever the pin is high.

And the eternal question: why interrupts at all?

As a beginner, it is incredibly unlikely that interrupts will be useful to you.

A common "newbie" misunderstanding is that an interrupt is a mechanism for altering the flow of a program - to execute an alternate function. Nothing could be further from the truth! :astonished:

An interrupt is a mechanism for performing an action which can be executed in "no time at all" with an urgency that it must be performed immediately or else data - information - will be lost or some harm will occur. It then returns to the main task without disturbing that task in any way though the main task may well check at the appropriate point for a "flag" set by the interrupt.

Now these criteria are in a microprocessor time scale - microseconds. This must not be confused with a human time scale of tens or hundreds of milliseconds or indeed, a couple of seconds. A switch operation is in this latter category and even a mechanical operation perhaps several milliseconds; the period of a 6000 RPM shaft rotation is ten milliseconds. Sending messages to a video terminal is clearly in no way urgent,

Unless it is a very complex procedure, you would expect the loop() to cycle many times per millisecond. If it does not, there is most likely an error in code planning; while the delay() function is provided for testing purposes, its action goes strictly against effective programming methods. The loop() will be successively testing a number of contingencies as to whether each requires action, only one of which may be whether a particular timing criteria has expired. Unless an action must be executed in the order of mere microseconds, it will be handled in the loop().

So what sort of actions do require such immediate attention? Well, generally those which result from the computer hardware itself, such as high speed transfer of data in UARTs(, USARTs) or disk controllers.

An alternate use of interrupts, for context switching in RTOSs, is rarely relevant to this category of microprocessors as it is more efficient to write cooperative code as described above.

As a beginner, it is incredibly unlikely that interrupts will be useful to you.

Yes, it is clear from your interrupt service routine which is called by the interrupt that you have no knowledge of how to use interrupts. You can not use delay() or Serial.print() inside an interrupt handler.

void DETECCION(){ //In the detection stage, I check which sensors are triggered and based on that I return to firebase a change of variable (which for now is only a serialprint), plus activate or not the siren based on it
   if (EPC == LOW){
           digitalWrite(LPC, HIGH);
           Serial.println("PCDIS");     // Warns that PC has been triggered
           if (estado == 'A'){       // Activates siren if it is 'Activated', for 1 minute
            digitalWrite(RSIR,HIGH); 
            delay(1000);
           }
       }
   if (EPG == LOW){
           digitalWrite(LPG, HIGH);
           Serial.println("PGDIS");     // same logic as in the previous case
           if (estado == 'A'){       // same logic as in the previous case
            digitalWrite(RSIR,HIGH); 
            delay(1000);
           }
       }
    if (ESB == HIGH){
           digitalWrite(LSB, HIGH);
           Serial.println("SBDIS");     // same logic as in the previous case
           if (estado == 'A'){       // same logic as in the previous case
            digitalWrite(RSIR,HIGH); 
            delay(1000);
           }
       }       
}

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