Posts mit dem Label SD Karte werden angezeigt. Alle Posts anzeigen
Posts mit dem Label SD Karte werden angezeigt. Alle Posts anzeigen

Sonntag, 21. Juli 2019

Daten in JSON speichern auf dem Wemos


Um seine Daten auf eine SD Karte zu speichern, muss am Anfang klar sein, in welches Format gespeichert werden soll. Das ist dann besonders entscheidend, wenn die Daten wieder weiter verarbeitet werden.
Wenn für den Moment nur ein Wert gespeichert wird, dann reicht Zeilenweise. Bei mehreren Werten müssen die durch ein Zeichen getrennt werden. Das kann dann über Leerzeichen, Semikolon oder Komma sein, bzw. CSV entsprechend. CSV kann prima in Excel betrachtet und weiter verarbeitet werden. Will man die Daten aber weiter verarbeiten, müssen am Ende viele Zeichenketten zu Werten umgewandelt werden. Grundsätzlich ist das nicht verkehrt, aber man muss sich selbst Standards festlegen, um Aufwände gering zu halten.

Was benötigt wird:
  • Arduino oder Wemos
  • SD Shield
  • SD Karte

Vorhaben
Für das Ziel Projekt werden einige Werte aus den Messungen gespeichert. Daher wird ein Daten Objekt benötigt, dass alle Werte enthält. Um dieses nicht im Arbeitsspeicher zu halten, muss der Inhalt persistiert werden und später auf Abruf wieder hergestellt werden.

Datenformat zum Speichern
Die Entscheidung war für mich schon ein eigenes Thema Wert. Neben CSV blicke ich seit langem wieder auf JSON und XML. Nachdem ich ein wenig gesucht habe, kam ich zu dem Entschluss JSON zu verwenden. Für das JSON Format existiert bereits eine fertige Bibliothek.



Was man beachten sollte
Nach einigen Tutorials und veralteten Beispielen, hatte ich die nötigen Informationen zusammen. Zum Schreiben und lesen der Daten können zwei verschiedene Klassen zum Verarbeiten von JSON verwendet werden.
  • StaticJsonDocument
  • DynamicJsonDocument

Für meinen Einsatz reicht der StaticJsonDocument aus. Dieser legt die Daten im Stack ab und verbraucht durch die Eingrenzung auch weniger Arbeitsspeicher. Das ist bedingt durch den Mikrocontroller, vorzugsweise zu verwenden.
Mit DynamicJsonDocument werden die Daten im Heap abgesetzt. Für mein Beispiel konnte ich evaluieren, das nur zwölf Datensätze zuverlässig verarbeitet werden, ohne dass das Programm anhält bzw. abstürzt.

Datenobjekt
Der Zeitpunkt der Aufnahme und zu speichernden Werte werden für den späteren verlauf verwendet. Sekunden habe ich hier nicht einbezogen, da solche Zeitlich genauen Messungen für die Darstellung keinen Nutzen hat. Die Stunden und Minuten werden wiederum verwendet, um später Durchschnittswerte zu berechnen. Der Tag, Monat und Jahr werden ebenfalls für die Durchschnittswerte verwendet.

 class MeasureData {  
  public:  
   int16_t Day;  
   int16_t Month;  
   int16_t Year;  
   int16_t Hour;  
   int16_t Minute;  
   float Temperature;  
   float Humidity;  
   float Pressure;  
 };  


Speichern (Serialisieren)
Bevor die Daten in das JsonObject geschrieben werden können, muss die Größe definiert werden. Im folgenden Programmcode in "JSON_ARRAY_SIZE" der Wert 1 eingetragen, weil hier nur einmal gespeichert wird. Im Github Repository zeige ich dieses mit mehreren Datensätzen.

 void SaveData() {  
  const size_t capacity = JSON_ARRAY_SIZE(1) * JSON_OBJECT_SIZE(8);        
  StaticJsonDocument jsonBuffer;     // set the content size  
  JsonArray data = jsonBuffer.to();   // setup array to write  
  JsonObject measure = data.createNestedObject();  // created to add a new object  
  measure["Day"] = 12;  
  measure["Month"] = 12;  
  measure["Year"] = 2019;  
  measure["Hour"] = 12;  
  measure["Minute"] = 12;  
  measure["Temperature"] = 21.4f;  
  measure["Humidity"] = 50.5f;  
  measure["Pressure"] = 12345.6f;  
  File file = SD.open(mFilename, FILE_WRITE);  
  serializeJson(jsonBuffer, file);       // write json document to file  
  file.close();   
 } 

Öffnen (Deserialisierung)
Genau wie beim Speichern, wird ebenfalls die Kapazität angegeben. Dann kann die eingelesene Datei aus dem JSON Inhalt eingelesen und als JsonObject abgerufen werden.

 void OpenData() {  
  File file = SD.open(mFilename);  
  String content = file.readString();  
  const size_t capacity = JSON_ARRAY_SIZE(1) * JSON_OBJECT_SIZE(8);        
  StaticJsonDocument doc;  
  deserializeJson(doc, content);  
  JsonObject measure = doc[0];  
  Serial.print(" Day:"); Serial.print((int16_t)measure["Day"], DEC);  
  Serial.print(" Month:"); Serial.print((int16_t)measure["Month"], DEC);  
  Serial.print(" Year:"); Serial.print((int16_t)measure["Year"], DEC);  
  Serial.print(" Hour:"); Serial.print((int16_t)measure["Hour"], DEC);  
  Serial.print(" Minute:"); Serial.print((int16_t)measure["Minute"], DEC);  
  Serial.print(" Temperatur:"); Serial.print((float)measure["Temperature"], DEC);  
  Serial.print(" Humidity:"); Serial.print((float)measure["Humidity"], DEC);  
  Serial.print(" Pressure:"); Serial.println((float)measure["Pressure"], DEC);  
 }  


Fazit
Das JSON Format kann ich jeden nahe legen, dieses zu verwenden. Sobald mehrere Daten erfasst und gespeichert werden, ist der Aufwand beim Einlesen nahezu gleich. Das mag anfangs etwas ungewohnt sein. Spätestens wenn ihr Daten aus einer CSV einlesen wollt, das innerhalb des Mikrocontroller Bereiches geschieht, spart ihr eine Menge Zeit für das Entwickeln einer Methode, dass die Daten einließt.

Wie immer ein Beispiel:

Samstag, 7. Juli 2018

Wetterstation und Daten Logger


Immer die Aktuellen Messdaten abzurufen ist schön, aber auf Dauer würde man doch gerne sich ansehen wie sich das Wetter über einen Zeitraum verändert hat. Man könnte natürlich immer zu jeder Stunde nach sehen und sich das in der Excel Tabelle Notieren. Besser wäre der Vorgang, ein Programm zu verwenden das im vordefinierten Intervall die Messdaten automatisch speichert.


Wemos Codebeispiele
Die kurz Beschreibung, wie die Daten auf die SD Karte geschrieben werden, ist auf dem Github zu Wemos zu finden.

Simple übernommen
Ich habe das Codebeispiel übernommen und entsprechende Anpassungen und Erweiterungen eingesetzt. Im wesentlich wird am Anfang das SD Shield initialisiert und geprüft, ob eine SD Karte eingesetzt ist. Über den Seriellen Monitor wird der Typ und die Kapazität der SD Karte abgezeigt. Wenn die Zieldatei noch nicht vorhanden ist beim Speichern, wird die Datei "weather.csv" angelegt und bekommt in die erste Zeile die Header Info zu den Spalten.

Abruf der gespeicherten Daten
Nach dem Initialisieren und der ersten Messungen, werden im Beispiel von mir, alle zehn Sekunden die aktuellen Daten auf die SD Karte gespeichert. Die Daten werden in einer CSV Datei angehängt. Hierbei wird die Datei geöffnet und der neue Datensatz in eine neue Zeile geschrieben. Um später die Datei zu entnehmen, muss die SD Karte aus dem Shield entnommen werden und am PC mit einem SD Karten Slot eingelesen werden.

Problem mit Excel
Öffnet man die Datei in Excel, so kann es sein das Werte als Datum Formatiert werden. Das liegt mitunter an der verwendeten Zeichen für Nachkommastelle. Technisch gesehen ist alles Richtig, nur Excel macht etwas zu viel des Guten.


Statt die Datei per Doppel klick zu öffnen, muss die Datei über Excel aufgerufen werden. Über den Reiter "Daten" und dann Daten abrufen -> Aus Datei -> Aus Text/CSV  kann die Datei importiert werden.


Nach dem Import öffnet sich ein neuer Dialog. In der dritten Combobox wählt ihr Dateitypen nicht ermitteln und anschließend kann dann auf den Button Laden geklickt werden.


Leider kann das hier nur zum Betrachten verwendet werden. Eine Darstellung in einem Diagramm geht hier ebenfalls nicht. Zugegeben empfand ich dies sehr nervig und schrieb hierzu ein einfachen Konverter, der mir die Werte in das Zielformat bringt. In dem vorigen Bild ist auch zu sehen, dass die Nachkommastelle komplett entfernt wurde.

Hat nur eine Aufgabe
Das Tool zum konvertieren der CSV Datei ist ebenfalls auf meinem Repository zu finden. Momentan kann das Tool nur eine Sache und zwar die Zahlen mit einem Punkt als Nachkommastelle umzustellen zu einem Komma. Wenn die Anforderungen steigt, dann werde ich sicherlich mehr daraus machen.


Im Diagramm betrachten
Kommen wir zum eigentlich Ziel. Die gemessenen Daten können in Excel im Einzelnen Betrachtet werden. Mit dem Anlegen einer Diagramm-kurve sieht man wie die Temperatur und Feuchtigkeit zu einander sich verändert haben. Der Luftdruck muss ein separates Diagramm haben, da die Werte im Hektopascal hinterlegt sind.


Immer noch nicht Rund
Das Automatische Aufzeichnen der Messdaten ist schon hilfreich. Aber an den gespeicherten Messungen ist keine Uhrzeit angegeben, so dass eine Zeitliche Orientierung nicht ermittelt werden kann. Und noch besser wäre, die Diagramme ebenfalls im Browser anzuzeigen. Aber dazu komme ich zu einem anderen Zeit.



Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...