Forum: Mikrocontroller und Digitale Elektronik Timestamp speichern und absteigend ordnen


von der_Zwerg (Gast)


Lesenswert?

Guten Samstag,
ich stehe vor folgender Herausforderung und weiß nicht recht wie ich es 
machen soll.

Also ich soll bei aktivieren und deaktivieren einer Funktion die Uhrzeit 
und das Datum speichern. Insgesamt sollen immer die letzten 30 ein und 
aus gespeichert werden.
Ich dachte mir ich mach das so das ich mir ein Array mit 60 int32_t 
anlege und den Timestamp beim einschalten auf die geraden stellen 
speichere und beim ausschalten auf die ungeraden.

Nun zu meinem Problem wenn ich meine 60 Einträge habe soll ich den 
ältesten überschreiben.
Was wäre ihr die sinnvollste Strategie? Soll ich die Daten des Array 
dann so verschieben das das 58 und 59 frei werden und ich dann wieder in 
58 und 59 rein schreibe?
Oder wie macht man das am sinnvollsten damit ich auch die Anzeige 
richtig geordnet habe?
Hierzu gibt es bestimmt ein paar Tricks

von Nop (Gast)


Lesenswert?

der_Zwerg schrieb:

> Was wäre ihr die sinnvollste Strategie?

Ringbuffer.

von W.S. (Gast)


Lesenswert?

der_Zwerg schrieb:
> Was wäre ihr die sinnvollste Strategie?

Die allersinnvollste Strategie für deine Bemühungen wäre zu allererst, 
nachzudenken.

Stattdessen fällt dir als Allererstes ein, daß du ein int32_t, also ein 
long zu benutzen gedenkst. Wie kommst du darauf, so etwas als 
Allererstes anzudenken?

Richtig wäre, wenn du dir als Allererstes Gedanken machen würdest, WAS 
für ein Datum + Uhrzeit du speichern sollst. Also beispielsweise die 
vergangenen Sekunden ab dem 1.1.1970 0.00 Uhr UTC. Kann aber auch sein, 
daß du es in Millisekunden seit dem 1.1.2020 0.00 Uhr abspeichern 
willst/sollst. Oder in irgend einer anderen Zeit-Notation - je nach dem 
tatsächlich dahinterstehenden Zweck.

Dann käme als nächstes das Aufsetzen eines Structs, der den Zeitstempel 
(in der von dir gewählten Notation) sowie einen Merker enthält, der da 
aussagt Ein, Aus, undefiniert.

Danach kannst du dir einen Ringpuffer in einem EEPROM anlegen und ihn 
mit Records {egal, undefiniert} initialisieren. Anschließend kannst du 
dort lustig draufschreiben, indem du den jeweils ältesten Eintrag 
überschreibst.

Fertig.

Bei sowas braucht man nicht einmal die 2 üblichen Zeiger eines 
Ringpuffers, denn man weiß aus den Zeitstempeln ja bereits, wann was 
gewesen ist und wo der Punkt im Ringpuffer ist, wo der Neuerste neben 
dem Ältesten steht.

Also: immer zuerst nachdenken und nicht als Erstes mit irgend einem 
int32_t hereinpoltern.

W.S.

von der_Zwerg (Gast)


Lesenswert?

W.S. schrieb:
> Also: immer zuerst nachdenken und nicht als Erstes mit irgend einem
> int32_t hereinpoltern.

Also soweit ich weiß wird die Unixzeit in einer 32 Bit variable 
gespeichert.
Also habe ich dazu an ein int32 gedacht.
Und die Information des ein und aus kann ich ja mit gerader und 
ungeradem Index des Array feststellen.
Also etwas hatte ich ja gedacht.
Das mit dem Ringbuffer war mir nicht klar.
da ich unbedingt auch die aufsteigende Sortierung benötige.

Werde mir den Ringbuffer jetzt ansehen.

von Nop (Gast)


Lesenswert?

der_Zwerg schrieb:

> Also soweit ich weiß wird die Unixzeit in einer 32 Bit variable
> gespeichert.

Das war mal und ist längst schon 64 Bit, weil es mit 32 Bit 2038 zum 
Überlauf kommt. Betroffen davon sind allerdings viele Geräte mit 
embedded Linux, welche 32-bittig laufen. Bis 2038 dürften die sich aber 
ohnehin erledigt haben.

von der_Zwerg (Gast)


Lesenswert?

Nop schrieb:
> Das war mal und ist längst schon 64 Bit

Auf einem 8bitter Atmega bleibe ich aber trotzdem bei 32Bit.

Habe mir jetzt den Ring buffer angesehen.
Aber der Ringbuffer birgt einige Fallstricke.
Wenn ich mit dem Ringbuffer arbeite darf ich nur den Schreibe Zeiger 
verwenden. Denn wenn ich auch den Lesezeiger verwende kann ich nur 
einmal die Daten raus hohlen oder habe ich da was falsch verstanden?
Würdet ihr dann für die Anzeige Das Array sortieren?

Danke für die Hilfe

von Nop (Gast)


Lesenswert?

der_Zwerg schrieb:

> Würdet ihr dann für die Anzeige Das Array sortieren?

Hat W.S. doch schon erklärt, zweitletzter Absatz: 
Beitrag "Re: Timestamp speichern und absteigend ordnen"

von HildeK (Gast)


Lesenswert?

der_Zwerg schrieb:
> da ich unbedingt auch die aufsteigende Sortierung benötige.

Ringpuffer; der Schreibindex i auf das Array[i] zählt eben von 0...59 
und weiter mit 0. (i++; if (i>59)i=0;)
Genau so machst du es mit dem Leseindex. Je nach dem, ob du mit den 
neuesten beginnen willst oder mit dem ältesten der Ausgabe zählst du 
halt vorwärts oder rückwärts.
Unabhängig davon kannst du auch das Feld in jedem Zustand kopieren und 
sortieren, denn die Einträge sind ja die Zeit.

von Schlaumaier (Gast)


Lesenswert?

W.S. schrieb:
> Danach kannst du dir einen Ringpuffer in einem EEPROM anlegen und ihn
> mit Records {egal, undefiniert} initialisieren.

AUA.

Das Ding ist je nach Arbeit nach 2 Tagen Schrott. EEPROM halten nach 
Aussagen in 1000 Foren nur eine ziemlich eingeschränkte Zeit.

Lass das ganze im Ram arbeiten, oder schreibe es auf eine SD-Karte.

Ganz normale Text-Datei im Append-Modus. Mit einen Zähler kannst du 
verhindern das die Datei platzt.

Beim Neustart einfach die letzten X Einträge lesen und neue Datei 
aufmachen und die alte Löschen. Das war's.

Wenn du es im Ram machst, brauchst du nur ein Array mit X Einträgen und 
einen Zähler.

Sub schreibe
X = x + 1
ich x = 61 then x = 1
  arry(x) = Uhrzeit
end sub

Fertig.

von Schlaumaier (Gast)


Lesenswert?

Schlaumaier schrieb:
> Sub schreibe
> X = x + 1
> is x = 61 then x = 1 ' ich hasse die Fehlerkorrektur manchmal.
>   arry(x) = Uhrzeit
> end sub

von W.S. (Gast)


Lesenswert?

der_Zwerg schrieb:
> Aber der Ringbuffer birgt einige Fallstricke.
> Wenn ich mit dem Ringbuffer arbeite darf ich nur den Schreibe Zeiger
> verwenden. Denn wenn ich auch den Lesezeiger verwende kann ich nur
> einmal die Daten raus hohlen oder habe ich da was falsch verstanden?

Lies meinen Beitrag noch einmal. Du hast ihn nämlich garnicht 
verstanden. In dem Ringpuffer, der hier nur mit einem einzigen Index 
auskommt. Im Puffer kannst du nur Structs haben, die als Merker "ein", 
"aus" oder "undefiniert" beinhalten. Also kannst du dir einmal nach dem 
Einschalten die 60 Einträge anschauen und dir die Stelle des Neuesten 
merken. Das ist dein Index, quasi der Zeiger auf den Hotspot, wo der 
allerneueste Eintrag steht. Alle weiteren Einträge kommen dahinter, eben 
einfach der Reihe nach. Und wenn der Index bei 59 angekommen ist, dann 
landet der nächste Eintrag eben bei 0, dann der nächste bei 1 und so 
weiter, immer im Kreis herum.

W.S.

von Nop (Gast)


Lesenswert?

Schlaumaier schrieb:

> Lass das ganze im Ram arbeiten

Dann ist es weg, wenn der Strom ausfällt oder neu gestartet wird.

> oder schreibe es auf eine SD-Karte.

µC-basierte Lösungen haben selten eine SD-Karte, und bei einem Raspi 
würde man nichts von EEPROM schreiben.

Idealerweise vereint man beides, indem man einen Powerdown-Interrupt 
hat, der bei Stromausfall die Daten aus dem RAM ins EEPROM schreibt, 
sofern die dort gespeicherten Daten nicht identisch zur RAM-Kopie sind. 
Während dieser Zeit läuft der Controller noch aus einem passend 
dimensionierten Kondensator.

von Schlaumaier (Gast)


Lesenswert?

Nop schrieb:
> Idealerweise vereint man beides, indem man einen Powerdown-Interrupt
> hat, der bei Stromausfall die Daten aus dem RAM ins EEPROM schreibt,
> sofern die dort gespeicherten Daten nicht identisch zur RAM-Kopie sind.

Das wäre wirklich ideal. Weil das passiert nicht so häufig und deshalb 
wird der EEPROM geschont.

von (prx) A. K. (prx)


Lesenswert?

Ich habe mit dem internen EEPROM der AVRs noch kein Problem bekommen, 
auch nicht mit einem fortlaufenden Protokoll in einem externen seriellen 
EEPROM über nun ca 15 Jahre. Aber es gibt auch persistente FRAMs ähnlich 
externen seriellen EEPROMs mit faktisch unbegrenzten Schreibzyklen.

Edit: Das erwähnte externe EEPROM fürs Protokoll arbeitet mit Einträgen 
fester Länge als Ringpuffer. Für die Timestamp habe ich das FAT Format 
genutzt, das auf 2 Sekunden auflöst: 
http://ntfs.com/exfat-time-stamp.htm

von Schlaumaier (Gast)


Lesenswert?

hm ok.

Ich habe aber schon gelesen das das EEPROM des Arduino nach 500 
Schreibversuchen die Flügel hängen lässt.

Und das kann wenn man alle paar Sekunden was schreibt, dann ziemlich 
schnell passieren.

Anders herum ;) meine SSD-Platte würde bei 500 Schreibzyklen es nicht 
einmal wagen in die Nähe meines PC zu kommen. ;)

von (prx) A. K. (prx)


Lesenswert?

Mal rechnen. Das externe EEPROM ist ein AT24C256, 32KB mit 1 Mio 
garantierten Schreibzyklen. Ein Eintrag ist 8 Bytes gross, d.h. auf 4096 
Einträge kommt ein EEPROM-Zyklus, insgesamt also 4 Milliarden Einträge. 
Wenn jede Sekunde ein Eintrag geschrieben wird, reicht das 130 Jahre.

von Schlaumaier (Gast)


Lesenswert?

OK sollte reichen ;)

von (prx) A. K. (prx)


Lesenswert?

Schlaumaier schrieb:
> meine SSD-Platte würde bei 500 Schreibzyklen es nicht
> einmal wagen in die Nähe meines PC zu kommen. ;)

Das heute übliche TLC Flash liegt in dieser Grössenordnung. ;-)

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.