Ferntemperatursensor mit permanenter Anzeige in Ihrem Haus

Mit Wemo D1 ESP8266

Die meisten von uns verwenden eine Telefon-App, um die Außentemperatur zu sehen – was in Ordnung ist, wenn es Ihnen nichts ausmacht, einen Messwert von einem Sensor zu erhalten, der sich irgendwo in der Nähe einer meteorologischen Station befindet.

Und wenn wir schließlich unsere eigenen IoT-Sensoren einrichten, müssen wir eine App öffnen oder uns auf einer Webseite anmelden, um sie zu sehen.

Kein Gerät erforderlich

Aber was, wenn Sie die Temperatur außerhalb Ihres eigenen Hauses wissen möchten, ohne ein Gerät zu öffnen? Sie möchten, dass Ihre Außentemperatur dauerhaft in Ihrem Haus angezeigt wird , damit Sie sie sehen können, wann immer Sie wollen und wo immer Sie sie sehen wollen. (Auch in mehreren Räumen…)

Dieser Beitrag erklärt, wie es geht. Ein Außentemperatursensor sendet seinen Messwert an einen Bildschirm im Haus. Es ist alles mit preiswerten Komponenten und ein paar Drähten und Anschlüssen erledigt. Wenn Sie bereits einen Raspberry Pi haben, sind Sie schon fast am Ziel.

Komponenten

Das Prinzip

Jede halbe Stunde (oder ein anderer benutzerdefinierter Zeitraum) erwacht der externe Wemos D1 aus dem Tiefschlaf, liest die Temperatur vom DS18B20 und überträgt dann die Daten per MQTT-Protokoll an den MQTT Server (Raspberry Pi) .

Der MQTT-Server empfängt die Daten und sendet sie dann an die MQTT- abonnierten Geräte – in diesem Fall die anderen Wemos D1 mini(s). Letztere zeigt dann die Temperatur auf dem SSD1306-OLED Bildschirm an.

Da das Wemos / Screen-Setup nur etwa 10€ kostet, kann eine beliebige Anzahl dieser Geräte im Haus aufgestellt werden und sie werden alle gleichzeitig aktualisiert.

RasPi als MQTT Server einrichten

Vorrausetzung ist ein MQTT Server welcher auf einen Raspberry oder vServer laufen kann. Es gibt unzählige Anleitungen im Internet wie ein MQTT Server installiert wird, deshalb gehe ich hierauf nicht ein. Schau doch einfach mal hier.

Zwei Dinge möchte ich hervorheben:

  • Verstehen Sie die Konzepte des Abonnierens und Veröffentlichens in MQTT, da wir sie beim Programmieren unserer Wemos D1-Minis benutzen werden.
  • Wenn auf dem MQTT-Server einen Benutzernamen und ein Passwort gesetzt ist, dann muss dieses im Wemos-Sketch eingetragen werden.

Einrichten des Wemos D1 mini mit dem DS18B20 Temperatursensor

Der DS18B20 ist ein wirklich einfach zu handhabender Sensor. Achten Sie beim Kauf darauf, dass Sie die wasserdichte Version erhalten, da die Indoor-Version den Elementen nicht lange standhält. Schließen Sie den Sensor wie folgt an den Wemos an:

DS18B20 Anschaltung Wemo D1 ESP8266

Dies ist eine NodeMCU, aber es ist das gleiche Prinzip wie der Wemos. Schließen Sie den 4,7k-Widerstand als Pull-up für den Data des Sensors an.

Einrichten des Wemos D1 mini mit dem OLED SSD1306-Bildschirm

In meinem Setup habe ich die SSD1306 an den Wemos 3,3-V-Ausgang angeschlossen. Einige OLED vertragen keine 5V

Das Skript für die Ausseneinheit

Dieses Skript wacht alle 30 Minuten aus dem Tiefschlaf auf, liest die Temperatur des DS18B20 aus, stellt eine Verbindung zum WLAN her und sendet die MQTT-Daten in einem Topic zum MQTT-Server.

Sie müssen Ihre WLAN-Anmeldeinformationen sowie Ihren Benutzernamen und Ihr Passwort für Ihren MQTT-Server und das von Ihnen gewählte TOPIC im Skript anpassen.

// Michael Diamond and Allan Shwartz

#include <OneWire.h>            // to connect to the OneWire temp. sensor
#include <DallasTemperature.h>  // temperature sensor driver
#include <ESP8266WiFi.h>        // for WiFi Client class
#include <PubSubClient.h>       // for MQTT PubSubClient class

// Update these with values suitable for your network.

const char *ssid = "Your_WiFi_Name_Here";       // your WiFi name goes here  
const char *password = "Your_WiFi_Password_Here";    // your WiFi password goes here  
const char *mqtt_server = "192.168.x.x"; // IP address of the MQTT server/Raspberry PI  
// Declaration of (instantiation of) a WiFiClient called espClient
WiFiClient espClient;

// Declaration of (instantiation of) a PubSubClient called client
PubSubClient client(espClient);

// GPIO where the DS18B20 temperature sensor is connected to
const int oneWireBus = 4;

// Setup a OneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our OneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);

// constants needed for millisecond timing
const unsigned long SECOND = 1000;  
const unsigned long MINUTE = (60 * SECOND);  
// Push data at this interval
const unsigned long deepSleep_ms = 30 * MINUTE;


//----------------------------------------------------------------------
//  setup() function
//
//  ... setup the Serial class, the Wifi, and the Publish-Subscribe Client
//----------------------------------------------------------------------
void setup()  
{
    // start the Serial Monitor
    Serial.begin(115200);
    // setup the temperature probe
    pinMode(2, OUTPUT);
    // setup the networking functions
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    // Start the DS18B20 temperature sensor
    sensors.begin();
}


// ----------------------------------------------------------------------
//  setup_wifi() function
//
//  ... connect this ESP node to the House WiFi network
//      we only call this once at "setup-time"
//----------------------------------------------------------------------
void setup_wifi() {

    delay(10);
    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

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

    randomSeed(micros());

    // networking is successfully up
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}


//----------------------------------------------------------------------
//  reconnect() function
//
//  ... The connection to the MQTT server must constantly be checked
//      if it is down, reconnect
//----------------------------------------------------------------------
void reconnect()  
{
    // Loop until we're reconnected
    while (!client.connected())
    {
        Serial.print("Attempting MQTT connection...");
        // Give each ESP its own client name. If they are all the same, it'll repeatedly connect.
        String clientId = "RemoteTempSensor";

        // Attempt to connect
        if (client.connect("Your_topic", "your_MQTT_user", "you_MQTT_PW"))
        {
            Serial.println("connected");
            // Once connected, publish an announcement...
            //     client.publish("Your_topic", tempString, "ºC");
        }
        else
        {
            // if our connection attempt fails, print some debugging to the Arduino console
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5 * SECOND);
        }
    }
}


//----------------------------------------------------------------------
//  loop() function
//
//  ... actually the most important function here.
//----------------------------------------------------------------------
void loop()  
{
    // we must be vigilant in keeping our MQTT connection up
    if (!client.connected())
    {
        reconnect();
    }

    // call the loop function of the Publish-Subscribe client
    client.loop();

    // now read the temperatures
    sensors.requestTemperatures();
    float temperatureC = sensors.getTempCByIndex(0);

    // display on the Arduio console ... just as a debugging tool
    Serial.print(temperatureC);
    Serial.println("ºC");

    // we need to convert this into a text string to transmit
    char text[8];
    dtostrf(temperatureC, 1, 1, text);

    // publish this text to our MQTT server
    client.publish("Your_topic", text, "ºC");
    delay(SECOND);   // to insure the packet gets out

    // now go into a power-saving deep sleep for 30 minutes
    ESP.deepSleep(deepSleep_ms);
}

Skript für die Innenstation

Dieses Skript abonniert auf dem MQTT-Server das Topic für den AußensensorsWenn der Außensensor seine Daten sendet, so empfängt der MQTT Server die Daten und sendet diese an die Geräte welche den TOPIC abonniert haben.
Sobald die Daten empfangen wurden, so werden die Daten auf dem Display angezeigt.

Auch hier müssen Sie Ihre WLAN-Zugangsdaten in das Skript schreiben, sowie Ihren Benutzernamen und Ihr Passwort für Ihren MQTT-Server und das von Ihnen gewählte Topic .

// Michael Diamond and Allan Shwartz

#include <Wire.h>             // to connect to I2C screen
#include <Adafruit_GFX.h>     // for screen graphics
#include <Adafruit_SSD1306.h> // for Adafruit_SSD2306 class
#include <ESP8266WiFi.h>      // for WiFiClient class
#include <PubSubClient.h>     // for MQTT PubSubClient class
#define SCREEN_WIDTH 128      // OLED display width, in pixels
#define SCREEN_HEIGHT 64      // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Update these with values suitable for your network.

const char *ssid = "Your_WiFi_Name_Here";       // your WiFi name goes here  
const char *password = "Your_WiFi_Password_Here";    // your WiFi password goes here  
const char *mqtt_server = "192.168.x.x"; // IP address of the MQTT server/Raspberry PI

// Declaration of (instantiation of) a WiFiClient called espClient
WiFiClient espClient;

// Declaration of (instantiation of) a PubSubClient called client
PubSubClient client(espClient);

// constants needed for millisecond timing
const unsigned long SECOND = 1000;  
const unsigned long MINUTE = (60 * SECOND);

//----------------------------------------------------------------------
//  setup() function
//
//  ... setup the Serial class, the Wifi, and the Publish-Subscribe Client
//----------------------------------------------------------------------
void setup()  
{
    // start the Serial Monitor
    Serial.begin(115200);
    // setup the networking functions
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    // set the callback function ... to be called when we get a message
    client.setCallback(callback);
}


//----------------------------------------------------------------------
//  setup_wifi() function
//
//  ... connect this ESP node to the House WiFi network
//      we only call this once at "setup-time"
//----------------------------------------------------------------------
void setup_wifi()  
{
    delay(10);
    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    // continue to try to connect to the WiFi, showing connection attempts
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    // networking is successfully up
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}


//----------------------------------------------------------------------
//  callback() function
//
//  ... we have received a message from the MQTT server
//      display it.  repaint the SSD1306 screen
//----------------------------------------------------------------------
void callback(String topic, byte *payload, unsigned int length)  
{

    Serial.print("Message arrived on topic: ");
    Serial.print(topic);
    Serial.print(". Message: ");

    // the payload is a "byte-stream".  Convert this to a printable String object
    String message;
    for (int i = 0; i < length; i++)
    {
        message += (char)payload[i];
    }
    Serial.println(message); // debug print on our Arduino console

    // We have our RemoteTemp MQTT message, we want to display

    if (topic == "Your_topic")
    {

        // restart the SSD1306 screen with a call to .begin()
        if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
        {   // Address 0x3D for 128x64
            Serial.println(F("SSD1306 allocation failed"));
            for (;;)
                ; // infinite loop on failure
        }

        // repaint the SSD1306 OLED screen using various Adafruit_SSD1306 functions
        delay(50000); // delay 50 seconds (otherwise is blinks too much)
        display.clearDisplay();
        display.setTextColor(WHITE);
        display.setTextSize(1);
        display.setCursor(2, 0);
        display.println("Temperature Celcius");
        display.setTextSize(4);
        display.setCursor(10, 20);
        // Display static text
        display.println(message); // This is the content to display
        display.display();
    }
}


//----------------------------------------------------------------------
//  reconnect() function
//
//  ... The connection to the MQTT server must constantly be checked
//      if it is down, reconnect
//----------------------------------------------------------------------
void reconnect()  
{

    // Loop until we're reconnected
    while (!client.connected())
    {
        Serial.print("Attempting MQTT connection...");
        // Give each ESP its own client name. If they are all the same, it'll repeatedly connect.
        String clientId = "Your_topic";

        // Attempt to connect
        if (client.connect("TopicName", "Your_MQTT_User", "Your_MQTT_Password"))
        {
            Serial.println("connected");
            client.subscribe("Your_topic");
        }
        else
        {
            // if our connection attempt fails, print some debugging to the Arduino console
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5 * SECOND);
        }
    }
}


//----------------------------------------------------------------------
//  loop() function
//
//  ... actually the most important function here.
//----------------------------------------------------------------------
void loop()  
{
    unsigned long loopTime_ms = millis();

    // we must be vigilant in keeping our MQTT connection up
    if (!client.connected())
    {
        reconnect();
    }

    // call the loop function of the Publish-Subscribe client
    client.loop();

    // we want to do this "loop" function once a minute
    while ((unsigned long)(millis() - loopTime_ms) < (1 * SECOND))
        ;   // wait for the minute to be over
}

Stromversorgung der Außenstation mit Solarpanel

Aufgrund seiner relativ hohen Stromentnahme während der WLAN-Aktivierung ist der ESP8266 notorisch schwierig aus der Ferne mit Strom zu versorgen. Ich habe das relativ leicht umgangen.

Erstens kann das Board durch Überbrücken der Pins RST und D0 auf dem Wemos in den vollständigen Tiefschlaf wechseln. Dies bedeutet, dass zwischen jedem Wakeup ein vernachlässigbarer Stromverbrauch besteht.

Als Stromversorgung kommt ein 18650-Akku Board zum Einsatz, das den Wemo über den USB-Ausgang mit Strom versorgt – und auch das Laden und Entladen des Akkus steuert, um alles Autark zu Betreiben kommt ein 5V Solarpanel zum Einsatz welches Akku zusätzlich nachlädt.

Ich habe die Anleitung hier gefunden und ins Deutsche übersetzt und einige Sachen angepasst.

Viel Spass beim Nachbauen.

vy 73 Jens