Running tasks in parallel

Hi,

I’m displaying several messages on a LCD so, to be able to read all of them, I need to add some delays.

The latter adds an overall delay to my main loop of about 7 seconds. To cut it down, I used Robin’s routine at Demonstration code for several things at the same time - Project Guidance - Arduino Forum.

Perhaps, I’m implanting it wrong, but the routine is not shorting out the overall delay. What’s the best way to accomplish it? TIA

#include <Bridge.h>
#include <Console.h>
#include <LiquidCrystal_I2C.h>

/* LCD Display */
const byte dir = 0x27; // I2C hexadecimal address
LiquidCrystal_I2C lcd(dir, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // set address and pins
/* https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */
unsigned long currentMillis = 0; 
unsigned long previousMillis = 0; // will store last time LCD was updated
unsigned long previousMillis_1 = 0;
const long interval = 1000;  // display delay

void setup() {

  Bridge.begin();
  Console.begin();

  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  lcd.print("Initializing...");
  delay(1000);
  lcd.clear();

}

void loop() {

 currentMillis = millis();

  Console.println("Start " + getTimeStamp());

  // doing several tasks here
  // ...

  /* updating LCD display */
  
  if (currentMillis - previousMillis >= interval) {
    updateDisplay ();
    previousMillis = currentMillis;
  }

  Console.println("End " + getTimeStamp()); // time delay of 6-7 seconds here from start loop
}

//// LCD update
void updateDisplay() {
  //unsigned long currentMillis = millis();
  // if (currentMillis - previousMillis >= interval) {
  lcd.clear();
  lcd.setCursor(0, 1); // col row
  lcd.print(getTimeStamp()); // display time date
  //previousMillis = currentMillis;
  delay(2000);
  // }

  // currentMillis = millis();
  // if (currentMillis - previousMillis_1 >= interval) {
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("H20 Temp is 40º C"); // display water temp
  //previousMillis_1 = currentMillis;
  delay(2000);
  //}

  lcd.clear(); // clear display
  lcd.setCursor(0, 0); // set curson
  lcd.print("Tech Room T=" + String(34) + " C");
  lcd.setCursor(0, 1);
  lcd.print("Tech Room H=" + String(44) + " %");
  lcd.setCursor(0, 2); // set curson
  lcd.print("Main Room T=" + String(31) + " C");
  lcd.setCursor(0, 3);
  lcd.print("Main Room H=" + String(43) + " %");
  delay(2000);
}
//// END updateDisplay

//**** Get Time Stamp ****
String getTimeStamp() {
  String result;
  Process time;
  time.begin("date");
  time.addParameter("+%d/%m/%Y-%T");
  time.run();

  while (time.available() > 0) {
    char c = time.read();
    if (c != '\n')
      result += c;
  }

  return result;
}
//// END getTimeStamp

Thanks for the reply.

I modified the code with the use of millis but the datetime, in this case, is not displayed on the LCD

currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    lcd.clear();
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display date & time
    previousMillis = currentMillis;
  }

Post your complete code.

I wonder if you are using previousMillis() in two different places and they are getting mixed up.

...R

We can't see the rest of your code so that the context of your timing can be seen.

Here's the code...

Thank you.

#include <Bridge.h>
#include <Console.h>
#include <LiquidCrystal_I2C.h>

/* LCD Display */
const byte dir = 0x27; // I2C hexadecimal address
LiquidCrystal_I2C lcd(dir, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // set address and pins
/* https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */
unsigned long currentMillis = 0;
unsigned long previousMillis = 0; // will store last time LCD was updated
const long interval = 1000;  // display delay

void setup() {

  Bridge.begin();
  Console.begin();

  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  lcd.print("Initializing...");
  delay(1000);
  lcd.clear();

}

void loop() {

  Console.println("Start " + getTimeStamp());

  // doing several tasks here
  // ...

  /* updating LCD display */
  updateDisplay ();

  Console.println("End " + getTimeStamp()); // time delay of 6-7 seconds here from start loop
}

//// LCD update
void updateDisplay() {
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    lcd.clear();
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
    previousMillis = currentMillis;
    // delay(2000);
  }

  // currentMillis = millis();
  // if (currentMillis - previousMillis_1 >= interval) {
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("H20 Temp is 40º C"); // display water temp
  //previousMillis_1 = currentMillis;
  delay(2000);
  //}

  lcd.clear(); // clear display
  lcd.setCursor(0, 0); // set curson
  lcd.print("Tech Room T=" + String(34) + " C");
  lcd.setCursor(0, 1);
  lcd.print("Tech Room H=" + String(44) + " %");
  lcd.setCursor(0, 2); // set curson
  lcd.print("Main Room T=" + String(31) + " C");
  lcd.setCursor(0, 3);
  lcd.print("Main Room H=" + String(43) + " %");
  delay(2000);
}
//// END updateDisplay

//**** Get Time Stamp ****
String getTimeStamp() {
  String result;
  Process time;
  time.begin("date");
  time.addParameter("+%d/%m/%Y-%T");
  time.run();

  while (time.available() > 0) {
    char c = time.read();
    if (c != '\n')
      result += c;
  }

  return result;
}
//// END getTimeStamp

You still have two delays in there.

void updateDisplay() {
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    lcd.clear();
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
    previousMillis = currentMillis;
    // delay(2000);
  }

  // currentMillis = millis();
  // if (currentMillis - previousMillis_1 >= interval) {
  lcd.clear();   // <---------- HERE

OK, you followed the advice above. You display the time stamp, and then in the line above you immediately clear the LCD. So obviously you don't see that display for long, right?

Moved the clear out the loop but no display...

#include <Bridge.h>
#include <Console.h>
#include <LiquidCrystal_I2C.h>

/* LCD Display */
const byte dir = 0x27; // I2C hexadecimal address
LiquidCrystal_I2C lcd(dir, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // set address and pins
/* https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */
unsigned long currentMillis = 0; // will store last time LCD was updated
unsigned long currentMillis1 = 0;
unsigned long currentMillis2 = 0;
unsigned long previousMillis = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval = 4000;  // display delay

void setup() {

  Bridge.begin();
  Console.begin();

  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  lcd.print("Initializing...");
  delay(1000);
  lcd.clear();

}

void loop() {

  Console.println("Start " + getTimeStamp());

  // doing several tasks here
  // ...

  /* updating LCD display */
  updateDisplay ();

  Console.println("End " + getTimeStamp()); // time delay of 6-7 seconds here from start loop
}

//// LCD update
void updateDisplay() {
  currentMillis = millis();
  lcd.clear();
  if (currentMillis - previousMillis >= interval) {
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
    previousMillis = currentMillis;
    // delay(2000);
  }

  currentMillis1 = millis();
  lcd.clear();
  if (currentMillis1 - previousMillis1 >= interval) {
    lcd.setCursor(0, 1);
    lcd.print("H20 Temp is 40º C"); // display water temp
    previousMillis1 = currentMillis1;
    //delay(2000);
  }

  currentMillis2 = millis();
  lcd.clear();
  if (currentMillis2 - previousMillis2 >= interval) {
    lcd.setCursor(0, 0); // set curson
    lcd.print("Tech Room T=" + String(34) + " C");
    lcd.setCursor(0, 1);
    lcd.print("Tech Room H=" + String(44) + " %");
    lcd.setCursor(0, 2); // set curson
    lcd.print("Main Room T=" + String(31) + " C");
    lcd.setCursor(0, 3);
    lcd.print("Main Room H=" + String(43) + " %");
    previousMillis2 = currentMillis2;
    //delay(2000);
  }
}
//// END updateDisplay

//**** Get Time Stamp ****
String getTimeStamp() {
  String result;
  Process time;
  time.begin("date");
  time.addParameter("+%d/%m/%Y-%T");
  time.run();

  while (time.available() > 0) {
    char c = time.read();
    if (c != '\n')
      result += c;
  }

  return result;
}
//// END getTimeStamp

Here:

if (currentMillis - previousMillis >= interval) {
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
    previousMillis = currentMillis;
    // delay(2000);
  }

  currentMillis1 = millis();
  lcd.clear();   // <---------- THIS

Nick, I need to clear the display otherwise, the text will overlap.
The code works fine with the function delay().

//// LCD update
void updateDisplay() {
    lcd.clear();
     lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
  delay(2000);

   lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("H20 Temp is 40º C"); // display water temp
delay(2000);

  lcd.clear();
      lcd.setCursor(0, 0); // set curson
    lcd.print("Tech Room T=" + String(34) + " C");
    lcd.setCursor(0, 1);
    lcd.print("Tech Room H=" + String(44) + " %");
    lcd.setCursor(0, 2); // set curson
    lcd.print("Main Room T=" + String(31) + " C");
    lcd.setCursor(0, 3);
    lcd.print("Main Room H=" + String(43) + " %");
  
delay(2000);

}
//// END updateDisplay

Delta: I'm displaying
date time
clear
Temperatures from dhr sensors
Clear
Temperature from a thermister
Clear

But it's not the scope of my original question.

Ok, thanks

ebolisa:
Delta: I'm displaying
date time
clear
Temperatures from dhr sensors
Clear
Temperature from a thermister
Clear

You really should be doing:
Clear
date time

clear
Temperatures from dhr sensors

Clear
Temperature from a thermister

ebolisa:
Nick, I need to clear the display otherwise, the text will overlap.
The code works fine with the function delay().

If would make a lot more sense if you cleared it, just before writing to it, not just after.

if (currentMillis - previousMillis >= interval) {
    lcd.clear();   //  <--- clear before writing something else
    lcd.setCursor(0, 1); // col row
    lcd.print(getTimeStamp()); // display time date
    previousMillis = currentMillis;
  }

Ok, I see the problem (said the blind man).

The code below prints 3 lines of text at different time simulating my LCD text.

The problem is that the text stays on for a cycle which is too short for a display.

So going back to my original code/question, how do I use millis in place of delay() correctly?

Thank you.

#include <Bridge.h>
#include <Console.h>

/* https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */
unsigned long currentMillis = 0;
unsigned long currentMillis1 = 0;
unsigned long currentMillis2 = 0;
unsigned long previousMillis = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval = 6000;  // 6 secs display delay

void setup() {

  Bridge.begin();
  Console.begin();
  while (!Console);

  Console.println("Hi, I'm ready!");

}

void loop() {

  currentMillis = millis();

  Console.println(currentMillis);
  Console.println(previousMillis);
  Console.println(currentMillis - previousMillis);

  if (currentMillis - previousMillis >= interval) {

    Console.println("Do nice things");

    //previousMillis = currentMillis;
    previousMillis += interval;

  }

  currentMillis1 = millis();

  Console.println(currentMillis1);
  Console.println(previousMillis1);
  Console.println(currentMillis1 - previousMillis1);

  if (currentMillis1 - previousMillis1 >= interval) {

    Console.println("Do more nice things");

    //previousMillis1 = currentMillis1;
    previousMillis1 += interval;

  }

  currentMillis2 = millis();

  Console.println(currentMillis2);
  Console.println(previousMillis2);
  Console.println(currentMillis2 - previousMillis2);

  if (currentMillis2 - previousMillis2 >= interval) {

    Console.println("Do much more nice things");

    //previousMillis2 = currentMillis2;
    previousMillis2 += interval;

  }

}

how do I use millis in place of delay() correctly?

Save the millis() value at the time that the start action, such as display of data, happens. Then, each time through loop(), check whether the required wait period has elapsed by subtracting the start time from the millis() value now. If the period has elapsed then act accordingly, display the next data, and save the start time for the next activity. If not, then go round loop() again, perhaps taking other actions and/or reading inputs, but don't block the free running of loop().

Bob, that's what I'm doing with the code shown in my prior post. Not sure there's a different way to do it.

ebolisa:
Bob, that's what I'm doing with the code shown in my prior post. Not sure there's a different way to do it.

take a look at this:

#include <Bridge.h>
#include <Console.h>

/* https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */
unsigned long previousMillis0 = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval0 = 6000;  // 6 secs display delay
const long interval1 = 12000;
const long interval2 = 18000;

void setup()
{
  Bridge.begin();
  Console.begin();
  while (!Console);
  Console.println("Hi, I'm ready!");
}

void loop()
{
  unsigned long currentMillis = millis();  //catch the current value of millis()

  if (currentMillis - previousMillis0 >= interval0)  // compare first
  {
    Console.println("Do nice things");
    //previousMillis = currentMillis;
    previousMillis0 += interval0;
  }

  if (currentMillis - previousMillis1 >= interval1) // second 
  {
    Console.println("Do more nice things");
    previousMillis1 += interval1;
  }

  if (currentMillis - previousMillis2 >= interval2)  //and third time against value of millis for the turn of loop()
  {
    Console.println("Do much more nice things");
    previousMillis2 += interval2;
  }
}

Bulldog: Thank you, it worked!! I saved the 7 seconds which I was after.