Bluetooth causes delay

Hi all,

I am trying to controll my motor in my Unity VR Game via a bluetooth module HC-05.
Everything is working fine, however, when my motors HC-05 receive an message from unity, it stops working for about 700 ms.
The important code is:

void loop() {
  motor.loopFOC();
  if (Serial.available() > 0) 
  { 
    String str = Serial.readString();
    String strValue = str.substring(1);
    float floatValue = strValue.toFloat();
    
   if (str.charAt(0)=='L') {
      motor.current_limit = floatValue;
      motor.PID_velocity.limit = floatValue;
   }
   if (str.charAt(0)=='V') {
      target_velocity = floatValue; 
   }
  }
  motor.move(target_velocity);
}

I think the problem is that the serial code inside the loop function causes a delay.
Is there another way to communicate with an bluetooth device? The commander do not cause any delay, can I use the commander with my bluetooth device?

Thank you for your answers!
Best,
Alex

I also am using Bluetooth to control my motor. My Bluetooth library (under STM32CubeIDE) triggers an interrupt whenever data is available. There is no noticeable delay in my loop.

I’m not knowledgeable in serial com or the commander. All I can think of is this: are you sure you don’t send too many messages from unity? Did you set up a throttle mechanism?

Yes I am sure that I do not send too many messages. I tested it with putty and received the same delay. I did not set up a throttle mechanism, all I used is the if (Serial.available() > 0) line. I do not use any Bluetooth library.

I am solving a very similar problem but with esp01 wifi, the answer is yes but you wont like it. Ill post what i did once i get to my office.

Edit: I am controlling multiple motors through a single esp-01 stock firmware (AT commands) wifi module which uses serial. I am streaming the data to a wifi module I designed where I have a read processing loop doing nothing else but the “brain” work of receiving, parsing and interpreting the wifi data stream via Serial. Then I send the motor commands using CANBus to the individual motor boards which they receive and use a hardware SPI chip with an interrupt to include the command inside the motor loop. The SPI chip handles the canbus and everything, and I use a simple SPI library with minimum overhead to get the commands and pass to the motor loop. Using interrupts guarantees no delay.

void loop() {
  motor.loopFOC();
  // here is the SPI / CANBus interrupt-based command 
}

In your case this may be an overkill however it is a generic and reproducible solution guaranteed to work in a high-speed, long cable, noisy environment.

Downside is you have to make your own boards or at least manufacture the SPI/Canbus module and dedicate another board to handle the bluetooth. Asking the motor control board to both run the motor and process communications inside the motor loop may not be very practical.

In another thread I shared the design by the way.

1 Like

What I meant is: do you use a throttle mechanism on the unity side? Maybe the 700ms delay is due to too many messages waiting in Serial.available(). You probably don’t need to send Bluetooth messages more than once every 100ms or so.

@Valentine thank you for that amazing insight, however I hope to find a less complex solution due to time reasons :wink:

@quentin I do not write many messages. I checked it with Debug.Logs and additionally tested it with Putty by sending one message manually. I still have a delay. I already worked with this kind of communication with an other arduino device and there I have no delay. But there I am not controlling a motor.

I solved my problem:
I changed Serial.readString to Serial.readStringUntil('\n'). The problem was, readString tries to read a string until Timeout (1000ms default).

Best,
Alex

Hey @Alexander992,

You can use the serial port in the commander and you will avoid the delays.
Just add your serial object to the commander.

I think the problem is that your function tries to read a string Serial.readString and the string finishes with the \n character which only commes at the end of the command. So the readString will not be able to read the command until all the command characters have arrived.
Your Serial.available()>0 will be true for any number of characters received, it will not be true only when your full command is received.

You can see how we used to solve these issues with the earlier releases of the library <2.0 when there was no commander:
For example:

The function serialReceiveUserCommand is non blocking and will build up your command string iteratively. :smiley:

1 Like