Esp8266 定时器代替延迟

问题描述

我正在开发基于 ESP8266 微控制器的智能灌溉系统,该微控制器在 Arduino ide 上编码;基本上我想每 4 分钟向我的数据库发送一次温度数据,每 10 分钟检查一次传感器,或者在一段时间后执行任何代码,但我不想使用 delay(),因为同一循环中的其他代码应该继续执行。 那么,有没有办法使用另一个可以执行其余代码函数,并在定时器完成后执行发送到数据库? 谢谢

解决方法

Arduino 包管理器有一个名为 NTPClient 的库,如您所料,它提供了一个 NTP 客户端。将此与系统时钟结合使用,您可以在没有电池支持的 RTC 的情况下保持合理的时间。

一旦知道时间,安排活动就变得微不足道了。这不是一个完全有效的例子,但应该给你一个想法。文档有更多信息。 NTPClient 还可以与 AceTime 库很好地配合进行时区和其他管理。

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <AceTime.h>
#include <ctime>

using namespace ace_time;
using namespace ace_time::clock;
using namespace std;

WiFiUDP ntpUDP;
const long utcOffsetInSeconds = 0;  
// Get UTC from NTP - let AceTime figure out the local time
NTPClient timeClient(ntpUDP,"pool.ntp.org",utcOffsetInSeconds,3600);  
//3600s/h - sync time once per hour,this is sufficient.
// don't hammer pool.ntp.org!


static BasicZoneProcessor estProcessor;
static SystemClockLoop systemClock(nullptr /*reference*/,nullptr /*backup*/);

const char* ssid = // your SSID;
const char* password = // your wifi password;
 
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid,password);
  Serial.println("Connecting to wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println('.');
    delay(500);
  }
  systemClock.setup();
  timeClient.begin();
}

int clockUpdateCounter = 50000;  
void loop(){
  // Update the system clock from the NTP client periodically
  if (++clockUpdateCounter > 50000){  // can be more elegant than this... depends on your loop speed,can actually use the real time for this too,I'm just making this simple because I don't have a lot of time...
    clockUpdateCounter = 0;
    timeClient.update();
    // doesn't matter how often you call timeClient.update().
    // you can put this in the main loop() if you want.  
    // We supplied 3600s as the refresh interval in the constructor
    // and internally .update() checks whether enough time has passed 
    // before making a request to the NTP server itself
    auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto,&estProcessor);
    auto estTime = ZonedDateTime::forUnixSeconds(timeClient.getEpochTime(),estTz);
    // using the system clock is optional,but has a few 
    // conveniences.  Here we just make sure that the systemClock remains 
    // sync'd with the NTP server.  Doesn't matter how often you do this
    // but usually around once an hour is plenty
    systemClock.setNow(estTime.toEpochSeconds());
  }
  systemClock.loop();
  delay(30);
}

以上使系统时钟与 NTP 服务器保持同步。然后您可以使用系统时钟来获取时间并将其用于所有类型的计时目的。例如:

 // get Time
  acetime_t nowT = systemClock.getNow();
  auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto,&estProcessor);
  auto nowTime = ZonedDateTime::forEpochSeconds(nowT,estTz);

检查时间很快,因此您可以在 loop() 内进行,并且仅在任何时间过去后才触发操作。

这是一个特别好的数据库集成解决方案,因为您可以在将数据记录到数据库时记录实际日期和时间的真实时间戳。