我正在致力于构建一个基于ESP8266的世界时钟,启动后可以更改时区以查看世界各地不同地点的时间。 我的代码基于 NTP_TZ_DST 示例代码。出于测试目的,我已将代码精简为必需的内容。 我没有将 RTC 模块连接到 ESP8266。
我遇到的问题有两个。
在设置时间之前,我确认网络已启动并正在运行。 这是代码的输出(代码运行的实际时间是美国中部时间 11:27)
Starting in 200msecs...
.......
WiFi connected
IP address:
10.4.4.231
Manually setting some time from some RTC:
timezone: TZ_America_Chicago
settimeofday(USER)
timezone: TZ_America_Chicago
settimeofday(SNTP)
Sat Sep 30 16:27:35 2023
Sat Sep 30 16:27:45 2023
Button pressed, changing timezone to 1
timezone: TZ_Europe_Copenhagen
settimeofday(SNTP)
Sat Sep 30 16:27:55 2023
Sat Sep 30 16:28:05 2023
Button pressed, changing timezone to 0
timezone: TZ_America_Chicago
settimeofday(SNTP)
Sat Sep 30 16:28:15 2023
Sat Sep 30 16:28:25 2023
Starting in 200msecs...
.......
WiFi connected
IP address:
10.4.4.231
Manually setting some time from some RTC:
timezone: TZ_America_Chicago
settimeofday(USER)
timezone: TZ_America_Chicago
settimeofday(SNTP)
Sat Sep 30 16:27:35 2023
Sat Sep 30 16:27:45 2023
Button pressed, changing timezone to 1
timezone: TZ_Europe_Copenhagen
settimeofday(SNTP)
Sat Sep 30 16:27:55 2023
Sat Sep 30 16:28:05 2023
Button pressed, changing timezone to 0
timezone: TZ_America_Chicago
settimeofday(SNTP)
Sat Sep 30 16:28:15 2023
Sat Sep 30 16:28:25 2023
这是我的代码
#include "simple.h"
// initial time (possibly given by an external RTC)
#define RTC_UTC_TEST 1510592825 // 1510592825 = Monday 13 November 2017 17:07:05 UTC
#include <TZ.h>
////////////////////////////////////////////////////////
#include <ESP8266WiFi.h>
#include <coredecls.h> // settimeofday_cb()
#include <Schedule.h>
#include <PolledTimeout.h>
#include <arduino-timer.h>
#include <time.h> // time() ctime()
#include <sys/time.h> // struct timeval
#include <sntp.h> // sntp_servermode_dhcp()
// for testing purpose:
extern "C" int clock_gettime(clockid_t unused, struct timespec* tp);
////////////////////////////////////////////////////////
#define BUTTON_PIN D7
static timeval tv;
static timespec tp;
static time_t now;
static uint32_t now_ms, now_us;
static esp8266::polledTimeout::periodicMs showTimeNow(60000);
static int time_machine_days = 0; // 0 = present
static bool time_machine_running = false;
static bool time_machine_run_once = false;
static char timezones[2][21] = {"TZ_America_Chicago", "TZ_Europe_Copenhagen" };
uint8_t currentTimeZone = 0;
uint32_t buttonPressMillis = 0;
uint32_t ButtonPressThresshold = 50;
uint8_t lastButtonState = HIGH;
auto timer = timer_create_default();
uint8_t toks = 0;
void time_is_set(bool from_sntp /* <= this parameter is optional */) {
// in CONT stack, unlike ISRs,
// any function is allowed in this callback
if (time_machine_days == 0) {
if (time_machine_running) {
time_machine_run_once = true;
time_machine_running = false;
} else {
time_machine_running = from_sntp && !time_machine_run_once;
}
}
Serial.printf("timezone: %s\n", getenv("TZ") ?: "(none)");
Serial.print("settimeofday(");
if (from_sntp) {
Serial.print("SNTP");
} else {
Serial.print("USER");
}
Serial.println(")\n");
}
// check for button press
// button_pin is HIGH when not pressed
void CheckButtonPress() {
uint32_t currentMillis = millis();
// check for button press
if ( digitalRead( BUTTON_PIN ) == LOW ) {
if ( lastButtonState == HIGH ) {
lastButtonState = LOW;
buttonPressMillis = currentMillis;
}
return;
}
// button is not pressed
if ( lastButtonState == LOW ) {
lastButtonState = HIGH;
// check for duration to differenciate between short and long presses
if ( currentMillis - buttonPressMillis >= ButtonPressThresshold ) {
currentTimeZone = !currentTimeZone;
Serial.print( "\nButton pressed, changing timezone to " );
Serial.println( currentTimeZone );
configTime(timezones[currentTimeZone], "pool.ntp.org");
}
}
}
// called every 10 seconds by timer.
bool tok( void * ) {
now = time(nullptr);
Serial.print(ctime(&now));
return true;
}
void setup() {
WiFi.persistent(false);
WiFi.mode(WIFI_OFF);
Serial.begin(115200);
Serial.println("\nStarting in 200msecs...\n");
delay(200);
pinMode( BUTTON_PIN, INPUT );
// start network
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();
settimeofday_cb(time_is_set);
// setup RTC time
// it will be used until NTP server will send us real current time
Serial.println("Manually setting some time from some RTC:");
time_t rtc = RTC_UTC_TEST;
timeval tv = { rtc, 0 };
settimeofday(&tv, nullptr);
// ----> Here is the ONLY ONE LINE needed in your sketch
configTime(timezones[0], "pool.ntp.org");
// Give now a chance to the settimeofday callback,
// because it is *always* deferred to the next yield()/loop()-call.
yield();
if (timer.empty()) {
timer.every(10000, tok);
}
}
void loop() {
CheckButtonPress();
timer.tick();
}
有谁知道为什么它没有从 NTP 服务器检索到正确的时间? 更改时区后还需要采取其他步骤吗?
发现我的方法有错误。 configTime 调用中指定的时区是 PSTR 的名称,而不是提供给函数的实际字符串。因此,例如删除 TZ_America_Chicago 周围的引号就可以解决问题。