【雙A計劃】Part7:Arduino超音波感測距離回傳數值給Android手機

雙A計畫不知不覺就來到第七篇了呢!這次我們將告訴您如何在 Android 手機端接收 Arduino端數位感測元件的數值,本範例使用的是超音波感測器讀取的距離數值。

雙A計畫文章總覽:

中文系列文章

English version

 

作者/攝影   袁又緣
難度

★★★☆☆

材料表

【推薦套件】自學者的天堂|Arduino 入門到雲端基本套件包

下載

範例程式請點我下載(App Inventor.aia)

先來看看示範的影片吧!  

 

 

請先按照電路圖將電路接上,以下是超音波感測器與藍牙收發器接到Arduino的各個腳位

藍牙收發器:

GND → GND,  VCC → 5V,  TX → 11,  RX → 10

超音波感測器:

GND → GND,  VCC → 5V,  Trig → 8,  Echo → 9

Screen Shot 2015-06-06 at 9.00.05 PM  

 

App Inventor 端程式

本範例使用的App使用者介面如下:
 
 
Screen Shot 2015-06-06 at 11.43.32 AM
 
記得要將Clock元件的TimeInterval設定設短一點,每隔一段時間手機會去接收來自藍牙的訊息,為了避免漏接的情形,我們可以把這個間個時間改短一點,本範例使用100毫秒。
 
Screen Shot 2015-06-06 at 11.45.15 AM
 
接下來是 Blocks 頁面,全部程式碼如下圖,大致上可區分成四個區塊:
 
Screen Shot 2015-06-06 at 11.52.21 AM
 
區塊 元件名稱 功能
1.藍牙列表的設定 when List_BT.BeforePicking 在藍牙連線到裝置前,先將之前配對好的藍芽裝置匯入到準備連接的列表中
2.藍牙連線到裝置 when List_BT.AfterPicking 選好要連接的藍牙裝置後,將藍牙列表關閉、啟動計時器開始每隔一段時間讀值,並把斷線的按鈕設定為可執行
3.藍牙通訊(發送key與接收資料) when Clock1.Timer 計時器啟動後,每隔一段時間(100ms)就會啟動一次,一開始我們會先發送一個key(=97)給Arduino,如果Arduino確任無誤的話也會發送一個key(=97)給手機,手機確認無誤後,會開始收兩個byte(1byte = 8 bits)的數值,因為Arduino端送出的數值是採用8bits的封包,所以在這邊要將它還原回來必須將它從8bits(2^8 = 256)轉回10進制,最後在除上100將單位轉成cm
4.斷線按鈕的設定 when Btn_Disconnect.Click 按下斷線後就會斷開藍牙通訊,並把按鈕配置回到一開始的狀態
 
 

Arduino端的程式設計

接下來我們看到Arduino的程式碼,藉由計算超音波打到物體的收發時間間隔,再搭配上音速的計算公式,就可以算出距離,注意到本程式碼為了保留小數兩位,所以先乘上100,並化成整數再轉成兩個bytes的封包,Arduino在發送訊息之前,也會先確認是否收到手機端送來的key,確認無誤之後,就會將資料送出去,資料的前頭也會附上Arduino傳給手機端的key,一方面讓手機知道可以接收資料了,一方面也比較不會有封包漏接的情況,因為手機端每次收資料,都會將以收到的key開始做基準收兩個bytes。
 
程式碼如下:
 
Arduino_Android_UltrasonicSensor
#include <SoftwareSerial.h> //Arduino I2C library

const int trig = 8; //define Arduino pin
const int echo = 9;
const int TX = 10;
const int RX = 11;

const int delay_time = 1000; //delay 1000 ms for every measurment

SoftwareSerial BT(RX, TX);
//set Bluetooth RX (-> pin TX of Bluetooth Module), TX (-> pin RX of Bluetooth Module)

void setup() {
Serial.begin(9600); //set baud rate of Serial Monitor
BT.begin(9600); //set baud rate of Bluetooth
pinMode(trig, OUTPUT); //set trigger pin to OUTPUT (-> pin trig of Ultrasonic Sensor)
pinMode(echo, INPUT); //set echo pin to INPUT (-> pin echo of Ultrasonic Sensor)
Serial.println("Start!!!");
}

void loop() {
float duration; //duration to record the time of every back and forth
float distance;
digitalWrite(trig, HIGH); //trigger sona for 1 ms
delayMicroseconds(1000);
digitalWrite(trig, LOW);
duration = pulseIn(echo, HIGH);
//use pulseIn() function to get the time of pin echo from HIGH to LOW, unit=microseconds
distance = (duration / 2) * 0.034;
//distance = ( half of time of back and forth )x( wave velocity(use 0.034 cm per microsecond) )

Serial.print("Distance ="); //show result on Serial Monitor
Serial.print(distance);
Serial.println("cm");
delay(delay_time);

int sendData = (int) (distance * 100); //times 100 and convert disance to integer
byte packet[3];
packet[0] = 97; //key send to phone
packet[1] = sendData / 256; //divides sendData to two 1 byte packets
packet[2] = sendData % 256;



if(BT.available() > 0) //check BT is succeed
if(BT.read() == 97) //check recieve key from phone
{
Serial.println("succeed!");
for(int i = 0; i < 3; i++)
BT.write(packet[i]); //send packet to phone
}


}

80 thoughts on “【雙A計劃】Part7:Arduino超音波感測距離回傳數值給Android手機

  1. 初學者 says:

    請問一下 : 有沒有可能 ….

    1. 點下手機 app 按鈕打開超音波接收 app 之後 , 藍芽自動連接上 , 而不需要再次去 點擊 connect 按鈕 ?

    2. 如果是懶人的話(像我這樣) , 有沒有可能設計成 : 手機一開機 , 就自動進入 app 的測量畫面 ?

    感謝回復 謝謝

    • CAVEDU 阿吉 - 雜工 says:

      您好, 當然可以的, 只要把藍牙連線的指令(bluetoothClient.connect)指令寫在 Screen1.Initialize 事件中就可以了. 但要注意您的arduino 要先開起來等候連線, 不然程式開啟時會試著連線一次, 沒連上就沒戲唱了

    • CAVEDU 阿吉 - 雜工 says:

      請參考本篇:http://blog.cavedu.com/programming-language/appinventor/appinventorandarduinowithbluetooth3/ 但您是用SR04嗎? 這類型的超音波感測器如果超過2公尺的話不是太準,建議只送出2m以內的數值這樣會比較簡單

  2. anthonCH says:

    你好,請問如果要將超音波之類的感測器從序列埠上讀取到的多筆數值,輸出成TXT檔可行嗎(週邊界面是超音波感測器->Arduino UNO改接USB->PC)?
    還有輸出指令的寫法是否是用void loop()迴圈裡用if else條件式去寫?

    • 許 鈺莨 says:

      你好,如果要將數值輸出成TXT檔是可行的,以下有幾種方法供你參考:
      1.使用teraterm免費軟體,在網路上搜尋teraterm Arduino關鍵字有很多教學,Arduino輸出指令是Serial.print(); 或 Serial.println();
      2.使用Arduino透過firmata協定,利用Python做輸出。建議參考書目:Python x Arduino物聯網整合開發實戰
      3.可以買SD卡模組,將檔案存入SD卡內。

      • anthonCH says:

        感謝你的回覆!
        方法一的部分我也有看到國外的玩家用類似Teraterm的免費軟體”Coolterm”來做ARDUINO的TXT輸出。
        只是方法二和方法三的是用Python的程式語言,比較符合我的需求。
        請問簡單來說使用方法二的話,是不是先將ARDUINO的程式上傳板子->Python再跟ARDUINO做連結->最後把ARDUINO的data存成TXT檔放到Python的資料夾裡面?

        • 許 鈺莨 says:

          你好,先說方法二,方法二只需要用到SD的函式庫即可,不需要用到Python。
          再來方法三,你說的沒錯,Arduino這端上傳完程式,然後Python這端要安裝pySerial套件跟Arduino COM port溝通,讀到的txt會存在執行的Python檔的同一個資料夾中。
          可以詳見:https://playground.arduino.cc/Interfacing/Python

    • CAVEDU 阿吉 - 雜工 says:

      可以的,但這樣就要走WIFI了,App Inventor端也要改成Web元件來與開發板互動,本篇教學就不適用囉 這篇提供您參考:https://medium.com/kidstronics/mit-app-inventor-2-meets-esp8266-03-kidserie-fa92cc8ae8a2

  3. Rxg says:

    我想請問下 我想將火焰感測器數值傳到手機app裡(利用藍芽的方式) 當偵測到火焰時蜂鳴器會叫 我可以參考哪一篇呢 我把您一~七篇教學文都參閱了 但還是不太會弄

  4. Aki says:

    老師您好
    如果要將這篇文章中的app跟常閉型震動感測器(sw-420)做應用的話應該如何修改呢?
    他是數位輸出的感測器
    我想要製作一個類似警報器的東西,當震動感測器感受到震動的時候就會透過藍牙傳送訊號給手機
    請問app及編碼的部分應該如何修改呢?
    謝謝老師

    • CAVEDU 阿吉 - 雜工 says:

      您好,請參考本系列Part 2,請把code中的analogread改為digitalRead即可。如果有偵測到震動(digitalRead() 結果為 1) 就送某個數字或字元給App Inventor,反之則送另一筆資料。架構都是一樣的,請先確認在Arduino端可以正確讀取感測器資料即可

      不過感測器都是輸入裝置才對喔

  5. 巫國華 says:

    如果改成用夏普PM2.5和DH22 使用藍芽HC06 傳送至手機 ARDUINO的程式碼怎麼寫? AI2的方面怎麼製作?

  6. Hsu says:

    您好,想做這個來做專題
    但我們運用的是 拿超音波來量身高的值。
    想請問 可以讀取 身高的值嗎, 我有這個來做測驗 發現距離一高的時候差距滿大的。

  7. 承德 says:

    您好,我們最近做專題遇到了一些問題想請教你們
    問題如下:我們因為需要所以用了兩台arduino,讓兩台以I2C連結(有線),其中master端想要加入藍芽,讓手機能夠傳一些數值給master的arduino做使用,但不知道會不會與I2C做衝突呢?

    • 鈺莨 says:

      你好Chris:
      如果使用MQ-3去做的話,AppInventor不需要改,則Arduino端需要改寫接收到MQ-3的值就好了

  8. Ruby says:

    你好,我想請問,若是不透過arduino模板去進行連接,直接將距離感測器連接藍芽然後由手機app去命令距離感測器回傳數值是可行的嗎,app inventor可以進行測距感測器的數值演算嗎?(從sensor傳回的數據有很多所以要進行演算排除才能將正確的距離顯示在app上)

    • CAVEDU 阿吉 - 雜工 says:

      您好,藍牙模組無法讀取距離感測器吧。應該不可行,都是需要Arduino的。只要Arduino端能正確讀取,數值傳送對App Inventor來說都是一樣的。本範例其實與之前的讀取Arduino類比腳位範例是一樣的

  9. chifong says:

    我所有的程式都是複製上面範例的APPINVETOR也是用版大給的可是我的手機無法顯示數值,監控台可以看到測出的值,類比輸出也有數值,想請問怎麼解決

  10. tony says:

    你好,我的程式碼與APP都是用上面的範例可是APP卻無法顯示數值,監控端視有數值的,用APP都是用上面的範例可是APP卻無法顯示數值,監控端視有數值的,用前面PART3的範例 是可以動作的 想請問是甚麼問題

  11. jun says:

    不好意思 如果我想要改成用紅外線測距的話要怎麼改呢,還有我想要固定距離的時候手機會出現提示又要怎麼改呢 麻煩了!!!

    • 鈺莨 says:

      你好,jun:
      分成兩個部分,Arduino程式和App Inventor程式:

      Arduino:
      要先抓出紅外線測距的距離,所以你要把本範例Arduino的超音波距離變數distance,換成紅外線測距的距離。

      App Inventor:
      添加訊息判別式
      在when Clock1.Timer元件中最內層if…then,是接收Arduino傳來的超音波距離。那你可以另外在底下在加上if…then的距離判別式,太遠或太近可以跳出對話框之類的功能。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *