ArduinoとAndroidをBluetoothでデータの送受信をする話
AndroidがBluetoothで
Arduinoと出会ったぁ〜。
この前買ったArduinoLeonardo互換機を使います
これです。
Leonardo互換といえども、
ピン配列はUnoに似てるので、
Bluetoothは以前作った
HC-06のシールドを使いまわします。
とりあえずシールドを刺してみました。
意外とイケる。
とりあえずコード書きますか
基本的な構成としては、
AndroidからBTで整数値をArduinoに送り、
Arduinoは受け取った数値をそのまま
Androidに返すだけのアプリ。
LeonardoはUSBのSerialの他に、
別途ソフトSerialが使えるので、
PCとArduinoを接続して
PCのシリアルモニタにLogを出力しつつ、
Bluetoothの方にもSerialで
入出力ができるようになってます。
素晴らしい。
まずはAndroid側
はじめに、お決まりのPermission。
<uses-permission android:name="android.permission.BLUETOOTH"/>
つぎにJava。
Activityに書くと長くなるので、
別クラスで書いてます。
public class BluetoothCommunicator { private static final UUID sUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private boolean mIsRunning; private Activity mActivity; private BluetoothCommunicatorListener mListener; private BluetoothDevice mBluetoothDevice; private BluetoothSocket mBluetoothSocket; private InputStream mInputStream; private OutputStream mOutputStream; public BluetoothCommunicator(Activity activity, BluetoothCommunicatorListener listener) { mIsRunning = true; mActivity = activity; mListener = listener; findDevice(); connectDevice(); } public void writeMessage(final String str) { if (mOutputStream == null | TextUtils.isEmpty(str)) { return; } new Thread(new Runnable() { @Override public void run() { try { mOutputStream.write(str.getBytes()); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public void destory() { mIsRunning = false; mActivity = null; disconnectDevice(); } private void findDevice() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null) { return; } for (BluetoothDevice device : adapter.getBondedDevices()) { if ("HC-06".equals(device.getName())) { mBluetoothDevice = device; return; } } } private void connectDevice() { if (mBluetoothDevice == null) { return; } new Thread(new Runnable() { @Override public void run() { try { BluetoothSocket socket = mBluetoothDevice .createRfcommSocketToServiceRecord(sUUID); socket.connect(); mBluetoothSocket = socket; mInputStream = socket.getInputStream(); mOutputStream = socket.getOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while (mIsRunning) { bytesRead = mInputStream.read(buffer); final String message = new String(buffer, 0, bytesRead); if (TextUtils.isEmpty(message.trim())) { continue; } mActivity.runOnUiThread(new Runnable() { @Override public void run() { mListener.onReceive(message.trim()); } }); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } private void disconnectDevice() { mListener = null; if (mBluetoothDevice == null) { return; } try { if (mBluetoothSocket != null) { mBluetoothSocket.close(); mBluetoothSocket = null; } if (mInputStream != null) { mInputStream.close(); mInputStream = null; } if (mOutputStream != null) { mOutputStream.close(); mOutputStream = null; } } catch (Exception e) { e.printStackTrace(); } } }
予めペアリング済みを想定。
Arduino側と似てるんですが、
Read側は、InputStreamを
Whileループでずっと監視。
ただし、バッファサイズは1024バイトしか
取ってなくて、それ以上のデータが来ることは
想定していません(笑)
そもそも1文字以上を連続して
やり取りするときは、
送受信でデータの終了文字とかを
決めておいたほうがイイかもしれません。
リスナーはこんな感じで、
単純なものです。これをActivity上で
実装して、よしなに表示してあげます。
public interface BluetoothCommunicatorListener { void onReceive(String str); }
クラス名のネーミングセンスは
不問とさせて下さい。
つぎにArduino側
こっちはスッゴイシンプル。
void setup() { // USB Serial Serial.begin(9600); // Bluetooth Serial Serial1.begin(9600); } void loop() { while (Serial1.available() > 0) { int input = Serial1.read(); Serial1.write(input); Serial.println(input); } }
たったこれだけ。
SerialはUSBとの通信。
Serial1はBTとの通信。
Arduino側は本当に簡単。
でも、こちらも複数文字のInputには
対応できてないので、
終端文字などを決めて実装する必要がある。