2

Following the google ble app, I created two joysticks on the android app. Then, I am sending the joystick values from android phone to an arduino over ble using 1 write characteristics, the packets size is 4 bytes.

when I lift up my finger from the phone screen. The last packet will contain a stop signal, but on my arduino side, I can not receive the last packet 100% of the time.

I came across this post and found this source to build a queue to ensure data gets through.

After implementing the queue, I am able to use logcat to see that the queue is being used. However, I still couldn't receive the stop signal 100% of the time after implementing the queue.

I think it's because by the time calling on the writeCustomCharacteristic(packets, writecharacteristic_uuid) on the last packet, the write operation is still busy writing, therefore, it doesn't event send my last packet out.

following is my code:

   private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        Log.d("onCharacteristicWrite", "reach onCharacteristicWrite +++++++++++++");
        isWriting = false;
    }

                          .
                          .
                          .


            public void writeCustomCharacteristic(int value, String uuid_char) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.w(TAG, "BluetoothAdapter not initialized");
                return;
            }


        /*check if the service is available on the device*/
            BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT));
            if (mCustomService == null) {
                Log.w(TAG, "Custom BLE Service not found");
                return;
            }

              writeValue(value, uuid_char, mCustomService);

                   /*get the read characteristic from the service*/
    //        BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString(uuid_char));
    //        mWriteCharacteristic.setValue(value, android.bluetooth.BluetoothGattCharacteristic.FORMAT_UINT16, 0);
    //        Log.d("CONNECT", "reached writeCustomCharacteristic");
    //        if (mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false) {
    //            Log.w(TAG, "Failed to write characteristic");
    //        }
        }

        public void writeValue(int dataInt, String uuid_char, BluetoothGattService mCustomService) {

            writeQueue.addFirst(dataInt);
            //Log.d("WriteQueue", "--------------write queue size: " + Integer.toHexString(writeQueue.peekFirst()));
            writeNextValueFromQueue(mCustomService, uuid_char);

        }

        public void writeNextValueFromQueue(BluetoothGattService mCustomService,String uuid_char) {

            if(isWriting) {
    //            if( (writeQueue.peekFirst() & LEFT_MOTOR_STOP_BIT_MASK ) != (1 << JoyStickActivity.LEFT_MOTOR_STOP_SIGNAL_MASK)) {
    //                return;
    //            }
                Log.d("isWritingFromQueue", "reach is writing equal to ture -----------> " + Integer.toHexString(writeQueue.peekFirst()));
                for(int s : writeQueue) {
                    System.out.println(Integer.toHexString(s));
                    Log.d("isWritingFromQueue",  Integer.toHexString(s));
                }
                return;
            }
            if(writeQueue.size() == 0) {
                Log.d("writeNextValueFromQueue", "reach queue size is zero --------------------");
                return;
            }
            isWriting = true;
            value = writeQueue.pollFirst();
            Log.d("writeNextValueFromQueue", "++++++++++++++++value: " + Integer.toHexString(value));

            /*get the read characteristic from the service*/
            BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString(uuid_char));
            mWriteCharacteristic.setValue(value,android.bluetooth.BluetoothGattCharacteristic.FORMAT_UINT32,0);
            Log.d("CONNECT", "reached writeCustomCharacteristic");
            if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false){
                Log.w(TAG, "Failed to write characteristic");
            }
        }
  }

Update: I added a while statement in my writeNextValueFromQueue() function, now it catches that when I receives the packet with the stop signal, I use the while loop to wait until the onCharacteristicWrite() is done, then send my last packet. This way I ensured that I send the last packet every time, however, it delays the time when the motor stops by a few hundred milliseconds.

Is there any way, where I can drop whatever packets that I am sending when I received my stop signal instead of waiting for the packets to be finished sending, then send the packet that includes my stop signal?

public void writeNextValueFromQueue(BluetoothGattService mCustomService,String uuid_char) {

    if(isWriting) {
        if( (writeQueue.peekFirst() & LEFT_MOTOR_STOP_BIT_MASK ) != (1 << JoyStickActivity.LEFT_MOTOR_STOP_SIGNAL_MASK)) {
            return;
        }
        while(isWriting) {

        }
        Log.d("isWritingFromQueue", "reach is writing equal to ture -----------> " + Integer.toHexString(writeQueue.peekFirst()));
        for(int s : writeQueue) {
            System.out.println(Integer.toHexString(s));
            Log.d("isWritingFromQueue",  Integer.toHexString(s));
        }
       // return;
    }
    if(writeQueue.size() == 0) {
        Log.d("writeNextValueFromQueue", "reach queue size is zero --------------------");
        return;
    }
    isWriting = true;
    value = writeQueue.pollFirst();
    Log.d("writeNextValueFromQueue", "++++++++++++++++value: " + Integer.toHexString(value));

    /*get the read characteristic from the service*/
    BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString(uuid_char));
    mWriteCharacteristic.setValue(value,android.bluetooth.BluetoothGattCharacteristic.FORMAT_UINT32,0);
    Log.d("CONNECT", "reached writeCustomCharacteristic");
    if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false){
        Log.w(TAG, "Failed to write characteristic");
    }
}

More Update: Since adding the while statement cause a lag in my app, I am trying to figure out a different solution. Following Emil's suggestion and I started to print out stuff in onCharacteristicWrite() callback. show in the code below:

               public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        final StringBuilder stringBuilder;
       // Log.d("onCharacteristicWrite", "reach onCharacteristicWrite +++++++++++++");
        if(status == BluetoothGatt.GATT_SUCCESS){
            final byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                 stringBuilder = new StringBuilder(data.length);
                for (byte byteChar : data)
                    stringBuilder.append(String.format("%02X ", byteChar));
                Log.d("onCharacteristicSuccess", "Value is " +stringBuilder.toString() );
            }


        }
        isWriting = false;
    }

Following is the log cat that successful sends the stop signal:

    04-22 21:21:36.242 11242-11255/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:36.392 11242-11254/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:36.544 11242-11254/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:36.694 11242-11255/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:36.843 11242-11254/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:36.993 11242-11254/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:37.143 11242-11284/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:37.292 11242-11255/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:37.442 11242-11284/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 80 FF 
04-22 21:21:38.947 11242-11284/com.example.android.toybot D/onCharacteristicSuccess: Value is 00 00 C0 00 

As you can see, the very last packet contain C0, which is a stop signal. However, this signal does not get received most of the time.

BOB
  • 151
  • 3
  • 13
  • 1. The read operations must also go into the queue. 2. Your queue is not thread safe, since it is now being used by different threads. – Emil Apr 12 '18 at 16:09
  • I am not using the read operation @Emil – BOB Apr 12 '18 at 17:54
  • 3. You don't store which characteristic to be written in the queue. 4. You don't continue sending data from the queue when the previous operation completes (onCharacteristicWrite is received). – Emil Apr 12 '18 at 18:22
  • The read operation, are you talking about the read characteristic? Can you elaborate more on your third point? @Emil – BOB Apr 12 '18 at 21:21
  • 1
    You say that you have three write characteristics. So what you should store in your queue is at least items of the pair value, characteristic. If you only store the value, how would you know which characteristic the value should be written to? – Emil Apr 12 '18 at 22:18
  • @emil, I changed my code to use only 1 characteristics and revised my question, but still I am unable to receive the very last packet on my the arduino side. – BOB Apr 21 '18 at 20:02
  • Do you continue to dequeue the queue when you get the onCharacteristicWrite callback? – Emil Apr 21 '18 at 22:20
  • are you asking me, while the write operation is busy, am I still dequeue the queue? I don't think so, since, my isWriting flag is preventing my code from dequeue the queue when the onCharactersticWrite function is called. @Emil – BOB Apr 22 '18 at 06:05
  • I mean when you get the onCharacteristicWrite callback, do you write the next packet in the queue? – Emil Apr 22 '18 at 09:04
  • @Emil, I don't think I write the next packet in the queue when I get the callback, I updated my post again – BOB Apr 23 '18 at 04:26

0 Answers0