Gegevens met het Ethernet-shield op een SD-kaart opslaan

FunduinoLaatst bijgewerkt op

Messwerte auf SD-Karte speichern und im Browser anzeigen

Das Ethernet-Shield bringt nicht nur einen Netzwerkanschluss mit, sondern auch einen Slot für eine SD-Karte. Damit kann dein Arduino Messwerte speichern oder sie als Webseite in deinem Heimnetz anzeigen.

In drei Projekten speicherst du zuerst eine einfache Zahlenreihe, dann die Messwerte eines DHT11 als CSV-Datei für die Tabellenkalkulation. Zum Schluss baust du mit dem TMP36 ein Thermometer, das du im Browser abrufst.

Ein DHT11-Sensor ist am Ethernet-Shield angeschlossen
DHT11-Sensor am Ethernet-Shield

Benötigte Bauteile

Für die ersten beiden Projekte brauchst du:

Für das dritte Projekt, das Thermometer im Browser, brauchst du zusätzlich einen Temperatursensor TMP36, ein LAN-Kabel und ein 9-V-Netzteil oder eine 9-V-Batterie.

Die Bauteilliste im Original nennt für das dritte Projekt weder den TMP36 noch LAN-Kabel und Netzteil. Sie sind hier ergänzt.

Die SD-Karte vorbereiten

Mit dem Ethernet-Shield kannst du einen Webserver einrichten. Du kannst es aber auch unabhängig davon als Datenspeicher nutzen: Im Kartenslot des Shields speicherst du Sensorwerte auf einer SD-Karte.

Wichtig: Die SD-Karte muss im Format FAT32 formatiert sein. Klicke unter Windows mit der rechten Maustaste auf den Wechseldatenträger und wähle „Formatieren“. Im folgenden Fenster wählst du unter „Dateisystem“ den Eintrag „FAT32“ und formatierst die Karte.

Beim Formatieren werden alle Daten auf der Karte gelöscht. Sichere vorher alles, was du noch brauchst.

Projekt 1: Eine Zahlenreihe speichern

Im ersten Sketch erzeugt der Arduino nur zwei Zahlenreihen und speichert sie auf der SD-Karte. Für den Aufbau steckst du lediglich das Ethernet-Shield auf den Mikrocontroller.

Kann der Sketch die SD-Karte lesen, blinkt die LED an Pin 13 zweimal. Danach schreibt er jede Sekunde eine neue Zeile in die Datei zaehlen.csv: Die erste Zahl steigt jeweils um 1, die zweite um 2. Ein Semikolon trennt die beiden Werte. Alle weiteren Erklärungen stehen als Kommentare im Sketch.

Die SD-Karte wird über Pin 4 angesprochen. Nutzt du einen Arduino MEGA, änderst du die 4 an beiden Stellen im Sketch in 53.

Zahlenreihen auf der SD-Karte speichern
#include <SD.h>      //SD Library hinzufügen
int a=0; // Variable für einen Zählvorgang
int b=0; // Variable für einen Zählvorgang
const int chipSelect = 4; //Chip Pin für die SD Karte(bei UNO 4,bei MEGA 53)
void setup() {
pinMode (13, OUTPUT);
  if (startSDCard() == true) // Durch den Rückgriff auf den Programmblock "startSDCard" wird die SD-Karte geprüft. Wenn die SD Karte gelesen werden kann dann soll die onboard-LED an Pin13 zweimal blinken
  {
  digitalWrite(13, HIGH); //an
  delay(500);
  digitalWrite(13, LOW); //aus
  delay(500);
  digitalWrite(13, HIGH); //an
  delay(500);
  digitalWrite(13, LOW); //aus
  delay(500);
  }
}
void loop()
{
  File dataFile = SD.open("zaehlen.csv", FILE_WRITE); //Excel Datei auf der SD Karte anlegen mit dem Namen "zaehlen"
a=a+1; // Unter der Variablen "a" wird jetzt der Wert a+1 gespeichert. Dadurch wird der Wert für "a" in jeden Durchgang um 1 erhöht.
b=b+2; // Unter der Variablen "b" wird jetzt der Wert b+2 gespeichert. Dadurch wird der Wert für "b" in jeden Durchgang um 2 erhöht.
dataFile.print(a); // Wert für "a" wird auf die SD-Karte gespeichert
dataFile.print(";"); // Es wird ein Semikolon in die CSV-Datei gespeichert, daduch lassen sich die Werte später als Tabelle getrennt darstellen.
dataFile.println(b); // Wert für "b" wird auf die SD-Karte gespeichert
dataFile.close(); // Die Datei wird vorrübergehend geschlossen.
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500); // Hier endet der Loop und beginnt dann wieder von vorne. Es werden im Sekundentakt die Werte für "a" und "b" in die Tabelle auf der SD-Karte gespeichert.
}
boolean startSDCard() // Dieser Programmblock wird benötigt, um zu prüfen, ob die SD-Karte einsatzbereit ist.
{
  boolean result = false;
  pinMode(4, OUTPUT); // 4 bei UNO, bei MEGA in 53 ändern
  if (!SD.begin(chipSelect)) //Überprüfen ob die SD Karte gelesen werden kann
  {
    result = false;
  }
  else // Wenn ja Datei wie im Loop anlegen
  {
  File dataFile = SD.open("datalog.csv", FILE_WRITE);
   if (dataFile)
    {
      dataFile.close();
      result = true;
    }
  }
  return result;
}

Das Ergebnis auswerten

Öffnest du die Datei zaehlen.csv mit einem Texteditor, sieht sie so aus:

1;2 · 2;4 · 3;6 · 4;8 · 5;10 · 6;12 …

Öffnest du die Datei dagegen mit einem Tabellenkalkulationsprogramm wie Excel oder LibreOffice Calc, landet jeder Wert nach einem Semikolon in der nächsten Zelle. Daraus kannst du zum Beispiel ein Diagramm erstellen.

Diagramm der gespeicherten Zahlenreihen in einem Tabellenkalkulationsprogramm
Auswertung der Messdaten in einem Tabellenkalkulationsprogramm

Projekt 2: Den DHT11 anschließen

Im zweiten Projekt misst du mit dem DHT11 Temperatur und Luftfeuchtigkeit und speicherst die Messwerte auf der SD-Karte. Anschließend wertest du sie mit einem Tabellenkalkulationsprogramm aus.

Stecke das Ethernet-Shield auf den Mikrocontroller und schließe den DHT11 so an:

  • Pin „−“ an GND des Ethernet-Shields
  • Pin „S“ an D2 des Ethernet-Shields
  • mittlerer Pin an 5V des Ethernet-Shields

Die Pinbezeichnungen „−“, „S“ und Mitte gehören zum DHT11 auf einer Modulplatine. Der verlinkte Sensor ohne Breakoutboard hat vier Beinchen: Von vorne gesehen ist das linke VCC, das zweite Data, das dritte bleibt frei und das rechte ist GND. Die Datenleitung braucht dann zusätzlich einen Pull-up-Widerstand, zum Beispiel 10 kΩ, nach 5V.

Ein DHT11-Sensor ist am Ethernet-Shield angeschlossen
DHT11-Sensor am Ethernet-Shield

Benötigte Bibliotheken

Für diesen Sketch brauchst du die Bibliothek DHT sensor library von Adafruit, die du über den Bibliotheksverwalter installierst. Die Bibliothek SD ist in der Arduino IDE bereits vorinstalliert.

Laut Original ließ sich der Sketch mit der Version 1.3.0 der DHT-Bibliothek nicht kompilieren. Aktuelle Versionen benötigen zusätzlich die Bibliothek Adafruit Unified Sensor; der Bibliotheksverwalter bietet an, sie mitzuinstallieren.

Messwerte speichern

Der Sketch prüft zuerst die SD-Karte und startet dann den DHT11. Im loop-Teil liest er Luftfeuchtigkeit und Temperatur aus, schreibt beide Werte getrennt durch ein Semikolon in die Datei werte.csv und zeigt sie zusätzlich im seriellen Monitor an.

println statt print sorgt dafür, dass nach der Temperatur eine neue Zeile in der Tabelle beginnt.

Die Funktion readSensor wird im Sketch nirgends aufgerufen, der Ersatzwert -273 bei einem Sensorfehler kommt also nie zum Einsatz. Außerdem fehlt in setup() die Zeile pinMode(13, OUTPUT); aus dem ersten Sketch. Ohne sie ist Pin 13 nicht als Ausgang eingestellt, und das Blinken beim Kartentest ist nicht zuverlässig.

Laut Original speichert der Sketch alle fünf Sekunden einen Wert. Mit delay(1000) ist es tatsächlich etwa jede Sekunde.

Messwerte des DHT11 auf der SD-Karte speichern
#include "SD.h"     //SD Library hinzufügen
#include "DHT.h"      //DHT Library hinzufügen
#define DHTPIN 2      //Pin an dem der DHT angeschlossen ist festlegen
#define DHTTYPE DHT11   //DHT Typ festlegen: Hier DHT11
#define TEMPERATURE 1
#define HUMIDITY 0
int feuchte;
int temperatur;
DHT dht(DHTPIN, DHTTYPE); //Sensor initializieren
const int chipSelect = 4; //Chip Pin für die SD Karte(bei UNO 4,bei MEGA 53)
void setup() {
  if (startSDCard() == true) // Durch den Rückgriff auf den Programmblock "startSDCard" wird die SD-Karte geprüft. Wenn die SD Karte gelesen werden kann dann soll die onboard-LED an Pin13 zweimal blinken
  {
  digitalWrite(13, HIGH); //an
  delay(500);
  digitalWrite(13, LOW); //aus
  delay(500);
  digitalWrite(13, HIGH); //an
  delay(500);
  digitalWrite(13, LOW); //aus
  delay(500);
  }
  Serial.begin(9600); //Serielle Verbindung starten
  dht.begin();       //DHT Sensor starten
}
void loop()
{
  File dataFile = SD.open("werte.csv", FILE_WRITE); //Excel Datei mit dem Namen „werte“ auf der SD-Karte anlegen
  feuchte = dht.readHumidity(); //Feuchtigkeit auslesen
  temperatur = dht.readTemperature(); //Temperatur auslesen
  dataFile.print(feuchte); //Feuchtigkeit in die Excel Datei eintragen
  dataFile.print(";"); // Es wird ein Semikolon in die CSV-Datei gespeichert, daduch lassen sich die Werte später als Tabelle getrennt darstellen.
  dataFile.println(temperatur); //Temperatur in die Excel Datei eintragen. Durch den Befehl mit der Endung „ln“ („LN“ in Kleinbuchstaben) wird ein Zeilenumsprung in der Wertetabelle erzeugt.
  dataFile.close(); // Die Datei wird vorrübergehend geschlossen.
  delay(1000);
   Serial.print("Luftfeuchtigkeit: "); //Im seriellen Monitor den Text und
  Serial.print(feuchte); //die Dazugehörigen Werte anzeigen
  Serial.println(" %");
  Serial.print("Temperatur: ");
  Serial.print(temperatur);
  Serial.println(" Grad Celsius");
}
boolean startSDCard() {
  boolean result = false;
  pinMode(4, OUTPUT); // 4 bei UNO, bei MEGA in 53 ändern
  if (!SD.begin(chipSelect)) { //Überprüfen ob die SD Karte gelesen werden kann
    result = false;
  }
  else {  // Wenn ja Datei wie im Loop anlegen
      File dataFile = SD.open("datalog.csv", FILE_WRITE);
    if (dataFile) {
      dataFile.close();
      result = true;
    }
  }
  return result;
}
float readSensor( int thisValue) {
  float result;
  if (thisValue == TEMPERATURE) {
    result = dht.readTemperature(); //Sensorwert auslesen und unter Temperature              speichern
  }
  else if (thisValue == HUMIDITY)  //Sensorwert auslesen und unter Humidity                   speichern
 {
 result = dht.readHumidity();
  }
  if (isnan(result))  // Die Library des DHT Sensors sendet beim Verlust des Signals vom DHT11 den Befehl „isnan“. Die passiert bspw. wenn das Kabel der Datenleitung zum Sensor den Kontakt verliert. In dem Fall soll als „Messwert“ die Zahl -273 angezeigt und gespeichert werden. Da dies der tiefste zu erreichende Punkt ist, dürfte jedem klar sein, dass mit den Werten etwas nicht stimmt, und dass der Aufbau überprüft werden muss.
 {
result = -273.0;
  }
  return result;
}

Messwerte auswerten

Die Datei werte.csv öffnest du wie im ersten Projekt mit einem Tabellenkalkulationsprogramm. Die erste Spalte enthält die Luftfeuchtigkeit, die zweite die Temperatur. So könnte das Ergebnis als Diagramm aussehen.

Diagramm der Temperatur- und Feuchtewerte des DHT11 in einem Tabellenkalkulationsprogramm
Die Messdaten des DHT11 in einem Tabellenkalkulationsprogramm

Projekt 3: Das Ethernet-Shield als Webserver

Im dritten Projekt liest du mit dem Temperatursensor TMP36 die Raumtemperatur aus und zeigst sie auf einer Webseite in deinem Heimnetz an. Der Aufbau orientiert sich an der Anleitung Temperatur messen mit dem TMP36.

Stecke das Ethernet-Shield auf den Mikrocontroller und verbinde es mit einem LAN-Kabel mit deinem Router. Schließe dann den TMP36 wie im Schaltplan an, der Signalausgang kommt an A3. Verwende eine externe Stromversorgung mit einem 9-V-Netzteil oder einer 9-V-Batterie, das verbessert die Genauigkeit des Sensors deutlich.

Das Ethernet-Shield belegt die digitalen Pins 10, 11, 12 und 13, für den SD-Kartenslot zusätzlich Pin 4. Diese Pins kannst du für andere Bauteile nicht verwenden.

Schaltplan: Ethernet-Shield auf dem Arduino, Temperatursensor TMP36 an A3

Die IP-Adresse festlegen

Jedes Gerät in einem lokalen Netzwerk hat eine eigene IP-Adresse. Meist vergibt der DHCP-Server (Dynamic Host Configuration Protocol) im Router diese Adressen automatisch, seltener werden sie fest eingetragen. Außerdem hat jedes Gerät eine eindeutige MAC-Adresse, im Sketch ist das 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED.

Im Sketch entscheidet der Schalter statischeIP, welche Variante du nutzt:

  • true: Du legst die IP-Adresse selbst fest.
  • false: Die IP-Adresse wird per DHCP vergeben.

Möchtest du eine feste IP-Adresse verwenden, brauchst du eine Adresse, die im Netzwerk noch frei ist. Öffne dazu unter Windows die Eingabeaufforderung (Windows-Taste, „cmd“ eingeben) und gib den Befehl arp -a ein. Die erste Zeile zeigt die IP-Adresse deines Computers, darunter stehen alle Geräte mit IP- und MAC-Adressen. Diese Adressen sind vergeben.

Ausgabe des Befehls arp -a mit den im Netzwerk belegten IP-Adressen

Das Thermometer im Browser

Zuerst legst du den Port für die Webseite fest und startest den EthernetServer. Im loop-Teil liest der Sketch den Sensorwert aus und rechnet ihn mit dem map-Befehl in eine Temperatur um, genau wie in der Anleitung zum TMP36.

Ruft ein Browser die Seite auf, schickt der Sketch die Temperatur als HTML-Seite. Nach einer kurzen Pause trennt client.stop() die Verbindung wieder.

Nach dem Hochladen zeigt der serielle Monitor die IP-Adresse des Ethernet-Shields an. Diese Adresse gibst du in die Adresszeile eines Browsers deiner Wahl ein.

Der serielle Monitor zeigt die IP-Adresse des Ethernet-Shields an
Die Webseite Funduino Thermometer mit der gemessenen Temperatur im Browser
1 / 2
Das Ethernet-Shield als Webserver-Thermometer
// Laden der notwendigen Bibliothek
#include "Ethernet.h"
int TMP36 = A3;  // Deklaration der Variablen
int sensorwert;
int temperatur = 0;
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};  // MAC Adresse des Arduino Boards  !WICHTIG! MAC Adresse darf nur einmal im Heimnetz vorkommen
// statischeIP = false -> IP-Adresse über DHCP vergeben
// statischeIP = true -> statische IP-Adresse bestimmen
bool statischeIP = false;
// statische IP
IPAddress ip(192, 168, 1, 200);
EthernetServer server(80);  // Port Einstellung (Standard für HTML : 80)
void setup()
{
  Serial.begin(9600);
  // Ethernet starten statische IP
  if (statischeIP) Ethernet.begin(mac, ip);
  // Ethernet starten DHCP
  else Ethernet.begin(mac);
  server.begin();  // Auf Clients warten
  // zur Kontrolle IP-Adresse im Seriellen Monitor anzeigen
  // localIP -> Adresse, die im Browser eingegeben werden muss
  Serial.print(F("IP des Ethernet-Shields: "));
  Serial.println(Ethernet.localIP());
}
void loop()
{
  sensorwert = analogRead(TMP36);                  //Auslesen des Sensorwertes an PIN A3
temperatur = map(sensorwert, 0, 410, -50, 150);  // Umwandeln des Sensorwertes mit Hilfe des "map" Befehls
  delay(500);
  EthernetClient client = server.available();  //Prüfen, ob Client Seite aufruft
  if (client) {                                // Seitenaufruf durch User
    // Ausgabe in HTML
    server.print("HTTP/1.0 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
    server.print("<HTML><HEAD><TITLE>");
    server.print("Funduino Thermometer");
    server.print("</TITLE>");
    server.print("</HEAD><BODY>");
    server.print("<h2 align=center><font size=7><b>Funduino Thermometer </b></font></h2>");
    server.print("<center><font size=5><b>Die Temperatur betr&aumlgt </font>");
    server.print(temperatur);  // Ausgabe der Temperatur
    server.print("<font size=5> Grad Celsius. </font");
    delay(500);     // Kurzer Delay, um Daten zu senden
    client.stop();  // Verbindung mit dem Client trennen
  }
}
Handleiding beoordelen

Opmerkingen

Stel een vraag of deel je ervaring

Neem contact met ons op als iets niet werkt. Vermeld daarbij je board en de foutmelding.

We controleren elke reactie voordat deze wordt gepubliceerd. Je e-mailadres blijft bij ons.