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.
example:
|
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 theclock()
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.
|
Final notes
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 Serial
.
The choice of char
and clock_t
for the types of Timer can be replaced in your Arduino sketches with bool
and 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
|