Fabio Magarelli
Fabio Magarelli

Reputation: 1101

Arduino delay is not precise

I'm new to Arduino, I'm building a simple sensor circuit using a DHT22 and a SparkFun ESP8266 Thing Dev module which is programmable with Arduino.

In my loop code I want my device to wait 5min so I placed at the end delay(300000). The problem is that when I look into my database the timestamp when the data is collected by the sensor, sometimes it wait 2 minutes, sometimes 1 etc.

Furthermore, I have a logical check (if else) that should prevent my device to transmit data when the difference of temperature or humidity is less than 1. But my device seems not to care about it.

I'm sure there should be something wrong with my code but this is the first time I try to use C++ and Arduino so I wasn't able to figure out what just yet. Any help?

This is my code:


#include <DHT.h>

#include <ESP8266WiFi.h>

#include <DNSServer.h>            
#include <ESP8266WebServer.h>     
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager WiFi Configuration Magic

#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN,DHTTYPE);

// here I declare the variable of humidity and temperature. 
// every time it loops, it should get data from the sensor into 
// temp1 and hum1, then check it against temp and hum if there 
// are any changes in the values 
float temp;
float hum;
float temp1;
float hum1;

int red_light_pin = 16;
int green_light_pin = 12;
int blue_light_pin = 13;

// Server, file, and port
const char hostname[] = "laundryireland.tk";
const String uri = "/write_data?";
const String arguments[3] = {"serial=","&temp=","&hum="};
const int port = 80;

String serialNumber;

WiFiClient client;


void RGB_color(int red_light_value, int green_light_value, int blue_light_value)
 {
  analogWrite(red_light_pin, red_light_value);
  analogWrite(green_light_pin, green_light_value);
  analogWrite(blue_light_pin, blue_light_value);
}

void setup() {

  pinMode(red_light_pin,OUTPUT);
  pinMode(green_light_pin,OUTPUT);
  pinMode(blue_light_pin,OUTPUT);
  RGB_color(0,0,255);

  WiFi.persistent(false);
  WiFiManager wifiManager;

  //Initialize Serial
  Serial.begin(9600);
  dht.begin();
  delay(100);

  //Connect to WiFi
  Serial.println("Connecting...");
  wifiManager.autoConnect();
  while (WiFi.status() != WL_CONNECTED ) {

    delay(500);
    Serial.print(".");
  }


  //Show that we are connected
  Serial.println("Connected!");
  Serial.println(WiFi.localIP());

  serialNumber = WiFi.macAddress();

}

void loop() {
  delay(2000);
  temp1 = dht.readTemperature();
  hum1 = dht.readHumidity();
  while (temp1 == NULL || hum1 == NULL){
      RGB_color(255,0,0);
      delay(5000);
      temp1 = dht.readTemperature();
      hum1 = dht.readHumidity();
    }

// THIS IS MY IF STATEMENT TO CHECK FOR
// CHANGES IN TEMP OR HUM

  if (temp > temp1+1 || temp < temp1-1 || hum > hum1+1 || hum < hum1-1){
    temp = temp1;
    hum = hum1;

    RGB_color(0,255,0);
    Serial.print("Temperature: ");
    Serial.println(temp);
    Serial.print("Humidity: ");
    Serial.println(hum);

    Serial.println("Testing flask ");
    if ( client.connect(hostname,port) == 0 ) {
      Serial.println("Flask Test Failed!");
    } else {
      Serial.println("Flask Test Success!");
      client.print("GET " + uri + arguments[0] + serialNumber +
                    arguments[1] + temp +
                    arguments[2] + hum +
                    " HTTP/1.1\r\n" +
                    "Host: " + hostname + "\r\n" +
                    "Connection: close\r\n" +
                    "\r\n");
      delay(500);

      while (client.available()){
        String ln = client.readStringUntil('\r');
        Serial.print(ln);
      }
    }

    client.stop();
    Serial.println();
    Serial.println("Connection closed");

  } else {
    Serial.println("temp or hum not changed");
    RGB_color(255,255,0);
  }

// THIS SHOULD WAIT 5min BEFORE NEXT CHECK

  delay(300000);
}

This is how my database looks like:

database


Solution

Has pointed out by the commenters and well described in the accepted answer, the use of mills() instead of delay() solve the issue with "fake" delay time.

Furthermore, the problem of the transmission of data even when the difference between the previous update and the current one was less than 1; was just a logic problem with my if-else statement. I solved with this code:

 int deltaT = abs(temp-temp1);
    int deltaH = abs(hum-hum1);

    if (deltaT >= 1 || deltaH >= 1){
    // code here

Upvotes: 0

Views: 677

Answers (1)

mathertel
mathertel

Reputation: 144

The loop function will be called again 300000msec AFTER the loop has finished. So the time to the next recording is all the processing time of * 2000 at the beginning * the times for the functions dht.readTemperature() and dht.readHumidity(); * the time for sending bytes to the Serial output * the time for client.connect and the network transfer time... * and the 300000 at the end

A better approach is to get the current millis() from the system to check for 300000 msecs since the last reading. Then calculate the next time for measurement and then do your processing

You can use a static variable for this to keep code together:

void loop() {
  static unsigned long next = 0;
  unsigned long now = millis();

  if (now > next) {
    … do processing
    next = now + 300000;
  } // if
} // loop()

Upvotes: 2

Related Questions