androidbluetoothobd-iielm327

'BluetoothChat'-to-ELM327 split response message


I am attempting to communicate with an ELM327 OBD-II Bluetooth dongle using the Android BluetoothChat example. I can connect to the device without any trouble, and messages from BluetoothChat to the OBD-II device seem to be transmitted and received by the device correctly.

However, the response messages from the OBD-II device are often split into several messages, scrambled, or missing characters.

For example, it takes three tries of the ati command to receive the full expected response:

Me: ati OBDII: a OBDII: 327 OBDII: 327 OBDII: 327 v1.5 > Me: ati OBDII: 1 OBDII: 1 OBDII: 1.5 >v OBDII: 1.5 > Me: ati OBDII: ELM327 v1.5 >

Similarly, sending 010c should trigger a one-line response containing three hexadecimal pairs. Instead, I usually (but not always) get results like the following:

Me: 010c OBDII: OBDII: 4 OBDII: 3C OBDII: 3 OBDII: 3C C OBDII: 3C OBDII: OBDII: OBDII: >

I have tried several different baud rates and different OBD-II protocols, but changes from the default settings only seem to make matters worse. Is there a problem with my response message handling? Why is the response message splitting? The Bluetooth dongle works properly with available apps, such as Torque, so I don't think the device is malfunctioning.

The code that I'm using is almost identical to the BluetoothChat project (source here). I have only modified the UUID for my Bluetooth device and added a carriage return to the outgoing message (as per this Stack Overflow question).

Change 1 (in file BluetoothChatService.java):

// Unique UUID for this application
private static final UUID MY_UUID_SECURE =

//UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
  UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

private static final UUID MY_UUID_INSECURE =

//UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
  UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

Change 2 (in file BluetoothChat.java):

    // The action listener for the EditText widget, to listen for the return key
private TextView.OnEditorActionListener mWriteListener =
    new TextView.OnEditorActionListener() {
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        // If the action is a key-up event on the return key, send the message
        if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
            String message = view.getText().toString();
            //sendMessage(message);
            sendMessage(message + "\r");
        }
        if(D) 
            Log.i(TAG, "END onEditorAction");
        return true;
    }
};

ELM327 manual for reference


Solution

  • I found a solution to my message splitting problem in this BluetoothSPP project by user akexorcist on GitHub. The relevant function from class ConnectedThread is presented below:

    public void run() {
        byte[] buffer;
        ArrayList<Integer> arr_byte = new ArrayList<Integer>();
    
        // Keep listening to the InputStream while connected
        while (true) {
            try {
                int data = mmInStream.read();
    
                if(data == 0x0A) {
    
                } else if(data == 0x0D) {
                    buffer = new byte[arr_byte.size()];
                    for(int i = 0; i < arr_byte.size(); i++) {
                        buffer[i] = arr_byte.get(i).byteValue();
                    }
    
                    // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(BluetoothState.MESSAGE_READ,
                                           buffer.length, -1, buffer).sendToTarget();
                    arr_byte = new ArrayList<Integer>();
                }
                else {
                    arr_byte.add(data);
                }
            } catch (IOException e) {
                connectionLost();
                // Start the service over to restart listening mode
                BluetoothService.this.start(BluetoothService.this.isAndroid);
                break;
            }
        }
    }
    

    Apparently, though please correct me if I'm wrong, .read() cannot grab and maintain the format of whatever bytes appear on the stream without some assistance.