I am a total beginner but I have finished the arduino projects book that came with the arduino kit and have finished a few projects of my own...
... so I am embarrassed to not figure out how to make the simplest stopwatch.
I understand the basic concept.
I must use the millis() function for START, the millis function for STOP and I can get the elapsed time from STOP - START.
With code borrowed from the internet I was able to get the serial monitor to display the START and STOP time difference... but only once after pressing STOP.
I have a 4 digit 7 segment display... after pressing START, I want the display to start running the seconds. Basically displaying a new calculated value every 10 ms.
So the display would show 37.22 > 37.23 > 37.24 ... two decimal places for seconds.
Until I press the STOP button. Then I want the display to show the time that was on the clock at the moment of pressing.
Can anyone write me pseudo code on how to achieve this.
Display "0000" until I press START
Count the time until I press STOP
Display the time when I pressed STOP
Press STOP again to make the display show "0000" again.
I don't know how to do it... if statement inside an if statement... or loop in a loop... please help.
You need to keep a second millis() based timing for the display update.
if current time minus last display update time gte 1 second
update last display update time to current time
display current time minus start time
endif
You have done well if you have learned millis()timing. (blink without delay).
Now you need to look at a few more of the example sketches included in the IDE:
file>>examples>>
02.Digital
Button
Debounce
StateChangeDetection
05.Control
IfStatementConditional
SwitchCase
The first 2 show how to use a button.
The last 3 introduce the concept of a "state machine" which is how a computer makes decisions.
So to answer your question, Yes a nested if or a switch statement is the correct answer.
You dont want a loop as it will block like delay does. Hint: you already have a loop it's called void Loop() use it.
Create a global flag called RUNNING and set it to false.
Create a global variable to store the display time. Set it to 0.
Repeat forever:
Read, debounce, and look for a change from un-pushed to pushed for the START
If START was just pressed:
if RUNNING is false
Record the StartTime
Set RUNNING to true.
Read, debounce, and look for a change from un-pushed to pushed for the STOP button
If STOP was just pressed:
if RUNNING is true
Set RUNNING to false.
Set the display time to NOW minus the start time.
else
Set the display time to zero
if RUNNING is true
Set the display time to NOW minus the start time.
Thank you for the example, it works like intended... but...
After a few start timer > stop timer > reset to "0" it will start reading up from 65 seconds.
I am guessing its 2^16 = 65536 ms... but I have no idea where it could come from.
Edit. I guess its because I defined the START as Integer.
I defined it as long and the problem seemed to go away.
Also... I don't think I do the debounce thing correctly. The timer obviously starts to run after the debounce delay. But this makes my timing off by 200ms.
I mean I don't really need debounce for the START button... Nothing happens if I were to press it twice... whereas for the STOP button... if I press it once it shows the stopped time... if I press it again, it will ZERO the clock.
And if I double press the STOP button I loose the time that was displayed and get ZERO immediately.
To keep the button from repeating you need to check for a CHANGE in the position of the button. If you don't do that, delay() will only set the repeat rate for the buttons. Here is my preferred way to debounce buttons:
const byte StartButtonPin = 2;
bool StartButtonLastState = false;
const byte StopButtonPin = 3;
bool StopButtonLastState = false;
unsigned long LastButtonStateChangeTime = 0;
unsigned long StartTime = 0;
unsigned long ElapsedTimeForDisplay = 0;
bool Running = false;
void setup()
{
pinMode(StartButtonPin, INPUT_PULLUP); // Active Low
pinMode(StopButtonPin, INPUT_PULLUP); // Active Low
}
void loop()
{
unsigned long currentMillis = millis();
bool startButtonPressed = digitalRead(StartButtonPin) == LOW; // Active Low
bool stopButtonPressed = digitalRead(StopButtonPin) == LOW; // Active Low
if (startButtonPressed != StartButtonLastState && currentMillis - LastButtonStateChangeTime > 20)
{
// State has changed but not by bounce
LastButtonStateChangeTime = currentMillis;
if (startButtonPressed)
{
// State has changed from unpressed to pressed
if (!Running)
{
StartTime = currentMillis;
Running = true;
Serial.println("Started...");
}
}
}
if (stopButtonPressed != StopButtonLastState && currentMillis - LastButtonStateChangeTime > 20)
{
// State has changed but not by bounce
LastButtonStateChangeTime = currentMillis;
if (stopButtonPressed)
{
// State has changed from unpressed to pressed
}
}
if (Running)
{
ElapsedTimeForDisplay = currentMillis - StartTime;
}
// Display "ElapsedTimeForDisplay" here
}