In this tutorial you will learn how to control many different tasks at the same time and how to execute high priority tasks interrupting all other tasks.
Table of contents:
Equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 |
#define LED_RED 3 void setup() { pinMode(LED_RED, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); delay(1000); digitalWrite(LED_RED, LOW); delay(1000); } |
Non-equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 |
#define LED_RED 3 void setup() { pinMode(LED_RED, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); delay(2000); digitalWrite(LED_RED, LOW); delay(1000); } |
Eeee... How to blink more than one LED?!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#define LED_RED 3 #define LED_GREEN 2 void setup() { pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, HIGH); delay(1000); digitalWrite(LED_RED, LOW); digitalWrite(LED_GREEN, LOW); delay(1000); } |
Non-equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#define LED_RED 3 #define LED_GREEN 2 void setup() { pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, HIGH); delay(2000); digitalWrite(LED_RED, LOW); digitalWrite(LED_GREEN, LOW); delay(1000); } |
Problems when:
1 2 3 4 5 6 7 8 |
LED_RED: 1,1,1,1,1,... LED_GREEN: 1,1,1,1,1,... LED_RED: 1,1,1,1,1,... LED_GREEN: 1,2,1,2,1,... LED_RED: 1,1,1,1,1,... LED_GREEN: 0.5,0.75,0.5,0.75,0.5,0.75,... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#define LED_RED 4 #define LED_GREEN 3 void setup() { pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, LOW); delay(1000); //digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, HIGH); delay(1000); digitalWrite(LED_RED, LOW); //digitalWrite(LED_GREEN, HIGH); delay(1000); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#define LED_RED 4 #define LED_GREEN 3 void setup() { pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); } void loop() { digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, LOW); delay(500); //digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, HIGH); delay(1500); digitalWrite(LED_RED, LOW); //digitalWrite(LED_GREEN, HIGH); delay(500); //digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, LOW); delay(500); } |
The disadvantage of this solution is that every delay
affects both leds. It may be difficult to control both leds independently. It may happend that changing timing of one led will force you to change code dractically.
Try to find extensible solution.
Equall timing for on and off state with only one led.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#define LED_RED 3 int counterRed = 0; char stateLedRed = LOW; void setup() { pinMode(LED_RED, OUTPUT); } void toogleLedRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; digitalWrite(LED_RED, stateLedRed); } else { stateLedRed = LOW; digitalWrite(LED_RED, stateLedRed); } } void loop() { if (counterRed == 100) { counterRed = 0; toogleLedRed(); } delay(10); counterRed++; } |
Non-equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#define LED_RED 3 int counterRedOn = 0; int counterRedOff = 0; char stateLedRed = LOW; void setup() { pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { if ((stateLedRed == HIGH) && (counterRedOn == 200)) { counterRedOn = 0; toogleLedRed(); } else if ((stateLedRed == LOW) && (counterRedOff == 100)) { counterRedOff = 0; toogleLedRed(); } delay(10); if (stateLedRed == LOW) { counterRedOff++; } else { counterRedOn++; } } |
Because counterRedOff
and counterRedOn
are increased inclusively (either counterRedOff
or counterRedOn
) you can use one counter as it is showned bellow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#define LED_GREEN 2 #define LED_RED 3 int counterRed = 0; char stateLedRed = LOW; void setup() { pinMode(LED_GREEN, OUTPUT); pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { if ((stateLedRed == HIGH) && (counterRed == 100)) { counterRed = 0; toogleRed(); } else if ((stateLedRed == LOW) && (counterRed == 200)) { counterRed = 0; toogleRed(); } delay(10); counterRed++; } |
Non-equall timing for on and off state of two leds.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#define LED_GREEN 2 #define LED_RED 3 int counterRed = 0; int counterGreen = 0; char stateLedRed = LOW; char stateLedGreen = LOW; void setup() { pinMode(LED_GREEN, OUTPUT); pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void toogleGreen() { if (stateLedGreen == LOW) { stateLedGreen = HIGH; } else { stateLedGreen = LOW; } digitalWrite(LED_GREEN, stateLedGreen); } void loop() { if ((stateLedRed == HIGH) && (counterRed == 200)) { counterRed = 0; toogleRed(); } else if ((stateLedRed == LOW) && (counterRed == 100)) { counterRed = 0; toogleRed(); } if ((stateLedGreen == HIGH) && (counterGreen == 50)) { counterGreen = 0; toogleGreen(); } else if ((stateLedGreen == LOW) && (counterGreen == 250)) { counterGreen = 0; toogleGreen(); } delay(10); counterRed++; counterGreen++; } |
Problems with this improvement:
Lack of control over code "outside" delay -- it may take as much time as it want. In consequence, delay(1000)
is not equall 100*delay(10)
. It means that you have to "collect" 100 delay(10)
s regardles of the time passed between every two delay(10)
s.
millis()
functionNon-blocking equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#define LED_RED 3 #define INTERVAL_RED 1000 char stateLedRed = LOW; unsigned long previousMillis = 0; void setup() { pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > INTERVAL_RED) { previousMillis = currentMillis; toogleRed(); } } |
Non-blocking non-equall timing for on and off state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#define LED_RED 3 #define INTERVAL_RED_ON 2000 #define INTERVAL_RED_OFF 1000 char stateLedRed = LOW; unsigned long previousMillis = 0; void setup() { pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { unsigned long currentMillis = millis(); if ((stateLedRed == HIGH) && (currentMillis - previousMillis > INTERVAL_RED_ON)) { previousMillis = currentMillis; toogleRed(); } else if ((stateLedRed == LOW) && (currentMillis - previousMillis > INTERVAL_RED_OFF)) { previousMillis = currentMillis; toogleRed(); } } |
Non-blocking non-equall timing for on and off state of two different LEDs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#define LED_GREEN 2 #define LED_RED 3 #define INTERVAL_RED_ON 2000 #define INTERVAL_RED_OFF 1000 #define INTERVAL_GREEN_ON 500 #define INTERVAL_GREEN_OFF 2500 char stateLedRed = LOW; char stateLedGreen = LOW; unsigned long previousMillisLedRed = 0; unsigned long previousMillisLedGreen = 0; void setup() { pinMode(LED_GREEN, OUTPUT); pinMode(LED_RED, OUTPUT); } void toogleRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void toogleGreen() { if (stateLedGreen == LOW) { stateLedGreen = HIGH; } else { stateLedGreen = LOW; } digitalWrite(LED_GREEN, stateLedGreen); } void loop() { unsigned long currentMillis = millis(); if ((stateLedRed == HIGH) && (currentMillis - previousMillisLedRed > INTERVAL_RED_ON)) { previousMillisLedRed = currentMillis; toogleRed(); } else if ((stateLedRed == LOW) && (currentMillis - previousMillisLedRed > INTERVAL_RED_OFF)) { previousMillisLedRed = currentMillis; toogleRed(); } if ((stateLedGreen == HIGH) && (currentMillis - previousMillisLedGreen > INTERVAL_GREEN_ON)) { previousMillisLedGreen = currentMillis; toogleGreen(); } else if ((stateLedGreen == LOW) && (currentMillis - previousMillisLedGreen > INTERVAL_GREEN_OFF)) { previousMillisLedGreen = currentMillis; toogleGreen(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#define BUTTON 8 #define LED_RED 3 int stateLedRed = LOW; void setup() { pinMode(LED_RED, OUTPUT); pinMode(BUTTON, INPUT); } void toogleLedRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { if (digitalRead(BUTTON) == HIGH) { delay(20); toogleLedRed(); while(digitalRead(BUTTON) == HIGH); delay(20); } } |
Add delay(10000)
to simulate time-consuming task
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#define BUTTON 8 #define LED_RED 3 int stateLedRed = LOW; void setup() { pinMode(LED_RED, OUTPUT); pinMode(BUTTON, INPUT); } void toogleLedRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void loop() { if (digitalRead(BUTTON) == HIGH) { delay(20); toogleLedRed(); while(digitalRead(BUTTON) == HIGH); delay(20); } delay(10000); } |
Digital pins usable for interrupts:
Uno, Nano, Mini, other 328-based: 2, 3
Micro, Leonardo, other 32u4-based: 0, 1, 2, 3, 7
Mega, Mega2560, MegaADK: 2, 3, 18, 19, 20, 21 (pins 20 & 21 are not available to use for interrupts while they are used for I2C communication)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#define BUTTON 3 #define LED_RED 4 int stateLedRed = LOW; void setup() { Serial.begin(9600); attachInterrupt(digitalPinToInterrupt(BUTTON), switchLed, RISING); pinMode(LED_RED, OUTPUT); } void toogleLedRed() { if (stateLedRed == LOW) { stateLedRed = HIGH; } else { stateLedRed = LOW; } digitalWrite(LED_RED, stateLedRed); } void switchLed() { if(digitalRead(BUTTON) == HIGH){ delay(20); toogleLedRed(); while(digitalRead(BUTTON) == HIGH); delay(20); } } void loop() { Serial.print(millis()/1000.0); delay(10000); } |