Hi Habe folgendes Problem: Ich bekomme über ein Protokoll auf der seriellen Schnittstelle das Datum folgendermassen gesendet: dd.mm.j Hat jemand eine Idee, wie ich aus der einzelnen Ziffer (Im Jahr 2008 nur die 8) für die nächsten 50 Jahre die ganze 4- stellige Zahl (2008 usw.) berechnen kann? Internes EEPROM steht zur Verfügung. Gruss Andy
Garnicht. Es fehlt nämlich die Information welches Jahrzehnt gemeint ist, und die kann man auch mit einem EEPROM nicht auf magische Weise gewinnen. Einziger Weg wäre es, zusätzlich noch das Jahrzehnt zu übertragen (2008->08), dann könnte man sogar bis zum Jahr 2099 ein gültiges Datum rekonstruieren. In einigen Systemen wurde das bis 2000 übrigens sogar genau so gemacht. ;) Vorschlag: Wenn ein Byte im Protokoll dafür reserviert ist, dass du anpassen könntest, dann übertrag das Jahr oder noch besser das ganze Datum doch als Binär-Wert. Beispiel für gepacktes 16-Bit Datum: 31 Tage -> 5 Bit 12 Monate -> 4 Bit Jahr -> 7 Bit Damit kannst du satte 127 Jahre lang ein Datum kodieren. Wenn du es als Offset auf das Jahr 2000 beziehst bist du damit bis ins Jahr 2127 auf der sicheren Seite...
Wenn die Einerstelle auf einmal kleiner ist als die im EEprom, kannst Du davon ausgehen das ein 10er Übertrag stattgefunden haben muß, dann neuen Wert in den EEprom schreiben. Das sollte auch noch funktionieren, wenn das Gerät mal 9 Jahre nicht im Betrieb war. Gruß Klaus
Nimm die ersten drei Stellen der Jahreszahl vom aktuellen Datum.
Danke für Eure Antworten! @Hmm... Hab leider keinen Einfluss auf das Protokoll. Deshalb bin ich auf diese einzelne Stelle angewiesen. @Klaus Diese Lösung sieht mir sehr vernünftig aus. Hab auch schon in diese Richtung gedacht. @Martin Weiss leider nicht genau, wie Du das gemeint hast.
Wieweit in die Zukunft bzw. die Vergangenheit können die Datumsangaben den liegen?
Hmm... wrote: > dann könnte man sogar bis zum Jahr 2099 ein gültiges Datum > rekonstruieren. In einigen Systemen wurde das bis 2000 übrigens sogar > genau so gemacht. ;) Man könnte dann auch bis zum Jahr 9999 ein gültiges Datum rekonstruieren, da Du annimmst, dass das Jahr immer "in der Nähe" des aktuellen Jahrs liegt. Wenn das Jahr im Protokoll immer sehr zeitnah ist, gäbe es höchstens Probleme um den Jahreswechsel, aber das könnte man auch noch lösen (z.B. mit Klaus' Idee). Martins Idee scheitert hingegen Ende 2009. Andy soll zuerst mal sagen, ob er am Datumsformat im Protokoll überhaupt etwas ändern kann (wohl nicht, sonst würde er wohl jjjj senden). Ausserdem muss man wissen, wie weit das Datum im Protokoll maximal vom aktuellen Datum abweichen kann.
Das Datum wird zusammen mit der Zeit ca. 4x pro Minute gesendet. Die Jahrzahl wie gesagt leider nur mit einer Stelle. Es kann aber auch passieren, dass das Gerät Monatelang ausser Betrieb am Lager liegt. Ab und zu (alle paar Monate, ist aber auch nicht garantiert) werden via Mamorystick Daten auf das Gerät übertragen. Da habe ich evt. auch noch die Gelegenheit das Datum zu synchronisieren. Muss dann anhand des Datums, den Wochentag und die Feiertage berechnen. Dies geht natürlich nur mit der gesamten 4-stelligen Jahreszahl. Wenn das ganze bis 2099 funktionieren würde wäre das ganz cool...
Wie gesagt, wenn stets nur das aktuelle Jahr gesendet wird könnte man es mit Klaus Methode machen. Man sichert einmal das vollständige aktuelle Jahr im EEPROM. Anschließend kann das gesendete Datum nur im selben Jahr wie der Wert im EEPROM oder danach liegen. Entsprechend aktualisiert man den Wert im EEPROM, wenn ein Jahreswechsel statt gefunden hat. Drei Nachteile hat es: 1. Das Gerät darf nicht länger als 9 Jahre am Stück kein neues Datum empfangen. Sonst verliert man ein Jahrzehnt. 2. Das gesendete Datum muss das aktuelle sein. Es sind keine beliebigen Datumsangaben möglich. 3. Man sollte wen möglich die Produktion der Geräte sicherheitshalber über Silvester still legen. ;)
Auch wenn es abgelehnt wurde, wie wäre es mit einer Protokolländerung? Es ist nunmal nicht möglich, sich Information zu erzaubern.(Dein Chef wird dir doch auch sagen, bis zu welchen Tag in welchem Monat und Jahr du das fertig haben sollst. Oder gibt er dir hier auch nur den Tag?) Man, wer denkt sich nur immer so einen Mist aus.
Andy wrote: > Ich bekomme über ein Protokoll auf der seriellen Schnittstelle das Datum > folgendermassen gesendet: dd.mm.j > > Hat jemand eine Idee, wie ich aus der einzelnen Ziffer (Im Jahr 2008 nur > die 8) für die nächsten 50 Jahre die ganze 4- stellige Zahl (2008 usw.) > berechnen kann? Hmm, knifflig. Versuche es mal mit jahr = j + 2000; Das baut darauf, dass der Sender die Jahre ab 2000 schickt, aber vergessen hat führende Nullen mit zu schicken (%d statt %02d im Formatstring). Es wäre interessant zu wissen, was bei einem Datum ab 2010 passiert, also ob eine j=10 kommt oder wieder eine j=0. Kannst du den Kalender am Sender testweise vor drehen?
Danke an alle! Falls es jemanden interessiert, scheint ganz gut zu klappen:
1 | //----------------------------------------------------------------------------
|
2 | // Funktionsnamen : complete_year()
|
3 | //
|
4 | // Beschreibung : 4-stellige Jahreszahl aus einer Ziffer berechnen
|
5 | // Arguments : unsigned char Jahresziffer 0-9
|
6 | // Return : unsigned int16 Jahreszahl (jjjj)
|
7 | //----------------------------------------------------------------------------
|
8 | unsigned int16 complete_year(unsigned char protokoll_jahr) |
9 | {
|
10 | unsigned int16 tmp_jahr=0; |
11 | unsigned char eeprom_jahr_einer=0; |
12 | unsigned char eeprom_jahr_zehner=0; |
13 | |
14 | eeprom_jahr_einer=save_memory_byte_read(EEPROM_IBIS_JAHR_EINER); |
15 | eeprom_jahr_zehner=save_memory_byte_read(EEPROM_IBIS_JAHR_ZEHNER); |
16 | |
17 | // Ist schon gültige Jahrzahl in EEPROM vorhanden?
|
18 | if (((eeprom_jahr_einer <= 9) && (eeprom_jahr_einer >=0)) && |
19 | ((eeprom_jahr_zehner <= 90) && (eeprom_jahr_zehner >=0))) |
20 | {
|
21 | |
22 | if(eeprom_jahr_einer == protokoll_jahr) // Ja, vergleichen mit IBIS_year |
23 | {
|
24 | tmp_jahr = read_eeprom(EEPROM_IBIS_JAHR_ZEHNER) + save_memory_byte_read(EEPROM_IBIS_JAHR_EINER); |
25 | }
|
26 | else
|
27 | {
|
28 | write_eeprom(EEPROM_IBIS_JAHR_EINER,protokoll_jahr); // Neue Jahrziffer aus Protokoll in EEPROM übernehmen |
29 | tmp_jahr = save_memory_byte_read(EEPROM_IBIS_JAHR_ZEHNER) + save_memory_byte_read(EEPROM_IBIS_JAHR_EINER); |
30 | |
31 | if(protokoll_jahr <= eeprom_jahr_einer) // Ist Protokoll Jahr kleiner als EEPROM Jahr |
32 | {
|
33 | if(eeprom_jahr_zehner <= 80) |
34 | {
|
35 | eeprom_jahr_zehner += 10; // Zehnerstelle um eins erhöhen |
36 | }
|
37 | |
38 | write_eeprom(EEPROM_IBIS_JAHR_ZEHNER,eeprom_jahr_zehner); // Wieder zurückschreiben |
39 | |
40 | // Neues Jahr berechnen
|
41 | tmp_jahr = save_memory_byte_read(EEPROM_IBIS_JAHR_ZEHNER) + save_memory_byte_read(EEPROM_IBIS_JAHR_EINER); |
42 | }
|
43 | }
|
44 | }
|
45 | else // Bei 0xFF neu formatieren |
46 | {
|
47 | // Neues EEPROM formatieren
|
48 | write_eeprom(EEPROM_IBIS_JAHR_EINER,8); // Default Jahr 2008 in EEPROM schreiben |
49 | write_eeprom(EEPROM_IBIS_JAHR_ZEHNER,0); |
50 | tmp_jahr=8; |
51 | }
|
52 | |
53 | tmp_jahr += 2000; |
54 | |
55 | return(tmp_jahr); |
56 | }
|
Beim der Anwendung handelt es sich übrigens um das IBIS- Protokoll, (Integriertes Bordinformationssystem) welches in der Bahntechnik zur Anwendung kommt. Datensatz: 006 d5Z > AD Kalender- Datum, welches wie gesagt nur 5 Ziffern enthällt. (dd.mm.j) Vielleicht kennt sich ja jemand damit aus und und kann mir ein Telegramm nennen, wo die gesamte Jahreszahl übertragen wird.
Klaus Idee gefällt mir. Es gibt aber noch einen eventuellen Nachteil: Die Verbindung muss zuverlässig sein. Gibt es Fehlererkennung / Fehlerkorrektur im Bahn-Protokoll? Sonst kann dich eine einmalig falsch empfangene Jahreszahl dauerhaft (oder bis zum nächsten Memorystick) um 10 Jahre nach vorne bringen.
Die Daten werden mit 1200,7,e,2 übertragen. D.h. 7Bit- ASCII Codierte Zeichen, welche mit einem Paritäts Bit codiert sind. Das Telegram beinhaltet am Ende ausserdem ein Längspartyäts- Byte als Chechsumme. Ich lese das Datum 2x hintereinander ein und akzeptiere dies nur, wenn es 2x gleich ist. Ein gewisses "Restrisiko" besteht natürlich immer. Hoffe jetzt, dass sich Murphy ein wenig zurück hält.
Hallo Andy, wenn das was kommerzielles wird machs sicher! Sonst steht "Murphy" schon neben Dir.
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.