Arduino nano freezes when using interrupt

Hi guys,

I am playing with interrups on my arduino nano, but everytime I use it, the board just freezes and stops executing anything. It doesn’t even go into the loop():

My code is this:

#include <LiquidCrystal_I2C.h>

//I2C pins declaration
LiquidCrystal_I2C lcd(0x27, 16, 2);

volatile int output = LOW;
int i = 0;

void setup()
{
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Interrupt Xample");
    lcd.setCursor(0, 1);
    lcd.print("ArduinoInterrupt");
    delay(3000);
    lcd.clear();
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
    pinMode(6, OUTPUT);

    attachInterrupt(digitalPinToInterrupt(2), buttonPressed1, FALLING); //  function for creating external interrupts at pin2 on Rising (LOW to HIGH)
    attachInterrupt(digitalPinToInterrupt(3), buttonPressed2, FALLING); //  function for creating external interrupts at pin3 on Rising (LOW to HIGH)
}

void loop()
{
    lcd.clear();
    lcd.print("COUNTER:");
    lcd.print(i);
    ++i;
    delay(1000);
    digitalWrite(6, output); //Turns LED ON or OFF depending upon output value
}

void buttonPressed1() //ISR function excutes when push button at pinD2 is pressed
{
    output = LOW; //Change Output value to LOW
    lcd.setCursor(0, 1);
    lcd.print("Interrupt 1");
}

void buttonPressed2() //ISR function excutes when push button at pinD3 is pressed
{
    output = HIGH; //Change Output value to HIGH
    lcd.setCursor(0, 1);
    lcd.print("Interrupt2");
}

So using this code, my display gets cleared, but then it never gets to a point where “COUNTER:” would be displayed.

First I thought it doesn’t work because of some ripoff arduino device, but then I actually went and bought a new one, but the result is still the same.

Can anybody help me and give me any suggestion with this? I can’t figure it out why this is happening.

Thanks

Never try to call a function or use the same device from both loop AND an interrupt.

You will end up in a complete mess because loop may be half way through doing something (writing string "COUNTER:" to the LCD for example) when the interrupt happens and tries to write "Interrupt 1".

The way this should work:

  1. Do ALL your LCD work in main
  2. Set flags to indicate the buttons have been pressed
  3. Monitor the flags in main and update the LCD appropriately

I see. I didn’t know that this could actually cause problems, even if the function isn’t actually being triggered or in other words, the button is being pushed.

So just for the test I removed the LCD code completely as following:

#include <LiquidCrystal_I2C.h>

volatile int output = HIGH;
int i = 0;

void setup()
{
    digitalWrite(6, output);
    Serial.begin(9600);
    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
    pinMode(6, OUTPUT);
    Serial.println("test");

    attachInterrupt(digitalPinToInterrupt(2), buttonPressed1, FALLING); //  function for creating external interrupts at pin2 on Rising (LOW to HIGH)
}

void loop()
{
    Serial.println(output);
    ++i;
    delay(1000);
    digitalWrite(6, output); //Turns LED ON or OFF depending upon output value
}

void buttonPressed1() //ISR function excutes when push button at pinD2 is pressed
{
    output = !output; //Change Output value to LOW
}

Now it is working and it doesn’t freeze.

But is this so to speak delayed response of the ISR normal? It seems as if the Arduino doesn’t always respond to button click or it’s reaction is delayed.

Thanks

fbele:
I see. I didn't know that this could actually cause problems, even if the function isn't actually being triggered or in other words, the button is being pushed.

But is this so to speak delayed response of the ISR normal? It seems as if the Arduino doesn't always respond to button click or it's reaction is delayed.

You have a 1 second delay so it may be delayed up to 1 second. Is there a reason you need to use an interrupt? You could easily monitor the button in loop.

After some tinkering, I’ve found out that that was the reason, yes.

Thanks.

The NANO freezes during interrupt process because you are executing print() method in the ISR. print() method works on interrupt strategy; but, interrupt gets disabled when the NANO is about to enter into ISR. Your original sketch could be moderated like this (tested on UNO with built-in L):

#include <LiquidCrystal_I2C.h>

//I2C pins declaration
LiquidCrystal_I2C lcd(0x27, 16, 2);//(0x3F, 20, 4);

volatile bool flag1 = false;
volatile bool flag2 = false;


int output = LOW;
int i = 0;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Interrupt Xample");
  lcd.setCursor(0, 1);  //display position-0 line-2
  lcd.print("ArduinoInterrupt");
  delay(3000);
  lcd.clear();
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(13, OUTPUT);
  lcd.setCursor(0, 0);
  
  attachInterrupt(digitalPinToInterrupt(2), buttonPressed1, FALLING); //  function for creating external interrupts at pin2 on Rising (LOW to HIGH)
  attachInterrupt(digitalPinToInterrupt(3), buttonPressed2, FALLING); //  function for creating external interrupts at pin3 on Rising (LOW to HIGH)
}

void loop()
{
  lcd.clear();
  lcd.print("COUNTER: ");
  lcd.setCursor(9, 0);
  lcd.print(i);
  ++i;

  if (flag1 == true)
  {
    output = LOW; //Change Output value to LOW
    lcd.setCursor(0, 1);
    lcd.print("Interrupt 1");
    digitalWrite(13, output); //Turns LED ON or OFF depending upon output value
    flag1 = false;
  }
  if (flag2 == true)
  {
    output = HIGH; //Change Output value to HIGH
    lcd.setCursor(0, 1);
    lcd.print("Interrupt2");
    digitalWrite(13, output);
    flag2 = false;
  }
  delay(1000);
}

void buttonPressed1() //ISR function excutes when push button at pinD2 is pressed
{
  flag1 = true;
}

void buttonPressed2() //ISR function excutes when push button at pinD3 is pressed
{
  flag2 = true;
}

Thank you for this insightful explanation. Now I understand exactly where my problem was and how to correctly maintain my code.