Hello. I tried to do a basic countdown timer, that shows output on LCD. This is the code
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int SSB = 6;// StartStop button
const int RB = 7;// Reset button
const int PB= 8;//Setup button
int StartStop=0;
int Reset=0;
int Setup=0;
int htime=0, mtime=0, stime=0; // variables for hours, minutes and seconds
void setup()
{
lcd.begin(20, 4);
lcd.print("Countdown timer");
lcd.setCursor(2,1);
lcd.print(":");//printing separation marks
lcd.setCursor(5,1);
lcd.print(":"); //printing separation marks
pinMode(SSB, INPUT);
pinMode(RB, INPUT);
pinMode(PB, INPUT);
}
void loop()
{
Reset=digitalRead(RB);
delay(50);
if (Reset == HIGH){htime=0; mtime=0; stime=0;}//if reset is pressed all time variables go to 0
lcd.setCursor(6, 1);//used to print all zeros on LCD
lcd.print(stime);//used to print all zeros on LCD
lcd.setCursor(3, 1);//used to print all zeros on LCD
lcd.print(mtime);//used to print all zeros on LCD
lcd.setCursor(3, 1);//used to print all zeros on LCD
lcd.print(htime);//used to print all zeros on LCD
StartStop=digitalRead(SSB);//if start is presed program goes to count function
delay(50);
if(StartStop == HIGH){count;}//if start is presed program goes to count function
Setup=digitalRead(PB);
delay(50);
if (Setup==HIGH)//if setup is pressed stime is incremented.
{
lcd.setCursor(6, 1);
stime++;
lcd.print(stime);
if (stime>=60) //after stime reaches 60 seconds it should increment mtime, reset stime to 0 and start counting again.
{
stime==0;
lcd.setCursor(3, 1);
mtime++;
lcd.print(mtime);
if (mtime>=60)
{
mtime=0;
lcd.setCursor(3, 1);
htime++;
lcd.print(htime);
}
}
}
}
void count()// count function
{
do
{
do
{
do
{
lcd.setCursor(6, 1);
stime--;//program enters this do-while loop and decrement stime to 0 and then mtime, and htime
lcd.print(stime);
delayMicroseconds(16667);//specific delay because I need it to go faster then seconds
if(StartStop == HIGH) {loop;}//if startstop button is pressed program jumps to loop -> changed "loop" to "return"
if (Reset == HIGH){htime=0; mtime=0; stime=0; loop;};//resets time variables and jumps to loop-> changed "loop" to "return"
}while(stime>=0);
lcd.setCursor(3, 1);
mtime--;
if (mtime>0){stime=60;}// added this line. count shoud be countdown timer with specific time
lcd.print(mtime);
}while(mtime>=0);
lcd.setCursor(3, 1);
//lcd.print(htime);
htime--;
if (htime>0){mtime=60;}// added this line. count shoud be countdown timer with specific time
lcd.print(htime);
}while(htime<=0);
}
My problem is in loop, where stime should be reseted it keeps counting to 61, 62, and further. Also reset and startstop doesn't work. I tested button they are connected properly, and LCD works.
One of these two statements is wrong. If the switches are wired correctly, the they should work. That they don't means that the switches are not wired correctly.
It is far easier to connect one side of the switch to ground, and the other side to a digital pin, and turn on the pullup resistor, than it is to deal with external pullup or pulldown resistors.
Thanks for the quick reply. Buttons work, i tested it in different code, where i count every time i press it. They are not disconnected or anything. I just realized that reset works, but because of LCD i thought it doesn't work(LCD resets first number, and when coundown reaches next digit it overwrite the previous.) There is still problem with StartStop
if(StartStop == HIGH) {loop;}//if startstop button is pressed program jumps to loop
This isn't how to call a function. Even if it were, you should NEVER call loop() from another function. Learn to use return or break statements.
A do/while loop is executed at least once. In some cases, that is one too many times. A while statement is executed at least zero times. In most cases, that is a better minimum number of times.
// Comments are a good thing. There is nothing to explain what the oddball count() function is doing. Or, is supposed to do.
I'm new at this so some mistakes are expected I changed the count so it doesn't use loop, but return. Count function should count backward to 0, from the previusly set variables htime, mtime and stime. I will edit my first post to comment that. thx
even with many years experience these kind or typos slip through.
Furthermore your code is not structured in layout. Good layout helps creating readable code.
Good variable names help too.
Here a partially code that is more structured to get started.
Not all details are filled in, but you should be able to fix those
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int SSB = 6; // StartStop button
const int RB = 7; // Reset button
const int PB = 8; //Setup button
int StartStop = 0;
int Reset = 0;
int Setup = 0;
int hours = 1;
int minutes = 2;
int seconds = 20;
unsigned long lastSecond;
int running = 0; // state of the timer 0 = idle 1 = running ...
void setup()
{
lcd.begin(20, 4);
lcd.print("Countdown timer");
lcd.setCursor(2,1);
lcd.print(":"); //printing separation marks
lcd.setCursor(5,1);
lcd.print(":"); //printing separation marks
pinMode(SSB, INPUT);
pinMode(RB, INPUT);
pinMode(PB, INPUT);
lastSecond = millis();
}
void loop()
{
// MAKE THE MEASUREMENTS
int startstop = digitalRead(SSB);
int reset = digitalRead(RB);
int setup = digitalRead(PB);
unsigned long now = millis();
// DO THE MATH
if (reset == HIGH)
{
hours = 0;
minutes = 0;
seconds = 0;
return; // loop will automatically be called again after return
};
if ( startstop == HIGH )
{
// fix the start stop state here
running = 1;
}
if (running == 1)
{
// adjust the seconds minutes and hours here when a second has passed.
// tip: look at blink without delay for timing
// tip use the var lastsecond
}
// DISPLAY THE RESULTS
lcd.setCursor(0, 1);
lcd.print(hours);
lcd.setCursor(3, 1);
lcd.print(minutes);
lcd.setCursor(6, 1);
lcd.print(seconds);
}
Thank allot, this is a great reference. Trouble is that this is my school assingment, and is very specific. Time must be fastened. I real second my timer must count 60 seconds. Thats why i tried using delaymicros.
After 8 hours of working i was able to make my program work. There were many mistakes, mostly in coding. Every thing works great except when counting startstop button won't go to loop: If anybody have some sugestions would be most appreciated. The problematic part is commented, its in "count" function.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int SSB = 6;
const int RB = 7;
const int PB= 8;
int StartStop=0;
int Reset=0;
int Setup=0;
int htime=1, mtime=58, stime=54;
void setup()
{
Serial.begin(9600);
lcd.begin(20, 4);
lcd.print("Count");
lcd.setCursor(3,1);
lcd.print(":");
lcd.setCursor(7,1);
lcd.print(":");
pinMode(SSB, INPUT);
pinMode(RB, INPUT);
pinMode(PB, INPUT);
}
void loop()
{
delay(100);
Reset=digitalRead(RB);
delay(50);
if (Reset == HIGH){htime=0; mtime=0; stime=0;}
lcd.setCursor(9, 1);
lcd.print(stime);
lcd.setCursor(5, 1);
lcd.print(mtime);
lcd.setCursor(1, 1);
lcd.print(htime);
StartStop=digitalRead(SSB);
delay(50);
if(StartStop == HIGH){count();}
Setup=digitalRead(PB);
delay(50);
if (Setup==HIGH)
{
lcd.setCursor(9, 1);
stime++;
lcd.print(stime);
Serial.print(stime);
if (stime>=60)
{
stime=0;
lcd.setCursor(5, 1);
mtime++;
lcd.print(mtime);
Serial.print(mtime);
if (mtime>=60)
{
mtime=0;
lcd.setCursor(1, 1);
htime++;
lcd.print(htime);
Serial.print(htime);
}
}
}
}
void count()
{
do
{
do
{
do
{
StartStop=digitalRead(SSB);
delay(10);
if(StartStop == HIGH) {loop();} //this thing here for some reason won't work
Reset=digitalRead(RB);
if (Reset == HIGH){ htime=0; mtime=0; stime=0; loop();}; //reset works, but jump to loop won't
delay(10);
lcd.setCursor(9, 1);
stime--;
lcd.print(stime);
Serial.print(stime);
//delay(16);
}while(stime>0);
lcd.setCursor(5, 1);
mtime--;
lcd.print(mtime);
Serial.print(mtime);
if (mtime>0){stime=60;}
}while(mtime>0);
lcd.setCursor(1, 1);
htime--;
lcd.print(htime);
Serial.print(htime);
if (htime>0){mtime=60;}
}while(htime>=0);
}
I have tried to use return but it stops the program for a moment then continues. Like i said i'm new to this. I could rewrite it to while loops but, if you could write specific line to exit count() it would be helpfull. I have tried return, break, even goto but nothing seems to work
Well, in the interest of indirect help see if this makes any sense to you.
TIme has been scaled per your earlier statement of 1 second equals 1 minute (or so I interpreted it as - if not change the value of 'ONE_SECOND').
const unsigned long ONE_SECOND = 16UL;
const unsigned long ONE_MINUTE = 60 * ONE_SECOND;
const unsigned long ONE_HOUR = 60 * ONE_MINUTE;
unsigned long msTarget;
unsigned long hms2millisecs(uint8_t const hours, uint8_t const minutes, uint8_t const seconds)
{
return ((hours * ONE_HOUR) + (minutes * ONE_MINUTE) + (seconds * ONE_SECOND));
}
void millisecs2hms(unsigned long milliseconds, uint8_t* hours, uint8_t* minutes, uint8_t* seconds)
{
uint8_t h = milliseconds / ONE_HOUR; milliseconds -= h * ONE_HOUR; *hours = h;
uint8_t m = milliseconds / ONE_MINUTE; milliseconds -= m * ONE_MINUTE; *minutes = m;
uint8_t s = milliseconds / ONE_SECOND; milliseconds -= s * ONE_SECOND; *seconds = s;
}
void loop()
{
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
long remaining = msTarget - millis();
millisecs2hms(remaining, &hours, &minutes, &seconds);
Serial.print((short)hours);
Serial.print(":");
Serial.print((short)minutes);
Serial.print(":");
Serial.println((short)seconds);
if ( remaining <= 0 )
{
// we've reached zero time
while (true)
{ }
}
}
void setup()
{
Serial.begin(9600);
msTarget = millis() + hms2millisecs(1, 50, 54); // hours, minutes, seconds
}