Hallo, ich bin gerade dabei, eine Terrariensteuerung zu realisieren und habe ein Problem bei der Synchronisierung des RTC über einen NTP. Hier das Minimalbeispiel:
#include <LiquidCrystal.h>
#include "clock_updater.h"
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void setup() {
RTC.begin();
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
//lcd.print("INITIALIZE");
Serial.begin(9600);
update_rtc();
}
//for update rtc
static unsigned long confirmed_start_time = 0;
unsigned long start_time;
//delay for the WiFi update (90000 = 15min, 60000 = 10 min, 30000 = 5min)
int update_delay = 600000;
//time till next loop
unsigned long confirmed_loop_time = 0;
unsigned long loop_time;
int loop_delay = 200;
void loop() {
start_time = millis();
//updates ntp after update_delay ms
if (start_time - confirmed_start_time > update_delay) //updates rtc
{
Serial.print("RTC time before update: ");
// Print out date (DD/MM//YYYY)
Serial.print(current_time.getDayOfMonth());
Serial.print("/");
Serial.print(Month2int(current_time.getMonth()));
Serial.print("/");
Serial.print(current_time.getYear());
Serial.print(" - ");
// Print time (HH/MM/SS)
Serial.print(current_time.getHour());
Serial.print(":");
Serial.print(current_time.getMinutes());
Serial.print(":");
Serial.println(current_time.getSeconds());
update_rtc();
confirmed_start_time = start_time;
RTC.getTime(current_time);
Serial.print("RTC time after update ");
// Print out date (DD/MM//YYYY)
Serial.print(current_time.getDayOfMonth());
Serial.print("/");
Serial.print(Month2int(current_time.getMonth()));
Serial.print("/");
Serial.print(current_time.getYear());
Serial.print(" - ");
// Print time (HH/MM/SS)
Serial.print(current_time.getHour());
Serial.print(":");
Serial.print(current_time.getMinutes());
Serial.print(":");
Serial.println(current_time.getSeconds());
}
loop_time = millis();
if (loop_time - confirmed_loop_time > loop_delay) {
RTC.getTime(current_time);
confirmed_loop_time = loop_time;
//float humidity = dht.readHumidity();
lcd.setCursor(0, 0);
int h_1 = current_time.getHour() / 10;
int h_2 = current_time.getHour() % 10;
int m_1 = current_time.getMinutes() / 10;
int m_2 = current_time.getMinutes() % 10;
int s_1 = current_time.getSeconds() / 10;
int s_2 = current_time.getSeconds() % 10;
lcd.print(String(h_1) + String(h_2) + ":" + String(m_1) + String(m_2)+":"+String(s_1)+String(s_2));
}
}
terraSteuerung.ino
#include "wifi_config.h"
WiFiUDP wifiudp;
NTP ntp(wifiudp);
const char *wifi_ssid=WIFI_SSID;
const char *wifi_pw=WIFI_PW;
const unsigned long timeout_connection=15000;
Month getMonth(int month){
switch (month) {
case 1: return Month::JANUARY; break;
case 2: return Month::FEBRUARY; break;
case 3: return Month::MARCH; break;
case 4: return Month::APRIL; break;
case 5: return Month::MAY; break;
case 6: return Month::JUNE; break;
case 7: return Month::JULY; break;
case 8: return Month::AUGUST; break;
case 9: return Month::SEPTEMBER; break;
case 10: return Month::OCTOBER; break;
case 11: return Month::NOVEMBER; break;
case 12: return Month::DECEMBER; break;
default: break;
}
}
DayOfWeek getDay(int day){
switch (day) {
case 0: return DayOfWeek::SUNDAY; break;
case 1: return DayOfWeek::MONDAY; break;
case 2: return DayOfWeek::TUESDAY; break;
case 3: return DayOfWeek::WEDNESDAY; break;
case 4: return DayOfWeek::THURSDAY; break;
case 5: return DayOfWeek::FRIDAY; break;
case 6: return DayOfWeek::SATURDAY; break;
default: break;
}
}
//for fixing:
int updates=0;
void update_rtc(){
unsigned long start_update_time=millis();
WiFi.begin(wifi_ssid,wifi_pw);
while(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
if(start_update_time+timeout_connection<millis()){//if the start of the connection takes longer than max_time, end this turn
Serial.println("connection error");
return;
}
}
delay(10000);
ntp.update();
if(ntp.year()<2000){
NTP ntp_tmp(wifiudp);
ntp_tmp.ruleDST("CEST", Last, Sun, Mar, 2, 120);
// CET: Central European Time
// start normal time last Sunday in October 3am GMT + 1h
ntp_tmp.ruleSTD("CET", Last, Sun, Oct, 3, 60);
ntp_tmp.begin();
ntp=ntp_tmp;
}
WiFi.end();
RTCTime update_time=RTCTime(ntp.day(), getMonth(ntp.month()), ntp.year(),ntp.hours(), ntp.minutes(), ntp.seconds(), getDay(ntp.weekDay()), SaveLight::SAVING_TIME_ACTIVE);
RTC.setTime(update_time);
RTC.getTime(current_time);
Serial.print("NTP time: ");
// Print out date (DD/MM//YYYY)
Serial.print(ntp.day());
Serial.print("/");
Serial.print(ntp.month());
Serial.print("/");
Serial.print(ntp.year());
Serial.print(" - ");
// Print time (HH/MM/SS)
Serial.print(ntp.hours());
Serial.print(":");
Serial.print(ntp.minutes());
Serial.print(":");
Serial.println(ntp.seconds());
updates++;
lcd.setCursor(0, 1);
lcd.print(String(updates));
}
clock_updater.ino
#pragma once
#include <WiFiS3.h>
#include <WiFiUdp.h>
#include <NTP.h>
#include "RTC.h"
RTCTime current_time;
void update_rtc();
clock_updater.h
Bei Initialisierung wird die Zeit korrekt dargestellt. Nach ein paar Stunden allerdings macht sich ein Drift der Uhrzeit zwischen RTC und tatsächlicher Uhrzeit einer Funkuhr bemerkbar. Dieser summiert sich auf, sodass nach etwa 12h die RTC um 1,5min hinterher läuft. Falls es hilft, habe ich exemplarisch ein paar Ausgaben vom Seriellen Monitor
RTC time after update 3/7/2024 - 8:1:29
RTC time before update: 3/7/2024 - 8:11:34
NTP time: 3/7/2024 - 8:11:29
RTC time after update 3/7/2024 - 8:11:29
RTC time before update: 3/7/2024 - 8:21:34
NTP time: 3/7/2024 - 8:21:29
RTC time after update 3/7/2024 - 8:21:29
RTC time before update: 3/7/2024 - 8:31:34
NTP time: 3/7/2024 - 8:31:29
RTC time after update 3/7/2024 - 8:31:29
RTC time before update: 3/7/2024 - 8:41:34
NTP time: 3/7/2024 - 8:41:29
RTC time after update 3/7/2024 - 8:41:29
Allerdings war es auf dem Funkwecker heute Morgen zum Update bereits 8:42:55.
Hat zufällig jemand von euch eine Ahnung, was diesen Drift verursacht und wie ich diesen beheben kann? Habe auf meinem r4 auch schon die Firmenware aktualisiert. Bevor ich jetzt das blinde Stochern anfange, frage ich lieber euch. Falls ihr noch Angaben braucht, um das Problem weiter einzugrenzen, sagt gerne Bescheid.
Grüße
Andy