使用 HC-06 蓝牙模块将数据从 Android 发送到 Arduino
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23963815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending data from Android to Arduino with HC-06 Bluetooth module
提问by Handoko
I've created an Android app to communicate with my Arduino using Bluetooth. But when I'm sending data from my Android device to my Arduino, the Arduino isn't responding to what I've send. I am able to get a connection from my Android device to my Arduino. So that's not the problem.
我创建了一个 Android 应用程序来使用蓝牙与我的 Arduino 通信。但是当我从我的 Android 设备向我的 Arduino 发送数据时,Arduino 没有响应我发送的内容。我能够从我的 Android 设备连接到我的 Arduino。所以这不是问题。
Here's my full script for Android.
这是我的 Android 完整脚本。
package nl.handoko.LumaMini;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "LumaMini";
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
Button fourty, thirty, twenty, twelve, automatic, manual;
TextView message;
// Well known SPP UUID
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Server's MAC address
private static String address = "98:D3:31:30:09:43";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "In onCreate()");
setContentView(R.layout.activity_mainnn);
fourty = (Button) findViewById(R.id.button1);
thirty = (Button) findViewById(R.id.button4);
twenty = (Button) findViewById(R.id.button2);
twelve = (Button) findViewById(R.id.button5);
automatic = (Button) findViewById(R.id.button3);
manual = (Button) findViewById(R.id.button6);
message = (TextView) findViewById(R.id.textView1);
fourty.setText("40 Leds");
thirty.setText("30 Leds");
twenty.setText("20 Leds");
twelve.setText("12 Leds");
automatic.setText("Automatic");
manual.setText("Manual");
message.setText("Using this app you can take full control of the Luma Mini!" +
"When it's running on automatic please switch back to manual first before switching to other versions.");
btAdapter = BluetoothAdapter.getDefaultAdapter();
checkBTState();
fourty.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("a");
Toast msg = Toast.makeText(getBaseContext(),
"40 Leds version", Toast.LENGTH_SHORT);
msg.show();
}
});
thirty.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("b");
Toast msg = Toast.makeText(getBaseContext(),
"30 Leds version", Toast.LENGTH_SHORT);
msg.show();
}
});
twenty.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("c");
Toast msg = Toast.makeText(getBaseContext(),
"20 Leds version", Toast.LENGTH_SHORT);
msg.show();
}
});
twelve.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("d");
Toast msg = Toast.makeText(getBaseContext(),
"12 Leds version", Toast.LENGTH_SHORT);
msg.show();
}
});
automatic.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("e");
Toast msg = Toast.makeText(getBaseContext(),
"Run automatically", Toast.LENGTH_SHORT);
msg.show();
}
});
manual.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("f");
Toast msg = Toast.makeText(getBaseContext(),
"Manually switch Leds", Toast.LENGTH_SHORT);
msg.show();
}
});
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "...In onResume - Attempting client connect...");
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
Log.d(TAG, "...Connecting to Remote...");
try {
btSocket.connect();
Log.d(TAG, "...Connection established and data link opened...");
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
}
}
// Create a data stream so we can talk to server.
Log.d(TAG, "...Creating Socket...");
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
}
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "...In onPause()...");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
}
}
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
}
}
private void checkBTState() {
// Check for Bluetooth support and then check to make sure it is turned on
// Emulator doesn't support Bluetooth and will return null
if(btAdapter==null) {
errorExit("Fatal Error", "Bluetooth Not supported. Aborting.");
} else {
if (btAdapter.isEnabled()) {
Log.d(TAG, "...Bluetooth is enabled...");
} else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
private void errorExit(String title, String message){
Toast msg = Toast.makeText(getBaseContext(),
title + " - " + message, Toast.LENGTH_SHORT);
msg.show();
finish();
}
private void sendData(String message) {
byte[] msgBuffer = message.getBytes();
Log.d(TAG, "...Sending data: " + message + "...");
try {
outStream.write(msgBuffer);
} catch (IOException e) {
String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
errorExit("Fatal Error", msg);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
And here's my Arduino script:
这是我的 Arduino 脚本:
#include <SoftwareSerial.h>
#include <TimerOne.h>
#define Rx 2
#define Tx 3
#define seconds 4
char serialData; // Serial data memory
int counter1; // Overflow memory
int action; // Action trigger
int once = 0; // Run only once
SoftwareSerial Bluetooth(Rx, Tx);
void setup(){
pinMode(Tx, OUTPUT); // Configure Tx as OUTPUT (Transmitter)
pinMode(Rx, INPUT);
delay(1000);
Bluetooth.begin(9600);
Serial.begin(1200);
delay(1000);
Serial.print("Bluetooth ready");
Bluetooth.flush();
TimerOneSetup(); // Run the setup for Timer One
for(int i = 5; i <= 8; i++){ // Make pins 5, 6, 7 and 8 OUTPUT
pinMode(i, OUTPUT);
}
}
void interrupt1(){ // Timer One loop
counter1++; // Count the amount of seconds has passed
if (counter1 == seconds){ // Trigger the next action after a several amount of seconds (Default: 4 seconds)
action++;
counter1 = 0;
}
if (action > 3){ // Reset action trigger when after all actions were runned
action = 0;
}
}
void loop(){ // Endless loop
if (Serial.available()){ // Wait for data recieved from Local device
serialData = Serial.read(); // Put recieved data in memory
Serial.print("Data recieved from Local device: ");
Serial.println(serialData);
}
if (Bluetooth.available()){ // Wait for data recieved from Bluetooth device
serialData = Bluetooth.read(); // Put recieved data in memory
Serial.print("Data recieved from Bluetooth device: ");
Serial.print(serialData);
}
if (once == 0){ // This script will be run only once
serialData = 'e'; // Put switch on automatic on startup
once++; // Get into the next stage which may be run only once
}
switch(serialData){ // Perform action on state of the switch
case 'a':
fourtyLeds(); // Show the 40 Leds version of the Luma Mini
break;
case 'b':
thirtyLeds(); // Show the 30 Leds version of the Luma Mini
break;
case 'c':
twentyLeds(); // Show the 20 Leds version of the Luma Mini
break;
case 'd':
twelveLeds(); // Show the 12 Leds version of the Luma Mini
break;
case 'e':
while(serialData == 'e'){ // Keep changing different Led versions of the Luma Mini automatically
switch(action){
case 0: // Wait for the action trigger to hit the first action
fourtyLeds(); // Show the 40 Leds version of the Luma Mini
break;
case 1: // Wait for the action trigger to hit the second action
twelveLeds(); // Show the 12 Leds version of the Luma Mini
break;
case 2: // Wait for the action trigger to hit the third action
twentyLeds(); // Show the 20 Leds version of the Luma Mini
break;
case 4: // Wait for the action trigger to hit the fourth action
thirtyLeds(); // Show the 30 Leds version of the Luma Mini
break;}
if (Serial.read() == 'f'){ // Wait for data recieved from Local device
serialData = Serial.read(); // Put recieved data in memory
Serial.print("Data recieved from Local device: ");
Serial.println(serialData);
}
if (Bluetooth.read() == 'f'){ // Wait for data recieved from Bluetooth device
serialData = Bluetooth.read(); // Put recieved data in memory
Serial.print("Data recieved from Bluetooth device: ");
Serial.println(serialData);
}
break;
}
}
}
void BluetoothSetup(){
pinMode(Tx, OUTPUT); // Configure Tx as OUTPUT (Transmitter)
pinMode(Rx, INPUT); // Configure Rx as INPUT (Reciever)
Bluetooth.begin(9600); // Set Bluetooth baud rate to default baud rate 38400
Bluetooth.print("\r\n+STWMOD=0\r\n"); // Set the Bluetooth to work in slave mode
Bluetooth.print("\r\n+STNA=Luma Mini\r\n"); // Set Bluetooth name to Luma Mini
Bluetooth.print("\r\n+STOAUT=1\r\n"); // Permit paired device to connect
Bluetooth.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
delay(2000);
Bluetooth.print("\r\n+INQ=1\r\n"); // Make this Bluetooth Slave inquirable
Serial.println("The slave Bluetooth is inquirable!");
delay(2000);
Bluetooth.flush();
}
void TimerOneSetup(){
Timer1.initialize(1000000); // Initialize Timer One for an overflow exactly every 1 second
Timer1.attachInterrupt(interrupt1); // Open the Timer One loop
}
void fourtyLeds(){ // Show the 40 Leds version of the Luma Mini
for(int i = 5; i <= 8; i++){
digitalWrite(i, LOW);
}
}
void thirtyLeds(){ // Show the 30 Leds version of the Luma Mini
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
}
void twentyLeds(){ // Show the 20 Leds version of the Luma Mini
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, HIGH);
}
void twelveLeds(){ // Show the 12 Leds version of the Luma Mini
for (int i = 5; i <= 8; i++){
digitalWrite(i, HIGH);
}
}
My question: How can I send CHAR data from an Android Device to my Arduino? And what to edit on my script?
我的问题:如何将 CHAR 数据从 Android 设备发送到我的 Arduino?在我的脚本上编辑什么?
采纳答案by SunGa
I have not gone through your code. But looking at the question, I suggests to keep Arduino FW coding away till Android app is tested and developed to a certain level. The way forward could be:
我没有通过你的代码。但是考虑到这个问题,我建议在 Android 应用程序经过测试并开发到一定水平之前,不要再进行 Arduino FW 编码。前进的道路可能是:
- Disconnect HC-06 from other hardware.
- Make a loopback connection at HC-06 (i.e Connect TX & RX outputs of HC-06 together.
- Then Test your Android application. If app is receiving same as transmitted, then your android app is ok, and you can move on perfecting Arduino FW. Else, the android app needs to be perfected.
- 断开 HC-06 与其他硬件的连接。
- 在 HC-06 进行环回连接(即,将 HC-06 的 TX 和 RX 输出连接在一起。
- 然后测试您的 Android 应用程序。如果应用程序接收与传输相同,那么您的 android 应用程序就可以了,您可以继续完善 Arduino FW。否则,Android 应用程序需要完善。
You can have a look at a similar question HC-05 bluetooth module on Arduino + Debugging.
您可以在 Arduino + Debugging 上查看类似的问题HC-05 蓝牙模块。
回答by DreamMaster Pro
Here's the code I use, and it works fine for me.
这是我使用的代码,它对我来说很好用。
On the Android side, I'm only including my bluetooth file, which should be easy to fit into your app. It's main advantage is that after your app start it by calling btConnect(), everything else is automatic. It finds and connects to your "HC-06" without further "human intervention". And if you turn off the "HC-06", Android will continue watching for the "HC-06" to come back online, and will auto-connect to it again.
在 Android 方面,我只包含我的蓝牙文件,它应该很容易适应您的应用程序。它的主要优点是在您的应用程序通过调用 btConnect() 启动它之后,其他一切都是自动的。它无需进一步的“人工干预”即可找到并连接到您的“HC-06”。如果您关闭“HC-06”,Android 将继续等待“HC-06”重新上线,并再次自动连接。
The Arduino Sketch sends a signal once each second. If 10 seconds are missed, the Android assumes the connection has been lost and re-enters connect mode.
Arduino Sketch 每秒发送一次信号。如果错过了 10 秒,Android 会认为连接已丢失并重新进入连接模式。
ANDROID BLUETOOTH JAVA FILE:
安卓蓝牙 Java 文件:
package com.exercise.androidanimbuttons;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.IntentFilter;
import android.widget.Toast;
import android.bluetooth.BluetoothSocket;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import java.util.Set;
import android.os.Handler;
public class BlueTooth extends vars {
private Set<BluetoothDevice> pairedDevices;
String address = null;
private ProgressDialog progress = null;
BluetoothAdapter myBluetooth = null;
BluetoothSocket btSocket = null;
InputStream mmInStream = null;
private Handler myHandler = new Handler();
byte[] buffer = new byte[25];
int readBytes;
files filesI = new files();
Handler btH = new Handler();
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private SingBroadcastReceiver mReceiver;
Runnable btSearch;
void stopDiscovery() {
if (myBluetooth.isDiscovering()){
myBluetooth.cancelDiscovery();
}
}
void findCurrentBT() {
if (!myBluetooth.isEnabled()){
Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBT, 0xDEADBEEF);
}
if (myBluetooth.isDiscovering()){
myBluetooth.cancelDiscovery();
}
closeProgress();
progress = ProgressDialog.show(BlueTooth.this, "Searching for headband...",
"MAKE SURE THE HEADBAND IS TURNED ON.");
progress.setCanceledOnTouchOutside(true);
myBluetooth.startDiscovery();
mReceiver = new SingBroadcastReceiver();
IntentFilter ifilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, ifilter);
checkSearch();
}
private class SingBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String derp = device.getName() + " - " + device.getAddress();
ta(derp);
Toast.makeText(context, derp, Toast.LENGTH_LONG);
if ((device.getName() != null) &&
(device.getName().indexOf("HC-06") == 0) &&
(device.getName().length() == 5))
{
myBluetooth.cancelDiscovery();
address = device.getAddress();
new ConnectBT().execute();
}
}
}
}
private Runnable readBT = new Runnable() {
public void run() {
int i;
int twoByte = 0;
short high = 0, low = 0;
try {
if (mmInStream.available() > 3) {
cnt = 0;
readBytes = mmInStream.read(buffer);
String S = "";
for (i = 0; i < 2; i++)
S += String.format("%03d", buffer[i] & 0xFF)+", ";
high = (short)(buffer[3] & 0xFF);
low = (short)(buffer[2] & 0xFF);
twoByte = ((high << 8) | low);
S += String.format("%03d", twoByte) + "\r\n";
filesI.writeALine("nights","data12.txt",S);
ta(S);
}
} catch (IOException e) {
ta("err:2 " + e.toString());
}
if (btSocket.isConnected())
myHandler.postDelayed(this, 100);
}
};
public void btConnect() {
Disconnect();
findCurrentBT();
}
public void btOn() {
turnOnLed();
}
public void btOff() { turnOffLed(); }
public void btDisconnect() { Disconnect(); }
private void Disconnect()
{
if (btSocket!=null)
{
try
{
btSocket.close();
}
catch (IOException e)
{ msg("Bluetooth Disconnect Error");}
}
}
private void turnOffLed()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("TF".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
private void turnOnLed()
{
int len;
byte[] buffer = new byte[400];
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("TO".toString().getBytes());
len = btSocket.getInputStream().available();
btSocket.getInputStream().read(buffer,0,len);
}
catch (IOException e)
{
msg("Error");
}
}
}
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}
void closeProgress() {
if (progress != null)
progress.dismiss();
}
private class ConnectBT extends AsyncTask<Void, Void, Void>
{
@Override
protected void onPreExecute()
{
closeProgress();
progress = ProgressDialog.show(BlueTooth.this, "Connecting to headband...",
"");
progress.setCanceledOnTouchOutside(true);
}
@Override
protected Void doInBackground(Void... devices)
{
try
{
if (btSocket == null || (!btSocket.isConnected()))
{
BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);
btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
btSocket.connect();
}
}
catch (IOException e) { }
return null;
}
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
if (!btSocket.isConnected())
{
msg("Connection Failed. Is the headband turned on?");
}
else
{
msg("Connected.");
try {
mmInStream = btSocket.getInputStream();
myHandler.postDelayed(readBT, 1000);
} catch (IOException e) {
ta("err:1 " + e.toString());
}
}
closeProgress();
}
}
int cnt = 0;
void checkSearch() {
if (btSearch != null)
return;
btSearch = new Runnable(){@Override public void run(){
if ((btSocket != null) && (btSocket.isConnected())) {
cnt--;
if (cnt < -10) {
cnt = 0;
btConnect();
}
} else if (myBluetooth.isDiscovering()) {
cnt++;
}
btH.postDelayed(this, 1000);
fa(cnt);
}};
btH.postDelayed(btSearch,1000);
}
}
MATCHING ARDUINO SKETCH:
匹配 ARDUINO 草图:
byte mini [4];
int battery;
unsigned long mill = millis();
byte moveCnt = 1;
int minuteCnt = 0;
int lastMove = 0;
int moveA, moveB, moveC, LMoveA, LMoveB, LMoveC, totMove, eyes, LEyes, totEyes;
int moveUpA = 0;
int moveDnA = 1000;
int moveUpB = 0;
int moveDnB = 1000;
int moveUpC = 0;
int moveDnC = 1000;
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 5); // RX, TX
void setup()
{
Serial .begin(9600);
mySerial.begin(9600);
}
void loop()
{
if (millis() > mill)
{
mill += 100;
minuteCnt++;
// *** EYES ***
eyes = analogRead(A6);
totEyes += abs(eyes-LEyes);
LEyes = eyes;
// *** MOVEMENT *** --KEEP-- moveA = max(0,analogRead(A1) >> 2);
moveA = analogRead(A0);
moveB = analogRead(A1);
moveC = analogRead(A2);
totMove += abs(moveA-LMoveA) + abs(moveB-LMoveB) + abs(moveC-LMoveC);
LMoveA = moveA; LMoveB = moveB; LMoveC = moveC;
// *** SEND SECOND ***
if (minuteCnt >= 10)
{
minuteCnt = 0;
// *** BATTERY ***
battery = analogRead(A5); // battery
mini[2] = (battery & 0xff); // battery low byte
mini[3] = ((battery >> 8) & 0xff); // battery high byte
// *** EYES ***
mini[0] = min(max(0,totEyes-10),255);
totEyes = 0;
// *** MOVEMENT ***
mini[1] = min(max(0,totMove-30),255);
totMove = 0;
Serial.print(mini[0]);
Serial.print(" ");
Serial.print(mini[1]);
Serial.print(" ");
Serial.print(mini[2]);
Serial.print(" ");
Serial.println(mini[3]);
mySerial.write(mini,4);
}
}
}