Hier mal ein erster Teil für das Abspeichern von Daten im Flash mit Ringpuffer.
Ich werde das Ganze in ein Makro packen, so dass die Anwendung einfach wird. Dies hier dient nur der Veranschaulichung!
Der Code speichert abhängig von Store_Timer (s.u.) z.B. alle 1/4 Stunde, täglich etc. Minimum, Maximum und Mittelwert und Zeitstempel. Er benötigt dazu 2 Speicherplätze im Flash. Diese Werte werden effizient in ein Stringarray gespeichert, so dass 116 Werte mitgeloggt werden.
Dabei wird eine Ringpufferstruktur angelegt, d.h. neue Werte überschrieben werden. Das Speichern auf das Flash wird mit der Variablen Store_Now gesteuert (hier um Mitternacht). Bis zu diesem Zeitpunkt wären die Variablen nur im RAM und nicht im Flash.
Der Puffer kann Datentypen zwischen 1 und 32 Bit aufnehmen.
Mit den Variablen Store_InitDay,Store_InitMon,Store_InitYear kann festgelegt werden, ob bei einem neuen Einspielen des Progamms aus dem Flash gelesen werden soll (das Datum muss bereits vorüber sein), oder ob die Daten neu geschrieben werden.
Da man (wenn mal ein Makro da ist) beliebige Puffer mit unterschiedlichen Zeitintervallen (Kurz-, Mittel-, Langzeit) ist die Sache an sich recht brauchbar - vielleicht erübrigt sich die RRD Datenbank
.
[highlight=epc]
//Value kann zwischen 1 und 32 Bit breiter Datentyp sein
Value='2/1/3'u08+1
// Ein paar Daten generieren zu Testzwecken
if stime(2) or stime(17) or stime(32) or stime(48) or stime(9) or stime(19) or stime(39) or stime(49) then write('2/1/3'u08,'2/1/3'u08+2) endif
//
// -----------------------------------------------------------------------
//
// Speichern auf das Flash:
// Platz1: Min,Max,Mittelwert (im Abstand von 4 Bytes)
// Platz2: std,min,sek,Tag,Monat, Jahr (im Abstand von 4 Bytes)
// -----------------------------------------------------------------------
//initga('2/1/3'f32)
Store_InitDay=2
Store_InitMon=12
Store_InitYear=10
Store_Start=AUS
// Zeitpunkt: 1/4 Stunden Werte
//Store_Timer=mtime(0,0) or mtime(15,0) or mtime(30,0) or mtime(45,0)
Store_Timer=stime(0) or stime(15) or stime(30) or stime(45)
// Speichern in temporäre Arrays
Store_Array=$$
Store_TimeStamp=$$
Store_ArrayPos=0u16
Store_TimeStampPos=1u16
Store_CarryFlag=OFF
Store_Now=htime(0,0,convert(random(59u32),0))
// Indexspeicher
Store_Init=2u16
Store_Pos=Store_Init
// Min,Max,Mittelwert
Store_Max=convert(0,Value)
Store_Min=convert(0,Value)
Store_Avg=0f32
Store_AvgIcr=1f32
//
Store_Error=AUS
// Datum als Zahlen abspeicher
Store_dd=convert(split(convert(setdate(),$$),0u16, 1u16),0)
Store_mm=convert(split(convert(setdate(),$$),3u16, 4u16),0)
Store_yy=convert(split(convert(setdate(),$$),6u16, 10u16),0u16)
// Aufzeichnung nur aus dem Flash lesen, wenn Aufzeichnung bereits begonnen hatte
if date(Store_InitDay,Store_InitMon,Store_InitYear) then {
readflash(Store_Array, Store_ArrayPos);
readflash(Store_TimeStamp, Store_ArrayPos+1u16)
} else {
writeflash(Store_Pos, Store_ArrayPos);
writeflash(Store_CarryFlag, Store_ArrayPos+1u16)
} endif
// Sollte ein Wert aus dem Flash gelesen werden, so muss dieser
// eine gültige Position haben
if after(systemstart(),500u64) and date(Store_InitDay,Store_InitMon,Store_InitYear) then {
Store_Pos=stringcast(Store_Array,Store_Pos,0u16);
if mod(Store_Pos-Store_Init,12u16)>0u16 then Store_Pos=Store_Init endif
} endif
if after(systemstart(),1000u64) then {
Store_Max=Value;
Store_Min=Value;
Store_Avg=convert(Value,0f32);
Store_AvgIcr=1f32;
Store_Start=EIN
} endif
// Min,Max, Mittelwert
if (Store_Max<Value) and Store_Start then Store_Max=Value endif
if (Store_Min>Value) and Store_Start then Store_Min=Value endif
if change(Value) and Store_Start then {
Store_AvgIcr=Store_AvgIcr+1f32;
Store_Avg=((Store_Avg*(Store_AvgIcr-1f32))+convert(Value,0f32))/Store_AvgIcr
} endif
// Messen im nächsten Zeitintervall
if after(Store_Timer,1u64) and Store_Start then {
Store_Max=Value;
Store_Min=Value;
Store_Avg=convert(Value,0f32);
Store_AvgIcr=1f32;
Store_Pos=Store_Pos+12u16
} endif
// In das StringArray Speichern
// 12 Byte (3x4 Byte): Value kann zwischen 1 und 32 Bit breiter Datentyp sein
// Die Zeitwerte werden im TimestampArray gespeichert
if Store_Start and Store_Timer then {
if (Store_Pos>END-12u16) then Store_Pos=Store_Init; Store_CarryFlag=ON endif;
stringset(Store_Array,Store_Pos,0u16);
stringset(Store_Array,Store_Min,Store_Pos);
stringset(Store_Array,Store_Max,Store_Pos+4u16);
stringset(Store_Array,Store_AvgIcr,Store_Pos+8u16) ;
stringset(Store_TimeStamp,Store_CarryFlag,0u16);
stringset(Store_TimeStamp,hour(),Store_Pos);
stringset(Store_TimeStamp,minute(),Store_Pos+1u16) ;
stringset(Store_TimeStamp,second(),Store_Pos+2u16) ;
stringset(Store_TimeStamp,Store_dd,Store_Pos+3u16) ;
stringset(Store_TimeStamp,Store_mm,Store_Pos+4u16) ;
stringset(Store_TimeStamp,Store_yy,Store_Pos+5u16)
} endif
// Speichern der Werte
if (change(Store_Array) and Store_Now) or (Store_Pos>END-12u16) then {
Store_Error=writeflash(Store_Array,Store_ArrayPos) or writeflash(Store_TimeStamp,Store_ArrayPos+1u16)
} endif
[/highlight]
Ich werde das Ganze in ein Makro packen, so dass die Anwendung einfach wird. Dies hier dient nur der Veranschaulichung!
Der Code speichert abhängig von Store_Timer (s.u.) z.B. alle 1/4 Stunde, täglich etc. Minimum, Maximum und Mittelwert und Zeitstempel. Er benötigt dazu 2 Speicherplätze im Flash. Diese Werte werden effizient in ein Stringarray gespeichert, so dass 116 Werte mitgeloggt werden.
Dabei wird eine Ringpufferstruktur angelegt, d.h. neue Werte überschrieben werden. Das Speichern auf das Flash wird mit der Variablen Store_Now gesteuert (hier um Mitternacht). Bis zu diesem Zeitpunkt wären die Variablen nur im RAM und nicht im Flash.
Der Puffer kann Datentypen zwischen 1 und 32 Bit aufnehmen.
Mit den Variablen Store_InitDay,Store_InitMon,Store_InitYear kann festgelegt werden, ob bei einem neuen Einspielen des Progamms aus dem Flash gelesen werden soll (das Datum muss bereits vorüber sein), oder ob die Daten neu geschrieben werden.
Da man (wenn mal ein Makro da ist) beliebige Puffer mit unterschiedlichen Zeitintervallen (Kurz-, Mittel-, Langzeit) ist die Sache an sich recht brauchbar - vielleicht erübrigt sich die RRD Datenbank

[highlight=epc]
//Value kann zwischen 1 und 32 Bit breiter Datentyp sein
Value='2/1/3'u08+1
// Ein paar Daten generieren zu Testzwecken
if stime(2) or stime(17) or stime(32) or stime(48) or stime(9) or stime(19) or stime(39) or stime(49) then write('2/1/3'u08,'2/1/3'u08+2) endif
//
// -----------------------------------------------------------------------
//
// Speichern auf das Flash:
// Platz1: Min,Max,Mittelwert (im Abstand von 4 Bytes)
// Platz2: std,min,sek,Tag,Monat, Jahr (im Abstand von 4 Bytes)
// -----------------------------------------------------------------------
//initga('2/1/3'f32)
Store_InitDay=2
Store_InitMon=12
Store_InitYear=10
Store_Start=AUS
// Zeitpunkt: 1/4 Stunden Werte
//Store_Timer=mtime(0,0) or mtime(15,0) or mtime(30,0) or mtime(45,0)
Store_Timer=stime(0) or stime(15) or stime(30) or stime(45)
// Speichern in temporäre Arrays
Store_Array=$$
Store_TimeStamp=$$
Store_ArrayPos=0u16
Store_TimeStampPos=1u16
Store_CarryFlag=OFF
Store_Now=htime(0,0,convert(random(59u32),0))
// Indexspeicher
Store_Init=2u16
Store_Pos=Store_Init
// Min,Max,Mittelwert
Store_Max=convert(0,Value)
Store_Min=convert(0,Value)
Store_Avg=0f32
Store_AvgIcr=1f32
//
Store_Error=AUS
// Datum als Zahlen abspeicher
Store_dd=convert(split(convert(setdate(),$$),0u16, 1u16),0)
Store_mm=convert(split(convert(setdate(),$$),3u16, 4u16),0)
Store_yy=convert(split(convert(setdate(),$$),6u16, 10u16),0u16)
// Aufzeichnung nur aus dem Flash lesen, wenn Aufzeichnung bereits begonnen hatte
if date(Store_InitDay,Store_InitMon,Store_InitYear) then {
readflash(Store_Array, Store_ArrayPos);
readflash(Store_TimeStamp, Store_ArrayPos+1u16)
} else {
writeflash(Store_Pos, Store_ArrayPos);
writeflash(Store_CarryFlag, Store_ArrayPos+1u16)
} endif
// Sollte ein Wert aus dem Flash gelesen werden, so muss dieser
// eine gültige Position haben
if after(systemstart(),500u64) and date(Store_InitDay,Store_InitMon,Store_InitYear) then {
Store_Pos=stringcast(Store_Array,Store_Pos,0u16);
if mod(Store_Pos-Store_Init,12u16)>0u16 then Store_Pos=Store_Init endif
} endif
if after(systemstart(),1000u64) then {
Store_Max=Value;
Store_Min=Value;
Store_Avg=convert(Value,0f32);
Store_AvgIcr=1f32;
Store_Start=EIN
} endif
// Min,Max, Mittelwert
if (Store_Max<Value) and Store_Start then Store_Max=Value endif
if (Store_Min>Value) and Store_Start then Store_Min=Value endif
if change(Value) and Store_Start then {
Store_AvgIcr=Store_AvgIcr+1f32;
Store_Avg=((Store_Avg*(Store_AvgIcr-1f32))+convert(Value,0f32))/Store_AvgIcr
} endif
// Messen im nächsten Zeitintervall
if after(Store_Timer,1u64) and Store_Start then {
Store_Max=Value;
Store_Min=Value;
Store_Avg=convert(Value,0f32);
Store_AvgIcr=1f32;
Store_Pos=Store_Pos+12u16
} endif
// In das StringArray Speichern
// 12 Byte (3x4 Byte): Value kann zwischen 1 und 32 Bit breiter Datentyp sein
// Die Zeitwerte werden im TimestampArray gespeichert
if Store_Start and Store_Timer then {
if (Store_Pos>END-12u16) then Store_Pos=Store_Init; Store_CarryFlag=ON endif;
stringset(Store_Array,Store_Pos,0u16);
stringset(Store_Array,Store_Min,Store_Pos);
stringset(Store_Array,Store_Max,Store_Pos+4u16);
stringset(Store_Array,Store_AvgIcr,Store_Pos+8u16) ;
stringset(Store_TimeStamp,Store_CarryFlag,0u16);
stringset(Store_TimeStamp,hour(),Store_Pos);
stringset(Store_TimeStamp,minute(),Store_Pos+1u16) ;
stringset(Store_TimeStamp,second(),Store_Pos+2u16) ;
stringset(Store_TimeStamp,Store_dd,Store_Pos+3u16) ;
stringset(Store_TimeStamp,Store_mm,Store_Pos+4u16) ;
stringset(Store_TimeStamp,Store_yy,Store_Pos+5u16)
} endif
// Speichern der Werte
if (change(Store_Array) and Store_Now) or (Store_Pos>END-12u16) then {
Store_Error=writeflash(Store_Array,Store_ArrayPos) or writeflash(Store_TimeStamp,Store_ArrayPos+1u16)
} endif
[/highlight]
Kommentar