The simplest solution to make functions work for a certain time is to use delay() [1] function. delay() function stops program execution for instructed time.
Blinking LED is a simple demonstration of delay functionality:
digitalWrite(LED_BUILTIN, HIGH); //Turn the LED on delay(1000); //Stop program for a second digitalWrite(LED_BUILTIN, LOW); //Turn the LED off delay(1000); //Stop program for a second
Limitations that come with using delay(): most tasks stop, there can be no sensor reading, calculation, pin manipulation. Some tasks continue to work, like receiving serial transmissions and outputting set PWM values. Alternative of using delay is to use millis().
millis() [2] returns number in milliseconds since Arduino began running current program. The number will reset after approximately 50 days. millis() can be used to replace delay().
Here is an example code of blinking LED using millis(). Millis is used as a timer. Every new cycle time is calculated since the last LED state change if passed time is equal to or greater than the threshold value LED is switched:
//Unsigned long should be used to store time values //Store value of current millis reading unsigned long currentTime = 0; //Store value of time when last time the LED state was switched unsigned long previousTime = 0; bool ledState = LOW; //Varible for setting LED state const int stateChangeTime = 1000; //Time at which switch LED states void setup() { pinMode (LED_BUILTIN, OUTPUT); //LED setup } void loop() { currentTime = millis(); //Read and store current time //Calculate passed time since last stateChange //If more time has passed than stateChangeTime, start state Change if (currentTime - previousTime >= stateChangeTime) { previousTime = currentTime; //Store LED state change time ledState = !ledState; //Change LED state to oposite digitalWrite(LED_BUILTIN, ledState); //Write LED state to LED } }
Protothread is a mechanism for concurrent programming in embedded systems with limited resources. In Arduino, it can be used to achieve a periodical function call, like sensor reading, output state change, calculations etc. Most Arduino used microcontrollers have only one core; it can’t execute multiple functions simultaneously. By using millis() and loop, we can schedule a function call if appropriate conditions are met, thus avoiding unnecessary taking processors time.
In the example, code second LED is added, to demonstrate how to blink two LED’s concurrent with different frequencies. In the same manner, servo control, button reading and other functionality can be added.
//Unsigned long should be used to store time values //Store value of current millis reading unsigned long currentTime = 0; //Store value of time when last time LED1 state was switched unsigned long previousTime1 = 0; //Store value of time when last time LED2 state was switched unsigned long previousTime2 = 0; bool led1State = LOW; //Varible for setting LED1 state bool led2State = LOW; //Varible for setting LED2 state const int stateChangeTimeLed1 = 1000; //Time at which switch LED1 states const int stateChangeTimeLed2 = 200; //Time at which switch LED2 states void setup() { pinMode (LED_BUILTIN, OUTPUT); //LED1 setup pinMode (2,OUTPUT); //LED2 setup } void loop() { currentTime = millis(); //Read and store current time //Calculate passed time since the last stateChange //If more time has passed than stateChangeTime, start state change if (currentTime - previousTime1 >= stateChangeTimeLed1) { previousTime1 = currentTime; //Store LED state change time led1State = !led1State; //Change LED1 state to oposite digitalWrite(LED_BUILTIN, led1State); //Write led1State to LED1 } if (currentTime - previousTime2 >= stateChangeTimeLed2) { previousTime2 = currentTime; //Store LED2 state change time led2State = !led2State; //Change led2state to oposite digitalWrite(2, led2State); //Write led2state to LED2 } }
There are dedicated libraries made by the Arduino community to implement protothreads [3].
Check Yourself
1. What are the drawbacks of using delay()?
2. What is the difference between delay() and millis()?
3. Can Arduino run truly parallel programs?
4. How is concurrency achieved on Arduino?