小屋創作

日誌2017-08-05 17:04

arduino 藍芽通信功能實作

作者:貓貓風 ฅ●ω●ฅ

.


















這次要測試的是用 arduino 跟手機做訊息的傳遞,我用的藍芽模組為 HC-06 ;

還有另外一個也常被使用的藍芽模組為HC-05,兩者主要的不同為傳輸的鮑率(baud)不一樣

HC -06 的baud rate預設為9600 , HC-05 預設值為38400 (不確訂有沒有記錯)

兩者功能上的不同如下

HC-05模組可以建立與其他模塊的連接。 例如可以當Master並連接到Slave藍牙模塊。
            或者在Slave模式下使用無線網路接到記事本。

HC-06模組只能作為Slave。 它僅適用於將筆電作為Master連接到具有Slave模組的裝置

藍芽的特性就是可以當Master也可以當Slave,看誰先連上誰

先連上的為Master 被連上的為Slave




Arduino 上的接收程式 , 主要使用pin11當Tx pin12當Rx


  1. #include <SoftwareSerial.h>  
  2. SoftwareSerial BT(11,12);   // 接收腳(RX), 傳送腳(TX);接HC-06之TXD、RXD   
  3.   
  4. char val;  
  5. String recieveData = "";   
  6. bool startRecieve = false;  
  7. void setup()  
  8. {  
  9.   Serial.begin(9600);   
  10.   BT.begin(9600); //HC-06 預設 baud  
  11. }  
  12.   
  13. void loop()  
  14. {  
  15.   while(BT.available()) //如果有收到資料  
  16.   {  
  17.     startRecieve = true;  
  18.     val=BT.read(); //每次接收一個字元  
  19.     recieveData += val; //字元組成字串  
  20.     BT.write(byte(val)); //把每次收到的字元轉成byte封包傳至手機端  
  21.     delay(200);  //每次傳輸間隔,如果太短會造成資料遺失或亂碼  
  22.   }  
  23.     
  24.   if(startRecieve)  
  25.   {  
  26.   startRecieve = false;  
  27.   Serial.println(recieveData); //呈現收到字串  
  28.   recieveData = "";  
  29.   }  
  30.     delay(300);  
  31. }  


Android端藍芽發送與接收程式,很多人應該都會用AppInventor做

不過我覺得那好難用,還是習慣直接自己寫

太久沒寫android有點不知道自己在寫什麼,光假設環境又用了一整天

從以前的 NetBean IDE 到 Eclipse 最後到現在的 android Studio感覺變化好大

設定方便搞了有點久~有空在來發環境建制的文章,從安裝Java與設定環境變數開始講起

然後環境好像越來越重,電腦都快跑不動了..

以下為Source Code


  1. package com.mcuhq.simplebluetooth;  
  2.   
  3. import android.bluetooth.BluetoothAdapter;  
  4. import android.bluetooth.BluetoothDevice;  
  5. import android.bluetooth.BluetoothSocket;  
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.content.IntentFilter;  
  10. import android.content.pm.PackageManager;  
  11. import android.os.Bundle;  
  12. import android.os.Handler;  
  13. import android.os.SystemClock;  
  14. import android.support.v4.app.ActivityCompat;  
  15. import android.support.v4.content.ContextCompat;  
  16. import android.support.v7.app.AppCompatActivity;  
  17. import android.view.View;  
  18. import android.widget.AdapterView;  
  19. import android.widget.ArrayAdapter;  
  20. import android.widget.Button;  
  21. import android.widget.EditText;  
  22. import android.widget.ListView;  
  23. import android.widget.TextView;  
  24. import android.widget.Toast;  
  25.   
  26. import java.io.IOException;  
  27. import java.io.InputStream;  
  28. import java.io.OutputStream;  
  29. import java.io.UnsupportedEncodingException;  
  30. import java.util.Set;  
  31. import java.util.UUID;  
  32.   
  33. public class MainActivity extends AppCompatActivity {  
  34.   
  35.     // GUI Components  
  36.     private TextView mBluetoothStatus;  
  37.     private TextView mReadBuffer;  
  38.     private Button mScanBtn;  
  39.     private Button mOffBtn;  
  40.     private Button mListPairedDevicesBtn;  
  41.     private Button mDiscoverBtn;  
  42.     private BluetoothAdapter mBTAdapter;  
  43.     private Set<BluetoothDevice> mPairedDevices;  
  44.     private ArrayAdapter<String> mBTArrayAdapter;  
  45.     private ListView mDevicesListView;  
  46.     //private CheckBox mLED1;  
  47.     private EditText inputdata;  
  48.     private Button sendDevice;  
  49.   
  50.     private Handler mHandler;
  51.      // Our main handler that will receive callback notifications  
  52.     private ConnectedThread mConnectedThread;
  53.     // bluetooth background worker thread to send and receive data  
  54.     private BluetoothSocket mBTSocket = null;
  55.     // bi-directional client-to-client data path  
  56.   
  57.     private static final UUID BTMODULEUUID = UUID.fromString
  58.     ("00001101-0000-1000-8000-00805F9B34FB"); // "random" unique identifier  
  59.   
  60.     // #defines for identifying shared types between calling functions  
  61.     private final static int REQUEST_ENABLE_BT = 1;
  62.     // used to identify adding bluetooth names  
  63.     private final static int MESSAGE_READ = 2;
  64.     // used in bluetooth handler to identify message update  
  65.     private final static int CONNECTING_STATUS = 3;
  66.      // used in bluetooth handler to identify message status  
  67.     private  String _recieveData = "";  
  68.   
  69.     @Override  
  70.     protected void onCreate(Bundle savedInstanceState) {  
  71.         super.onCreate(savedInstanceState);  
  72.         setContentView(R.layout.activity_main);  
  73.         //初始化元件  
  74.         mBluetoothStatus = (TextView)findViewById(R.id.bluetoothStatus);  
  75.         mReadBuffer = (TextView) findViewById(R.id.readBuffer);  
  76.         mScanBtn = (Button)findViewById(R.id.scan);  
  77.         mOffBtn = (Button)findViewById(R.id.off);  
  78.         mDiscoverBtn = (Button)findViewById(R.id.discover);  
  79.         mListPairedDevicesBtn = (Button)findViewById(R.id.PairedBtn);  
  80.         //mLED1 = (CheckBox)findViewById(R.id.checkboxLED1);  
  81.         inputdata = (EditText)findViewById(R.id.editText);  
  82.         sendDevice = (Button)findViewById(R.id.send);  
  83.   
  84.         mBTArrayAdapter = new ArrayAdapter<String>
  85.         (this,android.R.layout.simple_list_item_1);  
  86.         mBTAdapter = BluetoothAdapter.getDefaultAdapter();
  87.          // get a handle on the bluetooth radio  
  88.   
  89.         mDevicesListView = (ListView)findViewById(R.id.devicesListView);  
  90.         mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view  
  91.         mDevicesListView.setOnItemClickListener(mDeviceClickListener);  
  92.   
  93.         // 詢問藍芽裝置權限  
  94.         if(ContextCompat.checkSelfPermission(this,
  95.             Manifest.permission.ACCESS_COARSE_LOCATION) !=
  96.             PackageManager.PERMISSION_GRANTED)  
  97.             ActivityCompat.requestPermissions(this, new String[]
  98.             {Manifest.permission.ACCESS_COARSE_LOCATION}, 1);  
  99.   
  100.         //定義執行緒 當收到不同的指令做對應的內容  
  101.         mHandler = new Handler(){  
  102.             public void handleMessage(android.os.Message msg){  
  103.                 if(msg.what == MESSAGE_READ){ //收到MESSAGE_READ 開始接收資料  
  104.                     String readMessage = null;  
  105.                     try {  
  106.                         readMessage = new String((byte[]) msg.obj, "UTF-8");  
  107.                         readMessage =  readMessage.substring(0,1);
  108.                        //取得傳過來字串的第一個字元,其餘為雜訊  
  109.                         _recieveData += readMessage; //拼湊每次收到的字元成字串  
  110.                     } catch (UnsupportedEncodingException e) {  
  111.                         e.printStackTrace();  
  112.                     }  
  113.                     mReadBuffer.setText(_recieveData); //將收到的字串呈現在畫面上  
  114.   
  115.                 }  
  116.   
  117.                 if(msg.what == CONNECTING_STATUS){
  118.                  //收到CONNECTING_STATUS 顯示以下訊息  
  119.                     if(msg.arg1 == 1)  
  120.                         mBluetoothStatus.setText("Connected to Device: "
  121.                         + (String)(msg.obj));  
  122.                     else  
  123.                         mBluetoothStatus.setText("Connection Failed");  
  124.                 }  
  125.             }  
  126.         };  
  127.   
  128.         if (mBTArrayAdapter == null) {  
  129.             // Device does not support Bluetooth  
  130.             mBluetoothStatus.setText("Status: Bluetooth not found");  
  131.             Toast.makeText(getApplicationContext(),"Bluetooth device not
  132.              found!",Toast.LENGTH_SHORT).show();  
  133.         }  
  134.         else {  
  135.   
  136.            /* mLED1.setOnClickListener(new View.OnClickListener(){
  137.                 @Override
  138.                 public void onClick(View v){
  139.                     if(mConnectedThread != null) //First check to make sure thread created
  140.                         mConnectedThread.write(inputdata.getText().toString());
  141.                 }
  142.             });*/  
  143.   
  144.             sendDevice.setOnClickListener(new View.OnClickListener(){
  145.             //當按下send開始傳輸資料  
  146.                 @Override  
  147.                 public void onClick(View v){  
  148.                     _recieveData = ""; //清除上次收到的資料  
  149.                     if(mConnectedThread != null) //First check to make sure thread created  
  150.                         mConnectedThread.write(inputdata.getText().toString());
  151.                         //傳送將輸入的資料出去  
  152.                 }  
  153.             });  
  154.   
  155.             //定義每個按鍵按下後要做的事情  
  156.             mScanBtn.setOnClickListener(new View.OnClickListener() {  
  157.                 @Override  
  158.                 public void onClick(View v) {  
  159.                     bluetoothOn(v);  
  160.                 }  
  161.             });  
  162.   
  163.             mOffBtn.setOnClickListener(new View.OnClickListener(){  
  164.                 @Override  
  165.                 public void onClick(View v){  
  166.                     bluetoothOff(v);  
  167.                 }  
  168.             });  
  169.   
  170.             mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {  
  171.                 @Override  
  172.                 public void onClick(View v){  
  173.                     listPairedDevices(v);  
  174.                 }  
  175.             });  
  176.   
  177.             mDiscoverBtn.setOnClickListener(new View.OnClickListener(){  
  178.                 @Override  
  179.                 public void onClick(View v){  
  180.                     discover(v);  
  181.                 }  
  182.             });  
  183.         }  
  184.     }  
  185.   
  186.     private void bluetoothOn(View view){  
  187.         if (!mBTAdapter.isEnabled()) {//如果藍芽沒開啟  
  188.             Intent enableBtIntent = new
  189.              Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//跳出視窗  
  190.             startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
  191.             //開啟設定藍芽畫面  
  192.             mBluetoothStatus.setText("Bluetooth enabled");  
  193.             Toast.makeText(getApplicationContext(),"Bluetooth turned
  194.             on",Toast.LENGTH_SHORT).show();  
  195.         }  
  196.         else{  
  197.             Toast.makeText(getApplicationContext(),"Bluetooth is already on",
  198.             Toast.LENGTH_SHORT).show();  
  199.         }  
  200.     }  
  201.   
  202.     // Enter here after user selects "yes" or "no" to enabling radio  
  203.     //定義當按下跳出是否開啟藍芽視窗後要做的內容  
  204.     @Override  
  205.     protected void onActivityResult(int requestCode, int resultCode, Intent Data){  
  206.         // Check which request we're responding to  
  207.         if (requestCode == REQUEST_ENABLE_BT) {  
  208.             // Make sure the request was successful  
  209.             if (resultCode == RESULT_OK) {  
  210.                 // The user picked a contact.  
  211.                 // The Intent's data Uri identifies which contact was selected.  
  212.                 mBluetoothStatus.setText("Enabled");  
  213.             }  
  214.             else  
  215.                 mBluetoothStatus.setText("Disabled");  
  216.         }  
  217.     }  
  218.   
  219.     private void bluetoothOff(View view){  
  220.         mBTAdapter.disable(); // turn off bluetooth  
  221.         mBluetoothStatus.setText("Bluetooth disabled");  
  222.         Toast.makeText(getApplicationContext(),"Bluetooth turned Off",
  223.         Toast.LENGTH_SHORT).show();  
  224.     }  
  225.   
  226.     private void discover(View view){  
  227.         // Check if the device is already discovering  
  228.         if(mBTAdapter.isDiscovering()){ //如果已經找到裝置  
  229.             mBTAdapter.cancelDiscovery(); //取消尋找  
  230.             Toast.makeText(getApplicationContext(),"Discovery
  231.             stopped",Toast.LENGTH_SHORT).show();  
  232.         }  
  233.         else{  
  234.             if(mBTAdapter.isEnabled()) { //如果沒找到裝置且已按下尋找  
  235.                 mBTArrayAdapter.clear(); // clear items  
  236.                 mBTAdapter.startDiscovery(); //開始尋找  
  237.                 Toast.makeText(getApplicationContext(), "Discovery started",
  238.                 Toast.LENGTH_SHORT).show();  
  239.                 registerReceiver(blReceiver, new
  240.                 IntentFilter(BluetoothDevice.ACTION_FOUND));  
  241.             }  
  242.             else{  
  243.                 Toast.makeText(getApplicationContext(), "Bluetooth not on",
  244.                 Toast.LENGTH_SHORT).show();  
  245.             }  
  246.         }  
  247.     }  
  248.   
  249.     final BroadcastReceiver blReceiver = new BroadcastReceiver() {  
  250.         @Override  
  251.         public void onReceive(Context context, Intent intent) {  
  252.             String action = intent.getAction();  
  253.             if(BluetoothDevice.ACTION_FOUND.equals(action)){  
  254.                 BluetoothDevice device =
  255.                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
  256.                 // add the name to the list  
  257.                 mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());  
  258.                 mBTArrayAdapter.notifyDataSetChanged();  
  259.             }  
  260.         }  
  261.     };  
  262.   
  263.     private void listPairedDevices(View view){  
  264.         mPairedDevices = mBTAdapter.getBondedDevices();  
  265.         if(mBTAdapter.isEnabled()) {  
  266.             // put it's one to the adapter  
  267.             for (BluetoothDevice device : mPairedDevices)  
  268.                 mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());  
  269.   
  270.             Toast.makeText(getApplicationContext(), "Show Paired Devices",
  271.             Toast.LENGTH_SHORT).show();  
  272.         }  
  273.         else  
  274.             Toast.makeText(getApplicationContext(), "Bluetooth not on",
  275.             Toast.LENGTH_SHORT).show();  
  276.     }  
  277.   
  278.     private AdapterView.OnItemClickListener mDeviceClickListener = new
  279.         AdapterView.OnItemClickListener() {  
  280.         public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {  
  281.   
  282.             if(!mBTAdapter.isEnabled()) {  
  283.                 Toast.makeText(getBaseContext(), "Bluetooth not on",
  284.                 Toast.LENGTH_SHORT).show();  
  285.                 return;  
  286.             }  
  287.   
  288.             mBluetoothStatus.setText("Connecting...");  
  289.             // Get the device MAC address, which is the last 17 chars in the View  
  290.             String info = ((TextView) v).getText().toString();  
  291.             final String address = info.substring(info.length() - 17);  
  292.             final String name = info.substring(0,info.length() - 17);  
  293.   
  294.             // Spawn a new thread to avoid blocking the GUI one  
  295.             new Thread()  
  296.             {  
  297.                 public void run() {  
  298.                     boolean fail = false;  
  299.                     //取得裝置MAC找到連接的藍芽裝置  
  300.                     BluetoothDevice device = mBTAdapter.getRemoteDevice(address);  
  301.   
  302.                     try {  
  303.                         mBTSocket = createBluetoothSocket(device);  /
  304.                         //建立藍芽socket  
  305.                     } catch (IOException e) {  
  306.                         fail = true;  
  307.                         Toast.makeText(getBaseContext(), "Socket creation failed",
  308.                         Toast.LENGTH_SHORT).show();  
  309.                     }  
  310.                     // Establish the Bluetooth socket connection.  
  311.                     try {  
  312.                         mBTSocket.connect(); //建立藍芽連線  
  313.                     } catch (IOException e) {  
  314.                         try {  
  315.                             fail = true;  
  316.                             mBTSocket.close(); //關閉socket  
  317.                             //開啟執行緒 顯示訊息  
  318.                             mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)  
  319.                                     .sendToTarget();  
  320.                         } catch (IOException e2) {  
  321.                             //insert code to deal with this  
  322.                             Toast.makeText(getBaseContext(), "Socket creation failed",
  323.                             Toast.LENGTH_SHORT).show();  
  324.                         }  
  325.                     }  
  326.                     if(fail == false) {  
  327.                         //開啟執行緒用於傳輸及接收資料  
  328.                         mConnectedThread = new ConnectedThread(mBTSocket);  
  329.                         mConnectedThread.start();  
  330.                         //開啟新執行緒顯示連接裝置名稱  
  331.                         mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)  
  332.                                 .sendToTarget();  
  333.                     }  
  334.                 }  
  335.             }.start();  
  336.         }  
  337.     };  
  338.   
  339.     private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws
  340.          IOException {  
  341.         return  device.createRfcommSocketToServiceRecord(BTMODULEUUID);  
  342.         //creates secure outgoing connection with BT device using UUID  
  343.     }  
  344.   
  345.     private class ConnectedThread extends Thread {  
  346.         private final BluetoothSocket mmSocket;  
  347.         private final InputStream mmInStream;  
  348.         private final OutputStream mmOutStream;  
  349.   
  350.         public ConnectedThread(BluetoothSocket socket) {  
  351.             mmSocket = socket;  
  352.             InputStream tmpIn = null;  
  353.             OutputStream tmpOut = null;  
  354.   
  355.             // Get the input and output streams, using temp objects because  
  356.             // member streams are final  
  357.             try {  
  358.                 tmpIn = socket.getInputStream();  
  359.                 tmpOut = socket.getOutputStream();  
  360.             } catch (IOException e) { }  
  361.   
  362.             mmInStream = tmpIn;  
  363.             mmOutStream = tmpOut;  
  364.         }  
  365.   
  366.         public void run() {  
  367.             byte[] buffer = new byte[1024];  // buffer store for the stream  
  368.             int bytes; // bytes returned from read()  
  369.             // Keep listening to the InputStream until an exception occurs  
  370.             while (true) {  
  371.                 try {  
  372.                     // Read from the InputStream  
  373.                     bytes = mmInStream.available();  
  374.                     if(bytes != 0) {  
  375.                         SystemClock.sleep(100);
  376.                        //pause and wait for rest of data
  377.                         bytes = mmInStream.available();
  378.                         // how many bytes are ready to be read?  
  379.                         bytes = mmInStream.read(buffer, 0, bytes);
  380.                          // record how many bytes we actually read  
  381.                         mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)  
  382.                                 .sendToTarget(); // Send the obtained bytes to the UI activity  
  383.                     }  
  384.                 } catch (IOException e) {  
  385.                     e.printStackTrace();  
  386.   
  387.                     break;  
  388.                 }  
  389.             }  
  390.         }  
  391.   
  392.         /* Call this from the main activity to send data to the remote device */  
  393.         public void write(String input) {  
  394.             byte[] bytes = input.getBytes();           //converts entered String into bytes  
  395.             try {  
  396.                 mmOutStream.write(bytes);  
  397.             } catch (IOException e) { }  
  398.         }  
  399.   
  400.         /* Call this from the main activity to shutdown the connection */  
  401.         public void cancel() {  
  402.             try {  
  403.                 mmSocket.close();  
  404.             } catch (IOException e) { }  
  405.         }  
  406.     }  
  407. }  


執行結果

我用了兩個藍芽模組在測,在未連線前藍芽模組會一直閃,等待連線

連線後就會停止閃爍









其實一開始以為是藍芽模組有問題,才去弄第二個來測

結果後來發現是程式有問題才修正

最後是開始測試傳輸

Step1 開啟手機端程式 點選 Discover New Device 尋找附近藍芽裝置




Step2 點選藍芽裝置 HC-06   程式狀態切換為 Connecting



Step3 等待連線成功,狀態切換為 Connected to Device



Step4 : 送出文字給 Arduino, Rx的部分為 Arduino收到後回傳的Ack訊息

此部分為採用Echo的方式,收到什麼就原樣反還







最後查看 Arduino端收到的資訊,確實有收到剛剛傳的兩筆資料

分別為 test 與 Data1




相關閱讀

ANDROID NFC 功能實作
這篇為以前寫的,年代好像也有點久遠了,不嫌棄的話也可以去看看^^


32

41

LINE 分享

相關創作

不滅英雄 - 收集傳說英雄放置RPG Android APK iOS | 肯魚

第999位勇士 - 放置RPG公測 Android APK iOS | 肯魚

Magic Hero War - 魔幻放置RPG Android APK iOS | 肯魚

留言

開啟 APP

face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】