Sommer- und Normalzeitermittlung

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Das ist doch nicht schlimm. getdate holt die Zeit aus der rtc in die softclock. Jetzt mit dieser Zeit und Datum und Wochentag feststellen, ob man im Sommerzeitbereich ist. Wenn ja, softclock korrigieren und Datumüberlauf mit Wochentagüberlauf prüfen und ggf. anpassen. Was du nicht machen darfst, ist settime und damit deine rtc aus Versehen auf Sommerzeit setzen. Das ist alles.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Pluto25 schrieb:

      Klingt alles nach viel Rechnerei.
      Stimmt, kann man auch weg lassen und dann im Protokoll zum Einbruch einfach die Zeit mit 'MEZ' kennzeichnen. Dann kann der geneigte Protokollleser selber die genaue Uhrzeit rausknobeln.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Pluto25 schrieb:

      aber eine SMS hat einen Zeitstempel daher ist die Uhr unnötig.
      Ja, hat sie, aber es kann vorkommen, dass man den Inhalt einer SMS auswerten möchte.
      Darüber hinaus gibt es einen lokalen LOG, da sollte die Zeit auch nicht nur ungefähr sein (ich weiß, ich bin ein Perfektionist :D )

      tschoeatsch schrieb:

      Datumüberlauf mit Wochentagüberlauf prüfen...
      Das braucht es, so wie es jetzt aussieht nicht.
      So wie es aussieht, wird der Wochentag aus der SysSec mit DayOfWeek ermittelt. da gibt es keinen Überlauf.
      Das einzige Problem was ich jetzt noch habe, ist dass, das ganze wohl nur bis 2068-01-19 03:14:07 funktioniert, dann ist die Long voll ^^ .
    • Zitronenfalter schrieb:

      Das einzige Problem was ich jetzt noch habe, ist dass, das ganze wohl nur bis 2068-01-19 03:14:07 funktioniert, dann ist die Long voll .
      Hm, dann warten wir mal auf ein update von bascom, wo dann mit dword gearbeitet wird. :D
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Ich habe das jetzt noch nicht auf alle Eventualitäten überprüft. Aber in etwa so sollte jetzt die Sommerzeit korrekt erkannt werden und Zeit und Datum korrekt ausgegeben werden.

      BASCOM-Quellcode

      1. Sub IsSummertime()
      2. Local fD As Byte
      3. Local fX As Byte
      4. Local fW As Byte
      5. Status.Status_IsSummertime = 0
      6. Select Case RTC_Month
      7. Case 3 ' Monat Maerz
      8. If RTC_Day > 24 Then ' Pruefe auf letzten Sonntag
      9. fD = RTC_Day
      10. For fX = 25 To 31
      11. fW = DayOfWeek(RTC_Day)
      12. If fW = 6 Then ' =letzter Sonntag
      13. Exit For
      14. End If
      15. Incr RTC_Day
      16. Next
      17. If fX > fD Then ' Jedenfalls SZ
      18. Status.Status_IsSummertime = 1
      19. ElseIf fX = fD And RTC_Hour >= 2 Then ' So + >=2:00Uhr->SZ
      20. Status.Status_IsSummertime = 1
      21. End If
      22. RTC_Day = fD
      23. End If
      24. Case 4 To 9 ' Monate April bis September
      25. Status.Status_IsSummertime = 1
      26. Case 10 ' Monat Oktober
      27. If RTC_Day < 24 Then ' Jedenfalls SZ
      28. Status.Status_IsSummertime = 1
      29. Else ' Pruefe auf letzten Sonntag
      30. fD = RTC_Day
      31. For fX = 25 To 31
      32. fW = DayOfWeek(RTC_Day)
      33. If fW = 6 Then ' =letzter Sonntag
      34. Exit For
      35. End If
      36. Incr RTC_Day
      37. Next
      38. If fX < fD Then ' Jedenfalls SZ
      39. Status.Status_IsSummertime = 1
      40. ElseIf fX = fD And RTC_Hour < 2 Then ' So + <2:00Uhr->SZ
      41. Status.Status_IsSummertime = 1
      42. End If
      43. RTC_Day = fD
      44. End If
      45. End Select
      46. End Sub
      47. Function GetDate() As String
      48. GetDate = Date$
      49. GetDate = Date(RTC_SysSec)
      50. End Function
      51. Function GetTime() As String
      52. GetTime = Time$
      53. GetTime = Time(RTC_SysSec)
      54. End Function
      Alles anzeigen
      Hier noch die drei Subroutinen für die User-Clock.
      In der GetDateTime wird die Sommerzeit abgehandelt

      Quellcode

      1. SetDate:
      2. _day = Makebcd(_day)
      3. _month = Makebcd(_month)
      4. _year = Makebcd(_year)
      5. RTC_WeekdayH = RTC_Weekday + 1
      6. I2cstart
      7. I2cwbyte RTC_Clock_I2C
      8. I2cwbyte 3
      9. I2cwbyte RTC_WeekdayH
      10. I2cwbyte _day
      11. I2cwbyte _month
      12. I2cwbyte _year
      13. I2cstop
      14. Return
      15. SetTime:
      16. _sec = Makebcd(_sec)
      17. _min = Makebcd(_min)
      18. _hour = Makebcd(_hour)
      19. I2cstart
      20. I2cwbyte RTC_Clock_I2C
      21. I2cwbyte 0
      22. I2cwbyte _sec
      23. I2cwbyte _min
      24. I2cwbyte _hour
      25. I2cstop
      26. Return
      27. GetDateTime:
      28. I2cstart
      29. I2cwbyte RTC_Clock_I2C
      30. I2cwbyte 0
      31. I2cstart
      32. I2cwbyte RTC_Clock_I2Cread
      33. I2crbyte _sec , Ack
      34. I2crbyte _min , Ack
      35. I2crbyte _hour , Ack
      36. I2crbyte RTC_WeekdayH , Ack
      37. I2crbyte _day , Ack
      38. I2crbyte _month , Ack
      39. I2crbyte _year , Nack
      40. I2cstop
      41. _day = Makedec(_day)
      42. _month = Makedec(_month)
      43. _year = Makedec(_year)
      44. _sec = Makedec(_sec)
      45. _min = Makedec(_min)
      46. _hour = Makedec(_hour)
      47. RTC_Weekday = RTC_WeekdayH - 1
      48. RTC_Second = _sec
      49. RTC_Minute = _min
      50. RTC_Hour = _hour
      51. RTC_Day = _day
      52. RTC_Month = _Month
      53. RTC_Year = _year
      54. RTC_SysSec = SysSec()
      55. IsSummertime
      56. If Status.Status_IsSummertime = 1 Then
      57. RTC_SysSec = RTC_SysSec + 3600 ' eine Stunde hinzufuegen
      58. End If
      59. Return
      Alles anzeigen
    • Ich trau mich nicht zB. _sec und die weiteren Systemvariablen zu wandeln und dann für die I2c-Übertragung zu verwenden. Diese subs können ja durch einen interrupt unterbrochen werden und der könnte ja auch zufällig von der softclock kommen, die grad die Sekunde weiter stellt. Das kann dann alles vermurksen. Wäre aber schon ein großer Zufall, das gebe ich zu.

      Deine Funktionen gettime() und getdate() verstehe ich nicht.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • tschoeatsch schrieb:

      Ich trau mich nicht zB. _sec und die weiteren Systemvariablen zu wandeln...
      Das ist nicht auf meinen Mist gewachsen.
      Aber soweit ich das verstanden habe, schießt da beim abfragen oder setzen kein Interrupt rein. Es ist ja sogar so, dass man (zumindest im User-Mode der Clock) aktiv alles abfragen und setzen muss.
      Die "Systemvariablen _xxx" verändern sich da doch nur durch die Aktion Time$=, Date$= und umgekehrt. Da läuft nix in einem IRQ.
      Wäre ja auch fatal, wenn ein IRQ reinschießt, da würde ja kein anderes I2C mehr funktionieren.

      tschoeatsch schrieb:

      Deine Funktionen gettime() und getdate() verstehe ich nicht.
      Das ist ganz einfach.
      Aus den Variablen Date$ und Time$ hole ich die RTC-Daten (also die Normalzeit), während die Funktionen Date() und Time() wiederum die Werte aus der SysSec aufbauen (die dann ja eventuell um die Sommerzeitstunde verändert worden ist).
      Mit der ersten Zeile wird eigentlich nur die Uhr aktualisiert, mit der zweiten Zeile dann die durch die zuvor erfolgte Aktualisierung neu gefüllte SysSec verarbeitet.
      Wie schon oben gesagt, läuft da nix automatisch, man muss das ja jedes mal anstoßen (im User-Mode mit RTC zumindest).
    • ...eigentlich keine große Nummer: Die Systemzeit (Winter- bzw. Normalzeit, GMT) nehmen und die Zeitzone dazurechnen bzw. abziehen, gleiches mit der Sommerzeit. Die RTC läuft immer mit Greenwich Zeit - nichts umstellen. Der Rest muss über eine Funktion erledigt werden. Eine Umkehrfunktion zur SYSSEC() habe ich nicht entdeckt, die würde es sehr einfach machen...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • So hier jetzt meine Lösung verpackt in einem Demoprogramm.
      Es wird jetzt zu jeder Zeit (sowohl zum Einschaltzeitpunkt aber auch im laufenden Betrieb) erkannt ob zum aktuellen Zeitpunkt Sommer- oder Normalzeit vorherrscht (in der Vorwersion hier im Thread waren noch Erkennungsprobleme rund um den letzten Sonntag im März und Oktober).
      Auch werden die Systemvariablen nicht mehr angefasst.
      Das hatte ich ursprünglich auch nur von anderer Stelle übernommen und bei der Variante RTC ist es wohl aber ziemlich sicher egal, da diese Variablen nur durch den Aufruf von Time$ und Date$ beaufschlagt werden.
      Anders wird es sich verhalten mit IRQ-gesteuerten Uhren mit eigen Quarz oder Mischformen davon.
      Es gibt auch eine Einschränkung. Der erlaubte Datumsbereich muss zwischen 01.01.2000 und 31.12.2067 liegen (dies wird hier aber hier nicht weiter kontrolliert, sollte aber in eigenen Projekten dennoch geschehen da anderenfalls die Datums- und Zeit Funktion (Date() und Time()) Müll in Form von Hex-Code liefert. Dieser Umstand ist der aktuellen BasCom-Version geschuldet und wahrscheinlich auch egal, da ich irgendwie annehme. dass nach 2067 keine AVR so wie wir sie kennen existieren werden.

      Ich habe die Uhr auch so gelöst, dass die eigene SysSec im IRQ gesteuert wird und man dadurch eventuell den I2C-Verkehr etwas reduzieren kann.

      Der Code ist zu lange zum direkt Einfügen, daher stelle ich den als Anhang zur Verfügung.
      RTC-Uhrentest.bas

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Zitronenfalter ()

    • Ich hänge meine Version auch mal hier an.
      Zeitquelle ist ein GPS-Empfänger, der Zeit und Datum in UTC liefert, für die Anzeige der Zeit und des Datums brauche ich MEZ bzw MESZ.
      Mein Programm berechnet aus dem UTC-Datum für das aktuelle Jahr die UTC_Systemsekunden für die Umschaltung auf MESZ und das Rückschalten auf MEZ. Das Berechnen dieser 2 Werte brauch man nur einmalig Anfang jedes Jahres machen. Danach braucht man die aktuelle UTC_Systemsekunde nur mit diesen Grenzen vergleichen um die Zeitkorrekturen zur Lokalzeit zu bekommen.

      BASCOM-Quellcode

      1. '(
      2. Die Regeln für die Zeitumstellung
      3. Für die Sommerzeit gilt:
      4. Die Zeitumstellung findet am letzten Sonntag im März statt.
      5. Dabei wird um 2:00 Uhr MEZ die Uhr um eine Stunde vorgestellt.
      6. Das bedeutet : "Die Nacht ist eine Stunde kürzer".
      7. Für die Winterzeit (Normalzeit) gilt:
      8. Die Zeitumstellung findet am letzten Sonntag im Oktober statt.
      9. Um 3:00 Uhr MESZ wird die Uhr um eine Stunde zurückgestellt.
      10. Das bedeutet : "Die Nacht ist eine Stunde länger".
      11. ')
      12. $regfile = "m328pdef.dat"
      13. $crystal = 16000000
      14. $hwstack = 34
      15. $swstack = 32
      16. $framesize = 64
      17. $baud = 9600
      18. Config Clock = User
      19. Config Date = Dmy , Separator = .
      20. Dim Sec_szbeginn As Long 'syssec der Zeitumstellung auf Sommerzeit im Beispieljahr
      21. Dim Sec_szende As Long 'syssec der Zeitumstellung auf Winterzeit im Beispieljahr
      22. Dim W_t_2503 As Byte 'Wochentag vom 25.März
      23. Dim W_t_2510 As Byte 'Wochentag vom 25.Oktober
      24. Dim Datum_2503 As String * 8
      25. Dim Datum_letzter_sonntag As String * 8
      26. Dim Tage_bis_sonntag As Byte
      27. Dim Letzter_sonntag As Byte
      28. Dim Zeit_beginn As String * 8
      29. Zeit_beginn = "01:00:00" 'UTC
      30. Dim Zeit_ende As String * 8
      31. Zeit_ende = "01:00:00" 'UTC+1
      32. Dim Systemsekunde As Long
      33. Dim Utc_systemsekunde As Long
      34. Dim _utc_sec As Byte , _utc_min As Byte , _utc_hour As Byte , _utc_day As Byte , _utc_month As Byte , _utc_year As Byte
      35. 'Zeitquelle ist in UTC, die Anzeige soll MEZ bzw MESZ anzeigen
      36. _utc_year = 19 'Beispiel 2019
      37. _utc_month = 10
      38. _utc_day = 27
      39. _utc_hour = 02 'MEZ
      40. _utc_min = 00
      41. _utc_sec = 00
      42. Utc_systemsekunde = Syssec(_utc_sec)
      43. Time$ = Time(utc_systemsekunde)
      44. Print "UTC-" ; Time$ ; " UTC-Systemsekunde= " ; Utc_systemsekunde ; " ";
      45. Gosub Abgrenzung_sommerzeit
      46. If Utc_systemsekunde >= Sec_szbeginn And Utc_systemsekunde < Sec_szende Then
      47. Systemsekunde = Utc_systemsekunde + 7200 'MESZ
      48. Else
      49. Systemsekunde = Utc_systemsekunde + 3600 'MEZ
      50. End If
      51. _sec = Time(systemsekunde)
      52. _day = Date(systemsekunde)
      53. Time$ = Time(systemsekunde)
      54. Print Time$ ; " SZbeginn= " ; Sec_szbeginn ; " SZende= " ; Sec_szende
      55. Print
      56. End
      57. Abgrenzung_sommerzeit:
      58. Datum_2503 = "25.03." + Str(_utc_year)
      59. W_t_2503 = Dayofweek(datum_2503) 'ergibt Wochentag des 25.März im Beispieljahr
      60. Tage_bis_sonntag = 6 - W_t_2503
      61. Letzter_sonntag = 25 + Tage_bis_sonntag 'letzter Sonntag im März des Beispieljahres
      62. Datum_letzter_sonntag = Str(letzter_sonntag) + ".03."
      63. Datum_letzter_sonntag = Datum_letzter_sonntag + Str(_utc_year)
      64. Sec_szbeginn = Syssec(zeit_beginn , Datum_letzter_sonntag) 'ab dieser Sekunde MEZ beginnt die Sommerzeit im Beispieljahr
      65. W_t_2510 = W_t_2503 + 4 : If W_t_2510 > 6 Then W_t_2510 = W_t_2510 -7 'ergibt Wochentag des 25.Oktober im Beispieljahr
      66. Tage_bis_sonntag = 6 - W_t_2510
      67. Letzter_sonntag = 25 + Tage_bis_sonntag 'letzter Sonntag im Oktober des Beispieljahres
      68. Datum_letzter_sonntag = Str(letzter_sonntag) + ".10."
      69. Datum_letzter_sonntag = Datum_letzter_sonntag + Str(_utc_year)
      70. Sec_szende = Syssec(zeit_ende , Datum_letzter_sonntag) 'ab dieser Sekunde MESZ endet die Sommerzeit im Beispieljahr
      71. Return
      72. Getdatetime:
      73. Return
      74. Settime:
      75. Return
      Alles anzeigen
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Fehlerkorrektur: das Ende der Sommerzeit ist um 1Uhr UTC, was 3Uhr MESZ entspricht. Also in Zeile 38 muss auch "01:00:00" stehen.

      Korrigiert. /six1
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------