12 hr to 24 hr code change without RTC

I found this code.

How do I make it 24 hr clock?

#include <LiquidCrystal.h>;
const int rs = 12, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

bool isAlarm = false, isStopwatch = false, isTimer = false;
const int led = 13;
const int pushbtn1 = 10; 
const int pushbtn2 = 9;
const int pushbtn3 = 8;
const int pushbtn4 = 7;

int hour=9, minute=59, second=55, pis=0, mls=0, lastTime=0, now;
int hourAlarm=0, minuteAlarm=0, secondAlarm=0;
int mode=0;
int flag = 0, flagAlarm = 0;  //indicates 0 = AM, 1 = PM


int btnstate1; //indicates pushbtn's state
int btnstate2;
int btnstate3;
int btnstate4;


void setup() {
  lcd.begin(16, 2);
  pinMode(pushbtn2, INPUT);
  pinMode(pushbtn3, INPUT);
  pinMode(pushbtn4, INPUT);
  pinMode(pushbtn1, INPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  if(mode==0)clock();
  else if(mode==1)setTime();
  else if(mode==2)setAlarm();
  else if(mode==3)setTimer();
  else if(mode==4)stopwatch();
}


//////////****************CHECKING FOR NEW SCREEN***************//////////
void checkState(){
  btnstate1=digitalRead(pushbtn1);
  btnstate2=digitalRead(pushbtn2);
  btnstate3=digitalRead(pushbtn3);
  btnstate4=digitalRead(pushbtn4);
  if(btnstate1|btnstate2|btnstate3|btnstate4) {
     if(btnstate1==1){
       mode=1;
     }
     if(btnstate2==1){
       mode=2;
     }
     if(btnstate3==1){
       mode=3;
     }
     if(btnstate4==1){
       mode=4;
     }
    }
    else {
       mode=0;
    }
}


//////////****************CLOCK***************//////////
void clock(){
  lcd.setCursor(0,0);
  lcd.print("What time is it?");
  lcd.setCursor(0,1);
  lcd.print("It's ");
  if(hour<10)lcd.print("0");
  lcd.print(hour);
  lcd.print(":");
  if(minute<10)lcd.print("0");
  lcd.print(minute);
  lcd.print(":");
  if(second<10)lcd.print("0");
  lcd.print(second);

 if(flag==0) lcd.print(" AM");
 if(flag==1) lcd.print(" PM");
 
 checkState();
 delay(200);
 runningClock(&hour, &minute, &second, &now, &lastTime, &mls, &flag);
}

void runningClock(int* _hour,int* _minute, int* _second, int* _now, int* _lastTime, int* _mls, int* _flag){
 int increHour=0; 
 *_now=(millis());
 *_mls+=(*_now-*_lastTime);
 *_lastTime=*_now;

 if(*_mls >= 1000){
  *_second+=(*_mls/1000); 
  *_mls%=1000;
  }
 if(*_second >= 60){
   *_minute+=*_second/60;
   *_second%=60;
  }
 if(*_minute >= 60){
   increHour=*_minute/60;
   	*_minute%=60;
  }
  if(increHour%24==0); //hour as before
  else {
    increHour%=24;
    if(increHour<12){
      if(*_hour==12){
        *_hour=increHour;
      }
      else if(*_hour+increHour>=12){
        *_hour-=12;
        *_flag=*_flag==0?1:0;
      }
    }
    else{
      *_hour=((*_hour+increHour)%12);
      *_flag=*_flag==0?1:0;
      
    }
 	if(*_flag==0 & *_hour==12)*_hour=0;
 	else if(*_flag==1 & *_hour==0)*_hour=12;
 }
}



//////////****************TIMESETTING***************//////////
void setTime() {
  int *main_var;
  int X, Y;
  lcd.clear();
  
  int currentChangeIn = 1; //1 is hour 2 is minute and so on
  while(true) 
  {
    lcd.setCursor(0,0);
  	lcd.print("Set Time");
  	lcd.setCursor(0,1);
  	if(hour<10)lcd.print("0");
  	lcd.print(hour);
  	lcd.print(":");
  	if(minute<10)lcd.print("0");
  	lcd.print(minute);
  	lcd.print(":");
  	if(second<10)lcd.print("0");
  	lcd.print(second);

  	if(flag==0) lcd.print(" AM");
  	if(flag==1) lcd.print(" PM");
    
   	btnstate1=digitalRead(pushbtn1);
  	btnstate2=digitalRead(pushbtn2);
  	btnstate3=digitalRead(pushbtn3);
  	btnstate4=digitalRead(pushbtn4);
    if(btnstate1==1){
      mode=0;
      delay(200);
      break;
    }
    if(btnstate3==1){
      if(currentChangeIn==3)currentChangeIn=0;
      currentChangeIn+=1;
      delay(200);
    }
    if(currentChangeIn==1){
      main_var = &hour;
      X = 0;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        hour+=1;
        if(hour==13)hour=1;
        else if(hour==12 & flag==0)hour=0;
        delay(200);
      }
    }
    if(currentChangeIn==2){
      main_var = &minute;
      X = 3;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        minute+=1;
        if(minute==60)minute=0;
        delay(200);
      }
    }
    if(currentChangeIn==3){
      main_var = &second;
      X = 6;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        second+=1;
        if(second==60)second=0;
        delay(200);
      }
    }
    if(btnstate4==1){
      flag=flag==0?1:0;
      if(flag==0 & hour==12)hour=0;
      else if(flag==1 & hour==0)hour=12;
      delay(200);
    }
    blink(*main_var,X,Y);
	runningClock(&hour, &minute, &second, &now, &lastTime, &mls, &flag);
  }
}



//////////****************ALARM***************//////////
void setAlarm() {
  int *main_var;
  int X, Y;
  lcd.clear();
  
  int currentChangeIn = 1; //1 is hour 2 is minute and so on
  while(true) 
  {
    lcd.setCursor(0,0);
  	lcd.print("Set Alarm");
  	lcd.setCursor(0,1);
  	if(hourAlarm<10)lcd.print("0");
  	lcd.print(hourAlarm);
  	lcd.print(":");
  	if(minuteAlarm<10)lcd.print("0");
  	lcd.print(minuteAlarm);
  	lcd.print(":");
  	if(secondAlarm<10)lcd.print("0");
  	lcd.print(secondAlarm);

  	if(flagAlarm==0) lcd.print(" AM");
  	if(flagAlarm==1) lcd.print(" PM");
    
   	btnstate1=digitalRead(pushbtn1);
  	btnstate2=digitalRead(pushbtn2);
  	btnstate3=digitalRead(pushbtn3);
  	btnstate4=digitalRead(pushbtn4);
    if(btnstate1==1){
      mode=0;
      delay(200);
      break;
    }
    if(btnstate3==1){
      if(currentChangeIn==3)currentChangeIn=0;
      currentChangeIn+=1;
      delay(200);
    }
    if(currentChangeIn==1){
      main_var=&hourAlarm;
      X = 0;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        hourAlarm+=1;
        if(hourAlarm==13)hourAlarm=1;
        else if(hourAlarm==12 & flagAlarm==0)hourAlarm=0;
        delay(200);
      }
    }
    if(currentChangeIn==2){
      main_var=&minuteAlarm;
      X = 3;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        minuteAlarm+=1;
        if(minuteAlarm==60)minuteAlarm=0;
        delay(200);
      }
    }
    if(currentChangeIn==3){
      main_var=&secondAlarm;
      X = 6;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        secondAlarm+=1;
        if(secondAlarm==60)secondAlarm=0;
        delay(200);
      }
    }
    if(btnstate4==1){
      flagAlarm=flagAlarm==0?1:0;
      if(flagAlarm==0 & hourAlarm==12)hourAlarm=0;
      else if(flagAlarm==1 & hourAlarm==0)hourAlarm=12;
      delay(200);
    }
    blink(*main_var,X,Y);
  }
  isAlarm=true;
  runningClock(&hour, &minute, &second, &now, &lastTime, &mls, &flag);
}

//////////****************TIMER***************//////////
void setTimer() {
  int minuteTimer=0, secondTimer=0, mlsTimer=0, lastTimeTimer;
  int *main_var;
  int X, Y;
  lcd.clear();
  int brFlag=0; //blinking stopper
  int currentChangeIn = 2; //1 is hour 2 is minute and so on
  while(true) 
  {
    lcd.setCursor(0,0);
  	lcd.print("Set Timer");
  	lcd.setCursor(0,1);
  	if(minuteTimer<10)lcd.print("0");
  	lcd.print(minuteTimer);
  	lcd.print(":");
  	if(secondTimer<10)lcd.print("0");
  	lcd.print(secondTimer);
    
   	btnstate1=digitalRead(pushbtn1);
  	btnstate2=digitalRead(pushbtn2);
  	btnstate3=digitalRead(pushbtn3);
  	btnstate4=digitalRead(pushbtn4);
    if(btnstate1==1){
      mode=0;
      delay(200);
      break;
    }
    if(btnstate3==1){
      currentChangeIn+=1;
      if(currentChangeIn==4)currentChangeIn=2;
      delay(200);
    }
    if(currentChangeIn==2){
      main_var=&minuteTimer;
      X = 0;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        minuteTimer+=1;
        delay(200);
      }
    }
    if(currentChangeIn==3){
      main_var=&secondTimer;
      X = 3;
      Y = 1;
     
      if(digitalRead(pushbtn2)==1){
        secondTimer+=1;
        if(secondTimer==60)secondTimer=0;
        delay(200);
      }
    }
    if(btnstate4==1){
      if(!isTimer)isTimer=true;
      else{
        isTimer=false;
      }
      brFlag=1;
      lastTimeTimer=millis();
      delay(200);
    }
    if(isTimer)runningTimer(&minuteTimer, &secondTimer, &mlsTimer, &lastTimeTimer);
    if(minuteTimer==0&secondTimer==0)brFlag=0;
    if(brFlag==0)blink(*main_var,X,Y);
    delay(200);
    runningClock(&hour, &minute, &second, &now, &lastTime, &mls, &flag);
  }
}

void runningTimer(int* _minute, int* _second, int* _mls, int* _lastTime){
 int _now=millis();
 *_mls+=(_now-*_lastTime);
 *_lastTime=_now;
 if(*_mls >= 1000){
  *_second-=(*_mls/1000); 
  *_mls%=1000;
  }
 if(*_second <= 0){
   if(*_minute == 0 & *_second < 0){
   	isTimer=false;
   	digitalWrite(led, HIGH);
   	delay(3000);
   	digitalWrite(led, LOW);
    *_second=0;
  }
   else if(*_minute>0){
    *_minute-=1;
   	*_second=59;
   }
 }
}



//////////****************STOPWATCH***************//////////
void stopwatch(){
  int hourStopwatch=0, minuteStopwatch=0, secondStopwatch=0, mlsStopwatch=0, lastTimeStopwatch=0;
  lcd.clear();
  
  while(true) 
  {
    lcd.setCursor(0,0);
  	lcd.print("Stopwatch");
  	lcd.setCursor(0,1);
  	if(hourStopwatch<10)lcd.print("0");
  	lcd.print(hourStopwatch);
  	lcd.print(":");
  	if(minuteStopwatch<10)lcd.print("0");
  	lcd.print(minuteStopwatch);
  	lcd.print(":");
  	if(secondStopwatch<10)lcd.print("0");
  	lcd.print(secondStopwatch);
    
   	btnstate1=digitalRead(pushbtn1);
  	btnstate2=digitalRead(pushbtn2);
  	btnstate3=digitalRead(pushbtn3);
  	btnstate4=digitalRead(pushbtn4);
    if(btnstate1==1){
      mode=0;
      delay(200);
      break;
    }
    if(btnstate2==1){
      isStopwatch=true;
      lastTimeStopwatch=millis();
      delay(200);
    }
    if(btnstate3==1){
      isStopwatch=false;
      delay(200);
    }
    if(btnstate4==1){
      isStopwatch=false;
   	  hourStopwatch=0;
      minuteStopwatch=0;
      secondStopwatch=0;
      delay(200);
    }
    if(isStopwatch)runningStopwatch(&hourStopwatch, &minuteStopwatch, &secondStopwatch, &lastTimeStopwatch, &mlsStopwatch);
 	runningClock(&hour, &minute, &second, &now, &lastTime, &mls, &flag);
  }
}

void runningStopwatch(int* _hour,int* _minute, int* _second, int* _lastTime, int* _mls){
 int increHour=0, _now; 
 _now=(millis());
 *_mls+=(_now-*_lastTime);
 *_lastTime=_now;

 if(*_mls >= 1000){
  *_second+=(*_mls/1000); 
  *_mls%=1000;
  }
 if(*_second >= 60){
   *_minute+=*_second/60;
   *_second%=60;
  }
 if(*_minute >= 60){
   *_hour=*_minute/60;
   	*_minute%=60;
  }
  if(*_hour>=12){
    isStopwatch=false;
  }
}


//////////****************COMMON FUNCTION***************//////////
void blink(int main_var, int X, int Y){
  lcd.setCursor(X, Y);
  	if(pis == 0){ 
  	  if(main_var<10)lcd.print("0");
  	  lcd.print(main_var);
  	  delay(200);
  	}
  	if(pis == 1){
 	  lcd.print("  ");
 	  delay(200);
    }
  	pis=(pis+1)%2;
}

//////////****************THANK YOU***************//////////

By changing the code. The code look like being a 24 hour clock.
Look for the code where hours > 12 are changed.

Look at the PM flag, if it is true add 12 to the hours.

Take care with that -- what happens after midnight?

How do I make it 24 hr clock?

Simply remove the code that converts the timekeeping 24 hour clock to 12 hour AM/PM for display.

1 Like

Midnight is AM, as is "after midnight"

AM is Ante meridiem
PM is Post meridiem

Ante means before. Post means after. Meridiem means middle (of day DIEM, not night! NOX). Say thank you for teaching you what years of school did not.

I understand. If one doesn't take care with the time math, 1 minute after midnight could be one of:

12:01  
24:01  
00:01

As I wrote on the Discord channel, the sketch is not good, not well structured, and has bugs (a single & in the if-condition). To improve the sketch, it has to be completely rewritten.

There are common and reliable ways for a clock with millis() and for the hour/minute/seconds. Those are not used. My millis_clock.ino shows one common way to do it, there are more.

Every second that you spent on that sketch and every second spent by others looking into that sketch is wasted time in my opinion.

1 Like

Your code is very simple and effective.
Thanks for sharing.
This was code I simply found and thought it was a great start to my project which is was.

If you're okay with it. I am trying to adapt your code to show on a 20x4 LCD I2C and also get the arduino to activate a relay at two certain time points.

I was able to get the arduino to show the time on the LCD. I then added the relay loop condition and the time counted was not accurate (I suspect this is because each loop the arduino is checking the relay condition).

Are you willing to provide some guidance on this?

The next step would be able to use button to change the time of the "current time" instead of placing in the Serial Monitor and also change the start and finish times. However, I consider these additional steps to be difficult to achieve with my current level of knowledge.

// ---------------------------------------------
// millis_clock.ino
// ---------------------------------------------
// License: The Unlicense, Public Domain.
// Author: Koepel
// 2019 march 20
// ---------------------------------------------
// 
// Run a clock with hours, minutes and seconds.
// The serial monitor is used for the output and
// for setting the time.
//
// The format is hh:mm:ss with 24 hours.
//
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4); 

//On Time and Off Time
int OnHour = 17;
int OnMin = 30;
int OnSec = 00;

int OffHour = 17;
int OffMin = 31;
int OffSec = 00;

int x = OffMin - OnMin;
int y = 0;
//On Time and Off Time

// Relay Pin Allocation
const int RELAY_PIN = 3;
int rrt = 2000;
int rdt = 5000;


unsigned long previousMillis;
const unsigned long interval = 1000;   // 1 second

int hours, minutes, seconds;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.begin(16, 2);
  
  Serial.begin( 9600);
  Serial.setTimeout( 100);    // 100ms timeout for serial input
  lcd.println( "Set the new time in hh:mm:ss format");

 
}

void loop()
{

 
  lcd.setCursor(4,0);
  unsigned long currentMillis = millis();
  
  if( Serial.available() > 0)
  {
    delay( 100);               // wait 100ms to get whole line
    int h, a, m, b, s;
    h = Serial.parseInt();    // get integer with timeout
    a = Serial.read();        // get character, no timeout
    m = Serial.parseInt();    // get integer with timeout
    b = Serial.read();        // get character, no timeout
    s = Serial.parseInt();    // get integer with timeout

    if( a == ':' && b == ':') // check for right format
    {
      hours   = constrain( h, 0, 23);
      minutes = constrain( m, 0, 59);
      seconds = constrain( s, 0, 59);
    }
    else
    {
      lcd.println( "New time not accepted");
      lcd.clear();
    }
    // Clear remaining characters from the serial input buffer.
    while( Serial.available() > 0)
    {
      Serial.read();
    }
  }

  if( currentMillis - previousMillis >= interval)
  {
    // When previousMillis would be set to currentMillis,
    // then a delay in the code would delay the clock.
    // When previousMillis is incremented with 1 second,
    // then it stays synchronized.
    previousMillis += interval;   // increment with 1 second

    seconds++;
    if( seconds >= 60)
    {
      seconds = 0;
      minutes++;
      if( minutes >= 60)
      {
        minutes = 0;
        hours++;
        if( hours >= 24)
        {
          hours = 0;
        }
      }
    }

    // Update the time to the serial monitor.
    // The format is  hh:mm:ss.
    // For example    09:30:55
       if( hours < 10)
      lcd.print( "0");
    lcd.print( hours);
    lcd.print( ":");
    if( minutes < 10)
      lcd.print( "0");
    lcd.print( minutes);
    lcd.print( ":");
    if( seconds < 10)
      lcd.print( "0");
    lcd.print( seconds);
    lcd.println();
    delay(1000);
    lcd.clear();


///// Relay On Code ///////////
  
if(hours == OnHour && minutes == OnMin && seconds == OnSec)
for (y= 0; y <x*60/7; y++)
{ digitalWrite(RELAY_PIN, HIGH);
 delay(rrt);
digitalWrite(RELAY_PIN, LOW);
 delay(rrt);
 }
 {
  delay(rdt);
digitalWrite(RELAY_PIN, LOW);
}
   ///// Relay Code On Code /////
   
  }
}

That example is from my Fun with millis examples. You can also try every example in Wokwi with the green button.

Running a clock and then waiting in a delay for more than 1 second disturbs the clock. The clock will catch up with a burst, so eventually it will stay in sync with the time, but it is not nice.
You have to use millis() to keep everything running smooth. Start here: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay.

When writing code, please make the text layout look good. Put every space, every comma, every indent at the right place and use meaningful names for the variables. You do that for yourself, not for me. When the text is a mess, then the sketch will not work well. A good sketch shows what is going on with the first glance at the code.

Do you have an example of code that is a good layout?
Again, your advice is much appreciated.

What should it do ?

With the "text layout", I mean this:

A big mess:

if(hours == OnHour && minutes == OnMin && seconds == OnSec)
for (y= 0; y <x*60/7; y++)
{ digitalWrite(RELAY_PIN, HIGH);
 delay(rrt);
digitalWrite(RELAY_PIN, LOW);
 delay(rrt);
 }
 {
  delay(rdt);
digitalWrite(RELAY_PIN, LOW);
}
   ///// Relay Code On Code /////
   
  }

Better:

  if(hours == OnHour && minutes == OnMin && seconds == OnSec)
  {
    for(y=0; y<x*60/7; y++)
    { 
      digitalWrite(RELAY_PIN, HIGH);
      delay(rrt);
      digitalWrite(RELAY_PIN, LOW);
      delay(rrt);
    }
    {
      delay(rdt);
      digitalWrite(RELAY_PIN, LOW);
    }
    ///// Relay Code On Code /////
  }

The code is not okay, but at least it is readable and bugs can be spotted easier.

Mine goes to zero for midnight and hear midnight starts AM and noon starts PM. The PM flag is true from noon to midnight. Try using this as a search term: "when does am and pm change" . It will tell you:" The American Heritage Dictionary of the English Language states "By convention, 12 AM denotes midnight and 12 PM denotes noon."

If it is a 12 hour AM/PM clock, it would go from 11 to 12 at midnight, and then from 12 to 1 at 1:00AM.

Never is there a 24:01.

Never should there be a 24:01, but if you are sloppy parsing HH:MM AM/PM you can get that output.

If you use this rule on times from a 12 hour clock, then at one minute past noon, you can get 24:01.

Yes, more accurate.