ESP8266 使用 NTP_TZ_DST Arduino 示例代码获取错误时间

问题描述 投票:0回答:1

我正在致力于构建一个基于ESP8266的世界时钟,启动后可以更改时区以查看世界各地不同地点的时间。 我的代码基于 NTP_TZ_DST 示例代码。出于测试目的,我已将代码精简为必需的内容。 我没有将 RTC 模块连接到 ESP8266。

我遇到的问题有两个。

  1. 启动时我所在时区的时间不正确。休息了大约5个小时。
  2. 尝试更改时区时,似乎对时间没有任何影响。

在设置时间之前,我确认网络已启动并正在运行。 这是代码的输出(代码运行的实际时间是美国中部时间 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 服务器检索到正确的时间? 更改时区后还需要采取其他步骤吗?

arduino timezone esp8266
1个回答
0
投票

发现我的方法有错误。 configTime 调用中指定的时区是 PSTR 的名称,而不是提供给函数的实际字符串。因此,例如删除 TZ_America_Chicago 周围的引号就可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.