Lcd.clear using External Interrupt

Hello
i wanted to clear the written text on my LCD using 'external interrupt' , the external interrupt is triggered by a button when pressed , but no matter how many times i press the button the LCD wont be cleared . can Someone help me if i made a programming Mistake . Thankyou in Advance :slight_smile:

//The code

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
int btn_pin = 2;
LiquidCrystal_I2C lcd(0x20, 16, 2);

void setup()
{

// initialize the LCD
	Serial.begin(9600);
	pinMode (btn_pin, INPUT_PULLUP);
	lcd.begin();
	lcd.backlight();
	lcd.print("Hello, world!");
  attachInterrupt (digitalPinToInterrupt (btn_pin), toggle, FALLING);
}

void loop()
{
}
void toggle() {
   lcd.clear();
}

Is the lcd.clear() clearing the screen if run it from main code, not from irq?
What is arduino you using?

Are you sure that the button circuit is taking pin 2 LOW when you press the button ? Print a message in loop() when the button pin is LOW

Is this a theoretical exercise? Because in practise there is no need for an interrupt when reading a button; loop() can read that button hunderds of times in a second.

LCD.clear() might make use of interrupts; while you are in your ISR, all interrupts are disabled. The usual way to handle this is by setting a flag in the ISR and acting on it in loop().

volatile bool clsRequested = false;

...
...

void loop()
{
  if(clsRequested == true)
  {
    lcd.clear();
    clsRequested = false;
  }
}

void toggle()
{
   clsRequested = true;
}

After doing that, @lucaswilliam7868 will hopefully have an epiphany and realize there's no reason to have the interrupt / ISR at all. Just poll the button in loop().

no need for an ISR

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
constexpr byte btn_pin {2};
LiquidCrystal_I2C lcd(0x20, 16, 2);

void toggle() 
{
   lcd.clear();
}

void setup()
{

// initialize the LCD
	Serial.begin(9600);
	pinMode (btn_pin, INPUT_PULLUP);
	lcd.begin();
	lcd.backlight();
	lcd.print("Hello, world!");
  // attachInterrupt (digitalPinToInterrupt (btn_pin), toggle, FALLING); // don't use ISR the next two years!
}

void loop()
{
  if (digitalRead(btn_pin) == LOW) toggle();
}


I Wanted to make a Arduino countdown using LCD and IR receiver, 1 minute countdown begins when i press 1 on IR Remote, and if i want the countdown to stop I made a External interrupt with a button to make LCD clear when pressed, but LCD wont be cleared when i press button but LCD clear happens when countdown ends,

You don't need an interrupt if you get rid of the for-loop and the delay in your oneminute() function that you posted in Cant lcd.clear when lcd on countdown. As a rule of thumb, for-loops (and while-loops) have no place in Arduino code when it comes to timing or to waiting for something to happen; let loop() do the looping.

The below is a reworked version of your oneminute(). I've renamed i to counter and it's now local to the function. It's advisable not to use single letter variables as global variables; when code grows, it will be a mission to find them back. Because counter is declared as static, it will be remembered; this is similar to a global variable (that you declare before setup() but you don'thavethe risk to accidentally change them in other parts of the code).

The function also uses a static variable to keep track of the start of a 'delay'. Lastly the function controls a global variable countdownInProgress that indicates if countdown is in progress or not. It's initially set to false; if you call the function it will be set to true till the one minute has passed after which it will be set to false again.

// variable to indicate if countdown is in progress
bool countdownInProgress = false;

...
...

void setup()
{
  ...
  ...
}

void loop()
{
  ...
  ...
}

/*
  one minute countdown timer
*/
void oneMinute()
{
  static byte counter;
  static uint32_t delayStarttime;

  // if a new countdown needs to be started
  if (countdownInProgress == false)
  {
    // set the timer
    delayStarttime = millis();
    // initialise the counter
    counter = 60;
    // indicate that countdown is in progress
    countdownInProgress = true;

    // show the countdown
    lcd.setCursor(0, 0);
    if (counter < 10)
    {
      lcd.print("0");
    }
    lcd.print(counter);
  }

  // if one second passed
  if (millis() - delayStarttime >= 1000)
  {
    // reset  the timer for next 1 second delay
    delayStarttime = millis();
    // decrement the counter
    counter--;

    // show the countdown
    lcd.setCursor(0, 0);
    if (counter < 10)
    {
      lcd.print("0");
    }
    lcd.print(counter);
  }

  // if the countdown is finished
  if (counter == 0)
  {
    //indicate that the countdown is finished
    countdownInProgress = false;
  }
}

You will have to repeatedly call this function from loop(); the below will countdown from 60 to 0 and start again.

void loop()
{
  oneMinute();
}

Now you can write the loop() code to do what you want it to do; the below code demonstrates using a start button and a stop button.

// sensible name for the button status when it is low
#define ISPRESSED LOW
// variable to indicate if countdown is in progress
bool countdownInProgress = false;

// start and stop button
const uint8_t pinStartButton = 3;
const uint8_t pinStopButton = 2;

...
...

void setup()
{
  // set up the LCD's number of columns and rows:
  lcd.begin();
  pinMode(pinStartButton, INPUT_PULLUP);
  pinMode(pinStopButton, INPUT_PULLUP);
}

void loop()
{
  // read the start button
  if (digitalRead(pinStartButton) == ISPRESSED)
  {
    // start the countdown
    oneMinute();
  }

  // read the stop button
  if (digitalRead(pinStopButton) == ISPRESSED)
  {
    // stop the countdown
    countdownInProgress = false;
    // clear the lcd
    lcd.clear();
  }

  // if countdown is in progress
  if (countdownInProgress == true)
    // continue the countdown
    oneMinute();
}

This should give you enough to get your project going. If you have questions about this, ask.

Code not tested but basically compiles if the missing pieces are filled in.

Thankyou my friend , The start button and stop button works and countdown also starts but i still face a problem , I tried to modify start button signal with the signal of My IR remote , its like when i press 1 on IR remote, IR receivers sends signal to start the countdown , problem is The countdown only decreases if I keep Pressing the 1 on IR remote or else it stops. My Apologies for taking your time but can you help me with this.
Thankyou in advance :slight_smile:

// the code

// sensible name for the button status when it is low
#define ISPRESSED LOW
#include <IRremote.h>
#include <LiquidCrystal_I2C.h>
// start and stop button
// variable to indicate if countdown is in progress
bool countdownInProgress = false;
int receiver_pin = 9;
const uint8_t pinStopButton = 2;
LiquidCrystal_I2C lcd(0x20, 16, 2);
IRrecv receiver(receiver_pin);
decode_results output;

#define code1  41565 // to start 1 minute countdown
#define clear0 39015 // to clear lcd
void setup()
{
  Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin();
  lcd.print("LCD TEST");
  receiver.enableIRIn();
  pinMode(pinStopButton, INPUT_PULLUP);
}

void loop()
{
  while (receiver.decode(&output)) {
   unsigned int value = output.value;
    switch (value) {
      case code1:
        lcd.clear();
        oneMinute();
       break;
    }
    // read the stop button
    if (digitalRead(pinStopButton) == ISPRESSED)
    {
      // stop the countdown
      countdownInProgress = false;
      // clear the lcd
      lcd.clear();
    }

    // if countdown is in progress
    if (countdownInProgress == true) {
      // continue the countdown
      oneMinute();
    }
    Serial.println(value);
    receiver.resume();
  }
}
void oneMinute()
{
  static byte counter;
  static uint32_t delayStarttime;

  // if a new countdown needs to be started
  if (countdownInProgress == false)
  {
    // set the timer
    delayStarttime = millis();
    // initialise the counter
    counter = 60;
    // indicate that countdown is in progress
    countdownInProgress = true;

    // show the countdown
    lcd.setCursor(0, 0);
    if (counter < 10)
    {
      lcd.print("0");
    }
    lcd.print(counter);
  }

  // if one second passed
  if (millis() - delayStarttime >= 1000)
  {
    // reset  the timer for next 1 second delay
    delayStarttime = millis();
    // decrement the counter
    counter--;

    // show the countdown
    lcd.setCursor(0, 0);
    if (counter < 10)
    {
      lcd.print("0");
    }
    lcd.print(counter);
  }

  // if the countdown is finished
  if (counter == 0)
  {
    //indicate that the countdown is finished
    countdownInProgress = false;
  }
}

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