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
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.
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.
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.
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
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"
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.
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.
Schlaumaier schrieb: > Sub schreibe > X = x + 1 > is x = 61 then x = 1 ' ich hasse die Fehlerkorrektur manchmal. > arry(x) = Uhrzeit > end sub
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.
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.
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.
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
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. ;)
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.