第1步:電路
組件:
1 x Arduino Uno
3 x 220歐姆電阻器
1 x綠色LED
1 x黃色LED
1 x紅色LED
1 x TMP36溫度傳感器
1 x面包板
電線
連接:
步驟1):將Arduino的地線和5V連接到面包板。
步驟2):將LED放在面包板上,并將其陰極接地。將它們的陽極分別通過220歐姆電阻連接到數(shù)字引腳:黃色到引腳3,綠色到引腳4,紅色到引腳5。
步驟3):將TMP36傳感器放在面包板上,將其引腳連接到5V,接地和A0 Arduino引腳。
步驟4):將提供的電纜的一側(cè)連接到JY-MCU藍(lán)牙模塊,另一側(cè)連接到面包板;連接如下:
VCC 《-》 5V
GND 《-》 GND TXD 《-》引腳0(Rx)
RXD 《-》引腳1(Tx)
該草圖還將使用數(shù)字引腳13上的Arduino內(nèi)置LED。
由于TXD轉(zhuǎn)到Rx,而RXD轉(zhuǎn)到,藍(lán)牙模塊的連接可能會有些混亂。 Tx:這是一個解釋。發(fā)送和接收是針對每個設(shè)備的,因此,藍(lán)牙模塊的TXD引腳發(fā)出的傳輸必須由Arduino在Rx引腳0上接收;同樣,從Arduino Tx引腳1發(fā)出的傳輸也必須到達(dá)其RXD引腳上的JY-MCU藍(lán)牙模塊。
警告:藍(lán)牙模塊可能會干擾PC與Arduino的通信:對電路板進(jìn)行編程時,請斷開VCC。 (在我的測試中,情況并非如此,但請確保它不會造成任何傷害)。
步驟2:Arduino代碼-簡介
Arduino監(jiān)聽命令以點(diǎn)亮某些LED或顯示其狀態(tài)。另外,定時器中斷使它可以通過TMP36傳感器檢查溫度:如果溫度大于閾值,則LED點(diǎn)亮;否則,指示燈熄滅。每n秒(其中n是通過應(yīng)用設(shè)置的參數(shù))會向該應(yīng)用發(fā)送狀態(tài)報告。簡單的命令結(jié)構(gòu)使應(yīng)用程序可以將參數(shù)和值發(fā)送到Arduino,反之亦然。
程序中定義的命令結(jié)構(gòu)為:
CMD RED | GREEN | YELLOW =開|關(guān)
CMD TMAX | SECONDS =值
CMD SECONDS =值
CMD狀態(tài)
狀態(tài)消息結(jié)構(gòu)為:
狀態(tài)紅色|綠色|黃色| TMAX | SECONDS | TEMP | THIGH = value
Arduino將以完整狀態(tài)回答STATUS命令,而在中斷時它將報告較短的版本。
示例:
CMD RED = ON將紅色LED點(diǎn)亮
CMD GREEN = OFF將綠色LED熄滅
您可以通過在Arduino IDE的串行監(jiān)視器中發(fā)出命令并查看響應(yīng)來測試草圖:確保在底部的下拉選項(xiàng)中選擇“回車”。
您可以從附件中下載草圖代碼。下一步將對此進(jìn)行詳細(xì)說明。
步驟3:Arduino代碼-詳細(xì)信息
上一步中所述的命令和消息結(jié)構(gòu)
//串行參數(shù):COM11 9600 8 N 1
// r或 n結(jié)束命令行
//藍(lán)牙處于針腳0和1,速度為9600
//命令結(jié)構(gòu)//CMD RED | GREEN | YELLOW = ON | OFF
//CMD TMAX | SECONDS = value
//CMD SECONDS = value
//CMD STATUS
//狀態(tài)消息結(jié)構(gòu)
//STATUS RED | GREEN | YELLOW | TMIN | TMAX | SECONDS | TEMP | THIGH = value
溫度控制所需變量的初始化
float maxTemp = 30.0;//當(dāng)溫度》 maxTemp
int maxTempSensor =(int)((maxTemp/100 + .5)* 204.8);
浮點(diǎn)溫度= 0.0;
以后可以更改maxTemp,但是程序需要使用默認(rèn)值開始。 maxTempSensor是將maxTemp轉(zhuǎn)換為Arduino ADC轉(zhuǎn)換器提供的0-1023范圍;溫度比較將通過我們希望盡快執(zhí)行的中斷例程執(zhí)行:直接比較整數(shù)Pin輸出值而不是浮點(diǎn)溫度更為有效。我們?nèi)匀灰獔蟾鏈囟龋绦驎⑵湟韵嗤拿Q存儲在變量中。
如果您不熟悉溫度轉(zhuǎn)換公式,可以在這里查看。
maxSeconds也可以使用命令進(jìn)行更改,但再次需要默認(rèn)值
int maxSeconds = 10;//每maxSeconds
Pin常量聲明發(fā)送狀態(tài)消息
const int ledPin = 13;//溫度指示燈
const int tempPin = A0;//T36溫度傳感器模擬輸入引腳
const int led1Pin = 3;//黃色
const int led2Pin = 4;//Green
const int led3Pin = 5;//紅色
中斷例程中使用并從其外部訪問的變量
volatile int tempVal;
volatile int seconds = 0;
volatile boolean tempHigh = false;
volatile boolean statusReport = false;
Volatile是一個特殊的關(guān)鍵字,可防止編譯器執(zhí)行某些優(yōu)化:在中斷內(nèi)修改的所有變量例程,并且必須在例程之外進(jìn)行訪問,必須將其聲明為volatile,以表明其值可以隨時更改,并確保在需要時從內(nèi)存中讀取最新的正確值。
命令字符串變量(稍后將對此進(jìn)行說明)
字符串inputString =“”;
String command =“”;
字符串值=“”;
布爾stringComplete = false;
setup()函數(shù)
void setup(){
//開始串行連接
Serial.begin(9600);
Serial.print(“ Max T:”);
Serial.print(maxTemp);
Serial.print(“ Sensor:”);
Serial.println(maxTempSensor);
inputString.reserve(50);
command.reserve(50) ;
value.reserve(50);
pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,LOW);
pinMode(led1Pin,OUTPUT);
pinMode(led2Pin,OUTPUT) ;
pinMode(led3Pin,OUTPUT);
digitalWrite(led1Pin,LOW);
digitalWrite(led2Pin,LOW);
digitalWrite(led3Pin,LOW);
字符串的reserve方法分配作為參數(shù)提供的字節(jié)數(shù)。
需要以下代碼來初始化計(jì)時器中斷并將其設(shè)置為每秒觸發(fā)一次,這是Arduino可以完成的最慢的時間。有關(guān)詳細(xì)信息,請參見此處。
cli();//禁用全局中斷
//初始化Timer1以中斷@ 1000毫秒
TCCR1A = 0;//將整個TCCR1A寄存器設(shè)置為0
TCCR1B = 0;//與TCCR1B
相同//將比較匹配寄存器設(shè)置為所需的計(jì)時器計(jì)數(shù):
OCR1A = 15624;//打開CTC模式:
TCCR1B | =(1 《//為1024個預(yù)分頻器設(shè)置CS10和CS12位:
TCCR1B | =(1 《 TCCR1B | =(1 《//啟用計(jì)時器比較中斷:
TIMSK1 | =(1 《 sei();//啟用全局中斷
}
定時器中斷例程:我們無法更改其名稱,但內(nèi)容是完全可定制的。/p》
ISR(TIMER1_COMPA_vect)
{
tempVal = AnalogRead(tempPin);
if(tempVal》 maxTempSensor){
digitalWrite(ledPin,HIGH);
tempHigh = true;
}
else {
digitalWrite(ledPin,LOW);
tempHigh = false;
}
溫度值-或如上文所述,從傳感器讀取其0-1023整數(shù)表示形式,并將其與閾值進(jìn)行比較:當(dāng)上面的內(nèi)置LED點(diǎn)亮并且tempHigh設(shè)置為true時,否則關(guān)閉LED并 tempHigh設(shè)置為false。
如果(秒++》 = maxSeconds){
statusReport = true;
秒= 0;
}
}
請記住,每秒觸發(fā)一次中斷,但是我們希望報告系統(tǒng)狀態(tài)的頻率降低:秒變量在每次迭代時遞增,直到達(dá)到s報告到期時的值;稍后將在主循環(huán)中通過檢查statusReport標(biāo)志來完成此操作。通常,永遠(yuǎn)不要執(zhí)行太慢的操作,例如從中斷例程中將數(shù)據(jù)寫入串行。
loop()函數(shù)在接收到指令后便會解釋并執(zhí)行命令,然后如果計(jì)時器發(fā)出標(biāo)志,則會報告狀態(tài)打斷。為了從串行緩沖區(qū)讀取字符串,loop()依賴于將在最后定義的serialEvent()函數(shù):該例程在每次loop()運(yùn)行之間運(yùn)行。它沒有得到廣泛的記錄,并且可能不適用于所有的Arduino模型。無論如何,將其內(nèi)容嵌套在主循環(huán)中并不難(請參見本步驟的結(jié)尾)。
void loop(){
int intValue = 0;
if(stringComplete){ boolean stringOK = false;
if(inputString.startsWith(“ CMD”)){
inputString = inputString.substring(4);
首先,我們檢查接收到的字符串是否以“ CMD”開頭:如果是這樣,我們可以丟棄前四個字符,否則稍后會出現(xiàn)錯誤。
int pos = inputString.indexOf(‘=’);
if(pos》 -1){
command = inputString.substring(0,pos);
value = inputString。 substring(pos + 1,inputString.length()-1);//提取最多 n個被排除的命令
有兩種類型的命令:設(shè)置值的命令,在其中找到分隔空格的“ =”值對,以及該命令是單個指令(STATUS)。如果pos處出現(xiàn)“ =”,則字符串將分為命令(左部分)和值(右部分),并將“ =”插入中間,并在行尾添加末尾字符。
如果(command.equals(“ RED”)){//RED = ON | OFF
value.equals(“ ON”)? digitalWrite(led3Pin,HIGH):digitalWrite(led3Pin,LOW);
stringOK = true;
}
否則if(command.equals(“ GREEN”)){//GREEN = ON | OFF
value.equals(“ ON”)嗎? digitalWrite(led2Pin,HIGH):digitalWrite(led2Pin,LOW);
stringOK = true;
}
否則if(command.equals(“ YELLOW”)){//YELLOW = ON | OFF
value.equals(“ ON”)嗎? digitalWrite(led1Pin,HIGH):digitalWrite(led1Pin,LOW);
stringOK = true;
}
我們檢查并執(zhí)行LED命令;請注意,代碼僅檢查值ON:如果您寫入GREEN = ASD,它將被解釋為GREEN = OFF。它不是完美的,但是它使事情變得簡單得多。每次識別并執(zhí)行命令時都會設(shè)置stringOK = true,以便以后標(biāo)記錯誤的命令。
否則,如果(command.equals(“ TMAX”)){//TMAX =值
intValue = value.toInt();
如果(intValue》 0){
maxTemp = (float)intValue;
maxTempSensor =(int)((maxTemp/100 + .5)* 204.8);
stringOK = true;
}
}
否則,如果(command.equals(“ SECONDS”)){//SECONDS = value
intValue = value.toInt();
如果(intValue》 0){
maxSeconds = intValue;
stringOK = true;
}
}
當(dāng)值應(yīng)為數(shù)字時,我們需要將其轉(zhuǎn)換并測試它確實(shí)是一個數(shù)字。對于MaxTemp,我們還按照變量定義部分中的說明計(jì)算傳感器值
}//pos》 -1
else if(inputString.startsWith(“ STATUS”)){
Serial.print(“ STATUS RED =”);
Serial.println(digitalRead(led3Pin ));
Serial.print(“ STATUS GREEN =”);
Serial.println(digitalRead(led2Pin));
Serial.print(“ STATUS YELLOW =”);
Serial.println(digitalRead(led1Pin));
Serial.print(“ STATUS TMAX =“);
Serial.println(maxTemp);
Serial.print(” STATUS SECONDS =“);
Serial.println(maxSeconds);
Serial.print(“ STATUS TEMP =”);
Serial.println(temperature);
Serial.print(“ STATUS THIGH =”);
Serial.println(tempHigh);
stringOK = true ;
}//inputString.starts With(“ STATUS”)
如果命令是STATUS,則程序僅將所有信息輸出到串行。
}//inputString.startsWith (“ CMD”)
stringOK嗎? Serial.println(“ Command Executed”):Serial.println(“ Invalid Command”);
指示是否已收到有效或無效命令。
//清除字符串以進(jìn)行下一次迭代
inputString =“”;
stringComplete = false;
}//stringComplete
下一次命令迭代的變量內(nèi)務(wù)處理。
if(statusReport){
temperature =(tempVal * 0.0048828125-.5)* 100;
Serial.print(“ STATUS TEMP =”);
Serial.println(temperature);
Serial.print(“ STATUS THIGH =”);
Serial.println(tempHigh);
statusReport = false;
}
}
如果中斷例程已引發(fā)statusReport標(biāo)志,則將打印一些信息請注意,此時要計(jì)算當(dāng)前溫度值:因此,如果在statusReport時間間隔之間發(fā)出STATUS命令,則會得到舊的溫度值。
如前所述,只要新數(shù)據(jù)進(jìn)入硬件串行RX,就會發(fā)生serialEvent()。該例程在每次loop()運(yùn)行之間運(yùn)行,因此在循環(huán)內(nèi)部使用delay可以延遲響應(yīng)。可能有多個字節(jié)的數(shù)據(jù)。
無效的serialEvent(){
而(Serial.available()){
//獲得新的字節(jié):
char inChar =(char)Serial.read();
//將其添加到inputString:
inputString + = inChar;
//如果傳入字符是換行符或回車符,則設(shè)置標(biāo)志
//,因此主循環(huán)可以對此做一些事情:
if(inChar ==‘ n’|| inChar ==‘ r’){
stringComplete = true;
}
}
}
從串行讀取每個字節(jié)并將其添加到輸入字符串,直到遇到“ n”或“ r”表示字符串結(jié)尾:在這種情況下,設(shè)置由loop()檢查的stringComplete標(biāo)志。同時使用回車符 r和換行符 n確保代碼能夠從各種輸入(包括Arduino IDE串行監(jiān)視器以外的其他串行終端)檢測字符串結(jié)尾。
關(guān)于藍(lán)牙和串行的注意事項(xiàng)
在許多示例中,包括JY-MCU賣方的示例,您可以找到連接在不同Arduino數(shù)字引腳(例如10和11)上的藍(lán)牙模塊,以及通過SoftwareSerial庫訪問。根據(jù)我的測試結(jié)果,當(dāng)該模塊僅用于發(fā)送信息時,SoftwareSerial可以完美運(yùn)行,但是在接收命令時Arduino Uno不夠快。我沒有嘗試降低SoftwareSerial連接的速度(在示例中通常設(shè)置為2400bps),因?yàn)镸IT AppInventor應(yīng)用似乎不支持藍(lán)牙連接速度設(shè)置。
使用SoftwareSerial,serialEvent()不會工作:需要重命名它(例如mySerialEvent())并在loop()的開頭顯式調(diào)用它。
步驟4:App Inventor代碼-簡介
在使用Android應(yīng)用之前,您需要將Bluetooth模塊與智能手機(jī)配對。
給Arduino開發(fā)板通電,打開在Android手機(jī)上的藍(lán)牙上并搜索附近的藍(lán)牙設(shè)備:JY-MCU模塊將顯示為HC-06,配對密碼為1234。
藍(lán)牙Arduino連接的關(guān)鍵組件應(yīng)用程序是藍(lán)牙客戶端,而Arduino板將充當(dāng)服務(wù)器:這意味著應(yīng)用程序?qū)⑹冀K啟動連接。給Arduino開發(fā)板供電時,藍(lán)牙模塊紅色LED開始閃爍;按下應(yīng)用程序的“連接到設(shè)備”按鈕,然后從列表中選擇模塊:紅色LED指示燈將變?yōu)榉€(wěn)定,連接狀態(tài)將變?yōu)椤耙堰B接”。
同樣,這與藍(lán)牙無關(guān)Master/Slave,但仍可能令人困惑:您的Bluetooth模塊需要為Slave,但它(或Arduino草圖)在客戶端中將充當(dāng)Server-與Android應(yīng)用程序進(jìn)行服務(wù)器通信。
您可以直接從Android Play商店安裝Bluetooth Arduino Connection App,或者您可以通過下載附件將完整的應(yīng)用程序代碼導(dǎo)入到MIT App Inventor項(xiàng)目中。
藍(lán)牙Arduino連接應(yīng)用程序是使用MIT App Inventor 2開發(fā)的;以下步驟將提供詳細(xì)說明。
步驟5:App Inventor代碼-詳細(xì)信息
Arduino藍(lán)牙連接應(yīng)用程序的關(guān)鍵組件是:
用于藍(lán)牙配對設(shè)備的ListPicker(ListPicker1)
3個按鈕,每個按鈕控制相應(yīng)的配色板LED(RedLedBtn,GreenLedBtn,YellowLedBtn)
發(fā)送狀態(tài)命令(GetStatusBtn)的按鈕
帶有關(guān)聯(lián)按鈕的按鈕文本框以設(shè)置狀態(tài)報告間隔(SecondsBtn和SecondsTxBx)
巨大的多行狀態(tài)標(biāo)簽,顯示從Arduino板(狀態(tài))接收的信息
上一步(BluetoothClient1)
一個時鐘組件,該時鐘組件在客戶端連接時每秒觸發(fā)一次中斷(Clock1)
以下是基于以下內(nèi)容的應(yīng)用代碼說明:上面的圖片。
圖1
Variabl當(dāng)打開應(yīng)用程序屏幕時,將設(shè)置并初始化LED的狀態(tài)和間隔。
圖2
連接ListPicker對象ListPicker1使用兩種方法:
已準(zhǔn)備好可用(配對)的藍(lán)牙設(shè)備的列表,并顯示給用戶
當(dāng)用戶選擇設(shè)備時,將調(diào)用Bluetooth Client對象的Connect方法為了開始連接:如果成功,它將顯示在適當(dāng)?shù)臉?biāo)簽中,并激活Clock中斷,以便可以接收來自設(shè)備的消息。
圖3
在這里,我們演示如何向Arduino板發(fā)送命令。
按下GetStatusBtn時,將調(diào)用Bluetooth Client對象的SendText方法并執(zhí)行文本命令發(fā)出:注意,在“ CMD STATUS”字符串的末尾添加了“ n”,以便Arduino草圖中的serialEvent()函數(shù)能夠知道消息何時結(jié)束。
代碼打開或關(guān)閉LED稍微復(fù)雜一點(diǎn):
我們使用相應(yīng)的變量來跟蹤其當(dāng)前狀態(tài):如果打開,我們想將其關(guān)閉,反之亦然;因此,首先,我們將變量更改為布爾值
,然后使用新狀態(tài)更新按鈕標(biāo)簽
最后,調(diào)用BluetoothClient1.SendText來傳輸命令。
其他命令的代碼非常相似,因此未顯示。
圖4
每次Clock1計(jì)時器觸發(fā),該例程被執(zhí)行:它等效于Arduino的serialEvent();。如果BluetoothClient1接收到字節(jié),則將它們復(fù)制到狀態(tài)標(biāo)簽中。請注意,Bluetooth客戶端對象具有一種返回所接收消息長度的方法。
步驟6:結(jié)論
在此指導(dǎo)中,我演示了一個通過藍(lán)牙連接Arduino開發(fā)板和Android智能手機(jī)的有用方法。通信是雙向的,因此開發(fā)板不僅向應(yīng)用程序報告其狀態(tài),而且還從應(yīng)用程序接收命令。
此外,一個簡單的擴(kuò)展程序允許將Arduino的命令發(fā)送給應(yīng)用程序。電話:例如:按下板上的按鈕即可拍照或發(fā)送短信。
Arduino草圖可以作為遠(yuǎn)程命令處理的基礎(chǔ),它使用中斷來執(zhí)行一些操作-檢查溫度并打開LED警報-并發(fā)送狀態(tài)心跳信號:該技術(shù)不僅可以通過藍(lán)牙通信應(yīng)用,還可以通過以太網(wǎng)等其他方式應(yīng)用。
MIT App Inventor應(yīng)用程序使用中斷同樣:它等效于Arduino的loop()+ serialEvent()函數(shù)的重復(fù),并且類似地用于接收消息。
-
Android
+關(guān)注
關(guān)注
12文章
3941瀏覽量
127716 -
藍(lán)牙
+關(guān)注
關(guān)注
114文章
5862瀏覽量
170930 -
Arduino
+關(guān)注
關(guān)注
188文章
6477瀏覽量
187550
發(fā)布評論請先 登錄
相關(guān)推薦
評論