Stopwatch with LCD screen

Hello everyone,

I’m working on a timer or clock, but I’m having trouble with the code I have so far. What I imagined this code would do is count up a second every second and display it on the screen. Every time it hits 60 seconds, I’d add a minute to the minute counter and reset the seconds to zero, just like any old stopwatch. I tried uploading this to see if things worked so far, but all I see are white spaces on the top row of my LCD screen.

I know it isn’t a wiring issue because I can upload the Hello World sketch just fine.

The code:

#include <LiquidCrystal.h>

int seconds = 0;
int prevsecstate = 0;

int minute = 0;
int prevminstate = 0;

int hours = 0;
int prevhourstate = 0;

unsigned long previousMillis = 0;
const long timer = 1000;

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

void setup() {

  lcd.begin(16, 2);
  lcd.clear();

  lcd.print("clock");
  delay(1000);
  lcd.clear();
  
}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= timer) {

    prevsecstate = seconds;
    seconds = prevsecstate + 1;

    lcd.setCursor(7, 0);

    if (seconds < 10) {

      lcd.print("0");
      lcd.print(seconds);

    } 
    
    else {

      lcd.print(seconds);

    }

  } 
  
  else {
    
  }

  if (seconds == 60) {

    seconds = 0;

    minute = prevminstate + 1;
    lcd.setCursor(4, 0);  
    
    if (prevminstate < 10) {
      
      lcd.print("0");
      lcd.print(minute);
      
    } 
    
    else {

      lcd.print(minute);
      
    }

    lcd.setCursor(6, 0);
    lcd.print(":");
    
  }

}

any assistance would be greatly appreciated. Thanks!

marco

I know it isn't a wiring issue because I can upload the Hello World sketch just fine.

So what is different in your sketch ? Checking the pins used in creating the LCD instance would be the first step.

UKHeliBob:
So what is different in your sketch ? Checking the pins used in creating the LCD instance would be the first step.

What do you mean? The pin connections aren't the issue. If other sketches work with it, than we know it isn't that, right?

Where does previousMillis get updated?

ahh, oops! It should be right here, correct?

unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= timer) {

    previousMillis = currentMillis; // added here

    prevsecstate = seconds;
    seconds = prevsecstate + 1;

    lcd.setCursor(7, 0);

try like this…

#define USING_SERIAL

#ifdef USING_SERIAL

#else
//#include <LiquidCrystal.h>
#endif

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(0, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}

Comment out the first line to display to your LCD.

BulldogLowell:
try like this…

#define USING_SERIAL

#ifdef USING_SERIAL

#else
//#include <LiquidCrystal.h>
#endif

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print(“clock”);
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = “”;
    snprintf(currentTime, sizeof(currentTime), “%02d:%02d:%02d”, hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(0, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}




Comment out the first line to display to your LCD.

Thank you very much for your response!

I got it to work with the serial monitor, but I had no luck displaying it on the LCD screen. Also, I’ll be perfectly honest saying I have no idea what #else ,#endif, and #ifdef means. I guess I have some reading to do :slight_smile:

chummer1010:
Thank you very much for your response!

I got it to work with the serial monitor, but I had no luck displaying it on the LCD screen. Also, I'll be perfectly honest saying I have no idea what #else ,#endif, and #ifdef means. I guess I have some reading to do :slight_smile:

comment out his line and it should work on your lcd:

#define USING_SERIAL

like this:

//#define USING_SERIAL
/////////////////////////////////
// #define USING_SERIAL

#ifdef USING_SERIAL

#else
#include <LiquidCrystal.h>
#endif

////////////////////////////////

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(0, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}

no luck.

chummer1010:
no luck.

#define USING_SERIAL

#ifdef USING_SERIAL

#else
#include <LiquidCrystal.h>  // also had to uncomment here!!
#endif

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(4, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}

BulldogLowell:

#include <LiquidCrystal.h>  // also had to uncomment here!!

I did! I’m running this code:

//#define USING_SERIAL

#ifdef USING_SERIAL

#else
#include <LiquidCrystal.h>
#endif

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(4, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}

Is there a change we need to make elsewhere?

chummer1010:
I did! I’m running this code:

//#define USING_SERIAL

#ifdef USING_SERIAL

#else
#include <LiquidCrystal.h>
#endif

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

#ifdef USING_SERIAL

#else
LiquidCrystal lcd(12, 11, 9, 8, 7, 6);
#endif

void setup()
{
#ifdef USING_SERIAL
  Serial.begin(9600);
#else
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print(“clock”);
  delay(1000);
  lcd.clear();
#endif
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = “”;
    snprintf(currentTime, sizeof(currentTime), “%02d:%02d:%02d”, hours, minute, seconds);
#ifdef USING_SERIAL
  Serial.println(currentTime);
#else
    lcd.setCursor(4, 0);
    lcd.print(currentTime);
#endif
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}




Is there a change we need to make elsewhere?

what’s happening or not happening?

try without any compiler directives… i cannot edit, I’m on an iPhone!

perhaps this:

#include <LiquidCrystal.h>

byte seconds = 0;
//int prevsecstate = 0;

byte minute = 0;
//int prevminstate = 0;

byte hours = 0;
//int prevhourstate = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
}

void loop()
{
  if (millis() - previousMillis >= oneSecond)
  {
    seconds++;
    if(seconds > 59)
    {
      minute++;
      seconds = 0;
    }
    if(minute > 59)
    {
      hours++;
      minute = 0;
    }
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
    Serial.println(currentTime);
    lcd.setCursor(4, 0);
    lcd.print(currentTime);
    //prevsecstate = seconds;
    previousMillis += oneSecond;
  }
}
#include <LiquidCrystal.h>

byte seconds = 0;
byte minute = 0;
byte hours = 0;

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

void setup() {
  
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("clock");
  delay(1000);
  lcd.clear();
  
}

void loop() {
  
  if (millis() - previousMillis >= oneSecond) {
    
    seconds++;
    if(seconds > 59) {
      
      minute++;
      seconds = 0;
      
    }
    
    if(minute > 59) {
      
      hours++;
      minute = 0;
      
    }
    
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
    Serial.println(currentTime);
    lcd.setCursor(4, 0);
    lcd.print(currentTime);
    previousMillis += oneSecond;
  }
}

Nope. But I did clean the code a little and got rid of those un needed ints

chummer1010:
Nope. But I did clean the code a little and got rid of those un needed ints

Well you are going to have to describe a bit what is/is not happening!!!

you can try to change this:

lcd.setCursor(4, 0);

to this

lcd.setCursor(0, 0);

can you get anything to print to lcd?

Oh, sorry, I didn't see your other post.

I ran the hello world sketch and that works fine. When I upload this one, the first 8 boxes on the top turn white, and everything else freezes.

I re-upload the hello world sketch which yet again works fine.

I ran the hello world sketch and that works fine. When I upload this one, the first 8 boxes on the top turn white, and everything else freezes.

In the stock Hello World demo the LCD is initialised like this

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

In your program it is initialised like this

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

How is the LCD actually connected to your Arduino ?

UKHeliBob:
In the stock Hello World demo the LCD is initialised like this

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

In your program it is initialised like this

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

How is the LCD actually connected to your Arduino ?

Bingo! I just had to change that to (12, 11, 5, 4, 3, 2);

Thanks for the help both of you!

chummer1010:
Bingo! I just had to change that to (12, 11, 5, 4, 3, 2);

Thanks for the help both of you!

Actually, that solution was offered in reply #1.

aarg:
Actually, that solution was offered in reply #1.

i misunderstood the comment, i guess. my bad!

I’m working on modifying my code where a button resets the timer. The layout and timer works, but there are a few issues:

  1. I have (attempted) to make it so there would be a correct label depending on if the timer is at seconds, minutes, or hours, but it only displays ‘secs’ ago even when a minute passed. (i have made notes where I attempted this)

  2. The button does not reset the timer. I thought by just setting all the values back to zero when the button was pressed, that would do the trick. I guess not.

Here is the code with notes on whats going wrong:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

unsigned long previousMillis = 0;
const long oneSecond = 1000UL;

int seconds = 0;
int minute = 0;
int hours = 0;

int button = 7;

void setup() {

  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(button, INPUT_PULLUP);

}

void loop() {

  int buttonState = digitalRead(button);
  
  if (millis() - previousMillis >= oneSecond) {

    seconds++;

    if (seconds < 60) {

      lcd.setCursor(8, 1);
      lcd.print("secs ago"); // label for seconds
      
    }
    
    else if (seconds > 59) {

      minute++;
      seconds = 0;

      lcd.clear();
      lcd.setCursor(8, 1);
      lcd.print("mins ago"); // label for minutes

    }

    else if (minute > 59) {

      hours++;
      minute = 0;
      
      lcd.setCursor(8, 1);
      lcd.print("hrs ago"); // label for hours

    }

    lcd.setCursor(0, 0);
    lcd.print("  Last Clicked");
    
    char currentTime[10] = "";
    snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", hours, minute, seconds);
    Serial.println(currentTime);
    lcd.setCursor(0, 1);
    lcd.print(currentTime);

    previousMillis += oneSecond;

///////////////////////////////////////////SEE HERE //////////////////////////////////////////// 
    if (buttonState == LOW) { // if reset button is pressed
      
      seconds = 0; // set all values back to zero
      minute = 0;
      hours = 0;

      
    }


  }
}

Thanks for the help and my apologies for not seeing simple issues right away!

marco