Problem using interruptions and an lcd with I2C

Hi, I am trying to make a function that blink a led half a second with an external interruption that displays something on a LCD.

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

const int Band=300;
long Time=0;
const byte interruptPin = 2;
const byte interruptPin2= 3;
volatile byte state = LOW;
const byte ledPin = 8;

void setup() {
  // put your setup code here, to run once:
  lcd.init();
  lcd.backlight();
   attachInterrupt(digitalPinToInterrupt(interruptPin2), blink1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(interruptPin), intent1, CHANGE);
  pinMode(interruptPin, INPUT);
  pinMode(ledPin,OUTPUT);
  pinMode(7,OUTPUT);
}

void loop() {

  int i=0;
  // put your main code here, to run repeatedly:
  for(i=0;i<=99;i++){
    digitalWrite(7,HIGH);
    delay(500);
    digitalWrite(7,LOW);
    delay(500);
  }
}

void blink1() {
  if(millis()-Time>Band){
    state = !state;
    Time=millis();
    digitalWrite(ledPin,state);
  }
  
}

void intent1(void) {
  if(millis()-Time>Band){
  lcd.setCursor(0,1);
  lcd.print("I WORKED :)");
  }
}

The blink part works well as the blink1 interruption, the problem comes when I push the button to activate intent 1, then the program freeze. I have identified that if I removed the lcd commands on the interruption it works.
What could be the problem? :c

Without looking any further, I see you are asking for an interrupt to occur every time a change occurs on those pins. Every time you push the button you get AT least TWO interrupts and if the switch bounces, many interrupts.
Paul

You can not use anything that uses interrupts inside an ISR.
ISR's should be as short as possible.

Just set a volatile bool to true in the ISR, and act on the set flag in loop.

To make that responsive, you have to get rid of the dreaded delays that you are using now.

1 Like

Wasn't that a big enough clue?

This for loop gets repeated endlessly by loop, so it is superfluous.

1 Like

Maybe you could use something like this

#include <LiquidCrystal_I2C.h>

const uint16_t Band = 300;
const uint8_t interruptPin1 = 2;
const uint8_t interruptPin2 = 3;
const uint8_t ledPin1 = 7;
const uint8_t ledPin = 8;

LiquidCrystal_I2C lcd(0x27, 16, 2);
volatile bool triggered = false;

void setup() {
  lcd.init();
  lcd.backlight();
  attachInterrupt(digitalPinToInterrupt(interruptPin2), blink1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(interruptPin1), intent1, CHANGE);
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
}

void loop() {
  static uint32_t Time;
  static bool state;
  if (millis() - Time >= 500) {
    digitalWrite(ledPin1, state ? HIGH : LOW);
    state = !state;
    Time = millis();
  }
  if (triggered) {
    lcd.setCursor(0, 1);
    lcd.print("I WORKED :)");
    triggered = false;
  }
}

void blink1() {
  static uint32_t Time;
  static bool state = false;
  if (millis() - Time > Band) {
    state = !state;
    Time = millis();
    digitalWrite(ledPin, state ? HIGH : LOW);
  }
}

void intent1(void) {
  triggered = true;
}
1 Like

As @Whandall said you can't use anything that uses interrupts inside an ISR.
The Wire library uses interrupts. And while it uses interrupts it also polls flags set by an ISR (forever) waiting for certain things to complete.
So if you are inside an ISR and you call the lcd library which calls the Wire library, the Wire library gets stuck in an infinite loop waiting for a flag to get set by the Wire h/w ISR because interrupts are masked.

--- bill

1 Like

Thank both of you.
So this means that if for some case I want to write in my lcd inside the interruption function I need to use the lcd without the I2C, because the Wire library is used for the I2C communication, isn't it?

While it would probably work and block many pins, it's not a good idea.

The best ISRs just set some flags and gather information,
they do nothing that could be done later in normal mode,
or in a less elevated mode, if running on a more sophisticated processor like an ESP32.

1 Like

Or in short, you are trying to use interrupts when you have no idea what they are! :upside_down_face: