Diese Werte werden im Browser auf dem PC oder dem Smartphone (siehe Bild) angezeigt, wenn man die IP-Adresse des Web Servers (hier: http://192.168.178.100) in die Adresszeile eingibt.
Der Webserver ist so programmiert, dass er bei Überschreiten einer Temperatur von 50°C oder einer Gaskonzentration von 100 das Wort „Alarm“ ausgibt. Aber man muss schon aktiv auf der entsprechenden Seite nachsehen, um alles angezeigt zu bekommen. Das hat mir nicht gereicht, ich wollte auch mit einem akustischen und optischen Signal benachrichtigt werden. Also musste ich die Webseite mit einem Micro Controller oder Micro Computer auswerten, die Messwerte herausfiltern und ggf. den Alarm mit Buzzer und LED auslösen.
Benötigte Hardware für den ersten Teil
1 |
||
optional |
||
optional |
Lithium Batterie 3,7V |
|
1 |
||
1 |
||
Mini Breadboard, Jumperkabel |
Benötigte Hardware für den zweiten Teil
1 |
Raspberry Pi 3B, 4B oder Zero W (WLAN-fähig) |
|
1 |
||
Mini Breadboard, Jumperkabel |
||
Aktiver Buzzer |
||
rote LED mit Vorwiderstand 200 bis 330 Ohm |
Naheliegend ist die Benutzung eines Micro Controllers, da der nach dem Einschalten „auf Fingerschnipp“ funktioniert. Aber es wollte mir nicht auf Anhieb gelingen, mein D1 Board für die Abfrage zu nutzen. Erst nach der Hilfe eines Blogger-Kollegen habe ich es geschafft. Deshalb stelle ich zunächst die (für mich) schnellere Lösung mit dem Raspberry Pi vor und verschiebe den Sketch für das D1 Board als Web Client auf den dritten Teil der Blog-Serie.
Das Auslesen einer textbasierten Webseite habe ich im Zusammenhang mit dem Download von Treibern und Programmbibliotheken schon häufiger vorgenommen. Mit curl ( „Client for URLs“ ist ein Kommandozeilen-Werkzeug zum Herunter- oder Hochladen von Dateien über eine Internetadresse) kann ich im Terminal den kompletten HTML-Text von dem ESP Web Server mit der IP-Adresse 192.168.178.100 herunterladen. (Die entsprechende Zeile im Programm mit der IP-Adresse müssen Sie selbstverständlich für Ihren Web Server anpassen).
Nach vielen Zeilen mit Formatierungen finden wir ganz am Ende die gesuchten Messwerte für Temperatur, Rel. Luftfeuchtigkeit (engl. Humidity) vom DHT22 und für die Gaskonzentration vom MQ-2.
Mit der Umleitung >text.txt speichere ich den gesamten Text für die weitere Bearbeitung in einer Datei.
curl 192.168.178.100 >text.txt
Für das Herausfiltern der Messwerte, Überprüfung der Überschreitung von Grenzwerten und ggf. der Auslösung des Alarm benutze ich ein selbstentwickeltes Python-Programm. Für die Ausführung des eben genannten Terminal-Befehls wird das Programm-Modul os benötigt, also
import os
und dann
os.system('curl 192.168.178.100 >text.txt')
Um den abgespeicherten Text der Webseite einer Variablen zuzuordnen, werden folgende Befehle benötigt:
f=open("text.txt","r")
daten = f.read()
f.close
Mit den String-Methoden find(), slicing[from:to], split() und strip() werden schließlich die Messwerte herausgefiltert.
Hier das Python-Programm mit Web Client und Alarm (Download):
import os
import time
import RPi.GPIO as GPIO
buzzer=21
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer,GPIO.OUT)
def alarm():
print("Alarm")
for i in range(2):
GPIO.output(buzzer,True)
time.sleep(0.2)
GPIO.output(buzzer,False)
time.sleep(0.1)
GPIO.output(buzzer,True)
time.sleep(0.2)
GPIO.output(buzzer,False)
time.sleep(1)
while True:
try:
os.system('curl 192.168.178.100 >text.txt')
f=open("text.txt","r")
daten = f.read()
f.close
#print(daten)
print()
index=daten.find("Temperature")
#print(index)
daten1=daten[index:-23]
print(daten1)
werte=daten1.split(":")
print(werte)
t=float(werte[1][0:6].strip())
print("t = ",t," °C")
h=int(werte[2][1:3])
print("h = ",h," %")
g=int(werte[3][1:4])
print("g = ",g," ppm")
if (t>25.0 or g>100):
alarm()
time.sleep(1)
except:
time.sleep(10)
Die Ausgabe der Daten erfolgt in der Python-Shell, bei Überschreiten der Grenzwerte werden Buzzer und LED an GPIO21 aktiviert.
Um den Raspi im „Headless Mode“, also ohne Tastatur und Monitor zu betreiben, macht es Sinn, ein kleines OLED-Display für die Datenausgabe in die Anordnung zu integrieren. Das 1,3 Zoll OLED I2C 128 x 64 Pixel Display begnügt sich mit vier Anschlüssen für 3,3V (Pin 1) und GND (Pin 9) sowie SDA (Pin 3) und SCL (Pin 5). Dafür habe ich die Programm-Bibliothek luma.core von RM Hull von github heruntergeladen.
Wenn Ihr Raspberry Pi OS nicht auf dem neuesten Stand ist, sind ggf. folgende Befehle notwendig:
$ sudo usermod -a -G i2c,spi,gpio pi
$ sudo apt install python3-dev python3-pip libfreetype6-dev libjpeg-dev build-essential
$ sudo apt install libsdl-dev libportmidi-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev libsdl-image1.2-dev
Das Klonen des Repository erfolgt mit:
$ git clone https://github.com/rm-hull/luma.examples.git
$ cd luma.examples
$ sudo -H pip install -e .
In dem Verzeichnis oled mit seinen weiteren Unterverzeichnissen haben wir zunächst keine Schreibrechte. Aufgrund der internen Abhängigkeiten zu dem Programm-Modul demo_opts.py und dem Unterverzeichnis fonts macht es jedoch Sinn, unser Programm ebenfalls in das Unterverzeichnis examples zu schreiben. Wir holen uns die Schreibrechte mit:
sudo chmod 777 -c -R /home/pi/oled
Bitte vergessen Sie nicht, in der Raspberry Pi – Konfiguration auf der Registerkarte Schnittstellen sowohl SSH als auch I2C zu aktivieren. Hier das Schaltbild:
und das vollständige Python-Programm, das Teile des luma.core-Beispiels terminal.py verwendet: (Download)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Web Client to read environmental data
# By Bernd Albrecht for AZ-Delivery
#
# luma.core: Copyright (c) 2014-2020 Richard Hull and contributors
# See LICENSE.rst for details.
import os
import time
from pathlib import Path
from demo_opts import get_device
from luma.core.virtual import terminal
from PIL import ImageFont
import RPi.GPIO as GPIO
buzzer=21
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(buzzer,GPIO.OUT)
def make_font(name, size):
font_path = str(Path(__file__).resolve().parent.joinpath('fonts', name))
return ImageFont.truetype(font_path, size)
def alarm():
print("Alarm")
for i in range(2):
GPIO.output(buzzer,True)
time.sleep(0.2)
GPIO.output(buzzer,False)
time.sleep(0.1)
GPIO.output(buzzer,True)
time.sleep(0.2)
GPIO.output(buzzer,False)
time.sleep(1)
def sensor():
global t,h,g,zeit
try:
os.system('curl 192.168.178.100 >text.txt')
f=open("text.txt","r")
daten = f.read()
f.close
except:
t=h=g=0
time.sleep(10)
#print(daten)
print()
index=daten.find("Temperature")
#print(index)
daten1=daten[index:-23]
print(daten1)
werte=daten1.split(":")
print(werte)
t=float(werte[1][0:6].strip())
print("t = ",t," °C")
h=int(werte[2][1:3])
print("h = ",h," %")
g=int(werte[3][1:4])
print("g = ",g)
if (t>25.0 or g>100):
alarm()
time.sleep(1)
def main():
# for fontname, size in [(None, None), ("ProggyTiny.ttf", 16), ('ChiKareGo.ttf', 16)]:
for fontname, size in [("ProggyTiny.ttf", 16)]:
print()
print(fontname, size)
font = make_font(fontname, size) if fontname else None
term = terminal(device, font)
while True:
sensor()
term.clear()
term.animate = False
term.clear()
term.puts("Temperature:")
term.puts(str(t))
term.puts("°C")
term.println()
term.println()
term.puts("Humidity: ")
term.puts(str(h))
term.puts(" %")
term.println()
term.println()
term.puts("Gas: ")
term.puts(str(g))
term.println()
term.flush()
time.sleep(2)
if __name__ == "__main__":
try:
device = get_device()
main()
except KeyboardInterrupt:
pass
Für den Programmstart haben Sie grundsätzlich drei Möglichkeiten:
- Normaler Start mit Tastatur und Monitor, anschließend “abnabeln“.
- Start über SSH (secure shell) vom PC z.B. mit dem Programm Putty
- Einrichten von Autostart (beschrieben im Blog Robot Car mit Raspberry Pi)
Es reicht jedoch nicht, das Programm zu laden und zu starten, weil die Voreinstellungen für ein anderes Display mit dem Treiber SSD1306 festgelegt sind. Deshalb muss für unser 1,3 Zoll OLED I2C 128 x 64 Pixel Display beim Programmaufruf der Parameter --display sh1106 übergeben werden.
Die weiteren Voreinstellungen für Interface: I2C und Dimensions: 128 x 64 sind richtig. Wenn Sie ein anderes Display verwenden, lohnt der Blick in die Datei README.rst im Verzeichnis luma.examples.
Im dritten Teil werde ich die Auswertung der Messwerte mit einem D1 Board (oder einem beliebigen anderen ESP8266 Micro Controller) vorstellen.
4 comments
Wolfgang Menzel
Hallo,
es wird ja relativ viel mit de, 1.3" OLED Display gezeigt. Gibt es eigentlich auch einen funktionierenden Treiber für den Anschluss am ESP32??? Ich habe schon mehrere XXX-SH1106 ausprobiert, die am ESP32 laufen sollen, aber bisher hat noch nichts funktioniert, während es mit dem 0.96" Display und SSD1306 perfekt funktioniert.
Kann da jemand helfen?
Gruß
Wolfgang
Bernd Albrecht
@ Sylvio Beck:
In seinem Blog vom 12. August 2020 zeigt Markus Pohle die Verwendung von IFTTT (if this than that).
https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/enc28j60-ethernet-modul-fur-arduino-esp-und-raspi
Nachteil beider Lösungen: Man benötigt einen Internet-Dienstleister für das Versenden einer Nachricht. Das wollte ich vermeiden.
Wolfgang Herz
Sehr schönes Projekt. Sicherlich lässt sich da etwas optimieren. _Vielleicht ist der Vorschlag von Hr. Beck auch als Beispiel abbildbar. Trotzdem finde ich die direkte Anzeige im Display gut. Es macht Spaß derart tolle Projekt im AZ-Delivery zu haben! Ich habe bisher viel dazugelernt.
Danke
Sylvio Beck
Schönes Projekt
Aber viel zu kompliziert viel einfacher wäre es wenn das Gerät im Garten Anomalien selbst erkennt und mit Hilfe eines Web Dienstes wie notifymydevice.com eine push Meldung auf das Handy sendet.
Die Daten die der Server sammelt können auch direkt per ftp upload ins Web oder eigene nas hochgeladen werden.
Bei Interesse könnt ich den entsprechenden Code zur Verfügung stellen.