Countdown

Hi, I'm doing a countdown program for arduino but it have a 5 second of delay:

lcd.print("Cuenta atras");
arriba:
lcd.setCursor(0,1);
lcd.print("00:");
lcd.print(segundos);
lcd.print(":000");
for (milisegundos = 999;milisegundos>99;milisegundos--){
lcd.setCursor(6,1);
lcd.print(milisegundos);
}
for (milisegundos = 99;milisegundos>9;milisegundos--){
lcd.setCursor(6,1);
lcd.print("0");
lcd.print(milisegundos);
}
for (milisegundos = 9;milisegundos>=0;milisegundos--){
lcd.setCursor(6,1);
lcd.print("00");
lcd.print(milisegundos);
if(segundos==0){
delay(15500);
}
if(milisegundos==0){
segundos--;
milisegundos = 999;
goto arriba;
}
}

How Can I do a countdown in real time?

arriba:
...
goto arriba;

Start by ditching goto and never looking back. Then, post your ENTIRE code, not just snippets.

Without wishing to start yet another "goto" flame war, I totally agree with Arrch. Lose the "goto". If you want a loop use "do", "while" or "for".

Post all of your code after using the IDE's "auto format" tool on it. Having everything start in column 1 makes it hard to read.

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.

This is how I did it -

// ***********************************************************************************************
// 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.

Goto has it's place, just not in this code here...

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.

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?

Arrch:

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 (){}

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.

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.

Isleo:
I know but I think Arduino is limited when you do this.

No, it's just poorly designed code. This code will slip due to the way you update the recorded time values.

      if (millis() - ultimotick >= 1) {
          ultimotick = millis();

Replace it with something like this:

if (millis() - ultimotick >= 1) 
{
          ultimotick++;

PeterH:

Isleo:
I know but I think Arduino is limited when you do this.

No, it's just poorly designed code. This code will slip due to the way you update the recorded time values.

      if (millis() - ultimotick >= 1) {

ultimotick = millis();




Replace it with something like this:



if (millis() - ultimotick >= 1)
{
          ultimotick++;

Same result as first code.

        delay(200);

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 (){ }

What does this do?

        spaceCountdownSeconds+2;

Hint: nothing useful.