Arduino sketches are single threaded. This means your Arduino won’t be doing two things simultaneously. The problem of this is that when you use the command
sleep the micro-controller is blocked waiting for the time to pass and won’t be able to do anything else.
If you need the processor to work on other things you need to get rid of
sleep and replace it with a timer based logic. Here’s an example:
You want to turn a LED on for 1 second, but you don’t want to
sleep(1000) because during the period others things might happen. You might be reading data from a potentiometer in an unrelated piece of logic of your project. Or you might be sending data to other Arduino. Or the LED is just a warning light in a Robot and you want to turn it on and off every other second without stopping the robot from moving. Well, there are many examples where this is applicable. The solution to not using
sleep is to use a timer.
When you turn the LED ON, you start the timer; note that we declare the timer as
unsigned long because that is what the
millis() function returns.
Now, instead of sleeping for 1000ms we want to turn the LED OFF after 1000ms.
There you have it. No blocking
sleep. Notice that we checked to see if the LED was HIGH with a
digitalRead that shortcuts the evaluation of the condition. This avoids repeating the
digitalWrite continuously while the LED is OFF. Instead of using
digitalRead you could use a boolean
led_status variable that would make the code even faster.
Advanced C example
The principles above can be condensed in C by defining
struct timers and passing functions to execute parts of code as parameters to a timer function. The following example illustrates a minimum working case. This runs on the Desktop and not on the Arduino, but the principle is the same. Study the code to learn; the main function simulates the calls to setup and loop functions of the Arduino. You should be able to compile the code with gcc.
Note that we are using two timers (1 and 2) that run at intervals of 1 second and 3 seconds respectively. Note also that here we are using the
clock() function. When using the Arduino you’ll probably be using the
millis() function instead.
The important mechanisms are in functions runTimer and activateTimer; The latter sets up the timers while the former is called repeatedly in the
draw functions. print1 and print2 are the two functions that you want to invoke when the timers fire.
Take particular attention that without sleeps this code is running at full speed consuming more power. If your other input is a reading from a temperature sensor, probably you don’t want to be probing the sensor constantly and it might make perfect sense to use a sleep command. Use this approach to simulate a sort of fake multithreading where you really need not to block on sleeps.
This approach can be enhanced with other functions like stop, pause, toggle, check, run, etc, that would increase the functionality of the timer. In any case the two proposed functions are enough to have a running proof of concept.
What about Arduino C?
The conversion of the above C code to Arduino code can be straightforward. Everything is the same except the
main function doesn’t exist and you won’t be printing anything and therefore the inclusion of the
stdio.h header will probably be replaced with
The choice of
clock_t for the types of Timer can be replaced in your Arduino sketches with
unsigned long respectively; then just treat the active as
true|false and the
previous will be using the
millis() function. Also you won’t divide by
CLOCKS_PER_SEC but by 1000.
This means that you will not use the
time.h header and therefore the reference to it can be deleted.
Below is the code for Arduino. Compare it with the C version above and it will become clear that there is no structural difference.
Sleep free code for Arduino