Semorphe

溫濕度

讀一個有單位、而且會失敗的感測器。 · ⏱ 約 25 分鐘

你會學到三件事

  1. 有些感測器自己會換算,直接給你攝氏度
  2. 讀失敗的時候它給你 NaN,而 NaN 不是 0
  3. 為什麼這顆感測器不能一直讀

開始之前

第 5 課的光敏電阻給你一個 0~1023 的數字,意義要你自己賦予。

DHT11 不一樣:它裡面有一顆小晶片,已經幫你換算好了。

接線:DHT11 的資料腳接 2 號腳、VCC 接 5V、GND 接 GND。

🟢 先把編輯器打開,跟著下面一起做:跟著做

一、宣告要說兩件事

宣告的時候要說腳位,還要說是哪一型:

1DHT dht(2, DHT11);
2變數DHT11宣告溫濕度感測器dht使用命名空間std引入函式庫DHT.h1
意思
2 接在哪一支腳
DHT11 哪一型——DHT11 和 DHT22 的通訊時序不同

⚠️ 型號寫錯的話讀出來全是失敗,而不會報錯。

積木盤上這兩顆寫著「宣告溫濕度感測器 …」與「啟動溫濕度感測器 …」。

1dht.begin();      // setup 裡
變數dht的開頭位置(成員形式)1

二、讀

溫度和濕度各有一支:

1float t = dht.readTemperature();     // 攝氏度2float h = dht.readHumidity();        // 相對濕度 %
變數dht對執行readTemperature變數dht對執行readHumidity宣告float(小數)變數h=宣告float(小數)變數t=12

積木上它寫著「… 讀到的濕度(百分比)」——前面那格選溫度還是濕度。

而檢查有沒有讀到的那一顆寫著「… 不是數字」 ——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 秒), 讀太快的話它回你上一次的舊值,或直接失敗。

1delay(2000);
2000等待毫秒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}
2變數DHT119600啟動溫濕度感測器dht開啟序列埠 傳輸速率dht讀到的溫度(°C)dht讀到的濕度(%)變數t變數h2000等待毫秒序列埠輸出小數位數並換行序列埠輸出小數位數並換行宣告float(小數)變數h=宣告float(小數)變數t=定義函式 回傳型別void(無回傳)loop定義函式 回傳型別void(無回傳)setup宣告溫濕度感測器dht使用命名空間std引入函式庫DHT.h13485910111213

換你了

加上 isnan 檢查,讀失敗就印「讀失敗」而不是印 NaN。

再進階:接上第 12 課的 LCD,做一個桌上型溫濕度計。

到編輯器做這一題:練習:加上 isnan 檢查,讀失敗就印「讀失敗」

做一個

每隔幾秒讀一次溫度,記住到目前為止的最高和最低,一起印出來。

🔴 最高最低的初始值要設什麼?設 0 的話冷氣房裡會出事。 ⚠️ 而讀失敗(NaN)的那一次不可以拿去比:NaN 跟任何東西比都是 false, 所以它不會更新最大值,看起來好像沒事。想一下那會不會咬人。

到編輯器做這一題:做一個:這十分鐘的最高與最低

這一課你做了什麼

如果卡住了

你看到 多半是因為
一直是 NaN 沒接感測器、接錯腳,或型號寫錯(DHT11 vs DHT22)
溫度沒有小數 存進 int 了。要用 float
讀得到但值不動 讀太快了。DHT11 要間隔 2 秒
if (t == t) 判不出失敗 NaN 不等於自己也不等於別的。要用 isnan
在編輯器打開這一課 →