Raspberry Pi Pico W DHT22 Temperatur Sensor

Aus Laub-Home Wiki
Zur Navigation springen Zur Suche springen
Sensor dht22.png

Mit dem Raspberry Pi Pico oder Raspberry Pi Pico w ist es möglich den DHT22 Temperatur- & Luftfeuchtigkeitssensor auszulesen. Dieses Setup kann man zum Beispiel nutzen, um dauerhaft Temperatur und Luftfeuchtigkeit in einem Raum zu messen. Es ist möglich den Pico mit einem Battery Pack zu nutzen, was ihn dann somit sehr flexibel der Örtlichkeiten macht. Verbindet man den Pico W mit einem Wlan ist es auch möglich die Werte zum Beispiel via MQTT an das Smart Home senden.

Seid ihr auf der Suche nach einer Anleitung den DHT22 Sensor an einem Raspberry Pi zum laufen zu bekommen, schaut hier weiter:

Voraussetzungen

Wenn ihr noch keine Erfahrung mit dem Raspberry Pi Pico gesammelt habt, dann schaut am besten erst einmal hier rein:

Anschluss des Sensors am GPIO

Raspberry Pi Pico Pinbelegung
Raspberry Pi Pico W Pinbelegung

Wir schließen den Sensor wie folgt an:

Raspberry Pi Pico DHT22
Pin 36 3V3 +3,3V 1 (VCC) / +
Pin 29 GPIO 22 2 (Data)
Pin 28 GND 4 (GND) / -

Auslesen der Daten

Mit dem folgenden MicroPython Script kann man die Werte des DHT22 Sensors auslesen:

dht22.py

from machine import Pin
from time import sleep
from dht import DHT22

# GPIO Pin Number
gpio=22

# initializing GPIO and DHT22
sleep(1)
dht22_sensor = DHT22(Pin(gpio, Pin.IN, Pin.PULL_UP))

#degree symbol decleration
degreecels = '\u00B0' + "C"
# do the things
while True:
    dht22_sensor.measure()
    if dht22_sensor.temperature() == -50:
        dht22_sensor.measure()
    temperature = dht22_sensor.temperature()
    humidity = dht22_sensor.humidity()
    print('Temperature:', temperature, degreecels)
    print('   Humidity:', humidity, '%', '\n')
    sleep(3)

Die Konsolen Ausgabe sieht dann wie folgt aus.

>>> Running dht22.py

      Temperatur: 24.5 °C
Luftfeuchtigkeit: 54.7 % 

      Temperatur: 24.6 °C
Luftfeuchtigkeit: 54.6 % 

      Temperatur: 24.6 °C
Luftfeuchtigkeit: 55.0 % 

      Temperatur: 24.7 °C
Luftfeuchtigkeit: 54.1 % 

Senden der Sensorwerte via MQTT

Möchte man die Sensor Werte dann an einen MQTT Broker schicken, muss man zunächst den Pico W mit dem WLAN Verbinden und dann die ausgelesenen Daten mit umqtt an den MQTT Broker schicken. All dies macht das folgende Script. Die MQTT Werte werden nach der Homie MQTT Convention gesendet. Als Voraussetzung zur Nutzung des Skriptes (dht22homiemqtt.py) braucht ihr eine config.py mit allen Variablen zur Konfiguration und die wificonnection.py die für die WLAN Verbindung zuständig ist. Diese beiden Dateien, müssen auch immer auf den Pico mit übertragen werden. Auch wenn ihr das dht22homiemqtt.py testen möchtet in eurer IDE greift dieses auf die auf dem Pico liegenden config.py und wificonnection.py zu.

Ihr findet alle Scripte auch unter GitHub:

Installation umqtt.simple2 Library

Da die Library umqtt.simple2 nicht standardmäßig in der Pico MicroPython Version enthalten ist, müssen wir diese zu erst manuell installieren. Dafür müsst ihr euch, am besten mit eurer IDE an das MicroPython REPL verbinden.

Dort muss man sich zuerst mit dem WLAN verbinden. Danach folgendes auf der Konsole eingeben:

import upip
upip.install("micropython-umqtt.simple2")

config.py -- Konfigurationsdatei

In dieser Datei könnt ihr die Variablen definieren, die von der wificonnection.py und dht22homiemqtt.py verwendet werden.

config.py

# -*- coding: utf-8 -*-
"""Configuration File
This file is where you keep secret settings, passwords, and tokens!
If you put them in the code you risk committing that info or sharing it
you need to upload that file also on the Pico,
even if you are just testing your scripts.
"""

### Board Configuration ###
## Status LED ##
# LED can show you the status of the running scripts
# e.g. Wifi Connection Status Code
ledstatus = True

## LightSleep Mode ##
# Using LightSleep mode of Pico W to save power (True) just a Loop when "False"
usinglightsleep = True

## Wifi ##
# Wifi Connection Settings
wifissid = "<YourSSID>"
wifipassword = "<YOourWifiPassword>"
wificountrycode = "<CountryCode>" # "DE" for example


### MQTT Broker ###
mqttbroker = "<FQDN / IP of MQTTBroker>"
mqttport = 1883 # 8883 for TLS
mqttusername = "<MQTT-Username>"
mqttpassword = "<MQTT-Password"
mqttclientid = "<UniqueMQTTClientID>" # "pico-w-001" for example
# if you like to generate a unique ID:
#import ubinascii
#mqttclientid = ubinascii.hexlify(machine.unique_id())
mqttssl = False # True for TLS connection
mqttqos = 0 # only 0 and 1 is supported
mqttretainmessage = True # True or False
# Homie Configuration / Naming
homieclientid = "<UniqueHomieClientID>" # "pico-w-001-dht22" for example
homieclientname = "<Name your Homie Device>" # "Pico W 001 DHT22 Sensor" for example
homienodes="dht22"
# how often should be a publish to MQTT (in Seconds)
publishtime = 300


### Sensor Configurations ###
# At which value humidity alarm will be fired (x in %)
humidityalarm = 70

## DHT22 Sensor ##
# DHT22 GPIO Pin Number
dhtgpiopin = 22

wificonnection.py -- Wlan Management Datei

Mit Hilfe dieser Datei, verbindet sich die dht22homiemqtt.py mit dem Wifi. Und killt die Verbindung wieder bevor der Pico schlafen geht. Die Konfiguration zieht sie sich aus der config.py. Es gibt die folgenden Funktionen:

  • wificonnection.connect() --> Verbindet mit dem WLAN
  • wificonnection.disconnect() --> Trennt die Verbindung mit dem WLAN
  • wificonnection.status() --> Gibt den aktuellen Status der Verbindung aus (True / False)

wificonnection.py

# -*- coding: utf-8 -*-
"""Wifi Connection Module
Connecting Wifi, disconnecting Wifi and Wifi status
you'll need config.py to configure SSID, Password and CountryCode
* wificonnection.connect()
* wificonnection.disconnect()
* wificonnection.status()
"""

import config
import machine
from time import sleep
import network
import rp2

# wlan declearation
wlan = network.WLAN(network.STA_IF)
# led declaration
if config.ledstatus:
    led = machine.Pin('LED', machine.Pin.OUT)


def connect():
    # Setting Country
    rp2.country(config.wificountrycode)

    # activate wifi
    wlan.active(True)
    wlan.connect(config.wifissid, config.wifipassword)

    # Wait for connect or fail
    max_wait = 15
    while max_wait > 0:
        if wlan.status() < 0 or wlan.status() >= 3:
            break
        max_wait -= 1
        print('waiting for connection...')
        sleep(1)

    # Handle connection error
    if wlan.status() != 3:
        raise RuntimeError('network connection failed')
    else:
        # LED blinking
        if config.ledstatus:
            for i in range(wlan.status()):
                led.on()
                sleep(.1)
                led.off()
                sleep(.1)
        print('connected')
        status = wlan.ifconfig()
        print('ip = ' + status[0])


def disconnect():
    wlan.disconnect()
    wlan.active(False)
    wlan.deinit()
    print("Disconnected: " + str(wlan.status()))
    

def status():
    print("Connected: " + str(wlan.isconnected()))

dht22homiemqtt.py -- Hauptscript

Dieses Script holt sich die Konfigurationswerte aus der config.py. Dann passieren die folgenden Dinge:

  • Verbindung mit dem Wlan wificonnection.connect()
  • Verbindung zum MQTT Broker und Erstellung der Homie Convention Struktur
  • Auslesen der DHT22 Sensor Werte
  • Senden von Temperatur und Luftfeuchtigkeit an den MQTT Broker
  • UsingLightSleep - False / True
  • False: Entweder eine Loop des Lesend des Sensors und verschicken der Daten an den MQTT Broker
  • True: Oder trennen von MQTT und WLAN und schlafen legen bis zum nächsten publizieren.

dht22homiemqtt.py

# -*- coding: utf-8 -*-
"""DHT22 Homie MQTT
reads data (Temperature & Humidity) of DHT22 sensor and
sends values to a MQTT Broker in Homie MQTT Convention format
You are able to set a value, when humidity alarm is fired.
"""

import config
import wificonnection
from umqtt.simple2 import MQTTClient
from time import sleep
from dht import DHT22
import machine

#led declaration
if config.ledstatus:
    led = machine.Pin('LED', machine.Pin.OUT)
#degree symbol decleration
degreecels = '\u00B0' + "C"

# Functions
def publish(topic, payload):
    client.publish("homie/" + config.homieclientid + "/" + topic,
                   payload, retain=config.mqttretainmessage, qos=config.mqttqos)


def mqttconnect():
    global client
    client = MQTTClient(config.mqttclientid, config.mqttbroker, port=config.mqttport, user=config.mqttusername,
                            password=config.mqttpassword, keepalive=10, ssl=config.mqttssl,
                            ssl_params={})
    client.set_last_will("homie/" + config.homieclientid + "/$state",
                            "lost", retain=config.mqttretainmessage, qos=config.mqttqos)
    client.connect()
    # homie client config
    publish("$state", "init")
    publish("$homie", "4.0")
    publish("$name", config.homieclientname)
    publish("$nodes", config.homienodes)
    # homie node config
    publish(config.homienodes + "/$name", "DHT22 Sensor")
    publish(config.homienodes + "/$properties", "temperature,humidity,humidityalarm")
    publish(config.homienodes + "/temperature/$name", "Temperature")
    publish(config.homienodes + "/temperature/$unit", degreecels.encode('utf8'))
    publish(config.homienodes + "/temperature/$datatype", "float")
    publish(config.homienodes + "/temperature/$settable", "false")
    publish(config.homienodes + "/humidity/$name", "Humidity")
    publish(config.homienodes + "/humidity/$unit", "%")
    publish(config.homienodes + "/humidity/$datatype", "float")
    publish(config.homienodes + "/humidity/$settable", "false")
    publish(config.homienodes + "/humidityalarm/$name", "Humidity Alarm")
    publish(config.homienodes + "/humidityalarm/$datatype", "boolean")
    publish(config.homienodes + "/humidityalarm/$settable", "false")
    # homie state ready
    publish("$state", "ready")


def sensorpublish():
    publish(config.homienodes + "/temperature", "{:.1f}".format(temperature))
    publish(config.homienodes + "/humidity", "{:.1f}".format(humidity))
    if humidity >= config.humidityalarm:
        publish(config.homienodes + "/humidityalarm", "true")
    else:
        publish(config.homienodes + "/humidityalarm", "false")
    

def dht22sensor():
    global temperature
    global humidity
    # initializing GPIO and DHT22
    dht22_sensor = DHT22(machine.Pin(config.dhtgpiopin, machine.Pin.IN, machine.Pin.PULL_UP))
    dht22_sensor.measure()
    if dht22_sensor.temperature() == -50:
        dht22_sensor.measure()
    temperature = dht22_sensor.temperature()
    humidity = dht22_sensor.humidity()
   
   
# do the things
try:
    # connect to wifi
    wificonnection.connect()
    # connect to mqtt broker and initialize homie convention
    mqttconnect()
    while True:
        if config.ledstatus:
            led.value(True)
        dht22sensor()
        print('Temperature = ', temperature, degreecels)
        print('Humidity = ', humidity, '%', '\n')
        sensorpublish()
        sleep(.5)
        if config.usinglightsleep:
            publish("$state", "sleeping")
            sleep(.5)
            client.disconnect()
            sleep(.5)
            wificonnection.disconnect()
            print("done...")
            #sleep(.5)
            if config.ledstatus:
                led.value(False)
                machine.lightsleep((config.publishtime)*1000-11500)
            else:
                machine.lightsleep((config.publishtime)*1000-9200)
            break
        else:
            print("just a break for %s seconds" % config.publishtime)
            if config.ledstatus:
                led.value(False)
                sleep(config.publishtime-15)
            else:
                sleep(config.publishtime-10)
except RuntimeError as error:
    print(error.args[0])
    pass
except OSError as e:
    print(e.args[0])
    pass
machine.reset()

main.py -- Autostart

Möchte man, das das dht22homiemqtt.py Script autark auf dem Pico läuft, dann muss man entweder dieses als main.py umbenennen und auf den Pico übertragen, oder aber der bessere Weg, wir erstellen eine main.py und starten über diese unser dht22homiemqtt.py Script. Der Vorteil dieses Scripts hier, ist, das man mittels überbrücken von einem GPIO Pin (hier GPIO19) zu GND wieder in den programmierbaren Modus des Pico kommt:

main.py

# -*- coding: utf-8 -*-
"""Main Script
to prevent always blank flashing the pico
GPIO(19) is used to detect, if the system will break
instead of running the MQTT script.
Just use a jumper cable to connect GND and GPIO(19)
or use a switch on these two pins.
* on exit you'll see led 5 times flashing
* on entering the python script led will flash 1 time
"""


import machine
import config
from time import sleep

# declare EXIT Pin GPIO(19)
sw = machine.Pin(19,machine.Pin.IN,machine.Pin.PULL_UP)
# declare LED variable
if config.ledstatus:
    led = machine.Pin('LED', machine.Pin.OUT)

# Check if GPIO19 is activated
if  sw.value():
    if config.ledstatus:
        # LED blink on Startup
        led.value(True)
        sleep(.3)
        led.value(False)
    import dht22homiemqtt.py
else:
    blink = 5
    for i in range(blink):
        led.value(True)
        sleep(.1)
        led.value(False)
        sleep(.1)
    sys.exit()

Stromverbrauch

Wenn man den LightSleep Mode verwendet, verbraucht der Pico keinen für mich messbaren Strom. Beim Ausführen des Skriptes selbst liegen folgenden Maximal Werte an:

Raspberry Pi Pico W
Volt 5,13 V
Ampere 0,05 A
Watt 0,25 W
Einmalige Laufzeit des Skriptes in Sekunden Mit Status LED 12 s
Ohne Status LED 9,5 s

Quellen