Arduino筆記(20):DHT11、LM35 及DS18B20 的溫度值哪個比較準確?

我一共有三個溫度感測元件,分別是DHT11 (可測溫度跟濕度)、LM35及 DB18B20。如果在同一地點測這三個元件的溫度,不知測得的溫度會一樣嗎?如果跟家裡有顯示溫度量測的時鐘或溫濕度計比較,不知哪個比較準?

以下是我們家有溫度顯示的時鐘、溫濕度計及三個元件讀取數值的照片。我們來看一下比較的結果如何?


[材料]

  • Arduino Uno  x 1
  • DS18B20 IC   x1
  • TM35 IC  x1
  • DHT11 x1
  • 4.7K 電阻 x1
  • 麵包板 x1
  • 連接線 x n條
  • 不同廠牌時鐘或溫濕度計 x3個



[接線圖]

本次檢測的主角照片:最左邊為DHT11、中間為LM35,最右邊為 DB18B20。

[LM35]

在執行程式時,我們使用 analogReference() INTERNAL的方法,來設定 Arduino 的參考電壓 (即用作輸入範圍最高的值)。使用這個設定的原因是 LM35只產生 0 到+ 1V的電壓,而將參考電壓設置為INTERNAL會將其設置為1.1V,也顯著提高了精確度。

在 loop() 中,從LM35讀取數值開始,然後將該讀數除以 9.31。除以 9.31的原因是類比讀數範圍為1024,參考電壓設定為1.1V,計算每一刻度的電壓值為 1.1/1024 = 0.001074V,即1.0742毫V。

LM35的技術規格中提到壓差每10毫V為1攝氏度,若將 10毫V / 1.0742毫V =  9.31,亦即將LM35 讀取的數值除以9.31,就是我們要的攝氏溫度讀數。

LM35有多種不同封裝型式。在常溫下,LM35 不需要額外的校準處理即可達到 ±1/4℃的準確率。靈敏度:10mV/℃,精度:0.5℃ (在+25℃時),測量溫度範圍:0℃ ~ 100℃。

[程式]

註:程式參考Onewire DS18x20 範例進行修改,加入LM35及DHT11測得的結果。
#include <onewire.h>
#include <dht11.h>

int DHTPin=5;
float DHT11temp, DHT11humi, LM35temp;
int LM35Pin  = 0;
int reading;

DHT11 dht11(DHTPin); 
// Pin 4 連接 DS18B20 (4.7K resistor is necessary)
OneWire  ds(4);         

void setup(void) {
  Serial.begin(9600);
  analogReference(INTERNAL);   
  Serial.println("DHT11      LM35        DS18B20  ");
  Serial.println("================================");
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float DS18B20temp, fahrenheit;
  
  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }

  ds.reset();
  ds.select(addr);
  // 開始轉換
  ds.write(0x44, 1);        
  delay(1000);   

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);  

  // 需要9個位元
  for ( i = 0; i < 9; i++) {   
    data[i] = ds.read();
  }

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.

  int16_t raw = (data[1] << 8) | data[0];

  if (type_s) {
    // 預設 9 bit 解析度
    raw = raw << 3;            
    if (data[7] == 0x10) {

      // "count remain" 有完整的12 bit 解析度
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);

    // 在低解析度時,low bits沒有定義,因此設定為0
    // 9 bit 解析度, 93.75 ms
    if (cfg == 0x00) raw = raw & ~7; 
    // 10 bit 解析度, 187.5 ms     
    else if (cfg == 0x20) raw = raw & ~3; 
    // 11 bit 解析度, 375 ms
    else if (cfg == 0x40) raw = raw & ~1; 
    // 預設為12 bit 解析度, 750 ms conversion time
  }
  DS18B20temp = (float)raw / 16.0;

  // DHT11 
  int chk =  dht11.read(DHT11humi, DHT11temp);
  Serial.print(DHT11temp, 2);
  Serial.print(" C    ");   

  //LM35
  reading = analogRead(LM35Pin);
  LM35temp = reading / 9.31;   
  Serial.print(LM35temp);
  Serial.print(" C    ");
  
  // DS18B20
  Serial.print(DS18B20temp);
  Serial.println(" C  ");
}

[執行結果]

紅色鬧鐘:維持在 23.9 - 24.0度
白色溫濕度計:22.8 ~ 23.0 度
指針式溫濕度計:大約 23度
DHT11、LM35及DB18B20執行結果畫面如下:

由以上結果可以得到以下結論:


  • 沒有傳統水銀式的溫度計做比較,無法得知傳統溫度計跟數位溫度計的比較。
  • 白色溫濕度計跟指針式的結果比較接近。但與其他四個數值差異較大,無法得知其採用的晶片,就將該值當作參考。
  • 看一下DHT11的規格表,溫度測量精度:±2℃、濕度測量精度:±5%RH、溫濕靈敏度:1℃ / 1%RH,從程式測得的結果,無法精確到小數點1至2位數。
  • LM35從類比訊號取得溫度值,經過 analogReference() 換算後,提高溫度的精確度,結果跟DS18B20差不多,因為是類比數值換算,不會像DS18B20幾乎是固定的溫度值。
  • DS18B20 測溫度穩且精確度高。


[參考資料]


2 留言

  1. 您好,我想要在魚缸做一個 溫度檢測利用手機遠端監控,控制溫度 ,請問建議哪個溫度感測器較好?

    回覆刪除
    回覆
    1. 您好,可以用防水型的 DS18B20,可以看一下拍賣網站上產品的介紹,https://goods.ruten.com.tw/item/show?21538702351401 。

      刪除

張貼留言

較新的 較舊