没有 delay() 的 Arduino 简单定时循环 - millis() 不起作用?

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

有一些非常接近工作的临时记录器的 arduino 代码....!

我已经建立了一个 OTA 例程,所以我可以远程更新它们,但是我必须确保它只每 15 分钟记录一次温度的 delay() 循环现在导致了问题,因为它按设计有效地冻结了 arduino 15 分钟,意味着 OTA 在这种状态下无法工作。

一些建议说只是转向 millis() 而不是,但我似乎无法让它工作,它现在每秒记录约 20 条记录。

理想情况下,我只想 delay_counter 计数到 DELAY_TIME 中的值,然后 运行 其余代码并重置计数器。

任何人都可以帮助我并指出我在我的代码中做的蠢事吗???


// 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;
}

设置一个TimerObjectthis 看来是你想要的。

  1. 从 github 下载 Arduino TimerObject code 并按照安装说明进行操作
  2. #include "TimerObject.h"
  3. 创建回调函数
  4. 创建 TimerObject
  5. 设置 TimerObject 并在您的 loop():
  6. 中定期调用 update()
// 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();
}

如果您不想在第一次调用 doSensor 时等待 15 分钟,您可以在启动计时器之前在 setup() 函数的末尾显式调用它。

这是一个如何使用 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

}

让它变得简单并使用简单的代码:

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
   }
}