Umweltmessstation ohne Internetanbindung

Offline Upload mit SD-Karte

An Orten, wo gerade kein Internet oder LoRaWAN verfügbar ist, bietet es sich an, eine SD-Karte zu verwenden, um Messwerte zu speichern. Die Messwerte können später ganz einfach von der SD-Karte auf die openSenseMap übertragen werden! Das RTC-Modul (Real-Time-Clock) wird verwendet, um die Messwerte mit einem korrekten Zeitstempel zu versehen. Das RTC-Modul bestitzt eine Uhr, die nach einmaligem Einstellen mithilfe einer Batterie bis zu 7 Jahre läuft und ausgelesen werden kann.

Aufbau

Stecke die microSD-Karte in das SD-Bee. Achte hier darauf die microSD Karte korrekt zu installieren! Eine Illustration auf der Rückseite des SD-Bees zeigt dir, wie die microSD-Karte eingesteckt werden muss. Stecke daraufhin das SD-Bee an den XBEE2-Steckplatz. Wichtig ist, dass du den Steckplatz XBEE2 verwendest, da das Bee ansonsten nicht ordnungsgemäß funktioniert. Das RTC-Modul verbindest du mit einem der JST-JST-Kabel an einen der fünf I2C-Ports. Nun musst du noch den Umweltsensor mit dem JST-JST-Kabel an einen weiteren I2C-Port anschließen und der Aufbau ist fertig! Du kannst den Aufbau natürlich auch um weitere Sensoren erweitern.

Registrierung auf der openSenseMap

Bevor du mit der Programmierung beginnst, solltest du dein Messgerät auf der openSenseMap registrieren. Wähle die Sensoren aus, die du an deine senseBox angeschlossen hast. Nach der Registrierung erhälst du für jeden Sensor bzw. für jedes Phänomen eine SensorID, die wichtig ist, um die Messwerte richtig zuordnen zu können.

Programmierung: Messwerte auf SD-Karte speichern

Nutze den senseBox - Code Editor oder die Arduino IDE, um die Programmierung für dieses Projekt durchzuführen. Jede Minute soll ein Messwert auf der SD-Karte gespeichert werden, um diese nachher gebündelt auf der openSenseMap hochladen zu können.

Schritt 1: Librarys importieren, Variablen erstellen

Zuerst müssen die benötigten Librarys aus dem Board-Support-Package reingeladen werden.

#include <SPI.h>
#include <SD.h>
#include "SenseBoxMCU.h"
#include <RV8523.h>

Daraufhin werden für die Sensor ID’s der Sensoren Konstanten erstellt. Die Sensor ID’s werden dir nach Fertigstellung der Registrierung angezeigt und können alternativ über das Dashboard eingesehen werden Dashboard->deine SenseBox -> Editieren -> Sensoren.

// ID's
const char *TEMP_ID = "SENSORID";
const char *HUMI_ID= "SENSORID";

Zusätzlich wird noch ein Objekt myFile erstellt, welches die Datei, die auf der SD-Karte gespeichert werden soll, repräsentiert.
Danach muss noch ein Objekt sowohl für den Sensor als auch für das RTC-Modul definiert werden.

File myFile;
HDC1080 hdc;
RV8523 rtc;

Als Letztes wird noch eine Variable erstellt, in der die Uhrzeit später gespeichert wird. Der Typ char gibt an, dass es sich um eine Zeichenkette handelt und die Zahl innerhalb der eckigen Klammern definiert die Länge.

char timestamp[64];

Schritt 2: Uhrzeit einstellen

Bevor die Uhrzeit des RTC-Moduls ausgelesen werden kann, musst du diese vorher mithilfe eines anderen Sketches setzen. Schaue hier wie das funktioniert. Beachte, dass die Uhrzeit nur einmal eingestellt werden muss. Solange die Batterie korrekt eingelegt ist, läuft die Uhr weiter und kann ausgelesen werden.

Schritt 3: Datei auf der SD-Karte erstellen und Sensoren initialisieren

In der setup() Funktion wird nun die SD-Karte initalisiert. Daraufhin wird die SD-Karte geöffnet und die Datei mit dem Namen "data.csv" wird erstellt. Anschließend wird die Datei wieder geschlossen. Zusätzlich muss nun auch das RTC-Modul initalisiert werden. Zum Schluss werden hier noch die angeschlossenen Sensoren initialisiert.

void setup() {
  SD.begin(28);
  myFile = SD.open("data.csv", FILE_WRITE);
  myFile.close();

  rtc.begin();
  rtc.start();
  rtc.set24HourMode(); 
  rtc.set(SECOND, MINUTE, HOUR, DAY, MONTH, YEAR); // Aktuelle Uhrzeit / Datum HIER setzen!
  rtc.batterySwitchOver(1);

}

Schritt 4: Im Intervall Messwerte auf der SD-Karte speichern

In der loop() Funktion sollen nun alle 60 Sekunden Messwerte auf der SD-Karte gespeichert werden. Dafür wird nicht die delay() Funktion aus der Standard Arduino Library benutzt, sondern wir definieren unser eigenes Messintervall. Die delay() Funktion sorgt dafür, dass der Programmcode komplett unterbrochen wird, durch ein eigenes definiertes Messintervall lässt sich dies besser lösen. Dafür werden 3 zusätzliche Variablen am Anfang unseres Programms, noch vor dem setup() und der loop() Funktion, definiert. Die Variablen speichern die Zeit seit dem Start des Intervalls, die Länge des Intervalls und die aktuelle Laufzeit des Programmes.

const long interval = 60000; // 60.000 Millisekunden = 60 Sekunden
long time_start = 0;
long time_actual = 0;

Die Arduino Funktion millis() gibt die Anzahl an Millisekunden zurück, seitdem die senseBox gestartet ist. Mithilfe dieser Funktion kann eine if-Abfrage erstellt werden, welche gültig wird, wenn 60 Sekunden vergangen sind.

void loop() {
  time_start = millis();
    if (time_start > time_actual + interval) {
      // 60 Sekunden sind vergangen
      time_actual = millis();

    }

}

Nun da das Messinterval definiert ist, müssen noch innerhalb des Intervals die Messwerte auf der SD Karte speichern. Damit die Messwerte später Problemlos auf der openSenseMap hochgeladen werden können, müssen die Messwerte in einem bestimmten Format gespeichert werden. Dieses sieht wie folgt aus.

sensorID, Messwert, *Zeitstempel, *Längengrad, *Breitengrad, *Höhe

Parameter mit einem * davor deuten darauf hin, dass diese optional sind und nicht zwingend zum Upload benötigt werden. Da in diesem Beispiel kein GPS-Sensor installiert ist, können die Werte für Längengrad, Breitengrad und Höhe ignoriert werden. Der Zeitstempel im korrekten Format wird aus der Uhrzeit des RTC-Moduls erstellt. Dazu werden Variablen erstellt, in denen die einzelnen Bestandteile der Uhrzeit gespeichert werden. Im Anschluss wird die Funktion rtc.get() aufgerufen und wir übergeben zusätzlich die eben erstellten Variablen. Die Funktion speichert die nötigen Informationen in die Variablen, die übergeben wurden.

    uint8_t sec, min, hour, day, month;
    uint16_t year;
    // Uhrzeit wird in die verschiedenen Variablen gespeichert
    rtc.get(&sec, &min, &hour, &day, &month, &year);

Nun müssen die Variablen noch in ein ordentliches Format übersetzt werden. Mit der Funktion sprintf können wir Zeichenketten nach einem vorgegebenen Muster erstellen.

    sprintf(timestamp, "%02d-%02d-%02dT%02d:%02d:%02dZ",
            year,
            month,
            day,
            hour,
            min,
            sec);

Mithilfe dieser Funktion wird in der Variable timestamp, der String 20%02d-%02d-%02dT%02d:%02d:%02dZ eingefügt. Jedes %02d in diesem String wird mit dem Wert nach den Kommas ersetzt. In diesem Beispiel wird aus 20%02d-%02d-%02dT%02d:%02d:%02dZ nach der Funktion 2021-01-7T12:56:00Z. Mit diesem Vorwissen kann nun das Programm so verändert werden, dass die Messwerte korrekt auf der SD-Karte gespeichert werden.

void loop() {
  time_start = millis();
  if (time_start > time_actual + interval) {
    time_actual = millis();
    uint8_t sec, min, hour, day, month;
    uint16_t year;
    // Uhrzeit wird in die verschiedenen Variablen gespeichert
    rtc.get(&sec, &min, &hour, &day, &month, &year);
    sprintf(timestamp, "20%02d-%02d-%02dT%02d:%02d:%02dZ",
            year,
            month,
            day,
            hour,
            min,
            sec);
    // Datei vorher öffnen
    myFile = SD.open("data.csv", FILE_WRITE);
    myFile.print(TEMP_ID);
    myFile.print(",");
    myFile.print(hdc.getTemperature());
    myFile.print(",");
    myFIle.println(timestamp)
    // zweiter Messwert
    myFile.print(HUMI_ID);
    myFile.print(",");
    myFile.print(hdc.getHumidity());
    myFile.print(",");
    myFIle.println(timestamp)
    // Datei nachher schliessen
    myFile.close();
  }

}

Beim Speichern der Messwerte muss darauf geachtet werden, dass die Datei auf der SD-Karte anfangs per myFile = SD.open() geöffnet wird und anschließend per myFile.close() wieder geschlossen wird!

Schritt 5: Hochladen der Daten auf die openSenseMap

Nachdem du mit deiner senseBox eine Weile Messwerte gesammelt hast, können die Messwerte auf die openSenseMap hochgeladen werden! Entferne hierfür das SD-Bee von seinem Steckplatz und nehme die microSD-Karte heraus. Anschließend steckst du die microSD-Karte in den microSD-Adapter, welchen du an deinen Computer anschließen kannst. Nicht alle Computer haben einen Anschluss für den Adapter! Solltest du keinen Anschluss haben, gibt es im Internet zahlreiche Möglichkeiten unter anderem ein USB-Kartenlesegeräte.

Hast du den SD Adapter mit deinem Computer verbunden, so werden dir nun die Dateien auf der SD Karte angezeigt. Unter den Dateien befindet sich auch die Datei data.csv. Kopiere diese auf deinen PC.

Gehe auf die openSenseMap und logge dich in dein Benutzerkonto ein. Navigiere über das Dashboard (erreichbar über das Benutzer-Icon oben rechts) zu deiner senseBox und wähle Daten-Upload aus. Klicke dort auf Wähle eine Datei und wähle die soeben kopierte .csv Datei aus. In dem großen Kasten wird eine Vorschau der hochzuladenenen Messwerte angezeigt. Über den Upload Knopf kannst du nun die Messwerte hochladen!

/images/projects/SD/osmupload.png - Logo

Extras

Mit der erstellten csv Datei kannst du zusätzlich auch weitere Berechnungen oder Ähnliches durchführen. So lassen sich z.B. mit Programmen wie Excel leicht Graphen und Visualisierungen zu deiner Messung erstellen, probiere es mal aus!

Gesamter Code

Den vollständigen Sketch findest du hier.