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