Siechfred Noetigenfalls: elektronisches

elektronisches


Elektronische Basteleien
Test VI Wetterstation
Gleich vorweg: Das ist keine endgültige Wetterstation. Da kommen noch Gas-, Regen-, Licht-, Luftdruck- und sonstnochwas für Sensoren hinzu. Das ist auch nur ein Test (ähnlich dem Akkutest weiter unten), der die technische Umgebung, Softwarearchitektur und die Programmierung testet.
Es kann sein, dass während des Testlaufes die Batterien plötzlich versagen, Feuchtigkeit oder Hitze die Elektronik zerstören oder mir das Teil schlicht auf den Boden knallt.
Folgend der Link zu den Messdaten. Wenn Datum/Uhrzeit nicht mehr aktuell sind (-15 Minuten), hat der Herr die Station zu sich genommen.


(Update)
Die Batterie auf der Balkonstation habe ich gegen einen Akku austauschen müssen (Die Batterien waren zu schnell entladen ¯\_(ツ)_/¯).
Das Problem: Der Akku schaltet sich bei zu geringer Stromabgabe ab. Und das passiert, wenn der ESP in den Schlafmodus geht. Ich müsste alle 15 Minuten den Akku manuell hinzuschalten. Ist in der Nacht nicht angenehm, alle Viertelstunde aufzustehen. So habe ich vorerst den Schlafmodus aus der Programmierung herausgenommen.

Nachteil: Der ESP ist permanent im WiFi Modus und zieht Strom, viel Strom. Das bedeutet, dass der wahrscheinlich nur einige Stunden durchhält. das wird die Messkurve ja bald beweisen.
Wenn das so weitergeht, lege ich ein Starkstromkabel ausgelegt für 500 Ampere nach draußen. Es ist aber angedacht, einen kleinen ATtiny vor den ESP zu schalten, der zeitgesteuert den ESP hinzuschaltet. Der ist aber noch in China, freut sich aber schon, verbaut zu werden.
(Update Ende)

(Update II)
Der Akku schaltet sich trotzdem sporadisch aus ...
(Update Ende)

(Update III)
Zur Arbeitszimmerstation wurde noch ein zweiter DHT11 Sensor hinzugeschaltet. Die Abweichungen zwischen beiden Sensoren betragen ca. 1 Grad Celsius.
(Update Ende)

Das Ganze ist auf dem Balkon meiner Stadtwohnung installiert.
Der Wettersensor (DHT11) ist der billigste am Markt, der eine recht große Toleranz besitzt :). Abweichungen von 2 Grad sind möglich. Später werden präzise Sensoren verbaut.

Wer das alles nachbauen will, hier ein paar Hinweise.
Die Bauteile sind recht preiswert. Alles in allem inkl. Versand unter 10 € (ohne Batterien).
Die Codeschnipsel sind sehr reduziert wiedergegeben. Es fehlen Sicherheitsroutinen, Formatierungen, Optimierungen usw.. Funktioniert aber (bei mir zumindest :) ) und ist, ich kann es nicht oft genug wiederholen, nur ein Test ….

Der Schaltplan

Erkennbar der Spannungsteiler, der Sensor für Temparatur und Luftfeuchtigkeit und der ESP – Controller.



Es kommen 4 x 1,5 Volt AAA Batterien zum Einsatz. Die habe ich in zwei alte abgesägte Fernbedienungsbatteriefächer eingelegt. Batterien löten ist nicht ungefährlich. Bei großer Hitze können die explodieren und fliegen als Torpedo in dein Auge und treten aus deinem Hinterkopf wieder aus.
Hier zahlt sich übrigens mein Messiewesen aus, allen möglichen Krempel aufzubewahren.
Wie man weiterhin sehen kann, messe ich im Retrostil, analog.



Damit ich auch weiß, wie ich heiße habe ich mir gleich mal beim Löten das Initial meines Namens eingebrannt. Übrigens, die Batterieanschlüsse sind aus Stahl. Schwer zu löten. Da musste ich mit dem Gasbrenner ran.



Fertig aufgebaut – auf einem Testboard. Eine professionellere Arbeit gibt es wohl kaum.



Das Ganze wurde in eine Kunststoffdose gepackt, mit 100 Tonnen Heißkleber fixiert und kopfüber am Balkon befestigt.



Kommen wir zur Weichware.

Der initiale Code für den ESP.

 #include <ESP8266WiFi.h>  
 #include <DHT.h>  // Bibliothek V 1.2.3 belassen, kann nach Update neuerer Version Probleme bereiten
 const char* ssid   = "xxxxxxxxxx";  
 const char* password = "xxxxxxxxxx";  
 const char* host   = "daten.noetigenfalls.de"; //ohne http  
 //einige globale Variablen  
 int sekunde = 0;  
 long rssi = 0;  
 const int schlafe = 900;  // 900 Sekunden = 15 Minuten  
 //const int schlafe = 2;  
 // Sensor  
 #define DHTPIN 2     // Pin am ESP  
 #define DHTTYPE DHT11   // oder später DHT22  
 DHT dht(DHTPIN, DHTTYPE);  
 float h;         // Luftfeuchtigkeit  
 float t;         // Temperatur  
 void setup() {  
  Serial.begin(115200);   
 }  
 void loop() {  
  funktiontemperatur();  
  wifiverbindung();  
  httpverbindung();  
  schlafen();  
 }  


Obiger Code ruft folgende Funktionen auf (die habe ich in der Arduino IDE in Tabs verpackt) ...
Temperatur auslesen.


 void funktiontemperatur(){  
  h = dht.readHumidity();  
  t = dht.readTemperature();  
  if (isnan(h) || isnan(t)) {  
    Serial.println("Failed to read from DHT sensor!");  
    return;  
  }  
 }  


WiFi Verbindung

 void wifiverbindung(){  
  WiFi.begin(ssid, password);  
  delay(100);  
  Serial.println();  
  Serial.print("Verbindung wird aufgebaut");  
  Serial.println();  
  int millisekunden = 0;  
  while (WiFi.status() != WL_CONNECTED) {  
    Serial.print(".");  
    delay(200);  
    // Dauer Verbindungsaufbau  
    millisekunden = millisekunden + 200;  
  }  
   // Ausgabe Dauer Verbindungsaufbau  
   Serial.println();  
   if (millisekunden < 1000)  
   {  
    Serial.print("Verbindungsaufbau (Millisekunden): ");  
    Serial.print(millisekunden);  
   }  
   else  
   {  
    Serial.print("Verbindungsaufbau (Sekunden): ");  
    sekunde = millisekunden/1000;  
    Serial.print(sekunde);  
   }  
   Serial.println();  
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {  
   Serial.println("Verbindung fehlgeschlagen");  
   delay(5000);  
   ESP.restart();  
  }  
  Serial.print("IP-Adresse ESP: ");  
  Serial.println(WiFi.localIP());  
 }  


Http Verbindung

 void httpverbindung(){  
  Serial.print("connecting to ");  
  Serial.println(host);  
  // Use WiFiClient class to create TCP connections  
  WiFiClient client;  
  const int httpPort = 80;  
  if (!client.connect(host, httpPort)) {  
   Serial.println("connection failed");  
   return;  
  }  
  // We now create a URI for the request  
  String url = "/dht11/sens.php?"; //sende.php?  
  url += "w=";  
  url += rssi = WiFi.RSSI();  
  url += "&t=";  
  url += t;  
  url += "&h=";  
  url += h;  
  Serial.print("Requesting URL: ");  
  Serial.println(url);  
  // This will send the request to the server  
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +  
         "Host: " + host + "\r\n" +   
         "Connection: close\r\n\r\n");  
  Serial.println("Werte an WebServer uebergeben ");  
   unsigned long timeout = millis();  
   while (client.available() == 0) {  
    if (millis() - timeout > 5000) {  
     Serial.println(">>> Client Timeout !");  
     client.stop();  
     return;  
    }  
  }  
  // Read all the lines of the reply from server and print them to Serial  
  while(client.available()){  
   String line = client.readStringUntil('\r');  
   Serial.print(line);  
  }  
  Serial.println();  
  Serial.println("closing connection");  
 }  


Schlafmodus

 void schlafen(){   
  Serial.println("Schlafe");  
  WiFi.disconnect();  
  WiFi.mode(WIFI_OFF);  
  WiFi.forceSleepBegin(schlafe * 1000);  
  delay(schlafe * 1000);  
  WiFi.mode(WIFI_STA);  
  Serial.println("Erwache");   
 }  


Die Daten werden in eine MySQL Datenbank gespeichert. Hier die Struktur der Tabelle.

 CREATE TABLE IF NOT EXISTS `dht11` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `datum_mysql` timestamp NULL DEFAULT NULL,  
  `temperatur` float DEFAULT NULL,  
  `luftfeuchte` int(4) DEFAULT NULL,  
  `wifi` int(4) DEFAULT NULL,  
  PRIMARY KEY (`id`)  
 )   


Obiger Code des ESP schickt in der Funktion "httpverbindung()" via WLAN => Router => Internet die Daten an die Adresse "sens.php". Diese Datei ist für den Eintrag in die DB verantwortlich.

 <?php  
 $w = $_GET['w'];  
 $t = $_GET['t'];   
 $h = $_GET['h'];   
 // ein wenig Sicherheit  
 if (  
           (empty($w) or !is_numeric($w))  
      or      (empty($t) or !is_numeric($t))  
      or      (empty($h) or !is_numeric($h))  
      )  
      {   
           die("Keine Daten oder falsches Format ...");  
      }   
 $servername = "localhost";  
 $username = "xxxxx";  
 $password = "xxxxx";  
 $dbname = "xxxxxx";  
 $conn = new mysqli($servername, $username, $password, $dbname);  
 if ($conn->connect_error) {  
   die("Connection failed: " . $conn->connect_error);  
 }   
 $sql = "INSERT INTO dht11 (datum_mysql, temperatur, luftfeuchte, wifi)  
 VALUES (NOW(), $t, $h, $w)";  
 if ($conn->query($sql) === TRUE) {  
   echo "Eintrag erfolgreich ...";  
 } else {  
   echo "Error: " . $sql . "<br>" . $conn->error;  
 }  
 $conn->close();  
 ?>  


Um die Daten abzurufen, wird eine Seite generiert, die die Daten Jsonencodiert aufbereitet.

 <?php  
 header("Content-Type: application/json");  
 $servername = "localhost";  
 $username = "xxxxx";  
 $password = "xxxxx";  
 $dbname = "xxxxx";  
  error_reporting(E_ALL);  
 // in inc auslagern  
 error_reporting(0);  
 $mysqli = new mysqli($servername, $username, $password, $dbname);  
 print_r ($mysqli ->connect_error);  
 if ($mysqli ->connect_errno) {  
   die('Problem');  
 }  
 $query = "SELECT id, DATE_FORMAT(dht11.datum_mysql,'%d.%m.%Y - %H:%i') AS datum_mysql, temperatur, luftfeuchte, wifi FROM dht11 ORDER BY id ASC";  
 $result = $mysqli->query($query);  
 $data = array();  
 foreach ($result as $row) {  
      $data[] = $row;  
 }  
 $result->close();  
 $mysqli->close();  
 //Datenausgabe  
 print json_encode($data);  
 //json_encode($data);  
 ?>  


Da dort aber die Daten im Rohformat voeliegen und schlecht lesbar sind, werden sie durch folgende Routinen aufbereitet.
test.html liest diverse Javascript Dateien ein. Dabei ist die Steuerdatei "linegraph.js" die Datei, welche, im Zusammenspiel mit ihren anderen Schwester Javascript Dateien, die Json Daten aufbereitet und an die test.html übergibt. Hier die test.html.

 <!DOCTYPE html>  
 <html>  
      <head>  
           <!-- <meta http-equiv="refresh" content="5" > -->  
           <title>Auswertung</title>  
           <style>  
           @import url('http://fonts.googleapis.com/css?family=Oswald');  
           h1 {  
                font: bold 250% 'Oswald';  
                }  
                .chart-container {  
                     width: 1200px;  
                     margin-bottom:50px;  
                }  
                .chart-containera {  
                     width: 1200px;  
                }       
                .chart-containerb {  
                     width: 1200px;  
                }  
           </style>  
      </head>  
      <body>  
      <h1>Wetter auf einem Balkon in Pankow (Me&szlig;zeit alle Viertelstunde)</h1>  
           <div class="chart-container">  
                <canvas id="mycanvas" height="80"></canvas>  
           </div>  
           <div class="chart-containera">  
                <canvas id="mycanvas2" height="80"></canvas>  
           </div>       
           <div class="chart-containerb">  
                <canvas id="mycanvas3" height="80"></canvas>  
           </div>       
           <!-- javascript -->  
           <script type="text/javascript" src="js/jquery.min.js"></script>  
           <script type="text/javascript" src="js/Chart.min.js"></script>  
           <script type="text/javascript" src="js/linegraph.js"></script>  
      </body>  
 </html>  


Und die "linegraph.js".

 $(document).ready(function(){  
      $.ajax({  
           url : "http://daten.noetigenfalls.de/dht11/dbempfang_dht11.php",  
           type : "GET",  
           success : function(data){  
                console.log(data);  
                /*data = JSON.parse(data);*/  
                var id = [];  
                var datum_mysql = [];  
                var temperatur = [];  
                var luftfeuchte = [];                 
                var wifi = [];  
                for(var i in data) {  
                     id.push(data[i].id);  
                     datum_mysql.push(data[i].datum_mysql);  
                     temperatur.push(data[i].temperatur);  
                     luftfeuchte.push(data[i].luftfeuchte);                      
                     wifi.push(data[i].wifi);  
                }  
                var chartdata = {  
                     labels: datum_mysql,  
                     datasets: [  
                               {  
                               label: "Temperatur in Grad Celsius",  
                               fill: true,  
                               lineTension: 0.1,  
                               backgroundColor: "rgba(255, 255, 255, 0.25)",  
                               borderColor: "rgba(128, 128, 128, 1)",  
                               pointHoverBackgroundColor: "rgba(128, 128, 128, 0.2)",  
                               pointHoverBorderColor: "rgba(0, 0, 0, 0.2)",  
                               data: temperatur,  
                          }/*,  
                               {  
                               label: "id-wifi",  
                               fill: false,  
                               lineTension: 0.1,  
                               backgroundColor: "rgba(29, 202, 255, 0.75)",  
                               borderColor: "rgba(290, 202, 255, 1)",  
                               pointHoverBackgroundColor: "rgba(29, 202, 255, 1)",  
                               pointHoverBorderColor: "rgba(19, 202, 255, 1)",  
                               data: id  
                          }          */            
                     ]  
                };  
                var chartdata2 = {  
                     labels: datum_mysql,  
                     datasets: [  
                               {  
                               label: "Luftfeuchtigkeit in %",  
                               fill: false,  
                               lineTension: 0.1,  
                               backgroundColor: "rgba(29, 202, 255, 0.75)",  
                               borderColor: "rgba(29, 202, 255, 1)",  
                               pointHoverBackgroundColor: "rgba(29, 202, 255, 1)",  
                               pointHoverBorderColor: "rgba(29, 202, 255, 1)",  
                               data: luftfeuchte,  
                               //lineTension: 10  
                          }  
                     ]  
                };       
                     var chartdata3 = {  
                     labels: datum_mysql,  
                     datasets: [  
                               {  
                               label: "WiFi Signal in dbm",  
                               fill: false,  
                               lineTension: 0.1,  
                               backgroundColor: "rgba(255, 255, 255, 0.75)",  
                               borderColor: "rgba(16,78,139, 1)",  
                               pointHoverBackgroundColor: "rgba(16,78,139, 1)",  
                               pointHoverBorderColor: "rgba(16,78,139, 1)",  
                               data: wifi,  
                               steppedLine: true,  
                          }  
                     ]  
                };       
                var ctx = $("#mycanvas");  
                var LineGraph = new Chart(ctx, {  
                     type: 'line',  
                     data: chartdata  
                });  
                var ctz = $("#mycanvas2");  
                var LineGraph = new Chart(ctz, {  
                     type: 'line',  
                     data: chartdata2  
                });       
                var cty = $("#mycanvas3");  
                var LineGraph = new Chart(cty, {  
                     type: 'line',  
                     data: chartdata3  
                });       
           },  
           error : function(data) {  
           }  
      });  
 });  


Test V Betriebsdauer Akku
Getestet wurde ein Akkumulator aus Fernost mit 18 Ah 😀, der sowohl über USB als auch Solar geladen werden kann.
Die Ladezeit per USB dauert mehrere Stunden. Das Laden über das Solarmodul wurde nicht getestet. Warum nicht? Weil die Ladeelektronik im Modul falsch konzipiert ist. Das Paneel lädt nicht. Im Gegenteil, es zieht Strom trotz Sonnenkraft. Wir leben schon in einer verrückten Welt. Ein Solarpaneel, welches Strom verbraucht statt liefert.
Da das Solarpaneel sowieso sehr schmalbrüstig daherkommt, war schon vor dem Kauf klar, dass später hier ein externes Solarmodul angedockt wird.
Im wesentlichen ging es darum, für dieses externe Paneel die Ladeelektronik des Chargers zu nutzen. Aber wie gesagt, nicht brauchbar. Mein Kollege kümmert sich drum und baut das um - will ich doch hoffen 😐.
Interessant ist der Akku als Stromversorgung für ein weitgehend autarkes Sensorsystem. Aus diesem Grund habe ich eine Messreihe durchgeführt die die Kapazität aufzeigen sollte.
Als Verbraucher musste der ESP 8266 01S herhalten. Dieser wird später der Sensorblockwart. Er wird alle erfassten Daten per WiFi an einen Server melden.
Der Aufbau ist sehr simpel. Der ESP steckt schnöde im Akku und funkt alle paar Sekunden die WiFi Verbindungsgüte und die Zeit des Verbindungsaufbaus zwischen den Messungen.
Die Messung ist nicht unbedingt aussagefähig für den zukünftigen Einsatz. Es sind einige Variablen im Spiel, die zukünftig geändert werden.
Zum Beispiel geht der ESP zwischen den Messungen kurz in den Ruhemodus. Er schläft sozusagen. Das ist Blödsinn, weil ein Schlaf im Sekundentakt keinen Sinn macht. Es ging mir nur darum, ob die Software funktioniert.
Des Weiteren ziehen ein paar Parasiten Strom, die später entfallen. Da wären der Development Adapter für den ESP (den brauchte ich, weil der die USB Schnittstelle zum Akku ist), die 4 LEDs und das Solarpaneel.
Dafür kommen später die Verbraucher hinzu, die Sensoren.
Im Bild zu sehen der Versuchsaufbau.
Der ESP sendet oben beschriebene Daten an den Router, der sie an eine Datenbank weiterleitet. Diese Daten können über eine Webseite in Diagrammform abgerufen werden.



Die Messreihe nach 120 Zyklen. Wie gesagt, es werden alle paar Sekunden Daten an den Server geschickt.


Die Messreihe nach 800 Zyklen. Für einen kurzen Zeitraum verbessert sich die Signalstärke um einige dB. Während dieser Zeit war ich mit dem im Betrieb befindlichen Aufbau in einem anderen, dem Router näher befindlichen Zimmer, um den Aufbau zu fotografieren.
Nicht so ideal sind die Ausreißer beim Verbindungsaufbau. Einmal benötigte die kleine Binärkreatur 12 Sekunden, um den Router zu erreichen.



Das finale Ergebnis. Die Grafik ist schon ziemlich verwurschtelt. Auch das gehörte zum Test. Wie gestaltet sich die Optik bei größer werdenden Datenmengen.
Der Akku lieferte Strom für 5964 Datensätze.
Messbeginn: 03.06.2017 – 08:52:47
Messende: 04.06.2017 – 02:34:52. Da brach der Akku erschöpft zusammen.
Das bedeutet bei einer 15 Minütigen Messung eine Laufzeit von ca. zwei Monaten. Dazu muss der aber zwischen den Messungen in den tiefen Schlafmodus. Allerdings, wie schon erwähnt, werden sich hier noch die Variablen ändern und es wird per externem Solarmodul Energie zugeführt. Oder es werden Superkondensatoren als Energiespeicher verwendet, die wesentlich mehr Ladezyklen vertragen. Oder, u.s.w. , und überhaupt. Vielleicht kommt es ja ganz anders … 😀


Test IV "Windkraftanlage"
Test, ob der Balkon als Windkraftanlagestandort taugt.
Eher nicht. Bei der Windstärke im ersten Teil des Films, wird eine Spannung von vielleicht 0,1 Volt erreicht.
Werde noch andere Motoren testen.


Test III Statische IP & ThingSpeak
Die Konfiguration des ESP wurde um zwei Funktionalitäten erweitert. Zum einen wurde von dynamischer auf statische IP umgestellt.
Wenn der ESP auswärtige Daten erfasst ist es Quark, eine statische IP zu verwenden. Die kommt dann zum Einsatz, wenn ich den ESP als fernzusteuerndes Modul verwende.
Des Weiteren habe ich erste Experimente mit ThingSpeak unternommen.
Später sollen ja die Messwerte der Sensoren visualisiert werden. Eine rein tabellarische Listung ist langweilig.
Ich habe schon einige Sensoren bekommen, allerdings haben die alle einen analogen Ausgang. Mein derzeit im Einsatz befindlicher ESP hat keinen analogen Eingang, ergo muss ein höherwertiger her. Zudem habe ich auch noch keinen Multiplexer usw.. Ist aber aufgrund meines Kaufrausches kein Problem. Das wird die nächsten Wochen eintrudeln.
Aber ein Sensor ist dabei, mit dem ich etwas anfangen kann. Ein Lichtsensor, der bei einstellbaren Helligkeitswerten eine 1 oder 0 (HIGH, LOW) ausgibt. Den Sensor gibt es auch mit analogen Ausgang als Vierbeiner. Blöderweise habe ich aber nur die dreibeinige Variante, also nur mit digitalem Ausgang, gekauft. Zu schnell die Kauftaste gedrückt.
In Ermangelung weiterer Sensoren habe ich zusätzlich einen rechnerisch ermittelten Sinus und die Signalstärke des WiFi-Moduls hinzugefügt. Das Auge will ja was geboten bekommen.
Diese Werte werden also vom ESP berechnet bzw. aufgenommen und an ThingSpeak übermittelt, wo daraus eine Kurve generiert wird.
Im Film sieht man drei Signale, die verarbeitet werden.

Sinus: Hier wird im Mikrocontroller die mathematische Sinunsfunktion berechnet und als gefaktes Analogsignal an Thingspeak übergeben.
WiFi Signal: Der Controller ermittelt intern die Signalleistung der WiFi Verbindung und leitet das Ergebnis weiter.
Lichtsensor: EinLichtsensormodul ermittelt die Lichtstärke. Durch verschatten des Sensors wird ein Grenzwert erreicht und er schaltet entweder auf AN oder AUS. Dieses 0 und 1 Signal wird ebenfalls an ThingSpeak übermittelt.
Der Film läuft ab einer bestimmten Sequenz um ein Vielfaches schneller. ThingSpeak gestattet einen Empfang der Signale nur alle 15 Sekunden. Das musste ich im Film raffen.


Test II Erster WiFi Webserverversuch ESP8266-01 S


Test I DSO138 und ESP8266-01 S




Keine Kommentare :

Kommentar veröffentlichen