简体   繁体   中英

Arduino/Android Bluetooth delay

We are developping an app that uses Bluetooth library to communicate with an Arduino in bluetooth via an HC-05 module. We made a dummy configuration to test the delay without any computation from eather the Arduino or the app and we have a huge delay of about 1 second between a request and an answer...

Protocol looks easy : Android send byte -2 and if byte received is -2, Arduino send -6, -9 and Android answer again and again.

Android Code :

h = new Handler() {
            public void handleMessage(android.os.Message msg) {
                switch (msg.what) {
                    case RECIEVE_MESSAGE:                                                   // if receive massage
                        byte[] readBuf = (byte[]) msg.obj;

                        for(int i=0;i < readBuf.length;i++)
                        {
                            if((int) readBuf[i] != 0) {
                                txtArduino.append(String.valueOf((int) readBuf[i]) + ", ");
                            }
                        }
                        byte[] msg = {-2};
                        mConnectedThread.writeByte(msg);
                        break;
                }
            };
        };

Arduino Code :

const int receveidBuffLen = 8*4;


void setup() {
  Serial.begin(115200);
}

void loop() {
    if (Serial.available() > 0) 
    {
      byte buff[receveidBuffLen];
      Serial.readBytes(buff, receveidBuffLen);

      for(int i=0; i < receveidBuffLen;i++)
      {
        if(buff[i] == (byte) -2) // 254
        {
            byte message[2] = {(byte) -6, (byte) -9};
            Serial.write(message, 2);
            Serial.flush();
        }
      }
    }
    delay(3);
}

Does anyone know where the delay comes from?

We changed the HC05 baudrate (from 9600 to 115 200) : nothing happened. We changed HC05 with another : nothing happened. We used the Blue2Serial library (Bluetooth as SPP) before and delay was the same... We used another controler (ESP8266) and delay still was 1 second...

Looks like this string is an issue:

Serial.readBytes(buff, receveidBuffLen);

Where receveidBuffLen is 32. Although you get single byte at a time, you're trying to read 32 of them. Of course, if there are no more bytes, the code will be stuck until timeout.

Furthermore, after bytes is read, you never check how many bytes were actually read, but do scan whole the array from bottom to top:

for(int i=0; i < receveidBuffLen;i++)

instead, you have to do something like this:

int bytesAvailable = Serial.available();
if (bytesAvailable > 0)
{
  byte buff[receveidBuffLen];
  int bytesToRead = (bytesAvailable < receveidBuffLen) ? bytesAvailable : receveidBuffLen;
  // Read no more than the buffer size, but not more than available

  int bytesActuallyRead = Serial.readBytes(buff, bytesToRead);

  for(int i=0; i < bytesActuallyRead;i++)
  ...

There are a couple problems with the code that might cause delays:

  1. delay function at end of loop - This will slow down the processing that the Ardunio can keep up with
  2. Calling Serial.flush() - This will block the processing loop() until the internal TX serial buffer is empty. That means the Arduino is blocked and new RX data can pile up, slowing the response time.
  3. Calling Serial.readBytes() - You should focus on the smallest unit of data and process that each loop() iteration. If you are trying to deal with multiple message per loop, that will slow now the loop time causing a delay.

You can try to implement a SerialEvent pattern on the Arduino. We will only read one byte at a time from the serial buffer, keeping the processing that the loop() function has todo to a bare minimum. If we receive the -2 byte we will mark a flag. If the flag is marked the loop() function will call the Serial.write() function but will not block for the data to transmit. Here is a quick example.

bool sendMessage = false;
byte message[2] = {(byte) -6, (byte) -9};

void loop()
{
    if (sendMessage == true)
    {
        Serial.write(message, 2);
        sendMessage = false;
    }
}


/*
  SerialEvent occurs whenever a new data comes in the hardware serial RX. This
  routine is run between each time loop() runs, so using delay inside loop can
  delay response. Multiple bytes of data may be available.
*/
void serialEvent()
{
    while (Serial.available())
    {
        // get the new byte:
        byte inChar = ((byte) Serial.read());

        if (inChar == ((byte) -2))
        {
            sendMessage = true;
        }
    }
}

We just find some solutions by ourselves and want to share them :

Initial situation : 1050 ms for an answer. Alls solutions are independent and done with the initial situation.

  • Remove Serial.flush() : 1022 ms.
  • Add a simple Serial.setTimeout(100) in Arduino Code : 135 ms. (Oh man!)
  • Add a simple timeout to inputStream of 100ms in Android : 95 ms.

Which solution is the best, we can't say but it works now...

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