Issues with interrupts on Arduino Nano 33 IoT with IoT cloud

Hi everyone, I’m experiencing an issue using interrupts on pin 2 of an Arduino Nano 33 IoT. The button connected to pin 2 (configured as INPUT_PULLUP) is supposed to trigger an interrupt set on RISING. However, with the code provided below, the interrupt never triggers.

Important detail:
If I use a simpler test code that only checks the interrupt functionality without including additional libraries or features, and i uploud it by IDE the button works perfectly. It seems the problem is related to the complexity of the project.

The project includes:

  • An LED matrix (WS2812B) controlled using the FastLED library.
  • Synchronization with Arduino IoT Cloud to change visual effects.

Here’s the full code. Note that the project has additional pages containing only the function definitions.

#include <FastLED.h>
#include "thingProperties.h"

#define DATA_PIN 5
#define NUM_LEDS 152

CRGB leds[NUM_LEDS];
int Lum = 65;
int speed = 400;
int color = 0;
int color2 = 0;
int purple = 230;

volatile unsigned long lastDebounceTime = 0;  // Last button state change time
const unsigned long debounceDelay = 400;     // Debounce time
volatile bool aggiornareEffetto = false;     // Variable to signal button state change
volatile int statopulsante = 0;              // Must be volatile as it's used in the interrupt
const int pulsante = 2;

const int heartShape[NUM_LEDS][2] = {
    {2,0}, {3,0}, {4,0}, {5,0}, {11,0}, {12,0}, {13,0}, {14,0},
    /* Other elements defined here */
    {8,13},
};

void setup() {
    Serial.begin(9600);
    FastLED.setDither(BINARY_DITHER);
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    attachInterrupt(digitalPinToInterrupt(2), Pulsante, RISING); // Configure interrupt on pin 2
    pinMode(pulsante, INPUT_PULLUP); // Set button pin as INPUT_PULLUP
    initProperties(); // Defined in thingProperties.h
    ArduinoCloud.begin(ArduinoIoTPreferredConnection); // Connect to Arduino IoT Cloud
}

void Pulsante() {
    unsigned long currentTime = millis();
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        aggiornareEffetto = true;
        lastDebounceTime = currentTime;
    }
}

void onEffettiChange() {
    Serial.println("Effect changed!");
    switch (effetti) {
        case 0: pulseHeart(); break;
        case 1: expandAndContractHeart(); break;
        case 2: heartLayersEffect(); break;
        case 3: rainbowHeart(); break;
        case 4: sparkleHeart(); break;
        default: break;
    }
}

void loop() {
    ArduinoCloud.update(); 
    if (aggiornareEffetto) {
        unsigned long currentTime = millis();
        if ((currentTime - lastDebounceTime) > debounceDelay) {
            statopulsante = (statopulsante + 1) % 4;
            lastDebounceTime = currentTime;
            aggiornareEffetto = false;
            Serial.println("Button state updated: " + String(statopulsante));
        }
    }
    executeCorrespondingFunction();
}

void executeCorrespondingFunction() {
    updatetrim();
    switch (statopulsante) {
        case 0: break;
        case 1: break;
        case 2: break;
        case 3: break;
        default: break;
    }
}

Has anyone encountered similar issues with Arduino Nano 33 IoT? Could there be hardware limitations or library conflicts causing this? Thanks a lot for your help!

Hi everyone! I’m using FastLED to control a WS2812B LED matrix on an Arduino Nano 33 IoT. I also use a button connected to pin 2, configured with an interrupt on RISING, to change visual effects.

The problem is that the interrupt never triggers with the code I’m using. However, if I remove FastLED.show() and simplify the code, the interrupt works perfectly. It seems that FastLED is temporarily blocking interrupts during the LED update.

Here’s the complete code. The project includes additional pages containing only function definitions.

#include <FastLED.h>
#include "thingProperties.h"

#define DATA_PIN 5
#define NUM_LEDS 152

CRGB leds[NUM_LEDS];
int Lum = 65;
int speed = 400;
int color = 0;
int color2 = 0;
int purple = 230;

volatile unsigned long lastDebounceTime = 0;  // Last button state change time
const unsigned long debounceDelay = 400;     // Debounce time
volatile bool aggiornareEffetto = false;     // Variable to signal button state change
volatile int statopulsante = 0;              // Must be volatile as it's used in the interrupt
const int pulsante = 2;

const int heartShape[NUM_LEDS][2] = {
    {2,0}, {3,0}, {4,0}, {5,0}, {11,0}, {12,0}, {13,0}, {14,0},
    /* Other elements defined here */
    {8,13},
};

void setup() {
    Serial.begin(9600);
    FastLED.setDither(BINARY_DITHER);
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    attachInterrupt(digitalPinToInterrupt(2), Pulsante, RISING); // Configure interrupt on pin 2
    pinMode(pulsante, INPUT_PULLUP); // Set button pin as INPUT_PULLUP
    initProperties(); // Defined in thingProperties.h
    ArduinoCloud.begin(ArduinoIoTPreferredConnection); // Connect to Arduino IoT Cloud
}

void Pulsante() {
    unsigned long currentTime = millis();
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        aggiornareEffetto = true;
        lastDebounceTime = currentTime;
    }
}

void onEffettiChange() {
    Serial.println("Effect changed!");
    switch (effetti) {
        case 0: pulseHeart(); break;
        case 1: expandAndContractHeart(); break;
        case 2: heartLayersEffect(); break;
        case 3: rainbowHeart(); break;
        case 4: sparkleHeart(); break;
        default: break;
    }
}

void loop() {
    ArduinoCloud.update(); 
    if (aggiornareEffetto) {
        unsigned long currentTime = millis();
        if ((currentTime - lastDebounceTime) > debounceDelay) {
            statopulsante = (statopulsante + 1) % 4;
            lastDebounceTime = currentTime;
            aggiornareEffetto = false;
            Serial.println("Button state updated: " + String(statopulsante));
        }
    }
    executeCorrespondingFunction();
}

void executeCorrespondingFunction() {
    updatetrim();
    switch (statopulsante) {
        case 0: break;
        case 1: break;
        case 2: break;
        case 3: break;
        default: break;
    }
}

Is there any configuration or workaround to prevent FastLED from interfering with interrupts? Thanks a lot for your support!

FastLED.show() takes time to update the pixels; during that time interrupts are disabled.

You will have to write the functions that you call in onEffettiChange() to be non-blocking. I can not find where you call that function and I also don't seem to be able to find the functions like pulseHeart() etc.

1 Like

Hi everyone, I’m working on a project using Arduino Nano 33 IoT connected to Arduino IoT Cloud. I have a button connected to pin 2, configured with an interrupt on RISING, which is supposed to change visual effects on a WS2812B LED matrix (controlled using FastLED).

The issue is that the interrupt never triggers with the code I’m using. However, if I use a simpler test code that only focuses on the interrupt, without other libraries and using IDE to upload the sketch, the button works perfectly.

Here’s the complete code. Note that the project includes additional pages containing only function definitions.

#include <FastLED.h>
#include "thingProperties.h"

#define DATA_PIN 5
#define NUM_LEDS 152

CRGB leds[NUM_LEDS];
int Lum = 65;
int speed = 400;
int color = 0;
int color2 = 0;
int purple = 230;

volatile unsigned long lastDebounceTime = 0;  // Last button state change time
const unsigned long debounceDelay = 400;     // Debounce time
volatile bool aggiornareEffetto = false;     // Variable to signal button state change
volatile int statopulsante = 0;              // Must be volatile as it's used in the interrupt
const int pulsante = 2;

const int heartShape[NUM_LEDS][2] = {
    {2,0}, {3,0}, {4,0}, {5,0}, {11,0}, {12,0}, {13,0}, {14,0},
    /* Other elements defined here */
    {8,13},
};

void setup() {
    Serial.begin(9600);
    FastLED.setDither(BINARY_DITHER);
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    attachInterrupt(digitalPinToInterrupt(2), Pulsante, RISING); // Configure interrupt on pin 2
    pinMode(pulsante, INPUT_PULLUP); // Set button pin as INPUT_PULLUP
    initProperties(); // Defined in thingProperties.h
    ArduinoCloud.begin(ArduinoIoTPreferredConnection); // Connect to Arduino IoT Cloud
}

void Pulsante() {
    unsigned long currentTime = millis();
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        aggiornareEffetto = true;
        lastDebounceTime = currentTime;
    }
}

void onEffettiChange() {
    Serial.println("Effect changed!");
    switch (effetti) {
        case 0: pulseHeart(); break;
        case 1: expandAndContractHeart(); break;
        case 2: heartLayersEffect(); break;
        case 3: rainbowHeart(); break;
        case 4: sparkleHeart(); break;
        default: break;
    }
}

void loop() {
    ArduinoCloud.update(); 
    if (aggiornareEffetto) {
        unsigned long currentTime = millis();
        if ((currentTime - lastDebounceTime) > debounceDelay) {
            statopulsante = (statopulsante + 1) % 4;
            lastDebounceTime = currentTime;
            aggiornareEffetto = false;
            Serial.println("Button state updated: " + String(statopulsante));
        }
    }
    executeCorrespondingFunction();
}

void executeCorrespondingFunction() {
    updatetrim();
    switch (statopulsante) {
        case 0: break;
        case 1: break;
        case 2: break;
        case 3: break;
        default: break;
    }
}

Has anyone experienced conflicts between Arduino IoT Cloud and the use of interrupts? Could there be interference from the cloud library or connection? Thanks a lot for your help!

You had three topics on the same subject. It's called cross posting and wastes people's time. Your topics have been merged.

1 Like

Thanks