星期三, 4月 05, 2017

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

[2017/04/05]
我一共有三個溫度感測元件,分別是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); 
OneWire  ds(4);         // Pin 4 連接 DS18B20 (4.7K resistor is necessary)

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);        // start conversion, with parasite power on at the end
  delay(1000);   

  // we might do a ds.depower() here, but the reset will take care of it.
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++) {    // we need 9 bytes
    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) {
    raw = raw << 3;            // 9 bit resolution default
    if (data[7] == 0x10) {

      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);

    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;      // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 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 測溫度穩且精確度高。

[參考資料]

• DHT11 library:Arduino Playground
• LM35:Arduino Playground
• PJRC:OneWire Library & DS18x20 Temperature Example
Share:

0 意見:

張貼留言