Replace delay function with millisDelay

Can anyone amend my code to remove he delay function and replace it with millisDelay? I've read online that the delay function may be the cause of my problems that I'm having with the sketch taking up too much memory and possibly causing downtime on my wifi connection to the IoT cloud.

#include <BufferedInput.h>
#include <BufferedOutput.h>
#include <PinFlasher.h>
#include <SafeString.h>
#include <SafeStringNameSpace.h>
#include <SafeStringNameSpaceEnd.h>
#include <SafeStringNameSpaceStart.h>
#include <SafeStringReader.h>
#include <SafeStringStream.h>
#include <SerialComs.h>
#include <loopTimer.h>
#include <millisDelay.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include "thingProperties.h" // Include Arduino IoT Cloud Thing properties
#include <Arduino_ConnectionHandler.h>

const int SENSOR_PIN = 13; // Arduino pin connected to DS18B20 sensor's DQ pin

OneWire oneWire(SENSOR_PIN);         // setup a oneWire instance
DallasTemperature tempSensor(&oneWire); // pass oneWire to DallasTemperature library
LiquidCrystal_I2C lcd(0x3F, 16, 2);  // I2C address 0x3F (from DIYables LCD), 16 column and 2 rows

void setup() {
  Serial.begin(9600); // initialize serial
  delay(1500);
  
   // Connect to WiFi
  Serial.println("Attempting to connect to WiFi...");
  while (!WiFi.begin(SECRET_SSID, SECRET_OPTIONAL_PASS)) {
    Serial.println("Failed to connect to WiFi. Retrying...");
    delay(1000);
  }

  // Wait for WiFi connection to be established
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi!");
  
  // Initialize Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
  */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  // Defined in thingProperties.h
  initProperties();
  
  tempSensor.begin();    // initialize the sensor

  lcd.init();         // initialize the lcd
  lcd.backlight();    // open the backlight 
}

void loop() {
  tempSensor.requestTemperatures();             // send the command to get temperatures
  tempCelsius = tempSensor.getTempCByIndex(0);  // read temperature in Celsius

  Serial.print(tempCelsius);    // print the temperature in Celsius
  Serial.println("°C");

  lcd.clear();
  lcd.setCursor(0, 0);       // start to print at the first row
  lcd.print("CONCRETE TEMP:");  // print concrete temp wording
  lcd.setCursor(0, 1);       // start to print at the second row
  lcd.print(tempCelsius);    // print the temperature in Celsius
  lcd.print((char)223);      // print ° character
  lcd.print("C");

  ArduinoCloud.update(); // Update Arduino IoT Cloud
  delay(10000); // read temperature once every 15 minutes which is 900000 ms
}

// Function called when Concrete_Temperature property changes
void on_Concrete_Temperature_change() {
  // You can add custom behavior here if needed
}

what do you think the code needs to do during the delay period?

I'm reading online that the delay function can actually pause your code and cause it to get "stuck" during the time that it's in the delay period whereas if you use millisDelay, the code is still running it's just one specific function that is delayed.

I want a 15 minute delay between the collection of temperature data points and I don't want this delay to cause downtime between the connection of the UNO R4 wifi and the IoT cloud.

what has to be excuted to do that?

The millisDelay function shown here years ago -does- work but it's a good bit slower than non-blocking code as I demonstrated here years ago.

It's possible to replace delays with timing code, often callled millis-code that does not resort to context shifting interrupts and their associated overhead. I have a method I used to convert delay-ridden code that uses millis/micros timing combined with a state machine that always works. Many members here know it, I believe. and the un-delay examples are in the archives.

I go to cataract surgery today and next week but after that I'd be happy to show and explain how to write functions that run as parallel tasks in void loop() with NO O/S or interrupts. Those tasks run independently but can coordinate and cooperate through shared global variables to run very fast, void loop can be kept up to 50 kHz and higher speed, there is a lean function to show that I use to check on the impact of code changes in non-blocking sketches.

Remember that delay(1) wastes 16000 cpu cycles.
Every AVR interrupt requires a minimum of 85 cycles plus whatever the interrupt service code does, they make poor work-arounds for tasking and they use up interrupts some libraries need! There are better, indispensable uses for interrupts than get around code.. save interrupts for that and your tasks will be more reusable not to mention run faster.

People used to depending on an O/S to do it for them get into ruts where they HAVE TO have work-around bail-outs.

2 Likes

I'm not going to worry about the setup() function, but this one is really simple...

void loop() {
  static unsigned long cycleTimestamp = millis();
  if (millis() - cycleTimestamp >= 1000UL) {
    cycleTimestamp += 1000UL;
    tempSensor.requestTemperatures();             // send the command to get temperatures
    tempCelsius = tempSensor.getTempCByIndex(0);  // read temperature in Celsius
    Serial.print(tempCelsius);    // print the temperature in Celsius
    Serial.println("°C");
    lcd.clear();
    lcd.setCursor(0, 0);       // start to print at the first row
    lcd.print("CONCRETE TEMP:");  // print concrete temp wording
    lcd.setCursor(0, 1);       // start to print at the second row
    lcd.print(tempCelsius);    // print the temperature in Celsius
    lcd.print((char)223);      // print ° character
    lcd.print("C");
    ArduinoCloud.update(); // Update Arduino IoT Cloud
  }
}

See the tutorial on blink without delay for more information.

1 Like

How that condition can ever be true?

Test it and see it will be true every 1000 milliseconds.

static unsigned long cycleTimestamp = millis();

As this is a static local, this line is only executed once ever to initialize the variable. If this is over your head, you can also structure it as follows:

unsigned long cycleTimestamp;

setup() {
  //...
  cycleTimestamp = millis();
}

loop () {
  if (millis() - cycleTimestamp >= 1000UL) {
  cycleTimestamp += 1000UL;
  //...
  }
}

Of course! My brain fart :worried:

Is this topic a same question as ?

millisDelay.h is a library:

but it isn't a drop-in replacement for delay(). It just sets up millis()-based timers with classes and you still need to re-structure your code to be non-blocking.

1 Like

When you are doing one thing at a time, delay() makes no difference. The place it makes a difference is when the part that is delayed is keeping other code from running.

But now you can add other non-blocking functions to perhaps monitor ambient temperature or have buttons to decrease/increase the report period.

ALL -- I'm back from surgery on the worst eye, pupil still dilated and eye feels sort of scratched but already less blurry. The other eye gets done next week.

2 Likes

Yes

Is there any chance you'd be open to a video call with me to diagnose the issue I'm having? I'm a complete novice at coding and I can't for the life of me fix the arduino since I've updated the firmware. It collects two data points and then reads an error code, see the link here for the error

Do you think this would solve the error I'm seeing? See the error here. Sorry for late reply, I've been on holiday. I'm also a complete novice at this, i've pieced together the code from different blog posts and online forums and tried to put this together.

I can't repeat what you're doing since I don't have an Uno R4.

The code you show in that thread uses a library I don't have or is not complete since read temperatures function isn't in what you do show.

"fix the Arduino".... or fix the sketch?

Right now, we would be using terms differently and not understanding what the other means, leading to communication errors between us.

There are many unknowns at the same time.
Which unknown is causing which problem won't be apparent and that easily leads to fixing what isn't broken... and adding bugs as a result.
Trouble-shooting involves reducing unknowns to one then fixing that. It's done one piece at a time instead of on the whole by guessing what to change.

Where we left off, you were getting advice to make changes that I don't see any of done. Was it running good and solid before you changed the firmware? What happens when you change the firmware back? Why change what worked unless it didn't?

because the static variable only gets set the first time, when it is created. After that it stays and does not get reset.

For beginners it is more clear to make a global variable and set it to millis() in setup(). The difference is that only loop() has access to the local-to-loop() static variable.

ALL.... I can see now. Still doing eye drops but YOW what a difference! In a month I may have glasses and see 20-20 but close already and web pages that hurt my eyes before, don't!

1 Like

The sketch worked fine before I updated the firmware. I updated the firmware as I was seeing downtime in the connectivity between the R4 Wifi and the IoT cloud and a possible solution to this was to update the firmware. That is when my problem first started. I didn't know it was possible to change the firmware back. I'll look into this.

@GoForSmoke dunno how bad it got for you… my father, after he got his new eyes, sounded like a teenager on LSD…

Most alarming was his report that STOP signs are red.

a7

1 Like