May 24, 2021

How to do multiple tasks in Arduino

To watch it on youtube, Click Me

Post Thumbnail

Have you ever felt difficulties while trying to do multiple tasks in Arduino? If yes, this post is for you 😉.

Let’s say you want to execute several tasks at the same time. For example:

  • Reading data from Serial Monitor
  • Blinking some LEDs
  • Monitoring some external sensors
  • Sending data to the server after some time interval

With classic style of programming, may be you won’t be able to do these tasks. The problem is that Arduino is not built to do multiple tasks at the same time. It doesn’t support Multithreading like any classic computers you have. It executes instructions one by one in a queue.

But the good news is… Still you can do some tricks to make it feel like Arduino is doing multiple tasks at the same time.

1. Choosing an example project

To understand things practically, let’s choose a project where we have to do 4 tasks at the same time. And I have told you… the same time means just creating an illusion of same time.

  • Task 1 : Blinking an LED every 1 second
  • Task 2 : Glowing an LED whenever the button is pressed
  • Task 3 : Controlling the brightness of LED by user input from Serial Monitor
  • Task 4 : Printing brightness of LED (Task 3) every 5 seconds.

For Task 3, User can input a number from 0 to 255 where 0 means Totally Off 1 means Full brightness

2. Identifying Tasks that are affecting program workflow

After we defined our project objective, we need to identify the tasks that are affecting the program workflow.

Let me take Task 1 which is about blinking LED every 1 second. Here, We can define Task 1 with code below:

void loop() {
    // TODO: Task 1
    delay(1000); // wait for a second
    digitalWrite(LED1, HIGH); // turn ON LED
    delay(1000); // wait for a second
    digitalWrite(LED1, LOW); // turn OFF LED
    
    // TODO: Other tasks
}

In the code, delay(1000) is pausing the program flow. Arduino will execute another statement below it only after 1 second. Until 1 Second, it will wait in that line.

We need to cycle over tasks rapidly in a loop so that we can execute all tasks very fast.

Let’s put Task 2 in the code.

void loop() {
    // TODO: Task 1
    delay(1000); // wait for a second
    digitalWrite(LED1, HIGH); // turn ON LED
    delay(1000); // wait for a second
    digitalWrite(LED1, LOW); // turn OFF LED
    
    // TODO: Task 2
    if (digitalRead(BTN)) {
        digitalWrite(LED2, LOW);
    } else {
        digitalWrite(LED2, HIGH);
    }
}

Here, For glowing the LED whenever button is pressed, digitalRead(BTN) needs to be executed to read if BTN is pressed or not. But due to delay() function, the arduino will take time for task 1 to complete and then can read the button status.

So, we can conclude that Task 1 is affecting the program flow

And Is there any other tasks affecting the program flow? Yes… It’s Task 4 because It also waits for 5 seconds and print brightness.

To identify them, you just need to know whether the task is taking long time or not.

3. How to avoid delay and pause

Now, we need to avoid using delay() function. But how??

There’s a great function in Arduino for you. It’s millis() function.

  • Syntax: time = millis()
  • Description: Returns the number of milliseconds that your Arduino board has been powered up or reset.
  • Return Type: unsigned long

millis() function in code:

unsigned long prevTime = millis();

void setup() {}

void loop() {
  unsigned long currentTime = millis();

  if (currentTime - prevTime > 1000) {
    doSomething();

    prevTime = currentTime;
  }
}

In the code, currentTime reads and stores number of milliseconds elapsed since you power on the Arduino. When currentTime is greater than prevTime by 1000 ms then doSomething() is called. It means that doSomething() function is called every 1000 ms (1 second) without affecting the program cycle i.e. no delay/no pause. So, we can use this concept to replace delay() function from our project code.

4. Replacing delay with millis() in our project

Replace the Task 1 code with millis() code we use above.

LED1_state = LOW; // at top of the code
void loop() {
    // TODO: Task 1
    // delay(1000); // wait for a second
    // digitalWrite(LED1, HIGH); // turn ON LED
    // delay(1000); // wait for a second
    // digitalWrite(LED1, LOW); // turn OFF LED
    if (currentTime - prevTime_T1 > interval_T1) {
        LED1_state = !LED1_state;
        digitalWrite(LED1, LED1_state);

        prevTime_T1 = currentTime;
    }
    
    // TODO: Other tasks
}

Do the same thing for Task 4. Difference is that we replace doSomething with Serail Printing Code.

5. Final Code

#define LED1 13
#define LED2 12
#define LED3 11

#define BTN 4

// set LED states
int LED1_state = LOW;
int brightness = 0;

// previous time for the tasks depending upon time.
unsigned long prevTime_T1 = millis(); 
unsigned long prevTime_T4 = millis(); 

// time intervals for the tasks
long interval_T1 = 1000; // blink every 1 second
long interval_T4 = 5000; // print brightness of LED3 every 5 seconds

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(BTN, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long currentTime = millis();

  // Task 1 : Blink LED1 (T1)
  if (currentTime - prevTime_T1 > interval_T1) {
    LED1_state = !LED1_state;
    digitalWrite(LED1, LED1_state);

    prevTime_T1 = currentTime;
  }

  // Task 2 : Glow LED2 when BTN is pressed
  if (digitalRead(BTN)) {
    digitalWrite(LED2, LOW);
  } else {
    digitalWrite(LED2, HIGH);
  }

  // Task 3 : Read input from serial monitor (0-255) and then write to LED3
  if (Serial.available()) {
    brightness = Serial.parseInt();
    if (brightness >=0 && brightness <= 255) {
      analogWrite(LED3, brightness);
    }
  }

  // Task 4 : print the brightness of LED3 in the serial monitor after every 5 seconds
  if (currentTime - prevTime_T4 > interval_T4) {
    Serial.print("Brightness (0-255): ");
    Serial.println(brightness);

    prevTime_T4 = currentTime;
  }
}

6. Hardware Arrangement

Hardware Arrangement


Tags: arduino multitasking with arduino millis no delay in arduino

Contact Me

Feel free to contact me

Any message you want to leave?

Address
Butwal, Nepal
Phone
(+977) 9867209460