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).
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.
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
Der Link am Ende des ersten Teils
https://glaskugelsehen.wordpress.com/2014/05/10/freien-webspace-konfigurieren/
ist falsch, richtig sollte der hier sein: 12 statt 10
Vielen Dank Clemens,
ich hatte im Nachhinein das Datum des Beitrags geändert, damit die Reihenfolge stimmt, dabei aber den Link nicht berücksichtigt.
Gruß
Reinhard
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
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
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 ———-
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
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!?
muss nicht, ist aber übersichtlicher
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
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
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
Pingback: Sensordaten auf Website darstellen | wer bastelt mit?