2017年12月30日 星期六

DS18B20-讀取溫度值【準備篇】

恭禧!過了淺水區!

恭禧各位!已經過了淺水區,並撰寫了使用DS18B20最基礎的三項工具程式:重啟程序、寫位元及讀位元程式。

接下來,只要將它們作加強及掌握DS18B20的使用命令、程序、溫度值位置及溫度值轉換後,既可取得DS18B20的溫度值喲!

本篇文章,就是講述溫度值的讀取程序架構,並將所使用的三個主要工具(重啟、命令、讀取)的相應關係及其功能作一說明,並對於讀取、命令的工具程式作必要說明,這樣就完成了讀取DS18B20溫度值的熱身運動了!

讀取溫度值的程序架構

底下這圖就是讀取DS18B20的程序架構圖,請參考!
讀取程序的細部會於後面說明,此架構主要是標明其使用的三項工具的使用順序,以三個顏色區分:
1、重啟程序(綠色):Arduino將電位拉低並維持480μs,DS18B20應簽低電位值既代表重啟程序OK。

2、命令程序(藍色):命令拆解成為位元,再使用寫位元(Write bit)程序使用DS18B20

3、讀取程序(黃色):讀取DS18B20給予之位元值,並組合成一字元(Byte)

此三項程序於前面都有講述,其中,重啟程序已OK!但命令及讀取程序部份需由再作補充說明,故列舉於下!

命令工具:從寫位元(bit)到下命令

 在讀取程式架構中,會使用到的命令主要有三個:省略ROM確認(0xcc)、啟動溫度轉換(0x44)及讀取暫存器資料(0xbe)等。

似乎有點難,但其實就是將十六進位的命令值拆解成8個二進位位元值,再依序給予(Write)DS18B20既可,底下會以省略ROM確認命令(0xcc)說明之。

程式架構

"省略ROM確認"命令的使用必須是Arduino與DS18B20在一對一的狀況,等同於生活中的一對一相親,所以不用使用一對多的狀況,必須別名牌或是編號以作區別。

其命令值以十六進位表示就是0xcc,在二進位的表示為[11001100],而程式的架構就是將指令(instruction)分八次將位元值傳給DS18B20。簡單的說,就是從低位元起,讀位元值、寫位元(WriteSlot)並重覆8次的動作。


程式碼

void SendCommand(uint8_t instruction)
{
 for(uint8_t i = 0; i < 8; i++) {
  WriteSolt(bitRead(instruction, i));
 }
}

void WriteSolt(uint8_t order_bit)
{
 if(order_bit) {        //當值為1時的處理,
  pinMode(g_dq_pin, OUTPUT);      //先將pin腳改為輸出狀態
  digitalWrite(g_dq_pin, LOW);    //將電位拉低,等於通知DS18B20要do something
  delayMicroseconds(10);       //至少要等待1us,但於15us前轉為高電位
  pinMode(g_dq_pin, INPUT);     //將接收轉成INPUT狀態,轉為高電位
  delayMicroseconds(60);      //加前段的延時至少等待60us過此周期
 }
 else {           //當寫入值為'0'時,Tx拉低電位時段60~120us
  pinMode(g_dq_pin, OUTPUT);    //先轉為輸出狀態
  digitalWrite(g_dq_pin, LOW);   //將電位輸出低電位
  delayMicroseconds(65);         //靜靜的等待DS18B20來讀取資料
  pinMode(g_dq_pin, INPUT);      //釋放電位控制轉回輸入狀態
  delayMicroseconds(5);     //等待上拉電阻將電位復位為HIGH
 }
}

讀取資料工具:從讀位元(bit)到讀取字元(Byte)

從讀取溫度值的程式架構中,Arduino進了了重啟、略過ROM序號確認、啟動溫度轉換、等待轉換,再重啟、略過ROM、讀取暫存器資料後,DS18B20已準備好進行資料的交換,此時,讀取資料程序就必須上場了。

程式架構




讀取資料程序的步驟就是先準備一空白字元值(Byte=0),然後從最低位元(bit 0)開始,讀取DS18B20給予的位元值 (1/0),並將其值放入位槽中,並重覆執行到字元結束(bit 7)。

程式說明

程式中除了基礎的迴圈使用外,多了兩個位元命令[bitSet()]及[bitClear()],說明如下:

bitSet(x, n):將字元變數x的第n位元值設置為1

bitClear(x, n):將字元變數x的第n位元值設置為0


※n值-右起第一位為0、第二位為1


程式碼

uint8_t ReceiveData()
{
 uint8_t byte_in=0;
 for(uint8_t i = 0; i < 8; i++)
 {
  //此時所測到的電位,就是此位元的資料
  if(ReadSlot()) {
   //看看此時主機線的電位狀況若為高位,就是1
   bitSet(byte_in, i);     //將byte_in第i個位元值,設置為1
  }
  else {
   bitClear(byte_in, i);   //將byte_in第i個位元值,設置為0
  }
 }
 return (byte_in);
}

uint8_t ReadSlot() {
 delayMicroseconds(1);
 pinMode(g_dq_pin, OUTPUT);       //轉為輸出,可達到高電位
 digitalWrite(g_dq_pin, LOW);   //將電位拉低告訴DS18B20,主機已準備好了
 delayMicroseconds(2);
 pinMode(g_dq_pin, INPUT);    //轉為輸入狀態,同時釋放線路
 delayMicroseconds(10);     //加前面的延時,約於12~13us時取樣
 uint8_t fp=digitalRead(g_dq_pin);
 delayMicroseconds(55);    //加上延時過渡此段作業時間60us
 return fp;
}


 萬事俱備,讀取溫度去!

此篇是熱身準備,將前面的讀、寫位元的基礎工具進化到讀取資料及命令的程序

好了!工具齊全了,下一步驟就是依讀取溫度的步驟組合工具,讀取得溫度值去!

2017年12月26日 星期二

DS18B20-Read-讀個位元

跨入淺水區的第三步


二話不說,在上一步,我們知道如何寫入一個位元值到DS18B20,此篇是告訴你如何讀取DS18B20的位元值,重點仍是時間,特別是位元值"1"的取樣時間,底下將作細部說明!

從DS18B20讀取位元值

 要謮取DS18B20的位元值,最主要的關鍵是對於位元值"1"的取樣時間點的掌握,底下會先說明官方資料的內容,再作區段說明及程式碼步驟分析。

官方資料

讀取位元值的文字說明於DS18B20的Datasheet的第16頁下方(Read Time Slots),有興趣的可參考一下!

Read的時序圖


 上圖為官方文件中的第16頁中,有關讀位元的時序圖,可分為三部份,第三部份是線條示意,就不必特別介紹。

第一部分是DS18B20的時序輸出(左為位元"0"值輸出時序,右為位元"1"值的輸出時序)

第二部份中的長條狀Master(此為Arduino)讀取點。

關鍵是DS18B20給予的位元值的時間點,是在電位拉低後,1~15μs的時間點中,如果位元值為"0"時,問題不大,主要麻煩的是當位元值為"1"時,如何準確的掌握讀取的時間點,才是重點。

官方建議的讀取位元圖

  可能是讀取位元值"1"的時序很重要,當然也可能是上圖畫的不清楚,所以又給了一張[建議主機讀取時序圖],簡單的說啟始時間(Tint)及電位回復高電位(Trc)越短越好,而主機取樣點靠近信號尾端為佳。


讀取位元時序整合及關鍵

 底下將上述兩圖整合,再拆解成七個步驟來解析其讀取位元的順序及重點說明!

時序對照圖

 重點仍是放在當DS18B20給予的位元值為"1"時,如何正確的讀取其值。上圖為整體圖,而下圖為讀取位元值"1"的步驟及時序圖,其中紫色長條為Arduino的取樣時點(意謂著,當Arduino於此時點取樣時,1就是1,0就是0,不會搞錯)

區段概念分析

 在步驟分析之前,先看一下訊息區段,其實可分為四段

1-啟始訊號段:電位由高轉為低電位,等於通知DS18B20準備將位元值作輸出動作)

2-DS18B20接手段:主機放手:主機端放開電位控制,由DS18B20接手控制

3-訊息混亂段:
   位元值為"0"時,DS18B20會讓電位維持在低電位
   位元值為"1"時,DS18B20會放手讓上拉電阻將電位拉至高電位,這段時間(Trc)為混亂段,
   如果Arduino於此段(灰色段)讀取資料會出現問題

4-正確訊息段:上圖綠色的部份就是最好的取樣時段,在此區段取樣可獲得正確的位元值

關鍵步驟說明

程式碼中有附上詳細的說明,在此只提重點

1-確保讀取時序間,要有至少1μs的間隔

2-整個的讀取時序,最好是60μs

3- 步驟3/5/7的時間,可自行調整,如one wire中的設定是3/10/53,而官方建議是4/8/55,都可行,不妨都試試。

程式碼

ReadSlot()副程式中,分為7個步驟,其中fp為取樣值的變數名稱,讀取位元值並傳回。
uint8_t ReadSlot() {
 //步驟01:確保與上一個讀時序有1us的間隔
 delayMicroseconds(1);

 //步驟02:啟始信號--拉低電位
 pinMode(g_dq_pin, OUTPUT);       //轉為輸出,可達到高電位
 digitalWrite(g_dq_pin, LOW);   //將電位拉低告訴DS18B20,主機已準備好了

 //步驟03:保持低電位最少1us
 delayMicroseconds(3);

 //步驟04:釋放線路電位
 pinMode(g_dq_pin, INPUT);    //轉為輸入狀態,同時釋放線路

 //步驟05:等待時間,
 delayMicroseconds(9);     //加前面的延時,於2+9<=11us時取樣為保險值

 //步驟06:讀取slot的電位值
 uint8_t fp=digitalRead(g_dq_pin);

 //Step07:延時動作達到讀時序時段全長為60us
 delayMicroseconds(48);    //1+2+9+48=60us
 return fp;
}

基本功過關了

恭禧!到此,你已掌握了Arduino控制DS18B20的三個最基本工具:重啟、寫入一個位元值、讀取一個位元值。

下一步,我們就可以讀取溫度值了!


2017年12月25日 星期一

DS18B20-Write-寫個位元

跨出第二步



要掌握DS18B20,其實就只要三個基礎程序,第一項就是啟動程序:包含了重置及應答程序,而第二項就是寫位元(Write a bit)及第三項讀位元(Read a bit),有了這三項基本程序就能延伸出所有的後續操作如命令、讀取溫度值等。

啟動程序已在上一篇談過,本篇開始就進入第二項基礎程序寫字元(Write a bit),關鍵還是時序的掌握。

如何寫入一個位元至DS18B20

首先我會先介紹位元與字元的差異,以免混淆觀念,然後就是將官方資料(Datasheet)的資料呈現出來,再附上寫位元的時序分段概念圖,以供各位參考。

 基本概念:位元(bit)與字元(byte)

位元(bit) :目前電腦的最基本的單位就是位元(bit),每個位元,透過電壓(High/Low)的判別,可以儲存(1/0)兩種訊息

字元(byte):字元(byte)就是8個位元的組合,要注意的是位元序號是由0開始,且由右至左的升序,最左的位元為bit 7,由於每個位元有兩種狀態(0/1),因此8個位元組合而成的字元(byte)就有2^8(2的8次方)=256種狀態可區分。

基本應用:透過標準的狀態規定,可以達到訊息的傳遞。以電腦中常用的A,其基本組成如上圖例中的"01000001",而透過ASCII編碼表中,電腦可顯示它為"A"。

官方資料及其時序圖


資料來源:Datasheet之第15頁及第16頁的圖示

寫位元的時序圖

Arduino 寫"0"訊息進位元槽的時序
1-將電位拉高
2-將電位拉低
3-持續於低電位(60~120μS),讓DS18B20採樣讀取時間
4-釋放電位控制(上拉電阻會將其電位拉高)
5-等待間隔:等待上拉電阻將電位復位為High的時間

Arduino 寫"0"訊息進位元槽的時序1-將電位拉高
2-將電位拉低並持續於低電位(1~15μS)至少1μS,且於15μS前要回復高電位
3-轉換為高電位
4-加上前段的延時,至少要等待60μS(DS18B20採樣時間)

※簡單的來說:寫程序都是拉高電位,再拉低電位作開端,
所以整個寫的時序,需注意的是以下兩項重點:
1、程序間隔時間
2、在DS18B20的採樣時間中給予正確的位元訊息


程式碼撰寫

掌握了時序圖後,再配合程式碼中的說明,應該沒什麼問題,此程式碼沒有輸出,需等第三步Read程序的撰寫,才會有具體的輸出顯示。


程式碼


程式碼是一個WriteSolt(uint8_t order_bit)的副程式,會讀取一個位元值(傳值變數是order_bit),副程式依其值(1或0)來作不同的處理程序。
void WriteSolt(uint8_t order_bit)
{
 if(order_bit) {        //當欲寫入的值(變數名稱:order_bit)為1時的處理,
  pinMode(g_dq_pin, OUTPUT);      //先將pin腳改為輸出狀態
  digitalWrite(g_dq_pin, LOW);    //將電位拉低,等於通知DS18B20要do something
  delayMicroseconds(10);       //至少要等待1us,但於15us前轉為高電位
  pinMode(g_dq_pin, INPUT);     //將接收轉成INPUT狀態,轉為高電位
  delayMicroseconds(60);      //加前段的延時至少等待60us過此周期
 }
 else {           //當寫入值為'0'時,Tx拉低電位時段60~120us
  pinMode(g_dq_pin, OUTPUT);    //先轉為輸出狀態
  digitalWrite(g_dq_pin, LOW);   //將電位輸出低電位
  delayMicroseconds(65);         //靜靜的等待DS18B20來讀取資料
  pinMode(g_dq_pin, INPUT);      //釋放電位控制轉回輸入狀態
  delayMicroseconds(5);     //等待上拉電阻將電位復位為HIGH
 }
}

結語 

完成此一步驟,基本上對於DS18B20的時序圖及其英文資訊應該不會太排斥了吧!其實,電子類的操作英文都不會太難,只是我們不常接觸!

時序圖只要掌握到重點,再加上適當的步驟分解,也可以輕易的轉換成程式!

寫入一個位元,沒問題了,下一步應是講寫入一個字元(byte),但其實就是拆解字元命令,再重覆八次的寫入程序,必要但不重要,所以...

下一步,就是讀取一個位元值的程序!


2017年12月20日 星期三

DS18B20-Reset-3-連線檢測

 特務接頭前的觀察要點

一個特務,一定了解執行任何一次的接頭任務前,都要先觀察據點是否正常。意味著,它可能被"破了",若有出現"異常"的訊息,則立馬回報組織。

Arduino與DS18B20的連接檢測

上一篇[DS18B20-Reset-02-啟動程序]中,執行時可以重啟DS18B20,且當收到DS18B20的應答訊息後,會顯示"DS18B20 Exist"的回饋訊息,而當無法重啟DS18B20時,它會顯示"No DS18B20 right here"。
當一切連線正常時,它會如實的執行,不過此程式只能偵測DS18B20的正常反應,卻無法處理另一狀態,就是Arduino與DS18B20斷線時的錯誤回饋,而此篇的程式就是補強此一短處。

而程式設計的關鍵也不難,如Datasheet中第10頁[Hardware Configuration]中所言,就是當Arduino與DS18B20正常連接並外接一上拉電阻時,它會處於高電位的狀態。反之,當未執行任何執行命令時,連線若出現低電位既是異常。

程式設計說明

簡單而言,程式設計的理念就是在執行啟動程序前,先觀察連線的電位狀態一段時間,期間若有任何的低電位出現,就是連線異常

※ 硬體連線資料請參考[DS18B20-Reset-02-啟動程序]

STEP-1-程式架構

 此程式使用了四個副程式,其架構如下圖:
1.TestConnect():測試連線副程式,為此篇的重點,主要是偵測輸入pin腳,當出現低電位時, 就顯示錯誤訊息"DQ_pin no connect",並傳"0"值給ResetResult()副程式,若通過觀察期, 它仍處於高電位,就傳"1"值給ResetResult()副程式。

2.ResetResult():啟動結果副程式,統合連線測試及啟動測試兩功能,但先測連線,再測啟動, 兩者皆OK才傳"1"值給ShowOkInfo(),否則傳"0"值給ShowOkInfo()。

3.isReset():啟動程序副程式,主要功能為傳回重啟狀態值

4.ShowOkInfo():顯示程程式,當一切正常為"Reset OK",有任何異常顯示"Reset Fail"



STEP-2-關鍵程式碼說明 

此次程式的關鍵是測試連線副程式TestConnect(),觀察期間為240μs,每隔4μs觀察一次電位值,觀察60次,中間若有任何一次出現低電位,則傳回"0"值並結束程式,若整個觀察期間皆為高電位,則傳回"1"值。
uint8_t TestConnect()
{
 uint8_t retries = 60;
 //先拉高電位(轉為讀取狀態)
 pinMode(g_dq_pin, INPUT);
 //若是正常就會處於高電位(DS18B20的一般狀態)
 while(!digitalRead(g_dq_pin))
 {
  retries--;
  if(retries == 0) {
   Serial.println("DQ_pin no connect!");
   return 0;
  }
  delayMicroseconds(4);
 }
 return 1;
}

STEP-3-程式碼

#define g_dq_pin 7
void setup(){
	Serial.begin(9600);
	Serial.println("<>");
}

void loop(){
	ShowOkInfo(ResetResult()) ;
	delay(2000);
}

uint8_t ResetResult()
{
	//傳回檢測Arduino與DS18B20連接狀態
	if(!TestConnect()) {return 0;}
	//直接傳回Reset結果,1既存在,0為非
	return isReset();
}

void ShowOkInfo(uint8_t isOk)
{
	if(isOk) {
		Serial.println("Reset OK");
	} else {
		Serial.println("Reset Fail");
	}
}
//測試Arduino與DS18B20的連接狀態並傳回測試值
uint8_t TestConnect()
{
	uint8_t retries = 60;
	//先拉高電位(轉為讀取狀態)
	pinMode(g_dq_pin, INPUT);
	//若是正常就會處於高電位(DS18B20的一般狀態)
	while(!digitalRead(g_dq_pin))
	{
		retries--;
		if(retries == 0) {
			Serial.println("DQ_pin no connect!");
			return 0;
		}
		delayMicroseconds(4);
	}
	return 1;
}
//啟動程序並傳回狀態值
uint8_t isReset() {
	pinMode(g_dq_pin, OUTPUT);
	digitalWrite(g_dq_pin, LOW);
	delayMicroseconds(720);
	pinMode(g_dq_pin, INPUT);
	delayMicroseconds(70);
	uint8_t is_exist = !digitalRead(g_dq_pin);
	delayMicroseconds(410);
	return is_exist;
}

STEP-4-程式輸出

輸出結果中,可看出有成功四次Reset,然後兩次的失敗,因為我將Arduino與DS18B20的連線拔除, 然後,再插回去就顯示重啟正常。


結語

 其實此一功能是整個讀取溫度程序都完成了之後,到[檢錯/中斷設置及類別化(Object)]時才加上去,當初認為是多此一舉,沒必要,但後來考量到整體的檢錯功能時,就知道不加不行,且要能防止系統出問題,需傳回一異常值(-127℃),才能保證系統就算有硬體連線/元件異常時,也不會出大錯。當然,先在此補充了此功能,也讓各位有一個觀念。

接下來,要用實際數值,來檢驗Datasheet的數字是"正確"的嗎?

2017年12月16日 星期六

DS18B20-Reset-02-啟動程序

A特務與D特務的無聲接頭暗號

各位可以將Arduino與DS18B20的訊息交流,想像成兩個「啞巴」特務的接頭暗號
而訊息的交換是透過一個被彈簧繩(上接電阻)拉著的小球高低(電位狀態)來呈現
1-A特務(Arduino)拉低小球至低於80cm(<0.8V)約480秒,再放開
2-小球會被彈簧繩拉回原來的高度250cm(>2.2V)
3-D特務(DS18B20)會於15-60秒內,將小球再拉低60-240秒
當A特務於放開小球後的第70秒內看到小球是低於80cm(低電位)
代表D特務在線並能正常反應!

時序才是重點

由於DS18B20與Arduino只透過單一線傳遞訊息,因此,時序(包含時間及順序)就很重要,所以對於訊息傳遞過程中,什麼時候"發送"、什麼時段"接收",電位狀態就十分重要。底下,就解析其時序。

DS18B20啟動資料

此部份,先從Datasheet中截取關鍵說明及其時序圖,然後再加上自製的圖形及解說,掌握後既可輕鬆的寫出程式碼。

啟動之文字說明

底下為Datasheet第15頁中關於啟動程序(Initialization Procedure)的說明,簡單的說就是Arduino先發出重置(Reset)命令,接下來就是上拉電阻動作,然後是DS18B20的答應作業。
英文不難,各位可以看看先!(請注意電位的變化及時間數字)

啟動之官方時序圖

 上述的文字下方,就附上了DS18B20的初啟時序圖,可對照一下上述的文字參考之!

 時序圖解析

整個啟動程序(Initialization Procedure)主要可分為兩個部份Arduino發送重置(Reset)與DS18B20應答(Presence)脈沖,我將其細分為6個步驟:
一、Arduino發送重置脈沖(請問有人在嗎?)
1-Arduino先將電位拉高
2-再將電位接低
3-持續低電位至少480μ
4-Arduino釋放控制,然後,上接電阻會動作,將電位拉回高電位

二、DS18B20發送應簽脈沖(有,有人在!)
5-DS18B20於Arduino釋放控制開始,於15-60μs的時間後,將電位拉低並維持60-240μs
【Arduino就於此時段讀取電位值既可判斷是否有DS18B20的存在】
●當讀取的電位為高電位時,代表沒有DS18B20或是已故障
○當讀取的電位為低電位時,代表存有DS18B20
6-應答作業完成後,DS18B20釋放控制,上拉電阻將電位拉回至高電位 
※重置脈沖及接收訊息時段,建議都要超過480μs


程式設計步驟

掌握了Arduino與DS18B20之間的初啟程序後,我們底下就將其硬體接線、關鍵程式說明並將其程式碼及結果整理於下:

STEP-1-零配件清單及接線圖

此圖依序為Datasheet上之外部接線圖、材料清單及零件示意圖


此圖為Arduino與DS18B20接線圖及其局部放大,要注意的是DS18B20之接腳的接線:
1- GND 為電源地。
2- DQ 為數位資號輸入/輸出端。
3-VDD 為外接供電電源輸入端。
【注意:我使用的是Pin 7不是Pin 2喲!】

STEP-2-關鍵程式碼說明 

1、釋放電位控制
於上序時序圖中,Step-4為釋放電位控制,對Arduino而言,其程式碼就是
pinMode(DQ_Pin, INPUT);
代表著釋放控制,並將角色轉換為"聽"的狀態

2、讀取的時間點
由於DS18B20會於Arduino釋放電位後開始計時於15-60μs後將電位接低,
乾脆以最久的時間再加10μs來讀取其狀態,最保險!但最好不要超過120μs!

STEP-3-程式碼

//Arduino數位腳位7接到DS18B20的第2腳(DQ),DQ為Data input/output的縮寫
#define DQ_Pin 7            

void setup() {
 Serial.begin(9600);
 char is_exist = 0;  //有無DS18B20之變數,先預設為不存在(0)
 Serial.println("Start Reset DS18B20 in the Wire Bus...");
}

void loop() {
 //Tx階段:Step 1.主機發送重置脈沖
 pinMode(DQ_Pin, OUTPUT);    //將DQ_Pin調整為輸出狀態,自動會回歸HIGH電位
 //Tx階段:Step 2.主機拉低電位
 digitalWrite(DQ_Pin, LOW);  
 //Tx階段:Step 3.主機持續於低電位480us
 delayMicroseconds(480);     
 //Tx階段:Step 4.主機釋放電位控制,轉為輸入狀態
 pinMode(DQ_Pin, INPUT);  //將DQ_Pin設定作數位輸入動作
 //Rx階段:Step 5.讀取DS18B20電位值
 delayMicroseconds(70);  //此值為DS18B20 max回應反應時間60us再加10us

 //將讀取的電位值反轉,所以是低電位為有DS18B20
 char is_exist = !digitalRead(DQ_Pin);

 //Rx階段:Step 6.延時至超過主機接收訊息時段
 delayMicroseconds(410);

 //結果輸出
 if(is_exist) {
  Serial.println("DS18B20 Exist");
 } else {
  Serial.println("No DS18B20 right here");
 }
 delay(2000);
}

STEP-4-結果輸出 


結語

 是的,透過啟動程序的解析及撰寫,我們寫下了一個不用引用任何程式庫,並能正確的讀取DS18B20是否於線上的程式,踏出了第一步。

接下來,要再補充一下,初始之前還要作的一件事!


2017年12月15日 星期五

DS18B20-Reset-1-基礎知識篇

本篇是介紹DS18B20之基本狀態,如高低電位判定值、上拉電阻及"0與1"狀態介紹。

認識DS18B20的0與1-電壓閥值

首先,要知道Datasheet page2的電子參數:高低電位閥值的部份,其中輸入電壓(Supply Voltage)為DC +3.0-+5.5V之間,而在外接電源的狀態時,高電位閥值(VIH)為2.2V,意謂著只要電壓高於2.2V時,DS18B20會將其視為"1"。而低電位閥值(VIL)為0.8V,意謂著低於0.8V時,DS18B20視為"0"。

必要元件:上拉電阻(Pull-up resistor)的效用

Datasheet中p7,顯示了使用DS18B20要加裝一個必要的上拉電阻,才能有作用喲!
簡單的說:上拉電阻可視為天花板裝了一個彈簧,意謂著當無外力作用時,它能讓你維持於離地三尺的狀態,而就DS18B20而言,就代表著它位於高電位的狀態。
電阻值的選擇:一般是於1~10K中皆可,DS建議是5K,故使用4.7K為宜,而模塊多以10K,也行,只要你的電阻安裝上去後,量測電壓要能高於2.2V既可(太大會近於沒接,太小等同於短路)。

Arduino與DS18B20的硬體連接及狀態

 外部連接電路增加上拉電阻沒問題後,我們進一步看看到底Arduino與DS18B20的連接與讀取的機構為何?

DS18B20的硬體接線架構 

在Datasheet中第10頁的圖中,可以看到其連接機構圖,而將其簡化為右圖,可以幫助明白其作用關係。它代表著,連接通電時,因為上拉電阻的作用,會處於高電位(狀態為"1"),而DS18B20只要按下NMOS開關(接地),就會讓狀態變為"0",反之,Arduino按下NMOS開關(接地)DS18B20就會感應到低電位,狀態為"0",日常生活中,上下樓層間的雙切開關就是這個概念,任何一方皆可控制燈的ON/OFF
在這個作用圖中,有一個電子元件NMOS(N通道MOS),我們於下方簡略的說明其作用。

N通道MOS就是道路收費站

 NMOS的專有名稱為「金氧半場效電晶體」,是常用的電子元件,但簡單的來說,它就是個電晶體,等同於你每天在用的電源開關、水龍頭的概念 (按下開關,通電,打開水龍頭,來水)。如下圖所示:NMOS有三極,源極(S-Sourse)、汲極(D-Drain)及閘極(G-Gate),如同下圖的右上方,可將其視為一個單行道升降橋,重點是升降的部份,既為Gate,當NMOS按下時,等同於升降段下降至橋面水平,既可通車。
再生活化一點,就是開貨車過收費站時,要給足夠的過路費(閥值電壓)讓控制人員按下開關,接通橋面,貨車才能通過。

Arduino與DS18B20的五種狀態 :待機、0與1

了解上述的基本知識後,底下圖示就是將Arduino與DS18B20連接的五種情況列出:
1、一般狀態(Idle State):雙方不動作時,皆可讀到高電位的狀態

2、Arduino處於接收訊息的狀態,DS18B20按下NMOS開關,接通線路接地,Arduino會接收到低電位的狀態訊息,代表為"0"

3、Arduino處於接收訊息的狀態,DS18B20不動作(NMOS開關自動升起),線路會因上拉電阻作用拉回高電位,Arduino會接收到高電位的狀態訊息,代表為"1"

4、Arduino發出"0"的訊息:DS18B20處於接收的狀態下(RX-Receive),而Arduino為發送(TX-Transmit)狀態,Arduino按下NMOS,導通線路接地,代表著"0"的狀態。
     程式碼的寫法如下:
       pinMode(DQ_Pin, OUTPUT);    //Tx階段
      digitalWrite(DQ_Pin, LOW);       //接低電位


5、Arduino發出"1"的訊息:DS18B20處於接收的狀態下(RX-Receive),而Arduino為發送(TX-Transmit)狀態,Arduino接高電位,電路於上接電阻(彈簧)的作用下,自動回歸高電位,代表著"1"的狀態。程式碼如下:
     pinMode(DQ_Pin, OUTPUT);    //將DQ_Pin調整為輸出狀態,自動會回歸HIGH電位


小結

透過上面的介紹,我們知曉了DS18B20的如何透過電位閥值來判定"0"與"1"的狀態,以及Arduino與DS18B20之間如何透過「上拉電阻」的設置與「N通道MOS」的元件來實現雙方狀態訊息("0"與"1")的讀取。

狀態了解了,下一步就是學習如何透過時序來交換訊息

2017年12月9日 星期六

DS18B20的過河導航行前說明!

 想在不用外部程式庫的狀態下,自己能讀取DS18B20嗎?Simple!就是底下這張圖,只要8個步驟,就可以掌握DS18B20喲!想知道嗎?來參加<<DS18B20的過河導航行前說明會吧>>

岸邊熱身(Setup):準備及前置知識

首先,我們會簡介1-Wire通訊的訊息,必須有的常識是DS18B20於"平常"狀態,處於高電位的實現:上拉電阻的使用及直觀替代概念(彈簧)

淺水區(STEP 1-3):工具製作及練習

 以特務接頭的例子,來說明DS18B20如何作啟始(Reset)、命令發佈(Write)及資料讀取(Read),並於階段過程中檢驗官方數據與DS18B20實際表現的差異。

第一島礁(STEP-4):簡易讀取溫度值


常前置基礎工具準備好後,既可以獲得DS18B20的溫度數據組(LSB/MSB),並於了解DS18B20的數據架構及原理後,既可透過轉換程序,獲得初步的溫度值


島礁探索(STEP 5-6):讀取暫存器及CRC檢驗 

 既然,我們可以讀取暫存區的溫度數據組(LSB/MSB),那就可以讀取整組數據,同樣的,也可讀取ROM資料(但不會深入,因為這不是此次的主題),然後,就是數據的檢驗(CRC)的實務操作(不說原理,只明操作)程序,來檢驗溫度數據的正確性。
有了CRC的檢驗,那麼,我們就可以透過測試結果,回頭檢測關鍵程序(Read),並透過合理調整參數值,來增其數據穩定性(小概念:好的產品不是檢查出來的,而是透過檢查改善製程來達到產品的良率提升)

深水區(STEP-7):檢錯/中斷設置及類別化(Object)

 我們強化的工具,並使用CRC檢核DS18B20溫度數據正確性,基本上已完成主要工作,而透過檢錯功能的加入及回饋訊息(-127℃),能讓其安全性提高。禁止/停止中斷的設置,可增加讀取DS18B20的穩定性。
當上述的程序皆已達成後,基本上程式目標已完成。接下來,是將程式碼類別轉換成程式庫的過程,簡單但同樣是不容易,過程中,會說明類別化其實就是從名店轉換成加盟總店的過程的例子讓你更了解。最後,我們會獲得SimpleDs18b20的類別程式碼(.h/.cpp)

彼岸(STEP-8) :程式庫及範例

一步一步的從SimpleDs18b20函式碼(.h/.cpp),先撰寫範例程式(example),確認可正確執行後,再進行程式庫相關文件的生成(keywords-程式關鍵字/README.MD/LICENSE)。
最後,就是上傳到GitHub的簡易程序,到此,搞定,收功,享用海鮮吧!

少說了一個,那個最前面的Ghost是什麼意思?


"Everything you want is on the other side of fear!"

看了行前說明,難嗎?有點,但就是煩了點,不過你會收獲什麼?
嗯!你會知道怎麼看Datasheet、會知道DS18B20的時序圖、內部資料結構、CRC檢核操作、程式類別化、程式庫的建立與上傳!
然後呢?當你完成了這些,我想你已進了Arduino的大門,透過格物的過程,你知了,你就可以善用DS18B20了,既然你會用DS18B20,那麼,其他的又有什麼問題呢?一法通萬法通!

想要嗎?那麼就前進吧!開始這偉大的航程!


2017年12月6日 星期三

SimpleDs18b20就是這麼簡單!

你看,這就是我釣的魚!


話說老鄭拿著一條魚向朋友炫耀,說是他自己釣回來的!
然而,朋友們都不相信,此時,老鄭的老婆剛好路過,看了一下魚
就說:「這魚確實是老鄭自己釣的!,因為,市場沒這麼小條的魚!」
老鄭:「再小.........也是魚呀!」

沒有張屠夫,還是得吃肉

標準的使用DS18B20要使用兩個程式庫, OneWire及DallasTemperature,前者是1-Wire通訊協定,後者是此元件的專用程式庫。品牌好且大家使用也沒問題,真是一好三公道,且將DS18B20的功能發揮到完美。
不過, 各位有沒有想過,前面的溫度感測器DHT22、DS18B20、MAX6755等,我們最想要的其實就只是溫度值!
正如同,喝咖啡,你可以用這個頂級咖啡機來沖泡,大約18000美元,可以給你極致的美味咖啡!
圖片來源:https://shop.forfivecoffee.com/products/la-marzocco-strada-mp

也可以用這個越南咖啡壺來沖泡,價格約10元(在越南的價格),也是咖啡
http://oceanlinktravel.vn/news-travel-guide/cafe-sua-da-thuc-qua-rieng-cua-nguoi-sai-gon.html
其實,程式庫就是工具,它可以是豪華也可以簡單,在我眼中,現有的程式庫,就像是高級遊艇,而且功能齊全,又高大上(高端大氣上檔次),不過說穿了,不就是個出海的工具嗎?咱們用保麗龍板拼一拼也是可以出海不是嗎?
別人寫的出來,很好很強大,是否自己也可以寫一個試試!咱們要的也不多,不用功能齊全(什麼設定位元解析度、一線多元件的)!就設一個小目標:自己寫一個程式庫來就讀取溫度值。

是驢子?是馬?拉出來溜一溜就知道了!

對一個初學Arduino的人來說,這有點挑戰,但也還好,花了一點時間,摸著石頭過河,先參考現有的程式庫,不懂的就找Google、Datasheet,就這樣,一步一腳印的摸著石頭過了河,算是達到自己設定的目標-->程式庫名稱:SimpleDs18b20,功能:讀取DS18B20溫度值。

程式庫的限制 


【注意:這個程式庫只能於Arduino 1pin 接1個DS18B20的情況下使用】
使用條件:
1、Arduino 1pin 只能接1個DS18B20
2、外接電源模式
在滿足上述條件下,這個程式庫就能(也只能)讀取溫度值
※注意:當接線有問題或是DS18B20故障時,會出現"-127"異常值

STEP-1-零配件清單及接線圖

此圖依序為Datasheet上之外部接線圖、材料清單及零件示意圖
此圖為Arduino與DS18B20接線圖及其局部放大,要注意的是DS18B20之接腳的接線:
1- GND 為電源地。
2- DQ 為數位資號輸入/輸出端。
3-VDD 為外接供電電源輸入端。
【注意:我使用的是Pin 7不是Pin 2喲!】

STEP-2- 程式碼說明

SimpleDs18b20既然是Simple,那就是Simple
只有一個功能,就是讀取攝氏溫度值(Get Temperature)
所以只有一個函式GetTemperature()

範例程式的第15行:
Serial.println(ds01.GetTemperature());

讀取(GetTemperature)感測器物件(ds01)的溫度值,並將其值印出

STEP-3-程式碼及輸出

// 引用程式庫SimpleDs18b20
#include <SimpleDs18b20.h&gt
//將連接Pin腳設定於pin 7
uint8_t dq_pin=7;
//建立物件ds01(它是位於pin7的DS18B20)
SimpleDs18b20 ds01(dq_pin);

void setup() {
    Serial.begin(9600);
}

void loop() {
    Serial.print("Ds18B20's Temperature --> ");
    // 使用GetTemperature()來讀取溫度值,並顯示
    Serial.println(ds01.GetTemperature());
    delay(1000);
}

輸出結果 


STEP-4-下載/安裝程式庫(SimpleDs18b20)

有興趣的朋友,可以到以下的連結下載試用看看!內含接線圖、範例程式及程式庫!

 SimpleDs18b20程式庫下載連結




掌握DS18B20就只要過9塊石 

自己寫程式庫很難嗎?說真的,對一個初學者而言,寫DS18B20真有點難!因為到後來,我才發覺,它的水有點深但還不會太深,摸著石頭過河後,回頭看看,喲!不多,要過DS18B20這條河,就只要過九塊石!想試試嗎?且待下回分曉!。

2017年12月3日 星期日

用DS18B20讀溫度,就這麼簡單!

前面有提到要建構Sous Vide的系統架構,但飯要一口一吃,路要一步一步走,首先,就從溫度感測元件開始!
首先,我會說明選擇DS18B20的原因,再者,介紹使用DS18B20的快速、標準程序,最後,感恩一下前輩的努力讓我們可以方便、快速的上手,但想吃魚,除了市場買,也可以自己釣喲!

為什麼是DS18B20?

首先,以【Arduino 溫度】作為關鍵字於淘寶查詢,簡略的整理出以下的訊息

就溫度量測的範圍,都滿足加熱控制區段(40~80℃)的要求,接下來就是選擇的問題,首先,先去除不要的,我的想法是
1、DHT22溫濕度計:不能入水,去掉
2、RTD電阻傳感器:太貴,去掉
3、LM35及NTC傳感器:類比介面,太簡單沒挑戰性,去掉
最從,就剩下DS18B20與K型熱電偶(MAX6675)兩種,最後價格考量,選用DS18B20!

花個四分鐘了解DS18B20吧!

底下這個影片,用說圖的方式簡單的介紹DS18B20,簡單又不失其要,可讓各位有一必要的認識,參考一下


使用DS18B20的標準程序



專案製作前基本功

真心的建議您於實作前,您最好已具有以下幾項基本功:
  • 會安裝Arduino IDE和如何編譯與燒錄程式(這個必須有)
  • 至少實際執行過「LED閃爍控制程式」(不知道沒關係,可以趕快上網Google一下)
  • 了解Arduino程式語言的基本架構(至少要知道void setup()和void loop()的使用)
  • 會安裝第三方程式庫(這很重要,因為後續都會用到)

專案說明

此程式之目的是使用Arduino 連接一個DS18B20於外部供電模式下,讀取環境溫度並顯示於序列埠中。

STEP-1-善用網路資源:Datasheet/他山之石

我們要作的專案主角是DS18B20,所以,先上網下載一下它的Datasheet(使用說明書),英文的沒關係,先放著,我們後面會慢慢看!

DS18B20之原廠說明書

接下來列出三個使用DS18B20的網頁,參考一下,各有千秋

葉難: Arduino練習:溫度感測DS18B20
『物聯網』的生活應用實作:用DS18B20溫度感測器偵測天氣溫度
Arduino 溫度傳感器DS18B20

STEP-2-下載/安裝程式庫

目前使用DS18B20,大都引用二個程式庫:OneWire及DallasTemperature,前者是1-Wire通訊協定,後者是此元件的專用程式庫。Arduino UNO需要使用DallasTemperature函式庫來使用DS18B20溫度感測模組,而DallasTemperature函數庫則需使用OneWire函數庫(通訊協定)

Library01-->One-Wire程式庫

Library02-->DallasTemperature程式庫


下載程式庫的方式可由Arduino IDE中處理,亦可手動安裝,此處介紹手動安裝的方式。
點連結後先將程式庫下載到電腦後解壓縮,將程式庫目錄整個其放入Arduino的程式庫集中區(媒體櫃/文件/Arduino/libraries)
※注意:DallasTemperature程式庫下載後,其檔案名稱為"DallasTemperature_SparkCore-master",請將其改為DallasTemperature後,再置於程式庫集中區中

STEP-3-零配件清單及接線圖

此圖依序為Datasheet上之外部接線圖、材料清單及零件示意圖

此圖為Arduino與DS18B20接線圖及其局部放大,要注意的是DS18B20之接腳的接線:
   1- GND 為電源地。
   2- DQ 為數位資號輸入/輸出端。
   3-VDD 為外接供電電源輸入端。


STEP-4-程式碼說明

【這樣的連接方式是最簡單的情況,既一台Arduino連接單一的DS18B20,且使用外部電源,而非寄生電源】
首先,先將引用程式庫,並設定DQ (Data input/output)腳為pin 2
然後生成物件sensors

要讀取DS18B20的程序有二,先要求它作溫度的轉換,然後再取得攝氏溫度值,關鍵的代碼為19-20行
1、先要求Pin上所有的DS18B20進行溫度轉換
      sensors.requestTemperatures();

2、讀取DS18B20之攝氏溫度值
[ 函式sensors.getTempCByIndex之解析]
 感測器(sensors)使用編號的方式(ByIndex)讀取攝氏溫度(getTempC)
     Serial.println(sensors.getTempCByIndex(0));

 由於是1對1的連接狀況,就像是1對1的相親,而非1對多的狀況,DallsTemperature會自動將PIN腳上的DS18B20列為第一個,序號為0。整個程式碼就是先取得第1個(序號為0)DS18B
20的感測器中所測到的攝氏溫度值,再將其值送到序列埠中顯示。

STEP-5-範例程式及輸出

//注意:此程式只適用於一台Arduino連接一個DS18B20的狀況
#include <OneWire.h>
#include <DallasTemperature.h>

#define DQ_pin 2  

OneWire oneWire(DQ_pin);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
}

void loop(void)
{
  Serial.print("Temperatures->");
  sensors.requestTemperatures();
  Serial.println(sensors.getTempCByIndex(0));
  delay(2000);
}

程式輸出



感恩Seafood!

Arduino許多的元件都是依此模式,參考範例,取得程式庫,下載安裝,再依圖接線,然後,取出範例程式,執行,搞定!
不得不說,Arduino對於初學者而言,真的是十分容易上手,且有成就感!當然,這是它的特色,高手開發,眾人享用並分享心得,讓新手可以既時享用,快則十分鐘,慢則半小時,都可以得到溫度值,真是偉大,感恩Seafood(師傅)!讚嘆Seafood(鮪魚)!回家吃Seafood(海鮮)!
但這不是我要的!

"Me too” is not my style

我當然還是要使用DS18B20來讀取溫度值,但如果只懂得依樣畫葫蘆,就像是每次都等著別人給魚,但其實我想要的是要釣魚的技巧,想吃魚,自己釣!那就意味著,我的目標就是使用自己寫的程式庫,讀到我要的溫度值,就這麼簡單!