Interrupts not working on ESP8266 (NodeMCU 1.0)

Hi!
I want to build a lamp for a friend using WS2812B adressable LEDs and an ESP8266.
Therefore there is a user-input of three buttons. One for brightness, one for color and one for mode - control. Using the WS2812B LEDs on the ESP8266 isnt the problem, it already works fine.
What is causing me headaches is the use of interrupts to read the user inputs. It should work like this:
button press -> ISR -> brightness ++/mode++/color++

I therefore wrote a small code to test the interrupts but I didnt get it work yet. Maybe someone could have a look over it and let me know what my mistake is.
The buttons are connecting the pins to GND when being pressed and are pulled to 3.3V through the uC. Futhermore those are debounced on the hardware-side (RC-network to increase the time constant).

Here is my test code:




uint8_t brightness = 0, mode = 0, color = 0;

void setup() {

  Serial.begin(9600);

  pinMode(14, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(14), func_brightness, LOW);
  attachInterrupt(digitalPinToInterrupt(12), func_mode, LOW);
  attachInterrupt(digitalPinToInterrupt(13), func_color, LOW);
}

void loop() {
  Serial.println("loop");
  delay(500);
}

void func_brightness() {
  brightness ++;
  Serial.println("brightness: " + brightness);
}

void func_mode() {
  mode ++;
  Serial.println("mode: " + mode);
}

void func_color() {
  color ++;
  Serial.println("color: " + color);
}

According to it I would expect an increase in brightness, mode and color when I press the buttons as well as a new line in the SerialMonitor. However none of this happens.

Greetings from Germany,
Vince

Hi,
are you connecting 5V to the pins of the ESP8266?
The ESP8266 GPIOS are 3.3V and with 5V you can damage it.

Hi, no I am not connecting them to 5V, that was a typo. They are connected to 3.3V through the internal resistors of the ESP8266.
I also just edited the thread accordingly.

Hi,
the ESP8266 interrupt called routine must be start with " ICACHE_RAM_ATTR"

To create an interrupt, call attachInterrupt() and pass as arguments the GPIO interrupt pin, the ISR (funcion to be called) and mode. The ISR function must have the ICACHE_RAM_ATTR attribute declared.

Ex: ICACHE_RAM_ATTR void func_brightness()

Modify your 3 routine and try.

I just did that and it didnt help...
I also am pretty sure that "ICACHE_RAM_ATTR" just stores the ISR in RAM instead of Flash to make it run faster.


uint8_t brightness = 0, mode = 0, color = 0;

void setup() {

  Serial.begin(9600);

  pinMode(14, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(14), func_brightness, LOW);
  attachInterrupt(digitalPinToInterrupt(12), func_mode, LOW);
  attachInterrupt(digitalPinToInterrupt(13), func_color, LOW);
}

void loop() {
  Serial.println("loop");
  delay(500);
}

ICACHE_RAM_ATTR void func_brightness() {
  brightness ++;
  Serial.println("brightness: " + brightness);
}

ICACHE_RAM_ATTR void func_mode() {
  mode ++;
  Serial.println("mode: " + mode);
}

ICACHE_RAM_ATTR void func_color() {
  color ++;
  Serial.println("color: " + color);
}

hi
let's go
I built your project here using ESP8266 12E.
My ESP8266 won't work if I don't put
"ICACHE_RAM_ATTR " before the routines called by the interrupt.
They keep giving panic error.

But in addition it apparently has 2 problems.
The first one I haven't confirmed yet, but I modified the code and it worked.
It seems that ESP doesn't have the LOW and HIGH options for the no interrupt parameter.
But as I said, I haven't confirmed this information yet.
I tested it with the "FALLING" parameter.

The second is that you mix String with int when printing, and it doesn't work.

Need to momentarily change the value for String to print.

Here is the code I tested here and it works.

PS: See this ESP8266 reference:

" * Interrupt callback functions must be in IRAM, because the flash may be in the middle of other operations when they occur. Do this by adding the IRAM_ATTR attribute on the function definition. If this attribute is not present, the sketch will crash when it attempts to attachInterrupt with an error message. "

https://arduino-esp8266.readthedocs.io/en/latest/reference.html#interrupts

hi
let's go
I built your project here using ESP8266 12E.
My ESP8266 won't work if I don't put
"ICACHE_RAM_ATTR " before the routines called by the interrupt.
They keep giving panic error.

But in addition it apparently has 2 problems.
The first one I haven't confirmed yet, but I modified the code and it worked.
It seems that ESP doesn't have the LOW and HIGH options for the no interrupt parameter.
But as I said, I haven't confirmed this information yet.
I tested it with the "FALLING" parameter.

The second is that you mix String with int when printing, and it doesn't work.

Need to momentarily change the value for String to print.

Here I also found the information:
Pin interrupts are supported through attachInterrupt, detachInterrupt functions. Interrupts may be attached to any GPIO pin, except GPIO16. Standard Arduino interrupt types are supported: CHANGE, RISING, FALLING. ISRs need to have IRAM_ATTR before the function definition.
On topic " Digital IO".
https://arduino-esp8266.readthedocs.io/en/latest/reference.html#interrupts

uint8_t brightness = 0, mode = 0, color = 0;

void setup() {

  Serial.begin(9600);

  pinMode(14, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(14), func_brightness, FALLING);
  attachInterrupt(digitalPinToInterrupt(12), func_mode, FALLING);
  attachInterrupt(digitalPinToInterrupt(13), func_color, FALLING);
}

void loop() {
  Serial.println("loop");
  delay(500);
}

ICACHE_RAM_ATTR void func_brightness() {
  brightness ++;
  Serial.println("brightness: " + String(brightness));
}

ICACHE_RAM_ATTR void func_mode() {
  mode ++;
  Serial.println("mode: " + String(mode));
}

ICACHE_RAM_ATTR void func_color() {
  color ++;
  Serial.println("color: " + String(color));
}

Thanks a lot, that did the trick!

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