简体   繁体   中英

Android bluetooth communication with Arduino

I am currently looking at Google's Bluetooth Chat example. The goal is to get communication between android and and Arduino working based on this example.

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:

// 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. 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. 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.

Sample 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. Furthermore I used values 255-253 as commands to tell my Arduino to send me certain types of information. 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. 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.

Message Handler

Here is how I dealt with the 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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