Sensoren – Pollux Labs https://polluxlabs.net Arduino, ESP32 & ESP8266 | Projekte & Tutorials Wed, 06 Nov 2024 11:10:49 +0000 de hourly 1 https://wordpress.org/?v=6.6.2 https://polluxlabs.net/wp-content/uploads/2020/05/cropped-pollux-labs-p-32x32.png Sensoren – Pollux Labs https://polluxlabs.net 32 32 MQTT (Teil4): Sichere Kommunikation zwischen Geräten https://polluxlabs.net/esp8266-projekte/mqtt-teil4-sichere-kommunikation-zwischen-geraeten/ Thu, 10 Oct 2024 08:42:42 +0000 https://polluxlabs.net/?p=17423 MQTT (Teil4): Sichere Kommunikation zwischen Geräten Weiterlesen »

]]>
In den letzten Teilen der MQTT-Reihe hast du schrittweise die Kommunikation zwischen zwei ESP8266 eingerichtet und Sensordaten ausgetauscht. Ein wichtiger Baustein fehlt allerdings noch: die sichere Kommunikation. Wenn du nicht sicherstellst, dass der Austausch von Daten privat bleibt, könnte sich jemand in dein System einschleusen und einiges Chaos stiften.

In diesem Tutorial lernst du, wie du eine Authentifizierung integrierst, sodass deine ESP8266 einen Benutzernamen und ein Passwort benötigen, um mit dem MQTT-Broker kommunizieren zu können. Das bietet zwar immer noch keine 100% Sicherheit (falls es diese überhaupt gibt), aber wenn wir davon ausgehen, dass du keine kritischen Anwendungen mit MQTT aufbaust, sollte diese Authentifizierung schon ein großer Schritt in die richtige Richtung sein.

Konfiguration des MQTT-Brokers

Zunächst müssen wir den Mosquitto-Broker auf dem Raspberry Pi konfigurieren, um die Authentifizierung zu aktivieren.

Schritt 1: Erstellen der Passwortdatei

Hierfür verwendest du den Befehl mosquitto_passwd, um eine Passwortdatei zu erstellen und Benutzer hinzuzufügen. Gib im Terminal den folgenden Befehl ein – ersetze hierbei <username> mit einem Benutzernamen deiner Wahl:

sudo mosquitto_passwd -c /etc/mosquitto/passwd <username>

Anschließend wirst du aufgefordert, ein Passwort einzugeben. Dieses sollte natürlich möglichst sicher sein – Tipps für sichere Passwörter findest du z.B. auf der Webseite des BSI. Dieses Passwort wirst du später noch in den Sketches der ESP8266 benötigen.

Falls du noch einen weiteren Benutzer anlegen möchtest, ohne die Passwortdatei erneut zu erstellen, verwenden den folgenden Befehl, in dem du <username> und <password> entsprechend ersetzt:

sudo mosquitto_passwd -b /etc/mosquitto/passwd <username> <password>

Schritt 2: Konfiguration von Mosquitto

Nun widmest du dich der Konfigurationsdatei von Mosquitto, die du mit dem folgenden Befehl öffnest:

sudo nano /etc/mosquitto/mosquitto.conf

Füge am Ende der Datei die folgenden Zeilen hinzu:

allow_anonymous false
password_file /etc/mosquitto/passwd

Mit diesen beiden Zeilen deaktivierst du den anonymen Zugriff und gibst den Pfad zur Passwortdatei an.

Schritt 3: Neustart des Mosquitto-Dienstes

Sollte dein MQTT-Broker noch laufen, starte ihn mit dem folgenden Befehl neu, um deine Änderungen zu übernehmen:

sudo systemctl restart mosquitto

Konfiguration der ESP8266-Clients

Nun kommen die beiden ESP8266 dran. Hier änderst du deine Sketches, sodass sie sich mit Benutzernamen und Passwort beim Broker authentifizieren. Entscheiden sind die folgenden Änderungen. Zunächst die Integration des Benutzernamen und zugehörigen Passworts, dass du anfangs erstellt hast – hinterlege diese Informationen am Anfang des Sketchs (hinter den Infos zu WLAN und IP-Adresse des Raspberry Pis):

const char* mqtt_user = "Dein_MQTT_Benutzername";
const char* mqtt_password = "Dein_MQTT_Passwort";

Diese beiden Konstanten verwendest du anschließend, wenn der ESP8266 sich mit dem Broker verbinden möchte. Die Funktion reconnect() aus den vorherigen Teilen sieht dann folgendermaßen aus:

void reconnect() {
  while (!client.connected()) {
    Serial.print("Verbinde mit MQTT...");
    if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
      Serial.println("verbunden");
      client.subscribe("esp8266/light");
    } else {
      Serial.print("Fehler, rc=");
      Serial.print(client.state());
      Serial.println(" Nächster Versuch in 5 Sekunden");
      delay(5000);
    }
  }
}

Passe deine Sketches für die ESP8266 nun an und teste die Verbindung. Funktioniert alles wie vorher? Dann hast du ein MQTT-System jetzt erfolgreich abgesichert!

]]>
Raspberry Pi Webserver mit Flask https://polluxlabs.net/raspberry-pi-projekte/raspberry-pi-webserver-mit-flask/ Tue, 01 Oct 2024 10:04:56 +0000 https://polluxlabs.net/?p=16293 Raspberry Pi Webserver mit Flask Weiterlesen »

]]>
Hier auf Pollux Labs findest du bereits ein Tutorial für einen ESP8266 Webserver – in diesem Projekt programmierst du jedoch einen Raspberry Pi Webserver. Dieser wird regelmäßig Messdaten von einem ESP8266 empfangen und auf einer Webseite anzeigen. Neben einem Raspberry Pi benötigst du für dieses Tutorial nur noch einen Sensor – ich verwende im Folgenden den BMP180, um Temperatur und Luftfeuchtigkeit zu messen.

Außerdem verwende ich das Python-Modul Flask, um den Webserver zu programmieren. Damit kannst du sowohl einfache Webseiten erstellen als auch komplexere Applikationen, mit denen du, wie in unserem Fall, Hardware steuern und Messdaten anzeigen kannst.

Eine erste Webseite mit Flask

Bevor du dich einem Webserver widmest, lass uns mit den Grundlagen anfangen. Falls du Flask noch nicht auf deinem Raspberry Pi installiert hast, hole das im Terminal nach:

pip install Flask

Öffne nun einen Editor (z.B. Visudal Studio Code) und erstelle ein Python-Script mit folgendem Inhalt:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Hallo, Raspberry Pi!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Speichere es anschließend ab unter einem Namen deiner Wahl und starte es. Solltest du im Terminal daraufhin die Fehlermeldung “Port 5000 is in use by another program.” erhalten, wähle hinter port= eine andere Zahl, zum Beispiel 5010. Sobald das Script ordnungsgemäß auf einem freien Port läuft, siehst du im Terminal die IP-Adresse deines Raspberry Pis. Zum Beispiel: “Running on http://127.0.0.1:5010”

Ausgabe des Servers im Terminal

Wenn du die IP-Adresse (127.0.0.1:5010) kopierst und sie im Browser öffnest, solltest du den kleinen Gruß sehen, der im Code hinterlegt ist. Neben dieser IP-Adresse erhältst du auch eine Alternative – hier 192.168.0.143:5000. Falls sich die erste Adresse nicht öffnen lässt, probiere es einmal mit dieser.

So funktioniert der code

Lass uns nun einen genaueren Blick auf das Python-Script werfen, um zu verstehen, was dort passiert. Zunächst importierst du die Klasse Flask (Mehr über Flask) aus dem gleichnamigen Modul:

from flask import Flask

Anschließend erstellst du eine Instanz dieser Klasse namens app. Mit (__name__) dahinter teilst du Python mit, dass alle etwaigen zusätzlichen Dateien im selben Ordner liegen, wie das Script selbst. Dazu später mehr.

Die folgenden drei Zeilen

@app.route('/')
def home():
    return "Hallo, Raspberry Pi!"

stellen nun die Webseite bereit – in unserem Fall ist das nur eine einzelne Startseite. Mit dem sogenannten Dekorator @app.route(‘/’) bestimmst du, was passiert, wenn diese Startseite aufgerufen wird – also einfach nur die IP-Adresse. Hierfür dient der Schrägstrich /.

Wenn das nun also passiert (so wie du es vorhin im Browser getan hast), dann wird die darauf folgende Funktion def home(): aufgerufen. Darin befindet sich einfach nur die Anweisung, den String Hallo, Raspberry Pi! wiederzugeben – den du dann im Browser siehst. Später folgen nun noch weitere Dekoratoren und Funktionen, die deinem Raspberry Pi Webserver mehr Leben einhauchen werden.

Zuletzt die beiden Zeilen

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Dieser Code wird ausgeführt, wenn wir dieses Skript direkt ausführen (anstatt es als Modul in ein anderes Script zu importieren). In dem Fall startet der Webserver von Flask, der auf Anfragen von jedem Gerät im gleichen WLAN-Netzwerk am Port 5000 reagiert.

Sensordaten empfangen und anzeigen

So ein kleiner Gruß ist ja nett, aber eine wirklich praktische Anwendung ist besser. Wie wäre es, wenn dein Raspberry Pi Webserver regelmäßig Daten von einem ESP8266 empfängt und diese auf einer Webseite anzeigt?

Im Folgenden lernst du, wie du mit dem Sensor BMP180 an einem ESP8266 die Temperatur und Luftfeuchtigkeit misst und die Messdaten an den Raspberry Pi sendest. Du selbst kannst die aktuellen Daten dann auf einer Webseite einsehen.

Temperatur und Luftdruck auf dem Raspberry Pi Webserver

Hierfür benötigst du zweimal Code – einmal für den Raspberry Pi Webserver und einen Sketch für den ESP8266.

Das Python-Script für den Server

Zunächst kümmern wir uns um den Server. Damit dein Raspberry Pi die Daten in Empfang nehmen und auf einer Webseite anzeigen kann, ist nicht viel Code nötig. Du benötigst im Prinzip eine Funktion, die die gesendeten Messdaten entgegennimmt und eine weitere, um diese auf einer Webseite anzuzeigen. Hier das vollständige Script:

//Raspberry Pi Webserver
//polluxlabs.net

from flask import Flask, request, render_template_string
from datetime import datetime

app = Flask(__name__)

temperature = 0
pressure = 0
last_update = "Noch keine Daten empfangen"

@app.route('/update-sensor', methods=['POST'])
def update_sensor():
    global temperature, pressure, last_update
    temperature = request.form.get('temp')
    pressure = request.form.get('pressure')
    last_update = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    return "Daten aktualisiert", 200

@app.route('/')
def index():
    html = """
    <!DOCTYPE html>
    <html lang="de">
    <head>
        <meta charset="UTF-8">
        <title>BMP180 Sensordaten</title>
    </head>
    <body>
        <h1>BMP180 Sensordaten</h1>
        <p>Temperatur: {{ temperature }}°C</p>
        <p>Luftdruck: {{ pressure }} hPa</p>
        <p>Letzte Aktualisierung: {{ last_update }}</p>
    </body>
    </html>
    """
    return render_template_string(html, temperature=temperature, pressure=pressure, last_update=last_update)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Kopiere den obigen Code uns speichere ihn in einer Date, die du z.B. webserver.py nennst.

So funktioniert das Script

Ein kurzer Blick auf die Funktionsweise des Raspberry Pi Webservers:

Daten empfangen

Der Teil des Scripts, der neue Daten empfängt, sieht so aus:

   @app.route('/update-sensor', methods=['POST'])
   def update_sensor():
       global temperature, pressure, last_update
       temperature = request.form.get('temp')
       pressure = request.form.get('pressure')
       last_update = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
       return "Daten aktualisiert", 200
  • Dieser Code wartet auf neue Messwerte vom Sensor.
  • Wenn neue Daten ankommen, werden sie in den Variablen temperature und pressure gespeichert.
  • last_update speichert den Zeitpunkt, an dem die Daten ankamen.

Daten anzeigen

Die Webseite, die die Daten anzeigt, wird hier erstellt:

   @app.route('/')
   def index():
       html = """
       <!DOCTYPE html>
       <html lang="de">
       <head>
           <meta charset="UTF-8">
           <title>BMP180 Sensordaten</title>
       </head>
       <body>
           <h1>BMP180 Sensordaten</h1>
           <p>Temperatur: {{ temperature }}°C</p>
           <p>Luftdruck: {{ pressure }} hPa</p>
           <p>Letzte Aktualisierung: {{ last_update }}</p>
       </body>
       </html>
       """
       return render_template_string(html, temperature=temperature, pressure=pressure, last_update=last_update)
  • Dieser Code erstellt eine einfache Webseite mithilfe von HTML.
  • Die Seite zeigt die aktuelle Temperatur, den Luftdruck und die Zeit der letzten Aktualisierung an.

Webseite einrichten

Der Server wird hier gestartet:

   if __name__ == '__main__':
       app.run(host='0.0.0.0', port=5000, debug=True)
  • Diese Zeilen starten den Webserver.
  • host='0.0.0.0' bedeutet, dass der Server von anderen Geräten im Netzwerk erreichbar ist.
  • port=5000 legt fest, dass die Webseite über Port 5000 erreichbar ist.

So arbeiten alle Teile zusammen: Der Sensor sendet Daten, das Script empfängt und speichert sie, und die Webseite zeigt sie an.

Starte den Raspberry Pi WebServer

Öffne nun auf deinem Raspberry Pi das Terminal und öffne dein Script, wobei du natürlich den Script-Namen verwendest, den du vergeben hast:

python3 webserver.py 

Anschluss des BMP180 und der Sketch für den ESP8266

Nun zum Sender, dem ESP8266, der mit dem Sensor BMP180 die aktuelle Temperatur und Luftfeuchtigkeit misst und an den Raspberry Pi weiterleitet. Bevor wir zum Code kommen, hier eine Skizze, wie du den Sensor am ESP8266 anschließt:

BMP180 am ESP8266 angeschlossen

Wenn du den Sensor angeschlossen hast, kann es direkt mit dem Sketch weitergehen. Nur ein Hinweis vorab: Solltest du noch nie ein Projekt mit dem BMP180 gebaut haben, fehlt dir vermutlich noch die zugehörige Bibliothek. Öffne in diesem Fall den Bibliotheksmanager in der Arduino IDE und installiere die Bibliothek Adafruit BMP085 Library. Falls du gefragt wirst, ob du weitere benötigte Bibliotheken installieren möchtest, antworte bitte mit Ja.

Doch nun zum Sketch:

//Sending data to the Raspberry Pi Webserver
//polluxlabs.net

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>

const char* ssid = "DEIN NETZWERK";
const char* password = "DEIN PASSWORT";
const char* serverName = "http://SERVER-IP/update-sensor";

Adafruit_BMP085 bmp;

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  Serial.println("Verbinde mit WLAN");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Verbunden mit IP-Adresse: ");
  Serial.println(WiFi.localIP());

  if (!bmp.begin()) {
    Serial.println("BMP180 nicht gefunden, überprüfen Sie die Verkabelung!");
    while (1) {}
  }
}

void loop() {
  if(WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    HTTPClient http;

    float temperature = bmp.readTemperature();
    float pressure = bmp.readPressure() / 100.0F;

    // Daten für den POST-Request vorbereiten
    String httpRequestData = "temp=" + String(temperature) + "&pressure=" + String(pressure);

    // HTTP POST Request senden
    http.begin(client, serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    int httpResponseCode = http.POST(httpRequestData);

    if (httpResponseCode > 0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Fehler code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }
  else {
    Serial.println("WiFi getrennt");
  }

  delay(30000);  // Alle 30 Sekunden senden
}

So funktioniert der Sketch

Werfen wir nun einen Blick auf die einzelnen Bestandteile des Sketchs.

Einbindung der Bibliotheken

Am Anfang werden verschiedene Bibliotheken eingebunden, die für die WiFi-Verbindung, HTTP-Anfragen und die Kommunikation mit dem BMP180 Sensor benötigt werden.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>

Konfiguration

Anschließend legst du die WLAN-Zugangsdaten (SSID und Passwort) fest und hinterlegst die Adresse des Raspberry Pi Webservers. Ersetze hierbei SERVER-IP zum Beispiel durch 192.168.0.143:5000.

const char* ssid = "NETZWERK";
const char* password = "PASSWORT";
const char* serverName = "http://SERVER-IP/update-sensor";

Adafruit_BMP085 bmp;

Setup-Funktion

Hier stellst du die Verbindung zum WLAN her und initialisierst den Sensor:

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Verbinde mit WLAN");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Verbunden mit IP-Adresse: ");
  Serial.println(WiFi.localIP());

  if (!bmp.begin()) {
    Serial.println("BMP180 nicht gefunden, überprüfen Sie die Verkabelung!");
    while (1) {}
  }
}

Loop-Funktion

Nun zum Kern, hier prüfst du zunächst, ob die Internetverbindung steht, liest Temperatur und Luftdruck ein und sendest die Messdaten an den Raspberry Pi Webserver per HTTP POST. Anschließend prüfst du die Antwort des Servers, kappst die Verbindung zum WLAN und wartest 30 Sekunden bis zur nächsten Messung.

void loop() {
  if(WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    HTTPClient http;

    float temperature = bmp.readTemperature();
    float pressure = bmp.readPressure() / 100.0F;

    // Daten für den POST-Request vorbereiten
    String httpRequestData = "temp=" + String(temperature) + "&pressure=" + String(pressure);

    // HTTP POST Request senden
    http.begin(client, serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    int httpResponseCode = http.POST(httpRequestData);

    // Überprüfung der Antwort
    if (httpResponseCode > 0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Fehler code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }
  else {
    Serial.println("WiFi getrennt");
  }

  delay(30000);  // Alle 30 Sekunden senden
}

Lade den Sketch nun auf deinen ESP8266. Wenn du nun die IP-Adresse des Raspberry Pi Webservers in einem Browser öffnest, solltest du bald darauf die aktuellen Messdaten des ESP8266 darauf sehen.

Hübsche die Webseite etwas auf

Klappt alles? Dann wäre vielleicht eine etwas ansprechendere Webseite eine gute Idee. Im Prinzip sind dir hier keine Grenzen gesetzt, du kannst hier mit HTML und CSS schalten und walten wie du möchtest. Eine weiteres Layout inklusive eines Graphen für den Verlauf der Messdaten könnte z.B. dieses hier sein:

Webseite mit Temperatur und Luftdruck

Das zugehörige Python-Script sieht folgendermaßen aus:

//Raspberry Pi Webserver
//polluxlabs.net

from flask import Flask, request, jsonify, render_template_string
from datetime import datetime
import json

app = Flask(__name__)

temperature = 20.0
pressure = 1013.25
last_update = "Noch keine Daten empfangen"
history = []

@app.route('/update-sensor', methods=['POST'])
def update_sensor():
    global temperature, pressure, last_update, history
    temperature = float(request.form.get('temp'))
    pressure = float(request.form.get('pressure'))
    last_update = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    history.append({"time": last_update, "temperature": temperature, "pressure": pressure})
    if len(history) > 10:
        history.pop(0)
    
    return "Daten aktualisiert", 200

@app.route('/get-data')
def get_data():
    return jsonify({
        "temperature": temperature,
        "pressure": pressure,
        "last_update": last_update,
        "history": history
    })

@app.route('/')
def index():
    html = """
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BMP180 Sensordaten Dashboard</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        :root {
            --primary-color: #3498db;
            --secondary-color: #2c3e50;
            --background-color: #ecf0f1;
            --card-background: #ffffff;
        }
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: var(--secondary-color);
            background-color: var(--background-color);
            margin: 0;
            padding: 0;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        header {
            background-color: var(--primary-color);
            color: white;
            text-align: center;
            padding: 1rem;
            margin-bottom: 2rem;
        }
        h1 {
            margin: 0;
        }
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
        }
        .card {
            background-color: var(--card-background);
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            padding: 20px;
            text-align: center;
        }
        .card-title {
            font-size: 1.2rem;
            color: var(--secondary-color);
            margin-bottom: 10px;
        }
        .card-value {
            font-size: 2.5rem;
            font-weight: bold;
            color: var(--primary-color);
        }
        .card-icon {
            font-size: 3rem;
            margin-bottom: 10px;
            color: var(--primary-color);
        }
        #updateTime {
            text-align: center;
            margin-top: 20px;
            font-style: italic;
        }
        #chart {
            width: 100%;
            height: 300px;
        }
    </style>
</head>
<body>
    <header>
        <h1>BMP180 Sensordaten Dashboard</h1>
    </header>
    <div class="container">
        <div class="dashboard">
            <div class="card">
                <i class="fas fa-thermometer-half card-icon"></i>
                <div class="card-title">Temperatur</div>
                <div class="card-value" id="temperature">--</div>
                <div>°C</div>
            </div>
            <div class="card">
                <i class="fas fa-tachometer-alt card-icon"></i>
                <div class="card-title">Luftdruck</div>
                <div class="card-value" id="pressure">--</div>
                <div>hPa</div>
            </div>
        </div>
        <div class="card" style="margin-top: 20px;">
            <canvas id="chart"></canvas>
        </div>
        <div id="updateTime">Letzte Aktualisierung: <span id="lastUpdate">--</span></div>
    </div>

    <script>
        let chart;

        function updateData() {
            fetch('/get-data')
                .then(response => response.json())
                .then(data => {
                    document.getElementById('temperature').textContent = data.temperature.toFixed(1);
                    document.getElementById('pressure').textContent = data.pressure.toFixed(2);
                    document.getElementById('lastUpdate').textContent = data.last_update;
                    
                    updateChart(data.history);
                });
        }

        function updateChart(history) {
            const ctx = document.getElementById('chart').getContext('2d');
            
            if (chart) {
                chart.destroy();
            }
            
            chart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: history.map(entry => entry.time),
                    datasets: [{
                        label: 'Temperatur (°C)',
                        data: history.map(entry => entry.temperature),
                        borderColor: 'rgb(255, 99, 132)',
                        tension: 0.1
                    }, {
                        label: 'Luftdruck (hPa)',
                        data: history.map(entry => entry.pressure),
                        borderColor: 'rgb(54, 162, 235)',
                        tension: 0.1
                    }]
                },
                options: {
                    responsive: true,
                    scales: {
                        x: {
                            display: true,
                            title: {
                                display: true,
                                text: 'Zeit'
                            }
                        },
                        y: {
                            display: true,
                            title: {
                                display: true,
                                text: 'Wert'
                            }
                        }
                    }
                }
            });
        }

        // Initialer Datenabruf
        updateData();

        // Aktualisiere Daten alle 30 Sekunden
        setInterval(updateData, 30000);
    </script>
</body>
</html>
    """
    return render_template_string(html)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Wie geht es weiter?

Du hast nun einen Raspberry Pi Webserver, der Daten empfangen und auf einer Webseite visualisieren kann. Der nächste Schritt wäre eine Möglichkeit, über diese Webseite auch Geräte zu steuern, die wiederum z.B. an einem ESP8266 hängen und darüber gesteuert werden.

]]>
ESP8266 Wetterstation mit Datenaufzeichnung und -visualisierung https://polluxlabs.net/esp8266-projekte/esp8266-wetterstation-mit-datenaufzeichnung/ https://polluxlabs.net/esp8266-projekte/esp8266-wetterstation-mit-datenaufzeichnung/#respond Mon, 07 Aug 2023 12:54:39 +0000 https://polluxlabs.net/?p=13977 ESP8266 Wetterstation mit Datenaufzeichnung und -visualisierung Weiterlesen »

]]>
Baue eine ESP8266 Wetterstation, die dir die aktuelle Temperatur, Luftfeuchtigkeit und den Luftdruck anzeigt sowie deine Daten speichert und visualisiert. Die aktuellen Messdaten erscheinen auf einem kleinen OLED-Display. Aber das ist nicht alles: Deine Messdaten speicherst du in einer Datenbank, um auf vergangene Messungen zugreifen und sie auswerten zu können.

Um deine Messdaten zu speichern, verwendest du die Datenbank InfluxDB, die sicher hervorragend dazu eignet, zeitgebundene Daten zu speichern und nebenbei auch noch die Visualisierung deiner Daten einfach und intuitiv ermöglicht. InfluxDB wird lokal auf einem Raspberry Pi laufen. Der ESP8266 sendet die Messdaten dorthin und InfluxDB speichert und visualisiert sie. Anzeigen lassen kannst du diese dir dann in einem Browser und auf einem Gerät deiner Wahl.

Die Software, die du für die ESP8266 Wetterstation benötigst, ist kostenlos verfügbar.

Inhalte dieses Projekts:

Diese Bauteile benötigst du für die ESP8266 Wetterstation:

Den DHT22 AM ESP8266 anschließen und verwenden

Der Temperatursensor DHT22 misst neben der Temperatur auch die Luftfeuchtigkeit. Um ihn an deinem ESP8266 anzuschließen, orientiere dich an der folgenden Skizze. Achte bitte auf den 10 kΩ Widerstand, den du zwischen dem Anschluss des DHT22 am Pin D4 des ESP8266 und Plus einsetzen musst.

Temperatursensor DHT22 am ESP8266

Übrigens: Falls du deinen ESP8266 noch nicht in der Arduino IDE verfügbar gemacht hast, findest du hier bei uns ein passendes Tutorial.

DIE PASSENDEN BIBLIOTHEKEN

Um deinen Sensor verwenden zu können, musst du zwei Bibliotheken installieren, von denen du jedoch nur eine im Sketch einbinden musst. Öffne deinen Bibliotheksmanager. Suche dort zunächst nach Adafruit Unified Sensor und installiere die aktuelle Version. Die Versionsnummern in den folgenden Screenshots können abweichen.

Arduino Bibliothek Adafruit Unified Sensor

Suche anschließend nach DHT sensor library und installiere die entsprechende Bibliothek.

Arduino Bibliothek DHT Sensor Library

DIE TEMPERATUR und Luftfeuchtigkeit MESSEN

Kopiere dir den folgenden Sketch und lade ihn auf deinen Arduino hoch:

#include "DHT.h"

#define DHTPIN D4
#define DHTTYPE DHT22

float tempDHT22;
float humidity;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
}

void loop() {

  tempDHT22 = dht.readTemperature();
  humidity = dht.readHumidity();

  Serial.print("Temperatur: ");
  Serial.print(tempDHT22);
  Serial.println("*C");
  
  Serial.print("Luftfeuchtigkeit: ");
  Serial.print(humidity);
  Serial.println("%");
  
  Serial.println();
  delay(2000);
}

So funktioniert der Sketch: Nachdem du die Bibliothek eingebunden hast, legst du den Pin fest, an dem der Sensor angeschlossen ist. In unserem Sketch ist das der Pin D4.

In der nächsten Zeile legst du das Modell des Sensors fest – in unserem Fall also ein DHT22. Anschließend erstellst du ein Objekt der Bibliothek names dht, das später bei der Messung mit den Funktionen dht.readTemperature() und dht.readHumidity() zum Einsatz kommt.

Der Rest des Sketchs dürfte für dich kein Problem sein. Achte jedoch darauf, dass die Baudrate von Sketch und Seriellem Monitor übereinstimmt. Hinweis: Es kann auch sein, dass dein DHT22 auch ohne Widerstand funktioniert – oder auch nur ohne Widerstand.

Wenn du doch lieber den Sensor DHT11 verwenden möchtest, musst du nur eine Stelle im Sketch anpassen:

#define DHTTYPE DHT11

Wie du den “kleinen Bruder” des DHT22 – also den DHT11 – anschließt, erfährst du in der folgenden Skizze. Im weiteren Verlauf des Projekts verwenden wir jedoch weiterhin den DHT22.

Temperatursensor DHT11 am ESP8266

DEN BMP180 am ESP8266 anschließen und verwenden

Neben der Luftfeuchtigkeit und der Temperatur soll die ESP8266 Wetterstation auch den aktuellen Luftdruck messen. Hierfür eignet sich der Sensor BMP180. Da dieser auch die Temperatur messen kann, schauen wir uns gleich auch noch die Messunterschiede zwischen DHT11 und BMP180 an. Doch zunächst zum Anschluss – orientiere dich hierbei an der folgenden Skizze:

Sensoren DHT22 und BMP180 am ESP8266

Die benötigte Bibliothek

Neben der bereits vorinstallierten Bibliothek Wire (für die Kommunikation per I²C), benötigst du noch eine weitere, um die Daten des Sensors problemlos auslesen zu können.

Öffne also den Bibliotheksmanager in der Arduino IDE und suche nach BMP180. Du findest nun eine Bibliothek namens Adafruit BMP085 Library – das ist die richtige, auch wenn sie ein anderes Modell im Namen trägt. Der BMP085 war das Vorgängermodell des BMP180, was die Kommunikation angeht, jedoch mehr oder weniger baugleich.

Adafruit BMP085 Bibliothek

Die Temperatur und den Luftdruck messen

Nun erweiterst du den obigen Sketch um den Code für den BMP180:

#include "DHT.h"
#include "Wire.h"
#include "Adafruit_BMP085.h"

#define DHTPIN D4
#define DHTTYPE DHT22

Adafruit_BMP085 bmp;

float tempDHT22;
float tempBMP180;
float humidity;
float pressure;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();

  if (!bmp.begin()) {
    Serial.println("Sensor BMP180 nicht gefunden!");
    while (1) {}
  }
}

void loop() {

  tempDHT22 = dht.readTemperature();
  tempBMP180 = bmp.readTemperature();
  humidity = dht.readHumidity();
  pressure = bmp.readPressure();

  Serial.print("Temperatur DHT22: ");
  Serial.print(tempDHT22);
  Serial.println("*C");

  Serial.print("Temperatur BMP180: ");
  Serial.print(tempBMP180);
  Serial.println("*C");

  Serial.print("Luftfeuchtigkeit DHT22: ");
  Serial.print(humidity);
  Serial.println("%");

  Serial.print("Luftdruck BMP180: ");
  Serial.print(pressure/100);
  Serial.println("hPa");

  Serial.println();
  delay(2000);
}

Sobald du den Sketch auf deinen ESP8266 geladen hast, sollten im seriellen Monitor die vier Messdaten erscheinen.

Ausgabe der Wetterdaten im seriellen Monitor

In den allermeisten Fällen dürfte die Temperaturmessung des DHT22 und des BMP180 etwas auseinander liegen. Ein Blick in die jeweiligen Datenblätter verrät, dass beide Sensoren eine Genauigkeit von ±0,5°C haben – das ist eigentlich schon recht genau und für eine Wetterstation sicherlich genau genug. Für welchen Messwert du dich entscheidest, liegt nun bei dir – vielleicht hast du noch ein weiteres Thermometer zur Hand, das du als Referenz einsetzen kannst.

Im weiteren Verlauf dieses Projekts verwenden wir die Temperaturdaten des BMP180.

Das OLED-Display anschließen

Aktuell siehst du deine Messdaten nur im seriellen Monitor. Deshalb kommt nun ein Display zum Einsatz, auf dem du sie bequemer ablesen kannst. In diesem Projekt verwenden wir das handelsübliche OLED-Display Adafruit SSD1306 mit einer Größe von 128×64 px.

Erweitere also den Aufbau auf deinem Breadboard wie folgt:

Die fertig aufgebaute ESP8266 Wetterstation

Wie du siehst, sind sowohl der BMP180 als auch das OLED-Display per I²C (also an den Pins D1 und D2) am ESP8266 angeschlossen. Damit der Microcontroller beide Bauteile ansprechen kann, besitzen sie unterschiedliche Adressen – das OLED-Display mit 128×64 px die Adresse 0x3C und der BMP180 die Adresse 0x77.

Die benötigten Bibliotheken

Nun ist deine ESP8266 Wetterstation vollständig. Allerdings fehlt noch der Sketch, mit dem du deine Messdaten auf dem OLED-Display anzeigst. Auch für das Display benötigst du die Unterstützung von Bibliotheken, die du im Handumdrehen installierst. Öffne also wieder den Bibliotheksmanager und suche zunächst nach Adafruit SSD1306 und installiere die neueste Version. Falls du gefragt wirst, ob du auch zugehörige Erweiterungen installieren möchtest, bestätige das mit einem Ja.

Die zweite Bibliothek findest du mit einer Suche nach Adafruit GFX Library. Falls diese schon im Zuge der ersten Installation mitinstalliert wurde, brauchst du nichts weiter zu tun und kannst den Bibliotheksmanager schließen.

Messdaten auf dem Display anzeigen

Ersetze den Code auf deinem ESP8266 durch den folgenden erweiterten Sketch:

#include "DHT.h"
#include "Wire.h"
#include "Adafruit_BMP085.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define DHTPIN D4
#define DHTTYPE DHT22

Adafruit_BMP085 bmp;

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

float tempDHT22;
float tempBMP180;
float humidity;
float pressure;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();

  if (!bmp.begin()) {
    Serial.println("Sensor BMP180 nicht gefunden!");
    while (1) {}
  }

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Display-Addresse: 0x3C für Groesse 128x64px
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  display.setTextSize(1);       //Schriftgröße
  display.setTextColor(WHITE);  //Schriftfarbe


  display.clearDisplay();
  display.display();
}

void loop() {

  tempDHT22 = dht.readTemperature();
  tempBMP180 = bmp.readTemperature();
  humidity = dht.readHumidity();
  pressure = bmp.readPressure();

  Serial.print("Temperatur DHT22: ");
  Serial.print(tempDHT22);
  Serial.println("*C");

  Serial.print("Temperatur BMP180: ");
  Serial.print(tempBMP180);
  Serial.println("*C");

  Serial.print("Luftfeuchtigkeit DHT22: ");
  Serial.print(humidity);
  Serial.println("%");

  Serial.print("Luftdruck BMP180: ");
  Serial.print(pressure / 100);
  Serial.println("hPa");
  Serial.println();

  display.clearDisplay();

  display.setCursor(10, 10);
  display.println("Temp.:  " + String(tempBMP180) + " *C");

  display.setCursor(10, 29);
  display.println("Luftf.: " + String(humidity) + " %");
  display.setCursor(10, 48);

  display.println("Luftd.: " + String(pressure/100) + " hPa");

  display.display();
  delay(2000);
}

Auf deinem OLED-Display sollten nun untereinander die Werte für Temperatur, Luftfeuchtigkeit und Luftdruck zu sehen sein, die alle zwei Sekunden aktualisiert werden.

Die Daten auf dem Raspberry Pi speichern und visualisieren

Messdaten auf einem Display sind eine tolle Sache – aber wenn du die Werte deiner Wetterstation über längere Zeit speichern und sie als Graphen anzeigen möchtest, musst du ein paar Schritte weiter gehen.

Im Folgenden richtest du deinen Raspberry Pi so ein, dass du ihn bequem von deinem Computer per SSH steuern kannst. Anschließend installierst du dort die Datenbank InfluxDB, in der deine Messwerte gespeichert werden. Praktischerweise bringt InfluxDB gleich eine Möglichkeit, die Daten ansprechend darzustellen. Doch eins nach dem anderen.

Das Betriebssystem auf dem Raspberry Pi installieren

Zunächst benötigst du ein entsprechend konfiguriertes Betriebssystem. Das lässt du auf eine Micro-SD-Karte schreiben, die du dann in deinen Raspberry Pi steckst.

Besonders einfach ist das mit dem kostenlosen Rasperry Pi Imager, den du hier herunterladen kannst. Wähle einfach die Version für dein Betriebssystem und starte den Download.

Download-Screen Raspberry Pi Imager

Öffne das Programm nach dem Download und wähle in der Oberfläche unter Betriebssystem -> Raspberry Pi OS (other) -> Raspberry Pi OS (64-bit).

Schließe als nächstes die Micro-SD-Karte, auf die du das Raspberry Pi OS installieren möchtest, an deinen Computer an. Wähle sie anschließend im Feld SD-Karte aus.

Bevor du jetzt auf den Button Schreiben klickst, wähle zunächst die erweiterten Einstellungen hinter dem Zahnrad-Symbol. Hier kannst du gleich den Hostnamen festlegen, SSH aktivieren und auch deine WLAN-Zugangsdaten hinterlegen. Das bedeutet, dass du deinen Raspberry Pi nicht mehr an einen Monitor anschließen musst, um diese Einstellungen vorzunehmen. Später reicht es, die Micro-SD-Karte und das Stromkabel einzustecken.

Wähle zunächst im oberen Bereich die folgenden Optionen:

Raspberry Pi Imager erweiterte Optionen

Anschließend legst du deinen Benutzernamen fest und hinterlegst deine WLAN-Zugangsdaten. Die Wahl deines Benutzernamen steht dir natürlich frei – in den folgenden Befehlen verwenden wir hier jedoch das gängige pi.

Raspberry Pi Imager erweiterte Optionen

Noch ein Stück weiter unten stellst du noch dein Land und deine Zeitzone ein:

Raspberry Pi Imager erweiterte Optionen

Und das war es. Speichere diese Einstellungen und klicke im Hauptmenü auf Schreiben.

Per SSH auf den Raspberry Pi zugreifen

Nachdem das Raspberry Pi OS auf der Micro-SD-Karte und schließlich in deinem Raspberry Pi gelandet ist, starte diesen, indem du das Stromkabel anschließt. Warte nun ein paar Minuten, bis er fertig gebootet hat.

Nun wirst du dich per SSH (Secure Shell) mit dem Raspberry Pi verbinden. SHH ist eine beliebte – und verschlüsselte – Verbindung zwischen zwei Geräten. Hierdurch kannst du auf sichere Art und Weise von deinem Computer auf den Raspberry Pi zugreifen, Software installieren – und später deine Wetterdaten auswerten. So richtest du die Verbindung ein:

MacOS & Linux

Bei diesen beiden Betriebssystemen brauchst du lediglich das Terminal. In Unix-basierten Betriebssystemen ist SSH nämlich schon vorinstalliert. Öffne also das Terminal und tippe den folgenden Befehl ein:

sudo ssh pi@raspberrypi.local

Hinweis: Falls du einen anderen Benutzer- und Hostnamen vergeben hast, passe den Befehl entsprechend an.

Wenn du nach deinem Passwort gefragt wirst, trage jenes, das du im Raspberry Pi Imager vergeben hast, ein und drücke Enter. Möglicherweise musst du auch noch mal mit einem yes bestätigen, dass du die Verbindung aufbauen möchtest. Wenn die Verbindung steht, siehst du die folgende Zeile in deinem Terminal:

Kommandozeile im Terminal

Um die Verbindung wieder zu beenden und deinen Raspberry Pi herunterzufahren, trage folgenden Befehl ins Terminal ein:

sudo poweroff

Windows

In Windows benötigst du eine Software, um dich per SSH zu verbinden – zum Beispiel PuTTY. Diese Programm kannst du hier herunterladen.

Installiere PuTTY auf deinem Computer, öffne es und trage die folgenden Daten in den Optionen/Einstellungen ein:

  • Host Name: raspberrypi
  • Port: 22
  • Connection type: SSH

Klicke anschließend auf Open/Öffnen. Bei der ersten Verbindung erscheint ein Dialog-Fenster, das dich davor warnt, dass du eine Verbindung zu einem unbekannten Host aufbaust. Diese kannst du mit einem Klick auf No schließen.

Logge dich als nächstes mit deinen Zugangsdaten, die du im Raspberry Pi Imager festgelegt hast, ein. Sobald die Verbindung steht, siehst du auch wieder die oben genannte Zeile. Um den Raspberry Pi auszuschalten, verwendest du ebenfalls.

sudo poweroff

INfluxDB 2 auf dem Raspberry Pi installieren

Jetzt wo deine Verbindung steht, kannst du die Datenbank InfluxDB installieren, um die Daten deiner ESP8266 Wetterstation zu speichern. Trage hierfür im Terminal bzw. in PuTTY den folgenden Befehl ein. Kopiere die folgenden Zeilen vollständig, füge sie ins Terminal ein und führe sie mit Enter aus.

wget -q https://repos.influxdata.com/influxdata-archive_compat.key
echo '393e8779c89ac8d958f81f942f9ad7fb82a25e133faddaf92e15b16e6ac9ce4c influxdata-archive_compat.key' | sha256sum -c && cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null
echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | sudo tee /etc/apt/sources.list.d/influxdata.list

sudo apt-get update && sudo apt-get install influxdb2

Nun läuft die Installation im Terminal. Ab und an wirst du um deine Zustimmung zur Installation von Erweiterungspaketen gefragt. Gib diese einfach durch Eingabe von Y und Enter.

Nachdem die Installation abgeschlossen ist, erscheint wieder die Zeile pi@raspberrypi:~$

Trage nun folgenden Befehl im Terminal ein, der dafür sorgt, dass InfluxDB beim Start des Raspberry Pi ebenfalls gestartet wird:

sudo service influxdb start

Anschließend prüfst du noch kurz, ob InfluxDB aktiv ist:

sudo service influxdb status

Im Terminal erscheint nun einiges an Text – darunter hoffentlich ein grünes active (running):

Ausgabe im Terminal, dass InfluxDB aktiv ist

Drücke q auf deiner Tastatur, um wieder zur Kommandozeile zurückzukehren.

Auf die Datenbank zugreifen

Um auf InfluxDB im Browser zugreifen zu können, benötigst du zunächst die IP-Adresse des Raspberry Pi. Diese findest du mit folgendem Befehl im Terminal heraus:

hostname -I

In der Antwort des Raspberry Pi siehst du ganz vorne die IP-Adresse, in unserem Fall die 192.168.0.129

Um nun InfluxDB zu starten, öffne in deinem Browser ein neues Tab oder Fenster und tippe deine IP-Adresse gefolgt vom Port :8086. Die Adresse sieht dann zum Beispiel so aus:

192.168.0.129:8086

In deinem Browser öffnet sich nun die Startseite von InfluxDB:

Startscreen InfluxDB auf dem Raspberry Pi

Nun kann es losgehen – klicke also auf Get started. Es folgt eine Seite, auf der du deine Zugangsdaten festlegst:

Trage deinen Benutzernamen unter Username ein und hinterlege ein sicheres Passwort. Unter Initial Organization Name kannst du ebenso deinen Benutzernamen eintragen – solange du nicht wirklich eine Arbeitsgruppe für die Wetterstation hast.

Unter Initial Bucket Name kannst du zum Beispiel ESP8266 Wetterstation eintragen. Unter diesem Namen findest du später die Datenbank für deine Wetterstation.

Bestätige deine Eingabe und klicke auf der folgenden Seite auf Quick Start:

Testweise die WLAN-Signalstärke übertragen

Anschließend findest du auf der Webseite die Kachel Arduino. Dahinter verbirgt sich eine Art Tutorial, wie du deinen ESP8266 einrichtest, um Daten an die Datenbank zu übertragen – hier die Stärke deines WLAN-Signals. Dieses Tutorial spielen wir im Folgenden teilweise durch, um einen Sketch zu erhalten, den du danach so erweitern kannst, dass er die Messdaten der Wetterstation überträgt.

Im Menü links findest du mehrere Punkte – da du den zweiten Punkt Prepare Arduino IDE (also den ESP8266 in der IDE verfügbar machen) bereits beim Aufbau der Wetterstation abgeschlossen hast, kannst du ihn gleich überspringen und auf Install Dependencies klicken.

Hier erhältst du Informationen zu einer Bibliothek, die du in der Arduino IDE installieren musst, um Daten an InfluxDB übertragen zu können. Öffne also den Bibliotheksmanager und suche nach InfluxDB. Im Tutorial heißt die erforderliche Bibliothek InfluxDB Client for Arduino – es kann aber gut sein, dass du nur eine Bibliothek namens ESP8266 Influxdb findest. Sollte das der Fall sein, installiere einfach diese stattdessen. Wenn du fertig bist, klicke auf Next.

Auf der nächsten Seite Initialize Client kannst du den Bucket auswählen, in den die Daten übertragen werden sollen:

Gleich darunter findest du Code, den du in einen leeren Sketch einfügen sollst. Erstelle also einen neuen Sketch, kopiere den zur Verfügung gestellten Code und füge ihn ein. Achte unbedingt darauf, dass du die leeren Funktionen Setup und Loop mit diesem Code überschreibst.

In diesem Beispiel-Sketch musst du noch deine WLAN-Zugangsdaten hinterlegen, damit dein ESP8266 mit dem Raspberry Pi kommunizieren kann:

  // WiFi AP SSID
  #define WIFI_SSID "YOUR_WIFI_SSID"
  // WiFi password
  #define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"

Trage also deine Daten ein und klicke im Tutorial wieder auf Next.

Es folgen wieder zwei Zeilen Code, die du in der Setup-Funktion unterhalb des dort schon vorhandenen Codes einfügen musst:

Der Sketch in diesem Tutorial überträgt die Stärke deines WLAN-Signals an die Datenbank. Die zwei Zeilen fügen den Datenpunkten zwei Tags hinzu – einmal das Gerät und einmal die SSID, also der Name deines WLAN-Netzwerks.

Gleich darunter findest du den Loop des Sketchs. Dieser ist aktuell noch leer – kopiere ihn dir also aus dem Tutorial und überschreibe damit die leere Loop-Funktion in deiner Arduino IDE. Im Loop wird jede Sekunde der Received Signal Strength Indicator (RSSI, also die Signalstärke des WLAN-Netzes) gemessen und in der InfluxDB hinterlegt.

Die zwei nächsten Punkte des Tutorials können wir überspringen. Hier geht es um Datenbank-Abfragen, die wir jedoch für unsere Zwecke nicht benötigen.

Der vollständige Beispiel-Sketch

Diese Copy & Paste Arbeit hat etwas Fingerspitzengefühl erfordert. Wenn alles an der richtigen Stelle gelandet ist, sollte dein Sketch wie folgt aussehen:

#if defined(ESP32)
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
#define DEVICE "ESP32"
#elif defined(ESP8266)
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
#define DEVICE "ESP8266"
#endif

#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>

// WiFi AP SSID
#define WIFI_SSID "YOUR_WIFI_SSID"
// WiFi password
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"

#define INFLUXDB_URL "DEINE URL (ist vorausgefüllt)"
#define INFLUXDB_TOKEN "DEIN TOKEN (ist vorausgefüllt)"
#define INFLUXDB_ORG "DEINE ORG (ist vorausgefüllt)"
#define INFLUXDB_BUCKET "ESP8266 Wetterstation"

// Time zone info
#define TZ_INFO "UTC2"

// Declare InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);

// Declare Data point
Point sensor("wifi_status");

void setup() {
  Serial.begin(115200);

  // Setup wifi
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();

  // Accurate time is necessary for certificate validation and writing in batches
  // We use the NTP servers in your area as provided by: https://www.pool.ntp.org/zone/
  // Syncing progress and the time will be printed to Serial.
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");


  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }

  // Add tags to the data point
  sensor.addTag("device", DEVICE);
  sensor.addTag("SSID", WiFi.SSID());
}

void loop() {
    // Clear fields for reusing the point. Tags will remain the same as set above.
    sensor.clearFields();
  
    // Store measured value into point
    // Report RSSI of currently connected network
    sensor.addField("rssi", WiFi.RSSI());
  
    // Print what are we exactly writing
    Serial.print("Writing: ");
    Serial.println(sensor.toLineProtocol());
  
    // Check WiFi connection and reconnect if needed
    if (wifiMulti.run() != WL_CONNECTED) {
      Serial.println("Wifi connection lost");
    }
  
    // Write point
    if (!client.writePoint(sensor)) {
      Serial.print("InfluxDB write failed: ");
      Serial.println(client.getLastErrorMessage());
    }
  
    Serial.println("Waiting 1 second");
    delay(1000);
    
    }

Die Daten visualisieren

Jetzt wird es Zeit, sich die übertragenen Daten einmal anzusehen. Öffne hierfür im Menü links den Data Explorer über das Symbol mit dem Koordinatensystem und dem Graphen.

Hier kannst du dir im unteren Bereich eine Abfrage (Query) basteln, die die Signalstärke als Graphen darstellt:

Wähle hierfür links deinen Bucket und im ersten Filter rechts daneben im Dropdown-Menü SSID und darunter den Wert, der dem Namen deines WLAN-Netzwerks entspricht. Rechts daneben sollte ein weiterer Filter aufgehen, in dem im Dropdown-Menü bereits _field vorausgewählt ist. Als einzigen Wert findest du darin rssi, also die Signalstärke. Wähle diesen Wert aus. Falls noch ein weiterer Filter rechts daneben aufgehen, kannst du diesen über das X in der Ecke schließen.

Um diese als Graphen anzuzeigen, musst du nur noch rechts auf Submit klicken. Nun sollte im oberen Bereich eine Graph entstehen – hier ein Beispiel, das schon einige Minuten lief:

Deine Abfrage kannst du natürlich zeitlich anpassen. Voreingestellt ist ein Zeitraum von einer Stunde (Past 1h). Über das entsprechende Dropdown kannst du auch andere Zeiträume einstellen.

Ganz oben findest du auch die Auswahl Custom Time Range – hierüber kannst du den Zeitraum noch genauer über einen Kalender einstellen. Sobald du deine Auswahl getroffen hast, klicke links neben dem Dropdown-Menü auf den Refresh-Button oder auf Submit. Über diese beiden Buttons kannst du den Graphen auch aktualisieren, um die aktuellen Daten miteinzubeziehen.

Du überträgst nun bereits Daten von deinem ESP8266 an deine Datenbank auf dem Raspberry Pi – wenn auch “nur” die Stärke des WLAN-Signals. Nun wird es Zeit, die Messdaten zu übertragen.

Die Daten der ESP8266 WEtterstation übertragen und anzeigen

Um statt des WLAN-Signals die Messdaten zu übertragen, fügst du den Sketch aus dem Tutorial und deinen bisherigen Sketch der Wetterstation zusammen – und änderst außerdem noch zwei kleinere Stellen im Code.

Kopiere hierfür Stück für Stück aus deinem Wetterstation-Sketch die verschiedenen Teile (Bibliotheken und Definitionen, Setup sowie Loop) und füge sie nacheinander in den Sketch des Tutorials ein. Wenn du das getan hast, sieht dein vollständiger Sketch wie folgt aus:

#if defined(ESP32)
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
#define DEVICE "ESP32"
#elif defined(ESP8266)
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
#define DEVICE "ESP8266"
#endif

#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>

// WiFi AP SSID
#define WIFI_SSID "YOUR_WIFI_SSID"
// WiFi password
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"

#define INFLUXDB_URL "DEINE URL (ist vorausgefüllt)"
#define INFLUXDB_TOKEN "DEIN TOKEN (ist vorausgefüllt)"
#define INFLUXDB_ORG "DEINE ORG (ist vorausgefüllt)"
#define INFLUXDB_BUCKET "ESP8266 Wetterstation"

// Time zone info
#define TZ_INFO "UTC2"

// Declare InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);

// Declare Data point
Point sensor("wifi_status");

#include "DHT.h"
#include "Wire.h"
#include "Adafruit_BMP085.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define DHTPIN D4
#define DHTTYPE DHT22

Adafruit_BMP085 bmp;

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

float tempDHT22;
float tempBMP180;
float humidity;
float pressure;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);

  // Setup wifi
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();

  // Accurate time is necessary for certificate validation and writing in batches
  // We use the NTP servers in your area as provided by: https://www.pool.ntp.org/zone/
  // Syncing progress and the time will be printed to Serial.
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");


  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }

  // Add tags to the data point
  sensor.addTag("device", DEVICE);
  
  Serial.begin(115200);
  dht.begin();

  if (!bmp.begin()) {
    Serial.println("Sensor BMP180 nicht gefunden!");
    while (1) {}
  }

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Display-Addresse: 0x3C für Groesse 128x64px
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  display.setTextSize(1);       //Schriftgröße
  display.setTextColor(WHITE);  //Schriftfarbe


  display.clearDisplay();
  display.display();
}

void loop() {
  tempDHT22 = dht.readTemperature();
  tempBMP180 = bmp.readTemperature();
  humidity = dht.readHumidity();
  pressure = bmp.readPressure();

  Serial.print("Temperatur DHT22: ");
  Serial.print(tempDHT22);
  Serial.println("*C");

  Serial.print("Temperatur BMP180: ");
  Serial.print(tempBMP180);
  Serial.println("*C");

  Serial.print("Luftfeuchtigkeit DHT22: ");
  Serial.print(humidity);
  Serial.println("%");

  Serial.print("Luftdruck BMP180: ");
  Serial.print(pressure / 100);
  Serial.println("hPa");
  Serial.println();

  display.clearDisplay();
  display.setCursor(10, 10);
  display.println("Temp.:  " + String(tempBMP180) + " *C");
  display.setCursor(10, 29);
  display.println("Luftf.: " + String(humidity) + " %");
  display.setCursor(10, 48);
  display.println("Luftd.: " + String(pressure / 100) + " hPa");

  display.display();

  // Clear fields for reusing the point. Tags will remain the same as set above.
  sensor.clearFields();

  // Store measured value into point
  sensor.addField("temp", tempBMP180);
  sensor.addField("humidity", humidity);
  sensor.addField("pressure", pressure/100);

  // Print what are we exactly writing
  Serial.print("Writing: ");
  Serial.println(sensor.toLineProtocol());

  // Check WiFi connection and reconnect if needed
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Wifi connection lost");
  }

  // Write point
  if (!client.writePoint(sensor)) {
    Serial.print("InfluxDB write failed: ");
    Serial.println(client.getLastErrorMessage());
  }



  Serial.println("Waiting 1 second");
  delay(1000);
}

Im Code oben findest du zwei Änderungen, die wir uns jetzt näher anschauen. Zunächst streichst du den Tag SSID in der Setup-Funktion, da wir das nicht mehr brauchen. Übrig bleibt das device (also ESP8266) – hierüber können wir später im Data Explorer die Messdaten leichter finden.

// Add tags to the data point
sensor.addTag("device", DEVICE);

Außerdem müssen statt der Signalstärke unsere Messdaten für Temperatur, Luftfeuchtigkeit und -druck übertragen werden. Das geschieht im Loop mit folgendem Code:

  // Store measured value into point
  sensor.addField("temp", tempBMP180);
  sensor.addField("humidity", humidity);
  sensor.addField("pressure", pressure/100);

Hiermit werden die drei Felder (fields) mit den Namen temp, humidity und pressure in der Datenbank angelegt und mit den aktuellen Daten der Sensoren versorgt. Diese stammen aus unseren Variablen tempBMP180, humidity und pressure. Wie du siehst teilst du den Wert in der Variablen pressure noch durch 100, um statt Pascal (Pa) Hektopascal (hPa) zu erhalten.

Und das war auch schon alles. Achte darauf, dass deine korrekten WLAN-Zugangsdaten im Sketch eingetragen sind und lade ihn auf deinen ESP8266.

Die Daten im Data Explorer anzeigen

Als nächstes schaust du im Data Explorer nach, ob die Daten auch wie gewünscht deine Datenbank erreichen. Klicke hierfür links auf den entsprechenden Menüpunkt und erstelle deine Abfrage wie folgt:

Hier pickst du dir testweise die Temperatur über die Variable temp heraus. Wenn du deine Abfrage erstellt hast, klicke auf den Button Submit. Im oberen Bereich der Seite sollte nun ein Graph zu sehen sein – hier wieder ein Beispiel, das schon einige Zeit lief:

Wie du hier siehst begann die Aufzeichnung kurz nach 12 Uhr am 7. August 2023 mit Werten um die 24 °C. Gegen 12:20 Uhr brach die Verbindung zur Datenbank ab (die Wetterstation war aus) und begann wieder gegen 12:30 Uhr. Diese Zwischenzeit wird im Graphen als Verbindungslinie zwischen dem letzten erhaltenen und ersten wieder verfügbaren Datenpunkt dargestellt. Anschließend sank die Temperatur kontinuierlich von 25 °C auf circa 24,7 °C.

Hinweis: Auf der rechten Seite findest du den Punk Aggregate Function – hier kannst du einstellen, ob du von den Temperaturwerten den Durchschnitt (mean), den Median oder immer den letzten aktuellen Wert (last) sehen möchtest. Die letzte Option zeigt dir immer den aktuellen, tatsächlichen Wert an. Die beiden anderen glätten hingegen den Graphen, sodass Temperaturausschläge weniger ins Gewicht fallen.

Solange deine ESP8266 Wetterstation also läuft, werden Daten gesammelt. Auf diese kannst du entweder über das Dropdown (z.B. Past 1h) oder spezifisch über den Punkt Custom Time Range zugreifen. Es gibt allerdings noch eine weitere spannende Funktion: ein Dashboard.

Die Messdaten auf einem Dashboard anzeigen

Um die aktuelle Abfrage auf einem Dashboard zu speichern, das dir einen schnellen Überblick verschafft, klicke zunächst im Menü links auf den entsprechenden Button:

Klicke anschließend rechts auf den Button Create Dashboard und anschließend auf New Dashboard. Auf der folgenden Seite kannst du oben einen Namen für das Dashboard vergeben, zum Beispiel ESP8266 Wetterstation:

Anschließend kannst du über den Button Add Cell eine Kachel hinzufügen – zum Beispiel den gerade gesehenen Temperaturverlauf. Du landest nach deinem Klick wieder in der Ansicht des Data Explorers, nur das du diesmal hier die Abfrage für die neue Temperatur-Kachel erstellst.

Vergib zunächst wieder ganz oben einen Namen, zum Beispiel Temperaturverlauf. Anschließend wählst du im unteren Bereich wieder die Variable temp aus.

Alles, was jetzt noch fehlt ist ein Klick auf das Häkchen oben rechts – und schon landest du wieder auf deinem Dashboard, das nun den Temperaturverlauf enthält.

Im oberen Bereich findest du den Button Set Auto Refresh – hierüber kannst du einstellen, in welchem Intervall das Dashboard und damit auch der Graph aktualisiert werden soll.

Apropos Graph, du kannst auf dem Dashboard auch die aktuelle Temperatur anzeigen lassen. Klicke hierfür wieder auf Add Cell und erstelle die bekannte Abfrage erneut. Sobald du auf Submit geklickt hast, erscheint wieder dein Temperaturverlauf. Oben links findest du ein Dropdown-Menü, in dem du die Anzeige anpassen kannst. Wähle hier den Eintrag Gauge.

Nun siehst du nicht mehr den Verlauf, sondern die aktuelle Temperatur:

Vergib dieser Kachel wieder einen Namen und klicke abschließend auf das Häkchen rechts oben. Nun landest du wieder in deinem Dashboard mit den zwei Kacheln zur Temperatur.

Mit deinen beiden anderen Messwerten zu Luftdruck und -feuchtigkeit kannst du genauso verfahren. Noch ein letzter Hinweis zu den Kacheln: Über den Button Customize kannst du die Anzeige noch anpassen, was besonders beim Luftdruck sinnvoll ist. Stelle hier unter Thresholds einen Bereich von 900 bis 1100 ein, damit der Zeiger auch etwas zum Anzeigen hat. Ebenso kannst du dem Wert noch ein Suffix vergeben – hier also hPa.

Warnungen per Nachricht senden

Möchtest du Nachrichten an dich oder jemand anderes senden, wenn ein bestimmter Messwert über- oder unterschritten wird? Im folgenden Tutorial erfährst du, wie du mit dem ESP8266 oder ESP32 Nachrichten per Telegram, WhatsApp und E-Mail verschickst.

]]>
https://polluxlabs.net/esp8266-projekte/esp8266-wetterstation-mit-datenaufzeichnung/feed/ 0
Mit dem DHT11 und DHT22 Temperatur und Luftfeuchtigkeit messen https://polluxlabs.net/arduino-tutorials/mit-dem-dht22-temperatur-und-luftfeuchtigkeit-messen/ Fri, 12 Mar 2021 15:20:24 +0000 https://polluxlabs.net/?p=7246 Mit dem DHT11 und DHT22 Temperatur und Luftfeuchtigkeit messen Weiterlesen »

]]>
Für den Arduino und andere Microcontroller gibt es eine Vielzahl von Sensoren, die die Temperatur messen. Zwei davon sind der DHT11 und der DHT22, die darüber hinaus auch die Luftfeuchtigkeit ermitteln können.

In diesem Tutorial lernst du, wie du den DHT11 und den DHT22 am Arduino und ESP8266 anschließt und verwendest.

Den Sensor DHT11 anschließen

Der Anschluss des DHT11 am Arduino ist ganz leicht, du benötigst lediglich drei Kabel. Orientiere dich beim Anschluss an folgender Skizze. An welchen Digital-Pin du deinen Sensor anschließt, steht dir natürlich frei. Damit der Code dieses Tutorials passt, wähle bitte den Pin 4.

Anschluss DHT11 am Arduino

Den Sensor DHT22 anschließen

Um deinen DHT22 am Arduino oder ESP8266 anzuschließen, benötigst du neben Sensor, Microcontroller, Breadboard und Kabeln einen Widerstand mit 10 kΩ. Orientiere dich beim Anschluss am Arduino an folgender Skizze:

Anschluss DHT22 am Arduino

Hier ist der Signalpin des DHT22 am Digital-Pin 4 des Arduinos angeschlossen – so passt der Anschluss zum Sketch unten. Prinzipiell steht es dir natürlich frei, welchen Digital-Pin du verwendest.

Der Anschluss am ESP8266 sieht folgendermaßen aus:

Anschluss DHT22 am ESP8266

Beim Arduino kannst du den DHT11 oder DHT22 entweder mit 5 Volt oder 3,3 Volt versorgen. Beim ESP8266 stehen dir natürlich nur 3,3 Volt zur Verfügung.

Die passenden Bibliotheken

Du benötigst zwei Bibliotheken, von denen du jedoch nur eine im Sketch einbinden musst. Öffne zunächst deinen Bibliotheksmanager und suche dort nach Adafruit Unified Sensor. Installiere anschließend die aktuelle Version.

Bibliothek Adafruit Unified Sensor

Suche nun nach DHT11 oder DHT22 und installiere die Bibliothek DHT sensor library.

Wenn du beide Bibliotheken erfolgreich installiert hast, geht es weiter mit der Messung.

Temperatur und Luftfeuchtigkeit messen

Binde als erstes die Bibliothek für den Sensor zu Beginn deines Sketchs ein:

#include "DHT.h"

Anschließend definierst du den Pin, an dem der Sensor angeschlossen ist. In der Zeile danach legst du den Typ des DHT fest: In unserem Fall also DHT22 – wenn du einen DHT11 verwendest, kannst du die Zeile entsprechend abändern.

#define DHTPIN 4   
#define DHTTYPE DHT22

Nun fehlen noch zwei Variablen für die Temperatur und die Luftfeuchtigkeit sowie ein Objekt für den Sensor namens dht.

float temp;
float humidity;

DHT dht(DHTPIN, DHTTYPE);

In der Setup-Funktion startest du den Sensor mit

dht.begin();

Die eigentliche Messung findet dann im Loop statt. Diese könnte dank der eingebundenen Bibliothek kaum einfacher sein, da es passende Funktionen gibt. Die Messergebnisse speicherst du in den entsprechenden Variablen:

temp = dht.readTemperature();
humidity = dht.readHumidity();

Und das war es schon. Hier nun der vollständige Sketch, in dem du die Messergebnisse alle zwei Sekunden im Seriellen Monitor ausgibst:

#include "DHT.h"

#define DHTPIN 4   
#define DHTTYPE DHT22

float temp;
float humidity;

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
}

void loop() {

  temp = dht.readTemperature();
  humidity = dht.readHumidity();
  
  Serial.print("Temperatur: ");
  Serial.print(temp);
  Serial.println(" *C");
  Serial.print("Luftfeuchtigkeit: ");
  Serial.print(humidity);
  Serial.println(" %");

  Serial.println();
  delay(2000);

}

Wie geht es weiter?

Wie wäre es mit einem eigenen ESP8266 Web Server, über den du die aktuelle Temperatur vom Smartphone aus abrufen kannst?

]]>
Farben erkennen mit einem Farbsensor und dem Arduino https://polluxlabs.net/arduino-tutorials/farben-erkennen-mit-einem-farbsensor-und-dem-arduino/ Sun, 27 Dec 2020 18:50:27 +0000 https://polluxlabs.net/?p=4597 Farben erkennen mit einem Farbsensor und dem Arduino Weiterlesen »

]]>
Mit einem Farbsensor bringst du deinem Arduino bei, verschiedene Farben voneinander unterscheiden zu können. Zwar können die meisten Sensoren keine feinen Unterschiede erkennen – um aber zum Beispiel die Farben von M&Ms oder Skittles erkennen zu können, reichen sie allemal!

Hier lernst du, wie du einen Farbsensor* anschließt, damit Farben erkennst und diese in das bekannte RGB-Modell umrechnest. In diesem Tutorial verwenden wir den gängigen Sensor TC3200.

AZDelivery Farbsensor TCS230 TCS3200 Farben Sensor Modul kompatibel mit Arduino inklusive E-Book!
AZDelivery Farbsensor TCS230 TCS3200 Farben Sensor Modul kompatibel mit Arduino inklusive E-Book!
✅ Chip: TAOS TCS3200 RGB Sensor; ✅ Eingangsspannung: DC 3 ~ 5V; ✅ Hellweiße LEDs...
8,99 €

Den Farbsensor am Arduino anschließen

Am Sensor findest du insgesamt 8 Pins, von denen du 7 mit deinem Arduino wie folgt verbinden kannst. Die Wahl der Digitalpins ist natürlich dir selbst überlassen.

FarbsensorArduino (Digitalpin)
VCC5V
GNDGND
S06
S17
S28
S39
OUT10

Eine kurze Erklärung zu den einzelnen Pins am Farbsensor: Mit den Pins S0 und S1 kannst du die Ausgangsfrequenz des Sensors steuern. So kannst du deine Ergebnisse optimieren, was wir in diesem Tutorials allerdings erst einmal beiseite lassen.

Die Pins S2 und S3 steuern die einzelnen Photodioden des Sensors. Hiervon gibt es je 16 Stück für die Farben Rot, Grün, Blau und Clear (also ohne Farbfilter). Die beiden Pins kannst du von deinem Arduino entweder auf HIGH oder LOW setzen – die Kombination bestimmt dann, welche Dioden angesprochen und welche Farbe also “gelesen” werden soll:

S2S3Farbe
LOWLOWRot
LOWHIGHBlau
HIGHLOWClear (kein Filter)
HIGHHIGHGrün

Gleich im Sketch schauen wir uns diese Kombinationen genauer an. Es fehlt allerdings noch der Pin OUT – hierüber liest dein Arduino die Messergebnisse ein.

Der Sketch zum Farben erkennen

Kommen wir also zum Code. Du benötigst für den Farbsensor keine eigene Bibliothek, sondern kannst die Messungen mit ein paar einfachen Funktionen selbst erledigen. Definiere zunächst die verwendeten Anschlüsse zu Beginn des Sketchs:

#define S0 6
#define S1 7
#define S2 8
#define S3 9
#define sensorOut 10

Anschließend benötigst du noch je drei Variablen für die Roh- und RGB-Werte der einzelnen Farben Rot, Grün und Blau:

int frequencyR = 0;
int frequencyG = 0;
int frequencyB = 0;

int red = 0;
int green = 0;
int blue = 0;

Die Setup-Funktion

Hier startest du deinen Seriellen Monitor und definierst die einzelnen pinModes:

Serial.begin(115200);

pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(sensorOut, INPUT);

Wie du siehst, sprichst du die Pins S1 bis S3 von deinem Arduino aus an (OUTPUT) und möchtest vom Pin sensorOut Messdaten erhalten (INPUT). Fehlt noch eine Sache: Wie oben kurz erwähnt, steuerst du mit den Pins S1 und S2 die Ausgangsfrequenz. Diese setzt du mit den folgenden zwei Zeilen auf 20%:

digitalWrite(S0, HIGH);
digitalWrite(S1, LOW);

Für die Ausgangsfrequenz gibt es festgelegte Werte und Kombinationen. Wenn du etwas tiefer einsteigen und die Ergebnisse deines Sensors optimieren möchtest, orientiere dich an dieser Tabelle:

S0S1Ausgangsfrequenz
LOWLOWAus
LOWHIGH2%
HIGHLOW20%
HIGHHIGH100%

Der Loop

Kommen wir also zu den Messungen. Im Loop deines Sketchs führst du für jede der drei Farben Rot, Grün und Blau eine separate Messung durch und rechnest deine Ergebnisse in den RGB-Farbraum um. Zunächst der Code für Rot:

digitalWrite(S2, LOW);
digitalWrite(S3, LOW);

frequencyR = pulseIn(sensorOut, LOW);
Serial.print("Red = ");
Serial.print(frequencyR);

Als erstes setzt du die beiden Pins S2 und S3 auf LOW, um nur die Photodioden mit rotem Farbfilter anzusprechen. Anschließend liest du den Wert mit der Funktion pulseIn() ein und speicherst den Wert in der Variablen frequencyR. Zuletzt gibst du ihn im Seriellen Monitor aus. In der Arduino-Referenz lernst du mehr über die Funktion pulseIn().

Mit diesen Messergebnissen kannst du noch nicht viel anfangen – besser ist es, wenn du einen bekannten Wert wie den Rotanteil im RGB-Modus erhältst. So kannst du nämlich zusammen mit den Ergebnissen der Farben Grün und Blau die Farbe vor deinem Sensor mehr oder weniger genau bestimmen und sie z.B. zur Kontrolle auf einem TFT-Display* anzeigen.

Um das zu erreichen, bietet sich die Funktion map() an:

map(frequencyR, 20, 120, 255, 0)

In dieser Funktion benötigst du fünf Argumente: Zunächst den Messwert frequencyR und den Messbereich des Sensors. Hierfür machst du am besten ein paar Testmessungen mit verschiedenfarbigen Objekten vor deinem Farbsensor und schaust dir die Minimal- und Maximalwerte im Seriellen Monitor an. Bei uns lagen die Werte ungefähr im Bereich von 20 bis 120 – das kann bei dir jedoch anders sein.

Wenn du deinen passenden Wertebereich ermittelt hast, kommen die letzten beiden Argumente ins Spiel. Diese geben den maximalen (255) und minimalen Rotwert (0) im RGB-Modus an. Je “mehr” Rot dein Farbsensor erkennt, desto geringer sein Messwert (bei uns also in Richtung 20). Das entspricht jedoch einem hohen Wert im RGB-Farbraum – deshalb “mappst” du die 20 auf die 255 und andersherum die 120 auf die 0.

Alle Farben zusammen

Und das war es im Prinzip. Für die Farben Blau und Grün wiederholst du einfach das Prozedere der Farbe Rot. In deinem Seriellen Monitor siehst du nun die RGB-Werte jeder einzelnen Farbe, die zusammen in etwa die Farbe des Objekts vor dem Sensor ergeben sollten.

Hier nun der gesamte Sketch zum Rauskopieren:

//pins for color sensor
#define S0 6
#define S1 7
#define S2 8
#define S3 9
#define sensorOut 10

//raw and RGB values for each color
int frequencyR = 0;
int frequencyG = 0;
int frequencyB = 0;

int red = 0;
int green = 0;
int blue = 0;

void setup() {
  Serial.begin(115200);

  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
}

void loop() {
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);

  frequencyR = pulseIn(sensorOut, LOW);
  Serial.print("Red = ");
  //Serial.print(frequencyR);
  red = map(frequencyR, 20, 150, 255, 0);
  Serial.print(red);


  digitalWrite(S2, LOW);
  digitalWrite(S3, HIGH);

  frequencyB = pulseIn(sensorOut, LOW);
  Serial.print(" Blue = ");
  //Serial.print(frequencyB);
  blue = map(frequencyB, 20, 150, 255, 0);
  Serial.print(blue);


  digitalWrite(S2, HIGH);
  digitalWrite(S3, HIGH);

  frequencyG = pulseIn(sensorOut, LOW);
  Serial.print(" Green = ");
  //Serial.println(frequencyG);
  green = map(frequencyG, 20, 150, 255, 0);
  Serial.println(green);

  delay(100);
}

Wie geht es weiter?

Du kannst nun Farben mit einem Farbsensor erkennen und sie in den RGB-Farbraum übertragen. Wie wäre es, wenn du dir einen eigenen Color Picker baust, mit dem du die RGB-Werte einzelner Objekte ermittelst? Hierfür bietet sich ein TFT-Display an, auf dem du die ermittelte Farbe auch gleich darstellen kannst.

]]>
Arduino Wettervorhersage https://polluxlabs.net/arduino-projekte/arduino-wettervorhersage/ Wed, 02 Dec 2020 10:34:52 +0000 https://polluxlabs.net/?p=4363 Arduino Wettervorhersage Weiterlesen »

]]>
Eine Wetterstation mit aktuellen Werten ist eine Sache – aber zu wissen, wie das Wetter in einigen Stunden sein wird, eine ganz andere. In diesem Projekt baust du dir so eine einfache Wettervorhersage mit dem Luftdrucksensor BMP180 und einem Servo.

Zugegeben, mit den Meteorologen in den Nachrichten kann dieses Projekt nicht mithalten, aber möglicherweise kann es dich vor den ganz großen Wetterumschwüngen warnen.

Anfänger

1 – 2 Stunden

ca. 10 € + Arduino

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

So funktioniert die Wettervorhersage

Wie eingangs erwähnt, ist eine Wettervorhersage eine komplexe Angelegenheit, an der Spezialisten mit Großcomputern arbeiten. Es gibt jedoch einen Zusammenhang, den wir uns in diesem Projekt zunutze machen: Steigt der Luftdruck, bessert sich das Wetter – fällt er, wird das Wetter schlecht.

Auch das ist eine starke Vereinfachung der Realität sein, aber dieser Zusammenhang soll uns hier einmal genügen. Immerhin wird dieses Prinzip schon seit Jahrhunderten angewandt. Sicherlich kennst du alte Barometer wie dieses hier:

Dosen-Barometer, Quelle: Wikipedia/Langspeed

Mehr über Barometer und die möglichen Anwendungen erfährst du auf Wikipedia. In unserer Arduino Wettervorhersage messen wir in regelmäßigen Abständen den Luftdruck und vergleichen ihn mit dem zuletzt gemessenen Wert. Fällt der Luftdruck immer weiter, dreht ein Servo-Motor einen Zeiger nach links in Richtung schlechtes Wetter. Wenn der Luftdruck kontinuierlich steigt, bewegt sich der Zeig nach rechts – es wird also gutes Wetter geben. Übrigens: Mit unserer ESP8266 Wetterstation speicherst du Daten zum Luftdruck lokal in einer Datenbank.

Luftdruck messen mit dem BMP180

Für die Messung des Luftdrucks verwenden wir den Sensor BMP180. Du kannst auch den genaueren BMP280* oder einen BME280* verwenden. Letzterer misst auch die Luftfeuchte, die wir in diesem Projekt jedoch nicht brauchen.

Diese Sensoren lassen sich leicht per I²C anschließen und mit einer passenden Bibliothek komfortabel verwenden. In diesem Tutorial erfährst du mehr darüber, wie du den BMP180 anschließt und verwendest.

Das Wetter mit einem Servo anzeigen

Es gibt viele denkbare Möglichkeiten, um die Veränderungen des Luftdrucks anzuzeigen: Verschiedene Displays oder auch ein NeoPixel LED-Ring. Hier verwenden wir jedoch einen Servo-Motor und eine passende Schablone. Diese können z.B. Kinder farbig gestalten und sie hat ebenso den gewissen Retro-Charme. 🙂

Schablone für den Servo der Wettervorhersage
Schablone für den Servo

Was ein Servo-Motor ist, wie funktioniert und was es alles zu beachten gibt, erfährst in diesem Tutorial zu Servos.

Der Aufbau der Arduino Wettervorhersage

Es dauert nur wenige Minuten, die Wettervorhersage auf deinem Breadboard aufzubauen. Orientiere dich hierbei an diesem Schema:

Aufbau der Arduino Wettervorhersage

Achte darauf, dass du den Servo mit 5V und den BMP180 mit 3,3V versorgst. Die Beschriftung der Pins des BMP180 befindet sich auf seiner Unterseite – vergewissere dich, dass du sie richtig am Arduino angeschlossen hast, bevor du ihn mit Strom versorgst.

Der Sketch

Es sind nicht viele Zeilen Code nötig, um die Wettervorhersage zum Laufen zu bringen. Starte wie so oft, indem du die nötigen Bibliotheken einbindest. Wie du sie installierst, erfährst du in den oben genannten Tutorials.

#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <Servo.h>

Anschließend erstellst du zwei Objekte – eines für den Luftdruck-Sensor und eines für den Servo:

Adafruit_BMP085 bmp;
Servo myServo;

Dazu benötigst du noch ein paar Variablen, um die Werte des Sensors und die gewünschte Position des Servos zu speichern:

int servoPosition;
long currentPressure;
long oldPressure;
int delta;

Die Setup-Funktion

Hier startest du den Seriellen Monitor und vergewisserst dich, dass der BMP180 richtig angeschlossen und funktionstüchtig ist. Anschließend weist du dem Servo den Anschlusspin 8 zu und drehst den Zeiger nach oben – auf 90°.

void setup() {
  Serial.begin(115200);
  if (!bmp.begin()) {
    Serial.println("Sensor not found!");
    while (1) {}
  }

  myServo.attach(8);
  myServo.write(90);
}

Übrigens: Wenn du nicht weißt, in welcher Position sich dein Servo gerade befindet und in welche Position der Zeiger bei der Montage schauen soll, dann bringe ihn erst nach dem Start an. Zu Beginn des Sketchs steht der Servo auf 90° – sodass der Zeiger nach oben gerichtet ist.

Der Loop der Arduino Wettervorhersage

Hier misst du als erstes den aktuellen Luftdruck und gibst ihn im Seriellen Monitor aus:

  currentPressure = bmp.readPressure();
  Serial.print("Current Pressure = ");
  Serial.print(currentPressure);
  Serial.println(" Pa");

Wie du siehst, geht das ganz einfach mit der Funktion bmp.readPressure(). Gleichzeitig speicherst du diesen Wert – der in Pascal ausgegeben wird – in der Variablen currentPressure.

Danach fragst du ab, ob sich der aktuelle Luftdruck gegenüber der Messung davor (gespeichert in der Variablen oldPressure) verändert hat. Falls ja, speicherst du diese Veränderung in der Variablen delta.

 if (oldPressure && currentPressure != oldPressure) {
   delta = currentPressure - oldPressure;

Im If-Statement siehst du die Bedingung oldPressure && – diese befindet sich hier, da es im ersten Messdurchgang noch keine alte Messung gibt. Erst wenn in dieser Variablen eine Zahl hinterlegt ist – sie also nicht mehr auf 0 bzw. false steht – wird diese Bedingung wahr. Alternativ kannst du auch folgendes schreiben:

 if (oldPressure == true && currentPressure != oldPressure) {

Den Servo steuern

Kommen wir zum Servo und der Anzeige der Wetterlage. Um die Veränderung des Luftdrucks in der Variablen delta anzuzeigen, musst du dem Servo mitteilen, wo er sich hindrehen soll. Ein Servo kann eine Position zwischen 0° und 180° einnehmen – zu Beginn des Sketchs steht er in der Mitte, also auf 90°.

Wir nehmen mal an, dass die maximale Veränderung in unserem Messzeitraum (mehr dazu gleich) bei +- 100 Pa liegt. Bei -100 Pa soll der Servo auf 0° fahren, bei +100 Pa entsprechend auf 180°. Hinweis: Möglicherweise liegen wir mit dieser Einschätzung falsch – hier sind also deine eigenen Experimente gefragt. Verfolge im Seriellen Monitor die Messwerte und kalibriere deine Wetterstation entsprechend.

Jedenfalls musst du die beiden Wertebereiche +-100 Pa und 0-180° unter einen Hut bringen. Hierfür bietet sich die Funktion map() an:

servoPosition = map(delta, -100, 100, 0, 180);

Hier nimmst du die aktuelle Veränderung delta, ihren möglichen Wertebereich +-100 und “mappst” diesen Wert auf die möglichen Winkel des Servos: 0° bis 180°. Heraus kommt der Winkel, der der Veränderung des Luftdrucks entspricht. Diesen speicherst du in der Variablen servoPosition.

Anschließend steuerst du deinen Servo auf diese Position:

myServo.write(servoPosition);

Danach machst du die aktuelle Messung zur alten Messung oldPressure, mit der du die nächste vergleichst. Und als letztes wartest du eine gewisse Zeit bis zur Messung, in diesem Fall 5 Minuten bzw. 300.000 Millisekunden.

oldPressure = currentPressure;
delay(300000);

Hier nun der gesamte Sketch der Arduino Wettervorhersage zum Rauskopieren und Hochladen. Viel Spaß! 🙂

#include <Wire.h>
#include <Adafruit_BMP085.h>

#include <Servo.h>

Adafruit_BMP085 bmp;
Servo myServo;

int servoPosition;
long currentPressure;
long oldPressure;
int delta;

void setup() {
  Serial.begin(115200);
  if (!bmp.begin()) {
    Serial.println("Sensor not found!");
    while (1) {}
  }

  myServo.attach(8);
  myServo.write(90);
}

void loop() {
  currentPressure = bmp.readPressure();
  Serial.print("Current Pressure = ");
  Serial.print(currentPressure);
  Serial.println(" Pa");

  if (oldPressure && currentPressure != oldPressure) {
    delta = currentPressure - oldPressure;
    Serial.print("Change: ");
    Serial.print(delta);
    Serial.println();
  }

  servoPosition = map(delta, -100, 100, 0, 180);
  myServo.write(servoPosition);
  
  oldPressure = currentPressure;

  delay(300000);
}

Fehlen dir noch Bauteile? Dann wirf einen Blick in unsere Übersicht der besten Arduino Starter Kits.

]]>
Die aktuelle Temperatur per Telegram abfragen https://polluxlabs.net/esp8266-projekte/die-aktuelle-temperatur-per-telegram-abfragen/ Wed, 21 Oct 2020 19:01:15 +0000 https://polluxlabs.net/?p=3163 Die aktuelle Temperatur per Telegram abfragen Weiterlesen »

]]>
In diesem Projekt verwendest du Telegram, um bei deinem ESP8266 nachzufragen, wie hoch die aktuelle Temperatur ist. Sobald dein ESP8266 deine Anfrage erhalten hat, fragt er die aktuelle Temperatur beim Sensor BMP180 ab und sendet sie dir auf dein Smartphone.

Dieses Projekt ist der dritte Teil einer Serie und baut auf die Vorgängerprojekte auf. In diesem Artikel findest du alles zum Aufbau und den passenden Sketch; wir besprechen jedoch nicht alle Teile des Codes. Wenn du mehr Details erfahren möchtest, wirf bitte einen Blick in die folgenden Projekte:

  1. Ein stiller Alarm mit Telegram und einem ESP8266
  2. Überwache die Temperatur mit Telegram und einem ESP8266

Falls du noch kein Projekt mit Telegram gebaut hast, lerne zunächst, wie du einen Telegram-Bot erstellst.

Anfänger

1 – 2 Stunden

ca. 12 €

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

Der Aufbau des Projekts

Wenn du das Vorgängerprojekt aufgebaut hast, dann musst du auf Seiten der Hardware nichts weiter tun – du kannst deinen Aufbau hier einfach weiterverwenden. 🙂

Aufbau des Temperatursensors

Im Sketch hat sich dafür einiges verändert:

Der Sketch

Kopiere den folgenden Sketch in deine Arduino IDE, ergänze deine Daten und lade ihn auf deinen ESP8266.

Sketch als .txt anschauen

/*
   Die Temperatur abfragen mit Telegram - polluxlabs.net
*/

//Bibliotheken
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

#include <Wire.h>
#include <Adafruit_BMP085.h>

// Deine WLAN-Zugangsdaten
const char* ssid = "NETZWERKNAME";
const char* password = "PASSWORT";

// Den Telegram-Bot initialisieren
#define botToken "TOKEN"  // den Bot-Token bekommst du vom Botfather)

//Deine UserID
#define userID "USERID"

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

Adafruit_BMP085 bmp;

//Variable für die Temperatur
float temp;

//Variable für die Anzahl der Anfragen
int numNewRequests;

//Variable für den Text der Anfrage, die du sendest
String text = "";

//UserID des Absenders
String chat_id = "";

//Name des Absenders
String from_name = "";

//Variable für die Willkommensnachricht
String welcome = "";

//Funktion fürs Verarbeiten neuer Anfragen
void handleNewRequests(int numNewRequests) {

  for (int i = 0; i < numNewRequests; i++) { //loopt durch die neuen Anfragen

    //Checkt, ob du die Anfrage gesendet hast oder jemand anderes
    chat_id = String(bot.messages[i].chat_id);
    if (chat_id != userID) {
      bot.sendMessage(chat_id, "Du bist nicht autorisiert!", "");
      continue;
    }

    // Anfragetext speichern
    text = bot.messages[i].text;
    Serial.println(text);

    from_name = bot.messages[i].from_name;

    if (text == "/start") {
      welcome = "Willkommen, " + from_name + ".\n";
      welcome += "Mit folgendem Befehl fragst du die aktuelle Temperatur ab: \n\n";
      welcome += "/messen \n";
      bot.sendMessage(chat_id, welcome, "");
      bot.sendMessage(chat_id, "http://gph.is/2aLXZ8H", "");
    }

    if (text == "/messen") {
      temp = bmp.readTemperature();
      bot.sendMessage(chat_id, "Temperatur: " + String(temp) + " ºC", "");
    }
  }
}

void setup() {
  
  Serial.begin(115200);
  client.setInsecure();

  //Verbindung zum WLAN
  Serial.print("Verbinde mich mit: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  if (!bmp.begin()) {
    Serial.println("Kein Sensor gefunden! Checke die Verbindung.");
    while (1) {}
  }
}

void loop() {

  //checkt, ob eine neue Anfrage reinkam
  int numNewRequests = bot.getUpdates(bot.last_message_received + 1);

  while (numNewRequests) { //wird ausgeführt, wenn numNewRequests == 1
    Serial.println("Anfrage erhalten");
    handleNewRequests(numNewRequests);
    numNewRequests = bot.getUpdates(bot.last_message_received + 1);
  }
  delay(1000);
}

Was ist neu in diesem Sketch?

In diesem Sketch läuft einiges anders: In den zwei vorangegangenen Projekten hat dein ESP8266 nur Nachrichten gesendet, in diesem Projekt wartet er jedoch auf eine Nachricht von dir – die er dann selbst mit der aktuellen Temperatur beantwortet.

Dafür muss dein ESP8266 – im Gegensatz zu den vorherigen Projekten – die ganze Zeit mit deinem WLAN verbunden sein. Deshalb wandert der Code, mit dem du die Verbindung herstellst, direkt in die Setup-Funktion:

  Serial.print("Verbinde mich mit: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

Schauen wir jetzt direkt in den Loop. Dort prüft dein ESP8266 alle 1000 Millisekunden, ob eine neue Anfrage vorliegt:

int numNewRequests = bot.getUpdates(bot.last_message_received + 1);

Wenn das der Fall ist, wird in der Variablen numNewRequests mithilfe der Funktion bot.getUpdates() die Anzahl der vorliegenden Anfragen gespeichert (im Normalfall eine 1, aber es können theoretisch ja auch mehrere vorliegen).

Das wiederum setzt den folgenden While-Loop in Gang, der die Funktion handleNewRequests() so oft aufruft wie Anfragen “abzuarbeiten” sind. In diesem Loop wird auch die Variable numNewRequests aktualisiert – sobald hier wieder eine 0 enthalten ist, endet der Loop.

while (numNewRequests) {
  handleNewRequests(numNewRequests);
  numNewRequests = bot.getUpdates(bot.last_message_received + 1);
  }

Die Funktion handleNewRequests()

Kommen wir zum Kernstück des Sketchs. Diese Funktion handleNewRequests() erwartet bei Ihrem Aufruf ein Argument – nämlich die Anzahl der vorliegenden Anfragen, die in der Variablen numNewRequests steckt. Diese hast du beim Aufruf der Funktion im While-Lopp bereits mitgegeben:

handleNewRequests(numNewRequests);

Bei der Deklaration der Funktion taucht diese Variable wieder auf, um dann gleich weiterverarbeitet zu werden. Diesmal iterierst du mit einem For-Loop über die Anzahl der Anfragen, um sie eine nach der anderen abzuarbeiten:

void handleNewRequests(int numNewRequests) {
  for (int i = 0; i < numNewRequests; i++) { 

Innerhalb des Loops findet zuerst eine sehr wichtige Prüfung statt – nämlich ob die Anfrage überhaupt von einem autorisierten User (also von dir) stammt. Hierfür speicherst du die chat_id, die mit jeder Anfrage übergeben wird, in der gleichnamigen Variablen.

Anschließend prüfst du, ob diese mit deiner eigenen UserID übereinstimmt. Ist das nicht der Fall, erhält der Absender eine entsprechende Nachricht und der For-Loop wird mit continue abgebrochen:

chat_id = String(bot.messages[i].chat_id);
if (chat_id != userID) {
  bot.sendMessage(chat_id, "Du bist nicht autorisiert!", "");
  continue;
}

Wenn die Anfrage jedoch von dir stammt, speicherst du ihren Textinhalt und den Namen des Absenders (also wiederum deinen) ab:

text = bot.messages[i].text;
from_name = bot.messages[i].from_name;

Fehlen nur noch zwei If-Statements. Wenn du deinen Telegram-Bot zum ersten Mal startest, machst du das mit dem Text /start (den du natürlich auch senden kannst, wenn der Bot schon läuft). In diesem Fall erscheint eine kleine Begrüßungsnachricht mit einer Erklärung: Um die aktuelle Temperatur abzufragen, musst du deinem Bot (und damit deinem ESP8266) die Nachricht /messen schicken.

Begrüßung im Chat
Du kannst auch GIFs senden

Hier werden wieder Strings miteinander verbunden, diesmal mit dem Operator +=, der einfach die Variable welcome um weiteren Text erweitert. Auch beachtenswert: Mit \n kannst du einen Zeilenumbruch einfügen.

Am Ende des Statements findest du wieder die Funktion bot.sendMessage(), die du bereits kennengelernt hast. Diese taucht hier gleich zweimal auf: Einmal, um den String welcome zu senden und dann noch einmal, um ein GIF hinterherzuschicken. Wenn du spaßeshalber auch GIFs senden möchtest, reicht dafür einfach die entsprechende URL der Datei.

if (text == "/start") {
  welcome = "Willkommen, " + from_name + ".\n";
  welcome += "Mit folgendem Befehl fragst du die aktuelle Temperatur ab: \n\n";
  welcome += "/messen \n";
  bot.sendMessage(chat_id, welcome, "");
  bot.sendMessage(chat_id, "http://gph.is/2aLXZ8H", "");
}

Die zweite Abfrage kümmert sich um die Anfrage /messen, die mit der aktuellen Temperatur beantwortet werden soll. Auch das kennst du bereits aus den vorangegangenen Projekten:

if (text == "/messen") {
  temp = bmp.readTemperature();
  bot.sendMessage(chat_id, "Temperatur: " + String(temp) + " ºC", "");
}

Und das war es auch schon. Du hast in dieser Lektion gelernt, wie du nicht nur Nachrichten von deinem ESP8266 an deinen Telegram-Bot senden kannst, sondern auch von dort aus Sensordaten abrufen kannst.

Wie geht es weiter?

Du kannst natürlich nicht nur die Temperatur abfragen. Der Sensor BMP180 kann auch den Luftdruck ermitteln. Der Nachfolger BMP280 misst sogar die Luftfeuchtigkeit. Baue z.B. eine Wetterstation, bei der du die aktuellen Daten aus der Ferne abfragst.

Eine weitere Möglichkeit ist ein Feuchtigkeitssensor, den du neben eine Pflanze in die Erde steckst. Wenn du denkst, die Erde sei zu trocken, kannst du eine automatische “Gießkanne” von deinem Smartphone aus steuern.

]]>
Überwache die Temperatur mit Telegram und einem ESP8266 https://polluxlabs.net/esp8266-projekte/ueberwache-die-temperatur-mit-telegram-und-einem-esp8266/ Mon, 19 Oct 2020 14:42:24 +0000 https://polluxlabs.net/?p=3147 Überwache die Temperatur mit Telegram und einem ESP8266 Weiterlesen »

]]>
In diesem Projekt überwachst du die Temperatur mit einem Sensor und deinem ESP8266. Sobald der Temperatursensor einen von dir festgelegten Wert ermittelt, sendet dein Microcontroller eine Nachricht an deinen Telegram-Bot.

Dieses Projekt ist der zweite Teil einer Serie: Inhaltlich baut es auf unserem Stillen Alarm mit Telegram auf. Schaue dort hinein, um mehr über die grundlegenden Funktionen des Sketchs zu erfahren. Auch in diesem Projekt wartet dein ESP8266 darauf, dass ein bestimmtes Ereignis eintritt. Allerdings wird er hier nicht durch einen Interrupt getriggert, sondern fragt selbst die Daten eines Temperatursensors ab.

Anfänger

1 – 2 Stunden

ca. 12 €

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

Der passende Temperatursensor

In diesem Projekt verwenden wir den Sensor BMP180. Du kannst aber natürlich auch jeden anderen Temperatursensor verwenden – z.B. einen einfachen TMP36, einen DHT22 oder einen GY-906. Denke in diesem Fall daran, deinen Sketch entsprechend anzupassen.

In diesen Tutorials lernst du, wie du einen TMP36 und einen GY-906 anschließt und verwendest.

Der Aufbau des Projekts

Du benötigst nur deinen ESP8266, den Temperatursensor (in unserem Fall einen BMP180), ein Breadboard und Kabel. Orientiere dich beim Aufbau an diesem Schema:

Aufbau Temperatursensor am ESP8266

Der Sensor BMP180 wird per I²C angeschlossen. Am ESP8266 musst du deshalb zwingend die beiden Pins D1 und D2 verwenden. Schließe den Sensor wie folgt an:

BMP180ESP8266
VIN3v3
GNDGND
SDAD2
SCLD1

Der Sketch

___STEADY_PAYWALL___

Kopiere den folgenden Sketch in deine Arduino IDE, ergänze deine Daten und lade ihn auf deinen ESP8266.

Sketch als .txt anschauen

/*
   Die Temperatur überwachen mit Telegram - polluxlabs.net
*/

//Bibliotheken
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

#include <Wire.h>
#include <Adafruit_BMP085.h>

// Deine WLAN-Zugangsdaten
const char* ssid = "NETZWERKNAME";
const char* password = "PASSWORT";

// Den Telegram-Bot initialisieren
#define botToken "DEIN TOKEN"  // den Bot-Token bekommst du vom Botfather)

//Deine UserID
#define userID "DEINE USERID"

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

Adafruit_BMP085 bmp;

//Variablen für die Temperatur
float temp;
float threshold = 27.00;

//Verbindung zum WLAN
void connectToWiFi() {
  Serial.print("Verbinde mich mit: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

void setup() {
  Serial.begin(115200);
  client.setInsecure();

  if (!bmp.begin()) {
    Serial.println("Kein Sensor gefunden! Checke die Verbindung.");
    while (1) {}
  }
}

void loop() {
  temp = bmp.readTemperature();
  Serial.print("Temperatur = ");
  Serial.print(temp);
  Serial.println(" °C");

  if (temp > threshold) { //Die Temperatur, die überschritten werden muss
    connectToWiFi();
    bot.sendMessage(userID, "Temperatur zu hoch!  " + String(temp) + " °C", "");
    Serial.println("Temperatur zu hoch!");
    WiFi.disconnect();
    delay(300000);
  }
  delay(500);
}

Was ist neu in diesem Sketch?

Vieles im Code haben wir schon im Stillen Alarm verwendet. Ein paar Teile sind jedoch neu und diese schauen wir uns nun genauer an.

Zunächst benötigst du zwei weitere Bibliotheken. Wire.h ist für die Kommunikation per I²C zuständig. Diese Bibliothek ist standardmäßig bereits vorinstalliert. Damit du den Sensor BMP180 so einfach wie möglich verwenden kannst, existiert ebenfalls eine passende Bibliothek: Arduino_BMP085.h. Lass dich nicht vom Namen irritieren. Dort steht zwar BMP085 (das ist der Vorläufer des BMP180), sie funktioniert jedoch auch mit dem BMP180 problemlos.

Am Anfang deines Sketchs bindest du also zusätzlich diese beiden Bibliotheken ein:

#include <Wire.h>
#include <Adafruit_BMP085.h>

Ebenfalls zu Beginn des Sketchs erstellst du für den Sensor das Objekt bmp sowie zwei Variablen: eine für die gemessene Temperatur (temp) und eine für den Schwellenwert (threshold), bei dessen Überschreiten dein ESP8266 eine Nachricht an dich sendet. In unserem Beispiel setzen wir diesen Schwellenwert auf 27,00 °C. Da der BMP180 die Temperatur als Kommazahl ausgibt, benötigst du für diese Variablen den Dateityp float.

Adafruit_BMP085 bmp;
float temp;
float threshold = 27.00;

In der Setup-Funktion prüfst du, ob der Temperatursensor von deinem ESP8266 gefunden wurde und verwendet werden kann. Ist das nicht der Fall, wirst du im Seriellen Monitor darüber informiert und der Sketch begibt sich mit while(1) in eine Endlosschleife – friert also ein.

  if (!bmp.begin()) {
    Serial.println("Kein Sensor gefunden! Checke die Verbindung.");
    while (1) {}
  }

Solltest den obigen Text also in deinem Seriellen Monitor zu Gesicht bekommen, trenne deinen ESP8266 vom Strom und überprüfe deine Verkabelung. In den meisten Fällen sollte hier der Fehler liegen.

Der Loop

Im Loop fragst du die Temperatur im Halbsekundentakt ab und prüfst mit einem Schwellenwert, ob sie diesen überschritten hat.

temp = bmp.readTemperature();

Wenn das der Fall ist, verbindet sich dein ESP8266 mit dem Internet und sendet eine entsprechende Nachricht an dein Smartphone.

if (temp > threshold) { //Wenn die Temperatur über dem Schwellenwert liegt
    connectToWiFi();
    bot.sendMessage(userID, "Temperatur zu hoch!  " + String(temp) + " °C", "");

Die Funktion bot.sendMessage() besteht aus drei Teilen. Der mittlere ist die Nachricht selbst, die du hier jedoch aus zwei Strings und der Variablen temp “zusammenbaust”. Hierfür verbindest du die einzelnen Teilstrings einfach mit einem Pluszeichen – doch Vorsicht: In der Mitte befindet sich die Variable temp als float. Um den Wert in dieser Variablen senden zu können, musst du diese erst mit der Funktion String(temp) in einen String umwandeln.

Auf deinem Smartphone erscheint dann der Text: “Temperatur zu hoch! x °C” – wobei das x für die gemessene Temperatur steht.

Zuletzt trennt dein ESP8266 die Verbindung zu deinem WLAN wieder und setzt sich für 5 Minuten (300.000 Millisekunden) zur Ruhe. Erst dann beginnt er wieder damit, alle 500 Millisekunden die Temperatur vom BMP180 abzufragen.

    WiFi.disconnect();
    delay(300000);
  }
  delay(500);
}

Sollte danach die Temperatur immer noch über dem Schwellenwert liegen, erhältst du eine weitere Nachricht.

Falls noch nicht geschehen, lade den Sketch auf deinen ESP8266 und probiere ihn gleich aus.

Das passende Gehäuse

Möchtest du das Projekt in einem kleinen Gehäuse unterbringen? Hier findest du passende 3D-Druck-Dateien, die du herunterladen und ausdrucken kannst.

Wie geht es weiter?

Im nächsten Teil der Serie wartest du nicht darauf, bis dein ESP8266 sich bei dir meldet, sondern fragst die Temperatur selbst von deinem Smartphone aus ab.

Statt eines Temperatursensors kannst du auch andere Sensoren einsetzen: So kannst du dich warnen lassen, wenn die Luft zu schlecht oder das Licht zu hell ist. Es gibt auch Sensoren, die Flammen erkennen können – solltest du diesen einsetzen, hoffen wir, dass du niemals eine entsprechende Nachricht erhältst!

]]>
Ein stiller Alarm mit Telegram und einem ESP8266 https://polluxlabs.net/esp8266-projekte/ein-stiller-alarm-mit-telegram-und-einem-esp8266/ Tue, 22 Sep 2020 21:04:52 +0000 https://polluxlabs.net/?p=2494 Ein stiller Alarm mit Telegram und einem ESP8266 Weiterlesen »

]]>
In diesem Projekt baust du dir einen Bewegungsmelder, der dir eine Nachricht schickt, wenn sich vor ihm jemand bewegt. Im Prinzip handelt es sich hierbei um einen stillen Alarm – also eine Alarmanlage, die keinen Lärm macht, sondern ganz diskret mitteilt, das etwas im Gang ist.

Zum Einsatz kommt hierbei der Sensor HC-SR501. Diese Art von Sensoren kennst du von den handelsüblichen Bewegungsmeldern, die das Licht anschalten, sobald jemand an ihm vorbeikommt.

Das ist ein sogenannter PIR-Sensor – PIR steht für Passive Infrared. Dieser Sensor erkennt also Infrarotstrahlung bzw. Wärme, die von Körpern abgestrahlt wird. Darüber hinaus springt er nur an, wenn sich dieser Körper bewegt – denn sonst würde er schließlich auch bei einer warmen Heizung Alarm schlagen.

Heißt also konkret: Sobald eine Person (oder auch eine Katze oder ein Hund) in die Reichweite des Bewegungsmelders gerät, registriert dieser die abgestrahlte Wärme sowie die Bewegung und gibt dir Bescheid.

Anfänger

1 – 2 Stunden

ca. 10 €

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

Telegram vorbereiten

Zunächst benötigst du einen Account bei Telegram – und die dazugehörige App für dein Smartphone oder den Computer. Im Folgenden verwenden wir ein Smartphone. Telegram ist kostenlos, werbefrei und funktioniert so ähnlich wie WhatsApp. Allerdings hast du hier die Möglichkeit, Bots zu erstellen, mit denen du interagieren kannst.

Das machst du dir in diesem Projekt zunutze, indem du deinen ESP8266 mit deinem Telegram-Bot “sprechen” lässt. Der Bot wiederum sendet dir daraufhin umgehend eine Benachrichtigung.

In diesem Tutorial auf Pollux Labs lernst du, wie du deinen eigenen Telegram-Bot erstellst.

Das Projekt aufbauen

Der Aufbau auf dem Breadboard geht ganz fix: Du musst nur den Bewegungssensor mit deinem ESP8266 verbinden:

Die Beschriftung der Pins am Sensor siehst du, wenn du die weiße Kappe abhebst. Verbinde den Sensor und deinen ESP8266 wie folgt:

HC-SR501ESP8266
GNDGND
OUTD5
VCC3v3

Das war es auch schon mit der Hardware. Werfen wir einen Blick auf den Code.

Der Sketch für den Bewegungsmelder

Nun wird es Zeit für etwas Code. Falls du noch nie einen ESP8266 mit der Arduino IDE verwendet hast: In diesem Tutorial lernst du, wie du deinen ESP8266 in der Arduino IDE verfügbar machen und programmieren kannst.

Die benötigten Bibliotheken

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

Du benötigst insgesamt drei Bibliotheken. Zwei davon sollten bei dir schon vorinstalliert sein: ESP8266WiFi.h und WiFiClientSecure.h – du benötigst sie für die Verbindung zu deinem WLAN-Netzwerk und zum Senden der Daten.

Die Bibliothek UniversalTelegramBot.h übernimmt die Kommunikation mit deinem Telegram-Bot. Du findest sie im Bibliotheksverwalter der Arduino IDE –diese kann jedoch veraltet sein. Deshalb empfehlen wir dir, die Bibliothek hier bei uns herunterzuladen.

Anschließend musst du diese Bibliothek in deinen Sketch einbinden, indem du im Menü der Arduino IDE Sketch -> Bibliothek einbinden -> .ZIP-Bibliothek hinzufügen wählst und die gerade heruntergeladene ZIP-Datei auswählst.

Kopiere dir nun den folgenden Sketch und lade ihn auf deinen ESP8266.

Hinweis: Bevor dein Telegram-Bot Nachrichten empfangen kann, musst du ihn erst aufrufen und auf Start tappen. Das musst du allerdings nur einmal zu Beginn tun.

Sketch als .txt anschauen

/*
   Stiller Alarm mit Telegram - polluxlabs.net
*/

//Bibliotheken
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Deine WLAN-Zugangsdaten
const char* ssid = "NETZWERKNAME";
const char* password = "PASSWORT";

// Den Telegram-Bot initialisieren
#define botToken "DEIN TOKEN"  // den Bot-Token bekommst du vom Botfather)

//Deine User ID
#define userID "DEINE USERID"

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

const int sensor = 14; // Pin des Bewegungssensors, auf dem ESP Pin D5
bool motion = false;

// Indicates when motion is detected
void IRAM_ATTR detectingMovement() {
  motion = true;
}

//Verbindung zum WLAN
void connectToWiFi() {
  Serial.print("Verbinde mich mit: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

void setup() {
  Serial.begin(115200);
  client.setInsecure();

  // Verwendeter Pin
  pinMode(sensor, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(sensor), detectingMovement, RISING);
}

void loop() {

  if (motion == true) {
    connectToWiFi();
    bot.sendMessage(userID, "Hier bewegt sich etwas!", "");
    Serial.println("Bewegung erkannt");
    motion = false;
    WiFi.disconnect();
  }
}

Der Sketch Schritt für Schritt

Schauen wir uns nun ein paar wichtige Teile des Sketchs für deinen Bewegungsmelder genauer an.

Zunächst gibt es einige Daten, die du durch deine eigenen ersetzen musst: Deine WLAN-Zugangsdaten sowie dein Token und deine User ID von Telgram. Trage diese Daten hier ein:

const char* ssid = "DEIN WLAN-NETZWERK";
const char* password = "DEIN PASSWORT";
#define botToken "DEIN TOKEN"
#define userID "DEINE USER ID"

Anschließend erstellst du eine Instanz von WiFiClientSecure names client und ebenso einen bot mit deinem oben definierten botToken und dem client.

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

Jetzt fehlen noch eine Konstante und eine Variable. In ersteren legst du du den Pin fest, an dem der Sensor angeschlossen ist. Hinweis: Die Zahlen auf dem ESP8266 und im Sketch unterscheiden sich. Wenn du den Sensor am Pin D5 angeschlossen hast, entspricht das im Sketch der 14.

Die Variable motion setzt du hier zu Beginn des Sketchs auf false. Diese Variable kann zwei Zustände haben: false, wenn keine Bewegung erkannt wird und true, wenn genau das der Fall ist. Du benötigst also den Datentyp bool, der nur diese zwei Werte annehmen kann.

const int sensor = 14; // Pin des Sensors, am ESP8266 Pin D5
bool motion = false; // Variable für eine erkannte Bewegung

Die Funktionen im Sketch

Jetzt kommt die erste Funktion ins Spiel. Diese Callback-Funktion wird aufgerufen, sobald der Sensor eine Bewegung erkennt und eine 1 (HIGH) an deinen ESP8266 sendet.

Die Funktion macht nichts anderes als die gerade definierte Variable motion auf true zu setzen. Das wiederum setzt die Nachricht an deinen Telegram-Bot in Gang – was wir uns gleich genauer anschauen werden.

void IRAM_ATTR detectingMovement() {
  motion = true;
}

Zunächst steht im Sketch jedoch noch eine weitere Funktion, die deinen ESP8266 mit dem Internet verbindet, sobald eine Bewegung erkannt wurde.

void connectToWiFi() {
  Serial.print("Verbinde mich mit: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password); //hast du zu Beginn hinterlegt
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }
  Serial.println("");
  Serial.println("Verbunden!");
}

Die Setup-Funktion

Auch hier musst du noch ein paar grundlegende Dinge erledigen: Den seriellen Monitor starten, den client konfigurieren und den pinMode für den angeschlossenen Sensor festlegen. 

Mit der Funktion attachInterrupt definierst du die Bewegungsmeldung. Im ersten Parameter steht der Pin, an dem der Sensor angeschlossen ist. Im zweiten, was passieren soll, wenn etwas erkannt wurde: die Funktion detectingMovement() ausführen. Der dritte Parameter definiert, wann das passieren soll – nämlich wenn das Signal am Pin von LOW auf HIGH wechselt.


Genauere Erläuterungen dieser Funktion findest du in der Arduino-Referenz.

void setup() {
  Serial.begin(115200);
  client.setInsecure();
  pinMode(sensor, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(sensor), detectingMovement, RISING);
}

Der Loop

Hier kommt also der entscheidende Teil des Sketches. Der Loop läuft die meiste Zeit, ohne dass er irgendetwas ausführt. Erst wenn der Sensor ein Signal sendet und der Interrupt die Variable motion auf true setzt, wird die Bedinung im If-Statement erfüllt und einiges in Gang setzt.
Zunächst wird die Funktion connectToWiFi() aufgerufen und dein ESP8266 verbindet sich mit dem Internet.

Die Nachricht senden

Anschließend sendet er mit bot.sendMessage() eine Nachricht an deinen Telegram-Bot. 

Das ist sozusagen das Herzstück deines Sketchs. Die Funktion sendMessage() benötigt drei Argumente: 

  1. deine userID, die du oben im Sketch eingetragen hast
  2. eine Nachricht deiner Wahl als String
  3. den Parse Mode – Optional, lassen wir in diesem Projekte leer

Wenn also dein ESP8266 mit dem Internet verbunden ist, sollte nach wenigen Sekunden die Nachricht auf deinem Smartphone erscheinen.

Zuletzt wird die Variable motion wieder auf false gesetzt und die Verbindung zum Internet gekappt.

void loop() {

  if (motion == true) {
    connectToWiFi();
    bot.sendMessage(userID, "Hier bewegt sich etwas!", "");
    Serial.println("Bewegung erkannt");
    motion = false;
    WiFi.disconnect();
  }
}

Danach befindet sich dein Projekt wieder im Ausgangszustand und wartet auf die nächste Bewegung.
Falls noch nicht geschehen, lade den Sketch auf deinen ESP8266 und probiere ihn gleich aus. Und vergiss nicht: Vor dem ersten Test musst du deinen Bot zunächst einmalig starten, indem du auf start tappst.

Feinjustierung des Sensors

Auf der Unterseite des Sensors findest du zwei Potentiometer. Wenn du Sensor umdrehst, sodass die Platine nach oben zeigt, kannst du am linken Potentiometer die Empfindlichkeit einstellen. Experimentiere hiermit etwas, um die optimale Reichweite des Bewegungsmelders einzustellen.

Am rechten Potentiometer lässt sich einstellen, wie lange der Sensor ein HIGH-Signal sendet, bevor er wieder zurückgesetzt wird und neue Bewegungen erkennen kann. Diese Funktion nutzt du in diesem Projekt allerdings nicht, da der Sensor hier einen Interrupt triggert. Wie lange der Sensor das HIGH-Signal sendet, spielt hier keine Rolle.

Wie geht es weiter?

Du hast nun einen Bewegungsmelder, den du als stillen Alarm einsetzen kannst und der dir Nachrichten an deinen Telegram-Bot sendet. Im zweiten Teil dieser Projektserie überwachst du die Temperatur: Sobald ein von dir bestimmter Wert überschritten wurde, erhältst du eine Nachricht aufs Smartphone.

Auf pollux labs haben wir viele Tutorials und Projekte, die sich mit Temperatur- und anderen Sensoren beschäftigen.

Viel Spaß beim Ausprobieren! 🙂

]]>
Komplexe Gesten erkennen mit künstlicher Intelligenz und deinem Arduino https://polluxlabs.net/arduino-projekte/komplexe-gesten-erkennen-mit-kuenstlicher-intelligenz-und-deinem-arduino/ Wed, 26 Aug 2020 16:31:06 +0000 https://polluxlabs.net/?p=2257 Komplexe Gesten erkennen mit künstlicher Intelligenz und deinem Arduino Weiterlesen »

]]>
In diesem Projekt entwickelst du ein KI-Modell, das Gesten wie Kreisbewegungen und Winken erkennen kann. Anschließend lädst du es auf deinen Arduino Nano 33 BLE Sense und lässt dir die erkannten Bewegungen im Terminal deines PCs oder Macs anzeigen.

Mit diesem Setting kannst du später aufwändigere Projekte bauen, um z.B. das Licht durch Gesten an- und ausschalten zu können.

Anfänger

1 – 2 Stunden

Für dieses Projekt benötigst du:

Einen kostenlosen Account bei Edge Impulse und einen Arduino Nano 33 BLE Sense.

Arduino® Board Nano 33 BLE Sense with headers
Arduino® Board Nano 33 BLE Sense with headers
Arduino Board Nano 33 BLE Sense with headers; Inhalt: 1 Stück

Vorbereitungen

In unserem Tutorial Gesten erkennen mit dem Sensor APDS9960 haben wir beschrieben, wie du mit dem Arduino Nano 33 BLE Sense Bewegungen nach oben, unten, rechts und links erkennen kannst. Dieser Microcontroller kann aber deutlich mehr!

Du kannst ihn mit ein paar Vorbereitungen mit dem Service von Edge Impulse verbinden und seinen Beschleunigungssensor verwenden, um viel anspruchsvollere Gesten und Muster erkennen zu können.

Lies zunächst nach, wie du deinen Arduino mit Edge Impulse verbindest.

Bewegungsdaten sammeln

Am Anfang jeder künstlichen Intelligenz stehen Daten. Das bedeutet, dass du zunächst Daten zu den Bewegungen sammeln musst, die du später voneinander unterscheiden möchtest.

In diesem Tutorial lernst du, wie du Bewegungsdaten mit dem Arduino Nano 33 BLE Sense sammeln und speichern kannst. Auf dieses Tutorial bauen wir hier auf.

In diesem Projekt nutzt du dieses Wissen und bringst deinem Arduino bei zu erkennen, ob du eine Kreisbewegung ausführst, in der Luft winkst oder – nichts tust. Öffne in Edge Impulse als den Menüpunkt Data acquisition und sammle Samples für die zwei Bewegungen und den Ruhezustand – jeweils circa 3 Minuten.

Achte darauf, dass sich deine Bewegungen innerhalb einer Geste nicht zu sehr unterscheiden. Eine leichte Varianz ist aber normal und auch gut. Wenn du fertig bist, sollte dein Screen ungefähr so aussehen:

Anschließend geht es mit dem Training des KI-Modells weiter.

Einen Impulse entwickeln

Jetzt geht es weiter mit dem nächsten Menüpunkt: Impulse design. Hier entwickelst du aus deinen Rohdaten sogenannte Features, mit denen später deine Bewegungen analysiert und zugeordnet werden können.

Links siehst du die Karte Time series data – hier musst du zunächst nichts einstellen. Klicke stattdessen rechts daneben auf Add a processing block und wähle anschließend den Eintrag Spectral Analysis. Dieser Block eignet sich besonders für Bewegungsdaten.

Wähle eine Karte weiter den Eintrag Neural Network (Keras). Klicke zuletzt auf Save Impulse.

Neben dem Menüpunkt Create impulse sollte nun ein grüner Punkt erscheinen. Klicke nun gleich darunter auf Spectral features und anschließend oben auf Generate features.

Features generieren in Edge Impulse

Hier gibt es nichts weiter zu tun als auf den Button Generate features zu klicken. Diese Prozedur läuft nun durch und sollte nur wenige Sekunden dauern. Sobald sie abgeschlossen ist, siehst du rechts eine Visualisierung der Features und der Cluster, die sie bilden.

Die fertig generierten Feature-Cluster in Edge Impulse

Wie du oben siehst, bilden die verschieden farbigen Punkte eigene Cluster, die voneinander entfernt liegen. Das sollte auch bei deinen Bewegungsdaten der Fall sein. Je besser du die Cluster voneinander unterscheiden kannst, desto besser kann das auch später dein KI-Modell.

Solltest du nur einen Haufen bunter Punkte sehen, gehe noch einmal zurück und sammle weitere oder neue Bewegungsdaten.

Das neuronale Netz trainieren

Edge Impulse hat nun klar definierte Daten und Klassen, die gut voneinander zu unterscheiden sind. Fehlt nur noch ein neuronales Netz, das neue Daten einem dieser Klassen zuordnen kann.

Kurz gesagt, ist ein neuronales Netz nichts anderes als Algorithmen, die versuchen Muster zu erkennen. Auf Wikipedia lernst du mehr über dieses Thema.

Klicke nun im Menü auf den nächsten Punkt NN Classifier.

Der NN Classifier in Edge Impulse

Belasse die Einstellungen zunächst so wie sie sind und klicke auf den Button Start training. Das nun folgende Training des Netzes sollte wenige Minuten in Anspruch nehmen.

Anschließend erscheint eine neue Karte mit den Ergebnissen. Oben links siehst du unter Accuracy, wie akkurat dein neuronales Netz arbeitet. In unserem Fall kam eine Genauigkeit von 100% heraus, was darauf hoffen lässt, dass die Bewegungen und Gesten richtig erkannt werden.

Ergebnisse des Trainings des neuronalen Netzes

Wenn du eine niedrigere Genauigkeit erhalten hast, findest du hinter dem Link Model performing poorly? unten rechts Tipps, wie du ein besseres KI-Modell entwickeln kannst.

Ein erster Test der künstlichen Intelligenz

Jetzt wird es spannend: Erkennt deine KI die Bewegungen, die du mit deinem Arduino Nano 33 BLE Sense ausführst, richtig?

Klicke im Menü auf den Punkt Live classification. Hier kannst einen ersten Test starten, indem du auf den Button Start sampling klickst und eine der trainierten Bewegungen ausführst.

Nachdem du das Sample aufgenommen hast, erscheint das Ergebnis. Wir haben eine Kreisbewegung ausgeführt, was die künstliche Intelligenz richtig der Klasse circle zugeordnet hat.

Ergebnis der Klassifizierung in Edge Impulse

Sollte das bei dir nicht funktioniert haben, gehe am besten wieder ein paar Schritte zurück und versuche bessere Bewegungsdaten zu sammeln oder dein neuronales Netz besser zu trainieren.

Wenn du aber zufrieden bist, wird es Zeit die KI auf deinen Arduino zu bringen.

Die KI auf dem Arduino ausführen

Klicke hierfür auf den Menüpunkt Deployment und wähle unter der Überschrift Build firmware den Arduino Nano 33 BLE Sense.

Du kannst dir auch eine Arduino-Bibliothek erstellen lassen, die du in einen Sketch einbinden kannst. Wir bleiben hier jedoch bei der einfacheren Variante.

Die Firmware für den Arduino Nano 33 BLE Sense erstellen

Weiter unten hast du auch die Möglichkeit, Optimierungen an deinem KI-Modell vorzunehmen, aber auch diese lassen wir hier erst einmal beiseite.

Klicke als nächstes auf den Button Build. Jetzt wird die Firmware mit deinem KI-Modell erstellt, was wieder einige Minuten dauern kann.

Als nächstes erhältst du eine Zip-Datei mit der Firmware. Führe, je nachdem welches Betriebssystem du verwendest, eine der folgenden Dateien aus:

  • flash_windows.bat
  • flash-mac.command
  • flash_linux.sh

Achte darauf, dass du das Terminal, in dem das Sampling der Daten läuft, vorher schließt und diesen Prozess beendest.

Öffne nach dem Installieren der Firmware ein neues Terminal-Fenster und führe diesen Befehl aus:

edge-impulse-run-impulse

Jetzt läuft deine KI in diesem Terminal und prüft alle zwei Sekunden, ob sie eine Bewegung deines Arduinos erkennt und wenn ja, welche. Hier hat sie mit einer Wahrscheinlichkeit von 96% ein Winken erkannt – was stimmte:

Die KI hat das Winken richtig erkannt

Wie geht es weiter?

Du hast jetzt eine funktionierende künstliche Intelligenz auf deinem Arduino, die komplexe Bewegungen und Gesten erkennen kann.

Gehe einen Schritt weiter und integriere sie in ein neues Projekt, das du mit Gesten steuern kannst. Dein Arduino Nano 33 BLE Sense verfügt auch über ein Mikrofon, das du in Edge Impulse verwenden kannst. Sammle Geräusche und entwickle eine KI, die diese unterscheiden kann. Deiner Fantasie sind keine Grenzen gesetzt! 🙂

Edge Impulse ist übrigens nicht der einzige Service, mit dem relativ leicht KI-Modelle erstellen kannst: In diesem Tutorial stellen wir dir Googles Teachable Machine vor.

]]>