.
這次要測試的是用 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
- #include <SoftwareSerial.h>
- SoftwareSerial BT(11,12); // 接收腳(RX), 傳送腳(TX);接HC-06之TXD、RXD
-
- char val;
- String recieveData = "";
- bool startRecieve = false;
- void setup()
- {
- Serial.begin(9600);
- BT.begin(9600); //HC-06 預設 baud
- }
-
- void loop()
- {
- while(BT.available()) //如果有收到資料
- {
- startRecieve = true;
- val=BT.read(); //每次接收一個字元
- recieveData += val; //字元組成字串
- BT.write(byte(val)); //把每次收到的字元轉成byte封包傳至手機端
- delay(200); //每次傳輸間隔,如果太短會造成資料遺失或亂碼
- }
-
- if(startRecieve)
- {
- startRecieve = false;
- Serial.println(recieveData); //呈現收到字串
- recieveData = "";
- }
- delay(300);
- }
Android端藍芽發送與接收程式,很多人應該都會用AppInventor做
不過我覺得那好難用,還是習慣直接自己寫
太久沒寫android有點不知道自己在寫什麼,光假設環境又用了一整天
從以前的 NetBean IDE 到 Eclipse 最後到現在的 android Studio感覺變化好大
設定方便搞了有點久~有空在來發環境建制的文章,從安裝Java與設定環境變數開始講起
然後環境好像越來越重,電腦都快跑不動了..
以下為Source Code
- package com.mcuhq.simplebluetooth;
-
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.bluetooth.BluetoothSocket;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.pm.PackageManager;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.SystemClock;
- import android.support.v4.app.ActivityCompat;
- import android.support.v4.content.ContextCompat;
- import android.support.v7.app.AppCompatActivity;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.Toast;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.UnsupportedEncodingException;
- import java.util.Set;
- import java.util.UUID;
-
- public class MainActivity extends AppCompatActivity {
-
- // GUI Components
- private TextView mBluetoothStatus;
- private TextView mReadBuffer;
- private Button mScanBtn;
- private Button mOffBtn;
- private Button mListPairedDevicesBtn;
- private Button mDiscoverBtn;
- private BluetoothAdapter mBTAdapter;
- private Set<BluetoothDevice> mPairedDevices;
- private ArrayAdapter<String> mBTArrayAdapter;
- private ListView mDevicesListView;
- //private CheckBox mLED1;
- private EditText inputdata;
- private Button sendDevice;
-
- private Handler mHandler;
- // Our main handler that will receive callback notifications
- private ConnectedThread mConnectedThread;
- // bluetooth background worker thread to send and receive data
- private BluetoothSocket mBTSocket = null;
- // bi-directional client-to-client data path
-
- private static final UUID BTMODULEUUID = UUID.fromString
- ("00001101-0000-1000-8000-00805F9B34FB"); // "random" unique identifier
-
- // #defines for identifying shared types between calling functions
- private final static int REQUEST_ENABLE_BT = 1;
- // used to identify adding bluetooth names
- private final static int MESSAGE_READ = 2;
- // used in bluetooth handler to identify message update
- private final static int CONNECTING_STATUS = 3;
- // used in bluetooth handler to identify message status
- private String _recieveData = "";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //初始化元件
- mBluetoothStatus = (TextView)findViewById(R.id.bluetoothStatus);
- mReadBuffer = (TextView) findViewById(R.id.readBuffer);
- mScanBtn = (Button)findViewById(R.id.scan);
- mOffBtn = (Button)findViewById(R.id.off);
- mDiscoverBtn = (Button)findViewById(R.id.discover);
- mListPairedDevicesBtn = (Button)findViewById(R.id.PairedBtn);
- //mLED1 = (CheckBox)findViewById(R.id.checkboxLED1);
- inputdata = (EditText)findViewById(R.id.editText);
- sendDevice = (Button)findViewById(R.id.send);
-
- mBTArrayAdapter = new ArrayAdapter<String>
- (this,android.R.layout.simple_list_item_1);
- mBTAdapter = BluetoothAdapter.getDefaultAdapter();
- // get a handle on the bluetooth radio
-
- mDevicesListView = (ListView)findViewById(R.id.devicesListView);
- mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
- mDevicesListView.setOnItemClickListener(mDeviceClickListener);
-
- // 詢問藍芽裝置權限
- if(ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_COARSE_LOCATION) !=
- PackageManager.PERMISSION_GRANTED)
- ActivityCompat.requestPermissions(this, new String[]
- {Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
-
- //定義執行緒 當收到不同的指令做對應的內容
- mHandler = new Handler(){
- public void handleMessage(android.os.Message msg){
- if(msg.what == MESSAGE_READ){ //收到MESSAGE_READ 開始接收資料
- String readMessage = null;
- try {
- readMessage = new String((byte[]) msg.obj, "UTF-8");
- readMessage = readMessage.substring(0,1);
- //取得傳過來字串的第一個字元,其餘為雜訊
- _recieveData += readMessage; //拼湊每次收到的字元成字串
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- mReadBuffer.setText(_recieveData); //將收到的字串呈現在畫面上
-
- }
-
- if(msg.what == CONNECTING_STATUS){
- //收到CONNECTING_STATUS 顯示以下訊息
- if(msg.arg1 == 1)
- mBluetoothStatus.setText("Connected to Device: "
- + (String)(msg.obj));
- else
- mBluetoothStatus.setText("Connection Failed");
- }
- }
- };
-
- if (mBTArrayAdapter == null) {
- // Device does not support Bluetooth
- mBluetoothStatus.setText("Status: Bluetooth not found");
- Toast.makeText(getApplicationContext(),"Bluetooth device not
- found!",Toast.LENGTH_SHORT).show();
- }
- else {
-
- /* mLED1.setOnClickListener(new View.OnClickListener(){
- @Override
- public void onClick(View v){
- if(mConnectedThread != null) //First check to make sure thread created
- mConnectedThread.write(inputdata.getText().toString());
- }
- });*/
-
- sendDevice.setOnClickListener(new View.OnClickListener(){
- //當按下send開始傳輸資料
- @Override
- public void onClick(View v){
- _recieveData = ""; //清除上次收到的資料
- if(mConnectedThread != null) //First check to make sure thread created
- mConnectedThread.write(inputdata.getText().toString());
- //傳送將輸入的資料出去
- }
- });
-
- //定義每個按鍵按下後要做的事情
- mScanBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- bluetoothOn(v);
- }
- });
-
- mOffBtn.setOnClickListener(new View.OnClickListener(){
- @Override
- public void onClick(View v){
- bluetoothOff(v);
- }
- });
-
- mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v){
- listPairedDevices(v);
- }
- });
-
- mDiscoverBtn.setOnClickListener(new View.OnClickListener(){
- @Override
- public void onClick(View v){
- discover(v);
- }
- });
- }
- }
-
- private void bluetoothOn(View view){
- if (!mBTAdapter.isEnabled()) {//如果藍芽沒開啟
- Intent enableBtIntent = new
- Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//跳出視窗
- startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
- //開啟設定藍芽畫面
- mBluetoothStatus.setText("Bluetooth enabled");
- Toast.makeText(getApplicationContext(),"Bluetooth turned
- on",Toast.LENGTH_SHORT).show();
- }
- else{
- Toast.makeText(getApplicationContext(),"Bluetooth is already on",
- Toast.LENGTH_SHORT).show();
- }
- }
-
- // Enter here after user selects "yes" or "no" to enabling radio
- //定義當按下跳出是否開啟藍芽視窗後要做的內容
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent Data){
- // Check which request we're responding to
- if (requestCode == REQUEST_ENABLE_BT) {
- // Make sure the request was successful
- if (resultCode == RESULT_OK) {
- // The user picked a contact.
- // The Intent's data Uri identifies which contact was selected.
- mBluetoothStatus.setText("Enabled");
- }
- else
- mBluetoothStatus.setText("Disabled");
- }
- }
-
- private void bluetoothOff(View view){
- mBTAdapter.disable(); // turn off bluetooth
- mBluetoothStatus.setText("Bluetooth disabled");
- Toast.makeText(getApplicationContext(),"Bluetooth turned Off",
- Toast.LENGTH_SHORT).show();
- }
-
- private void discover(View view){
- // Check if the device is already discovering
- if(mBTAdapter.isDiscovering()){ //如果已經找到裝置
- mBTAdapter.cancelDiscovery(); //取消尋找
- Toast.makeText(getApplicationContext(),"Discovery
- stopped",Toast.LENGTH_SHORT).show();
- }
- else{
- if(mBTAdapter.isEnabled()) { //如果沒找到裝置且已按下尋找
- mBTArrayAdapter.clear(); // clear items
- mBTAdapter.startDiscovery(); //開始尋找
- Toast.makeText(getApplicationContext(), "Discovery started",
- Toast.LENGTH_SHORT).show();
- registerReceiver(blReceiver, new
- IntentFilter(BluetoothDevice.ACTION_FOUND));
- }
- else{
- Toast.makeText(getApplicationContext(), "Bluetooth not on",
- Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- final BroadcastReceiver blReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if(BluetoothDevice.ACTION_FOUND.equals(action)){
- BluetoothDevice device =
- intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- // add the name to the list
- mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
- mBTArrayAdapter.notifyDataSetChanged();
- }
- }
- };
-
- private void listPairedDevices(View view){
- mPairedDevices = mBTAdapter.getBondedDevices();
- if(mBTAdapter.isEnabled()) {
- // put it's one to the adapter
- for (BluetoothDevice device : mPairedDevices)
- mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
-
- Toast.makeText(getApplicationContext(), "Show Paired Devices",
- Toast.LENGTH_SHORT).show();
- }
- else
- Toast.makeText(getApplicationContext(), "Bluetooth not on",
- Toast.LENGTH_SHORT).show();
- }
-
- private AdapterView.OnItemClickListener mDeviceClickListener = new
- AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
-
- if(!mBTAdapter.isEnabled()) {
- Toast.makeText(getBaseContext(), "Bluetooth not on",
- Toast.LENGTH_SHORT).show();
- return;
- }
-
- mBluetoothStatus.setText("Connecting...");
- // Get the device MAC address, which is the last 17 chars in the View
- String info = ((TextView) v).getText().toString();
- final String address = info.substring(info.length() - 17);
- final String name = info.substring(0,info.length() - 17);
-
- // Spawn a new thread to avoid blocking the GUI one
- new Thread()
- {
- public void run() {
- boolean fail = false;
- //取得裝置MAC找到連接的藍芽裝置
- BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
-
- try {
- mBTSocket = createBluetoothSocket(device); /
- //建立藍芽socket
- } catch (IOException e) {
- fail = true;
- Toast.makeText(getBaseContext(), "Socket creation failed",
- Toast.LENGTH_SHORT).show();
- }
- // Establish the Bluetooth socket connection.
- try {
- mBTSocket.connect(); //建立藍芽連線
- } catch (IOException e) {
- try {
- fail = true;
- mBTSocket.close(); //關閉socket
- //開啟執行緒 顯示訊息
- mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
- .sendToTarget();
- } catch (IOException e2) {
- //insert code to deal with this
- Toast.makeText(getBaseContext(), "Socket creation failed",
- Toast.LENGTH_SHORT).show();
- }
- }
- if(fail == false) {
- //開啟執行緒用於傳輸及接收資料
- mConnectedThread = new ConnectedThread(mBTSocket);
- mConnectedThread.start();
- //開啟新執行緒顯示連接裝置名稱
- mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
- .sendToTarget();
- }
- }
- }.start();
- }
- };
-
- private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws
- IOException {
- return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
- //creates secure outgoing connection with BT device using UUID
- }
-
- private class ConnectedThread extends Thread {
- private final BluetoothSocket mmSocket;
- private final InputStream mmInStream;
- private final OutputStream mmOutStream;
-
- public ConnectedThread(BluetoothSocket socket) {
- mmSocket = socket;
- InputStream tmpIn = null;
- OutputStream tmpOut = null;
-
- // Get the input and output streams, using temp objects because
- // member streams are final
- try {
- tmpIn = socket.getInputStream();
- tmpOut = socket.getOutputStream();
- } catch (IOException e) { }
-
- mmInStream = tmpIn;
- mmOutStream = tmpOut;
- }
-
- public void run() {
- byte[] buffer = new byte[1024]; // buffer store for the stream
- int bytes; // bytes returned from read()
- // Keep listening to the InputStream until an exception occurs
- while (true) {
- try {
- // Read from the InputStream
- bytes = mmInStream.available();
- if(bytes != 0) {
- SystemClock.sleep(100);
- //pause and wait for rest of data
- bytes = mmInStream.available();
- // how many bytes are ready to be read?
- bytes = mmInStream.read(buffer, 0, bytes);
- // record how many bytes we actually read
- mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
- .sendToTarget(); // Send the obtained bytes to the UI activity
- }
- } catch (IOException e) {
- e.printStackTrace();
-
- break;
- }
- }
- }
-
- /* Call this from the main activity to send data to the remote device */
- public void write(String input) {
- byte[] bytes = input.getBytes(); //converts entered String into bytes
- try {
- mmOutStream.write(bytes);
- } catch (IOException e) { }
- }
-
- /* Call this from the main activity to shutdown the connection */
- public void cancel() {
- try {
- mmSocket.close();
- } catch (IOException e) { }
- }
- }
- }
執行結果
我用了兩個藍芽模組在測,在未連線前藍芽模組會一直閃,等待連線
連線後就會停止閃爍
其實一開始以為是藍芽模組有問題,才去弄第二個來測
結果後來發現是程式有問題才修正
最後是開始測試傳輸
Step1 開啟手機端程式 點選 Discover New Device 尋找附近藍芽裝置
Step2 點選藍芽裝置 HC-06 程式狀態切換為 Connecting
Step3 等待連線成功,狀態切換為 Connected to Device
Step4 : 送出文字給 Arduino, Rx的部分為 Arduino收到後回傳的Ack訊息
此部分為採用Echo的方式,收到什麼就原樣反還
最後查看 Arduino端收到的資訊,確實有收到剛剛傳的兩筆資料
分別為 test 與 Data1
相關閱讀
這篇為以前寫的,年代好像也有點久遠了,不嫌棄的話也可以去看看^^