Counter not displaying properly on LCD

Hello All,

I am trying to have a counter display on an LCD so that one knows how long to wash their hands for. The problem I am having is that the counter will appear 4 times in the LCD instead of one as I have commanded it to. Any ideas of what could be wrong?

code:

// defines pins numbers
const int servo = 9;
const int trigPin = 10;
const int echoPin = 11;
const int rs = 1, en = 2, d4 = 4, d5 = 5, d6 = 6, d7 = 7;

// defines variables
long duration;
int distance;
int StartTimer;
int Timing;
int TimeStart;
int Timer;
int TimeNow;

#include <Servo.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
Servo myservo;  // servo object to control a servo
int pos = 0;    // stores the servo position
char timeline[16];

void setup() {
  lcd.begin(16, 2);
  lcd.print("Soap_Dispenser1");
  delay(3000);
  lcd.setCursor(0, 0);
  lcd.print("Stop The Spread");
  lcd.setCursor(0, 1);
  lcd.print("Wash Your Hands");
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  myservo.attach(servo);  // attaches the servo on pin 9 to the servo object
  myservo.write(0);   // Sets Servo to initially 0 degrees
  Serial.begin(9600); // Starts the serial communication
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH); // Sets the trigPin on HIGH state for 10 micro seconds
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH); // Reads the echoPin, returns the sound wave travel time in microseconds
  distance = duration * 0.034 / 2; // Calculating the distance
  Serial.print("Distance: "); // Prints the distance on the Serial Monitor
  Serial.println(distance);

  if (distance < 10) { //Check distance is less than 10cm
    myservo.write(45);
    delay(100);
    myservo.write(90);
    delay(100);
    myservo.write(135);
    delay(100);
    myservo.write(180);
    delay(100);
    myservo.write(0); // Reset the servo to 0 Degrees
    delay(2000);

    StartTimer = 1;
    Timing = 1;

    //StartTimer
    while (Timing == 1)
    {
      if (StartTimer)
      {
        TimeStart = millis(); // capture time at start of timer
        StartTimer = 0;
      }
      else
      {
        TimeNow = millis();
        Timer = (TimeNow - TimeStart) / 1000; // diff in start time and now is time for timer
        lcd.setCursor(0, 0);
        sprintf(timeline, "%0.2d Secs", Timer);
        lcd.print(timeline);
      }
      if (Timer > 30.0) {
        Timing = 0;
      }
    }
  }
}

It appears that it can perform this block:

        TimeNow = millis();
        Timer = (TimeNow - TimeStart) / 1000; // diff in start time and now is time for timer
        lcd.setCursor(0, 0);
        sprintf(timeline, "%0.2d Secs", Timer);
        lcd.print(timeline);

multiple times until the value of Timer reaches 30.

When (or how often) do you want it to print a value to the LCD ?

Move the things you only want to do once outside the loop…

    //StartTimer
    TimeStart = millis(); // capture time at start of timer
    do
    {
        TimeNow = millis();
        Timer = (TimeNow - TimeStart) / 1000; // diff in start time and now is time for timer
        lcd.setCursor(0, 0);
        sprintf(timeline, "%0.2d Secs", Timer);
        lcd.print(timeline);
    }
    while(Timer < 30);

A lot cleaner.

Also, if you want your time to include decimals, you’ll need to make the Timer variable and calculation a floating point type. Your current choice of int won’t cut it.

Plus the return type for millis() is unsigned long, and you are only storing in an int which can result in truncation errors. By luck more than judgement, for a 30 second timer you may just get away with it as it’s less than 32767ms. Personally I wouldn’t risk it and would always use unsigned long for millis() values and calculations.