2018年1月6日 星期六

DS18B20-溫度值計算

 基本的命令及讀取程序完備後,接下來要進入取值並計算成溫度值的程序。由下面DS18B20的讀取溫度值程序中,可以知道,在Arduino命令DS18B20啟動溫度轉換命令(0x44)後,待待其轉換時間750μs(DS18B20會將溫度值放入暫存區中),再進行重啟、省略ROM確認,再通知DS18B20開始讀取暫存器資料(0xbe),此時DS18B20會依序(從暫存器依序從byte 0開始到byte 8)逐位元(從bit 0到bit 7)傳遞資料給Arduino

而我們會讀取兩次資料,第一次會讀到的Byte為LS Byte(簡寫為LSB)為溫度值的低位元值,再讀一次,會讀到MS Byte(簡稱MSB)為溫度值的高位元值。而溫度值就是MSB+LSB的組合的轉換。

DS18B20的暫存器結構 

 下圖為DS18B20的官方資料,其中左方為暫存器(SCRATCHPAD)結構,及右方EEPROM資料,在此不多介紹EEPROM,簡單的說它就是上下限警告值及位元設定的資料。我們將焦點置於暫存器。
下圖是將官方的暫存器重繪後,並以啟始的狀態呈現。由下圖可看到DS18B20暫存器共有9個byte,但可區分為五個部份


1、溫度值(byte0~1):存放量測到的溫度值,byte 0為溫度值的LSB,而byte 1為溫度值的MSB,以通電後之初值而言,LSB為[01010000]而MSB為[00000101]

2、警示溫度上下限(byte2~3)

3、精確度位元(byte 4): 如下表,使用R1與R0來設定其位元精度(有效值)
4、無效區(byte5~7):未使用

5、CRC檢驗碼(byte 8):通CRC的運算的檢驗碼,可提供Arduino確認資料的正確性。

DS18B20溫測範圍及精度差異

 在了解DS18B20的暫存器後,下圖是DS18B20的量測溫度值、暫存器之二進位元輸出值及十六進位表示值。
由官方資料及表中可知,DS18B20量測的溫度區間為-55~+125℃(-10~85℃時精度為±0.5℃),在12位元的解析度時,其可分辨的溫度最小的量測單位為0.0625℃。

 

由MSB與LSB組成的溫度值

DS18B20的溫度值是用16位元(MSB+LSB)組合,如官方所提供的資料如下:

底下將其區段內容及計算的概念整理之。

溫度值區段


如上圖所示,溫度值位元資料其實是MSB+LSB的組合成十六位元(bit)資料,可區分為符號區、整數值區及精確度區。

符號區(MSB之bit3~bit7):使用5個位元,當溫度值為正時皆為0,而當溫度值為負時則為1,故於程式設計時,只要MSB大於7就意謂著溫度值為負。

整數值區:使用7個位元,MSB之bit 0~2加LSB之bit 4~7組合而成。

精確度區:以12位元為例,正負號(1)+整數值(7)+小數點(4)共計為12位元,而一般作溫度數值計算時,會直接以12位元做計算,再取正確小數點既可。

溫度值計算

 有了上述的基礎知識後,接下來,就是計算的程序,整理如下圖:先判斷正負值,若為負值是做二補數處理並設定負號值,再將兩數結合運算乘於單位量測值0.0625,既得溫度值,若負號值為真,則補上負號,傳回溫度值。
下圖以溫度值-25.0625℃為例(資料於十六位元表示為FE6FH),在12位元的狀態下,其計算的變化:正負號判定、取反值、加1的位元變化(※"~"代表取反值,既0與1互換的動作)。
當初也被LSB負值的計算方式:[取反加一]的為何"加1"所困,後來了解後才知道,因為"0"被算到正值的陣營去了,只好用加1位補足。(詳細的部份,各位可用"二補數"作關鍵字搜索,再細探之)

程式說明

程式中有使用到位元運算反相(~):0與1互換,向左移位(<<)的指令,不難,只是不習慣,可參考上圖的位元變化程序及程式說明,應可掌握

程式碼

float Caculate_Temperature(uint8_t temp_LSB , uint8_t temp_MSB)
{
 boolean  fp_minus = false;        //温度正負標誌:預設為false,因為通常為零度以上
 //當temp_MSB>7代表此溫度為負數值時,測到的數值需要先反相再加 1
 if(temp_MSB > 0x7f)  
 {
  fp_minus = true;      //溫度正負指標,負數時fg_Minus=0
  temp_MSB = ~temp_MSB;     //將temp_MSB中的每一位元反相(0、1互換)
  temp_LSB = ~temp_LSB + 1;
  //將temp_LSB中的每一位元反相(0、1互換),要記得加一,才能正確的反應其值
 }
 //以十六位元空箱來結合MSB及LSB
 uint16_t raw_temp =
     (((uint16_t)temp_MSB) << 8) |   //將MSB先用空的十六位元左移8個位元
     (((uint16_t)temp_LSB));
 //將十六位元的整數值再乘於0.0625的單位值,既得溫度值
 float fp_temp = raw_temp * 0.0625;
 if(fp_minus) {fp_temp = -fp_temp;} //當fp_minus是1,代表是負數,將溫度加上負號
 return fp_temp;
}

結語

此篇資料要花點時間了解,因為包含了DS18B20的硬體、暫存器及位元數值運算、位移等,當初研究時,也不怎麼順利,不過,一去二回,熟了就懂了,但其實只是不習慣而已,只要花點時間,相信就能掌握,而且一旦了解後,你會發覺,好像電子元件的運作就是這麼一回事,很簡單,但這個簡單(Simple)卻不容易(Easy)!

總算完成所有的準備功夫了,下一步,就最讀取溫度值了!

沒有留言:

張貼留言