51单片机物联网智能小车系列文章目录

第一篇:最简单DIY的51蓝牙遥控小车设计方案
第二篇:最简单DIY串口蓝牙硬件实现方案
第三篇:最简单DIY蓝牙PS2遥控器控制蓝牙智能小车
第四篇:最简单DIY基于51单片机的舵机控制器
第五篇:最简单DIY基于蓝牙、51单片机和舵机的钢铁爱国者机关枪控制器
第六篇:最简单DIY基于Android系统的万能蓝牙设备智能遥控器


文章目录

  • 51单片机物联网智能小车系列文章目录
  • 前言
  • 一、最简单DIY基于Android系统的万能蓝牙设备智能遥控器是什么?
  • 二、软件制作过程
    • 1.设计软件逻辑
    • 2.分析代码
  • 三、仿真与调试
    • 1.操控舵机云台:准备好硬件,上电,运行app。
    • 2. 操控智能小车
  • 总结

前言

    daodanjishui物联网核心原创技术之最简单DIY基于Android系统的万能蓝牙设备智能遥控器。
    市面上有各种开源智能手机舵机控制器app,但是有复杂的有简单的,如果想快速入门安卓app开发蓝牙设备万能遥控器,这个方案会给你一个快捷高效的方案。


一、最简单DIY基于Android系统的万能蓝牙设备智能遥控器是什么?

    在第五篇完成了51单片机多个舵机控制的设计的遥杆,读者好奇当时为什么不写控制多个舵机的PWM波的手机APP呢?那是因为学习是一个循序渐进的过程,掌握基本的技能才能去举一反三。到现在来看是为我第六篇博文是第五篇博文的升级版,可以手机app替代ESP32蓝牙遥杆控制舵机,并且互相不受影响。安卓手机app的java代码相当精妙,纯粹是自己的原创代码,如果不好好专研深入思考,是不可能写出这样的代码的,物联网技术就需要万物互联,那能不能写一个安卓app来替代单片机组成的硬件蓝牙遥控器,就是使用一个app能控制智能小车(第一篇)又能控制钢铁爱国者机关枪(第五篇)?答案是肯定的,这也是鸿蒙系统想要做到的思想。
    虽然市面上也有不少开源的蓝牙调试助手,但是跟硬件结合的代码却很少,特别是能遥控多个蓝牙设备的app更是少见,这个app还能实现在线调试硬件设备,能遥控我设计的智能小车和智能舵机云台,全方位开源原创,现在用文字的形式记录下来,这个代码蓝牙通信代码的改造,除了基本代码之外都是我原创的!这次源码进行了大幅度的升级,代码写得非常精简和奇妙,现在用文字的形式记录下来,对自己童年时代深刻地回忆和对未来技术的展望。“闭门造app”虽然有点痛苦,但是当你看到自己亲手做的app在手机上安装通过自制的遥控器遥控多个设备动起来的时候,你会发现一切的付出都是值得的!全家福如下图所示:


万能遥控器控制智能小车优酷视频地址:https://v.youku.com/v_show/id_XNDk2MDkyMjI0OA==.html?spm=a2hbt.13141534.app.55!25!2555!255!25!25!255!27A

直接看视频

51智能蓝牙小车控制

万能遥控器控制舵机云台优酷视频地址:https://v.youku.com/v_show/id_XNDk2MDkyMDUwOA==.html?firsttime=0

直接看视频

钢铁爱国者机关枪控制

    功能描述:手机app发送指令控制智能小车或者智能云台,硬件将控制信息通过蓝牙返回给手机app显示,单片机解析控制指令,最后控制二自由度舵机转动或者小车运动,可玩性相当高,其实该app除了可以用蓝牙调试助手按键控制之外,也可以手机自带的重力传感器控制云台或者小车。

二、软件制作过程

1.设计软件逻辑

1.1明确小车控制协议:
(1)FFF\r\n是前进
(2)BBB\r\n是后退
(3)LLL\r\n是左转
(4)RRR\r\n是右转
(5)SSS\r\n是停止

1.2明确舵机控制协议:
(1)FFF\r\n是仰头
(2)BBB\r\n是低头
(3)LLL\r\n是左转
(4)RRR\r\n是右转
(5)SSS\r\n是切换机关开关

1.3准备一份蓝牙串口调试助手的app源码
首先强调一下这个app使用eclipse搭建的Android开发环境编写的Android4.3版本的app,如果想要定制高版本的app或者Android studio版本的源码请联系我。
部分源码如下:

package daodanjishui.Bluetooth;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
@SuppressLint("NewApi")
public class BluetoothService {// Debuggingprivate static final String TAG = "BluetoothChatService";private static final boolean D = true;// Name for the SDP record when creating server socketprivate static final String NAME_SECURE = "蓝牙搜索";// Unique UUID for this applicationprivate static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");// Member fieldsprivate final BluetoothAdapter mAdapter;private final Handler mHandler;private AcceptThread mSecureAcceptThread;private AcceptThread mInsecureAcceptThread;private ConnectThread mConnectThread;private ConnectedThread mConnectedThread;private int mState;// Constants that indicate the current connection statepublic static final int STATE_NONE = 0; // we're doing nothingpublic static final int STATE_LISTEN = 1; // now listening for incoming// connectionspublic static final int STATE_CONNECTING = 2; // now initiating an outgoing// connectionpublic static final int STATE_CONNECTED = 3; // now connected to a remote// device/*** Constructor. Prepares a new BluetoothChat session.* * @param context*            The UI Activity Context* @param handler*            A Handler to send messages back to the UI Activity*/@SuppressLint("NewApi")public BluetoothService(Context context, Handler handler) {mAdapter = BluetoothAdapter.getDefaultAdapter();mState = STATE_NONE;mHandler = handler;}/*** Set the current state of the chat connection* * @param state*            An integer defining the current connection state*/private synchronized void setState(int state) {if (D)Log.d(TAG, "setState() " + mState + " -> " + state);mState = state;// Give the new state to the Handler so the UI Activity can updatemHandler.obtainMessage(BTconnect.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();}/*** Return the current connection state.*/public synchronized int getState() {return mState;}/*** Start the chat service. Specifically start AcceptThread to begin a* session in listening (server) mode. Called by the Activity onResume()*/public synchronized void start() {if (D)Log.d(TAG, "start");// Cancel any thread attempting to make a connectionif (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}setState(STATE_LISTEN);// Start the thread to listen on a BluetoothServerSocketif (mSecureAcceptThread == null) {mSecureAcceptThread = new AcceptThread(true);mSecureAcceptThread.start();}if (mInsecureAcceptThread == null) {mInsecureAcceptThread = new AcceptThread(false);mInsecureAcceptThread.start();}}/*** Start the ConnectThread to initiate a connection to a remote device.* * @param device*            The BluetoothDevice to connect* @param secure*            Socket Security type - Secure (true) , Insecure (false)*/public synchronized void connect(BluetoothDevice device, boolean secure) {if (D)Log.d(TAG, "connect to: " + device);// Cancel any thread attempting to make a connectionif (mState == STATE_CONNECTING) {if (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}// Start the thread to connect with the given devicemConnectThread = new ConnectThread(device, secure);//开启一个线程去连接远程蓝牙设备mConnectThread.start();setState(STATE_CONNECTING);}/*** Start the ConnectedThread to begin managing a Bluetooth connection* * @param socket*            The BluetoothSocket on which the connection was made* @param device*            The BluetoothDevice that has been connected*/@SuppressLint({ "NewApi", "NewApi" })public synchronized void connected(BluetoothSocket socket,BluetoothDevice device, final String socketType) {if (D)Log.d(TAG, "connected, Socket Type:" + socketType);// Cancel the thread that completed the connectionif (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}// Cancel the accept thread because we only want to connect to one// deviceif (mSecureAcceptThread != null) {mSecureAcceptThread.cancel();mSecureAcceptThread = null;}if (mInsecureAcceptThread != null) {mInsecureAcceptThread.cancel();mInsecureAcceptThread = null;}// Start the thread to manage the connection and perform transmissionsmConnectedThread = new ConnectedThread(socket, socketType);mConnectedThread.start();// Send the name of the connected device back to the UI ActivityMessage msg = mHandler.obtainMessage(BTconnect.MESSAGE_DEVICE_NAME);//开启连接蓝牙设备的线程之后,还要返回设备的名字给主线程Bundle bundle = new Bundle();bundle.putString(BTconnect.DEVICE_NAME, device.getName());msg.setData(bundle);mHandler.sendMessage(msg);setState(STATE_CONNECTED);}/*** Stop all threads*/public synchronized void stop() {if (D)Log.d(TAG, "stop");if (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}if (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}if (mSecureAcceptThread != null) {mSecureAcceptThread.cancel();mSecureAcceptThread = null;}if (mInsecureAcceptThread != null) {mInsecureAcceptThread.cancel();mInsecureAcceptThread = null;}setState(STATE_NONE);}/*** Write to the ConnectedThread in an unsynchronized manner* * @param out*            The bytes to write* @see ConnectedThread#write(byte[])*/public void write(byte[] out) {// Create temporary objectConnectedThread r;// Synchronize a copy of the ConnectedThreadsynchronized (this) {if (mState != STATE_CONNECTED)return;r = mConnectedThread;}// Perform the write unsynchronizedr.write(out);}/*** Indicate that the connection attempt failed and notify the UI Activity.*/private void connectionFailed() {// Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(BTconnect.MESSAGE_TOAST);Bundle bundle = new Bundle();bundle.putString(BTconnect.TOAST, "Unable to connect device");msg.setData(bundle);mHandler.sendMessage(msg);// Start the service over to restart listening modeBluetoothService.this.start();}/*** Indicate that the connection was lost and notify the UI Activity.*/private void connectionLost() {// Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(BTconnect.MESSAGE_TOAST);Bundle bundle = new Bundle();bundle.putString(BTconnect.TOAST, "Device connection was lost");msg.setData(bundle);mHandler.sendMessage(msg);// Start the service over to restart listening modeBluetoothService.this.start();}/*** This thread runs while listening for incoming connections. It behaves* like a server-side client. It runs until a connection is accepted (or* until cancelled).*/@SuppressLint("NewApi")private class AcceptThread extends Thread {// The local server socketprivate final BluetoothServerSocket mmServerSocket;private String mSocketType;@SuppressLint({ "NewApi", "NewApi" })public AcceptThread(boolean secure) {BluetoothServerSocket tmp = null;// Create a new listening server sockettry {tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,MY_UUID);} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);}mmServerSocket = tmp;}@SuppressLint({ "NewApi", "NewApi", "NewApi", "NewApi", "NewApi" })public void run() {if (D)Log.d(TAG, "Socket Type: " + mSocketType+ "BEGIN mAcceptThread" + this);setName("AcceptThread" + mSocketType);BluetoothSocket socket = null;// Listen to the server socket if we're not connectedwhile (mState != STATE_CONNECTED) {try {// This is a blocking call and will only return on a// successful connection or an exceptionsocket = mmServerSocket.accept();} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType+ "accept() failed", e);break;}// If a connection was acceptedif (socket != null) {synchronized (BluetoothService.this) {switch (mState) {case STATE_LISTEN:case STATE_CONNECTING:// Situation normal. Start the connected thread.connected(socket, socket.getRemoteDevice(),mSocketType);break;case STATE_NONE:case STATE_CONNECTED:// Either not ready or already connected. Terminate// new socket.try {socket.close();} catch (IOException e) {Log.e(TAG, "Could not close unwanted socket", e);}break;}}}}if (D)Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);}public void cancel() {if (D)Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);try {mmServerSocket.close();} catch (IOException e) {Log.e(TAG, "Socket Type" + mSocketType+ "close() of server failed", e);}}}/*** This thread runs while attempting to make an outgoing connection with a* device. It runs straight through; the connection either succeeds or* fails.*/@SuppressLint({ "NewApi", "NewApi" })private class ConnectThread extends Thread {private final BluetoothSocket mmSocket;private final BluetoothDevice mmDevice;private String mSocketType;@SuppressLint({ "NewApi", "NewApi", "NewApi" })public ConnectThread(BluetoothDevice device, boolean secure) {mmDevice = device;BluetoothSocket tmp = null;mSocketType = secure ? "Secure" : "Insecure";// Get a BluetoothSocket for a connection with the// given BluetoothDevicetry {if (secure) {tmp = device.createRfcommSocketToServiceRecord(MY_UUID);} else {tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);}} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);}mmSocket = tmp;}@SuppressLint({ "NewApi", "NewApi", "NewApi" })public void run() {Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);setName("ConnectThread" + mSocketType);// Always cancel discovery because it will slow down a connectionmAdapter.cancelDiscovery();// Make a connection to the BluetoothSockettry {// This is a blocking call and will only return on a// successful connection or an exceptionmmSocket.connect();} catch (IOException e) {// Close the sockettry {mmSocket.close();} catch (IOException e2) {Log.e(TAG, "unable to close() " + mSocketType+ " socket during connection failure", e2);}connectionFailed();return;}// Reset the ConnectThread because we're donesynchronized (BluetoothService.this) {mConnectThread = null;}// Start the connected threadconnected(mmSocket, mmDevice, mSocketType);}public void cancel() {try {mmSocket.close();} catch (IOException e) {Log.e(TAG, "close() of connect " + mSocketType+ " socket failed", e);}}}/*** This thread runs during a connection with a remote device. It handles all* incoming and outgoing transmissions.*/@SuppressLint("NewApi")private class ConnectedThread extends Thread {private final BluetoothSocket mmSocket;private final InputStream mmInStream;@SuppressLint("NewApi")private final OutputStream mmOutStream;private  ByteArrayOutputStream out = new ByteArrayOutputStream();public ConnectedThread(BluetoothSocket socket, String socketType) {//蓝牙连接线程Log.d(TAG, "create ConnectedThread: " + socketType);mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;// Get the BluetoothSocket input and output streamstry {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) {Log.e(TAG, "temp sockets not created", e);}mmInStream = tmpIn;mmOutStream = tmpOut;}public void run() {Log.i(TAG, "BEGIN mConnectedThread");byte[] buffer = new byte[1024];int bytes;/*// Keep listening to the InputStream while connectedwhile (true) {try {// Read from the InputStreambytes = mmInStream.read(buffer);//从输入流读取字节到字节数组buffer,如果读取的数组过长,那么返回的信息就会断断续续// Send the obtained bytes to the UI Activity//mHandler.obtainMessage(BTconnect.MESSAGE_READ, bytes,-1, buffer).sendToTarget();//发消息到主线程                 ByteArrayOutputStream out = new ByteArrayOutputStream();// 根据读取的长度写入到os对象中out.write(buffer, 0, bytes);out.flush();//强制输出到控制台                                                  //返回消息到主线程Message msg=new Message();              msg.what=BTconnect.MESSAGE_READ;String result=new String(out.toByteArray());msg.obj = result;              mHandler.sendMessage(msg);//将消息发回手机主线程查看 out.reset();//清空缓冲区} catch (IOException e) {Log.e(TAG, "disconnected", e);connectionLost();break;}}*/while (true) {try {// Read from the InputStreamif( (bytes = mmInStream.read(buffer)) > 0 ){byte[] buf_data = new byte[bytes];for(int i=0; i<bytes; i++){buf_data[i] = buffer[i];}String s = new String(buf_data);Message msg = new Message();msg.obj = s;//msg.what = 1;msg.what=BTconnect.MESSAGE_READ;//LinkDetectedHandler.sendMessage(msg);mHandler.sendMessage(msg);//将消息发回手机主线程查看}} catch (IOException e) {try {mmInStream.close();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}break;}}}/*** Write to the connected OutStream.* * @param buffer*            The bytes to write*/@SuppressLint("NewApi")public void write(byte[] buffer) {try {mmOutStream.write(buffer);//直接写给蓝牙模块System.out.println("----发送指令到蓝牙模块--------"+new String(buffer));//ByteArrayOutputStream out = new ByteArrayOutputStream();// 根据读取的长度写入到os对象中//out.write(buffer, 0, buffer.length);//out.flush();//强制输出到控制台//返回消息到主线程Message msg=new Message();             msg.what=BTconnect.MESSAGE_WRITE;// String result=new String(out.toByteArray());msg.obj = new String(buffer);//存入消息mHandler.sendMessage(msg);//将消息发回BTconnect主线程查看// out.reset();//清空缓冲区// Share the sent message back to the UI Activity//mHandler.obtainMessage(BTconnect.MESSAGE_WRITE, -1, -1,buffer.toString()).sendToTarget();//在返回写出的信息到主线程。} catch (IOException e) {Log.e(TAG, "Exception during write", e);}}public void cancel() {try {mmSocket.close();} catch (IOException e) {Log.e(TAG, "close() of connect socket failed", e);}}}
}

1.4准备一份重力传感器的app源码
部分代码如下:

package daodanjishui.Bluetooth;import java.util.Enumeration;
import org.join.wfs.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.Camera.Size;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.CompoundButton.OnCheckedChangeListener;/*** This is the main Activity that displays the current chat session.*/
@SuppressLint("HandlerLeak")
public class BTconnect extends Activity {//下面是重力传感器添加//ToggleButton transButton;Button button3,button4,button5,button6,button7,button8;SensorManager sensorManager;// 管理器对象private Sensor gyroSensor;// 陀螺 传感器对象private Sensor acceSensor;// 加速度private Sensor quatSensor;// 旋转矢量private TextView tv_X;private TextView tv_Y;private TextView tv_Z;boolean transFlag = false;//重力传感器开关// Debuggingprivate static final String TAG = "BTconnect";private static final boolean D = true;// Message types sent from the BluetoothChatService Handlerpublic static final int MESSAGE_STATE_CHANGE = 1;public static final int MESSAGE_READ = 2;public static final int MESSAGE_WRITE = 3;public static final int MESSAGE_DEVICE_NAME = 4;public static final int MESSAGE_TOAST = 5;// Key names received from the BluetoothChatService Handlerpublic static final String DEVICE_NAME = "device_name";public static final String TOAST = "toast";// Intent request codesprivate static final int REQUEST_CONNECT_DEVICE_SECURE = 1;private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;private static final int REQUEST_ENABLE_BT = 3;// Layout Viewsprivate TextView mTitle;TextView  textView0,textView1,textView2;// Name of the connected deviceprivate String mConnectedDeviceName = null;// String buffer for outgoing messagesprivate static StringBuffer mOutStringBuffer;// Local Bluetooth adapterprivate BluetoothAdapter mBluetoothAdapter = null;// Member object for the chat servicesprivate static BluetoothService mChatService = null;int cout = 0;private Button button=null;private Button button2=null;private EditText editText=null;private boolean Bluetooth_connect_flag=false;public void projectinit() {sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);acceSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);quatSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);if (gyroSensor == null) {Toast.makeText(BTconnect.this, "您的设备不支持陀螺仪~~~", Toast.LENGTH_SHORT).show();} else {           /*** 注册监听器*/sensorManager.registerListener(sensoreventlistener, gyroSensor,SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(sensoreventlistener, acceSensor,SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(sensoreventlistener, quatSensor,SensorManager.SENSOR_DELAY_GAME);}}    private SensorEventListener sensoreventlistener = new SensorEventListener() {private long acceTime;private float[] acce = { 0, 0, 0, }; byte command;int value = 0x00;private int count1 = 0;@SuppressWarnings("deprecation")@Overridepublic void onSensorChanged(SensorEvent event) {float[] values = event.values;if (event.sensor == acceSensor) {//加速度acce[0] = values[0];acce[1] = values[1];acce[2] = values[2];this.acceTime = event.timestamp;}tv_X.setText("X-acce:" + Float.toString(acce[0]));//手机左右加速度,xtv_Y.setText("Y-acce:" + Float.toString(acce[1]));//手机前后加速度,ytv_Z.setText("Z-acce:" + Float.toString(acce[2]));//手机上下加速度,平放静止手机这个值是9.8,zif (count1 >= 10) {//延时采集数据textView2.setText("重力手势的状态是:"+transFlag);                   if (transFlag){//sendCmd(command, value);//如果手势开关打开了,就发送手势参数给蓝牙模块//sendMessage(value+"");////在这里写逻辑if(acce[0]<-5&&acce[1]<-2&&acce[2]>0){//右转,acce[0]=x,acce[1]=y,acce[2]=zsendMessage("RRR"+"\r\n");}else if(acce[0]>5&&acce[1]<-2&&acce[2]>0){//左转sendMessage("LLL"+"\r\n");}else if(acce[0]<1&&acce[0]>-1&&acce[1]<-3&&acce[2]>0){//前进sendMessage("FFF"+"\r\n");}else if(acce[0]<1&&acce[0]>-1&&acce[1]>3&&acce[2]>0){//后退sendMessage("BBB"+"\r\n");}else if(acce[0]<1&&acce[0]>-1&&acce[1]>-1&&acce[1]<1&&acce[2]>0){//停止sendMessage("SSS"+"\r\n");}elsesendMessage("SSS"+"\r\n");//停止}count1=0;}count1++;}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// TODO Auto-generated method stub}};  @SuppressLint("NewApi")@Overridepublic void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);if (D)Log.e(TAG, "+++ ON CREATE +++");// Set up the window layoutrequestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.bluetooth);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.custom_title);tv_X = (TextView) findViewById(R.id.tvX);tv_Y = (TextView) findViewById(R.id.tvY);tv_Z = (TextView) findViewById(R.id.tvZ);button3 = (Button) findViewById(R.id.button3);button3.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(transFlag==false)transFlag=true;elsetransFlag=false;Toast.makeText(BTconnect.this, "transFlag="+transFlag,Toast.LENGTH_SHORT).show(); //显示消息提示}});button4 = (Button) findViewById(R.id.button4);//前进button4.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){              BTconnect.sendMessage("FFF"+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}               }});button5 = (Button) findViewById(R.id.button5);//向左button5.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){               BTconnect.sendMessage("LLL"+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}}});button6 = (Button) findViewById(R.id.button6);//向右button6.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){              BTconnect.sendMessage("RRR"+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}}});button7 = (Button) findViewById(R.id.button7);//向后button7.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){              BTconnect.sendMessage("BBB"+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}}});button8 = (Button) findViewById(R.id.button8);//停止button8.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){              BTconnect.sendMessage("SSS"+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}}});projectinit(); // 初始化传感器监听getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 保持屏幕常亮textView0= (TextView) findViewById(R.id.textView0); textView1= (TextView) findViewById(R.id.textView1);textView2= (TextView) findViewById(R.id.textView2);textView1.setText("等待机器人的回应");    textView2.setText("手势开关的状态是:"+transFlag); editText=(EditText)findViewById(R.id.editText1);button=(Button)findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if(Bluetooth_connect_flag){Toast.makeText(BTconnect.this, "提交蓝牙指令是:"+editText.getText().toString(),Toast.LENGTH_SHORT).show(); // 显示消息提示//ipname=editText.getText().toString();BTconnect.sendMessage(editText.getText().toString()+"\r\n");//加入\r\n的字符串才能触发stm32串口1中断editText.setText("");}else{Toast.makeText(BTconnect.this, "蓝牙还有没有连接上",Toast.LENGTH_SHORT).show(); // 显示消息提示}}});button2=(Button)findViewById(R.id.button2);button2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Intent serverIntent = null;         // Launch the DeviceListActivity to see devices and do scanserverIntent = new Intent(BTconnect.this, DeviceListActivity.class);startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);//注意有返回值}});// Set up the custom titlemTitle = (TextView) findViewById(R.id.title_left_text);mTitle.setText(R.string.app_name);mTitle = (TextView) findViewById(R.id.title_right_text);  //mTitle.setText(getIpAddress());// Get local Bluetooth adaptermBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// If the adapter is null, then Bluetooth is not supportedif (mBluetoothAdapter == null) {Toast.makeText(this, "Bluetooth is not available",Toast.LENGTH_LONG).show();finish();return;}}@SuppressLint("NewApi")@Overridepublic void onStart() {super.onStart();if (D)Log.e(TAG, "++ ON START ++");// If BT is not on, request that it be enabled.// setupChat() will then be called during onActivityResultif (!mBluetoothAdapter.isEnabled()) {/*Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableIntent, REQUEST_ENABLE_BT);*///历史蓝牙连接上之后自动跳转到 主窗口// Otherwise, setup the chat session} else {if (mChatService == null)setupChat();}}@Overridepublic synchronized void onResume() {super.onResume();if (D)Log.e(TAG, "+ ON RESUME +");// Performing this check in onResume() covers the case in which BT was// not enabled during onStart(), so we were paused to enable it...// onResume() will be called when ACTION_REQUEST_ENABLE activity// returns.if (mChatService != null) {// Only if the state is STATE_NONE, do we know that we haven't// started alreadyif (mChatService.getState() == BluetoothService.STATE_NONE) {// Start the Bluetooth chat servicesmChatService.start();}}}@SuppressLint("NewApi")private void setupChat() {Log.d(TAG, "setupChat()");// Initialize the BluetoothChatService to perform bluetooth connectionsmChatService = new BluetoothService(this, mHandler);// Initialize the buffer for outgoing messagesmOutStringBuffer = new StringBuffer("");     }@Overridepublic synchronized void onPause() {super.onPause();if (D)Log.e(TAG, "- ON PAUSE -");}@Overridepublic void onStop() {super.onStop();if (D)Log.e(TAG, "-- ON STOP --");}@Overridepublic void onDestroy() {super.onDestroy();// Stop the Bluetooth chat servicesif (mChatService != null)mChatService.stop();if (D)Log.e(TAG, "--- ON DESTROY ---");}@SuppressLint("NewApi")private void ensureDiscoverable() {if (D)Log.d(TAG, "ensure discoverable");if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {//打开蓝牙Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);}}public static void sendMessage(String message) {// Check that we're actually connected before trying anythingif (mChatService.getState() != BluetoothService.STATE_CONNECTED) {
//          Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT)
//                  .show();return;}// Check that there's actually something to sendif (message.length() > 0) {// Get the message bytes and tell the BluetoothChatService to writebyte[] send = message.getBytes();mChatService.write(send);// Reset out string buffer to zero and clear the edit text fieldmOutStringBuffer.setLength(0);}}// The Handler that gets information back from the BluetoothChatServiceprivate final Handler mHandler = new Handler() {//接收BluetoothChatService发回来的消息并且解析这些消息,提取数据,如果是获取蓝牙设备返回的消息,需要用这个//但是如果是单纯发送数据到蓝牙设备的话,直接用sendMessage(String message)就可以了@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MESSAGE_STATE_CHANGE:if (D)Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);switch (msg.arg1) {case BluetoothService.STATE_CONNECTED://连接成功了就可以跳转到监控界面了mTitle.setText(R.string.title_connected_to);mTitle.append(mConnectedDeviceName);Bluetooth_connect_flag=true;//startActivity(new Intent (BTconnect.this, CameraTest.class) );//连接成功了就可以跳转到监控界面了break;case BluetoothService.STATE_CONNECTING:mTitle.setText(R.string.title_connecting);break;case BluetoothService.STATE_LISTEN:case BluetoothService.STATE_NONE:mTitle.setText(R.string.title_not_connected);break;}break;case MESSAGE_DEVICE_NAME:// save the connected device's namemConnectedDeviceName = msg.getData().getString(DEVICE_NAME);//BTconnect.DEVICE_NAMEToast.makeText(getApplicationContext(),"Connected to " + mConnectedDeviceName,Toast.LENGTH_SHORT).show();//显示连接到的是哪个蓝牙设备break;case MESSAGE_TOAST:Toast.makeText(getApplicationContext(),msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();break;case  MESSAGE_READ://Toast.makeText(getApplicationContext(),msg.getData().toString(), Toast.LENGTH_SHORT).show();//System.out.println("收到的蓝牙消息是"+msg.getData().toString());Object result1 = msg.obj;System.out.println("收到蓝牙模块的消息是:"+result1); //Toast.makeText(getApplicationContext(),"recive from BT:"+result1, Toast.LENGTH_SHORT).show();textView1.setText("recive from BT:"+result1);  break;case MESSAGE_WRITE:  Object result = msg.obj;//result=msg.getData().getString("result");System.out.println("send to BT:"+result); //Toast.makeText(getApplicationContext(),"send to BT:"+result, Toast.LENGTH_SHORT).show();//Toast.makeText(getApplicationContext(),"send to BT:"+msg.getData().toString(), Toast.LENGTH_SHORT).show();break;}}};public void onActivityResult(int requestCode, int resultCode, Intent data) {//接收DeviceListActivity界面返回的结果if (D)Log.d(TAG, "onActivityResult " + resultCode);switch (requestCode) {//请求码case REQUEST_CONNECT_DEVICE_SECURE://请求连接设备,startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);//注意有返回值// When DeviceListActivity returns with a device to connectif (resultCode == Activity.RESULT_OK) {//请求成功了connectDevice(data, true);}break;case REQUEST_CONNECT_DEVICE_INSECURE:// When DeviceListActivity returns with a device to connectif (resultCode == Activity.RESULT_OK) {connectDevice(data, false);}break;case REQUEST_ENABLE_BT:// When the request to enable Bluetooth returnsif (resultCode == Activity.RESULT_OK) {// Bluetooth is now enabled, so set up a chat sessionsetupChat();} else {// User did not enable Bluetooth or an error occuredLog.d(TAG, "BT not enabled");Toast.makeText(this, R.string.bt_not_enabled_leaving,Toast.LENGTH_SHORT).show();finish();}}}@SuppressLint({ "NewApi", "NewApi" })private void connectDevice(Intent data, boolean secure) {// Get the device MAC addressString address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);//获取意图返回的设备地址// Get the BLuetoothDevice objectBluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);//去连接蓝牙设备// Attempt to connect to the devicemChatService.connect(device, secure);//去连接蓝牙设备}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {MenuInflater inflater = getMenuInflater();inflater.inflate(R.menu.option_menu, menu);              return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {//链接蓝牙的第一步Intent serverIntent = null;switch (item.getItemId()) {case R.id.secure_connect_scan:// Launch the DeviceListActivity to see devices and do scanserverIntent = new Intent(this, DeviceListActivity.class);startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);//注意有返回值return true;}return false;}}

1.5组合代码。缺省代码说明:整个安卓工程一个三个文件,非常简洁,很适合二次开发或者学习,目前给出了两个最重要的文件,还剩下一个蓝牙设备列表的文件,如果耐心够的读者慢慢看两个代码也能收获很多,说不定还能再现我这个app出来,毕竟代码关键的地方都写了注释,这个代码我编写了一周,如果感兴趣的读者想要我全部的源码,麻烦到我指定的地方下载工程吧,尊重原创,尊重劳动成果,我能保证的是我的app绝对是靠谱的,能控制所指定的硬件。

2.分析代码

    首先强调一下这个app使用eclipse搭建的Android开发环境编写的Android4.3版本的app,如果想要定制高版本的app或者Android studio版本的源码请联系我,其实用什么软件开发程序都是次要的,关键是你设计产品的逻辑。记得我的老师说过,其实开发语言只是工具而已,关键还是你自己心中是否有完整的运行逻辑机制。
    其实给出的源码我写上了完整的注释了,就说说读者能学到什么内容吧?这份源码可以学习的地方很多的,比如handler,蓝牙的调用和使用,主界面更新UI,activity参数传递,回调函数的使用,IO流控制,字节传输,重力传感器的调用和使用,私人通信协议的定制和解析判断,蓝牙通信反馈设计等等,如果要实现安卓手机app来控制蓝牙设备,那么我这个源码绝对物超所值!


三、仿真与调试

1.操控舵机云台:准备好硬件,上电,运行app。

1.1刚开始运行app可以看到正下方显示了三个方向的手机重力加速度和重力手势开关状态和蓝牙连接状态

1.2然后启动智能小车或者是钢铁爱国者机关枪,再打开手机蓝牙,再点击“设置蓝牙”,出现

1.3上面的图会看到我历史上连接好的设备,如果记性好是可以直接连上正在通电的HC-05蓝牙设备了,新安装软件如下显示,再也没有历史信息了。

1.4那么我们需要点击“搜索设备”,这个功能还是很人性化的,可以帮助用户搜寻需要连接的蓝牙设备,比如我这里有智能小车和爱国者机关枪,那它们名字是一样的,但是mac地址不一样,也是可以区分开来的。搜索结果如下所示

1.5最后点击搜索出来的蓝牙信息,点击输入密码1234,不行就输入0000,即可连上,出现下图所示,已连接。


1.6连上之后 ,就可以开始控制蓝牙设备了,这个万能遥控器可以使用三种模式控制:第一种是指令发送;第二种是方向按键控制;第三种是重力传感器控制。非常人性化,也方便用户调试,另外蓝牙设备反馈可以在手机app显示出来,这是很多app没有的功能。

剩下的事情就交给视频来说明了。

2. 操控智能小车

这里就交给视频说明吧。类似上面操控智能舵机云台一样的道理。

总结

    说了那么多,无非就是想强调这份源码可以学习的地方很多的,比如handler,蓝牙的调用和使用,主界面更新UI,activity参数传递,回调函数的使用,IO流控制,字节传输,重力传感器的调用和使用,私人通信协议的定制和解析判断,蓝牙通信反馈设计等等,如果要实现安卓手机app来控制蓝牙设备,那么我这个源码绝对物超所值!
    现代生活中蓝牙设备原来越多,所以手机智能蓝牙控制app的开发永不停止,除了蓝牙之外WIFI的应用也很广泛,那么下一期我将推出万能wifi app控制器,并且使用该控制器控制WiFi设备,敬请期待。

代码工程下载链接:https://www.cirmall.com/circuit/21240/
点我直接跳转
花5个积分apk安装包试用链接

最简单DIY基于Android系统的万能蓝牙设备智能遥控器相关推荐

  1. DIY基于android的带GPS的相机遥控器

    相机GPS可以把位置坐标写到照片中,永远记录了你每张照片的拍摄地点,是一种很有价值的摄影附件.尤其对于那些经常旅游的拍摄者来说,更是不可或缺的装备.对于单反相机,很多品牌或型号都必须外接专用的GPS接 ...

  2. 最简单DIY基于C#和51单片机上下位机一体化的PCA9685舵机控制程序

    51单片机物联网智能小车系列文章目录 第一篇:最简单DIY的51蓝牙遥控小车设计方案 第二篇:最简单DIY串口蓝牙硬件实现方案 第三篇:最简单DIY蓝牙PS2遥控器控制蓝牙智能小车 第四篇:最简单DI ...

  3. 最简单DIY基于STM32单片机的蓝牙智能小车设计方案

    STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 文章目录 STM32库函数开发系列文 ...

  4. 最简单DIY基于51单片机、PCA9685、IIC、云台的舵机集群控制程序

    51单片机物联网智能小车系列文章目录 第一篇:最简单DIY的51蓝牙遥控小车设计方案 第二篇:最简单DIY串口蓝牙硬件实现方案 第三篇:最简单DIY蓝牙PS2遥控器控制蓝牙智能小车 第四篇:最简单DI ...

  5. 最简单DIY基于ESP32CAM的物联网相机系统③(在JSP服务器图传相片给所有客户端欣赏)

    最简单DIY基于ESP32CAM的物联网相机系统系列文章目录 第一篇:最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传) 第二篇:最简单DIY基于ESP32CAM的物联网相机系统 ...

  6. 最简单DIY基于ESP32CAM的物联网相机系统⑥(用上位机VS2013 MFC实现WIFI图传)

    第一篇:最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传) 第二篇:最简单DIY基于ESP32CAM的物联网相机系统②(在JAVAWEB服务器实现图片查看器) 第三篇:最简单DI ...

  7. 最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)

    STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 第三篇:最简单DIY基于STM32F ...

  8. 最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)

    STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 第三篇:最简单DIY基于STM32F ...

  9. 最简单DIY基于ESP8266的智能彩灯⑥(Android开发通过WIFI控制彩灯实现表白神器)

    ESP8266和ESP32智能彩灯开发系列文章目录 第一篇:最简单DIY基于ESP8266的智能彩灯①(在网页用按钮点亮普通RGB灯) 第二篇:最简单DIY基于ESP8266的智能彩灯②(在网页用按键 ...

  10. 最简单DIY基于ESP32CAM的物联网相机系统②(在JAVAWEB服务器实现图片查看器)

    最简单DIY基于ESP32CAM的物联网相机系统系列文章目录 第一篇:最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传) 第二篇:最简单DIY基于ESP32CAM的物联网相机系统 ...

最新文章

  1. Action4D:人群和杂物中的在线动作识别:CVPR209论文阅读
  2. python拼音怎么写-python: 拼音处理模块
  3. 用正则表达式验证php用户注册系统,php用户注册时常用的检验函数实例总结
  4. 3.程序的局部性原理
  5. VNC over reverse SSH
  6. Django项目配置mysql主从数据库实现读写分离
  7. React开发(249):react项目理解 ant design input loading
  8. Python爬取“Python小屋”公众号所有文章生成独立Word文档
  9. 微信的服务器是联想的吗,吕再峰:联想希望借微信建设一个新的服务通路
  10. Android studio 常用的插件
  11. OC中iO操作相关方法
  12. 移动领先100笔试面试经验
  13. 华为工作10年,年薪80万。
  14. ORA-02292: integrity constraint
  15. 内热外寒感冒,不能乱吃药
  16. IoT通讯技术选型及模型设计的思考
  17. 面向端到端的情感对话生成研究综述
  18. 基于OSGi的企业级开发框架实践——发布和使用分布式OSGi服务
  19. ibm服务器如何查看内存型号,ibmx3650m4不识别|认不出内存怎么办|内存安装规则要求...
  20. java知识体系综合面试题

热门文章

  1. vue2整合echarts5.0
  2. 第33期、基于java的网上订餐管理系统
  3. 好用的在线开发辅助工具
  4. 自动将视频文件生成字幕的软件autosub的替代工具字幕酱(支持英文、日语和法语、德语、韩语)
  5. 自动将视频文件生成字幕的软件autosub安装及使用(支持英文、日语和法语)
  6. word转网页html,Word转网页html
  7. 3Dmax已渲染的图怎么加载VFB和LUT?
  8. 数学建模之主成分分析
  9. 清明上河图对计算机技术的启发,《清明上河图》鉴定故事的启示
  10. NBU 备份系统详细操作手册之维护与安装