Performance Test ESP8266

Der ESP8266 gehört inzwischen zu meinen Standardboards. Die Integration in die Arduino IDE ist erfolgt und die Zahl der Libraries nimmt ständig zu. Um ein Gefühl für die Performance des Boards zu bekommen habe ich das Primzahlenprogramm genutzt, mit dem ich bereits den STM32 Maple gegen den Arduino UNO getestet habe.

Das Ergebnis als Übersicht, alle Zeitangaben in Millisekunden.

Datentyp Suchbereich Arduino Maple ESP8266
uint8_t 255 550 30 83
uint16_t 65535 10760 241 1054
uint32_t 2*65535 84551 583 2919
uint32_t 1000000 abgebrochen 10042 30369

Auf eine Besonderheit möchte ich an dieser Stelle hinweisen:

Ich hatte anfänglich Schwierigkeiten beim ESP mit dem uint32_t Datenformat. Aus zunächst unerklärlichen Gründen gab es immer Abstürze des Programms aufgrund von Watchdog Fehlern. Das hängt wohl damit zusammen, dass der ESP seine komplette WLAN Abarbeitung im Hintergrund erledigt. Wenn aber längere Loops im Programm sind, bekommt er offensichtlich Schwierigkeiten. Um das zu vermeiden habe ich den Befehl yield() in die Loop eingebaut. Das verhindert den Absturz, frisst aber auch ca. 6μs je Aufruf.

Advertisements

Integration des ESP8266 in die Standard Arduino IDE

In meinem letzten Beitrag habe ich beschrieben wie der ESP8266 angeschlossen werden muss, um mit der Arduinio IDE geflashed zu werden. Zu diesem Zeitpunkt war eine eigenständige IDE (siehe Link) notwendig. Heute ist die Integration des ESP8266 in die Standard IDE sehr viel einfacher. Adafruit hat eine ausführliche Anleitung veröffentlicht, die bis jetzt allerding nicht auf Deutsch verfügbar ist. Deshalb und da die Anleitung auch für den ESP8266-01 gültig ist, diese Anleitung hier. Zunächst installieren wir uns die aktuellste IDE von arduino.cc. In meinem Fall ist es die Version 1.6.5.

Nach der Installation der IDE wird diese gestartet. Unter Datei->Voreinstellungen muss nun unter Additional Boards Manager URLs folgende Eintragung vorgenommen werden: http://arduino.esp8266.com/staging/package_esp8266com_index.json . Mit OK wird das Fenster geschlossen. (Mit der stableVersion hatte ich einen CRC Fehler, deshalb hier die staging-Version).

ESP_BoardsManager4Auf ein Detail möchte ich an dieser Stelle noch hinweisen. Es ist zweckmäßig für die ESP Sketches ein eigenes Sketchbook Verzeichnis unter Sketchbook-Speicherort zu definieren, da für den ESP teilweise eigene Libraries gebraucht werden, die nicht mit den AVR Libraries kompatibel sind.

Jetzt kommt der eigentliche Clou. Arduino hat mit dem Board Manager ein tolles Tool geschaffen, um neue Boards in die IDE zu integrieren. Unter Werkzeuge->Platine rufen wir jetzt den Boards Manager auf und geben in das Suchfeld ESP8266 ein.  Die Boards Erweiterung der ESP Community wird schnell gefunden.

ESP_BoardsManager2Wir wählen die Erweiterung aus und wählen Install. Nach dem Download der Erweiterung, meldet der Board-Manager INSTALLED.

ESP_BoardsManager3Jetzt können wir unter Werkzeuge->Platine die Veränderung bewundern. Für den ESP8266-01 wählen wir jetzt das Generic ESP8266 Module.

ESP_BoardsManager5Wenn wir dann Werkzeuge->Platine erneut aufrufen, sehen wir weitere Einstellungen für den ESP. Hier können wir getrost die default-Einstellungen übernehmen.

ESP_BoardsManager6Zusätzlich tauchen unter Datei->Beispiele spezifische Sketches für den ESP8266 auf. Wer Lust hat kann jetzt mit der Beschaltung und Beschreibung meines letzten Blog Posts das Blink Beipiel flashen.

ESP_BoardsManager7Da mit der Aufbau auf dem Steckbrett auf Dauer zu fehleranfällig war, habe ich mir eine Programmier-Platine auf einer Streifenraster-Platine zusammengelötet.

guvcview_image-5Rechts unten kann ich die GPIO Pins des ESP abgreifen, die Buchse ist mit langen Pins nach unten ausgestattet, so dass ich die Platine auch auf ein Steckbrett stecken kann. Für die Erzeugung der 3.3V habe ich ein AMS1117 Modul integriert. Um in den Flash Mode zu kommen habe ich einen Pushbutton für GPIO0 auf GND und einen Schalter, um die Spannungsversorgung zu unterbrechen eingebaut. Vor dem Flashen wird GPIO0 auf GND gezogen, dann die Spannungsversorgung kurz unterbrochen. Der ESP ist jetzt im Flash Mode. Wie gewohnt wird das Programm mit dem -> hochgeladen.

ESP_BoardsManager8

ESP8266 mit Arduino IDE flashen

esp_blink640

Mit der angepassten IDE auf https://github.com/esp8266/Arduino lässt sich der ESP8266 direkt flashen.

Hier die Verschaltung zum Flashen des ESP8266. Wenn ein 3,3V FTDI zur Verfügung steht, kann man sich den Spannungsteiler auf der TX Leitung zum ESP sparen.

Variante 1: 3,3V FTDI (an der oberen Leiste des Steckbretts liegen 3,3V an)

 

ESP8266_Steckplatine_3.3Variante 2: 5V FTDI (an der oberen Leiste des Steckbretts liegen 3,3V an)

 

ESP8266_5VFTDI_Steckplatine

 

Zum Flashen wird zunächst der Schalter umgelegt und damit der GPIO0 auf GND gezogen. Dann einmal die 3,3V Spannungsversorgung aus- und wieder einschalten. Jetzt ist der ESP im Flash Modus.

Programm hochladen. Der ESP bekommt nach dem Flashen ein Reset und läuft direkt los, allerdings werden Einstellungen für den Modus (Access Point, Client, usw) erst nach einem Aus- und Wiedereinschalten  übernommen. Ich schalte nach dem Flashen den GPIO0 wieder auf offen und mache die Schaltung einmal stromlos, so bin ich sicher, das alles übernommen ist.

Download der Fritzing Files:

https://www.dropbox.com/s/sl04lnjxaocozg6/ESP8266.fzz?dl=0

https://www.dropbox.com/s/j5b2rium000nciw/ESP8266_5VFTDI.fzz?dl=0

What IF ? — Kein FTDI zur Hand

Der FTDI ist der wohl bekannteste USB Seriell Wandler auf dem Markt und wird in der Mikrocontroller Entwicklung sehr häufig eingesetzt, nämlich immer dann, wenn es darum, geht ein serielles Device direkt über USB anzusprechen. Ich setze den FTDI gerne ein, wenn ich ein HC-05 Bluetooth Modul mit AT Befehlen umkonfiguriere oder wenn ich die FW Version eines ESP8366 neu flashen will.

Doch was, wenn man gerade keinen FTDI zur Hand hat? Dumm gelaufen, macht aber nix, wenn man zumindest einen Arduino UNO zur Hand hat.

Auf dem UNO ist mit dem ATmega 16U2 bereits ein USB-Seriell Wandler eingebaut und der zweite wichtige Punkt ist, dass man den ATmega328, also den Chip auf dem die Arduino Programme laufen, entnehmen kann. Leider funktionioert das Beschriebene deshalb auch nicht mit der SMD Version.

Als erstes entnehmen wir vorsichtig den Chip von der Platine und passen auf, dass keine Beinchen verbiegen. An Pin 0 und 1 auf dem Platine kann jetzt das serielle Signal abgenommen werden. Wichtig ist zu beachten, dass die Beschriftung jetzt sozusagen für den Empfänger gilt und deshlab müssen RX und TX zwischen den beiden Devices 1:1 verbunden werden.

Ich habe das mal mit einem HC-05 aufgebaut. Der Einfachheit halber bin ich davon ausgegangen, dass der HC-05 in diesem Fall 5V tolerant ist.

hc-05-serial_Steckplatine

Als serielles Terminal kann jetzt die Arduino IDE genommen werden, ich persönlich bevorzuge Cutecom unter Linux. Die einzustellende Baudrate enspricht der Baudrate des HC-05.

Die ist der erste Blogpost zum Thema „What IF“  –  kleine Tips, die das Leben einfacher machen. Weitere werden folgen.

 

 

Vergleich Maple vs Arduino*

maple1

Zugegebenermaßen ein wirklich unfairer Vergleich, was sollte man schon bei dem Vergleich eines STM32 mit 32Bit und 72MHz Taktfrequenz gegen einen 8Bit Atmel mit 16MHz erwarten? Der Erstere ist natürlich schneller – aber wieviel schneller?

Zunächst geht es erst mal darum möglichst gleiche Ausgangspositionen zu schaffen. Für den Vergleich wählte ich ein Programm zur Suche von Primzahlen. Dieses Programm ist der Erweiterung für die Arduino IDE beigefügt. Um den Maple mit der Arduino IDE zu flashen habe ich nach dieser Anleitung die IDE 1.6.0 erweitert. Im Arduino Forum gibt es dazu einen inzwischen über 100 Seiten (!!) langen Post.  Das Flashen ist etwas umständlich, man muss erst den Maple in den Perpetual bootloader mode bringen und nach dem Upload die Reset Taste drücken. Aber es geht hier weniger um die Bedienbarkeit, ich bin ja froh, dass ich überhaupt mit der Arduino IDE arbeiten kann.

Das Programm sucht die Primzahlen bis zu einer gegebenen Zahl. Da ich größere Geschwindigkeitsunterschiede bei großen Zahlen bereits erwartet habe, habe ich zunächst mit uint8_t als Datentyp begonnen.

Hier das Programm, in der Kommentierung sieht man die Unterschiede für beide Prozessoren im Code, die lediglich im setup() vorhanden sind. Damit man überhaupt im Millisekunden Bereich was messen kann, wird die Schleife 255x durchlaufen.

/*
  PrimeNos3: by Nick Gammon
  Maple Mini port m. ray burnette: Compiled under Arduino 1.6.0
  PUBLIC DOMAIN EXAMPLE
*/

#define BAUD 115200
uint8_t limit = 255;

/* Arduino part
#define BOARD_LED_PIN 13
void setup() {
  // initialize the digital pin as an output.
  pinMode(BOARD_LED_PIN, OUTPUT);
  Serial.begin(BAUD);  
  Serial.println("Prime Number Generator V2");
} */  //Arduino part

// Maple part
void setup() {
  // initialize the digital pin as an output.
  pinMode(BOARD_LED_PIN, OUTPUT);
  Serial.begin(BAUD);  // BAUD has no effect on USB serial: placeholder for physical UART
  // wait for serial monitor to be connected.

  while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS())))
  {
    toggleLED();
    delay(100);         // fast blink
  }
  Serial.println("Prime Number Generator V2");
} //   //Maple part

void loop() {
  uint8_t i;
  Serial.print("Searching prime numbers between 1 and "); Serial.println(limit);
  unsigned long starttime = millis();
  for (uint8_t k = 0; k < 255; k++) {
    for (i = 3; i < limit; i += 2) {
      // This loop stops either when j*j>i or when i is divisible by j.
      // The first condition means prime, the second, not prime.
      uint8_t j = 3;
      for (; j * j <= i && i % j != 0; j += 2); // No loop body
      // if (j * j > i) Serial.println(i);      // output prime numbers
    }
  }
  Serial.print("Test run for ");
  Serial.print((millis() - starttime));
  Serial.println(" milliseconds\r\n");
  delay(2000);
}
 

Ergebnis: Arduino UNO 550ms / Maple 30ms  — immerhin also ein Faktor von 18,3 erstaunlich viel, da der Unterschied in der Taktfrequenz ja nur Faktor 4,4 ist.

In nächsten Test habe ich den Datentyp auf uint16_t geändert und die Primzahlen bis zur Grenze von 65535 gesucht. Der 255-malige Durchlauf wurde auf 1x reduziert.

Ergebnis: Arduino UNO 10760ms / Maple 241ms  — also immerhin schon ein Faktor von 44,7. Hier zeigen die 32Bit des STM ihre Wirkung.

Im nächsten Test bin ich dann auf uint32_t und einen Suchbereich bis 2x 65535 gegangen.

Ergebnis: Arduino UNO 84551ms / Maple 583ms  — den Maple mit seinem 32Bit Prozessor kümmert das recht wenig, die Rechenzeit ist erstaunlicherweise nur etwas mehr als doppelt so lang, wie beim vorherigen Grenzwert. Der Arduino quittiert den längeren Datentyp sofort mit einer 7,9x längeren Rechenzeit.

Im letzten Test habe ich dann die Grenze nochmal weiter erhöht, musste den Test aber abbrechen, weil mir die Geduld fehlte, auf den Arduino zu warten. Der Maple rechnete für eine Grenze von 1000000 (eine Million) nur 10042ms.

Die Ergebnisse hier nochmals als Übersicht, alle Zeitangaben in Millisekunden.

Datentyp Suchbereich Arduino Maple
uint8_t 255 550 30
uint16_t 65535 10760 241
uint32_t 2*65535 84551 583
uint32_t 1000000 abgebrochen 10042

Fazit: Dass der Maple soviel schneller bei der Verarbeitung von 32Bit Zahlen ist, habe ich in der Tat nicht erwartet. In Zukunft werde ich bei Performance kritischen Verarbeitungen den Maple sicher mal nutzen. Momentan ist aber die Unterstützung der Standard Libraries noch ziemlich rudimentär, aber das wird sich hoffentlich weiter entwickeln. Arduino bringt mit dem Due ja auch einen 32Bit Prozessor in die Familie.  Auf Dauer geht an 32Bit kein Weg vorbei. Bleibt zu hoffen, dass Arduino die Integration in die IDE und die Entwicklung der Libraries schnell vorantreibt.

*mir ist bewusst, dass die Abbildung keinen Arduino zeigt, sondern einen Arduino Nachbau, Die Messergebnisse sind aber sicher portierbar. Zusätzlich mächte ich betonen, dass ich auch Orginale Arduinos in meiner Sammlung habe und jedem empfehle, mit einem Orginalen anzufangen, um die Idee Arduino zu unterstützen.

Arduino WiFi für unter 3 Euro – der ESP8266

IMG_20150116_090344

In den letzten Monaten ist ein regelrechter Hype ausgebrochen um den ESP8266, ein Chip aus chinesischer Entwicklung, der auf einer winzigen Fläche sowohl Access Point als auch WiFi Client sein kann. Inzwischen exisitieren verschiedene Breakout Boards, die zunächst eine UART-WiFi Schnittstelle bereitstellen und auf eBay für unter 3 Euro gehandelt werden. Da der Chip einen 32bit Prozessor enthält kann er aber auch mit eigener Firmware bestückt werden. Ich möchte mich hier nicht näher mit Details beschäftigen, da es bereits viele Webseiten zu diesem Thema gibt. Eine kurze und knappe Zusammenfassung auf deutsch mit Verlinkung zu weiteren Seiten hat das FabLab Nürnberg erstellt.

Inzwischen konnte ich einige Erfahrungen mit diesem Modul machen und solange man kein Highspeed WiFi braucht ist das Modul eine gute Wahl und macht für kleines Geld IoT möglich. Die ersten Versuche mit diesem Modul habe ich in Verbindung mit einem Arduino MEGA gemacht. Der MEGA hat mehrere in Hardware implementierte serielle Schnittstellen, so kann man sowohl die Verbindung zum Computer als auch die Verbindung zum ESP8266 mit 115200 Baud laufen lassen. In den neueren Firmwares des ESP ist die Baudrate aber auch einstellbar, so dass ein Betrieb an einer SoftSerial Schnittstelle bei z.B. 9600 Baud, damit an einem UNO, auch möglich ist.  Die Verbindung des ESP an den MEGA muss über Pegelwandler 5V->3.3V erfolgen, die Schnittstelle ist hier nicht tolerant. Ich habe die Verbindung von TX (MEGA) zu RX (ESP) über einen Spannungsteile aus 1k und 2.2k herunter geteilt. Der ESP braucht einen eigenen 3.3V Spannungswandler, der 3.3V Ausgang des Arduino liefert zu wenig Strom für den ESP (max 200mA).

Für erste Experimente, bei denen die AT Befehle „per Hand“ eingegeben werden, eignet sich das folgende kurze Programm.

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
  Serial.println("Program started");
}

void loop() {
  if(Serial1.available()) {   
    char ser = Serial1.read();
    /*if (ser==10) {         // kann genutzt werden, um ein Gefühl für die Antwortzeiten zu bekommen
      Serial.print("  ");
      Serial.print(millis());
    }*/
    Serial.print(ser);
  }
  if(Serial.available()) {   
    char ser = Serial.read();
    Serial1.print(ser);
  }
}

Die meisten Einstellungen des Chip bleiben über ein Power on Reset bestehen. Es ist also nicht notwendig, im Programm die Einstellungen jedes mal neu zu setzen. Ich habe mir zu diesem Zweck ein Programm erstellt mit den wichtigsten Einstellungen (Access Point, SSID, PASS, Client usw.). Mit diesem Programm mache ich die Grundkonfiguration des Chip.

// ESP_Minimal.ino - sketch to quickly view and change some of ESP8266 parameters
// most of the ESP parameters are stored in eeprom, so also outlive the power on reset
// special thanks to http://rayshobby.net/?p=9734
// sketch is written for ArduinoMega, ESP connected with voltage devider to Serial1
// This code is in the public domain.

#define SET // for just viewing parameters, set this as comment

#define BUFFER_SIZE 512
#define esp Serial1
#define dbg Serial //For debugging purposes

char buffer[BUFFER_SIZE];
char OKrn[] = "OK\r\n";
int mode;

boolean wait_for_esp_response(int timeout, char* term=OKrn) {
 unsigned long t=millis();
 bool found=false;
 int i=0;
 int len=strlen(term);
 // wait for at most timeout milliseconds
 // or if OK\r\n is found
 while(millis()<t+timeout) {
 if(esp.available()) {
 buffer[i++]=esp.read();
 if(i>=len) {
 if(strncmp(buffer+i-len, term, len)==0) {
 found=true;
 break;
 }
 }
 }
 }
 buffer[i]=0;
 dbg.print(buffer);
 return found;
}

void setup() {
 esp.begin(115200); //esp baud rate
 dbg.begin(115200); //debugger baud rate
 dbg.println("start of program ...");
 esp.println("AT"); // check for existence of ESP8266
 if (!wait_for_esp_response(1000)) {
 dbg.println("no ESP found");
 while(true); // hang forever
 }
 // some important checks of operation modes
 esp.println("AT+CWMODE?"); // check mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 char *result = strstr(buffer, "+CWMODE:");
 if (result!=0) {
 mode=atoi(result+8);
 if (mode!=1) {
 esp.println("AT+CWSAP?"); // actual AP configuration
 }
 if (mode!=3) {
 esp.println("AT+CWJAP?"); // actual connected WiFi
 wait_for_esp_response(1000);
 }
 }

 esp.println("AT+CIPMUX?"); // check connection mode 0=single, 1=multiple
 wait_for_esp_response(1000);
 esp.println("AT+CIPMODE?"); // check data mode 0=normal, 1=transparent
 wait_for_esp_response(1000);
 esp.println("AT+CIFSR"); // actual IP adress
 wait_for_esp_response(1000);

#ifdef SET
 esp.println("AT+CWMODE=3"); // set mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 // set AP or Client
 esp.println("AT+CWMODE?"); // check mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 result = strstr(buffer, "+CWMODE:");
 if (result!=0) {
 if (mode!=1) { // AP settings
 esp.println("AT+CWSAP=\"ESP_9F2556\",\"blablabla\",1,3"); // set AP: SSID, PASS, channel, encryption
 wait_for_esp_response(1000); // 0=open, 1=WEP, 2=WPA_PSK, 3=WPA2_PSK, 4=WPA_WPA2_PSK
 }
 if (mode!=2) { // Client settings
 esp.println("AT+CWJAP=\"yourSSID\",\"passphrase\""); // connect client to AP
 wait_for_esp_response(5000); // was really that long!
 }
 }

#endif

 esp.println("AT+RST"); // RESET, necessary for some changes of settings
 wait_for_esp_response(3000, "ready");
}

void loop() {

}

Die zu ändernden Parameter werden direkt im Code verändert. Wenn die erste Zeile #define SET auskommentiert wird, werden die wichtigsten Parameter nur angezeigt.

Arduino goes Wireless

Die Experimente zu meinem Tutorial  „Speicherung von Arduino Messdaten auf Webserver und deren Darstellung“ setzten alle auf einen Arduino mit Ethernet Shield zur Verbindung mit dem Internet auf. Nun gibt es Situationen, wo kein Ethernet Anschluss in Reichweite ist, trotzdem aber die Verbindung ins Internet benötigt gewollt ist. Oder es ist Mobilität gefordert, während Daten übertragen werden. Das Arduino Wifi Shield wäre eine Lösung, ist aber mit fast 70€ eine sehr kostspielige und zusätzlich muss das Programm daraufhin angepasst werden. Eine wesentlich kostengünstigere und ohne Anpassung des Programms einsetzbare Lösung ist ein Wireless Client. Ich habe mich für den TP-Link TL-WR702N entschieden, der schon inklusive Versand für weniger als 20€ zu bekommen ist.

IMG_20150114_181434

Der TL-WR702N ist im Auslieferungszustand ein Access Point, für unsere Anwendung muss er aber als Client oder als Bridge konfiguriert werden. Der TL-WR702N stellt als Client über WLAN die Verbindung zum Access Point her, der Arduino mit Ethernet Shield wird mit dem TL-WR702N über die Ethernet Schnittstelle verbunden und verhält sich genauso, wie bei direkter Verbindung nur über Ethernet.

Die Konfiguration als Client ist im Handbuch ausreichend beschrieben, deshalb möchte ich hier nicht näher darauf eingehen. Einen Sonderfall möchte ich an dieser Stelle näher beschreiben, nämlich, wenn ich keinen Rechner zur Verfügung habe, den TL-WR702N zu konfigurieren. Eine Konfiguration über Wireless, z.B. mit einem Smartphone oder Tablet ist im Handbuch nicht beschrieben.

Nachfolgend gehe ich davon aus, dass der TL-WR702N im Auslieferungszustand vorliegt. Dieser Zustand kann jederzeit hergestellt werden, indem der Reset Taster mit einem spitzen Gegenstand z.B. einer aufgebogenen Büroklammer, für ca. 7 Sekunden gedrückt wird, bis die Betriebs LED mehrmals kurz blinkt. Die nachfolgenden Schritte habe ich mit meinem Nexus 7 durchgespielt, mit anderen Geräten kann das leicht variieren.

Zunächst verbinde ich mich mit dem Tablet auf den Access Point des TL-WR702N. Die SSID, nach der ich suche, steht auf dem Typenschild des TL-WR702N, ebenso die zugehörige Passphrase.

Screenshot_2015-01-14-16-45-17_bea

Wenn ich die Verbindung hergestellt habe, wird mein Tablet eine IP aus dem 192.168.0.x Netz erhalten haben. Im Browser des Tablet gebe ich 192.168.0.254 ein, die IP des TL-WR702N zur Konfiguration. In der Abfragemaske wird für User: admin und Passwort: admin eingegeben. Wir kommen auf die Konfiguration des Routers und Erstellen eine Konfiguration für eine Bridge.

Screenshot_2015-01-14-16-59-39

Der Vorteil der Bridge Konfiguration ist, dass ich später noch über WLAN auf die Konfigurationsschnittstelle komme, um Änderungen zu machen. Das ist im Client Modus nur über Ethernet möglich. Wichtig ist jetzt, dass über Quick Setup gegangen wird, sonst verliert man nach Reboot die Konfigurationsseite. Also Quick Setup, Next, Bridge, Next.

Screenshot_2015-01-14-17-08-36

Unter Survey sehe ich die zur Verfügung stehenden WLANs und kann den gewünschten Access Point direkt mit connect auswählen. Nach Eingabe des Password für dieses WLAN gehe ich weiter mit Next. Wenn die Meldung erscheint „Your AP channel is not the same as the Bridged AP’s channel, do you want to change your channel to the Bridged AP’s channel?“ kann ich das mit OK bestätigen. Im nächsten Fenster wird kann die bestehende Verschlüsselung bestätigt werden oder eine neue Passphrase vergeben werden. Mit Next kommt man auf das letzte Fenster zum Reboot des Routers.

Screenshot_2015-01-14-17-14-33

Beim Reboot verliere ich die Verbindung zur Konfiguration des Routers. Mein Tablet verliert möglicherweise auch die Anbindung zu Access Point oder verbindet sich zu einem anderen bekannten Access Point. Eigentlich ist jetzt alles fein und ich kann mein Ethernet Shield mit dem Router verbinden und loslegen. Wenn ich die Konfiguration mit dem Tablet bearbeiten will, muss ich die IP des Routers herausfinden. Wenn ich nicht die Möglichkeit habe, die IP auf meinem Router nachzusehen, kann ich folgenden Trick anwenden. Die Android App Ping-Tools hilft mir dabei. Ich stelle über das Menü links oben die Funktion UPnP scanner ein und schon sehe ich meinen TP-Link mit seiner IP-Adresse.

Screenshot_2015-01-14-17-22-38

Über diese IP in der Browserzeile komme ich jetzt wieder auf die Konfigurationsschnittstelle, falls ich noch etwas ändern möchte. Sinnvoll wäre z.B. die Änderung des Standard Passworts für den Admin Zugang.

Der Stromverbrauch des TL-WR702N liegt übrigens nur bei ca, 150mA. Bei einer mobilen Anwendung kann der Router also ohne weiteres aus der 5V Schnittstelle des Arduino mit versorgt werden oder Arduino und der TL-WR702N werden über eine Powerbank mit USB Schnittstelle versorgt.

Als nächstes steht jetzt ein Test mit dem TP-Link TL-MR3020 an, der für unter 30€ mit gleichem Verfahren einen Arduino ins 3G/4G Mobilfunknetz und damit ins Internet bringt. Zusätzlich ist nur ein USB Stick mit Mobilfunkkarte notwendig.

 

 

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

In diesem Post fasse ich einige Informationen zusammen, die ich noch loswerden wollte

Addendum1 – Config-file für MySQL Datenbank

Wenn man mit verschiedenen Abfragen einer Datenbank arbeitet und immer wieder die Zugangsdaten eingeben muss, ist das auf Dauer ziemlich nervig. Übersichtlicher ist es dann auch die Zugangsdaten separat in einen File, hier mit dem Namen config.php zuschreiben, der dann in die eigentliche Abfrage included wird.


<?php
$mysql_host = "<hier Name des Server/Host eintragen>";
$mysql_db = "<hier Datenbanknamen eintragen>";
$mysql_user = "<hier MySQL User eintragen>";
$mysql_pw = "<hier MySQL Passwort eintragen>";
$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.");
?>

Die Abfrage sieht dann so aus, hier das Beipiel aus Teil 4 zur Abfrage der letzten 20 Datensätze, Zusätzlich habe ich hier die Tabelle in eine Stringvariable gesetzt. Damit wird der File leichter anpassbar für andere Tabellen.


<?php
require ($_SERVER['DOCUMENT_ROOT']."/config.php");
$mysql_table = "analog_data";
$abfrage = "SELECT datum, analog0, analog1 FROM ".$mysql_table." ORDER BY datum DESC LIMIT 20";
$ergebnis = mysql_query($abfrage);
while($row = mysql_fetch_array($ergebnis))
{
echo $row[datum].",".$row[analog0].",".$row[analog1]."<br>";
}
?>

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

Teil 5 – CSV und MySQL Daten grafisch präsentieren

Bei der Recherche, wie MySQL Daten einfach und dennoch wirkungsvoll grafisch zu präsentieren sind, habe ich mir viele Möglichkeiten angesehen. Letztendlich habe ich mich dann für dygraphs entschieden, weil diese JavaScript Library viele Möglichkeiten bietet und die Dokumentation und das Tutorial gut verständlich sind.

Um die Library einzusetzen muss zunächst der File dygraph-combined.js von der dygraphs Download-Seite geladen werden und im Basisverzeichnis des Webspaces abgelegt werden. Um die Funktionsweise der Library kennenzulernen, möchte ich  zunächst zeigen, wie die Daten aus dem csv-File aus dem 3. Teil des Tutorials dargestellt werden können. Dazu erstellen wir auf dem Webspace eine html-Seite, die im Wesentlichen dem Beispiel auf den Dygraphs Seite für csv-Dateien entspricht. Der Name dieser Datei könnte z.B. graphcsv.html sein.

<html>
<head>
<script type="text/javascript"
src="dygraph-combined.js"></script>
</head>
<body>
<div id="graphdiv2"
style="width:500px; height:300px;"></div>
<script type="text/javascript">
g2 = new Dygraph(
document.getElementById("graphdiv2"),
"test.csv", // path to CSV file
{} // Options
);
</script>
</body>
</html>

Wer jetzt schon einige Daten in seiner csv-Datei hat, sollte nach Aufruf dieser html-Seite jetzt die typische Dygraphs Grafik sehen. Dabei fällt allerdings auf, dass Dygraphs den Unix Timestamp nicht als Datum und Zeit interpretiert. Um das zu ändern, muss entweder die Speicherung der Daten geändert werden oder dem dygraphs-Aufruf eine optionale Funktion mitgegeben werden. Die Option wird in den geschweiften Klammern übergeben, hier der gesamte Funktionsaufruf. Zusätzlich habe ich noch Labels ergänzt.


g2 = new Dygraph(
document.getElementById("graphdiv2"),
"test.csv", // path to CSV file
{ xValueFormatter: Dygraph.dateString_,
xValueParser: function(x) { return 1000*parseInt(x);},
xTicker: Dygraph.dateTicker,
labels: [ "Datum", "A0", "A1" ]
} // Options
);

Die Darstellung des Datums in der Grafik finde ich aber sehr ungünstig, habe mich aber nicht weiter damit beschäftigt, das zu verändern. Sinnvoller finde ich, die csv-Daten direkt mit einem interpretierbaren Datumsformat zu erzeugen. (Sorry, dass das nicht schon in Teil 3 berücksichtigt wurde). Hier die Änderung der php-Seite zur Ablage der Daten als csv-Datei, im Aufruf der Dygraph Funktion müssen jetzt natürlich die Optionen wieder entfernt werden.

<?php
isset($_GET['A0']) ? $a0=$_GET['A0'] : $a0='';
isset($_GET['A1']) ? $a1=$_GET['A1'] : $a1='';
$jetzt = time();
$delimiter = ",";
$enclosure = " ";
$handle = fopen("./test.csv", 'a');
fputcsv($handle, array(date("Y/m/d H:i:s",$jetzt),$a0,$a1),$delimiter,$enclosure);
fclose($handle);
?>

Doch nun zur Darstellung der Daten aus der MySQL Datenbank. Ich habe lange rumprobiert, wie man die Daten aus MySQL in den JavaScript Aufruf einbauen kann. Als Lösung habe ich die Daten innerhalb des JavaScript Aufrufs per php aus der Datenbank gelesen und als Array an die dygraphs Funktion übergeben. Die Daten müssen in genau dieser Form

[
[ new Date("2009/07/12"),100, 200 ],
[ new Date("2009/07/19"), 150, 220 ]
]

an dygraphs übergeben werden, deshalb sieht die Formatierung der Daten innerhalb der php-Funktion etwas chaotisch aus (siehe hier).

Folgende php-Seite sollte unter dem Namen graph.php auf dem Webspace erzeugt werden. Natürlich müssen wieder die Zugangsdaten der Datenbank eingetragen werden:

<html>
<head>
<body style="color: rgb(0, 0, 0); background-color: rgb(77, 77, 77)" alink="#ee0000" link="#0000ee" vlink="#551a8b">
<div style="text-align: center;"><span style="color: rgb(255, 255, 255);">Daten aus MySQL<br></span>
<br>
<script type="text/javascript"
src="dygraph-combined.js"></script>
</head>
<body>
<table style="margin:0px auto" border="0" width="500" align="center">
<tr>
<td style="background-color: #FFFFFF">
<div id="graphdiv2"
style="width:500px; height:300px;"></div>
<script type="text/javascript">

g2 = new Dygraph(document.getElementById("graphdiv2"),
<?php
$mysql_host = "<hier Name des Server/Host eintragen>";
$mysql_db = "<hier Datenbanknamen eintragen>";
$mysql_user = "<hier MySQL User eintragen>";
$mysql_pw = "<hier MySQL Passwort eintragen>";
$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.");
$abfrage = "SELECT DATE_FORMAT(datum, '%Y/%m/%d %H:%i:%s') AS date, datum, analog0, analog1 FROM analog_data";       //   2009/07/12 12:34:56
$ergebnis = mysql_query($abfrage);
echo "[";                                  // start of the 2 dimensional array
while($row = mysql_fetch_array($ergebnis))
{
$utime = strtotime($row[datum]);
$diffutime = $utime - $lastutime;
if ($diffutime > 600) {
echo "["."new Date(\"".$row[date]."\")".",NaN,NaN],";
}
else {
echo "["."new Date(\"".$row[date]."\")".",".$row[analog0].",".$row[analog1]."],";
}
$lastutime = strtotime($row[datum]);
}
echo "]";
?> ,
{ rightGap: 20,
connectSeparatedPoints: true,
labels: [ "Datum", "A0", "A1" ] }          // options
);
</script>
</div>
</td>
</tr>
</table>
</body>
</html>

In der Übergabe des Arrays an die dygraph-Funktion habe ich eine Abfrage eingebaut, die dafür sorgt, dass (zeitliche) Lücken in der Datenreihe nicht als verbundene Punkte dargestellt werden.

Ich hoffe, diese Tutorial hat euch geholfen eure Daten zu speichern und grafisch zu präsentieren. Ich bin gespannt auf euer Feedback und eure Ergebnisse.

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

Teil 4 – Einrichten der MySQL Datenbank und speichern der Daten

In diesem Teil des Tutorials werde ich euch zeigen, wie man vom Arduino erzeugte Daten über Ethernet in einer MySQL Datenbank abspeichert. Eine Datenbank hat gegenüber der im vorherigen Beitrag angelegten csv-Datei viele Vorteile, z.B. dass die Daten bei der Abfrage bereits selektiert werden können (z.B. ein bestimmter Zeitraum) oder sortiert werden können. Ein Abfragebeispiel dazu werde ich in diesem Teil des Tutorials später vorstellen.

Die MySQL Datenbank und die Datentabelle muss zunächst auf dem Webspace angelegt werden, am einfachsten ist das über das Programm phpMyAdmin, dass auf den meisten Webspaces bereits installiert ist. Auf dem Webspace aus dem Teil 2 des Tutorials greift man darauf über die Administration des eigenen Webspaces zu. Dazu loggt man sich ein und wählt im linken Menue meine Projekte und dann das bereits angelegte Projekt. Auf dieser Seite scrollt man ganz nach unten und wählt dann unter Webspace MySQL. Die Zugangsdaten für MySQL werden später im Programm noch verwendet. Wenn noch keine Datenbank angelegt ist, muss man jetzt zunächst eine Datenbank anlegen.

Über den Link zu phpMyAdmin erreichen wir die Administration der Datenbank. Als nächstes legen wir eine Tabelle zur Speicherung der Daten an, Das geht am schnellsten mit einem SQL Statement. Zunächst wählt man links die Datenbank, dann den Reiter SQL und geben folgendes Statement ein

CREATE TABLE IF NOT EXISTS `analog_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datum` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`analog0` int(11) NOT NULL COMMENT 'Analog0',
`analog1` int(11) NOT NULL COMMENT 'Analog1',
PRIMARY KEY (`id`)
)

das wir mit OK bestätigen. Mit diesem Statement wird eine Tabelle mitr dem Namen analog_data mit 4 Feldern (Spalten) angelegt, einer ID, die mit jedem Datensatz automatisch hochzählt, einem Zeitstempel, der bei Erzeugung eines neuen Datensatzes automatisch erzeugt wird und die beiden Messwerte analog0 und analog1.
Wenn keine Fehlermeldung kommt, ist die Tabelle, zunächst leer, jetzt angelegt.

Wie in Teil 3 benötigen wir jetzt zunächst eine php-Webseite die die Daten des Arduino annimmt und dann in der MySQL Tabelle abspeichert. Diese Seite legen wir unter dem Namen data2mysql.php an. Die Zugangsdaten (siehe Webspace Administrationsseite) müssen innerhalb der Anführungsstriche eingetragen werden. Der Name des Servers ($mysql_host) ist im Falle von kilu.de „localhost“.

<?php
$mysql_host = "<hier Name des Server/Host eintragen>";
$mysql_db   = "<hier Datenbanknamen eintragen>";
$mysql_user = "<hier MySQL User eintragen>";
$mysql_pw   = "<hier MySQL Passwort eintragen>";
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!");
?>

Einen ersten Test können wir wie im 3. Teil auch mit dem direkten Aufruf der Webseite machen, also z.B.:  <webspace>/data2mysql.php?A0=123&A1=345

Mit phpMyAdmin kann man jetzt kontrollieren, ob die Werte korrekt übernommen wurden. Nun muss nur noch das Arduino Programm aus Teil 3 auf die neue php-Webseite umgestellt werden, also statt der Zeile

client.print("GET /data2csv.php?A0=");

wird jetzt

client.print("GET /data2mysql.php?A0=");

eingetragen.

Um sich die letzten Daten anzusehen reicht diese einfache php-Webseite, wobei wieder die Zugangsdaten der Datenbank eingetragen werden müssen.

<?php
$mysql_host = "<hier Name des Server/Host eintragen>";
$mysql_db   = "<hier Datenbanknamen eintragen>";
$mysql_user = "<hier MySQL User eintragen>";
$mysql_pw   = "<hier MySQL Passwort eintragen>";
$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.");
$abfrage = "SELECT datum, analog0, analog1 FROM analog_data ORDER BY datum DESC LIMIT 20";
$ergebnis = mysql_query($abfrage);
while($row = mysql_fetch_array($ergebnis))
{
echo $row[datum].",".$row[analog0].",".$row[analog1]."<br>";
}
?>

In dieser Abfrage wird die oben erwähnte Selektion, hier der letzten 20 Datensätze und eine Sortierung angewendet. Im nächsten und letzten Teil des Tutorial beschäftigen wir uns dann mit der grafischen Präsentation der Daten.