HOME - - - - - - - - Table of contents, my Arduino "How To" articles
  - -  Lazarus/ Delphi tutorials
Other material for programmers

Dealing with "roll over"

(filename: RollOver.htm)

Remember as a very small child the wonder of discovering once you'd got past those wretched "teen" numbers (you didn't know about the "teen years" yet)... "eleven, twelve... nineteen", that after that there was no limit!?

Remember as a slightly older child trying to count to... what was it for you? For me it was 1,000. (Never made it.)

Well, while it is true that in mathematics, there is always a number one bigger than the one you've counted to so far, that is NOT true when you are dealing with electronics and computers.

If I have 2 LEDs on a device, they can count to 3...

Both off stands for zero
0 1 is one
1 0 is two
11 is three

... and after that you are stuck. By the generally understood rules for these things, "add" one, and you go back to 00, zero.

And while you are not usually limited to only two bits ("BInary digiTs), you ARE limited, someplace, somewhere, when you are doing numbers in computers, or digital electronics more generally.

(Digression: There are 10 sorts of people- Those who understand binary, and those who don't.)

With 8 bits, you can show 0-255. (Or, if you use the bits differently, -128 to +127... a different widely used mapping of 256 "numbers" onto 256 on/off "codes".)

With 32 bits (The Arduino "unsigned long" data type) you can show 4,294,967,295... but not 4,294,967,296. There's still a limit. (Don't try to count to that number.

In each case, if you get to the maximum number, and try to add one, you will "roll over" back to the smallest number (often zero) your system can show. (Unless you are using clever software, for instance Lazarus / Delphi with range checking turned on. {$R+} is how to turn it on. (In such cases, an event is triggered. Not available, on Arduinos.))

Consider clocks and car odometers. They exhibit "roll over", don't they?

Who Cares (about roll over)

Well... you might!

Some programs make use of timers available on the system. The Arduino offers you the "millis()" function, which tells you how many milliseconds it has been since your Arduino was last reset. Lazarus has getTickCount();

Generally speaking, if you want a 1 second delay, you can say something along the lines of...

while (then+1000<millis())

//... and whatever should happen
//after the 1 second delay
//goes here.

That code will generally give you a one second delay.... but not always.

Millis rolls over after 4,294,967,295.

What if you went into the code above at 4,294,967,290?

You wouldn't get the delay you would expect. And even this simple example can be relevant, although I admit that it won't often be. But less simple examples of cases where roll over matters do exist. And if you don't know about roll over can be perplexing.

I'm using an Arduino. What's wrong with "delay()"?

Arduino users can do...

//Do something
//Do other thing

... and the "other thing" will be done, reliably, one second after the "something".

There's no roll over problem. But there IS a problem in that during the 1 second, the Arduino becomes unresponsive.

There will be times when you want the Arduino waiting on something, but able to do other things in the meantime. For which the following is an answer. It can be adapted quite easily for other languages. It will not have roll over problems.

//See Serial.println's in setup() for prgm name, version info

//This demonstrates how you can deal with the fact that
//   in a computer you eventually reach "roll-over", if
//   you add 1 to a variable for too long.

//    while (millis()-ulBefore<ulWait)

//It is demonstrated within the context of a "Blinky"
//   type program.

//Hardware for the demo...
//On many Arduinos, there is an LED and resistor on the
//   Arduino itself, wired so that if you make D13
//   high, the LED comes on. (Make it low to turn off.)
//This demo assumes you are using such a board. You can
//   hook up an external LED, if you wish, on 13 or
//   anywhere you wish. Just set pLED accordingly.
//The built in LED is connected (through resistor)
//   on one side to the system's Vcc... so if you
//   connect the other side to an output of the
//   Arduino, set that LOW to turn the LED ON.

const byte pLED=13;

//That is the only hardware NEEDED for this.
//Optional extra hardware: If you put an switch
//   on pButton, and another LED on pStateOfSwitch,
//   then you can SEE that we've created a
//   "non-blocking" wait routine.
//The switch, when pressed, should connect
//   pButton to the Arduino's ground.
//Anything associated with that LED or switch
//   is OPTIONAL. The code can be run as is
//   regardless of whether the LED or switch
//   are present.

const byte pButton=2;
const byte pLEDStateOfSwitch=3;

unsigned long ulBefore, ulWait;

void setup() {
  Serial.println("ver 06 Nov 188");


}//end of setup()

void loop() {

  //equiv of delay(800);....
  ulBefore=millis();//Millis returns the time
  //  the processor has been running, in
  //  milliseconds.
  while (millis()-ulBefore<ulWait)
      //Do nothing, in this case... but
      //in many cases you WOULD have a whole lot
      //to do here. Or you might use the
      //"(millis()-ulBefore<ulWait)" test
      //differently. But it would still
      //survive a roll-over of millis().
      //N.B: You might need to change
      //it to "(millis()-ulBefore<ulWait)".

      //Should one or the other of those be
      //"less than" (or "greater than") OR EQUAL?
      //Possibly. And it COULD matter... once in
      //4 billion cases. But ignoring such things
      //leads to tears!

      //Just a little something to show that
      //   during the delay, the Arduino is
      //   not "blocked".
      //   (See...
      //     https://www.makeuseof.com/tag/arduino-delay-function-shouldnt-use/
      //   for an explanation of what "blocking"
      //   is, and why we don't like it!)


    }//end of while

  //end of 1st "equiv of.."

  ToggleLED(pLED);//To show we've left the first
  //"wait" delay.

  //equiv of delay(60);.... This merely repeats
  //  what we did above, for a different delay,
  //  for the time the LED should spend in other
  //  state.

  while (millis()-ulBefore<ulWait)
      //Just to show Arduino isn't blocked...
      //  you will often have USEFUL things
      //  to put in similar places.

    }//end of while

 //end of 2nd "equiv of.."

  ToggleLED(pLED);//To show we've left the second
  //"wait" delay.

}//end of loop()

void ToggleLED(byte bWhich)
//A detail.. there are other solutions, if
//you don't like this one, but they have no
//bearing on "beating roll-over", the main
//point of this example program.

//This "LED on/ off" subroutine relies
//on an untested assumption...
//pLED is currently set up for OUTPUT, so it
//is a little unusual to read it. I am hoping
//(and tests seem to bear me out) that if I've
//written to a configured-as-output pin, I can
//read what state it has been set to.
  if (digitalRead(bWhich)==LOW)
       {digitalWrite(bWhich,HIGH);}//no ; here

void ReactToButton()
//Optional "extra", to demonstrate Arduino
//  isn't "blocked" while doing a "delay"
//  as shown in this program.
if (digitalRead(pButton)==LOW)//will be low if pressed
  digitalWrite(pLEDStateOfSwitch,HIGH);//Set high to turn off
  }//no ; here
  digitalWrite(pLEDStateOfSwitch,LOW);//Turns LED on
}//End of ReactToButton()

Concluding remarks

The above was intended to introduce the idea of roll over, and present a "roll over friendly" way of using a loop counter to manage when things occur in a program.

Do, please, get in touch, if parts were unclear. Save the next reader the confusion you were subjected to! Contact details below.

My thanks to the great Nick Gammon, who has explained this many times at the Arduino forum. I keep forgetting the details, but his post explaining that there IS a simple solution was my Damascus moment for this annoying detail- which- needs- attention. "You just have to subtract and then it all works automagically." (For how you do that... see above!)

A few words from the sponsors...

Please get in touch if you discover flaws in this page. Please mention the page's URL. (Sheepdogguides.com/elec/princ/RollOver.htm).

If you found this of interest, please mention in forums, give it a Facebook "like", Google "Plus", or whatever. If you want more of this stuff, help!? There's not much point in me writing these things, if no one feels they are of any use.

   Search this site                 powered by FreeFind
Site Map    What's New    Search

Click here to visit my main homepage where you can explore other areas, such as education, programming, investing.

Ad from page's editor: Yes.. I do enjoy compiling these things for you. I hope they are helpful. However... this doesn't pay my bills!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

How to email or write this page's editor, Tom Boyd

Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes. A few "bad attributes" due to Google+ button, etc.

Why does this page cause a script to run? Because of the Google panels, and the code for the search button. Also, I have my web-traffic monitored for me by eXTReMe tracker. They offer a free tracker. If you want to try one, check out their site. Why do I mention the script? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....