简体   繁体   English

Android与Arduino的蓝牙通信

[英]Android bluetooth communication with Arduino

I am currently looking at Google's Bluetooth Chat example. 我目前正在看Google的蓝牙聊天示例。 The goal is to get communication between android and and Arduino working based on this example. 目标是基于此示例在android和Arduino之间进行通信。

While communication from the smartphone to the Arduino is working great, the other direction does not: When sending bytes from the Arduino to the smartphone, the following code is used for receiving: 虽然从智能手机到Arduino的通信运行良好,但另一个方向却行不通:从Arduino向智能手机发送字节时,以下代码用于接收:

// Read from the InputStream
bytes = mmInStream.read(buffer);

// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();

This has the following problems: 这有以下问题:

  • In my main activity, I get a handed a byte array that's always 1024 bytes long. 在我的主要活动中,我得到了一个始终为1024个字节长的字节数组。 No matter what the incoming byte length was. 不管传入的字节长度是多少。 It would be really nice, if I had an idication how many bytes were received. 如果我能说明收到了多少个字节,那将是非常好的。
  • The bytes seem not to get read all at once. 字节似乎无法一次全部读取。 Eg the code above is called multiple times, but the buffer NEVER contains all the bytes I sent from the Arduino. 例如上面的代码被多次调用,但是缓冲区从不包含我从Arduino发送的所有字节。 SOmetimes there is only the first bytes, then later only the last bytes. 有时只有第一个字节,然后只有最后一个字节。
  • Although this code is calles multiple times, my main activity gets only notified once. 尽管此代码被多次调用,但我的主要活动仅收到一次通知。 How can that be? 怎么可能?

What is the right way to do this. 什么是正确的方法来做到这一点。 Should one implement a mechanism that collects and concatenates the bytes? 是否应该实现一种收集和连接字节的机制? Or am I using this code the wrong way? 还是我以错误的方式使用此代码?

I always had trouble reading a byte buffer greater than one at a time. 我总是很难一次读取大于一个的字节缓冲区。 This is because there is no way to guarantee that you received all the bytes correctly. 这是因为无法保证您正确接收了所有字节。 My work around was to call read repeatedly one byte at a time and fill out my buffer. 我的解决方法是一次调用一次重复读取一个字节并填充我的缓冲区。 That way if any of my bytes aren't read ill catch that in the I/O catch part of my connectedThread and can choose to deal with it however I want. 这样,如果我的任何字节都没有被读取,请在我的connectThread的I / O捕获部分中捕获该异常,并可以选择处理它,但是我想这样做。

Sample connectedThread 样本connectedThread

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; // 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
                       // You can define this buffer to be 1024 or anything you like
                        buffer = new byte[3];
                            mmOutStream.write(253);
                            bytes = mmInStream.read(buffer,0,1);
                            mmOutStream.write(254);
                            bytes = mmInStream.read(buffer,1,1);
                            mmOutStream.write(255);
                            bytes = mmInStream.read(buffer,2,1);
                            mHandler.obtainMessage(MESSAGE_READ, buffer).sendToTarget();
                        }
                        catch (IOException e) {
                            break;
                     }
                }
             }
            /* Call this from the main activity to send data to the remote device */
            public void write(byte[] bytes) {
                try {
                    mmOutStream.write(bytes);
                } catch (IOException e) { }
            }
        }

In this case I used a unsigned byte array to represent integers from 0-255. 在这种情况下,我使用无符号字节数组表示0-255之间的整数。 Furthermore I used values 255-253 as commands to tell my Arduino to send me certain types of information. 此外,我使用值255-253作为命令来告诉Arduino向我发送某些类型的信息。 You do not have to set any value to represent a command to arduino, instead you can just tell the arduino to loop through values it needs to send each time it receives a request for information. 您不必设置任何值来表示arduino的命令,而是只需告诉arduino遍历每次收到信息请求时需要发送的值即可。 I found out this is one of the only ways to can confirm the amounts of bytes you received(ie the size of your byte[] buffer ).Although in this case I did not put anything in my catch statement for the connectedThread you could put a read command in there to confirm you receive a byte. 我发现这是确认收到的字节数(即byte[] buffer的大小)的唯一方法之一。尽管在这种情况下,我没有在catch语句中为您可以放置​​的connectedThread放入任何内容那里的读命令,以确认您收到一个字节。

Message Handler 讯息处理常式

Here is how I dealt with the readBuffer... 这是我处理readBuffer的方式...

/*
     * Bluetooth Handler Method
     */
    ConnectedThread connectedThread;
    Handler mHandler = new Handler(){           
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            switch(msg.what){
                case SUCCESS_CONNECT:
                    // Do Something;
                    Toast.makeText(getActivity(),"CONNECTED",Toast.LENGTH_SHORT).show();

                    connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
                    listView.setVisibility(View.GONE);
                    connectedThread.start();
                    break;

                case MESSAGE_READ:
                    byte[] readBuf = (byte[])msg.obj;
                    int tempInt = byteToInt(readBuf[0]);
                    int speedInt = byteToInt(readBuf[1]);
                    int cadenceInt = byteToInt(readBuf[2]);

                    EditText temperatureData = (EditText)getActivity().findViewById(R.id.temperatureData);
                    temperatureData.setText(Integer.toString(tempInt) + " C" );
                    EditText cadenceData = (EditText)getActivity().findViewById(R.id.cadence);
                    cadenceData.setText(Integer.toString(cadenceInt) + " rpm");
                    EditText speedData = (EditText)getActivity().findViewById(R.id.speed_data);
                    speedData.setText(Integer.toString(speedInt) + " kph");

            }
        }       
    };

In this case I was displaying live sensor data on my phone. 在这种情况下,我正在手机上显示实时传感器数据。 But you can do anything really. 但是你真的可以做任何事情。

Hope that helped. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM