Uhrzeitrechner

OP (Firma: ASch) #7263628
Lesenswert?

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?
Gast #7263647
Lesenswert?

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.
Gast #7263683
Lesenswert?

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.
Gast #7263919
Lesenswert?

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
Gast #7263938
Lesenswert?

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.
Gast #7264049
Lesenswert?

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.
#7264050
Lesenswert?

Wolle G. schrieb:
> etwas unklar
> z.B.
> a) in welchen Zeitabständen werden die Daten erfasst?
1
if (ts.totalseconds() >= 6)

Wolle G. schrieb:
> wo werden die Daten abgespeichert?
1
dataFile_IN = SD.open("inputfile.txt", O_WRITE | O_APPEND);

PittyJ schrieb:
> Ich würde eine SQL Datenbank nehmen.
1
// Pin 10 auf Arduino Uno

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.
#7264370
Lesenswert?

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.
#7264462
Lesenswert?

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/578383

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

https://www.arduino.cc/reference/en/libraries/sd/close/

Dann verballert sie halt für die 40-50 Byte Nutzdaten momentan immer 
einen kompletten Sektor...
Gast #7264470
Lesenswert?

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.
Gast #7266356
Lesenswert?

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.
Gast #7266378
Lesenswert?

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.
Gast #7266428
Lesenswert?

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):
1
  String zeit = rtc.now().timestamp(); //("2020-06-25T15:29:37")
2
  //Lesen mit
3
    String input="2020-06-25T15:29:37|37";
4
  int index = input.indexOf('|');
5
    const String check = input.substring(0,index);
6
    DateTime test(&check);//"2020-06-25T15:29:37"
7
    DateTime temp= test - TimeSpan(  0,    11,    0,    0  );
8
    if(test>temp)
9
    {true}
Gast #7266550
Lesenswert?

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!
#7266640
Lesenswert?

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
#7266670
Lesenswert?

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.
#7266859
Lesenswert?

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.
Gast #7267157
Lesenswert?

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.
Gast #7267159
Lesenswert?

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.
Gast #7267217
Lesenswert?

Adafruit RTClib (es gibt 4 verschiedene RTClib in verschiedenen 
Versionen, der Vergleich von Datetime Objekten ist ziemlich neu, in 
meiner Lib auf dem Rechner war es vor der aktualisierung nicht möglich.)

Erstellung eines DateTime Objektes mit gespeichertetr Zeit.

DateTime (uint32_t t=SECONDS_FROM_1970_TO_2000)
DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour=0, 
uint8_t min=0, uint8_t sec=0)
DateTime (const DateTime &copy)
DateTime (const char *date, const char *time)
DateTime (const __FlashStringHelper *date, const __FlashStringHelper 
*time)
DateTime (const char *iso8601date)(datumTzeit)

Danach geht der vergleich if(DateTime < > DateTime)

man kann aber auch mit der Klasse Timespan Zeit von einem DateTime 
Objekt  mit +- addieren oder hinzufügen.

also wäre logisch:
Datetime jetztbis = rtc.now() - TimeSpan(0,0,11,0)

Datetime LineFromFile("iso8160date"); // siehe oben

und dann:
if(LineFromFile>jetztbis)
.......

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren