I did a countdown timer with a 7 segment display and pot for a setpoint as an exercise some time ago. The code can be found in the code repository in my signature below. You may be able to use parts of that code to do what you need.
I agree with the others. If you need to use a goto you should probably look at restructuring your code so that you don't need it. It makes the code hard to follow and maintain.
// ***********************************************************************************************
// Loop here endlessly, checking if time or score needs updating, if wireless message came in,
// if touch lights are on
// ***********************************************************************************************
void loop()
{
// check if time needs updating
if ((time_running == 1) || (time_running == 2)) // fencing time is counting down or delay time is counting down
{
unsigned long currentMillis = millis(); // see how long its been
if (currentMillis - previousMillis >= interval) // more than our quarter second interval?
{
// save the last time we okayed time updates
previousMillis = currentMillis;
quarter_interval = quarter_interval+1;
// cycle the colon state
if (colon == 0x80)
{
colon = 0x00;
}
else
{
colon = 0x80;
}
update_time = 1; // enable time display to be updated
if (quarter_interval == 4) // we hit the one second update time
{
quarter_interval = 0;
// update the time digits
// cases:
// 0:01, final second - stop time, disable touch lights, sound buzzer
// Tens of seconds rollover: time = x:50, x:40, x:30, x:20, x:10: decrement tens of seconds, rollover seconds to 9
// Minutes rollover: time = 9:00, 8:00, etc. 2:00, 1:00: decrement ones of minutes, rollover tens of
// seconds to 5, ones of seconds to 9
// 10:00: Roll all the digits over
// otherwise: just roll over the seconds
// Case: Final Second
if ((minutes_ones == 0) && (seconds_tens == 0) && (seconds_ones == 1)) // don't need minutes_tens, can't have 10:01
{
touchlight_enable = 0; // score touches are locked out
time_running = 0; // stop time running
seconds_ones = 0; // clear the last second
updated = 1; // fake a Case complete flag
buzzer = 1; // add a buzzer for this: end of time buzzer sounds
if ((time_running == 1) && (period>0) && (period<9)) { // update period counter if was fencing time, not 1:00 or 10:00 break
period = period +1;
update_period=1; // enable period display to be updated
}
} // end of if final second
// Case: x:50, x:40, x:30, x:20, x:10
if ((seconds_tens >0) && (seconds_ones == 0)) // case for the last tens of seconds
{
seconds_tens = seconds_tens - 1; // decrement the tens
seconds_ones = 9; // rollover the ones
updated = 1;
} // end of if 10 of seconds rollover
// Case: 9:00, 8:00, etc 2:00, 1:00
if ((minutes_ones > 0) && (seconds_tens == 0) && (seconds_ones == 0)) // case for the last ones of minutes
{
minutes_tens = 0x00; //
minutes_ones = minutes_ones - 1; // decrement the minutes
seconds_tens = 5; // rollover the tens of seconds;
seconds_ones = 9; // rollover the ones of seconds;
updated = 1;
} // end of if minutes rollover
// Case: starting from 10:00
if (minutes_tens == 0x01) // roll over all digits
{
minutes_tens = 0x00; // rollover the tens of minutes
minutes_ones = 9; // rollover the ones of mints;
seconds_tens = 5; // rollover the tens of seconds;
seconds_ones = 9; // rollover the ones of seconds;
updated = 1;
} // end of if 10:00 rollover
// General Case: just decrement the seconds
if (updated == 0) // nothing else updated - but don't decrement if = 0.
{
seconds_ones = seconds_ones - 1;
}
updated = 0; // reset for next pass thru
} // end of if quarter_interval
} // end of reaching our interval
} // end of if time_running
else
{
update_time = 0; // no time update this time around - probably don't need this
}
After this, check the state of
update_time, if ==1 then update the display with the time variables.
Isleo:
My conclusion: you can't do a countdown in millisecond because Arduino can't do 1000 operations per second. It do 733.33 operations per second.
16 MHz means 16 million instructions (assuming 1 CPI) per second. Where are you getting this 733.33 figure?
I know but I think Arduino is limited when you do this.
int segundos = 15;
int espacio_countdown_segundos = 3;
int milisegundos = 735; //it will be 1000, but I set 735 because if you compare it with a real cronometre, it takes 20 second in count 15.
static unsigned long ultimotick = 0;
void setup (){ while (milisegundos > 0) {
if (millis() - ultimotick >= 1) {
ultimotick = millis();
milisegundos--;
lcd.setCursor(6,1);
lcd.print(milisegundos);}
if (milisegundos == 0) {
ultimotick = millis();
segundos--;
if (segundos == 9){
lcd.setCursor(espacio_countdown_segundos,1);
lcd.print("0");
espacio_countdown_segundos+2;
}
if (segundos == 0 && (milisegundos == 0)){
milisegundos = 0;
if (segundos == 9){
}
lcd.setCursor(espacio_countdown_segundos,1);
lcd.print(segundos);
delay(200);
cronometro ();
break;}
milisegundos = 735;
lcd.setCursor(3,1);
lcd.print(segundos);
}
}}
void loop (){}
Arrch:
Why are you updating the LCD every millisecond? There probably aren't many people on this earth that can visibly see the milliseconds counting down.
HAHAHAHAHA. Yes, but it's cool see crazy numbers haha
Isleo:
My conclusion: you can't do a countdown in millisecond because Arduino can't do 1000 operations per second. It do 733.33 operations per second.
Oh?
You better check out my VGA output sketch:
That displays 160 pixels wide by 480 pixels deep, 60 times a second. Let's see, that is
160 * 480 * 60 = 4,608,000
So that's 4.6 million pixels per second.
For you, 25 or 30 refreshes a second would be plenty, there's a reason why that refresh rate is used for TV screens, it's about the most the eye can see.
You are displaying the time (I think) then waiting 200 mS. Doesn't that account for most of the amount it is out?
Your code is pretty convoluted. I can't quite make out what you are trying to do.
For my benefit, and others, I have formatted your code, added some comments, and translated a few words into English:
int seconds = 15;
int spaceCountdownSeconds = 3;
int milliseconds = 735; //it will be 1000, but I set 735 because if you compare it with a real cronometre, it takes 20 second in count 15.
static unsigned long lastTick = 0;
void setup ()
{
while (milliseconds > 0)
{
if (millis() - lastTick >= 1)
{
lastTick = millis();
milliseconds--;
lcd.setCursor(6,1);
lcd.print(milliseconds);
}
if (milliseconds == 0)
{
lastTick = millis();
seconds--;
if (seconds == 9)
{
lcd.setCursor(spaceCountdownSeconds,1);
lcd.print("0");
spaceCountdownSeconds+2;
} // end if seconds == 9
if (seconds == 0 && (milliseconds == 0))
{
milliseconds = 0;
if (seconds == 9) { }
lcd.setCursor(spaceCountdownSeconds,1);
lcd.print(seconds);
delay(200);
cronometro ();
break;
} // end if seconds and milliseconds are zero
milliseconds = 735;
lcd.setCursor(3,1);
lcd.print(seconds);
} // end if milliseconds == 0
} // end of while
} // end of setup
void loop (){ }