Interrupt not working on calling other function [Solved]

Hi, I attachInterrupt() to setup() to plant an event to be triggered, let’s say:

int blinky(String cmd) {
  while(1) {
    digitalWrite(ledPin, HIGH);
    delay(2000);
    digitalWrite(ledPin, LOW);
    delay(2000);
  }
  return 10;
}

void buttonPushed() {
  analogWrite(motorPin, 200);
}

void setup() {
  Spark.function("blinky", blinky);
  attachInterrupt(buttonInputPin, buttonPushed, FALLING);
}

Then I send a POST request to the blinky function like so:

curl https://api.spark.io/v1/devices/myCoreId/blinky -d access_token=myCoreToken

Of course the blinky function works, but then I was expecting the interrupt to works when I push the button to make buttonInputPin LOW and should trigger buttonPushed() and get motor running. I assume setup() is run everytime and although I request only the blinky() function, interrupt should still work.

setup(), like in arduino, only gets the first time the core powers up or resets.

The interrupt should work since you have defined it in setup() and you only need to do it once.

Can you try pushing the button to see if the function is called?

maybe change to:

void buttonPushed() {
  digitalWrite(ledPin, !digitalRead(ledPin));
}

@kennethlimcp can we do !digitalRead(ledPin) when we set it to OUTPUT?

Also, it didn’t work. Since setup() gets run the first time core powers up or reset, is flashing count as reset? My buttonInputPin is also tapped to D3 which is available as interruptPin. I’m certain it’s all connected right, since running simple push button check reads buttonInputPin == LOW

What else can I miss?

Oh yes you can do that. :smiley: Just going to toggle the led on and off.

I'll test your code when i have some time later. :wink:

1 Like

Thanks a awful lot!

Tried changing a variable inside the interrupt function and calling Spark.variable to check the value. Yep, the code doesn't reach there. Variable hasn't changed. :frowning:

@metaculus,

I tested the code and it works.

Few things to note:

1.) You have a while(1) in the blinky() function and the core will repeatedly blink the leds and no longer execute the code in loop()

I’m not sure if that’s the behavior you are looking at

2.) If you can, do share the full code as there might be some initialisation issues for the analog pin you are using causing the motor not to move.

I tested be inverting the D7 led upon interrupt and it worked perfectly.

Here’s the test code i used:

#define buttonInputPin D0
#define ledPin D7

void setup(){
  pinMode(D7,OUTPUT);
  pinMode(D0,INPUT_PULLUP);
  Spark.function("blinky", blinky);
  attachInterrupt(buttonInputPin, buttonPushed, FALLING);
}

void buttonPushed(){
  digitalWrite(D7,!digitalRead(D7));
}

void loop(){
}

int blinky(String cmd) {
  //while(1) {
    digitalWrite(ledPin, HIGH);
    delay(2000);
    digitalWrite(ledPin, LOW);
    delay(2000);
  //}
  return 10;
}

1 Like

Also - dont’t call delay() in an interrupt.

Golden rules for interrupt routines:

  • do as little as possible
  • do it as quickly as possible
  • don’t declare any large data objects as automatic variables
  • if you are setting/reading variables, make sure they are volatile

This is a gross simplification (but hey, we’re talking arduino-like sketches here, not hypervisors), but - you would do well to set a (volatile) flag in the interrupt routine, and handle the processing in loop() based on said flag.

4 Likes

@kennethlimcp the reason I put while(1) there was because I wanted a loop that runs forever to test if the core will break that routine upon being interrupted. Seems like that isn’t the case.

Here is the code, please do advice:

int led = D0;  // You'll need to wire an LED to this one to see it blink.
int button = D3; // for ISR
int motor = A1;
int dutyCycle = 200; 
int led3 = A0;

int blinkLed(String cmd) {
  if (cmd == "on") {
    // keep blinking the LED
    while(true) {
        digitalWrite(led, HIGH);
        delay(1000);
        digitalWrite(led, LOW);
        delay(1000);
    }
  } else return -1;
  
  return 1;
}

void setup() {
  Spark.function("blinky", blinkLed);
  pinMode(D0, OUTPUT); // for led
  pinMode(A1, OUTPUT); // for motor
  pinMode(D3, INPUT_PULLUP); // for push button which will trigger ISR
    
  attachInterrupt(button, buttonPushed, FALLING);
}

void loop() {}

void buttonPushed(){
  digitalWrite(D7,!digitalRead(D7));
}

I need a better understanding of what loop() does, when it’s being executed (before/after my called functions?) and why in Spark code I often see the function left blank. (As in arduino the loop checks for any serial communication as well, other than that it’s like normal while() loop.

My project needs to “pool” for a few sensor inputs all the time to send that data over HTTP, while at any time the other side can send request to execute some Spark.functions as well.

I tested and the interrupt worked the core was in the while (1) loop. You can test out the code above.

2 Likes

@kennethlimcp it worked. Thank you. @AndyW yes, thank you for the guide. I’ll just change variables inside interrupt functions and process that inside loop()

@AndyW with volatile variables, can they be changed outside of the interrupt functions? I’m having a problem that:


volatile bool poked = false;
volatile bool padded = false;

void isPoked() {
  poked = true;
}
void isPadded() {
  padded = true;
}

void setup() {
  attachInterrupt(D3, isPoked, FALLING);
  attachInterrupt(D4, isPadded, FALLING);
}
void loop() {
  if (poked) {
    // do things here and set poked back to false
    poked = false;
  }
  if (padded) {
    // do things here and set padded back to false
    padded = false;
  }
}

First time it worked, but then after that nothing seemed to execute.

I can’t see any pinMode() setup for your input pins.

You should have this in your setup(), I guess

  pinMode(D3, INPUT_PULLUP);
  pinMode(D4, INPUT_PULLUP);

@ScruffR Yes, I did. Sorry forgot to include. Still it wasn’t working. Is it possible that my // do things is blocking and therefore the variables never set back to false?

I have no idea why then it would not work on your Core.

When I do this

volatile bool poked = false;
volatile bool padded = false;

void isPoked() {
  poked = true;
}
void isPadded() {
  padded = true;
}

void setup() {
  pinMode(D3, INPUT_PULLUP);
  pinMode(D4, INPUT_PULLUP);
  pinMode(D7, OUTPUT);
  attachInterrupt(D3, isPoked, FALLING);
  attachInterrupt(D4, isPadded, FALLING);
}

void loop() {
  if (poked) {
    digitalWrite(D7, HIGH);
    // do things here and set poked back to false
    poked = false;
  }
  if (padded) {
    digitalWrite(D7, LOW);
    // do things here and set padded back to false
    padded = false;
  }
}

it does exactly what I’d expect.

2 Likes

Are you driving the pin high and low, or just shorting it to ground ?

If you’re just shorting it to ground, do you have either external pull-ups ?

The problem might be that the capacitance of the pin is holding it low after the first usage (at least as far as the innards of the chip are concerned)

If you don’t have external pull-ups, try enabling the internal ones, by adding these to setup():

pinMode(D3, INPUT_PULLUP);
pinMode(D4, INPUT_PULLUP);

1 Like

OMG thanks @AndyW one of the pullup resistors was loose without knowing. It’s working just great!

2 Likes

Excellent. I love it when a plan comes together.

The code looked right - at least as a proof of concept.
Nice job groking the concept and prototyping so fast.

Do watch out for contact bounce if you have mechanical switches, and write your code to accomodate that in a fail-safe manner (expect multiple mS of bounce.) Note that the iteration-to-iteration latency between calls to loop() will change if you disconnect from the cloud, so you may not see contact bounce when connected to the cloud, but may see it if you run disconnected.

1 Like

I can see your point that being connected to the cloud will provide enough latency to skip any bounce, but as far as I'm educated (and that's not far :blush:) , when connected to the cloud, once flashed, isn't the core just working locally on the code stored inside anyway? Unless it has to communicate with the cloud again, either due to some request?

p.s. Hope I'm not asking too many questions here. I've been around for just a few days and this forum has been very helpful. Kinda addicted.

While connected with the cloud, the core checks to see if there are any messages pending from the cloud between calls to loop(). This takes a minimum of 5mS, because of limitations of the CC3000 interface. So you’ll see something like 200 iterations of loop() per second.

Skipping that 5mS delay if not cloud-connected is why you’ll see a much higher rate of calls to loop() when not connected.