Trouble with interrupts on Argon

Hi, I’m new to the Argon. It’s my second MC I’ve worked with and the first one outside of a class.

I’m having trouble getting interrupts to work on my argon. I keep getting the red “sos” error led (firmware crash) and I can’t figure it out. I’ve checked the forums, YouTube, and read through the Reference Guide.

I have the inputPin plugged`` into a point in a circuit that goes from 0 to 2.7 volts when I push a button.

Here’s my code

/*
 * Project IOT_RemoteSensor_00
 * Description:
 * Author: BobTheBob47!
 * Date: 04/2021
 */
#include "Particle.h"

int boardLED = D7;
int switchRead = D5;
int switchOn;
int interuptPin = D6;

void setup() {
  pinMode(boardLED, OUTPUT);
  pinMode(switchRead, INPUT);
  pinMode(interuptPin, INPUT);
  attachInterrupt(interuptPin,ledInterupt,RISING);


}

void loop() {  
  //light_boardLED_withSwitch();
  //blink_boardLED();

}

int blink_boardLED() {
    digitalWrite(boardLED, HIGH);
    delay(1000);
    digitalWrite(boardLED,LOW);
    delay(1000);
    
    return 0;

}

int light_boardLED_withSwitch() {
    switchOn = digitalRead(switchRead);
    delay(200);
    if (switchOn == digitalRead(switchRead)){
        if (switchOn == 1) {
            digitalWrite(boardLED,HIGH);
            //Particle.publish("Light_On", PRIVATE);
        }
        else {
            digitalWrite(boardLED,LOW);
        }
        
    }
    
    switchOn = 0;
    return 0;

}

void ledInterupt(void) {
  Particle.publish("Light_On", PRIVATE);

  digitalWrite(boardLED,HIGH);
  delay(500);
  digitalWrite(boardLED,LOW);
  delay(500);

}

And here are some of the sources I’ve been using.
https://docs.particle.io/reference/device-os/firmware/#interrupts

https://docs.particle.io/tutorials/device-os/led/argon/

Any help is appreciated.

I GOT IT TO WORK!!!

I think the code in the interrupt was too long. I had originally had a publish to the cloud and that had the same effect. I SWITCHED IT TO CHANGING A VARIABLE AND IT WORKED!!!

Sorry for all caps but it’s midnight here and I literally jumped out of bed to try my code.

Eddit: My Code

/*
 * Project IOT_RemoteSensor_00
 * Description:
 * Author: BobTheBob47!
 * Date: 04/2021
 */
#include "Particle.h"

int boardLED = D7;
int switchRead = D5;
int switchOn;
int interuptPin = D6;
int interuptTriggered = 0;

void setup() {
  pinMode(boardLED, OUTPUT);
  pinMode(switchRead, INPUT);
  pinMode(interuptPin, INPUT);
  attachInterrupt(interuptPin,ledInterupt,RISING);


}

void loop() {  
  //light_boardLED_withSwitch();
  //blink_boardLED();

  if (interuptTriggered == 1){
    blink_boardLED();
  }

  interuptTriggered = 0;

}

int blink_boardLED() {
    digitalWrite(boardLED, HIGH);
    delay(1000);
    digitalWrite(boardLED,LOW);
    delay(1000);
    
    return 0;

}

int light_boardLED_withSwitch() {
    switchOn = digitalRead(switchRead);
    delay(200);
    if (switchOn == digitalRead(switchRead)){
        if (switchOn == 1) {
            digitalWrite(boardLED,HIGH);
            //Particle.publish("Light_On", PRIVATE);
        }
        else {
            digitalWrite(boardLED,LOW);
        }
        
    }
    
    switchOn = 0;
    return 0;

}

void ledInterupt(void) {
  //Particle.publish("Light_On", PRIVATE);
interuptTriggered = 1;

}

That’s definitely the issue.
delay() is an absolute no-go in an ISR.

Also a very heavy function call like Particle.publish() should be avoided at any cost.

BTW, you should only reset the flag when it actually was dealt with.
The way you do it there would miss a second trigger if it happened to occur during blink_boardLED().

I’d rather put it this way

  if (interruptTriggered) {
    interruptTriggered = false;
    blink_boardLED();
  }

Another alternative to your flag approach with a blocking blink function would be to use a Software Timer to do the blinking.

void ledOff() {
  digitalWrite(boardLED, LOW);
}
Timer tLedOff(1000, ledOff, true); // one-shot timer 

void ledInterrupt() {
  digitalWrite(boardLED, HIGH);    // switch on the LED
  tLedOff.startFromISR();          // queue the switch off in one second
}

I left out the 1 second delay after switching off the LED as it also doesn’t actively do anything other than slowing down your over all code flow.
With this approach, if the interrupt fires again while the LED is on the timer will be reset to start counting again and the LED will stay on for till that “new” second expires.

Another thing to note is that you need to make sure your switches and buttons won’t let the attached GPIO pins float when not pressed. The simplest way to do that would be via INPUT_PULLUP or INPUT_PULLDOWN instead of merely using INPUT.

1 Like

After my little epiphany last night I worked until about 3am. I did change it to reset the flag after the interrupt is dealt with as you said.

I’ve added Software Timers to my list of things to learn. I’ve modified the blink function to make it multi-use but I’ve got to learn I2C for a sensor so I’m focusing my efforts there.

I’m including my current code. I’ve commented out parts to reduce ram usage and I’m about to save a copy then remove those parts entirely.

Thank you ScruffR.

/*
 * Project IOT_RemoteSensor_00
 * Description:
 * Author: garthenar
 * Date: 04/2021
 */
#include "Particle.h"

int boardLED = D7;
//int switchRead = D5;
//int switchOn;
int interuptPin = D6;
int ledInteruptTriggered = 0;
int floodSensor = D4;
int itsFlooding = 0;
int floodCountInterval = 100;

void setup() {
  pinMode(boardLED, OUTPUT);
  //pinMode(switchRead, INPUT);
  pinMode(interuptPin, INPUT);
  attachInterrupt(interuptPin,ledInterupt,RISING);
  pinMode(floodSensor, INPUT);
  attachInterrupt(floodSensor,floodInterrupt, FALLING);


}

void loop() {  
  //light_boardLED_withSwitch();
  //blink_boardLED();

  if (ledInteruptTriggered == 1){
    if(Particle.publish("Button_Pushed") == true){
      ledInteruptTriggered = 0;
      blink_boardLED(2,0.25);
    }
    else{
      Particle.publish("Shit went Wrong");
    }
  }

  if (itsFlooding == 1) {
    again:
    if(Particle.publish("It's_Flooding") == true){
      itsFlooding = 0;
      floodCountInterval = 100;
    }
    else{
      goto again;
    }
  }

  floodCountInterval -= 1; //Work on this. (making sure it's not pinging every second it's flooding)
}

int blink_boardLED(int times, float seconds) {
    
    for(int i = 0; i <times; i++) {
      digitalWrite(boardLED, HIGH);
    delay(seconds*1000.0);
    digitalWrite(boardLED,LOW);
    delay(seconds*1000.0);
    }
    
    
    return 0;

}

// int light_boardLED_withSwitch() {  //Old function DO NOT USE (uses pin d5)
//     switchOn = digitalRead(switchRead);
//     delay(200);
//     if (switchOn == digitalRead(switchRead)){
//         if (switchOn == 1) {
//             digitalWrite(boardLED,HIGH);
//             //Particle.publish("Light_On", PRIVATE);
//         }
//         else {
//             digitalWrite(boardLED,LOW);
//         }
        
//     }
    
//     switchOn = 0;
//     return 0;

// }

void ledInterupt(void) {
ledInteruptTriggered = 1;
}

void floodInterrupt(void) {
  itsFlooding = 1;  
}

Also forgot to address the pull up/down resistors part. I thought those might be a problem while I was trouble shooting but I have the digital I/O connected to branches that are high or low (connected to Vs or gnd) but change when the button is pressed (circuit 1: button, led, transistor switch) or the circuit is completed (water sensor made with a transistor).