Alphatester77
Alphatester77

Reputation: 702

Arduino simple timed loop without delay() - millis() doesn't work?

Have some arduino code for temp loggers that is VERY NEARLY working....!

I've built an OTA routine so I can update them remotely, however the delay() loop I had to ensure it only logged temperatures every 15 mins is now causing problems as it effectively freezes the arduino by design for 15mins, meaning OTA wouldn't work whilst it is in this state.

Some suggestions say just to flip to millis() instead, but I can't seem to get this working and it's logging ~20 records every second at the moment.

Ideally I just want delay_counter counting up to the value in DELAY_TIME, then running the rest of the code and resetting the counter.

Can anyone help me and point out what I'm doing daft in my code???


// v2 Temp sensor
// Connecting to Home NAS

#include <DHT.h>
#include <DHT_U.h>


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <InfluxDbClient.h>



#define SSID "xxx" //your network name
#define PASS "xxx" //your network password
#define VersionID "v3"


#define SensorName "ServerUnit" //name of sensor used for InfluxDB and Home Assistant
// Temp Sensor 1 - GardenTropical
// Temp Sensor 2 - GardenRoom
// Temp Sensor 3 - Greenhouse
// Temp Sensor 4 - OutsideGreenhouse
// Temp Sensor 5 - ServerUnit

// Connection Parameters for Jupiter InfluxDB
#define INFLUXDB_URL "http://192.168.1.5:8086"
#define INFLUXDB_DB_NAME "home_assistant"
#define INFLUXDB_USER "xxx"
#define INFLUXDB_PASSWORD "xxx"


// Single InfluxDB instance
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);
// Define data point with measurement name 'DaveTest`
Point sensor("BrynyneuaddSensors");


#define PORT 80
#define DHTPIN 4     // what pin the DHT sensor is connected to
#define DHTTYPE DHT22   // Change to DHT22 if that's what you have
#define BAUD_RATE 115200 //Another common value is 9600
#define DELAY_TIME 900000 //time in ms between posting data to Home Server
unsigned long delay_counter = 0;

DHT dht(DHTPIN, DHTTYPE);


//this runs once
void setup()
{
  Serial.begin(BAUD_RATE);

  // Connect to WIFI
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print("*");
  }

  // Initialise OTA Routine
   ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());



  //initalize DHT sensor
  dht.begin();

  // set InfluxDB database connection parameters
  client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME, INFLUXDB_USER, INFLUXDB_PASSWORD);

  // Add constant tags - only once
  sensor.addTag("device", SensorName);

  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
    Serial.println(client.getServerUrl());
    Serial.println("Exiting DB Connection");

  }

}

//this runs over and over
void loop() {
  ArduinoOTA.handle();


  float h = dht.readHumidity();
  Serial.print("Humidity: ");
  Serial.println(h);
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float c = dht.readTemperature();
  Serial.print("Temperature: ");
  Serial.println(c);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(c)) {
    Serial.println("Reading DHT22 Failed, exiting");
    return;
  }

  //update Influx DB channel with new values
  updateTemp(c, h);

  Serial.print("Writing to InfluxDB: ");


  //INFLUXDB - clear temp data so it doesn't repeat
  sensor.clearFields();

  // Update Influx DB
  sensor.addField("Temperature", c);
  sensor.addField("Humidity", h);

  Serial.println(sensor.toLineProtocol());
  // Write data
  client.writePoint(sensor);

  //wait for delay time before attempting to post again
  if(millis() >= DELAY_TIME){
        delay_counter += 0;
        }

    //Increment Delay Counter
    delay_counter++;
}


bool updateTemp(float tempC, float humid) {

  WiFiClient client;    // Create a WiFiClient to for TCP connection


  Serial.println("Receiving HTTP response");
  while (client.available()) {
    char ch = static_cast<char>(client.read());
    Serial.print(ch);
  }
  Serial.println();


  Serial.println("Closing TCP connection");
  client.stop();
  return true;
}

Upvotes: 0

Views: 1511

Answers (3)

Codebreaker007
Codebreaker007

Reputation: 2989

Make it simole and use easy code:

const unsigned long timeIntervall = 15*60*1000; // 15 minutes
unsigned long timeStamp = 0;

void setup(){....}

void loop() {
  ArduinoOTA.handle(); // is running all the time

  // Code in this section only runs every timeIntervall - rollover safe
  if(millis() - timeStamp > timeIntervall ){

  float h = dht.readHumidity();
 ......
  // Write data
  client.writePoint(sensor);

  timeStamp = millis();  // reset the timer
   }
}

Upvotes: 1

Maxim Sagaydachny
Maxim Sagaydachny

Reputation: 2218

Here is an simple example how to use millis()


int last_report = -777;//dummy value

int REPORT_INTERVAL = 15 *60 ; // 15 minutes

void loop() {

  ArduinoOTA.handle();

  int interval = millis() / 1000 - last_report;

  if (interval < REPORT_INTERVAL) {
    return;
  }

  last_report = millis() / 1000;

  //do some important stuff

}

Upvotes: 2

JohnFilleau
JohnFilleau

Reputation: 4288

Set a TimerObject. this seems to be what you want.

  1. Download the Arduino TimerObject code from github and follow the installation instructions
  2. #include "TimerObject.h"
  3. Create the callback function
  4. Create the TimerObject
  5. Setup the TimerObject and periodically call update() in your loop():
// make sure to include the header
#include "TimerObject.h"

...

// setup your TimerObject
TimerObject* sensor_timer = new TimerObject(15 * 60 * 1000); // milliseconds

...

// define the stuff you want to do every 15 minutes and
// stick it in a function
// not sure what from your loop() needs to go in here
void doSensor()
{
  float h = dht.readHumidity();
  Serial.print("Humidity: ");
  Serial.println(h);
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float c = dht.readTemperature();
  Serial.print("Temperature: ");
  Serial.println(c);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(c)) {
    Serial.println("Reading DHT22 Failed, exiting");
    return;
  }

  //update Influx DB channel with new values
  updateTemp(c, h);

  Serial.print("Writing to InfluxDB: ");


  //INFLUXDB - clear temp data so it doesn't repeat
  sensor.clearFields();

  // Update Influx DB
  sensor.addField("Temperature", c);
  sensor.addField("Humidity", h);

  Serial.println(sensor.toLineProtocol());
  // Write data
  client.writePoint(sensor);
}

...

// add the timer setup to your setup()
// probably at the end is a good place
void setup()
{
    ...
    // lots of stuff above here
    sensor_timer->setOnTimer(&doSensor);
    sensor_timer->Start();
}

// modify your loop() to check the timer on every pass
void loop()
{
    ArduinoOTA.handle();

    sensor_timer->Update();
}

If you don't want to wait 15 minutes for the first call of doSensor, you can explicitly call it at the end of your setup() function before you start the timer.

Upvotes: 4

Related Questions