derzeit bin ich am basteln eines Datenloggers um den Stromverbrauch im Haus und der erzeugte Strom einer Photovoltaikanlage aufzuzeichnen. Somit möchte ich herausfinden wie viel Strom eigenverbraucht werden könnte und wie weit dieser im Winter zur Eigenversorgung ausreichen würde.
Es sollen zwei separate Logger verwendet werden, da die beiden Zähler nicht nebeneinander hängen sondern auf der jeweils gegenüberliegenden Straßenseite sind (Die PV ist auf einer Garage). Das Ganze soll über mehrere Jahre laufen um eine gute Aussagegenauheit zu erhalten. Dementsprechend groß wird die Datei mit den Aufzeichnungen werden.
Hierzu habe ich mir eine Infrarotlichtschranke gebastelt um die Umdrehungen des Zählerrades vom Ferraris-Zähler zählen zu können. Die Anzahl der Umdrehungen soll zusammen mit Datum und Uhrzeit alle zwei Minuten auf einer SD Karte gespeichert werden. Nach entfernen der SD Karte kann das Ganze dann mit Excel ausgewertet werden. Derzeit verwende ich die bei der IDE enthaltene Library für die SD Karte.
Auf der SD Karte werden die Daten derzeit in folgendem Format gespeichert, da der Import in Excel somit sehr einfach ist.
TT.MM.JJJJ HH:MM:SS, "Anzahl der Umdrehungen"
16.8.2018 12:28:00,10
Jetzt hätte ich gerne die Funktion, dass wenn der Strom ausfällt das Arduino nach dem Neustart den letzten Zählerstand von der SD Karte ausliest und dort weiterzählt wo es vor dem Stromausfall aufgehört hat. Meine Idee wäre hierzu das Format so abzuändern, dass die Anzahl der Umdrehungen immer die gleiche Länge von 8 Zeichen hat. Das Log-fiel könnte dann so aussehen:
Das heißt nach einem Stromausfall soll das Arduino die Datei auf der SD Karte öffnen, und einfach die letzten 8 Zeichen in die Zählvariable laden und weiterzählen als wäre nichts gewesen. Uhrzeit und Datum kommen von einer externen Echtzeituhr und können unberücksichtigt bleiben.
Nun kommt mein Problem. Ich habe keine Idee wie ich die letzten 8 Zeichen aus der Datei auslesen und in die Variable übertragen kann. Ich habe schon eine Weile gegoogelt und auch verschiedenes gefunden, jedoch ist die ganze SD Geschichte für mich Neuland und ich habe das Gefühl mir fehlen die Grundlagen um das geschriebene zu verstehen.
kann mir hierbei jemand weiterhelfen, wie ich das am besten anstellen kann? Ich wäre schon froh wenn mir jemand einen Tipp geben könnte wo ich Hilfen finde die ich mit möglichst wenig Vorahnung verstehen kann. Quasi Hilfe zur Selbsthilfe.
vielleicht liest Du dann die ganze Datei zeichenweise in ein Char Array mit 8 Stellen.Und schiftest die Zeichen jeweils eins weiter beim lesen, bis das Dateiende Zeichen gelesen wird.
@combie: Danke für den Hinweis mit den begrenzten Schreibzyklen einer SD Karte. Das war mir nicht bekannt. Ich habe mich wohl selbstüberschätzt, was das angeht mit der SD Karte. Ich dachte das wird schon halb so wild sein und hab mir blauäugig einen SD Adapter bestellt.
Von FRAM oder NVRAM habe ich noch nichts gehört und muss mich erstmal schlaulesen. Hintergrund gleich zu addieren war folgender, mein Plan war es später noch ein LCD anzuschließen welches den aktuellen Zählerstand anzeigt der auf der SD Karte gespeichert ist. Somit kann ich einfach abgleichen ob der gespeicherte Stand dem auf dem Ferraris-Zähler entspricht, ohne die Karte entnehmen zu müssen.
Ich habe mal Codeschnipsel zusammenkopiert mehr kann man das nicht nennen. Das ganze sieht jetzt so aus:
#include <SPI.h>
#include <SD.h>
File myFile;
char Zahl;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4))
{
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
myFile = SD.open("test.txt");
if (myFile)
{
myFile.seek( myFile.size() - 10);
while (myFile.available()) {
Serial.write(myFile.read());
}
myFile.seek( myFile.size() - 10);
while (myFile.available()) {
Zahl = (myFile.read());
Serial.println(Zahl);
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// nothing happens after setup
}
Auf der Speicherkarte ist eine Datei mit folgendem Inhalt vorhanden:
16.8.2018 12:28:00,00000010
16.8.2018 12:30:00,00000011
16.8.2018 12:32:00,00000012
16.8.2018 12:34:00,00000020
Die richtigen Zeichen sind schonmal vorhanden aber wie mache ich jetzt eine rechenbare Variable daraus?
Entschuldigt meine Unwissenheit. Wenn ihr einen guten Link mit Erklärungen kennt oder ein Buch zu dem Thema empfehlen könnt wäre das auch ganz gut. Ich würde mich gerne einlesen.
Alles fertig, mit Datenbank, mit Webinterface, mit App, mit Support, und kann noch viel mehr.
...und kost nix
Benutze ich seit gut 1,5 Jahren und habe aktuell glaub ich so rund 40 Mio. Datensätze von inzwischen rund 69 Sensoren (Strom, Wasser, Temperatur, Lüfterdrehzahl, ...)
Und wenn man das aber auch macht weil man selber was machen will: Da gibt's noch genug woran man sich selber austoben kann.
Ich habe z.B. eine Drehzahlmessung für 3 Ventilatoren aus der Be- und Entlüftungsanlage selber gemacht, und ein Display im Gäste WC welches Daten anzeigt (davon kommen noch weitere), habb hätte ich gerne noch ein anders gestricktes Webinterface für die Auswertung, und und und, da gibt's auch noch nie riesen Spielwiese drum rum
wo kommt der Unsinn mit dem SD-Karten tot schreiben her? Wenn du aller Minute paar Bytes schreibst bekommste die im ganzen Leben nicht tot geschrieben. Die kannste vererben und die Urenkel können weiterschreiben. Eine billige Karte vom Wühltisch sollte es dennoch nicht sein. Die Probleme kommen eher von anderer Seite. Kontaktprobleme oder Softwareabstürze zu ungünstigen Zeitpunkten mitten im schreiben o.ä. ...
Vom Raspberry her hat man die allgemeine Erfahrung das es eher bei dem alten großen Kartenformat zu Kontaktproblemen kommt. Micro SD macht bisher keine Probleme. Eine eigene Sicherheitsvorkehrung wäre zum Bsp. für jeden Monat eine Datei anzulegen.
.....Ich hab schon eine SanDisk 64GB Karte im Handy kaputtgespielt. Nach 1,5 Jahren konnte man nur noch lesen, aber nicht mehr schreiben. Der Effekt war so, das man ein Foto gemacht hat, dies in der Kurzansicht sehen konnte, und danach aber keins mehr in der Gallery zu finden war. Alle alten Fotos waren aber da.
Die SanDisk Karte hat da einen speziellen Modus, der nur noch lesen erlaubt wenn es zu irgendwelchen Fehler kommt. So ist sichergestellt, dass die Daten die drauf sind nicht auch noch kaputt gehen.
Im Raspi3 hatte ich eine Datenbank laufen. Da hat die Karte keine 2 Wochen durchgehalten.
Man kriegt die Karten auf jeden Fall kaputt. (Gut okay, mit welchen Datenmengen ist natürlich ne andere Geschichte)
Die meisten Karten sind gut für große Dateien geeignet, Streaming.
Kontinuierliches Schreiben großer Dateien.
Logging, funktioniert eher nach dem Random Access Prinzip.
Da muss die Datei dauernd auf und zu gemacht werden.
Man will ja schließlich die Zeit, während das Dateisystem inkonsistent ist, möglichst kurz halten.
den "Schreibschutz" bei defekt hat eigentlich jede Karte. Sollte heutzutage jede haben. Auch SSDs haben das. Ich weiß aber nicht was ihr mit euren Karten macht. Ich habe noch keine Einzige kaputt bekommen. Ehrlich. Mit kaputt meine ich kaputt. Die im Raspi zickte mal rum. Neu formatiert, läuft heute noch. Datalogger im Auto unterm Sitz, nicht gerade die sauberste Umgebung, keine Probleme. Handy, noch nie Probleme gehabt. Dashcam im Auto in Endlosschleife, keine Probleme.
Gerade durch das Wear Leveling sind auch kleine Dateien und eben im langen Minutenabstand kein Problem. Ich sehe dabei auch keine Probleme. Was anderes wäre es wenn das im Sekundentakt wäre. Hier würde auch Dateien anlegen helfen. Die Chance alte Dateien zu retten die nicht mehr im Zugriff waren ist höher falls das Dateisystem einen Treffer weg haben sollte. Eben das muss noch lange nicht auf einen Defekt der Karte hindeuten. Zudem ich bei dem Vorhaben, egal was ist, immer zwischendurch Backups anlegen würde. Ich würde, wenn die Daten so wichtig sind, mich niemals blind darauf verlassen das über Jahre unkontrolliert laufen zu lassen. Am PC sichert man schießlich auch regelmäßig seine wichtigsten Daten für den Fall der hoffentlich niemals eintritt. Er tritt aber immer genau dann ein wenn man kein Backup hat. Murphys Gesetz ist erbarmungslos.
Edit:
All die Dinge über die wir bis jetzt gesprochen haben sind plötzliche Hardwaredefekte wie sie immer auftreten können. Das alles hat jedoch nichts mit aktiven "tot schreiben" zu tun. Dafür müssen ganz andere Datenmengen her. Soviel zum Mythos. Nur damit der Unterschied deutlich wird.
Danke euch Allen,
jetzt läuft der Code wie er soll. Ich hoffe das macht er auch zukünftig.
Mit dem gefürchteten tot schreiben der Karte habe ich es jetzt so gelöst, dass ich alle zwei Minuten die Menge der hinzugekommenen Impulse in ein Array schreibe(Da innerhalb dieser Zeit nur wenige Impulse auftreten können reicht ein Byte Array um Ram zu sparen). Ist nun eine Stunde vorbei wird aus den Änderungen der Zählerstand rückwirkend berechnet und anschließend alle Daten der Vergangenen Stunde auf einmal auf die Karte geschrieben. Sollte jetzt der Strom ausfallen fehlt maximal eine Stunde Datenmaterial was zu verkraften ist.
Ich habe vor ca. einmal im Monat die Daten zu ernten. Dazu wäre es noch schön, wenn ich die Karte im laufenden Betrieb herausziehen und die Daten auf den PC übertragen könnte. Hierzu wäre jetzt theoretisch eine Stunde Zeit bis die SD karte wieder vom Arduino beschrieben wird. Tante Google hat mir verraten, dass das so mancher von euch schon mit einer modifizierten SD Library gelöst hat. Jedoch ist mir noch nicht ganz klar wie ich das machen kann. Hättet ihr hierzu nochmals einen Tip für mich?
@themanfrommoon: Den Volkslogger habe ich mir schon im Vorfeld angesehen. Jedoch dagegen entschieden, da ich in der Garage wo der Zähler der PV installiert ist keinen Internetzugang habe. Eine Funkverbindung wird wahrscheinlich auch schwierig, da ich durch einige Wände und Decken müsste.
wegen Karte ziehen im laufenden Betrieb. Dafür habe ich einen extra Taster. Wurde der betätigt, leuchtet eine Kontroll LED für diesen Modus und gleichzeitig sind Lese- und Schreibfunktion gesperrt. Wenn Karte wieder drin, Taster erneut drücken, LED aus, alles wieder scharf geschalten.
Damit das mit der SD Lib von Arduino immer klappt, musste diese leider noch etwas modifizieren.
C:\Program Files (x86)\Arduino\libraries\SD\src\SD.cpp
Ab Zeile 337 gibts eine Methode die eine zusätzliche Zeile benötigt.
bool SDClass::begin(uint8_t csPin) {
/*
Performs the initialisation required by the sdfatlib library.
Return true if initialization succeeds, false otherwise.
ergänzt, root wird geschlossen falls offen, damit kann jederzeit erneut initialisiert werden,
zum Bsp. nach Kartenwechsel
*/
if (root.isOpen()) root.close(); // allows repeated calls
return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);
}
Du kannst natürlich auch etwas moderneres verwenden. Das wäre die SdFat Lib von einem gewissen Greiman.
danke nochmals für eure tolle Unterstützung. Der Logger lief jetzt über Nacht probe und hat einwandfrei funktioniert. Die Karte wird einmal in der Stunde beschrieben. Die SD kann während des Betriebs entfernt werden und anschließend einfach wieder eingesteckt werden. Ein LCD zeigt an wie lange es noch bis zum nächsten Schreibvorgang dauert um zu wissen wann man die Karte gefahrlos entfernen kann. Ist die Karte während des Schreibens nicht eingesteckt, geht der Datensatz der vergangenen Stunde verloren aber der Logger funktioniert trotzdem weiter und schreibt sobald eine SD vorhanden ist auch wieder darauf.
Da jetzt schon ein LCD daran hängt lasse ich auch noch den momentanen Zählerstand in Echtzeit anzeigen und den Zählerstand der auf der SD gespeichert ist. Dieser wird einmal in der Stunde aktualisiert. Da ich noch ein 4 Zeilen LCD hatte und somit noch eine Zeile über ist, zeige ich noch die aktuelle Leistung in Watt an.
Nun noch eine kleine Frage, das Display zeigt an manchen Stellen immer dasselbe Zeichen, bzw. die Anzeige verändert sich nur sehr selten. Muss ich mir bei einer normalen LCD-Matrixanzeige (die Dinger mit z.B. 20x4 Zeichen und angeflanschtem HD44780) sorgen machen, dass etwas einbrennt? Dann würde ich noch eine Art Bildschirmschoner hinzufügen. Auch könnte ich mir vorstellen das Display nachts nichts anzeigen zu lassen, wenn das hilft. Aber wenn dies nicht nötig ist spare ich mir gerne den Aufwand dazu.
@themanfrommoon: WLAN ist leider nicht vorhanden. Die Entfernung zum Haus beträgt ca. 50 Meter und es sind einige Störkonturen im Weg, die erfolgreich verhindern, dass irgendein Signal in der Garage ankommt. Vielleicht würde es funktionieren wenn man die Antennen nach Außen verlegt, aber das ist mir den Aufwand nicht wert.
Du musst Dir um das LCD keine Sorgen machen, das sind nur stehengelassene Zeichen!
Wenn da vorher 4 Ziffern o.ä. standen, und jetzt 3 Ziffern, dann bleibt das an dieser Stelle zuletzt geschriebene Zeichen stehen. Also diese Stelle mit Leerzeichen überschreiben.
Dass Die Zeichen stehen bleiben, wenn sie nicht überschrieben werden ist mir bewusst. Ich meinte damit, dass sie Ablaufbedingt sehr lange bzw. auch immer stehen bleiben.
Bei einem 6 Stelligen Zähler der gerade z.B. 243716 kW/h anzeigt bleiben die ersten paar Zahlen sehr lange stehen. Ob dies dem Display schadet, wenn es immer die gleiche Ziffer anzeigen muss, ist mir unklar.
Wenn es ihm nicht schadet, kann ich einfach die Hintergrundbeleuchtung ausschalten und per Knopfdruck wieder einschalten. Sollte es ihm doch schaden wäre es vielleicht wirklich am besten wenn ich den Inhalt nur auf Knopfdruck erscheinen lasse und nach einer gewissen Zeit den gesamten Displayinhalt wieder lösche.
Axialgeblaese:
Bei einem 6 Stelligen Zähler der gerade z.B. 243716 kW/h anzeigt bleiben die ersten paar Zahlen sehr lange stehen. Ob dies dem Display schadet, wenn es immer die gleiche Ziffer anzeigen muss, ist mir unklar.
Im Wikipedia-Artikel zu LCDs wird die Lebensdauer und das, was Du möglicherweise befüchtest, nicht erwähnt (ich habe allerdings nicht alles gelesen). Aber im Artikel ist eine Armbanduhr mit LC-Display zu sehen. Die Haltbarkeit ist zumindest bei Uhren ziemlich gut.