前面幾章,我們已經讓 Raspberry Pi 具備:
GPIO Input
+
Digital Output
+
PWM Output
可以做到:
Button
↓
Python
↓
LED / Buzzer
不過目前 Raspberry Pi 所取得的輸入,大多仍然來自:
人
↓
Push Button
或:
Keyboard
↓
input()
真正的自動控制系統還缺少一個重要能力:
Sensor
也就是:
感測器。
本章開始,Raspberry Pi 將第一次真正取得環境資料:
Environment
│
├── Temperature
└── Humidity
↓
DHT Sensor
↓
Raspberry Pi
↓
Python
這代表系統正式進入:
Sense → Decide → Act
也就是:
感知
↓
判斷
↓
動作
的完整自動控制架構。
1. Sensor 是什麼?
Sensor:
感測器
是一種將現實世界物理量轉換成電氣或數位資料的裝置。
例如:
Temperature Sensor
→ 溫度
Humidity Sensor
→ 濕度
Light Sensor
→ 光線
Pressure Sensor
→ 壓力
Motion Sensor
→ 人體移動
Distance Sensor
→ 距離
Raspberry Pi 再透過 GPIO、I²C、SPI、UART 等介面取得這些資訊。
2. Analog Sensor 與 Digital Sensor
Sensor 可以先簡單分成:
Sensor
│
├── Analog
└── Digital
Analog Sensor
輸出連續電壓,例如:
0.4V
1.2V
2.6V
需要 ADC:
Analog Sensor
↓
ADC
↓
Raspberry Pi
因為 Raspberry Pi 40-pin Header 沒有 Arduino UNO 式的一般用途 Analog Input。
Digital Sensor
Sensor 本身已經完成:
Sensing
+
Analog Processing
+
ADC
+
Digital Encoding
然後直接輸出數位資料。
DHT11 / DHT22 就屬於這一類。
3. DHT11 / DHT22 是什麼?
DHT11 與 DHT22 是很常見的低成本:
Temperature + Humidity Sensor
內部包含:
- Humidity sensing element
- Temperature sensing element
- 基本 A/D conversion
- Digital communication logic
因此 Raspberry Pi 不需要自己做 ADC,就能讀取溫度與相對濕度。Adafruit 將 DHT 系列定位為基本、速度較慢,但很適合初學與簡單資料記錄的數位溫溼度感測器。
4. DHT11 和 DHT22 外觀很像
兩者通常都是帶孔塑膠外殼。
常見:
DHT11
→ 藍色
DHT22
→ 白色
但不要只靠顏色辨識。
真正應該確認:
Part Number
+
Module Label
+
Datasheet
5. DHT11 規格
Adafruit 目前整理的 DHT11 典型能力包括:
- 工作電源約 3~5V
- 濕度範圍約 20~80% RH
- 濕度精度約 ±5%
- 溫度範圍約 0~50°C
- 溫度精度約 ±2°C
- 最快約每秒讀取一次。
所以 DHT11 的定位比較偏:
低成本入門。
6. DHT22 規格
DHT22 / AM2302 的能力較高:
- 工作電源約 3~5V
- 濕度範圍約 0~100% RH
- 濕度精度約 2~5%
- 溫度範圍約 -40~80°C
- 溫度精度約 ±0.5°C
- 最快大約每 2 秒讀取一次。
7. DHT11 與 DHT22 比較
| 項目 | DHT11 | DHT22 |
|---|---|---|
| 成本 | 較低 | 較高 |
| 溫度範圍 | 約 0~50°C | 約 -40~80°C |
| 溫度精度 | 約 ±2°C | 約 ±0.5°C |
| 濕度範圍 | 約 20~80% | 約 0~100% |
| 濕度精度 | 約 ±5% | 約 2~5% |
| 最快取樣 | 約 1 秒一次 | 約 2 秒一次 |
| 適合 | 基礎教學 | 較好的環境監測 |
官方教學也明確指出 DHT22 的量測範圍與精度優於 DHT11,但兩者都屬於速度較慢的基本 Sensor。
8. 本系列比較建議使用哪一個?
如果只是第一次學 Sensor:
DHT11
就可以。
如果希望後面的:
- IoT
- SQLite
- MQTT
- Web Dashboard
使用比較合理的環境資料,本系列更推薦:
DHT22
因為:
Range 更大
+
Accuracy 較好
9. DHT 是高精度工業 Sensor 嗎?
不是。
DHT11 / DHT22 比較適合:
- 學習
- Maker Project
- 家庭環境監測
- 基本資料記錄
如果是:
- 校正設備
- 工業量測
- 醫療
- 高精度控制
應選擇更適合的 Sensor。
Adafruit 目前甚至明確把 DHT11 / DHT22 稱為較基本、較慢的裝置,並在目前 Python Package 文件中建議有更高需求時評估較新的感測器。
10. DHT 有兩種常見外型
市面常看到:
4-pin Raw Sensor
以及:
3-pin Module
兩者不能完全當成相同 PCB 直接照搬接線。
11. 4-pin DHT Raw Sensor
感測器正面朝向自己時,一般腳位排列為:
Pin 1
VCC
Pin 2
DATA
Pin 3
NC
Pin 4
GND
Adafruit 的 DHT 接線文件也是:
- Power
- Data
- 不接
- Ground。
12. 3-pin DHT Module
市售模組常把 Raw Sensor 裝在一片 PCB 上。
可能只剩:
VCC
DATA
GND
而 PCB 上可能已經包含:
Pull-up Resistor
有些甚至還有:
- LED
- Capacitor
- Protection Components
但是:
不能假設所有三腳模組內部完全一樣。
要查看:
- 模組絲印
- PCB
- 商品規格
- Schematic
13. VCC、DATA、GND 是什麼?
VCC
Sensor Power。
DATA
DHT 數位資料線。
GND
Ground Reference。
基本架構:
Raspberry Pi
│
├── 3.3V ───── DHT VCC
├── GPIO4 ──── DHT DATA
└── GND ────── DHT GND
14. Raspberry Pi 最重要的電壓安全
Raspberry Pi 一般 GPIO 使用:
3.3V Logic
官方 GPIO 文件說明 Output HIGH 會嘗試驅動到 3.3V Rail。
所以 DATA Signal 必須保持:
3.3V-safe
不要直接把:
5V Digital Signal
送進 Raspberry Pi GPIO。
15. DHT Sensor 可以用 3.3V 嗎?
DHT11 與 DHT22 官方教學資料列出的工作電源大致為:
3~5V
因此教學電路可以優先使用 Raspberry Pi:
3.3V
供電。
這樣 DATA Pull-up 也能直接以:
3.3V
作為邏輯 HIGH。
16. 為什麼本系列優先使用 3.3V?
因為 Raspberry Pi GPIO 是 3.3V Logic。
所以本章的 Raw DHT Sensor 採:
VCC
→ 3.3V
DATA Pull-up
→ 3.3V
這樣整個 Sensor Logic Domain 都維持:
3.3V。
17. 網路文章為什麼有人把 DHT VCC 接 5V?
DHT Sensor 本體的確通常能在 5V Power 下工作,而 Adafruit 一些通用 DHT 教學也提到某些環境下 5V 供電可能較穩定;不過 DATA Pull-up 仍應維持對 3.3V Logic 安全。
對 Raspberry Pi 初學者來說,最單純且安全的方案仍是:
先使用 3.3V。
18. 三腳 Module 更要小心 5V
某些 Module 的:
DATA Pull-up Resistor
可能直接拉到:
VCC
如果你給 Module:
5V
DATA HIGH 就可能與 Raspberry Pi 3.3V GPIO 不相容。
所以不知道 Module Schematic 時:
不要直接假設 VCC=5V 一定安全。
19. DATA 為什麼需要 Pull-up?
DHT DATA Line 需要 Pull-up,讓 Bus 在沒有被主動拉低時保持明確 HIGH。
Adafruit CircuitPython DHT 文件明確指出 DHT11 與 DHT22 的 Data Signal 都需要 Pull Resistor。
概念:
3.3V
│
Pull-up
│
├──── DATA
│
DHT
20. Pull-up 電阻使用多少?
Adafruit CircuitPython DHT 文件目前建議依 Datasheet 選擇,並指出約:
1kΩ ~ 5kΩ
的範圍。
本系列 Raw Sensor 實驗使用很常見的:
4.7kΩ
因為它位於這個建議範圍內。
21. 為什麼有些 DHT 教學使用 10kΩ?
不同製造商與 Module 設計可能使用不同 Pull-up 值,Adafruit 的另一份一般 DHT 接線教學也示範過 10kΩ Pull-up。
因此真正工程做法應該是:
先看 Datasheet
+
模組電路
而不是認為世界上只有一個固定 Resistance。
本系列為 Raw DHT11 / DHT22 統一採:
4.7kΩ
方便教學。
22. 3-pin Module 還要加 4.7kΩ 嗎?
如果 Module 已經內建:
Pull-up Resistor
通常不需要再額外增加。
如果不確定:
- 查看 PCB 上是否有 Resistor。
- 查看 Module Datasheet。
- 查看 Schematic。
- 用 Multimeter 分析。
不要盲目一直疊加 Pull-up。
23. 本章使用 GPIO4
DHT DATA 使用:
BCM GPIO4
=
Physical Pin 7
原因:
- 容易辨識
- 不占用 I²C GPIO2 / GPIO3
- 不占用 SPI0
- 很適合單線 Sensor Lab
Python Blinka 寫法:
board.D4
表示 BCM GPIO4。
24. 4-pin DHT22 接線
本章推薦:
Raspberry Pi 5 DHT22
3.3V / Pin 1 ────────────── VCC / Pin 1
┌─4.7kΩ─ 3.3V
│
GPIO4 / Pin 7 ──────┴────── DATA / Pin 2
Pin 3
NC
GND / Pin 6 ─────────────── GND / Pin 4
25. DHT11 接線相同嗎?
一般 Raw DHT11 與 DHT22 Pinout 相同:
1 VCC
2 DATA
3 NC
4 GND
Adafruit 目前也將兩者描述為相同 Pinout。
因此硬體可以相同。
程式只需要改:
DHT22
成:
DHT11
26. 接線前仍然先關機
執行:
sudo poweroff
然後:
拔除 USB-C
↓
確認 DHT 方向
↓
接 VCC
↓
接 DATA
↓
接 Pull-up
↓
接 GND
↓
重新確認
↓
Power On
不要拿著 DHT 在通電中的 40-pin Header 上試位置。
27. 接反 VCC / GND 可能損壞 Sensor
DHT 外觀看起來簡單,但:
VCC
GND
接反並不是合理測試方法。
所以在插線前:
先確認 Sensor 正面方向與 Pin 1。
尤其三腳 Module 的 VCC/GND 排列不是所有品牌都相同。
28. 本章 Python Library
本章使用:
Adafruit CircuitPython DHT
目前 PyPI 的 Adafruit CircuitPython DHT 最新版本為 4.0.12,發布於 2026 年 4 月 23 日,支援 DHT11 與 DHT22。
Linux Raspberry Pi 上透過:
Regular Python
+
Adafruit Blinka
+
CircuitPython Driver
存取 Sensor。
29. Blinka 是什麼?
Blinka 是讓一般 Linux Python 可以使用 CircuitPython Hardware API 的 Compatibility Layer。
例如程式可以寫:
import board
以及:
board.D4
在 Raspberry Pi 上操作實際 GPIO。
Adafruit 目前明確說明 Blinka 支援包括 Raspberry Pi 5 在內的 Raspberry Pi 系列。
30. 不使用舊 Adafruit_DHT Library
搜尋老文章時可能看到:
import Adafruit_DHT
那是很舊的 Python DHT Library 世代。
本系列使用目前維護中的:
import adafruit_dht
也就是:
Adafruit CircuitPython DHT
目前 PyPI 版本仍持續更新至 2026 年。
31. Raspberry Pi OS 要使用 Virtual Environment
從 Raspberry Pi OS Bookworm 開始,Raspberry Pi 官方要求第三方 pip Package 使用:
Python Virtual Environment
避免直接修改 System Python;作業系統提供的 Package 則優先使用 APT。
所以本章不使用:
sudo pip install ...
32. 建立 Chapter 11 Project
cd ~
建立:
mkdir -p raspberrypi-course/chapter11
進入:
cd raspberrypi-course/chapter11
33. 安裝必要 System Package
先:
sudo apt update
安裝:
sudo apt install -y \
python3-venv \
python3-pip \
libgpiod-dev \
python3-libgpiod
Adafruit 的目前 Raspberry Pi Blinka 安裝文件列出 libgpiod-dev 與 python3-libgpiod 等 Linux GPIO Dependency;Bookworm 之後則建議在 Virtual Environment 內安裝 Python Module。
34. 建立 .venv
python3 -m venv \
.venv \
--system-site-packages
使用 --system-site-packages 可以讓 Virtual Environment 同時看到部分由 APT 安裝的 System Python Package,這也是 Raspberry Pi 與 Adafruit 在硬體 Python Library 情境中提供的做法。
35. 啟動 .venv
source .venv/bin/activate
看到:
(.venv)
代表已進入 Virtual Environment。
確認:
which python
應該指向:
chapter11/.venv/bin/python
36. 安裝 Blinka 與 DHT Library
在:
(.venv)
裡執行:
python -m pip install \
--upgrade \
adafruit-blinka \
adafruit-circuitpython-dht
Adafruit CircuitPython DHT 官方文件支援在 Raspberry Pi 這類 GNU/Linux 系統透過 PyPI 與 Virtual Environment 安裝。
37. 確認 Library
執行:
python -c \
"import board, adafruit_dht; print('DHT library OK')"
如果得到:
DHT library OK
代表:
board
+
adafruit_dht
至少可以正常 Import。
38. 第一支 DHT22 程式
建立:
nano dht22_test.py
內容:
import time
import adafruit_dht
import board
dht = adafruit_dht.DHT22(
board.D4,
use_pulseio=False
)
try:
while True:
try:
temperature = dht.temperature
humidity = dht.humidity
print(
f"Temperature: "
f"{temperature:.1f} C"
)
print(
f"Humidity: "
f"{humidity:.1f} %"
)
print("-" * 30)
except RuntimeError as error:
print(
"DHT read failed:",
error
)
time.sleep(2)
except KeyboardInterrupt:
print(
"\nProgram stopped."
)
finally:
dht.exit()
39. 為什麼 Raspberry Pi 使用 use_pulseio=False?
Adafruit DHT 的目前官方 Example 特別指出,在 Raspberry Pi 這類 Linux Single Board Computer 上,可以使用:
use_pulseio=False
避免使用 CircuitPython pulseio 路徑。
因此本系列 Raspberry Pi 5 範例明確使用:
DHT22(
board.D4,
use_pulseio=False
)
40. 執行 DHT22 程式
確認:
(.venv)
仍然存在。
執行:
python dht22_test.py
可能看到:
Temperature: 27.4 C
Humidity: 63.2 %
------------------------------
Temperature: 27.5 C
Humidity: 63.1 %
------------------------------
這就是 Raspberry Pi 第一個真正 Sensor Reading。
41. 使用 DHT11 時只改一行
把:
dht = adafruit_dht.DHT22(
board.D4,
use_pulseio=False
)
改成:
dht = adafruit_dht.DHT11(
board.D4,
use_pulseio=False
)
Adafruit 官方文件也是以 DHT11 與 DHT22 兩個 Class 分別建立 Sensor Object。
42. dht.temperature 是什麼?
temperature = dht.temperature
取得:
Temperature
單位:
°C
Adafruit DHT API 的基本使用方式就是讀取 temperature Property。
43. dht.humidity 是什麼?
humidity = dht.humidity
取得:
Relative Humidity
一般表示成:
%
例如:
65%
代表:
相對濕度約 65%。
44. 為什麼每 2 秒才讀一次?
DHT22 本身最多大約:
0.5Hz
也就是約 2 秒一次。
而目前 Adafruit CircuitPython DHT Package 也明確建議發生讀取問題時至少等待 2 秒後再 Retry;短時間再次存取時 Library 可能回傳 Cache 值。
因此本系列統一:
time.sleep(2)
對 DHT11 / DHT22 都比較簡單。
45. 不要每 10ms 狂讀 DHT
例如:
while True:
temperature = dht.temperature
沒有 Delay。
這不是好的 DHT 使用方式。
DHT 本來就是:
Low Sampling Rate Sensor。
如果需要:
- 10Hz
- 100Hz
- Fast Control Loop
DHT11 / DHT22 就不是合適選擇。
46. DHT 偶爾讀取失敗正常嗎?
是。
Adafruit 官方 DHT Guide 明確指出,因為訊號受 Noise 或 Timing 影響,偶爾可能發生讀取 Exception;正確程式設計應:
Catch Error
↓
Retry Later
而不是第一次失敗就整個程式退出。
47. RuntimeError
例如:
except RuntimeError as error:
處理:
Sensor Read Failure
可能訊息包含:
Checksum did not validate
或:
A full buffer was not returned
這類讀取錯誤不一定代表 Sensor 已經壞掉。
48. Retry 的正確觀念
比較好的:
Read
↓
Success?
├─ Yes → Process Data
└─ No → Wait → Retry
而不是:
Read Fail
↓
Program Crash
IoT Program 尤其需要這種容錯思維。
49. 更完整的 Retry Function
可以寫:
import time
def read_dht(
sensor,
retries=3,
delay=2
):
for attempt in range(
1,
retries + 1
):
try:
temperature = (
sensor.temperature
)
humidity = (
sensor.humidity
)
return (
temperature,
humidity
)
except RuntimeError as error:
print(
f"Read attempt "
f"{attempt} failed: "
f"{error}"
)
time.sleep(delay)
return None
50. 使用 Retry Function
result = read_dht(dht)
if result is None:
print(
"Sensor read failed."
)
else:
temperature, humidity = (
result
)
print(
temperature,
humidity
)
這樣 Sensor Driver 和應用邏輯就開始分離。
51. 不要把所有 Exception 都當 RuntimeError 忽略
DHT Timing Error 可以 Retry。
但是如果出現:
SyntaxError
ModuleNotFoundError
Permission Error
Wrong Library
不能只:
except Exception:
pass
把所有錯誤吃掉。
否則真正問題會被隱藏。
52. 對未知 Exception 應該讓程式顯示
例如:
except RuntimeError as error:
print(
"Temporary DHT error:",
error
)
except Exception:
dht.exit()
raise
這和 Adafruit 官方 DHT Example 的處理方向一致:預期中的 DHT RuntimeError Retry,其他 Exception 則清理 Sensor 後重新拋出。
53. 溫度轉 Fahrenheit
如果需要 Fahrenheit:
temperature_f = (
temperature * 9 / 5
+ 32
)
例如:
25°C
=
77°F
Adafruit 官方 DHT Example 也同時示範 Celsius 與 Fahrenheit。
本系列主要使用:
°C
因為台灣一般環境監測使用攝氏比較自然。
54. 建立漂亮的 Terminal 監測畫面
print(
f"Temperature : "
f"{temperature:.1f} °C"
)
print(
f"Humidity : "
f"{humidity:.1f} %RH"
)
輸出:
Temperature : 27.8 °C
Humidity : 65.3 %RH
55. 加入時間
Python:
from datetime import datetime
然後:
now = datetime.now()
輸出:
print(
now.strftime(
"%Y-%m-%d %H:%M:%S"
)
)
就能得到:
2026-08-17 23:10:00
之後第 19 章存 SQLite 時,Timestamp 會非常重要。
56. 即時 Monitor 完整版
import time
from datetime import datetime
import adafruit_dht
import board
dht = adafruit_dht.DHT22(
board.D4,
use_pulseio=False
)
try:
while True:
try:
temperature = dht.temperature
humidity = dht.humidity
now = datetime.now()
print(
now.strftime(
"%Y-%m-%d %H:%M:%S"
)
)
print(
f"Temperature : "
f"{temperature:.1f} °C"
)
print(
f"Humidity : "
f"{humidity:.1f} %RH"
)
print(
"-" * 35
)
except RuntimeError as error:
print(
"Temporary read error:",
error
)
time.sleep(2)
except KeyboardInterrupt:
print(
"\nMonitor stopped."
)
finally:
dht.exit()
57. 如何判斷 Normal / Warning / Danger?
例如定義:
Temperature < 30°C
→ Normal
30~34.9°C
→ Warning
>= 35°C
→ Danger
這只是教學 Threshold。
實際設備應依:
- 使用環境
- 設備規格
- 安全要求
制定。
58. Status Function
def get_status(
temperature
):
if temperature >= 35:
return "DANGER"
if temperature >= 30:
return "WARNING"
return "NORMAL"
接著:
status = get_status(
temperature
)
59. 加入濕度狀態
也可以:
def get_humidity_status(
humidity
):
if humidity >= 80:
return "HIGH"
if humidity <= 30:
return "LOW"
return "NORMAL"
注意這些值是:
教學範例 Threshold
不是醫療、工業或建築環控的通用安全標準。
60. 完整文字狀態
Temperature : 32.4 °C
Humidity : 68.5 %RH
Temperature Status:
WARNING
Humidity Status:
NORMAL
到這裡,Sensor 已經完成:
Sense
↓
Decision
下一步是:
Act
61. 加入第 10 章 PWM LED
LED 使用:
GPIO18
=
Physical Pin 12
Sensor:
GPIO4
=
Physical Pin 7
兩者不衝突。
架構:
DHT22
│
GPIO4
│
▼
Python
│
▼
PWMLED
GPIO18
62. 用 LED 亮度表示溫度狀態
例如:
NORMAL
→ 30%
WARNING
→ 70%
DANGER
→ 100%
程式:
def update_led(
led,
status
):
if status == "DANGER":
led.value = 1.0
elif status == "WARNING":
led.value = 0.7
else:
led.value = 0.3
63. 加入 TonalBuzzer
沿用:
GPIO23
=
Physical Pin 16
架構:
DHT22
↓
Temperature
↓
Python
↓
Status
/ \
LED Buzzer
64. 警報邏輯
例如:
NORMAL
→ Buzzer OFF
WARNING
→ 短促提示音
DANGER
→ 高音警報
注意實際 Buzzer 電壓與電流仍要符合第 10 章的安全原則。
65. 完整 DHT + PWM LED + Buzzer 程式
import time
from datetime import datetime
import adafruit_dht
import board
from gpiozero import PWMLED
from gpiozero import TonalBuzzer
DHT_PIN = board.D4
LED_PIN = 18
BUZZER_PIN = 23
NORMAL_LED = 0.3
WARNING_LED = 0.7
DANGER_LED = 1.0
READ_INTERVAL = 2
dht = adafruit_dht.DHT22(
DHT_PIN,
use_pulseio=False
)
led = PWMLED(
LED_PIN
)
buzzer = TonalBuzzer(
BUZZER_PIN
)
def get_status(
temperature
):
if temperature >= 35:
return "DANGER"
if temperature >= 30:
return "WARNING"
return "NORMAL"
def update_outputs(
status
):
if status == "DANGER":
led.value = DANGER_LED
buzzer.play(
"A5"
)
elif status == "WARNING":
led.value = WARNING_LED
buzzer.play(
"A4"
)
time.sleep(0.15)
buzzer.stop()
else:
led.value = NORMAL_LED
buzzer.stop()
def display_data(
temperature,
humidity,
status
):
now = datetime.now()
print(
now.strftime(
"%Y-%m-%d %H:%M:%S"
)
)
print(
f"Temperature : "
f"{temperature:.1f} °C"
)
print(
f"Humidity : "
f"{humidity:.1f} %RH"
)
print(
f"Status : "
f"{status}"
)
print(
"-" * 35
)
try:
while True:
try:
temperature = (
dht.temperature
)
humidity = (
dht.humidity
)
status = get_status(
temperature
)
display_data(
temperature,
humidity,
status
)
update_outputs(
status
)
except RuntimeError as error:
print(
"Temporary DHT error:",
error
)
time.sleep(
READ_INTERVAL
)
except KeyboardInterrupt:
print(
"\nMonitor stopped."
)
finally:
led.off()
buzzer.stop()
led.close()
buzzer.close()
dht.exit()
66. 這個完整系統在做什麼?
流程:
DHT22
│
├── Temperature
└── Humidity
↓
Python
↓
Temperature Status
/ | \
Normal Warning Danger
│ │ │
30% LED 70% LED 100% LED
│ │ │
Silent A4 Beep A5 Alarm
這就是完整:
Sensor Monitoring + Alarm System
67. 為什麼 Danger Buzzer 一直響?
程式:
buzzer.play("A5")
會讓 TonalBuzzer 持續播放。
下一次正常/警告狀態才會:
buzzer.stop()
所以 Danger 狀態會維持持續警報。
68. 如果不想 Danger 持續響
可以改成:
buzzer.play(
"A5"
)
time.sleep(
0.3
)
buzzer.stop()
這樣每次 Sensor Update 只響一下。
69. Sensor Data Filtering 是什麼?
真實 Sensor 可能看到:
27.4
27.5
27.4
27.7
27.5
小幅變動是正常的。
不要因為:
27.4 → 27.5
就認為 Sensor 壞掉。
後續可以使用:
- Moving Average
- Median
- Hysteresis
- Range Check
降低 Noise 對控制的影響。
70. 為什麼控制系統需要 Hysteresis?
假設 Threshold:
30°C
Sensor 在:
29.9
30.1
29.9
30.1
變動。
如果直接控制 Fan:
ON
OFF
ON
OFF
就會不斷切換。
比較好的方法:
>= 30°C
→ ON
<= 29°C
→ OFF
建立:
1°C Hysteresis
這會在後面 Relay / Fan 控制章節再次使用。
71. DHT11 / DHT22 適合控制高速設備嗎?
不適合。
因為它們的 Sampling Rate 本身就很低:
DHT11
約 1Hz
DHT22
約 0.5Hz
所以它們適合:
Room Temperature
Humidity Monitoring
Environmental Logging
而不是:
High-speed Control
Real-time Motor Loop
72. DHT 完全讀不到:第一步檢查 Wiring
確認:
VCC
→ 3.3V
DATA
→ GPIO4 / Pin 7
GND
→ GND
DATA Pull-up
→ 3.3V
以及:
Pin 3
→ NC
73. DHT 一直 RuntimeError
先檢查:
- VCC 是否穩定。
- DATA 是否 GPIO4。
- Pull-up 是否存在。
- DHT Pin Direction 是否看反。
- Breadboard 是否插錯 Row。
- Sensor 是否真的 DHT11 / DHT22。
- 程式 Class 是否正確。
- Read Interval 是否至少約 2 秒。
DHT 本來就偶爾可能讀失敗;但如果完全沒有一次成功讀值,就應優先查 Hardware。
74. ModuleNotFoundError: adafruit_dht
如果:
No module named 'adafruit_dht'
先:
source .venv/bin/activate
再:
python -m pip list
確認 Package 是否真的存在。
75. 確認你現在使用哪個 Python
which python
應該:
.../chapter11/.venv/bin/python
不是:
/usr/bin/python
否則你很可能:
Library 安裝在 venv
程式卻用 System Python
76. 確認 Package
python -m pip show \
adafruit-circuitpython-dht
應該顯示:
- Name
- Version
- Location
目前 PyPI 的最新 DHT Driver 為 4.0.12。
77. board.D4 找不到怎麼辦?
先測:
python -c \
"import board; print(board.D4)"
如果連:
import board
都失敗,就應先檢查:
Adafruit Blinka
而不是 Sensor。
Adafruit 目前說明 Blinka 支援 Raspberry Pi 5。
78. Blinka 安裝問題
確認:
python -m pip show \
adafruit-blinka
以及 Linux Dependency:
dpkg -l | grep gpiod
Adafruit Raspberry Pi Blinka Guide 目前依賴 libgpiod-dev 與 python3-libgpiod 等 Linux Package。
79. Raspberry Pi 5 和老版 GPIO 教學不同
Pi 5 使用:
RP1
管理大量外部 Peripheral。
這使一些早期直接針對 BCM283x Hardware 的 Library 或技巧不再適合直接照搬。
Adafruit 目前也特別說明 Pi 5 的 RP1 架構迫使原本某些 GPIO 實作改採新的 Linux GPIO Backend。
80. 為什麼本章使用 CircuitPython Driver 而 GPIO Output 用 GPIO Zero?
因為 Library 的選擇應依:
Device
+
成熟 Driver
+
API
而不是要求整個 Project 所有硬體都只能使用同一套 Library。
本系列:
Button / LED / Buzzer
→ GPIO Zero
DHT Sensor
→ Adafruit CircuitPython DHT
兩者都屬高階 Python Hardware API。
81. 可以把 DHT DATA 接 GPIO18 嗎?
技術上可以選其他合適 GPIO。
但是本章 GPIO18 已經給:
PWM LED
所以不應兩個 Device 同時搶同一 Pin。
本章分配:
| 功能 | BCM GPIO | Physical |
|---|---|---|
| DHT DATA | GPIO4 | Pin 7 |
| PWM LED | GPIO18 | Pin 12 |
| Buzzer | GPIO23 | Pin 16 |
| 3.3V | — | Pin 1 |
| GND | — | Pin 6 |
82. 建立 Pin Assignment Table 的好處
Project 越大,越應該先寫:
Sensor
→ GPIO4
LED
→ GPIO18
Buzzer
→ GPIO23
避免:
GPIO18
同時接 Sensor
又接 LED
造成 Resource Conflict。
83. DHT Sensor 發熱會影響讀值嗎?
Sensor 如果:
- 靠近 Raspberry Pi SoC
- 靠近 Active Cooler 排風
- 靠近 Power Supply
- 放在密閉熱源旁
量到的溫度可能不代表真正室內環境。
所以環境 Sensor 應該:
遠離主要熱源
+
保持空氣流通
84. 不要把 DHT 貼在 Raspberry Pi 5 CPU 上
如果 Sensor 就在:
BCM2712
Active Cooler
USB-C PSU
旁邊,
你量到的可能更接近:
主機附近微環境溫度
而不是:
室溫
這是 Sensor Installation 的基本觀念。
85. 濕度讀值為什麼變化很慢?
DHT 本身就是:
Slow Sensor
而濕度感測材料也有一定反應時間。
因此:
吹一口氣
之後數值可能需要一些時間變化與恢復。
Adafruit 也明確將 DHT11/DHT22 描述為速度較慢的環境 Sensor。
86. 不要對 Sensor 直接吹很濕的氣體當校正
人體呼氣可以用來觀察:
Humidity 是否會變化
但這不是:
Calibration
真正校正需要:
- Reference Instrument
- Known Humidity Environment
- Calibration Procedure
87. DHT 數值要不要儲存?
這正是後面課程要做的事。
目前:
Sensor
↓
Terminal
後面:
Sensor
↓
SQLite
↓
Historical Data
↓
Chart
再:
MQTT
↓
Remote Monitoring
這就是 IoT 架構逐步形成。
88. 現在已經完成第一個完整 Sensor Loop
DHT
↓
Read
↓
Validate
↓
Display
↓
Decision
↓
LED / Buzzer
↓
Wait 2 sec
↓
Repeat
這個 Pattern 後面幾乎所有 Sensor 都會再看到。
89. 本章常用安裝指令
sudo apt update
sudo apt install -y \
python3-venv \
python3-pip \
libgpiod-dev \
python3-libgpiod
python3 -m venv \
.venv \
--system-site-packages
source .venv/bin/activate
python -m pip install \
--upgrade \
adafruit-blinka \
adafruit-circuitpython-dht
Raspberry Pi OS Bookworm 之後使用 venv 安裝 pip Library,是 Raspberry Pi 官方目前建議的套件管理方式。
90. 本章 DHT Python API 速查
| Python | 用途 |
|---|---|
| import board | Blinka Board Pin |
| import adafruit_dht | DHT Driver |
| board.D4 | BCM GPIO4 |
| DHT11() | 建立 DHT11 |
| DHT22() | 建立 DHT22 |
| temperature | 取得溫度 |
| humidity | 取得濕度 |
| use_pulseio=False | Linux SBC 常用模式 |
| exit() | 關閉 DHT Resource |
Adafruit 的目前 Raspberry Pi / Linux Example 明確示範 DHT22、temperature、humidity、RuntimeError、2 秒 Delay 與 use_pulseio=False。
91. DHT11 / DHT22 快速比較
DHT11
│
├── 便宜
├── 0~50°C
├── ±2°C
├── 20~80% RH
└── 約 1 秒一次
DHT22
│
├── 較準
├── -40~80°C
├── ±0.5°C
├── 0~100% RH
└── 約 2 秒一次
92. 本章硬體安全整理
- Raspberry Pi GPIO 是 3.3V Logic。
- 不把 5V DATA 直接送進 GPIO。
- Raw DHT 本章使用 3.3V Power。
- DATA Pull-up 拉到 3.3V。
- Raw Sensor 要確認 Pin 1~4。
- 3-pin Module 要確認實際 Pinout。
- 不假設所有 Module 都內建相同 Pull-up。
- 接線前先關機。
- 不要反接 VCC / GND。
- Sensor 應遠離 Raspberry Pi 主要熱源。
93. 本章軟體安全整理
- 使用 Python 3。
- Bookworm 之後 pip 使用 venv。
- 不使用 sudo pip install 當標準流程。
- DHT 使用 adafruit_dht。
- Raspberry Pi Linux 使用 use_pulseio=False。
- DHT22 至少約每 2 秒讀一次。
- RuntimeError 可以 Retry。
- 未知 Exception 不要全部忽略。
- 程式退出要 dht.exit()。
- GPIO Output 同時做 Cleanup。
94. 本章重點整理
完成本章後,應掌握:
- Sensor 是將物理世界資訊轉換成電氣/數位資料的裝置。
- DHT11 / DHT22 可以同時量 Temperature 與 Humidity。
- DHT 是 Digital Sensor,不需要 Raspberry Pi 外接 ADC。
- DHT11 成本較低,但量測範圍與精度較有限。
- DHT22 溫度與濕度範圍較廣,精度也較高。
- DHT11 最快約每秒讀一次。
- DHT22 最快約每兩秒讀一次。
- Raw DHT 通常有 VCC、DATA、NC、GND 四 Pin。
- 3-pin Module 常將 NC 與 Pull-up 電路整合掉。
- 不能假設所有 DHT Module Pinout 都相同。
- Raspberry Pi GPIO 使用 3.3V Logic。
- 本系列 Raw DHT 使用 3.3V Power。
- DATA Line 需要 Pull-up。
- 本系列使用 4.7kΩ DATA Pull-up。
- DHT DATA 使用 GPIO4 / Physical Pin 7。
- Pull-up 接到 3.3V。
- Unknown 5V DHT Module 應先檢查 DATA Logic。
- 現代 Python DHT Library 使用 adafruit_dht。
- 目前 Adafruit CircuitPython DHT 仍有持續維護。
- Blinka 讓普通 Linux Python 使用 CircuitPython Hardware API。
- Adafruit Blinka 支援 Raspberry Pi 5。
- Raspberry Pi OS Bookworm 之後 pip Package 應使用 Virtual Environment。
- .venv 可以隔離 Project Dependency。
- --system-site-packages 可存取部分 APT System Package。
- Blinka Raspberry Pi 安裝會使用 libgpiod 相關 Dependency。
- board.D4 代表 GPIO4。
- adafruit_dht.DHT22() 建立 DHT22 Object。
- DHT11 則使用 adafruit_dht.DHT11()。
- Linux Raspberry Pi 可使用 use_pulseio=False。
- dht.temperature 取得攝氏溫度。
- dht.humidity 取得相對濕度。
- DHT 偶爾 RuntimeError 並不罕見。
- Sensor Program 應該具有 Retry。
- RuntimeError 可以捕捉後再次讀取。
- 其他未知 Exception 不應全部靜默忽略。
- 每兩秒更新一次適合 DHT22。
- Terminal 可以做即時 Environment Monitor。
- Timestamp 能為之後 Database 做準備。
- Sensor Data 可以建立 Normal / Warning / Danger 狀態。
- PWM LED 可以表示警報程度。
- TonalBuzzer 可以產生高溫聲音警報。
- GPIO4、GPIO18、GPIO23 可以分別安排 Sensor、LED、Buzzer。
- Project 應建立 Pin Assignment Table。
- Sensor 不應太靠近 Raspberry Pi CPU 等熱源。
- Sensor 小幅浮動不一定代表故障。
- Threshold 附近控制最好考慮 Hysteresis。
- DHT 不適合高速 Control Loop。
- DHT 適合初學、環境監測與基本 Logging。
- 完整 Sensor Program 應該有 Cleanup。
- 本章已完成真正的 Sense → Decide → Act 控制系統。
FAQ:Raspberry Pi DHT11 / DHT22 常見問題
Q1:DHT11 和 DHT22 哪個比較適合 Raspberry Pi?
兩個都可以。
如果只是學習:
DHT11
已經足夠。
如果之後要做:
- MQTT
- Database
- Web Environment Monitor
比較推薦:
DHT22
因為它具有較廣量測範圍與較好的精度。
Q2:DHT11 / DHT22 是 Analog Sensor 嗎?
不是一般 Analog Output Sensor。
它內部會輸出 Digital Data,因此 Raspberry Pi 不需要外加 ADC 才能取得溫度與濕度。
Q3:DHT22 可以接 Raspberry Pi 3.3V 嗎?
可以。
DHT11 / DHT22 一般工作範圍約為 3~5V。
本系列為了保持 Raspberry Pi DATA Logic 為 3.3V,Raw Sensor 優先使用:
3.3V
供電。
Q4:可以把 DHT Module 接 5V 嗎?
Sensor 本體可能支援 5V,但未知 Module 的 DATA Pull-up 可能直接連到 VCC。
因此如果 Module 供 5V,有可能讓 DATA HIGH 超過 Raspberry Pi 3.3V Logic。
所以:
先查 Module Schematic。
不要直接假設安全。
Q5:DHT DATA 一定需要 Pull-up 嗎?
對 Raw DHT11 / DHT22 應提供 DATA Pull-up。Adafruit CircuitPython DHT 文件目前也明確要求 Data Line 使用 Pull Resistor。
Q6:Pull-up 要多少 Ω?
本系列使用:
4.7kΩ
Adafruit CircuitPython DHT 文件指出可依 Datasheet 使用約 1kΩ~5kΩ 範圍;其他模組/文件也可能看到不同數值。
Q7:三腳 DHT Module 還需要 Pull-up 嗎?
不一定。
很多 Module 已經內建 Pull-up。
請先查看:
- PCB
- Schematic
- Module Specification
Q8:DHT DATA 接哪個 Raspberry Pi Pin?
本章:
BCM GPIO4
=
Physical Pin 7
程式:
board.D4
Q9:Python 要安裝哪個 DHT Library?
本系列使用:
adafruit-circuitpython-dht
Python Import:
import adafruit_dht
目前 PyPI 版本仍持續維護。
Q10:為什麼不使用 Adafruit_DHT?
Adafruit_DHT 是舊世代 Library。
目前本系列改採維護中的:
Adafruit CircuitPython DHT
+
Blinka
Q11:為什麼需要 Blinka?
因為 CircuitPython Library 原本使用:
board
等 Hardware API。
Blinka 讓 Raspberry Pi OS 的 Regular Python 可以使用這些 API 控制 Raspberry Pi Hardware。
Q12:Blinka 支援 Raspberry Pi 5 嗎?
目前 Adafruit 明確說明 Blinka 支援 Raspberry Pi 5。
Q13:為什麼要用 Python Virtual Environment?
因為 Raspberry Pi OS Bookworm 開始,不建議 pip 直接修改 System Python。
Raspberry Pi 官方建議:
APT
→ System Packages
venv + pip
→ Project Packages
Q14:為什麼出現 externally-managed-environment?
代表你正在嘗試用 pip 修改 Raspberry Pi OS 管理的 System Python。
正確做法是:
python3 -m venv .venv
source .venv/bin/activate
再用 pip 安裝 Project Package。
Q15:為什麼 Raspberry Pi 範例使用 use_pulseio=False?
Adafruit 的目前 DHT Linux Example 說明,Linux Single Board Computer,例如 Raspberry Pi,可能需要:
use_pulseio=False
模式。
Q16:DHT 為什麼偶爾讀取錯誤?
DHT 的 Timing、Noise 或訊號品質可能讓某次讀取失敗。
官方教學也說明這類 Sensor 偶爾讀不到並不罕見,因此應用程式應 Catch RuntimeError 並 Retry。
Q17:多久讀一次 DHT22?
建議至少約:
2 秒
DHT22 本身最快約 0.5Hz,而目前 Adafruit Library 也建議 Retry 時等待至少兩秒。
Q18:DHT11 可以每兩秒讀一次嗎?
可以。
DHT11 最快約每秒一次,因此每兩秒讀一次屬於更保守的更新速度。
Q19:可以用 DHT22 控制風扇嗎?
可以把 DHT22 當:
Temperature Input
但風扇本身不應直接由 GPIO 供電。
應使用:
DHT22
↓
Python
↓
GPIO
↓
MOSFET / Driver
↓
Fan
並依 Fan 電壓與電流設計。
Q20:DHT11 / DHT22 適合長期產品嗎?
可以用於低成本非關鍵環境監測,但它們本身屬於基本、速度較慢的 Sensor,Adafruit 目前也建議有更高可靠度需求時評估較新的感測器方案。
結語
完成第 11 章後,我們已經跨過 Raspberry Pi 課程另一個重要里程碑。
以前:
Human
↓
Button
↓
Raspberry Pi
現在:
Physical Environment
↓
DHT22
↓
Temperature + Humidity
↓
Raspberry Pi
↓
Python
↓
Decision
↓
LED + Buzzer
也就是:
Raspberry Pi 已經真正開始「感知環境」。
目前我們已經具備:
GPIO Input
+
Digital Output
+
PWM
+
Sensor
並且完成:
Sense
↓
Validate
↓
Retry
↓
Decision
↓
Alarm
這已經是一個真正 IoT Device 的核心。
不過 DHT 的通訊方式屬於:
單一 Sensor
+
單一 Data Line
下一章,我們會進入 Raspberry Pi 最重要的標準感測器 Bus 之一:
I²C
I²C 最大的差異是:
一組 SDA / SCL
↓
可以連接多個不同 Address Device
接下來我們會使用:
- raspi-config
- /dev/i2c-*
- i2cdetect
- I²C Address
- LCD1602 I²C
正式學習 Raspberry Pi 標準周邊通訊。
下一章
第 12 章 Raspberry Pi I²C 通訊完整教學:I²C Scanner 與 LCD1602 顯示器
下一章將完整學習:
- I²C 是什麼
- Master / Controller
- Peripheral / Device
- SDA
- SCL
- GPIO2 / Physical Pin 3
- GPIO3 / Physical Pin 5
- 3.3V Logic
- Open-drain
- Pull-up
- I²C Address
- 7-bit Address
- 多設備共用 Bus
- Raspberry Pi 5 I²C
- 開啟 I²C
- raspi-config
- /dev/i2c-1
- i2c-tools
- i2cdetect
- I²C Scanner
- 找出裝置 Address
- LCD1602
- PCF8574 I²C Backpack
- LCD Address 0x27 / 0x3F 的判斷
- LCD 5V 與 Raspberry Pi 3.3V Logic 安全
- I²C Level Shifter
- Python LCD Library
- 顯示 Hello Raspberry Pi
- 顯示 DHT22 Temperature
- 顯示 DHT22 Humidity
- Terminal + LCD 雙重顯示
- I²C Device Not Found 排查
- Remote I/O error
- Address 錯誤
- SDA / SCL 接反
- I²C Bus Conflict
- 建立 Raspberry Pi 第一個 Sensor + Display 系統
完成第 12 章後,就可以把本章:
DHT22
↓
Temperature / Humidity
直接顯示在:
LCD1602
讓 Raspberry Pi 從只有 Terminal 的 Sensor Monitor,進一步變成真正具有獨立顯示介面的環境監測設備。