Counter on LCD display

Hello, I am having a problem programming a counter that can be reset to 0 to be displayed on my LCD. The counter works fine when it is still in its one's digit, but once it reaches 2 digits and I reset the counter, there is a problem. When it reaches 2 digits, for example 10, the LCD keeps the second digit, meaning that when I restart my counter, it reads 10, 11, 12... . Elaborating on the problem, when I stop the counter at 11, it holds the 1 digit. This means that when I restart the count, it displays 11, 21, 31 and so on. This is my code as for now.

#include<Wire.h>
#include<LiquidCrystal_I2C.h> //Including library for LCD that is connected to an I2C device
LiquidCrystal_I2C lcd1 (0x27, 16, 2); //Defining the LCD's I2C address, and size

enum class States { // Assigns names to a set of numbers starting at 0.
WaitForButtonPress,
ButtonChecks,
SwitchOnMotor,
MotorOnPeriod,
SwitchOffMotor,
MotorOffPeriod,
}
currentState; // these constants are used for this variable named "currentState"

enum class counts{
Shows,
Waits,
}
currentvalues;

bool codestart = false; //used to only start motor code when button has been released
const unsigned long firstmotorOffPeriod = 6000; //the initial 4 days that the motor is off (in milliseconds), make cost if variable never changes
const unsigned long motorOnPeriod = 2000; // how long should the motor be on (in milliseconds), make const if variable never changes
const unsigned long motorOffPeriod = 4000; // how long should the motor be Off (in milliseconds), make const if variable never changes
const unsigned long DayDelay = 2000; //the delay to update the day value

void setup() {
Serial.begin(9600); //rate in milliseconds that arduino sends info to serial monitor
lcd1.begin(); //starting up LCD display
lcd1.backlight();
pinMode(buttonPin, INPUT_PULLUP); //Button pin is an input device, and will atomatically pull
up its state
pinMode(LED, OUTPUT); // LED pin is an output
pinMode(motor, OUTPUT); // Motor pin is an output
currentState = States::WaitForButtonPress; //Setting the current state for the enum function
digitalWrite(LED, LOW); //LED's state is initially always LOW
digitalWrite(motor, LOW); //Motor's state is initially always LOW

void loop() {
motordelay(); // the state machine called inside the loop to run the relay/motor
DayLCD(); //the state machine called inside the loop to print the number of days and number of loops
}

void motordelay() {
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0; // timestamp when the current State was started, as these variables must survive after the end of the function, they are declared as static

// this is the state-machine based on the switch-case-statement
// depending on the value of variable "currentState" only the commands
// below one "case" gets executed

switch (currentState) {
case States::WaitForButtonPress:
// a state that waits for an external input to occur
if (digitalRead(buttonPin) == LOW) {
previousMillis = currentMillis;
codestart = true;
}
if(codestart){
if (currentMillis - previousMillis >= firstmotorOffPeriod) {
codestart = false;
currentState = States::SwitchOnMotor;

  }
  }
  break;

case States::ButtonChecks:
  if(digitalRead(buttonPin) == HIGH) {
    currentState = States::SwitchOnMotor;
  }
  else{
    CountRounds = 0;
    currentState = States::WaitForButtonPress;
  }
  break;
  
case States::SwitchOnMotor:
  // a state that does an action repeatedly 
  digitalWrite(LED, HIGH);
  digitalWrite(motor, HIGH);
  CountRounds++;
  Serial.println(CountRounds);
  previousMillis = currentMillis;
  currentState = States::MotorOnPeriod;
  break;

case States::MotorOnPeriod:
  if (currentMillis - previousMillis >= motorOnPeriod) {
    currentState = States::SwitchOffMotor;
  }
  break;

case States::SwitchOffMotor:
  // a state that does an action just ONE time
  digitalWrite(LED, LOW);
  digitalWrite(motor, LOW);
  previousMillis = currentMillis;
  currentState = States::MotorOffPeriod;
  break;

case States::MotorOffPeriod:
  // a state that waits for a timePeriod to pass by
  if (currentMillis - previousMillis >= motorOffPeriod) {
    currentState = States::ButtonChecks;
  }
  break;

}
}

void DayLCD() {
unsigned long currentMillis = millis();
static unsigned long prev = 0;

switch(currentvalues) {
case counts ::Shows:
Serial.print("No. of turns: ");
Serial.print(CountRounds);
lcd2.setCursor(0,0);
lcd2.print(" No.of turns: ");
lcd2.print(CountRounds);
lcd2.setCursor(0,1);
prev = currentMillis;
currentvalues = counts::Waits;
break;

case counts::Waits:
if(currentMillis - prev >= DayDelay) {
Serial.println("Waiting for days");
currentvalues = counts::Shows;
 }
 break;
 
}  

}

Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".

This will tell you how to present your code in a scrolling window.

Your problem is probably due to you over writing on the LCD.
Before you write to a place on the LCD, write blank spaces, then when you write your new data the old data will have gone.

Thanks... Tom.. :grinning: :+1: :coffee: :australia:

Hi Tom, understood about the scrolling down window, will do so from now on. Can I ask, what do you mean by 'before you write to a place on the LCD, write blank spaces'?

Thank you so much for your help. :slight_smile:

Hi,

lcd2.setCursor(0,0);
lcd2.print(" No.of turns: ");
lcd2.print(CountRounds);

Basically for example and simply.

lcd2.setCursor(0,0);
lcd2.print(" No.of turns: ");
lcd2.print("  "); //  two blank spaces assuming CountRounds is a max of two figures, 
lcd2.setCursor(0,0);
lcd2.print(" No.of turns: ");
lcd2.print(CountRounds);

You can also only update the data if it changes as well.

Hope this helps.. Tom... :grinning: :+1: :coffee: :australia:

Hi Tom, I understand what you mean now. Thank you for your quick replies! I have tried the code out and it works, thankyou so much!
Could you explain why the 2 spaces helps to reset the data at those 2 spaces? Also, could you explain why you printed "No. of turns" twice, both set at cursor 0,0?

Common problem. The LCD puts the characters you print in the display and they stay there until you print a different character in the same place.

Write blanks over the area of the display where you are going to put your number or print some blanks after you print your number to cover old digits left in the display.

Hi,
I printed number of turns twice just to make it simple to see what I have done.
Printing 2 blank spaces, erases the figures that were there before, your new data then prints over blank figures.
You could just move the cursor across and print the blank spaces.

Tom... :grinning: :+1: :coffee: :australia: