Hallo zusammen,
ich versuchen zurzeit einen Datalogger zu programmieren. Dieser soll
alle werte der letzten 10 h abspeichern.
Dafür verwende ich ein RTC Modul. Wenn ich jetzt zum Beispiel um 19:00
Uhr die Daten anschauen will sollen alle werte bis 09:00 sichtbar sein.
Um 08:00 Uhr alle Daten bis 22:00 Uhr.
Habt ihr eine Idee wie man das macht?
Hier könnt ihr Projekte, Schaltungen oder Codeschnipsel vorstellen. Projekte bitte nur mit Code oder Schaltplan posten (falls ihr nur Fotos vorstellen möchtet, bitte in "Zeigt her eure Kunstwerke"). Bitte hier keine Fragen posten.
Geht es Dir darum, Uhrzeiten zu vergleichen?
Das einfachste: Rechne in Sekunden (oder ms) um. Wenn es nur um < 24h
geht:
Sekunden ab Mitternacht (h*3600 + m * 60 + s).
Für "heute" einen ganzen Tag addieren (24*3600), für gestern nicht,
vorgestern und älter sind eh raus.
Dann Vergleichen ob der Zeitstempel < Zeit(jetzt)-10*3600 ist.
--> bitte mit 32 bit rechnen
--> Race-Conditions beim Auslesen Uhrzeit/Datum beachten. Wenn Du nicht
weißt, was das bedeutet, Deinen Code posten.
Wenn es allgemein ist, Sekunden seit z.B. 1.1.2020 nehmen.
Wenn alle Werte hintereinander gespeichert werden,
UND Du weisst WIE-OFT PRO ZEITEINHEIT Du gesampelt/gespeichert hast:
Dann reicht einfaches zählen.
Ansonsten genau wie "(achs)" schrub.
A. S. schrieb:> Race-Conditions beim Auslesen Uhrzeit/Datum beachten. Wenn Du nicht> weißt, was das bedeutet, Deinen Code posten.
Datei ist angehängt
Es geht eigentlich nur um die if Bedingung am ende
Eva T. schrieb:> Uhr die Daten anschauen will sollen alle werte bis 09:00 sichtbar sein.
Sichtbar wo? Lokal oder Handy-App oder PC?
Wenn du immer die letzten 10 Datensätze abspeicherst musst du eigentlich
nicht mal die Zeit mit abspeichern - wenn du abrufst sind das ja immer
die letzten 10 Stunden.
Es gibt Umrechnungssoftware für Daten in alles denkbare bis hin zum
Maya-Kalender. Die gehört in das Anzeigeprogramm und nicht in den
Datenlogger.
Georg
Ich würde eine SQL Datenbank nehmen.
Alle Werte darin abspeichern mit insert.
Bei der Abfrage dann nur die letzten 10 Stunden durch den select
auswählen.
Dabei dann alle älteren durch einen delete löschen.
Da ja keine Aussagen zu Rechner, OS etc gemacht wurden, durfte ich mir
das frei wählen.
Eva T. schrieb:> ich versuchen zurzeit einen Datalogger zu programmieren. Dieser soll> alle werte der letzten 10 h abspeichern.
etwas unklar
z.B.
a) in welchen Zeitabständen werden die Daten erfasst?
b) wo werden die Daten abgespeichert?
Harald W. schrieb:>> Wenn es allgemein ist, Sekunden seit z.B. 1.1.2020 nehmen.>> Oder man nimmt gleich die Unixzeit.> Dann ist es wirklich allgemeingültig.> https://de.wikipedia.org/wiki/Unixzeit
Nix davon ist allgemeingültig. Wann z.B. haben die Neandertaler gelebt?
In Sekunden nach dem 1.1.1970?
Zeit ist für uns quasi unendlich in beide Richtungen. Da reichen auch
keine 32 Bit. Also ist es völlig legitim für eine bestimmte Anwendung,
nur einen bestimmten Ausschnitt der Zeit überstreichen zu können.
Für Evas Anwendung wäre es ausreichend, wenn die zu zählende Zeit
rückwärts vom jeweiligen Jetzt gezählt würde, allerdings hat es dabei
den Haken, daß das Jetzt voranschreitet und folglich alle zuvorigen
Ereigniszeiten nach jeder Sekunde aktualisiert werden müßten. Ist ne
recht ungünstige, da rechenintensive Weise.
Also kann man sich einen relativ beliebigen Zeitpunkt hernehmen und den
als Startpunkt wählen. Man muß bloß dann einen neuen Zeitpunkt 0 wählen
und die Zeiten aktualisieren, wenn die Zeitspanne so groß geworden ist,
daß die Zählvariablen überzulaufen drohen.
Eine völlig andere Herangehensweise wäre, zu jedem Ereignis die
Zeitspanne zum vorherigen Ereignis zu merken. Wenn die Ereignisse nicht
allzuweit zeitlich auseinanderliegen, reicht dafür dann auch eine
kleinere Zählvariable. Allerdings müßte man dann, wenn man den Zeitpunkt
des tausendsten Ereignisses vor Jetzt haben will, tausend Additionen
machen.
Es kommt da also auf das an, was mit den gespeicherten Ereignissen
gemacht werden soll.
W.S.
Ich rate Mal nur ins Blaue, die Beschreibung des Problems ist wirklich
schlecht.
Dem Code nach handelt es sich um einen Arduino Uno der alle 6 Sekunden
auf eine SD Karte speichert.
Auf Anforderung sollen alle Daten von (now - 10h) zur Verfügung gestellt
werden.
Das sind grob überschlagen 10 Werte pro Minute 60 Minuten 10 Stunden
* mindestens 40 Byte pro Eintrag (da alles als String). Also 240kB+.
Also nichts was man bei dem uC im RAM hält.
Es wird also darauf raus laufen z.B. eine Datei pro Stunde anzulegen.
Zum Beispiel mit Datum/Uhrzeit im Dateinamen. Immer wenn es 11 Dateien
sind, löschst du die älteste Weg.
W.S. schrieb:> Nix davon ist allgemeingültig. Wann z.B. haben die Neandertaler gelebt?> In Sekunden nach dem 1.1.1970?
Genau! Am besten definiert man die Zeit in Sekunden nach dem Urknall. :)
N. M. schrieb:> der alle 6 Sekunden> auf eine SD Karte speichert.
Aha, es werden Werte auf einer SD-Karte im Abstand von 6s abgespeichert.
Man kann die Daten sammeln und wenn 512Byt erreicht sind, sektorenweise
in einer Datei, welche auf der SD-Karte angelegt wurde, schreiben.
Diese Datei kann im Nachgang beliebig analysiert werden.
Läuft bei mir mit einem MSP430F1611 schon über 10 Jahre, wobei die Datei
jährlich überschrieben wird.
Eva T. schrieb:> Dieser soll alle werte der letzten 10 h abspeichern.
Dann brauchst du einen Zwischenspeicher, in dem du dir die Werte der
letzten 10h merken kannst, bevor du sie abspeicherst.
Wolle G. schrieb:> Aha, es werden Werte auf einer SD-Karte im Abstand von 6s abgespeichert.
Ja werden sie. Lese doch ihren Code von oben:
https://www.mikrocontroller.net/attachment/highlight/578383Wolle G. schrieb:> Man kann die Daten sammeln und wenn 512Byt erreicht sind, sektorenweise> in einer Datei, welche auf der SD-Karte angelegt wurde, schreiben.
Ja, kann und sollte man. Sie macht aber nach jedem Schreibzugriff ein
close der Datei. In der Doku steht dazu:
1
SD - close()
2
Close the file, and ensure that any data written to it is physically saved to the SD card.
Wolle G. schrieb:> N. M. schrieb:>> der alle 6 Sekunden>> auf eine SD Karte speichert.> Aha, es werden Werte auf einer SD-Karte im Abstand von 6s abgespeichert.
Na und? Ich habe einen Spannungslogger gebaut, wo ich sogar jede Sekunde
auf die Karte schreibe. In anderen Anwendungen schreibe ich alle 15
Sekunden.
Die Idee, alles älter 10 Stunden zu löschen, sehe ich problematisch -
dafür müsste er die komplette Datei einlesen und bearbeiten können. Mit
einem EEPROM könnte man einen Ringspeicher bauen, das sehe ich aber mit
einer SD-Karte nicht als machbar an.
Manfred schrieb:> Die Idee, alles älter 10 Stunden zu löschen, sehe ich problematisch
Sehe ich nicht.
Manfred schrieb:> dafür müsste er
Sie
Manfred schrieb:> die komplette Datei einlesen und bearbeiten können
Ne müsste sie nicht, wenn sie einfach pro Stunde eine Datei anlegt und
sobald es 11 Dateien gibt die älteste löscht.
Dann bleiben 10 Dateien für 10h übrig.
Manfred schrieb:> Na und? Ich habe einen Spannungslogger gebaut, wo ich sogar jede Sekunde> auf die Karte schreibe.
Das kann man machen. Im obigen Fall ist Wolles Einwand aber
gerechtfertigt, da es sehr ineffektiv ist.
Es wäre effektiver die Datei nicht ständig zu schließen damit die
Sektoren besser ausgenutzt werden.
im Prinzip schon falsch/ungünstig abgespeichert..
ich würd eimemr ein Format nehmen wie CSV, das auch Excel lesen kann.
man könnte die X Zeilen aus "11Stunden/Intervall", ein Array in der
Größe schaffen und einfach beschreiben, somit hat man am Ende nur die
letzten X Intervalle.(Array muss wenn voll von Vorne anfangen
(Ringbuffer))
an kann aber auch alles rechenintensiv mit strptime überprüfen und jede
Zeile mit einem datumsvergleich mit difftime analysieren.. somit könnte
man sich auch beliebige zeitbereiche aussuchen.
Bei einem eSP32 oder ähnlichem bräuchte man nichtmal eine SD. wenn man
in unixtime rechnen würde, hätte man sogar weniger Daten zu speichern.
Purzel H. schrieb:> Was fuer eine schwache Idee auf einem Logger ein File und eine Datenbank> zu verwenden,
Wenn man genug Rechenleistung und Speicher hat, ist eine Datenbank nicht
wirklich dumm. Im Gegenteil, die bietet die Basis, ältere Einträge zu
löschen.
Aber wir wissen nicht, was geloggt werden soll und wie die Hardware
aussieht.
TotoMitHarry schrieb:> ich würd eimemr ein Format nehmen wie CSV, das auch Excel lesen kann.
Mache ich so, wenn ich auf SD-Karte schreibe. Da muß man, zumindest in
Arduino, Klimmzüge machen, Dezimalpunkt gegen zu Komma tauschen.
> man könnte die X Zeilen aus "11Stunden/Intervall", ein Array in der> Größe schaffen und einfach beschreiben, somit hat man am Ende nur die> letzten X Intervalle.(Array muss wenn voll von Vorne anfangen> (Ringbuffer))
Ringpuffer hatte ich erwähnt und dabei den Beitrag von N. M. übersehen:
N. M. schrieb:> Es wird also darauf raus laufen z.B. eine Datei pro Stunde anzulegen.> Zum Beispiel mit Datum/Uhrzeit im Dateinamen. Immer wenn es 11 Dateien> sind, löschst du die älteste Weg.
Der Ring mit 10 Dateien scheint doch der sinnvollste Ansatz zu sein.
oder die rtclib eigenen Funktionen nutzen..
wobei der Ringbuffer bei nem Arduino Uno und 6Sekunden Intervall nen
bisschen zu groß wird ;)
Pseudocode aus der RTCLIB Referenz (ungeprüft zusammengewurschtelt):
Du brauchst eine Zeitbasis und Speicherplatz, für die Daten der letzten
10 Stunden:
10 Werte für jede Stunde, 600 Werte für jede Minute. 36000 Werte für
jede Sekunde. Am besten, als Ringspeicher in passender Größe!
Liest man jetzt die Daten vom letzten Eintrag rückwärts aus dem
Speicher, ist dein Problem gelöst. FERTIG!
Schnarch schrieb:> 10 Werte für jede Stunde, 600 Werte für jede Minute. 36000 Werte für> jede Sekunde.
Gerade andersrum! Wäre etwas merkwürdig wenn man für einen längeren
Zeitraum weniger Werte hat, oder?
10 Werte pro Minute, 600 Werte pro Stunde, 6000 Werte pro 10h.
Bis dahin sieht es noch garnicht so viel aus. Aber man sieht bereits
jetzt, dass das so mit ihrem Arduino Uno (2kB SRAM) nichts geben wird
mit dem Ringpuffer. Egal ob sie die Temperatur als String, als Rohwerte
(int) oder auch nur als einzelnes Byte abspeichert.
Außerdem spricht sie von Wetterdaten, was zwangsläufig nicht nur die
Temperatur sein wird.
Es kommen also bei jedem weiteren Messwert 6000 Werte dazu.
Zusätzlich wird man ab und zu eine richtige Uhrzeit abspeichern müssen.
Der interne Quartz wird bei 10h weglaufen.
Wenn wir also mit 2 Byte pro Wert rechnen und pro Stunde einen richtigen
Zeitstempel von RTC, dann sind wir ungefähr bei 12kB pro 10h und Wert
plus 40 Byte für die Uhrzeiten.
Alles im RAM zu halten hat auch einen Nachteil. Wenn innerhalb der 10h
die Spannung einmal ausfällt, sind alle Daten futsch.
Ein Mittelweg wäre es, nur so viele Daten im RAM zu halten bis ein
voller Sektor geschrieben werden kann (z.B. 512Byte). Dann braucht man
weder viel RAM noch muss man Angst haben dass einem alle Daten flöten
gehen.
P.S. der oben gezeigte Code von ihr ist zu 99% von der SD Lib (Arduino)
Beispiel Datenlogger:
https://docs.arduino.cc/learn/programming/sd-guide
N. M. schrieb:> Außerdem spricht sie von Wetterdaten, was zwangsläufig nicht nur die> Temperatur sein wird.> Zusätzlich wird man ab und zu eine richtige Uhrzeit abspeichern müssen.> Der interne Quartz wird bei 10h weglaufen.
Bei Wetterdaten wird es wohl kaum auf Millisekunden oder Sekunden
ankommen, sodass es reichen sollte, die Startzeit zu erfassen.
Wolle G. schrieb:> Bei Wetterdaten wird es wohl kaum auf Millisekunden oder Sekunden> ankommen, sodass es reichen sollte, die Startzeit zu erfassen.
Der Uno hat scheinbar ein Keramik Resonator mit drauf. 0,5% weicht der
angeblich ab. Also 3 min / 10h. Da hast du also Recht.
Hatte ich übersehen.
Der interne RC Oszillator wird nämlich mit 7,3-8,1MHz angegeben. Anstatt
10h können es also auch gerne Mal 10,875h sein. Fast eine Stunde mehr
ist dann schon eine andere Hausnummer.
Im Endeffekt steht alles im Datecalc beispiel in der library.
Man kann auch mit substring oder was auch immer den gespeicherten Text
wie im geposteten Sketch auseinandernehmen und daraus ein Datetime
Objekt erstellen.
Darauf ein timespan anwenden.
Ich denke das liegt der programmiertechnischen Lösung am nächsten.
Die billigen ds1307 sind auch nicht viel genauer wie die interne etc
wenn man den Quarz nicht gegen einen Markenquarz tauscht der mehr wie
das breakout Board kostet.
Mit dem ds3231 hat man 1 Minute pro Jahr Maximum.
Außerdem kann es vorkommen das die rtc durch die vermehrten i2c abfragen
Ticks verliert, also sollte man die interne rtc alle 15-20 Minuten mit
der externen Uhr synchronisieren und diese nutzen.
Wenn es nur ein Lehrbeispiel/Aufgabe ist macht der Aufwand aber keinen
Sinn.