Raspberry Pi 筆記 : DHT11溫濕度計 踩坑紀錄

前陣子南部陰雨不斷,房間長時間處於潮濕狀態因此許多木製品與衣物都發霉了,原本想買個簡易型的濕度計來觀察房內的溼度狀況,但又想到未來應該會購入除濕機,而經過簡單的研究後發覺除濕機也是會耗費不少電,因此想到之前在學校上課用到的DHT11溫溼度計可以作為使用。

當初是使用Arduino UNO開發板作為上課與練習,雖然UNO板子還在,但看著手邊的樹梅派也有GPIO端子,便興起了使用Raspberry pi直接透過GPIO讀取DHT11的data的想法。

想的簡單,實際上卻是各種踩完一坑又一坑,將其寫下作為日後參考之用。

設備準備

  1. Raspberry Pi 型號不拘
  2. DHT11 溫溼度模組
  3. 杜邦線3條

Raspberry Pi GPIO Pinout 這個網站提供了詳細的樹梅派端子資訊可以做參考。再搭配 DHT11 Datasheet 服用即可。
我們將DHT11連接上杜邦線作為延長,再接上Raspberry Pi,連接點分別如下:

樹梅派 DHT11
3.3V VDD
pin7(GPIO4) DATA
GND GND

軟體

我們與 DHT11 溝通的方式將透過 Adafruit 這個 python 套件進行,程式碼如下

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
import adafruit_dht

# Initial the dht device, with data pin connected to:
dhtDevice = adafruit_dht.DHT11(board.D4)

# you can pass DHT22 use_pulseio=False if you wouldn't like to use pulseio.
# This may be necessary on a Linux single board computer like the Raspberry Pi,
# but it will not work in CircuitPython.
# dhtDevice = adafruit_dht.DHT22(board.D18, use_pulseio=False)

while True:
    try:
        # Print the values to the serial port
        temperature_c = dhtDevice.temperature
        temperature_f = temperature_c * (9 / 5) + 32
        humidity = dhtDevice.humidity
        print(
            "Temp: {:.1f} C    Humidity: {:.1f}% ".format(
                temperature_c, humidity
            )
        )

    except RuntimeError as error:
        # Errors happen fairly often, DHT's are hard to read, just keep going
        print(error.args[0])
        time.sleep(2.0)
        continue
    except Exception as error:
        dhtDevice.exit()
        raise error

    time.sleep(2.0)

因此系統上必須先安裝 pythonpip,若你習慣使用其他套件管理如 conda 之類的不影響。接下來就是安裝必要的 python 套件與系統 library。

  1. 安裝 Adafruit_CircuitPython_DHT,若是你照著 readme 的步驟直接使用 pip3 install adafruit-circuitpython-dht 肯定噴錯給你看,解決這問題我在網路上有找到一個方法,只要在安裝前加入$export CFLAGS=-fcommon這行指令就可以順利安裝,實際上怎麼解決的我也不是很清楚,但是有用。
  2. 接下來就是安裝 GPIO 所需之系統 library,如果這邊直接照著網路上的一般教學會教你透過 APT 安裝 libgpiod2 這個 library,若是透過$sudo apt install libgpiod2,系統將會幫你安裝 arm64的版本,但實際上由於 adafruit-circuitpython-dht 這個 module 並不支援 64bit 的 libgpiod2,因此要透過以下指令安裝 armhf 的版本:
    $sudo dpkg --add-architecture armhf
    $sudo apt update
    $sudo apt install libc6:armhf libstdc++6:armhf libgpiod2:armhf
  3. 一般來說教學到此為止就可以正常執行,但實際上還是會噴錯,why?
    因為在 /dev 底下,系統與 GPIO 溝通所用的 character special file 在 debian base 的系統中預設的擁有者與群組為 root,且只有 root 使用者能夠使用。身為初學者的我們一定都會想說有甚麼困難 sudo 下去就可以了,抱歉因為你的 python 當初是使用 user 權限下去裝的,或是使用 venv 之類的,使用了 sudo 反而會讓它找不到 python所使用的module,但又不可能將 user 加入 root 群組內,造成權限上的問題。因此解決方法如下:
    1. $sudo chown root:$USER /dev/gpio*
    2. $sudo chmod g+rw /dev/gpio*

完成以上三點即可正常在裝有 Debain 系統的 Raspberry Pi 上讀取 GPIO 的資料了。

參考資料

  1. adafruit/Adafruit_CircuitPython_DHT
  2. Installation of RPI.GPIO failure on Pi4 running Ubuntu 20.10 Desktop
  3. raspberry4-64 : libgpiod_pulsein [from adafruit_blinka] cannot execute in the container
  4. RuntimeError: Not running on a RPi! with Ubuntu for Raspberry Pi #837
  5. What's meaning of the c in crw-rw-rw- in linux file permissions? [duplicate]
  6. 树莓派4B Ubuntu 21.04 自动温控开关风扇以及RPi.GPIO避坑指南
  7. 隨意亂玩:Raspberry Pi筆記:DHT11溫濕度感測器