學習目標 : 使用藍芽車監測環境溫溼度和空氣品質
學習時間 : 180min
使用模組 : (1) faya brickNano
(2) faya 減速馬達模組 x 2
(3) faya 藍芽模組
(4) faya 溫溼度感應模組
(5) faya 灰塵感應模組
(6) faya 萬向輪模組
工具 : 樂高積木
Android手機
行動電源 (自備)
====================相關知識====================
這篇文章中所用到的模組使用方式及相關知識整理如下,需進一步了解時可點進去參考:
功能介紹 : faya電子積塊與LEGO積木的結合
模組介紹 : faya brickNano
模組介紹 : faya 減速馬達模組
模組介紹 : faya 藍芽模組
模組介紹 : faya 溫溼度感應模組
模組介紹 : faya 灰塵感應模組
模組介紹 : faya 萬向輪模組
註: 本篇的範例需透過Android手機的藍芽介面來遙控faya藍芽遙控車,由於Apple手機的藍芽通訊規範較為嚴謹,一般市場上未經過認證的創客藍芽模組(例如:HC-05),無法和蘋果手機相互溝通。
======================開箱======================
faya空氣品質遙控車(型號NTG-905)是fayalab和高雄海青工商共同討論所開發的專屬手作課程,該遙控車沿用了藍芽遙控車(NGT-503)的概念,額外加入了溫溼度感應模組和灰塵感應模組,配合手機的APP,能夠讓遙控車所到之處進行環境品質的偵測。
包裝盒內包含了製作環境品質遙控車所需的全部模組及附件:
1. faya brickNano主板 2.萬向輪模組 3.減速馬達模組x2
4. 藍芽模組 5. 溫溼度感應模組 6. 灰塵感應模組
7. 積木包 8. micro USB傳輸線 9. 額外積木
10. 積木柱子/蓋子 11. 電源線(B) 12. 跳線盒
====================組裝======================
首先把[1.faya brickNano主板]、[2.萬向輪模組]、[3.減速馬達模組x2]、[4.藍芽模組]、 [5. 溫溼度感應模組]、[6. 灰塵感應模組]的四個角落裝上[10. 積木柱子/蓋子],詳細組裝過程可參考[功能介紹 : faya電子積塊與LEGO積木的結合]和[積木蓋子的使用方式],柱子和蓋子的位置可參考如下完成圖:
接下來把[2.萬向輪模組]取出,在兩端四個柱子,到時候才能使輪子朝下,利用上方的柱子連上積木。
接著開始組裝積木,組出完整結構的車體是非常重要的,這樣才不會在行走過程中,一不小心散得七零八落 。以下的組裝範例是faya團隊經過多次的嘗試,利用有限數量的一般的積木,組出結構還算堅固的車體,大家可以先參考以下組法,待組出心得後,可以創造自己的組裝方式。
如果按照以下的範例,組出來以後會長如下圖,先給大家參考:
我們從車子的主體開始組裝,首先從[7.積木包]中拿出(10x2薄板積木)當作底板,在底板上方組裝出如下圖的結構,此結構需要用到4個轉90度的單粒積木。
然後在上方組兩個(4x2一般積木)和一個(3x2一般積木),如下所示。
接著用另外一個(10x2薄板積木)壓住上圖的結構體
在此薄板上方繼續組出一層如下的排列,記得同樣使用4個轉90度的單粒積木。
以上為車子的主體部分,完成後,拿出[3.減速馬達模組],如果以上車體組裝無誤的話,減速馬達模組的四個樂高圓孔,能夠穩穩地組在剛剛完成車體的側邊,如下所示,首先組裝左輪
接著組裝右輪,然後用一條[11. 電源線(B)]將兩個減速馬達的模組串起來
接下來我們要在車子前方延伸一些機構,增加空間已放置前輪和其他延伸模組,首先加入一片(6x2薄板積木)在最前方做延伸,如下所示。
然後在薄板上方,擺兩個(4x2一般積木)
接著用另一個(2x6薄板積木)壓住在最上方,使結構穩定。
拿出[2.faya萬向輪模組],輪子朝下,在上方的四個積木柱子裝兩片(6x2薄板積木)。
把以上的完成品扣在延伸出來的結構下方,此時萬向輪模組的上方會有三片同樣高度的(6x2薄板積木),如下所示。
接著在前方的左右薄板積木上方,擺兩個(4x2一般積木),如下所示
然後用兩片(6x2薄板積木)壓住前方,增加結構穩定性,如下所示
然後在兩片薄板上面架上兩片(10x2薄板積木)和一片(6x2薄板積木),目的是為了安裝灰塵感應模組,如下所示
接著用兩條[11. 電源線(B)],從左右兩個減速馬達模組先把電源拉出來
接著再覆蓋一片(2x6薄板積木),下圖中兩個橫向的(2x6薄板積木)用來放置溫溼度感應模組的位置。
再來我們在最放方擺一塊(8x6薄板積木),位置請和下方一致,薄板後方要留下兩個轉90度的單粒積木,最為延伸後方車體用。
接下來要延伸車體後方,此區域可用來放置行動電源或額外的模組,首先跨上一片(6x2薄板積木)。
在薄板積木上方放置一個(4x2一般積木)。
然後在上方用另一片(6x2薄板積木)壓住,加強結構穩定性。
接著用一片(6x2薄板積木)放在最上層,如下圖所示。
後方再緊連著一片(8x6薄板積木),此區域可用來放示延伸模組和行動電源
然後用一片(6x2薄板積木)把整個上層壓住穩定,如下所示。
然後我們用幾片積木在後方組出如下結構
接著我們開始安裝剩下的模組,首先在中間的(8x6薄板積木)上方,放上 [1.faya brickNano主板],如下圖所示
安裝完主板後,我們把剛剛左輪拉出來的[11. 電源線(B)]連接到主板上的電源座,安裝位置如下
接下來在主板的後安裝[4.藍芽模組],位置和方向請參照下圖
同樣的,我們用一條[11. 電源線(B)]將電源從主板拉到後方的藍芽模組,電源線安裝位置如下
接下來在主板的前方安裝[5. 溫溼度感應模組],位置和方向請參照下圖
接著我們把之前右輪拉出來的[11. 電源線(B)]連接到[5.溫溼度感應模組]上的電源座,安裝位置如下:
接著同樣的用一條[11. 電源線(B)]將電源從[5.溫溼度感應模組]拉到[6.灰塵感應模組],如下所示
完成後再將[6.灰塵感應模組]安裝在前方[2x10平板積木]上,位置和方向請參考下圖
最後我們開始安裝訊號線,線材從[12.跳線盒]內取出
右輪減速馬達 訊號線:
Arduino_D11 ===> 減速馬達_SIG (右輪)
Arduino_D12 ===> 減速馬達_DIR (右輪)
右輪減速馬達訊號線 :
Arduino_D6 ===> 減速馬達_SIG (左輪)
Arduino_D7 ===> 減速馬達_DIR (左輪)
藍芽模組訊號線:
Arduino_D2 ===> 藍芽模組_RxD
Arduino_D3 ===> 藍芽模組_TxD
溫溼度模組訊號線:
Arduino_D4 ===> 溫溼度感應模組_Data
灰塵感應模組訊號線:
Arduino_Rx0 ===> 灰塵感應模組_TXD
以上完成了訊號線的安裝,最後我們在車子的後方連接上行動電源,本自走車需要行動電源才能自由的活動,由於每個人的行動電源大小不太一樣,底下將以手筆者手邊的行動電源當作示範,大家參考後可以根據自己的行動電源大小組出合適的結構。

首先從藍芽模組下方先接上一條micro USB線
接著在車子最後方組出如下圖結構
然後在藍芽模組的正後方疊三片積木,用來隔開前方的藍芽模組,如下圖所示
完成後就可以在此區域放示行動電源了
下圖為未放置行定電源前的車子外觀,大家可以在他四周加入其他積木,裝飾成自己喜歡的造型,接下來我們可以開始撰寫程式了,
藍芽手機配對:
撰寫程式之前,我們先將手機配和藍芽配對,首先利用micro USB線將行動電源(或任何USBport)與brickNano連結,此時faya藍芽模組會通電,由於手機的藍芽和faya藍芽模組還未配對,因此藍芽模組下方的LED燈會快速閃爍。
接著開啟手機的藍芽通訊通能,並在清單中搜尋HC-05的裝置 (無此選項時,可以找顯示[不明]的那個試試看)。
點選該藍芽裝置後,會要求輸入裝置密碼的畫面,輸入預設密碼[1234]
完成後,模組下方的紅色LED每2秒會閃爍1次 -代表電腦藍芽(主)和模組藍芽(僕)配對成功,手機[paired devices]也會顯示HC-05裝置。
以上配對程序只需要做一次,電腦會記得此模組已經配對過,未來無須重新配對。
程式目標:
(1) Android藍芽介面控制藍芽遙控車
(2) Android藍芽介面收集環境感測資料
(3) App控制介面[fayalab Bluetooth Remote]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2018/11/6 | |
// Faya-Nugget Sample Code (BLE_SensorCar_1.ino) | |
// 單元: 空氣品質遙控車 | |
// 網址: https://fayalab.blogspot.com/2018/11/BLE-SensorCar.html | |
// 目標: (1) Android藍芽介面控制藍芽遙控車 | |
// (2) 可隨時監測環境溫溼度與灰塵 | |
// Wire : Arduino ==> faya Module | |
// D11 ==> SIG (右輪減速馬達) | |
// D12 ==> DIR (右輪減速馬達) | |
// D6 ==> SIG (左輪減速馬達) | |
// D7 ==> DIR (左輪減速馬達) | |
// D3 ==> TxD (藍芽模組) | |
// D2 ==> RxD (藍芽模組) | |
// D4 ==> Data (溫溼度感應模組) | |
// Rx1 ==> TXD (灰塵感應模組) | |
#include <SoftwareSerial.h> // 引入軟體模擬串列埠的函式庫,用來連接藍芽模組 | |
#include "dht.h" // 引入DHT11 溫溼度測器含式庫 | |
#define delayTime 250 // 定義延遲時間 | |
#define DHTPIN 4 // 定義DHT11腳位 | |
#define Wheel_R_DIR 12 // 右輪方向腳位 | |
#define Wheel_R_SIG 11 // 右輪速度腳位 | |
#define Wheel_L_DIR 7 // 左輪方向腳位 | |
#define Wheel_L_SIG 6 // 左輪速度腳位 | |
const int TX = 2; //藍芽模組 RxD 埠連接到Arduino第2腳 | |
const int RX = 3; //藍芽模組 TxD 埠連接到Arduino第3腳 | |
SoftwareSerial fayaBT(RX, TX); // 設定 SoftwareSerial 腳位 | |
dht faya_dht11; // 建構物件名稱 | |
// 以下變數為灰塵感測器使用 | |
int incomeByte[7]; //儲存七個字節的資料 | |
int data; //暫存每個字節的資料 | |
int z=0; // 字節計數器 數據傳輸共7字節 (0~6) | |
int sum; // 校驗位 = 第1~第4字節的總和 = Vout(H)+Vout(L)+Vref(H)+Vref(L) | |
int A=390; // A = 比例係數 (280~500間) | |
int ud; // 灰塵濃度變數 | |
byte Data[5]; //儲存感測資料 [a]+[temp]+[humid]+[dust_high]+[dust_low] | |
String command; // 儲存藍芽控制字串 | |
void setup() { | |
Serial.begin(2400); // 串列埠通訊 baudrate (灰塵感測器 <=> Arduino) | |
fayaBT.begin(9600); // 軟體串列埠通訊 baudrate (Arduino <=> 藍芽模組) | |
pinMode(Wheel_R_DIR,OUTPUT); //右輪方向腳位 | |
pinMode(Wheel_R_SIG,OUTPUT); //右輪速度腳位 | |
pinMode(Wheel_L_DIR, OUTPUT); //左輪方向腳位 | |
pinMode(Wheel_L_SIG, OUTPUT); //右輪速度腳位 | |
StopMove(); //停止前進 | |
} | |
void loop() | |
{ | |
BT_Sensor_Car(); // 呼叫遙控車程式 | |
} | |
//------------副程式 : 接收藍芽指令並呼應相關動作 ------------- | |
void BT_Sensor_Car(){ | |
while(fayaBT.available()>0) // 藍芽資料進來時 | |
{ | |
char command = fayaBT.read(); // 讀取來自手機的指令 | |
switch(command) { | |
case 'S': // 指令 'S' = STOP (停止移動) | |
StopMove(); | |
break; | |
case 'F': // 指令 'F' = Move Foraward (向前進) | |
Forward(); | |
break; | |
case 'B': // 指令 'B' = Move Backward (向後退) | |
Backward(); | |
break; | |
case 'R': // 指令 'R' = Turn Right (右轉) | |
turnRight(); | |
break; | |
case 'L': // 指令 'L' = Turn Left (左轉) | |
turnLeft(); | |
break; | |
case 'A': // 指令 'A' = 收集環境資料 | |
collectData(); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
//---------------- 副程式 : 馬達控制------------------ | |
void StopMove() //停止副程式 | |
{ | |
analogWrite(Wheel_R_SIG,0); | |
analogWrite(Wheel_L_SIG,0); | |
} | |
void Forward() //向前進副程式 | |
{ | |
digitalWrite(Wheel_R_DIR,LOW); | |
analogWrite(Wheel_R_SIG,200); // 修改數值讓後退速度一致 | |
digitalWrite(Wheel_L_DIR,HIGH); | |
analogWrite(Wheel_L_SIG,170); // 修改數值讓後退速度一致 | |
} | |
void turnRight() //向右轉副程式 | |
{ | |
digitalWrite(Wheel_R_DIR,HIGH); | |
analogWrite(Wheel_R_SIG,100); | |
digitalWrite(Wheel_L_DIR,HIGH); | |
analogWrite(Wheel_L_SIG,150); //右轉時左輪動比較快 | |
} | |
void turnLeft() //向左轉副程式 | |
{ | |
digitalWrite(Wheel_R_DIR,LOW); | |
analogWrite(Wheel_R_SIG,150); //左轉時右輪動比較快 | |
digitalWrite(Wheel_L_DIR,LOW); | |
analogWrite(Wheel_L_SIG,100); | |
} | |
void Backward()//向後退副程式 | |
{ | |
digitalWrite(Wheel_R_DIR,HIGH); | |
analogWrite(Wheel_R_SIG,185); // 修改數值讓前進速度一致 | |
digitalWrite(Wheel_L_DIR,LOW); | |
analogWrite(Wheel_L_SIG,170); // 修改數值讓前進速度一致 | |
} | |
//--------------- 副程式 : 發送感測資料 ------------------- | |
void collectData() | |
{ | |
get_dust(); //呼叫get_dust()函式取得灰塵濃度ud | |
Data[0]='a'; //資料傳輸header第1位元 = 'a' | |
int chk = faya_dht11.read11(DHTPIN); // 讀取並儲存溫濕度資料 | |
Data[1]=faya_dht11.temperature; //資料傳輸第2位元 = '溫度值' <70 所以只佔1個byte | |
Data[2]=faya_dht11.humidity; //資料傳輸第3位元 = '濕度值' <100 所以只佔1個byte | |
Data[3]=ud/256; //資料傳輸第4位元 = '灰塵濃度' 0~1300 之間,會佔2個byte,取商數得到高位元byte數 | |
Data[4]=ud%256; //資料傳輸第5位元 = '灰塵濃度' 0~1300 之間,會佔2個byte,取餘數得到低位元byte數 | |
for(int i=0;i<=4;i++){ | |
fayaBT.write(Data[i]); //收集完資料受,將資料透過藍傳到手機端 | |
} | |
command='0'; //資料歸0 | |
} | |
void get_dust() { | |
while (Serial.available()>0) | |
{ | |
data=Serial.read(); | |
if(data == 170) // 170 = 0xaa, 起始字節 | |
{ | |
z=0; // 字節計數歸零 | |
incomeByte[z]=data; // 將data存到第0個字節(0Xaa) | |
} | |
else | |
{ | |
z++; | |
incomeByte[z]=data; // 依序儲存第1字節到第6字節的資料 | |
} | |
if(z==6) //儲存完七個字節後 | |
{ | |
sum=incomeByte[1]+ incomeByte[2]+ incomeByte[3] + incomeByte[4]; //加總字節1~4 | |
if(incomeByte[5]==sum && incomeByte[6]==255 ) //比對加總後是否和字節5(校驗位)相同,並且字節6是否為結束位元 0xff | |
{ | |
float vo=(incomeByte[1]*256.0+incomeByte[2])*5/1024.0; | |
ud=vo*A; //粉塵濃度 Ud= Vout x A | |
} | |
else | |
{ | |
Serial.flush(); //確認傳送緩衝區資料傳送完畢 | |
data='/0'; | |
for(int m=0;m<7;m++){ | |
incomeByte[m]=0; // 七個字節內的資料歸零 | |
} | |
z=0; // Z=6後 | |
} | |
} | |
} | |
} |
備註:
重要!!! 由於下載程式時,請將Arduino的[Rx0]和灰塵感應模組的[TXD]訊號線斷開,因為Arduino會透過Tx1和Rx0上傳程式,上傳時如有負載,會造成上傳失敗。上傳成功後,再將此訊號線接回去。
-L43: 我們直接利用Arduino的串列傳輸介面和灰塵感測器溝通 (Arduino Rx0 連到 灰塵感應模組 Tx1),由於灰塵感測器的傳輸速率協定為2400bps,因此需先定義。灰塵感應模組的詳細使用方式可以參考[模組介紹 : faya 灰塵感應模組]
- L44: 本章範例會透過手機藍芽用無線的方式(藍芽)來控制遙控車,兩這間的協定連線速度為9600bps,faya藍芽模組出廠預設值就是9600 bps,如果之前曾經將藍芽模組改成其他的連線速度,請將他手動改回9600 bps。 修改步驟請參考 [參考資料 : 修改藍芽模組預設BaudRate]
-L64~85 : 本範例會從手機利用藍芽送出控制字串(S/F/B/R/L/A)來控制車子的動作(停止/向前/後退/右轉/左轉/索取感測資料),因此Arduino不須不斷地接收字串指令,比對後進讓車子進行相關動作,指令的部分會在後面介紹。
-L90~94 : 車子暫停副程式 - 當兩顆馬達接收到0V電壓時,馬達就會停止動作
-L96~102 : 車子前進副程式 - 由於兩顆馬達方翻了180度,當右輪順時針轉,左輪逆時針轉時,也就是給的訊號分別為LOW和HIGH時,車子才會前進。SIG給的數值不一致原因是因為由於每顆馬達吃的電流和轉速關係會有些許差異,因此當執行此指令時,車子如果會往左右偏,我們可以透過修改馬達的電壓,讓左右輪前進的速度一致,這邊給的數值需要看到結果後再回來調整。
-L120~126 : 車子倒退副程式 - 控制方式和車子前進的道理一樣,只要把馬達全部反向即可。
- L104-110 : 車子右轉副程式 : 兩輪的自走車需靠兩個輪子間的差速才能轉彎,當要右轉時,左輪的移動路徑會比右輪多出很多,因此在程式中,我們須設定左輪的速度(電壓)比右輪快上許多。
- L120-126 : 車子左轉副程式 : 原理和右轉副程式相同,只要把左右輪的速度和方向對調即可。
-L128-141 : 收集三筆資料 (1) 溫度資料 (2) 濕度資料 (3)灰塵濃度資料,三筆資料收集完成後,會將資料透過.write副程式透過藍芽傳到手機。我們利用5個字元傳輸這三筆資料,其格式如下
Data[0] : 儲存小寫字母a,當作資料傳輸協定的標頭,當手機端接收到字元'a'時,就知道些下來會帶入三筆資料
Data[1] : 儲存溫度資料,由於量到的溫度一定在100度以內,因此只需要一個byte (2^8)的空間就足夠
Data[2] : 儲存濕度資料,由於量到的濕度一定小於100%,因此只需要一個byte(2^8)的空間就足夠
Data[3][4] : 儲存灰塵濃度溫度資料,空氣品質不好時,濃度會破1000,大於256,因此需要兩個byte (2^8)的空間才足夠,因此我們其所量測到的值轉成8進位,存到此兩位元中,等手機端接收到後,在資料還原。
-L143~176 : 取得灰塵濃度,詳細解釋請參考[模組介紹 : faya 灰塵感應模組]
手機藍芽要控器安裝與設定:
本範例透過faya團隊利用App Inventor開發的藍芽遙控器,用來控制藍芽遙控車並收集環境感測資料,app可由此下載。下載完成後,請儲存到手機[Downloads]資料夾,點選此檔案安裝。
安裝完成後,手機會出現以下畫面,此時由於還未和自走車連線,因此下方的三個感測資料全部都是空白的。
接著點選上方粉紅色的[Connection]按鍵,會進入到選擇藍芽裝置的畫面,選擇剛剛配對的藍芽裝置,大家可以透過對藍芽模組下AT Command查詢裝置的位址,我們以後會寫一篇這個文章教學,在此之前,還不會的人只好一個一個式,建議連線成功後,用簽字筆在藍芽模組上寫一下模組的後四碼紀錄一下。
連線成功後,藍芽模組的LED燈會每兩秒閃爍2次,(記得開啟自走車電源),畫面會跳回遙控器的介面,此時下方的三筆資料就會每1秒更新一次,接著就可以使用遙控器控制遙控車了。
遙控器功能 :
(1) 壓下[Forward]按鍵 : 送出字元 'F'
(2) 壓下[Backward]按鍵 : 送出字元 'B'
(3) 壓下[Right]按鍵 : 送出字元 'R'
(4) 壓下[Left]按鍵 : 送出字元 'L'
(5) 放開[Forward / Backward / Right / Left]按鍵 : 送出字元 'S'
以上指令會經由手機藍芽介面送出,並由Arduiono連接的藍芽介面所接受,呼叫副程式讓馬達做出相對應的動作。
拼圖程式很簡單,以[前進]的範例如下
另外,程式裡面用了一個Timer,每秒鐘發送一個'A'給Arduino,Arduino端接收到'A'後,會呼叫[collectData()]副程式,開始收集感測資料,並將資料傳回給手機,程式區塊如下:
範例結果(1):
我們先透過電腦提供電源給藍芽車,在桌上測試車子是否能如期移動,且測試是否接收到環境資料,由影片中我們可看到當連線成功後,順利偵測到環境溫度為22度,濕度為43%,灰塵濃度為26ug/m3。當我們把香放到感測器下方時,灰塵感測器偵測到往上飄的菸,灰塵濃度瞬間就跳到1000ug/m3以上。
第二個範例我們裝上行動電源,直接測試藍芽車的遙控功能,由影片發現前進後退時還是有一點點彎曲,這方便我們可以在程式中微調sig數值進行校正。
討論:
- 本篇範例我們利用Android手機的APP透過藍芽介面發送指令給藍芽遙控車,遙控車上的Arduino接收到指令後,經過程式的比對,馬達會執行相對應的運轉方向,使得藍芽遙控車產生前後左右和停止的動作,同時也會根據指令按時收集空氣品質資料回傳給藍芽手機。
- 手機端的介面[faya Bluetooth Remote]所定義的指令都已經固定了 [F/B/R/L/S/A],如果想要體驗自行定義指令的人,可以下載[Ghost Remote BT],我們在[創意組合 : 二合一自走車 (藍芽遙控車) - 使用手機控制 ]介紹過。
====================================
fayalab 粉絲團
FB本篇留言版
沒有留言:
張貼留言