Forum: Mikrocontroller und Digitale Elektronik Berechnung der Jahrzahl [jjjj], wenn nur die letzte Stelle vorhanden ist


von Andy (Gast)


Lesenswert?

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

von Hmm... (Gast)


Lesenswert?

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...

von Klaus (Gast)


Lesenswert?

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

von Martin (Gast)


Lesenswert?

Nimm die ersten drei Stellen der Jahreszahl vom aktuellen Datum.

von Andy (Gast)


Lesenswert?

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.

von Hmm... (Gast)


Lesenswert?

Wieweit in die Zukunft bzw. die Vergangenheit können die Datumsangaben 
den liegen?

von Severino R. (severino)


Lesenswert?

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.

von Andy (Gast)


Lesenswert?

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...

von Hmm... (Gast)


Lesenswert?

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. ;)

von Matthias L. (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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?

von Andy (Gast)


Lesenswert?

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
}

von Andy (Gast)


Lesenswert?

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.

von Zwischenfrequenz (Gast)


Lesenswert?

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.

von Andy (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.