Tutorial: Speicherung von Arduino Messdaten auf Webserver und deren Darstellung – Teil 1

Einführung

Es ist immer wieder das selbe Problem:

Da entwickelt man ein Program für den Arduino zur Messung von irgendwelchen Daten. Solange der Computer angeschlossen ist, kann man die Daten über die serielle Schnittstelle als Text darstellen. Um diese Daten dann grafisch darzustellen, kann man die Daten z.B. nach Excel kopieren. Das ist aber umständlich und letzendlich nur eine Momentaufnahme der Messung.
Doch was, wenn der Arduino ohne Computer weiter messen soll?
Eine mögliche Lösung wäre die Speicherung der Daten auf einer SD-Karte. Es gibt günstige Shields mit SD Kartenslot und auch das Ethernet Shield hat einen SD Slot. Aber auch hier muss man die Messung unterbrechen und die Daten der SD Karte im Computer weiterverarbeiten.

Das alles ist umständlich und außerdem will ich an meine Daten ohne in der Nähe meines Arduinos zu sein. Die Lösung ist die Speicherung der Daten auf einem Webserver und der Abruf der Daten von irgendeinem Rechner oder Tablett über das Internet.

In diesem Tutorial werde ich in mehreren Schritten zeigen, wie Daten nur von einem Arduino mit Ethernetshield auf einen Webserver abgelegt werden und sich von dort grafisch aufarbeiten lassen. Hier ein kleiner Vorgeschmack was euch in diesem Tutorial erwartet. (edit: leider hat sich der Betreiber funpic.de aufgelöst, der Link funktioniert deshalb nicht mehr. Ich werde das Beispiel in Kürze auf eine andere Webseite nehmen).

funpic1

Diese Daten liegen auf einem kostenlosen Webspace von Funpic.de . Der Anbieter finanziert sich mit Werbung, die aufpoppenden Fenster muss man leider dafür billigend in Kauf nehmen. In die Messwerte kann man durch Markieren eines Bereiches mit der Maus reinzoomen. Nach dem Durcharbeiten dieses Tutorial bist du in der Lage, deine Daten ebenso darzustellen.

Im ersten Teil dieses Tutorial gehe ich darauf ein, wie Daten vom Arduino mit Ethernetshield an einen Webspace gesendet werden. Im zweiten Teil werden wir dann einen freien Webspace einrichten und eine einfache Webseite anlegen. Im dritten Teil geht es dann um das Ablegen der Messdaten in einer CSV Datei. Der vierte Teil beschreibt die Konfiguration einer MySQL Datei und das Speichern der Daten darin. Im letzten Teil werden wir uns dann mit der grafischen Darstellung der Daten beschäftigen.

Teil 1 – Verbindung mit Webspace

Ich benutze für meine Experimente ein Ethernetshield mit Wiznet Chipsatz, die man inzwischen sehr günstig bekommen kann. Eine genaue Beschreibung findet man hier. Mit diesem Shield kann man die Beispiele aus der Arduino IDE verwenden, z.B. in der Arduino IDE über das Menü. Datei->Beispiele->Ethernet->WebClient. Ich habe dieses Beispiel geringfügig verändert und lade damit die aktuelle Zeit von einer von mir entsprechend vorbereiteten Webseite. Das Beispiel kann so übernommen werden, lediglich die IP des Ethernet Shield muss angepasst werden. Der Arduino verbindet sich mit der Webseite und liest deren Inhalt (in diesem Fall die aktuelle Zeit) und gibt ihn seriell aus. Sicher nichts spektakuläres, aber man könnte damit unter Verwendung des Time Libraries die Uhrzeit stellen und Gangungenauigkeiten ausgleichen. Natürlich geht das auch über NTP, soll aber hier als Beispiel für den Aufruf einer Webseite dienen.

/*
  WebClock by Reinhard Nickels
 
 This sketch connects to a website
 using an Arduino Wiznet Ethernet shield.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 based on WebClient (arduino Examples)
 by David A. Mellis, by Tom Igoe, based on work by Adrian McEwen
  */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "rncologne.rn.funpic.de";    // <-  wenn du das auf deinem eigenen Server machen willst, muss das hier geändert werden

// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192,168,2,99);       // <- an dieser Stelle die IP des Ethernet Shield eintragen, ich habe eine feste Adresse vergeben.

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(115200);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  Ethernet.begin(mac, ip);
  // give the Ethernet shield a second to initialize:
  delay(1000);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());

  Serial.println("connecting...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /clock.php HTTP/1.1");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
  }
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop()
{
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while(true);
  }
}

Die Ausgabe seriell sieht dann z.B. so aus:

My IP address: 192.168.2.99
connecting...
connected
HTTP/1.1 200 OK
Server: Apache
Set-Cookie: notabotxxx=775e1282fb3146e7de81e2f8f769d433; expires=Sun, 11-May-2014 18:31:16 GMT; path=/; domain=..
Vary: Accept-Encoding
Content-Type: text/html
X-Funpic-Backend-ID: webfree_071
Content-Length: 15
Accept-Ranges: bytes
Date: Sun, 11 May 2014 17:31:19 GMT
Via: 1.1 varnish
Connection: close
X-Funpic-ID: 1392478474
X-Funpic-Age: 0
X-Funpic-Host: rncologne.rn.funpic.de
X-Funpic-Backend: fp_storage_07
X-Funpic-Cache: MISS

Es ist 19:31:16
disconnecting.

Im zweiten Teil dieses Tutorials geht es dann um die Konfiguration eines kostenlosen Webspaces.

Veröffentlicht am 11. Mai 2014, in Arduino, MySQL, Tutorial. Setze ein Lesezeichen auf den Permalink. 26 Kommentare.

  1. Hallo ich bins mal wieder!
    Ich hätte noch eine Ergänzung zur Konfiguration des Ethernet Shields:

    // start the Ethernet connection:
    Ethernet.begin(mac, ip);
    // give the Ethernet shield a second to initialize:
    delay(1000);
    // print the Ethernet board/shield’s IP address:
    Serial.print(„My IP address: „);
    Serial.println(Ethernet.localIP());

    bei meinen 3 originalen Ethernet Shields funktioniert das so aber ich habe noch ein China Teil getestet und musste das delay auf 3000 erhöhen, anscheinend braucht der Chip etwas länger zum hochfahren.

    Gruß Scherheinz

  2. Hi, kann man sich deine Live Messungen im www ansehen? Die Links oben auf den Webhost scheinen nicht mehr zu funktionieren.

    • Hallo,
      wie ich bereits im Beitrag geschrieben habe, hat der Betreiber funpic.de seinen Betrieb eingestellt. Leider habe ich noch keine Alternative aufgesetzt, die ich anbieten kann.
      Probier es selber aus. Als alternativen kostenfreien Betreiber für Webseite und MySQL kann ich dir bplaced.net empfehlen.
      Gruß
      Reinhard

  3. Hi

    erst mal besten Dank für diese doch sehr gute und wertvolle Einführung

    ich habe eine Wetterstation aufgebaut (Arduino), diese sendet alle 10 Minuten meine Daten an die WetterCloud app.weathercloud.net „Phaselis“
    7 Sensoren 15 Werte

    nun arbeite nun schon eine geraume Zeit, diese Daten lokal bei mir zu speichern
    – Netzwerk LAN
    – Server Raspberry Pi 4 mit Apache2, PHP7.3, mysql/Maria Db 10.3

    mittels einem PHP-Script hole ich die Daten und will dies in die mysql Datenbank speichern
    der Script läuft ohne Fehlermeldung!, im „Apache2 Log „access.log“ sehe ich die Daten so, wie diese gesendet werden, am Ende: „HTTP/1.1“ 200 192 „-“ „-“
    – 200 würde heissen Empfang ok
    – 192 ? (weiss ich nicht)

    Die Daten werden aber nicht in die Datenbank eingefügt

    ich habe einen php-Script erstellt, um Daten aus der Datenbank heraus zu lesen, mit dem gleichen Aufbau, wie der Script für die Daten zu empfangen.
    dies funktioniert auch

    via phpMyAdmin kann ich Daten ebenfalls in die Datenbank schreiben

    ich weiss nicht mehr wie weiter, da ich keinerlei weitere Info’s finden kann, warum!

    besten Dank für jegliche Hinweise

    Gruss
    Max

    • Hallo Max,
      prüfe mal, ob der User (vermutlich apache), unter dem das php Script läuft, überhaupt Rechte hat, die mysql-Datenbank zu beschreiben.
      Gruß
      Reinhard

      • Hallo Reinhard

        besten Dank für Deine Meldung
        die Rechte habe ich über phpMyAdmin vergeben
        Apache kenne ich noch nicht genau, darum wüsste ich nicht, wo weitere Rechte zu definieren wäre

        Wo ich ebenfalls unsicher bin, ist die Übergabe der Variablen
        – $temp= $GET[ˋtempˋ]
        – INSERT INTO TEM_db (date, , time, temp) VALUES(CURRENT_DATE, CURRENT_TIME, $temp);

        wie bereits erwähnt, über phpMyAdmin gehts

        Gruss
        Max

  4. Frage, müsste ich nicht eine Verweigerung im Error.log sehen? ( var/log/apache2/ )

    • So genau kenn mich mit Apache nicht aus.
      Kannst du mal den Inhalt der php Webseite hier einstellen?

      • PHP logo
        PHP Version 7.3.11-1~deb10u1

        System Linux raspi02 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l
        Build Date Oct 26 2019 14:14:18
        Server API Apache 2.0 Handler
        Virtual Directory Support disabled
        Configuration File (php.ini) Path /etc/php/7.3/apache2
        —– Rest wurde gelöscht, da nicht zielführend ———-

  5. so meinte ich das nicht – ich meinte die Webseite, die die Daten schreiben soll, in etwa so wie in meinem Beispiel:

    <?php
    $mysql_host = "“;
    $mysql_db = „“;
    $mysql_user = „“;
    $mysql_pw = „“;
    isset($_GET[‚A0‘]) ? $a0=$_GET[‚A0‘] : $a0=“;
    isset($_GET[‚A1‘]) ? $a1=$_GET[‚A1‘] : $a1=“;

    $connection = mysql_connect($mysql_host, $mysql_user, $mysql_pw) or die(„Verbindung zur Datenbank fehlgeschlagen.“);
    mysql_select_db($mysql_db, $connection) or die(„Datenbank konnte nicht ausgewaehlt werden.“);
    $insert_data = „INSERT INTO analog_data (analog0, analog1) VALUES ($a0, $a1)“;
    mysql_query($insert_data, $connection) or die(„Fehler beim Eintragen der Daten in die Datenbank!“);
    ?>

    • hier noch die letzten Datensätze, die der Arduino sendet:

      192.168.1.130 – – [13/Dec/2019:15:34:05 +0300] „GET /data-get.php?tempin/24.23/temp/15.38/chill/15/dew/16/heat/16/hum/99.90/wspd/6.00/wspdhi/6/wspdavg/4/wdir/0.0/bar/1007.7/rain/0/rainrate/0/solarad/0.00/uvi/0.65 HTTP/1.1“ 200 192 „-“ „-“
      192.168.1.130 – – [13/Dec/2019:15:35:19 +0300] „GET /data-get.php?tempin/24.21/temp/15.31/chill/15/dew/16/heat/16/hum/99.90/wspd/6.00/wspdhi/13/wspdavg/5/wdir/0.0/bar/1007.7/rain/0/rainrate/0/solarad/0.00/uvi/0.66 HTTP/1.1“ 200 192 „-“ „-“
      192.168.1.130 – – [13/Dec/2019:15:36:31 +0300] „GET /data-get.php?tempin/24.19/temp/15.31/chill/15/dew/16/heat/16/hum/99.90/wspd/6.00/wspdhi/13/wspdavg/4/wdir/0.0/bar/1007.6/rain/0/rainrate/0/solarad/0.00/uvi/0.71 HTTP/1.1“ 200 192 „-“ „-“
      192.168.1.130 – – [13/Dec/2019:15:37:43 +0300] „GET /data-get.php?tempin/24.18/temp/15.31/chill/15/dew/16/heat/16/hum/99.90/wspd/6.00/wspdhi/13/wspdavg/4/wdir/0.0/bar/1007.6/rain/0/rainrate/0/solarad/0.00/uvi/0.72 HTTP/1.1“ 200 192 „-“ „-„

    • bin mir nicht sicher, ob meine Post angekommen ist, darum nochmals den entsprechenden Script:

      • Das ist sicher der Log vom Apache?
        Stell mal die paar Zeilen Arduino Code ein, wo du die PHP Seite „data-get.php“ aufrufst.
        Und ohne den Code auf der „data-get.php“ Webseite werde ich dir nicht weiterhelfen können.
        Es könnte sein, dass WordPress hier die Übermittlung von Code unterdrückt.
        Dann stell den Code auf https://pastebin.com/ und sende mir den Link.

      • hallo Reinhard
        sorry aber ich habe 2 mal versucht, den pdp-code zu übermittlen, bekomme jedoch keine klar Rückmeldung

        es ist richtig, letzeres war aus dem Log von Apache

      • anbei der Teil im Arduino-script:

        // sending data intranet

        if (txcount > 60) {

        if (client.connect(server2, httpsPort2)) {
        delay(1000);
        Serial.print(„1 connected to „);
        Serial.println(client.remoteIP());
        client.print(„GET /data-get.php?“);
        client.print(„tempin/“); client.print(T,2);
        client.print(„/temp/“); client.print(tempC);
        client.print(„/chill/“); client.print(wchill);
        client.print(„/dew/“); client.print(dew);
        client.print(„/heat/“); client.print(heat);
        client.print(„/hum/“); client.print(h);
        client.print(„/wspd/“); client.print(wspd);
        client.print(„/wspdhi/“); client.print(wsphi);
        client.print(„/wspdavg/“); client.print(aa);
        client.print(„/wdir/“); client.print(wdir, 1);
        // client.print(„/wdiravg/“);
        client.print(„/bar/“); client.print(P,1);
        client.print(„/rain/“);
        if(rpd < 10){
        client.print("0"); //client.print(rpd);
        }
        else{
        client.print(rpd);
        }
        client.print("/rainrate/");
        if(rph < 10){
        client.print("0"); //client.print(rph);
        }
        else{
        client.print(rph);
        }
        client.print("/solarad/"); client.print(rad);
        client.print("/uvi/"); client.print(UVindex);

        client.println(" HTTP/1.1");
        client.println("Host: raspi02");
        client.println("Connection: close");
        client.println();
        client.stop();

        Serial.println("Intranet successfuly sent");
        }
        else {
        Serial.println("connection LAN failed -1");
        }
        txcount = 0;
        }
        else {
        txcount = txcount + 8;
        }

      • ich hoffe, es hat auf diesem Weg geklappt
        nochmals besten Dank für Deine hilfe und Unterstützung!!!
        Gruss
        Max

  6. Wenn ich daraus zusammensetze, wie der Aufruf der Webseite aussieht, dann kommt da genau das raus, was der Apache Log zeigt (ich war mir beim Log nicht sicher). Der Aufruf müsste aber in etwa so aussehen, damit die Parameter übergeben werden:
    data-get.php?tempin=24.18&temp=15.31&chill=15&dew=16&heat=16&hum=99.90&wspd=6.00&wspdhi=13&wspdavg=4&wdir=0.0&bar=1007.6&rain=0&rainrate=0&solarad=0.00&uvi=0.72
    Ruf die Seite mal so aus dem Browser auf.

    • es ist tatsächlich so, wenn ich die Daten auf diese Weise mittels „data-get.php“ über den Browser eingebe, funktioniert es!
      dh zuerst den ganzen Daten-String zusammenstellen und dann senden!?

    • Hi Reinhard

      habe im Arduino-Script folgende Änderung gemacht:
      – client.print(„&temp=“)
      anstelle Client.print(/temp/)

      die Schreibweise („/temp/“) hatte ich jener für die Übermittlung in die Cloud entsprechend übernommen

      im access.log sieht es wiederum genau so aus

      tempin=nn&temp=n&… und es läuft!!!!

      2 Wochen analysieren … doch nun etwas gescheiter geworden

      meinen besten Dank
      Gruss
      Max

  7. Hallo Max,
    das freut mich sehr. Vielen Dank für die Rückmeldung.
    Gruß
    Reinhard

    • hi Reinhard

      ich hätte da nochmals ein kleineres Problem,
      aus mysql Daten heraus lesen in einem php-script und auf einer Browser-Seite darstellen funktioniert und ist soweit klar
      aber ich möchte Daten aus einer mysql-Table herauslesen und mit diesen weiter arbeiten
      dh. im selben script wo die Wetterdaten von der Wetterstation via http empfangen und in mysql gespeichert werden die selben mit Daten aus der weiteren mysql-Table vergleichen und bei „Änderung“ zurück schreiben
      zB Temperatur Ist mit früher erfasstem Wert vergleichen und als Max- bzw Min-Wert in diese weitere HiLow-Table speichern

      $abfrage = „SELECT date, time, sun_hrs, wind_hi, wind_dir, temp_hi, temp_low, bar_hi, bar_low, nullset FROM HiLow_db ORDER BY id DESC LIMIT 0,1“;
      $ergebnis = mysqli_query($connection, $abfrage);
      … ???
      … ???

      if ($nullset = 1) {
      $temp_hi = $temp;
      $temp_low. = $temp;
      $wind_hi = $speed;
      $wind_low. = $speed;
      $bar_hi = $bar;
      $bar_low = $bar;
      $nullset = 0;
      }
      else {

      if ($temp > $temp_hi) {
      $temp_hi = $temp;
      }
      elseif ($temp < $temp_low) {
      $temp_low = $temp;
      }



      }

      $nullset = 1 bedeutet die Min/Max Werte wieder zurück stellen auf die momentanen Ist-Werte

      die mittels Abfrage erhaltenen Werte müssen den entsprechenden $variables zu gewiesen werden, aber wie?

      ich gehe davon aus, dass die von der Wetterstation empfangenen Ist-Werte (Variablen) nach dem speichern immer noch verfügbar sind

      Gruss
      Max

  8. Hallo Max,
    leider habe ich viel zu wenig „Hobby-Zeit“ und kann mich deshalb nicht mit Fragen beschäftigen, die nichts mehr direkt mit dem Inhalt dieses Blogposts zu tun haben. Wende dich mit solchen Fragen besser an ein Forum, z.B. das deutschsprachige Arduino Forum. Dort bekommst du sicher schneller die Hilfe, die du benötigst.
    Vielen Dank, dass du meinen Blog abonniert hast.
    Reinhard

  1. Pingback: Sensordaten auf Website darstellen | wer bastelt mit?

Hinterlasse eine Antwort zu glaskugelsehen Antwort abbrechen