Guten Abend, ich hab zwei Möglichkeiten, meine Sommer- und Winterzeit-Umstellung in einer kleinen Uhr zu implementieren. - Triggern, wenn der letzte Sonntag im März 2:00 / Oktober 3:00 ist und die Zeit um eine Stunde vor oder zurück stellen. - Die Zeit intern immer auf Winterzeit lassen und berechnen, ob das Aktuelle Datum + Zeit in der Sommerzeit liegt und dann einfach nur anders anzeigen. Die erste Version gefällt mir nicht, weil ich eine RTC habe, die mit einem Supercap gepuffert ist. D.h. der Trigger könnte einfach übersehen werden, wenn die Uhr aus ist, aber die RTC weiter läuft. Die zweite Version ist zwar sicherer, aber die Uhr-Einstellung ist schwieriger. Beispielsweise müsste man auch noch einen Überlauf der Stunden auf den nächsten Tag oder nächsten Monat implementieren, der bei Stunde+1 passieren könnte. Wenn man dann Zeit und Datum einstellt, muss man das alles wieder zurück auf die Winterzeit rechnen, was dann auch wieder doof ist. Wie habt ihr das so gemacht? *edit*: Hmm, zu Version 1 könnte ich im Backup RAM noch speichern, ob zuletzt Winter- oder Sommerzeit "gesehen" wurde und dann ermitteln, ob sich das geändert hat und dann entsprechend korrigieren. Dann würde ich den Trigger nicht verpassen ...
:
Bearbeitet durch User
Mampf F. schrieb: > - Triggern, wenn der letzte Sonntag im Oktober 3:00 ist und > die Zeit um eine Stunde zurück stellen. Also: .. Okt 2:58 Okt 2:59 Okt 3:00 -> Okt 2:00 Okt 2:01 Okt 2:02 .. Okt 2:58 Okt 2:59 Okt 3:00 -> Okt 2:00 Okt 2:01 Okt 2:02 .. Okt 2:58 Okt 2:59 Okt 3:00 -> Okt 2:00 Okt 2:01 Okt 2:02 .. Ungefähr so? ;) Mampf F. schrieb: > *edit*: Hmm, zu Version 1 könnte ich im Backup RAM noch speichern, ob > zuletzt Winter- oder Sommerzeit "gesehen" wurde und dann ermitteln, ob > sich das geändert hat und dann entsprechend korrigieren. Dann würde ich > den Trigger nicht verpassen ... Nicht "könnte", sondern "muss". ---- Wie "klein" ist denn die Uhr? Sprich, auf welche Werkzeuge kannst Du zurückgreifen? Prinzipiell fände ich die Option "Die Zeit intern immer auf Winterzeit lassen und berechnen, ob das Aktuelle Datum + Zeit in der Sommerzeit liegt und dann einfach nur anders anzeigen." komfortabler.
Wenn du die RTC abfragst, kannst du ja feststellen, ob du dich im Intervall 'Last Sunday in Oktober' bis 'Lest Sunday in March' befindest und dann entweder die RTC stellen, Flag setzen oder nur fürs Display umrechnen. Dann verschwendest du nix vom Supercap, weil das nur passiert, wenn der Core läuft.
:
Bearbeitet durch User
Matthias S. schrieb: > Wenn du die RTC abfragst, kannst du ja feststellen, ob du dich im > Intervall 'Last Sunday in Oktober' bis 'Lest Sunday in March' befindest > und dann entweder die RTC stellen, Flag setzen oder nur fürs Display > umrechnen. Dann verschwendest du nix vom Supercap, weil das nur > passiert, wenn der Core läuft. Hmm ja, im Grunde ist das einfach, aber die ganzen Grenzfälle bereiten mir etwas Kopfzerbrechen (die in der Praxis vmtl niemals vorkommen würden). Beispielsweise zu Variante 2: Die Uhr wird gestartet und festgestellt, dass das letzte mal als sie gelaufen ist noch Sommerzeit war und jetzt ist Winterzeit. Aber der RTC-Counter (zählt von 0 bis 24*60*60) ist noch auf einem Zählerstand von <60*60, dann würde die Subtraktion vom Zähler wieder eine Korrektur im Datum erfordern. Ich glaube mein Problem ist, dass die RTC so saudumm implementiert ist... Vlt sollte ich einfach Sekunden seit 2000 verwenden ... Das würde zumindest noch 50 Jahre funktionieren und ich müsste aus den Sekunden nur das Datum herausrechnen. Die aktuelle Implementierung - von HAL inspiriert, vielen Dank an ST! ? - ist so, dass der RTC-Counter quasi nur die Sekunden pro Tag zählt, das Datum wird quasi in den Backup-Registern mitgeführt. Wir der Core neu gestartet aktualisiert der Code das Datum so lange, bis der RTC-Counter wieder innerhalb einer Tagesgrenze ist. Der STM32F103 hat leider keinen richtigen Calendar eingebaut.
Achim H. schrieb: > Ungefähr so? ;) Nicht ganz ... Letzter Sonntag im März um 2Uhr wird auf 3Uhr umgestellt. Letzter Sonntag im Oktober von 3Uhr auf 2Uhr. > Wie "klein" ist denn die Uhr? Sprich, auf welche Werkzeuge kannst Du > zurückgreifen? Oh, die ist ganz ordentlich ausgestattet ... STM32F103 mit 64kB Flash und 20kB RAM. Mit dem Clock von 48MHz kann ich da viel Rechenzeit verschwenden ohne, dass man es merkt :) > Prinzipiell fände ich die Option "Die Zeit intern immer auf Winterzeit > lassen und berechnen, ob das Aktuelle Datum + Zeit in der Sommerzeit > liegt und dann einfach nur anders anzeigen." komfortabler. Ja, würde das Uhr einstellen verkomplizieren ... Aber ich denke auch fast ...
Mampf F. schrieb: > - Die Zeit intern immer auf Winterzeit lassen und berechnen, ob das > Aktuelle Datum + Zeit in der Sommerzeit liegt und dann einfach nur > anders anzeigen. So mache ich das auch. Die RTC zählt 32Bit Sekunden Normalzeit und erst die Ausgaberoutine rechnet in menschliches Zeitformat und dann in Sommerzeit um. Beim Stellen der Stunden (t+=3600) kann es passieren, daß mal 2 Stunden weitergezählt wird und mal nicht weitergezählt wird. Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit"
:
Bearbeitet durch User
Peter D. schrieb: > Mampf F. schrieb: >> - Die Zeit intern immer auf Winterzeit lassen und berechnen, ob das >> Aktuelle Datum + Zeit in der Sommerzeit liegt und dann einfach nur >> anders anzeigen. > > So mache ich das auch. > Die RTC zählt 32Bit Sekunden Normalzeit und erst die Ausgaberoutine > rechnet in menschliches Zeitformat und dann in Sommerzeit um. > Beim Stellen der Stunden (t+=3600) kann es passieren, daß mal 2 Stunden > weitergezählt wird und mal nicht weitergezählt wird. > > Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit" Wunderbar, ich glaube ich schmeiße meinen aktuellen Ansatz weg und integriere deine Version :) *edit*: Hmm, mein ARM-GCC hat auch includes für <time.h> ... Vlt sollte ich mal mktime oder localtime_r testen^^
:
Bearbeitet durch User
Was soll denn die Uhr gesehen haben müssen? Eine ordentliche Uhr mit Sommer-/Winterzeit gibt es nur mit mitlaufendem Kalender. Oder man nimmt DCF, wo das genau so von der PTB gemacht wird. Um es ohne DCF übersichtlich zu programmieren, lässt du die Uhr (und die RTC) in unbeirrbarer (außer Schaltsekunden) UTC laufen. Je nach Kalender und Zeitzone wird daraus die ME(S)Z, oder sonstwas errechnet und zur Anzeige gebracht. Und beim Stellen der Uhr geht die Eingabe mit entsprechendem kalendergerechtem utc-Versatz in die Uhr und die RTC. Das lässt sich in sehr kleinen µCs unterbringen.
Mampf F. schrieb: > Wie habt ihr das so gemacht? Zwei 32 Bit Zahlen im System: kanonischer Tag (ab 1.1.2000) und kanonische Uhrzeit (in 1 ms Einheiten). Für Datum und Uhr einen RTC von Seiko-Epson per I2C und 0.22F im System. Dazu beim Startup des Gerätes (Einschalten) oder Mitternacht die Systemuhr eingerichtet (für kanonischen Tag und Zeit) und diese Systemuhr mit dem RTC einmal richtig synchronisiert. Im System werden nur die obigen 2 long Zahlen verwendet. Stellt der Kunde die Uhr, dann nur auf den RTC wirkend. Anschließend das obige Synchronisieren. W.S.
Peter D. schrieb: > So mache ich das auch. > Die RTC zählt 32Bit Sekunden Normalzeit und erst die Ausgaberoutine > rechnet in menschliches Zeitformat und dann in Sommerzeit um. > Beim Stellen der Stunden (t+=3600) kann es passieren, daß mal 2 Stunden > weitergezählt wird und mal nicht weitergezählt wird. > > Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit" Ahja C ist ja wieder mal ein geiler Scheiß ;-) Dein Code leicht umgeschrieben:
1 | void gettime(uint32_t sec, RTC_TimeTypeDef_H24* time, RTC_DateTypeDef *date) { |
2 | uint16_t day; |
3 | uint16_t year; |
4 | uint8_t month; |
5 | |
6 | time->RTC_Seconds = sec % 60; |
7 | sec /= 60; |
8 | time->RTC_Minutes = sec % 60; |
9 | sec /= 60; |
10 | time->RTC_Hours = sec % 24; |
11 | day = sec / 24; |
12 | |
13 | year = STARTYEAR; |
14 | for (int dpy;day>=(dpy=365+rtc_isLeapYear(year));day-=dpy,year++); |
15 | date->RTC_Year = year - STARTYEAR; |
16 | month = 1; |
17 | for (int dpm;day>=(dpm=rtc_daysPerMonth(month,year));day-=dpm,month++); |
18 | |
19 | date->RTC_Month = month; |
20 | date->RTC_Date = day + 1; |
21 | }
|
Kommt sogar das richtige raus^^ Hab mit 1Mio Zufalls-Zeiten und Daten getestet ... Jeweils den Weg Time+Date -> Timestamp und wieder zurück. Den Timestamp bekomme ich über
1 | uint32_t rtc_getTimestamp(RTC_TimeTypeDef_H24 *time, RTC_DateTypeDef *date) { |
2 | uint32_t timestamp = 0; |
3 | // add year
|
4 | uint32_t days = 0; |
5 | for (int y = STARTYEAR; y < date->RTC_Year + STARTYEAR; y++) { |
6 | days += 365 + rtc_isLeapYear(y); |
7 | }
|
8 | // add month
|
9 | for (int m = 1; m < date->RTC_Month; m++) { |
10 | days += rtc_daysPerMonth(m, date->RTC_Year + STARTYEAR); |
11 | }
|
12 | // add remaining days
|
13 | days += date->RTC_Date - 1; |
14 | |
15 | timestamp += days * 24l * 60l * 60l; // days to seconds |
16 | timestamp += time->RTC_Hours * 60l * 60l; |
17 | timestamp += time->RTC_Minutes * 60l; |
18 | timestamp += time->RTC_Seconds; |
19 | return timestamp; |
20 | }
|
Quasi das gleiche nur andersherum. Und die (kanonischen) Helferlein:
1 | uint8_t rtc_isLeapYear(uint16_t nYear) { |
2 | if ((nYear % 4) != 0) { |
3 | return 0; |
4 | }
|
5 | |
6 | if ((nYear % 100) != 0) { |
7 | return 1; |
8 | }
|
9 | |
10 | if ((nYear % 400) == 0) { |
11 | return 1; |
12 | } else { |
13 | return 0; |
14 | }
|
15 | }
|
16 | |
17 | uint8_t rtc_daysPerMonth(int m, int y) { |
18 | if (m < 1 || m > 12) |
19 | return 0; |
20 | |
21 | uint8_t dpm[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
22 | if (m == 2) |
23 | return dpm[m - 1] + (rtc_isLeapYear(y) ? 1 : 0); |
24 | else
|
25 | return dpm[m - 1]; |
26 | }
|
:
Bearbeitet durch User
Meine Geräte arbeiten intern immer mit UTC/Unixzeit. Die Ausgabe erfolgt dann in MEZ/MESZ oder welche Zeitzone auch immer. Den Tag der Uhrenumstellung kann man in eine Tabelle packen....
tnsz schrieb: > Meine Geräte arbeiten intern immer mit UTC/Unixzeit. Die Ausgabe > erfolgt > dann in MEZ/MESZ oder welche Zeitzone auch immer. Den Tag der > Uhrenumstellung kann man in eine Tabelle packen.... Ja, ich mach es jetzt auch so. Ist viel einfacher, wenn man einen Sekunden-Timestamp und die Konvertierungsfunktionen von timestamp zu time+date und andersherum hat. Ich hatte irrtümlich geglaubt, ich könnte mir das sparen - macht alles aber nur viel komplizierter.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.