Jetzt ist es schon wieder einige Zeit her dass ich ein Arduino Tutorial veröffentlicht habe, also wird es mal wieder Zeit dafür.
Vor Kurzem habe ich mir bei eBay ein paar interessante Sensoren gekauft. Darunter befand sich z.B. auch ein CC3000 Wifi-Modul, das ich direkt einmal ausprobiert habe. In diesem Beispiel werde ich ein Szenario verwenden, das ich bereits bei einigen meiner vorherigen Arduino Tutorials genutzt habe.
Ich werde die Daten eines DHT22 Temperatur- und Luftfeuchtesensors per CC3000 Wifi-Modul an eine eigens dafür geschriebene PHP Seite senden. Diese PHP Seite wiederum speichert die Sensorwerte, das aktuelle Datum und die aktuelle Zeit in einer MySQL Datenbank. Letztendlich wird auf einer weiteren Seite immer der aktuellste Wert aus der Datenbank angezeigt, wobei sich die Anzeige Dank jquery alle paar Sekunden selber aktualisiert.
Das CC3000 Wifi-Modul selbst wird von Texas Instruments hergestellt. Nun gibt es viele Anbieter von Breakout Boards die auf den CC3000 Chip setzen. Ich selber nutze ein Board von Sparkfun. Ein weiterer bekannter Anbieter ist Adafruit. Leider musste ich die Erfahrung machen dass nicht jede CC3000 Library die man so findet mit jedem CC3000 Breakout Board zusammenarbeitet. Ich schaffe es z.B. nicht, mit der Library von Sparkfun eine Internetverbindung aufzubauen. Das Board kann ich mit dieser Libary erfolgreich testen aber das war es auch schon. Die Library von Adafruit hingegen funktioniert hier tadellos. Hier müssen Sie einfach selber testen welche Library mit Ihrem Board zusammenarbeitet.
- benötigte Bauteile
- Verbinden der Bauteile
- Arduino Sketch
- die MySQL Datenbank
- ein PHP-Script empfängt unsere Sensordaten und speichert diese in einer Datenbank
- Website zum anzeigen der aktuellsten Sensordaten
Benötigte Bauteile
- 1 x CC3000 Wifi-Modul
- 1 x Arduino Uno
- 1 x DHT22 Sensor
- 1 x Widerstand für den DHT22
Verbinden der Bauteile
Anhand der folgenden zwei Zeichnungen können Sie ganz gut die Unterschiede der verschiedenen CC3000 Breakout Boards erkennen.
Hier nun ein Beispiel anhand eines CC3000 Breakout Board von Sparkfun.
Da ich kein Fritzing Part für ein CC3000 Breakout Board finden konnte habe ich hier lediglich eine 9 polige Stiftleiste benutzt.
Arduino Sketch
Die für dieses Sketch notwenigen Libraries können Sie am Ende des Tutorials herunterladen.
#include <Adafruit_CC3000.h> #include <SPI.h> #include "DHT.h" // Define CC3000 chip pins #define ADAFRUIT_CC3000_IRQ 3 // Interrupt Pin (UNO = 2 und 3) #define ADAFRUIT_CC3000_VBAT 8 // VBEN #define ADAFRUIT_CC3000_CS 10 // CS // Define WiFi Settings #define WLAN_SSID "IHREWLANSSID" // WLAN SSID - Darf nicht länger als 32 Zeichen sein! #define WLAN_PASS "IHRWLANPASSWORT"// WLAN Passwort #define WLAN_SECURITY WLAN_SEC_WPA2 // WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2 // Define DHT22 sensor pins #define DHTPIN 4 // Digitaler Pin an dem der DHT angeschlossen ist #define DHTTYPE DHT22 // Typ des DHT Sensors (DHT11, DHT22) // Erzeugen von Instanzen für CC3000 & DHT DHT dht(DHTPIN, DHTTYPE); Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2); // Define website settings #define WEBSITE "fluuux.de" // Domainname #define WEBPAGE "/Wetterstation/insertValues.php" // URL + Name der Datei die aufgerufen werden soll #define privateKey "VppzZoKZ2DfEGzJjmwm6" // Dieser Key steht als sha1 hash in der insertValues.php uint32_t ip; // IP Adresse des Servers wird im setup() mit getHostByName aus der URL ermittelt long previousMillis = 0; long interval = 1; // Upload-Interval in Minuten int h; // Luftfeuchte int t; // Temperatur void setup(void) { interval = interval * 1000 * 60; // Das in Minuten angegebene Interval in Millisekunden umrechnen delay(2000); Serial.begin(115200); Serial.println(F("WiFi Wetter-Station (CC3000)\n")); Serial.println(F("Initialisiere CC3000...")); if (!cc3000.begin()) { Serial.println(F("CC3000 - Verkabelung checken!")); while(1); } if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) { Serial.println(F("Fehlgeschlagen!")); while(1); } Serial.println(F("Verbunden!")); // Wait for DHCP to complete while (!cc3000.checkDHCP()) { delay(1000); } // IP Adresse, DNS, Gateway, usw ermitteln und ausgeben while (! displayConnectionDetails()) { delay(1000); } ip = 0; // Versuchen die IP-Adresse der Website zu ermitteln Serial.print(WEBSITE); Serial.print(F(" -> ")); while (ip == 0) { if (!cc3000.getHostByName(WEBSITE, &ip)) { Serial.println(F("Konnte nicht aufgeloest werden!")); } delay(500); } cc3000.printIPdotsRev(ip); Serial.println(); } void loop(void) { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; // Temperatur und Luftfeuchte ermitteln h = dht.readHumidity(); t = dht.readTemperature(); // Messwerte ausgeben Serial.print(F("Temperatur: ")); Serial.println(t); Serial.print(F("Luftfeuchte: ")); Serial.println(h); Serial.println(""); //Werte des DHT22 an Website senden send_request(t, h); } delay(1000); } /************************************************************************** Messwerte an Server senden und Antwort des Servers ausgeben /**************************************************************************/ void send_request (int t, int h) { // Verbindung zum Server herstellen Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80); // Anfrage senden if (client.connected()) { client.fastrprint(F("GET ")); client.fastrprint(WEBPAGE); client.fastrprint(F("?private_key=")); client.fastrprint(privateKey); client.fastrprint("&temp="); client.print(t); client.fastrprint("&hum="); client.print(h); client.fastrprint(F(" HTTP/1.1\r\n")); client.fastrprint(F("Host: ")); client.fastrprint(WEBSITE); client.fastrprint(F("\r\n")); client.println(); } else { Serial.println(F("Verbindung fehlgeschlagen")); } // Antwort vom Server ausgeben while (client.connected()) { while (client.available()) { char c = client.read(); Serial.print(c); } // Verbindung zum Server schließen Serial.println(F("Verbindung geschlossen")); Serial.println(); } client.close(); } /************************************************************************** IP-Adresse und andere Verbindungsdetails auslesen /**************************************************************************/ bool displayConnectionDetails(void) { uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv; if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv)) { Serial.println(F("Unable to retrieve the IP Address!\r\n")); return false; } else { Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress); Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask); Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway); Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv); Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv); Serial.println(); return true; } }
die Datenbank
Das Arduino Sketch sendet in regelmäßigen Abständen die Sensordaten des DHT22 an ein PHP-Script. Dieses wiederum prüft die Daten, öffnet eine Verbindung zur MySQL Datenbank und speichert die Werte in der Datenbank. Damit das alles funktioniert, müssen wir zunächst eine neue Tabelle in der vorhandenen MySQL-Datenbank anlegen. In folgendem Fenster sehen Sie den MySQL Befehl mit dem Sie die Tabelle erzeugen können. Am einfachsten geht das über phpMyAdmin.
CREATE TABLE IF NOT EXISTS `arduino_Wetterstation` ( `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, `Luftfeuchte` int(3) DEFAULT NULL, `Temperatur` int(3) DEFAULT NULL, `DatumZeit` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
PHP-Seite zum empfangen und speichern der Sensordaten in einer MySQL DB
Damit dieses PHP-Script funktioniert benötigen wir neben der Datenbanktabelle, die wir zuvor hoffentlich angelegt haben, auch ein Script mit dem wir eine Verbindung zur Datenbank herstellen können. Dieses Script habe ich in einem Ordner Namens “includes” ausgelagert und “mysqli.inc.php” genannt. Ersetzen Sie zunächst die Angaben in den Zeilen 6 bis 9 durch die Zugangsdaten Ihrer Datenbank.
mysqli.inc.php
<?php if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) exit('No direct access allowed.'); //Datenbank Zugangsdaten $DB_SERVER = "localhost"; $DB_NAME = "DATENBANKNAME"; $DB_USER = "DATENBANKUSER"; $DB_PASSWORD = "DATENBANKPASSWORT"; $db = new mysqli($DB_SERVER, $DB_USER, $DB_PASSWORD, $DB_NAME); if (mysqli_connect_errno()) { printf("Verbindung fehlgeschlagen: %s\n", mysqli_connect_error()); exit(); } mysqli_set_charset($db,"utf8"); ?>
insertValues.php
Diese Datei wird vom Arduino direkt aufgerufen und sorgt dafür dass die Sensorwerte des DHT22 in der Datenbank gespeichert werden.
In der fünften Zeile des Scripts finden Sie die Variable $privateKey. Sie erinnern sich sicher, dass im Arduino Sketch eine gleichnamige Variable definiert wurde der Sie einen beliebigen Key zugewiesen haben. Sie werden sicher feststellen dass der Key in diesem Script nicht aussieht wie der Key aus dem Arduino Sketch. Das hat einen einfachen Grund. Der Key in diesem Script ist der SHA1 hash Wert des Keys aus dem Arduino Sketch. Um den hash Wert Ihres Keys zu ermitteln, können Sie eine einfache PHP Datei anlegen und dort folgenden Code eingeben.
<?php echo sha1('IHR KEY AUS DEM ARDUINO SKETCH'); ?>
Rufen Sie diese Datei über Ihren Webbrowser auf, kopieren Sie die angezeigte Zeichenkette und fügen Sie diese in Zeile 5 des folgenden Scripts hinter der Variablen “$privateKey” ein.
Der Rest des Scripts sollte selbsterklärend sein, trotzdem hier noch ein paar kurze Bemerkungen.
- Es wird geprüft ob der privateKey vom Arduino übergeben wurde.
- Dann wird geprüft ob der SHA1 hash Wert des private Key vom Arduino mit dem private Key des PHP Scripts aus Zeile 5 übereinstimmt.
- Wenn es bis hier hin passt, werden das aktuelle Datum und die aktuelle Zeit in der Variablen $DATUM gespeichert.
- Anschließend werden Temperatur, Luftfeuchte und Datum in der Datenbank gespeichert.
- Sollte irgendein Fehler auftreten, wird dieser an den Arduino zurück gesendet. Dieser kann im seriellen Monitor ausgegeben werden.
<?php header('Content-type: text/plain'); include("includes/mysqli.inc.php"); $privateKey = "0e19f527a5fe0ac950aef9ac3bd280843c579f6f"; //sha1 $humi = mysqli_escape_string($db, $_GET['hum']); $temp = mysqli_escape_string($db, $_GET['temp']); $private_key = mysqli_escape_string($db, $_GET['private_key']); if(isset($private_key)) { if(sha1($private_key) == $privateKey) { $DATUM = date("Y-m-d H:i:s"); $sql="INSERT INTO `arduino_Wetterstation` SET `Luftfeuchte` = '".$humi."', `Temperatur` = '".$temp."', DatumZeit = '".$DATUM."'"; if (!mysqli_query($db,$sql)) { die('Error: ' . mysqli_error($db)); } else { echo "Data stored in database"; } } else echo("Private Key is incorrect"); } else echo("Private Key is missing"); ?>
Ausgabe der aktuellsten Werte
index.html
Wenn man im Webbrowser nun die Datei “index.html” aufruft soll immer der aktuellste Wert aus der Datenbank angezeigt werden. Damit das funktioniert, nehmen wir hier jQuery zu Hilfe. In der Datei “index.html” wird in einem voreingestellten Intervall die Datei “showSensorValue.php” aufgerufen. Diese Datei ließt den zuletzt in der Datenbanktabelle gespeicherten Wert aus, weist die ausgelesenen Werte Variablen zu und gibt diese anschließend an die Datei “index.html” zurück. Ach ja, bevor Temperatur und Luftfeuchte ausgegeben werden, wird geprüft in welchem Bereich sich der Wert befindet und färbt die Ausgabe dementsprechend ein.
Hier zunächst der Code für die index.html
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js?ver=1.4.2"></script> <title>Wetter Station</title> <style type="text/css"> .data { font-size: 36px; margin: 30px; clear: both; line-height: 40px; } .dataTitle { float: left; width:180px; height: 50px; margin-right: 20px; line-height: 36px;} #dateDisplay { color: silver; font-size: 19px;} body { font-family: Helvetica; } #tempDisplay, #humiDisplay { float:left; color:#efefef; } </style> </head> <body> <div class="data"> <div class="dataTitle">Temperatur:</div> <div id="tempDisplay">Warte auf Daten vom Arduino ...</div> </div> <div class="data"> <div class="dataTitle">Luftfeuchte:</div> <div id="humiDisplay">Warte auf Daten vom Arduino ...</div> </div> <div class="data"> <div id="dateDisplay"></div> </div> <script type="text/javascript"> setInterval(function() { $("#dateDisplay").load('showSensorValue.php?a=d'); $("#tempDisplay").load('showSensorValue.php?a=t'); $("#humiDisplay").load('showSensorValue.php?a=h'); }, 10000); </script> </body> </html>
showSensorValue.php
Die Datei “showSensorValue.php” wird wie bereits erwähnt, in einem vorgegebenen Intervall von der Datei “index.html” aufgerufen. Sie ließt den aktuellsten Wert aus der Datenbank aus und gibt diesen anschließend an die Datei “index.html” zurück damit dieser angezeigt werden kann.
<?php include("includes/mysqli.inc.php"); if(isset($_GET['a'])) $ausgabe = $_GET['a']; else exit; function MySQLDateTimeToDateTime($datumzeit) { $OLDDATA = explode(" ",$datumzeit); $OLDDATE = explode("-",$OLDDATA[0]); $OLDTIME = explode(":",$OLDDATA[1]); $datum = $OLDDATE[2].".".$OLDDATE[1].".".$OLDDATE[0]; $zeit = $OLDTIME[0].":".$OLDTIME[1]; $ausgabe = $datum.', '.$zeit; return($ausgabe); } $q_values = $db->query("SELECT Luftfeuchte, Temperatur, DatumZeit FROM `arduino_Wetterstation` ORDER BY DatumZeit DESC LIMIT 0, 1"); if(mysqli_num_rows($q_values) > 0) { $r_values = $q_values->fetch_object(); // Wert aus Datenbank auslesen $datu = $r_values->DatumZeit; $temp = $r_values->Temperatur; $humi = $r_values->Luftfeuchte; // Farben der Ausgabe je nach Wert anpassen switch(true) { case in_array($humi, range(0,30)): $colh = "blue"; break; case in_array($humi, range(31,60)): $colh = "green"; break; case in_array($humi, range(61,100)): $colh = "red"; break; } switch(true) { case in_array($temp, range(-10,10)): $colt = "#00ccff"; break; case in_array($temp, range(11,25)): $colt = "#0085ff"; break; case in_array($temp, range(26,30)): $colt = "green"; break; case in_array($temp, range(31,50)): $colt = "red"; break; } // Ausgabe des aktuellsten Wertes aus der Datenbank if($ausgabe == "d") echo "Wert vom ".MySQLDateTimeToDateTime($datu)." Uhr"; if($ausgabe == "t") echo "<div style=\"color:".$colt."\">".$temp."°C</div>"; if($ausgabe == "h") echo "<div style=\"color:".$colh."\">".$humi."%</div>"; } ?>
So sieht die Ausgabe aus
Beim ersten Aufruf der Seite wird folgendes ausgegeben bis die Datei “showSensorValue.php” das erste mal durch die Datei “index.html” aufgerufen wird.
Nachdem die Datei “showSensorValue.php” aufgerufen und den aus der Datenbank ausgelesenen Datensatz zurückgegeben hat sieht die Ausgabe in etwa wie folgt aus.
Wenn Sie Ihren Sensor nun per Batterie betreiben können Sie diesen an einer beliebigen Stelle in der Nähe Ihres WLAN-Netzwerkes platzieren ohne auch nur ein Kabel verlegen zu müssen.
Adafruit_CC3000_Library
Sparkfun_CC3000_Library
The post Arduino – Sensordaten mit dem CC3000 Wifi-Modul an Webserver senden appeared first on Fluuux - TechBlog.