0

I am making an Arduino alarm clock. I am checking for the state of a button. If it is clicked, I increment the button counter. If the counter is divisible by 2, it is mode 0, if not, it is mode 1. I have small delays in the code for each mode to help the lcd clear itself. Those delays are preventing the buttons to reacting to my touch, because there is likely a delay during that time.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int hours=0;
int minutes=0;
const int modePin=6; //button
int prevModeState=0; //prev state of button
unsigned long timer;
int modeState;//current state
int mode=0;//mode of alarm
int buttonCounter=0;
void setup() {
lcd.begin(16, 2);
lcd.setCursor(6, 0);
lcd.print("Time:");
lcd.setCursor(6, 1);
lcd.print("00:00");
pinMode(modePin, INPUT);
}

void loop() {
modeState=digitalRead(modePin);
if(prevModeState!=modeState){    //this is the part where I check for the state
  if(modeState==HIGH){
    buttonCounter++;
  } 
}
prevModeState=modeState;
if(buttonCounter%2==0){
  mode=0;
}
else{
  mode=1;
}


if(mode==0){
  timer=millis();
  if(timer%600==0){
     minutes++;
    if(minutes==60){
        minutes=0;
        hours++;
        }
     if(hours==24){
        hours=0;
     }
    lcd.clear();
    lcd.setCursor(6, 0);
    lcd.print("Time:");
    lcd.setCursor(6, 1);
    writeTime();
    delay(200); //delay
    }
}
else if(mode==1){
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("Set Time:");
  lcd.setCursor(6, 1);
  writeTime();
  delay(500); //delays

}
}

void writeTime(){
if(minutes<10){

      if(hours<10){
        lcd.print(String("0")+hours+":"+"0"+minutes);
      }
      else{
        lcd.print(hours+String(":")+"0"+minutes);
      }
    }
    else{
      if(hours<10){
         lcd.print(String("0")+hours+":"+minutes);
      }
      else{
         lcd.print(hours+String(":")+minutes);//possibly split if problems arise
      }

    }
}

How can I edit my code?

| improve this question | | | | |
2

The simple answer is, of course, don't use any delay() calls. There is no need for them in your code.

I cannot remove delays since lcd.clear(); would be done very often and nothing would be visible on the lcd.

So don't clear the LCD. There is no reason to clear the LCD. Just over-print the existing text with new text. Go on, have a go. Just remove the lcd.clear() calls and the delays from your program and see just how smoothly the screen updates.

On an LCD a cell can only hold one character at a time. Printing one thing and then printing something else in the same place replaces the characters that are already there with the new ones. There is rarely any need to use lcd.clear() for normal screen updates - only if you really need to clear the entire screen should you use it. Just updating a bit of text on the screen does not require clearing of the entire screen.

In fact, you don't even need to print Time: or Set Time: every loop - you only need to do that once when you change mode. If you are going to clear the screen that is the time to do it. So a quick outline:

  • When button pressed:
    • Set mode
    • Clear screen
    • Print static text (Time: etc)
  • Every iteration:
    • Print the mode's dynamic text

You see the heavyweight screen clearing is only done once when you change mode. All the rest of the time it's just updating small portions of the screen. Not only does it look nicer (no flicker) but it's also considerably more efficient and allows your program to do more.

| improve this answer | | | | |
2

You have a few options, including using interrupts. But I believe the most important thing is: "do not use delay()" and you might not even need to use interrupts...

Have a look on this nice post from Nick Gammon: http://www.gammon.com.au/blink with some tips about non-blocking coding.

Also a very simple "Blink LED" example: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

| improve this answer | | | | |
  • I will look into that. Also, I cannot remove delays since lcd.clear(); would be done very often and nothing would be visible on the lcd. Also, the clear takes time - that is why I need the delay. – shurup Jun 13 '16 at 1:36
  • 2
    Sure you can remove the delays. Have a look on the examples from the links and you'll understand how to do non-blocking coding.In your example, instead of using the delay to hold before "clearing" the LCD, you just define "when" in the future you'll be running clearing. You are already familiar with millis() so tou're on the right direction ;) – Talk2 Jun 13 '16 at 1:42
  • You don't need to clear the display at all. Just overwrite the existing text with the new text. Clearing an LCD is quite an "expensive" operation and if you don't actually need it then you should avoid it. – Majenko Jun 13 '16 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.