Decrements Time

OK, here is the deal, want to make countdown timer, this code blow will increment time:

      seconds++;
      if(seconds==60)
      {
        seconds=0;     //let the counter of seconds begin once more
        minutes++;
        if(minutes==60)
        {
          minutes=0;     //let the counter of minute begin once more
          hours++;
        }
      }

But I'm having trouble to decrease timer, like if i set start time 00:02:03, it will decrease till 00:00:00.

My code glitches, in transitions, is this right:

seconds--;
      if(seconds==00)
      {
        seconds=60;     //let the counter of seconds begin once more
        minutes--;
        if(minutes==00)
        {
          minutes=60;     //let the counter of minute begin once more
          hours--;
        }
      }

Best regards :astonished:

Variable mismatch

segundos --
if (seconds == ...

vinicaog:
But I'm having trouble to decrease timer, like if i set start time 00:02:03, it will decrease till 00:00:00.

Isn't that what you want it to do?

My code glitches, in transitions, is this right:

segundos--;

if(seconds==00)
      {
        seconds=60;     //let the counter of seconds begin once more
        minutes--;
        if(minutes==00)
        {
          minutes=60;     //let the counter of minute begin once more
          hours--;
        }
      }

Well, the Arduino is very capable, but it won't automatically translate between Spanish and English. segundos <--> seconds?

Sorry that was mistake while posting on forum, just edited for the right variable name.

here is and example:

the countdown time was set to 00:03:03

Serial output:

00:03:03
00:03:02
00:03:01
00:02:60
00:02:65535
00:02:14
00:02:13
00:02:12
00:02:11
00:02:10
00:02:09
00:02:08
00:02:07
00:02:06
00:02:05
00:02:04
00:02:03
00:02:02
00:02:01
00:01:60
00:01:65535
00:01:14
00:01:13
00:01:12
00:01:11
00:01:10
00:01:09
00:01:08
00:01:07
00:01:06
00:01:05
00:01:04
00:01:03
00:01:02
00:01:01
65535:60:60
15:0:65535
15:00:14
15:00:13
15:00:12
15:00:11
15:00:10

Here is my method, which is crazy but works (unless I've made a stupid mistake somewhere):

      // Code for counting UP:
      seconds++;
      if(seconds>=60)
      {
        seconds-=60;     //let the counter of seconds begin once more
        minutes++;
      }
      if(minutes>=60)
      {
        minutes-=60;     //let the counter of minute begin once more
        hours++;
      }
      
      
      
      // Code for counting DOWN:
      seconds+=59;
      minutes+=59;
      if(seconds>=60)
      {
        seconds-=60;     //let the counter of seconds begin once more
        minutes++;
      }
      if(minutes>=60)
      {
        minutes-=60;     //let the counter of minute begin once more
        hours++;
      }
      hours--;

The concept is from very old calculating machines which could not subtract. They could only add, so if you wanted to subtract, you had to convert the subtraction into an addition, as I have done here.

Well odometer, that's nice coding, looks efficient for old machines :slight_smile:

It actually works pretty well, no glitches.
Now i'm trying to understand how it works.

Thank you so much for your time and help.
Regards.

if(seconds==00)
{
seconds=60; //let the counter of seconds begin once more
minutes--;

I would say:

  if(seconds==00)
      {
        seconds=59;     //let the counter of seconds begin once more
        minutes--;
Example calculation:

  hr  min  sec
   1    0    1   Counting down: what comes next?
      +59  +59   Take care of minutes and seconds
   1   59   60   Too many seconds
      + 1  -60   Carry seconds into minutes
   1   60    0   Too many minutes
  +1  -60        Carry minutes into hours
   2    0    0
  -1             Remove the extra hour
   1    0    0   Result
   
   1    0    0   ... wait for the next second ...
   
   1    0    0   Then what happens?
      +59  +59   Take care of minutes and seconds
   1   59   59
  -1             Remove extra hour
   0   59   59   Result
   
   0   59   59   ... wait for the next second ...

   0   59   59   And then what?
      +59  +59   Take care of minutes and seconds
   0  118  118   Too many seconds!
       +1  -60   Carry seconds into minutes
   0  119   58   Too many minutes!
  +1  -60        Carry minutes into hours
   1   59   58
  -1             Remove extra hour
   0   59   58   Result

pito:

if(seconds==00)
{
seconds=60; //let the counter of seconds begin once more
minutes--;

I would say:

  if(seconds==00)

{
        seconds=59;     //let the counter of seconds begin once more
        minutes--;

No. A minute has 60 seconds, not 59.

Yeah but I've never seen a countdown clock that shows you :60. You usually see zero and then 59. So it should be something like if seconds == -1 then seconds =59. You don't want to do it at zero or the countdown will go 5... 4... 3... 2... 1... 60... 59... 58 and that's not what people normally want to see. They normally want 3... 2... 1... 0... 59... 58... 57...

Delta_G:
Yeah but I've never seen a countdown clock that shows you :60. You usually see zero and then 59. So it should be something like if seconds == -1 then seconds =59.

I don't know. What datatype is he using? Will it correctly handle the negative number?

My approach has a weakness of its own. If seconds and minutes are of datatype char, then they need to be kept in the range -127 to 127. This might be all right (because 59 + 59 + 1 < 127), but a timer set to "90 seconds" (as opposed to "1 minute 30 seconds") will defeat this (as 90 + 59 > 127). However, I think it very unlikely that vinicaog is using char for the relevant variables.

The real question is why bother to keep up with minutes and seconds in separate variables and add all this layer of confusion in the first place. If seconds is what you need, then just keep up with that. I don't care if you suck at math, the processor is pretty good at it. Then if you want to see minutes and hours and stuff when you display it, then do that when you display it. That's just for the humans.

unsigned int countdown = 183;  //3 minutes and 3 seconds as seconds
boolean countdownEnded = false;

void setup()
{
  Serial.begin(9600);
}

void loop(){
 if (countdown == 0){
      Serial.println("Countdown Ended");
      countdownEnded = true;
    }
  if (!countdownEnded){
    printTime(countdown);
    countdown--;
    delay(1000);  // This code has nothing else to do. 
   
  } 
}

void printTime(unsigned int time){
  Serial.print(time /60);  // print the number of minutes
  Serial.print(':');
  int seconds = time % 60;
  if (seconds < 10){
    Serial.print('0');
  }
  Serial.print(time % 60);
  Serial.println();

}
3:03
3:02
3:01
3:00
2:59
2:58
2:57
2:56
2:55
2:54
2:53
2:52
2:51
2:50
2:49
2:48
2:47
2:46
2:45
2:44
2:43
2:42
2:41

...

0:12
0:11
0:10
0:09
0:08
0:07
0:06
0:05
0:04
0:03
0:02
0:01
Countdown Ended

That's pretty good.

Thanks everyone for helping and giving opinion about this subject!!

Make seconds and minutes signed integers, then its simple

int seconds, minutes ;
...
...

  seconds -- ;
  if (seconds < 0)
  {
    seconds += 60 ;  // borrow from minutes
    minutes -- ;
    if (minutes < 0)
    {
      minutes += 60 ;  // borrow from hours
      hours -- ;
      ...... etc etc
    }
  }

This is just a special case of subtraction in base 60, it works just
like with pencil and paper.

I wrote these functions just for fun:

unsigned long timeAdd (unsigned long x, unsigned long y) {
  // no sanity checking of input
  // format is hhmmssff with ff being decimal fractions of a second
  // "out of range" results are e.g. A0000000 for 100 hours
  unsigned long binsum = x + y;
  unsigned long carry = ((binsum + 0x06A6A666) ^ x ^ y) & 0x11111110;
  return (binsum + ((carry - (carry>>4)) & 0x06A6A666));  
}

unsigned long timeSub (unsigned long x, unsigned long y) {
  // no sanity checking of input
  // format is hhmmssff with ff being decimal fractions of a second
  // "negative" results are e.g. F9595999 for -0.01 second
  unsigned long bindiff = x - y;
  unsigned long borrow = (bindiff ^ x ^ y) & 0x11111110;
  return (bindiff - ((borrow - (borrow>>4)) & 0x06A6A666) );
}

/*
   Usage example:

   2 h 58 min 30.98 s --> 0x02583098
   0 h  1 min 44.06 s --> 0x00014406
   
   Addition:
   timeAdd(0x02583098, 0x00014406) gives 0x03001504
                             which means 3 h 0 min 15.04 s
                             
   Subtraction:
   timeSub(0x02583098, 0x00014406) gives 0x02564692
                             which means 2 h 56 min 46.92 s
*/