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的答應作業。英文不難,各位可以看看先!(請注意電位的變化及時間數字)
啟動之官方時序圖
時序圖解析
整個啟動程序(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是否於線上的程式,踏出了第一步。接下來,要再補充一下,初始之前還要作的一件事!
沒有留言:
張貼留言