溫濕度
讀一個有單位、而且會失敗的感測器。 · ⏱ 約 25 分鐘
你會學到三件事
- 有些感測器自己會換算,直接給你攝氏度
- 讀失敗的時候它給你
NaN,而 NaN 不是 0
- 為什麼這顆感測器不能一直讀
開始之前
第 5 課的光敏電阻給你一個 0~1023 的數字,意義要你自己賦予。
DHT11 不一樣——它裡面有一顆小晶片,已經幫你換算好了。
接線:DHT11 的資料腳接 2 號腳、VCC 接 5V、GND 接 GND。
一、宣告要說兩件事
DHT dht(2, DHT11);
|
意思 |
2 |
接在哪一支腳 |
DHT11 |
哪一型——DHT11 和 DHT22 的通訊時序不同 |
⚠️ 型號寫錯的話讀出來全是失敗,而不會報錯。
dht.begin(); // setup 裡
二、讀
float t = dht.readTemperature(); // 攝氏度
float h = dht.readHumidity(); // 相對濕度 %
⚠️ 用 float 不用 int——溫度是 25.3 這種帶小數的值。
存進 int 會變成 25,而那是無聲的資料遺失(C++ 入門第 2 課那件事)。
三、NaN:讀失敗的樣子
執行看看——如果沒有真的接感測器,你會看到:
NaN
NaN
NaN 是 Not a Number(不是一個數字)。
它是浮點數專用的一個特殊值,意思是「這裡沒有有效的答案」。
NaN 不是 0,而這一點很重要。
如果失敗時回傳 0,那 0 度和「讀失敗」就分不出來了——
而在冬天那是兩件完全不同的事。
⚠️ NaN 有一個很怪的性質
if (t == t) { ... } // NaN 的話這是【不成立】的
NaN 不等於自己。這是浮點數標準規定的。
所以判斷讀失敗要用 isnan(t):
if (isnan(t)) {
Serial.println("讀失敗");
return;
}
每次讀完都該檢查一次——DHT11 偶爾會失敗,那是正常的。
四、⚠️ 它讀得很慢
DHT11 每 2 秒才能讀一次(DHT22 是 1 秒)。
讀太快的話它回你上一次的舊值,或直接失敗。
delay(2000);
這是感測器的物理限制,不是程式的問題。
有些東西你就是不能一直問它。
(正式的專案裡,這個 delay 應該換成第 10 課的 millis() 寫法。)
完成的樣子
DHT dht(2, DHT11);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
Serial.println(t);
Serial.println(h);
delay(2000);
}
換你了
加上 isnan 檢查,讀失敗就印「讀失敗」而不是印 NaN。
再進階:接上第 12 課的 LCD,做一個桌上型溫濕度計。
這一課你做了什麼
- 你讀了一個自己會換算的感測器
- 你看到了
NaN,並知道它為什麼不能是 0
- 你知道有些感測器有最短讀取間隔
如果卡住了
| 你看到 |
多半是因為 |
一直是 NaN |
沒接感測器、接錯腳,或型號寫錯(DHT11 vs DHT22) |
| 溫度沒有小數 |
存進 int 了。要用 float |
| 讀得到但值不動 |
讀太快了。DHT11 要間隔 2 秒 |
if (t == t) 判不出失敗 |
NaN 不等於自己也不等於別的。要用 isnan |
在編輯器打開這一課 →