したいこと
Arduinoのシリアル通信からBluetoothを通じてAndroidアプリで受け取り、Logcatに映し出したいです。受信はできているのですが、Arduino側で送信したものと全く同じものにして(型を整える、必要な情報だけ)受け取ることができません。方法を教えていただけますでしょうか。
構築したいシステムの概要図
環境
- Android Studio Bumblebee | 2021.1.1 Patch 3Build #AI-211.7628.21.2111.8309675, built on March 17, 2022
- API:26 minSdk:23 targetSdk:32 compileSdk:32
- Android端末 モデル名:Nexus7 Androidバージョン:6.0.1
- Arduino IDE (Windows Store 1.8.57.0)
- 使用マイコン基板Arduino Uno
- 使用Bluetooth送信機(RN-42)詳細>https://akizukidenshi.com/catalog/g/gK-07378/
今できてること
この記事を元にArduino側で以下のプログラムを書き込み、Arduinoを接続したPC上のシリアルモニターから所望の文字や数字を送信します。
Arduino
1#include <SoftwareSerial.h> 2 3SoftwareSerial btSerial(2,3); 4char moji;//入力・送信する文字に応じて型を変更 5 6void setup () { 7 btSerial.begin(115200); 8 Serial.begin(115200); 9} 10 11void loop () { 12 if(Serial.available()){ 13 moji = Serial.read(); 14 btSerial.write(moji);//送信部分 15 } 16 delay(20); 17}
その送信したデータを下記のプログラム(MainActivity.kt)で作成した、AndroidアプリをインストールしたAndroid端末で受信、Logcatで確認するという流れです。
kotlin
1package com.mongodb.arduinoble 2 3import android.Manifest 4import android.bluetooth.BluetoothAdapter 5import android.bluetooth.BluetoothDevice 6import android.bluetooth.BluetoothSocket 7import android.content.Intent 8import android.content.pm.PackageManager 9import android.os.Bundle 10import android.util.Log 11import androidx.appcompat.app.AppCompatActivity 12import androidx.core.app.ActivityCompat 13import java.io.IOException 14import java.io.InputStream 15import java.io.OutputStream 16import java.nio.ByteBuffer 17import java.util.* 18 19const val TAG = "MainActivity" 20const val TARGET_DEVICE_NAME = "デバイス名(Android端末とペアリングしたRN-42のデバイス名)" 21const val REQUEST_ENABLE_BLUETOOTH = 1 22// Defines several constants used when transmitting messages between the 23// service and the UI. 24const val MESSAGE_READ: Int = 0 25const val MESSAGE_WRITE: Int = 1 26const val MESSAGE_TOAST: Int = 2 27//SPPを行うための専用UUID? 28val MYUUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") 29 30class MainActivity : AppCompatActivity() { 31 private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() 32 private var connectedThread: ConnectedThread? = null 33 private var connectThread: ConnectThread? = null 34 override fun onCreate(savedInstanceState: Bundle?) { 35 super.onCreate(savedInstanceState) 36 setContentView(R.layout.activity_main) 37 38 if (bluetoothAdapter == null) { 39 Log.d(TAG, "bluetooth is not supported.") 40 return 41 } 42 43 if (!bluetoothAdapter.isEnabled) { 44 val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) 45 startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH) 46 } 47 48 val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter.bondedDevices 49 pairedDevices?.forEach { device -> 50 val deviceName = device.name 51 val deviceHardwareAddress = device.address // MAC address 52 if (device.name == TARGET_DEVICE_NAME) { 53 Log.d(TAG, "name = %s, MAC <%s>".format(deviceName, deviceHardwareAddress)) 54 device.uuids.forEach { uuid -> 55 Log.d(TAG, "uuid is %s".format(uuid.uuid)) 56 } 57 connectThread = ConnectThread(device) 58 connectThread?.start() 59 return 60 } 61 } 62 } 63 64 fun manageMyConnectedSocket(socket: BluetoothSocket) { 65 connectedThread = ConnectedThread(socket) 66 connectedThread?.start() 67 } 68 69 private inner class ConnectThread(device: BluetoothDevice) : Thread() { 70 private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { 71 device.createInsecureRfcommSocketToServiceRecord(MYUUID) 72 } 73 74 public override fun run() { 75 // Cancel discovery because it otherwise slows down the connection. 76 bluetoothAdapter?.cancelDiscovery() 77 if (mmSocket == null) { 78 return 79 } 80 val socket = mmSocket 81 socket ?: return 82 socket.connect() 83 // The connection attempt succeeded. Perform work associated with 84 // the connection in a separate thread. 85 manageMyConnectedSocket(socket) 86 } 87 88 // Closes the client socket and causes the thread to finish. 89 fun cancel() { 90 try { 91 mmSocket?.close() 92 } catch (e: IOException) { 93 Log.e(TAG, "Could not close the client socket", e) 94 } 95 } 96 } 97 98 private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() { 99 100 private val mmInStream: InputStream = mmSocket.inputStream 101 private val mmOutStream: OutputStream = mmSocket.outputStream 102 private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream 103 private var message: Array<String?> = arrayOfNulls(10) 104 105 override fun run() { 106 var numBytes: Int // bytes returned from read() 107 Log.d(TAG, "connect start!") 108 // Keep listening to the InputStream until an exception occurs. 109 while (true) { 110 // Read from the InputStream. 111 numBytes = try { 112 mmInStream.read(mmBuffer) 113 } catch (e: IOException) { 114 Log.d(TAG, "Input stream was disconnected", e) 115 break 116 } 117 //message = arrayOf(ByteBuffer.wrap(mmBuffer).toString()) 118 if (mmBuffer[0].toString()!="10"){ 119 Log.d(TAG, mmBuffer[0].toString()+","+mmBuffer[1].toString()) 120 } 121 else{ 122 123 } 124// // Send the obtained bytes to the UI activity. 125// val readMsg = handler.obtainMessage( 126// MESSAGE_READ, numBytes, -1, 127// mmBuffer) 128// readMsg.sendToTarget() 129 } 130 } 131 132 // Call this method from the main activity to shut down the connection. 133 fun cancel() { 134 try { 135 mmSocket.close() 136 } catch (e: IOException) { 137 Log.e(TAG, "Could not close the connect socket", e) 138 } 139 } 140 } 141}
ManifestファイルでBluetoothに必要なuses-permissionは設定済みです。
実行結果
Android端末が接続されているPCのSerialモニターに、文字を打ち込み送信(Enter)を押すと、
Android studio上のlogcat上には「97」と「10」が表示されます。
この場合、aの情報が97で改行?の情報が10だと思います。この数値を97と10でなくて、しっかりとaと表示させ、不要な情報である10は条件分岐などで消せればよいと考えてます。
やったこと
自分なりに考えてみたのですが下のコードで情報を受け取っていると思いました。このmmBuffer
に最終的に情報が入っていると考察しています。
kotlin
1 numBytes = try { 2 mmInStream.read(mmBuffer) 3 }
このmmBuffer
は ByteArray型(バイト配列?)であると出てきたので、型変換を行うために後ろに変換したい所望の型を付け加えたりしました。
例:整数なら.toInt()
しかし、結果は変わらずでした。
また、この記事を元にByteBuffer.wrap(longBytes).getLong()
なども付け加えたりしたのですが、こちらも結果は変わりませんでした。
応用について
もし、上記の問題が解決できた場合でさらなる応用をしたいと思っています。
Arduino側で,
区切りで複数のデータを送信してそのデータを受信側で区別する方法はありますでしょうか?送信側のArduinoのプログラム↓
Arduino
1 btSerial.write(mojia); 2 btSerial.write(","); 3 btSerial.write(mojib); 4 btSerial.write(","); 5 btSerial.write(mojic); 6 btSerial.write("\n");
以上です。
ここで質問するのは初めてなので、冗長で分かりづらい文章になってしまいましたがご助言やコード例、考え方などを教えていただけますと幸いです。
kotlinも始めて数か月ですので、まだまだ初歩的なこともわかっていません()...
よろしくお願いいたします。
回答2件
あなたの回答
tips
プレビュー