Heute war es mal wieder an der Zeit den Kopf frei zu bekommen. Dazu ist es stets gut die Bastelkiste aus dem Schrank zu kramen. Darin fand ich neben vielem anderen Kram

  • 4 x NodeMCU 0.9
  • 5 x DHT11
  • PinOut Wires
  • ...

Klar, es gab noch viel mehr in der Kiste zu finden - aber diese 3 Bauteile reichen mir für heute schon mal aus.

Das Ziel

Sobald wir mit diesem Beitrag durch sind, sendet der NodeMCU die per DHT11 gemessene Temperatur und Luftfeuchtigkeit per WiFi mittels POST an Dweed. Von dort aus nutzen wir freeboard.io um die Daten abzuholen und zu visualisieren. Insgesamt wird kaum nennenswert Code benötigt, trotz allem fürge ich den, den ich zusammengestellt habe hier an.

Zutaten

Pro Zimmer benötigen wir jeweils: 1x NodeMCU (0.9) 1x USB Wandadapter (Stromversorgung) 3x Pin Wire (F<-->F) 1x DHT11 1x Micro-USB Kabel

Zubereitung

Zunächst bereiten wir schon mal die Hardware vor. Dazu Verbinden wir folgende Pins der NodeMCU mit den Pins des DHT11

NodeMCU DHT11
V (in) Vin
Gnd Gnd
S (signal) D3

Als nächstes nutzen wir die Arduino (.cc) IDE um unsere Software zu erstellen und auf die NodeMCU zu flashen. Allerdings bringt die Arduino IDE nicht per default die nötige Unterstützung für das board. Daher müssen wir kleine Anpassungen machen.

Öffnet die IDE und wählt in den Einstellungen das Textfeld "Zusätzliche Board-Verwalter URLs" und trägt folgende URL ein: http://arduino.esp8266.com/stable/package_esp8266com_index.json

Das Herzstück - Der Sketch

Der Sketch selbst ist in Windeseile und provisorisch als "proof of concept" entstanden. Hier muss im Laufe der nächsten Tage noch sauber nachgebessert werden. Ihr solltet den code also auf gar keinen Fall 1 zu 1 so übernehmen!

#include <ESP8266WiFi.h>
#include <dht.h>
#include <WiFiClientSecure.h>

// Your work:
// Fill in the credentials matching your setup:
const char* ssid = "YOUR_WIFI_SSID_GOES_HERE";
const char* password = "YOUR_WIFI_PASS_GOES_HERE";

// current humidity and temperature
static double currentHum = 0.0;
static double currentTemp = 0.0;
static int val;

#define relaisPin 16
#define dhtPin  D4

// Create an instance of the humidity and temperature sensor
dht dht11;

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

// Create an instance of the client
const char* host = "dweet.io"; 
const int httpsPort = 443;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "27 6F AA EF 5D 8E CE F8 8E 6E 1E 48 04 A1 58 E2 65 E8 C9 34";

void postValuesToDweet(void);

// Initial setup
void setup() {

  // Init serial communication
  Serial.begin(115200);
  delay(10);

  // prepare GPIO2
  pinMode(relaisPin, OUTPUT);
  digitalWrite(relaisPin, 0);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  // Set Wifi mode to just be client
  WiFi.mode(WIFI_STA);

  // Connect to AP
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

// The main loop
void loop() {

    delay(1000);
    dht11.read11(dhtPin);
    delay(200);

    // fetch temperature and humidity from
    // DHT11
    currentHum = dht11.humidity;
    currentTemp = dht11.temperature;

    postValuesToDweet();

    String ptlnS = "\r\nGPIO is now ";
    ptlnS += (val)?"high":"low";
    ptlnS += "\n";
    ptlnS += "Humidity: ";
    ptlnS += currentHum;
    ptlnS += " hum";
    ptlnS += "\n";
    ptlnS += "Temperature: ";
    ptlnS += currentTemp;
    ptlnS += " °C";
    ptlnS += "\n\n\n";

  Serial.print(ptlnS);
    /* 
     // Step A:
     // uncomment if you want to change pin state
     // according to humidity

    if(currentHum <= 40.0 && val == 0){
      digitalWrite(relaisPin, 0);
    }else{
      digitalWrite(relaisPin,1);
    }
    */

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  // Match the request
  if (req.indexOf("/gpio/0") != -1)
    val = 0;
  else if (req.indexOf("/gpio/1") != -1)
    val = 1;
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  // Set GPIO2 according to the request
  // if uncommented step A: the hum val might override this setting!
  digitalWrite(relaisPin, val);

  client.flush();

  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
  s += (val)?"high":"low";
  s += "<br>";
  s += "Humidity: ";
  s += currentHum;
  s += " hum";
  s += "<br>";
  s += "Temperature: ";
  s += currentTemp;
  s += " °C";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);

  delay(1);

  Serial.println("Client disonnected");

  // The client will actually be disconnected 
  // when the function returns and 'client' object is detroyed 
}

void postValuesToDweet(void)
{
    WiFiClientSecure client;
    Serial.print("connecting to ");
    Serial.println(host);
    if (!client.connect(host, httpsPort)) {
      Serial.println("connection failed");
      return;
    }

    if (client.verify(fingerprint, host)) {
      Serial.println("certificate matches");
    } else {
      Serial.println("certificate doesn't match");
    }

    String url = "/dweet/for/YOUR_THINGS_NAME?t=";
    url += currentTemp;
    url += "&h=";
    url += currentHum;
    Serial.print("requesting URL: ");
    Serial.println(url);

    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

    Serial.println("request sent");
    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line == "\r") {
        Serial.println("headers received");
        break;
      }
    }
    String line = client.readStringUntil('\n');
    if (line.startsWith("{\"this\":\"success\"")) {
      Serial.println("esp8266/Arduino update successfull!");
    } else {
      Serial.println("esp8266/Arduino update has failed");
    }
    Serial.println("reply was:");
    Serial.println("==========");
    Serial.println(line);
    Serial.println("==========");
    Serial.println("closing connection");
 }

Bitte tausch dringend folgende Passagen durch eure eigenen aus:

  • const char* ssid = "YOUR_WIFI_SSID_GOES_HERE";
  • const char* password = "YOUR_WIFI_PASS_GOES_HERE";
  • String url = "/dweet/for/YOUR_THINGS_NAME?t=";

Fingerprint: Den SHA1 Fingerprint könnt ihr für eine URL hier online auslesen: https://www.grc.com/fingerprints.htm Das sollte für Euch aber nur dann von Interesse sein, wenn ihr den Sketch anpasst und eine Verbindung zu einem anderen host als dweet.io aufbaut.

Erste Ergebnisse

Hier angekommen, gibt die NodeMCU die aktuelle Temperatur und Luftfeuchtigkeit schon mal über den Seriellen Monitor bekannt (zyklisch)... Darüber hinaus gibt sie aber auch preis ob sie sich mit dem Wifi Access Point verbinden konnte und welche IP Adresse sie zugewiesen bekommen hat. Letztere können wir verwenden um im Browser bereits die Temperatur zu sehen UND einen GPIO Port zu schalten...

Ihr ruft die entsprechende Seite mit der IP wie folgt auf:

http://IP_AUS_SERIAL_MONITOR/gpio/0 bzw. http://IP_AUS_SERIAL_MONITOR/gpio/1

Darüber hinaus landen sowohl Temperatur als auch Luftfeuchte bereits auf Dweet.io. Dort erreicht ihr eure Daten mit dem Link https://dweet.io/follow/YOUR_THINGS_NAME --> YOUR_THINGS_NAME muss natürlich durch euren "thing name" wie im Quellcode ausgetauscht werden.

Visualisierung in freeboard

In der rechten oberen Ecke eures "Things" auf der dweet Seite findet ihr einen Button. Klickt ihr diesen, wird euch der Sensor direkt in freeboard.io angelegt. Nun noch etwas mit dem Anzeigetyp (ich verwende Gauge) spielen und schon sollte das Ergebnis wie folgt aussehen:

BTW: Solltet Ihr eure Daten nicht extern versenden wollen, oder die NodeMCU gar nicht erst in eurem lokalen Netzwerk einbuchen, könnt Ihr den Sketch abwandeln und mittels anderem Wifi.mode(YOUR_MODE); ohne probleme den Spieß umdrehen. Dann müsstet Ihr euch zum auslesen der Werte vom Endgerät aus an der NodeMCU per WiFi anmelden und dort den Webserver nach den aktuellen Werten befragen.

Previous Post Next Post