Countdown timer 16x2 lcd

yes! (was nagging at me lately)

Warning: On a basic Arduino like an UNO, Nano, or Mega this is likely to result in an integer overflow. The numbers '60' and '1000' are 'int' literals. If 'minsDelay' is an 'int' then the math will all be done in 'int' which can't hold 60 * 1000, let alone 45 * 60 * 1000.

thanks, i will try

I got this

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned long currentMillis = millis();
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
pinMode(backLight, OUTPUT);
digitalWrite(backLight, HIGH);
lcd.begin(16,2);
lcd.clear();

Serial.begin(9600);
pinMode (2,OUTPUT);
pinMode (3,OUTPUT);
pinMode (4,OUTPUT);

pinMode (8,OUTPUT);
}



void loop()
{
  

  // Count down once per second
  if (currentMillis - PreviousMillis == 1000)
  {
    PreviousMillis += 1000;

    if (SecondsRemaining > 0)
    {
      SecondsRemaining--;
      lcd.clear();
      lcd.println(SecondsRemaining);
      if (SecondsRemaining == 0)
      {lcd.write("beep");}
    }
  }
int keyVal = analogRead(A0);
Serial.println(keyVal);
  // Check for input:
  if (keyVal == 341)
    {
    SecondsRemaining = 1800; // 30 minutes
    PreviousMillis = currentMillis; // Restart the timer
   }
   else if (keyVal == 1001)
    {
    SecondsRemaining = 900; // 15 minutes
    PreviousMillis = currentMillis; // Restart the timer
   }
   else if (keyVal == 10)
    {
    SecondsRemaining = 2700; // 45 minutes
    PreviousMillis = currentMillis; // Restart the timer
   }
}

but I have no idea how to display the time on the LCD, any ideas?

I've tried lcd.write(SecondsRemaining); but then i get a weird symbol or something

have you tried lcd.print()?

thanks, that worked, but now it says 1800 on the lcd and it doesnt count down whatsoever

can't help w/o seeing some code ???

sorry
here it is:

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned long currentMillis = millis();
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
pinMode(backLight, OUTPUT);
digitalWrite(backLight, HIGH);
lcd.begin(16,2);
lcd.clear();

Serial.begin(9600);
pinMode (2,OUTPUT);
pinMode (3,OUTPUT);
pinMode (4,OUTPUT);

pinMode (8,OUTPUT);
}



void loop()
{
  

  // Count down once per second
  if (currentMillis - PreviousMillis == 1000)
  {
    PreviousMillis += 1000;

    if (SecondsRemaining > 0)
    {
      SecondsRemaining--;
      lcd.clear();
      lcd.println(SecondsRemaining);
      if (SecondsRemaining == 0)
      {lcd.write("beep");}
    }
  }
int keyVal = analogRead(A0);
Serial.println(keyVal);
  // Check for input:
  if (keyVal == 341)
    {
    SecondsRemaining = 1800; // 30 minutes
    lcd.print(SecondsRemaining);
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
   }
   else if (keyVal == 1001)
    {
    SecondsRemaining = 900; // 15 minutes
    PreviousMillis = currentMillis; // Restart the timer
   }
   else if (keyVal == 10)
    {
    SecondsRemaining = 2700; // 45 minutes
    PreviousMillis = currentMillis; // Restart the timer
   }
}

You never update currentMillis...

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;

LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(16, 2);
  lcd.clear();

  Serial.begin(9600);
  pinMode (2, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);

  pinMode (8, OUTPUT);
}



void loop()
{
  unsigned long currentMillis = millis();
  // Count down once per second
  if (currentMillis - PreviousMillis >= 1000)
  {
    PreviousMillis += 1000;

    if (SecondsRemaining > 0)
    {
      SecondsRemaining--;
      lcd.clear();
      lcd.println(SecondsRemaining);
      if (SecondsRemaining == 0)
      {
        lcd.write("beep");
      }
    }
  }
  int keyVal = analogRead(A0);
  Serial.println(keyVal);
  // Check for input:
  if (keyVal == 341)
  {
    SecondsRemaining = 1800; // 30 minutes
    lcd.print(SecondsRemaining);
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 1001)
  {
    SecondsRemaining = 900; // 15 minutes
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 10)
  {
    SecondsRemaining = 2700; // 45 minutes
    PreviousMillis = currentMillis; // Restart the timer
  }
}

Thanks this was the answer, but I dont know if I need it in minutes for example (15:00) or in seconds but im gonna show this to my teacher and tell you

The key is to always track elapsed time in seconds or milliseconds and then convert it as needed for display purposes. It is far easier to keep track of all the math and then do something like

unsigned long t = SecondsRemaining;
int hours = t / 3600;  // integer division so rounds down
t = t % 3600;
int minutes = t / 60;
int seconds = t % 60;
// now display hours:minutes:seconds

I'm trying something like this

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned MinutesRemaining = 0;
unsigned long t = SecondsRemaining;
int hours = t % 3600;  // integer division so rounds down
int minutes = t / 60;
int seconds = t % 60;
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(16, 2);
  lcd.clear();
  Serial.begin(9600);

}



void loop()
{
  unsigned long currentMillis = millis();
  // Count down once per second
  
  if (currentMillis - PreviousMillis >= 1000)
  {
    PreviousMillis += 1000;
    MinutesRemaining = SecondsRemaining % 60;
    if (SecondsRemaining > 0)
    {
      SecondsRemaining--;
      lcd.clear();
      lcd.println(SecondsRemaining);
     
      if (MinutesRemaining == 0)
      {
        lcd.clear();
        lcd.write("beep");
        tone(5, 523, 2000);
        
      }
    }
    if (SecondsRemaining = 0)
  {
   MinutesRemaining - 1;
    SecondsRemaining == 59;
   
  }
  }
  int keyVal = analogRead(A0);
  Serial.println(keyVal);
  // Check for input:
  if (keyVal == 341)
  {
    MinutesRemaining = 44;
    SecondsRemaining = 59; // 30 minutes
   lcd.print(MinutesRemaining);
    lcd.print(":");
    lcd.print(SecondsRemaining);
   delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 1001)
  {
    SecondsRemaining = 900; // 15 minutes
    lcd.print(SecondsRemaining);
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 10)
  {
    SecondsRemaining = 2700; // 45 minutes
    lcd.print(SecondsRemaining);
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
}

Am I on the right path
(im trying to make it in (minutes:seconds) )

sometimes the code is over-complicated to see how simple it is. and there were various problems

  • the compiler reported several warnings

should be "=="
if (SecondsRemaining = 0)

should be "MinutesRemaining --;"
MinutesRemaining - 1;

should be "="
SecondsRemaining == 59;

  • whenever the pot value changes -- and it will dither between values -- SecondsRemaining gets reset.

need to check for a change in value beyond some threshold

    static int keyValLst;
    int keyVal = analogRead (A0);

    if (abs (keyValLst - keyVal) > 2)  {
  • and the comparison to a specific value when checking for a change beyond some threshold needs a threshold
        if (abs(keyVal - 341) < 3)
  • PreviousMillis should be set to currentMillis when it expires, after
    if (currentMillis - PreviousMillis >= 1000)   {
        PreviousMillis = currentMillis;
  • i believe lcd.write() writes a single character. i think lcd.print() is what is needed

consider

#undef MyHW
#ifdef MyHW
struct LiquidCrystal {
    LiquidCrystal (int a, int b, int c, int d, int e, int f, int g) { };

    void begin (int a, int b)   { };
    void clear (void)           { };
    void setCursor (int a, int b) { };

    void write (const char *s) { 
        Serial.print ("write -- ");
        Serial.println (s);
    };

    void print (int i)         { Serial.print   (i); };
    void print (const char *s) { Serial.print   (s); };

    void println (int i)         { Serial.println (i); };
    void println (const char *s) { Serial.println (s); };
};

#else
# include <LiquidCrystal.h>
#endif

unsigned long PreviousMillis = 0;

unsigned SecondsRemaining = 0;

LiquidCrystal lcd (6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight

char s [80];

// -----------------------------------------------------------------------------
void setup () {
    pinMode (backLight, OUTPUT);
    digitalWrite (backLight, HIGH);
    lcd.begin (16, 2);
    lcd.clear ();

    Serial.begin (9600);
}

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long currentMillis = millis ();

    // Count down once per second
    if (currentMillis - PreviousMillis >= 1000)
    {
        PreviousMillis = currentMillis;

        if (0 < SecondsRemaining) {
            SecondsRemaining--;

            sprintf (s, " %2d:%02d",
                SecondsRemaining / 60, SecondsRemaining % 60);
            lcd.println (s);
        }
    }

    static int keyValLst;
    int keyVal = analogRead (A0);

    if (abs (keyValLst - keyVal) > 2)  {
        keyValLst = keyVal;

        if (abs(keyVal - 341) < 3)
            SecondsRemaining = 30 * 60;
        else if (abs(keyVal - 1001) < 3)
            SecondsRemaining = 15 * 60;
        else if (abs(keyVal - 10) < 3)
            SecondsRemaining = 45 * 60;

        sprintf (s, " key %4d, secs %4d",
            keyVal, SecondsRemaining);
        lcd.println (s);
    }
}

Depends on the arguments:
lcd.write(char); Single character
lcd.write(char *); Writes characters until it reaches a null.
lcd.write(char *, int); Writes 'int' characters.

Thanks all for your answers, I wrote this myself and it works
for anyone curious:

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned MinutesRemaining;
int t = SecondsRemaining;
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(16, 2);
  lcd.clear();
  Serial.begin(9600);

}



void loop()
{
  unsigned long currentMillis = millis();
  // Count down once per second
  
  if (currentMillis - PreviousMillis >= 1000)
  {
    PreviousMillis += 1000;
    if (SecondsRemaining > 0)
    {
      SecondsRemaining--;
    }else if (SecondsRemaining == 0)
    {
      MinutesRemaining -= 1;
      SecondsRemaining += 59;
    }
    lcd.clear();
    lcd.print(MinutesRemaining);
    lcd.print(":");
    if(SecondsRemaining < 10)
    {lcd.print("0");}
    lcd.print(SecondsRemaining);
    if (MinutesRemaining == 0)
    {
      lcd.clear();
      lcd.write("beep");
      tone(5, 523, 2000);
    }
  }
  int keyVal = analogRead(A0);
  Serial.println(keyVal);
  // Check for input:
  if (keyVal == 341)
  {
    MinutesRemaining = 30;
    SecondsRemaining = 00; // 30 minutes
   lcd.print(MinutesRemaining);
    lcd.print(":");
    lcd.print(SecondsRemaining);
   delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 1001)
  {
   MinutesRemaining = 15;
   SecondsRemaining = 0;
   delay(1000);
   PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 10)
  {
    MinutesRemaining = 45;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
}

Your code will beep when there are 59 seconds, 0 minutes left on your timer and continue to do so until you reset it again. Is that the behavior you want?

No, but I updated it again

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned MinutesRemaining;
int t = SecondsRemaining;
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(16, 2);
  lcd.clear();
  Serial.begin(9600);
lcd.clear();
lcd.write("Select your time");
}



void loop()
{
  unsigned long currentMillis = millis();
  // Count down once per second
  
  if (currentMillis - PreviousMillis >= 1000)
  {
    PreviousMillis += 1000;
    if (SecondsRemaining > 0)
    {
      lcd.clear();
      SecondsRemaining--;
    }else if (SecondsRemaining == 0)
    {
      MinutesRemaining -= 1;
      SecondsRemaining += 59;
    }
    lcd.clear();
    lcd.print(MinutesRemaining);
    lcd.print(":");
    if(SecondsRemaining < 10)
    {lcd.print("0");}
    lcd.print(SecondsRemaining);
    if (MinutesRemaining + SecondsRemaining == 0)
    {
      lcd.clear();
      lcd.write("beep");
      tone(5, 523, 2000);
    }
  }
  int keyVal = analogRead(A0);
  Serial.println(keyVal);
  // Check for input:
  if (keyVal == 544)
  {
    MinutesRemaining = 30;
    SecondsRemaining = 00; // 30 minutes
   lcd.print(MinutesRemaining);
    lcd.print(":");
    lcd.print(SecondsRemaining);
   delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 1023)
  {
   MinutesRemaining = 15;
   SecondsRemaining = 0;
   delay(1000);
   PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 784)
  {
    MinutesRemaining = 45;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
}

Rather than all that code dealing with SecondsRemaining and MinutesRemaining, you should just track SecondsRemaining as your one countdown variable and then convert it to MM:SS for display purposes. You will find it will make your code much more straight forward

I have this now

#include <LiquidCrystal.h>

unsigned SecondsRemaining = 0;
unsigned long PreviousMillis = 0;
unsigned MinutesRemaining;
int t = SecondsRemaining;
LiquidCrystal lcd(6, 7, 8, 9, 10, 11, 12);
int backLight = 13; // pin 13 will control the backlight
void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(16, 2);
  lcd.clear();
  Serial.begin(9600);
lcd.clear();
lcd.write("Select your time");
}



void loop()
{
  unsigned long currentMillis = millis();
  // Count down once per second
  
  if (currentMillis - PreviousMillis >= 1000)
  {
    PreviousMillis += 1000;
    if (SecondsRemaining > 0)
    {
      lcd.clear();
      SecondsRemaining--;
    }else if (SecondsRemaining == 0)
    {
      MinutesRemaining -= 1;
      SecondsRemaining += 59;
    }
    lcd.clear();
    lcd.print(MinutesRemaining);
    lcd.print(":");
    if(SecondsRemaining < 10)
    {lcd.print("0");}
    lcd.print(SecondsRemaining);
    if (MinutesRemaining + SecondsRemaining == 0)
    {
      lcd.clear();
      lcd.write("beep");
      tone(5, 523, 2000);
      delay(60000);
      tone(5, 400, 2000);
      
    }
  }
  int keyVal = analogRead(A0);
  Serial.println(keyVal);
  // Check for input:
  if (keyVal == 544)
  {
    MinutesRemaining = 30;
    SecondsRemaining = 00; // 30 minutes
   lcd.print(MinutesRemaining);
    lcd.print(":");
    lcd.print(SecondsRemaining);
   delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
  else if (keyVal == 1023)
  {
   MinutesRemaining = 15;
   SecondsRemaining = 0;
   delay(1000);
   PreviousMillis = currentMillis; // Restart the timer
  }

  else if (keyVal == 784)
  {
    MinutesRemaining = 45;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer 
      }
      else if (keyVal == 783)
  {
    MinutesRemaining = 45;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
    else if (keyVal == 782)
  {
    MinutesRemaining = 45;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
    } 
      else if (keyVal == 543)
  {
    MinutesRemaining = 30;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  }
    else if (keyVal == 545)
  {
    MinutesRemaining = 30;
    SecondsRemaining = 00;
    delay(1000);
    PreviousMillis = currentMillis; // Restart the timer
  } 
}

Every time it starts it says "Select your time" but then it clears out and gives the number "65535:60", I have looked through my code and I don't see any reason why it says that.
anyone knows?