Serial ~500ms delay in remote controlled car project using bluetooth

Hello everyone,

I have an annoying problem with my remote controlled car project. Any signal I send via bluetooth has a delay of about 500ms which can get really annoying when trying to control the car. I made a small android app which acts as the remote control. I tested the app already to check if the error might be there but the bluetooth signal is sent out immediatelly from the phone.

Apart from that everything works perfectly.

I have absolutely no idea why it takes half a second to read the serial data. I've done some projects using the hc-06 on a raspberry pi and the data was received immediately.

Parts used in the project:

  • Arduino Mega
  • 8x 1.5V Batteries
  • 2x geared DC motors
  • 1x L293D
  • 1x HC-06 Bluetooth slave

Thanks to anyone who is taking their time to try and help me. There is a bit of code below...

Picture of the car: (The breadboard is just temporary until I finish it 100%) |500x281

RC_Car.ino

#include "Car.h"

Car* pCar;

void setup()
{
    Serial1.begin(115200);
    pCar = new Car(2, 3, 4, 5);
}

void loop()
{
    pCar->update();
}

Car.h

#ifndef CAR_H
#define CAR_H

#define BT_REGISTER "hi"
#define BT_FORWARD  "fwd"
#define BT_BACKWARD "bwd"
#define BT_LEFT     "lft"
#define BT_RIGHT    "rgt"
#define BT_STOP     "stp"   

#define BT_SPEED    "spd"

#define DISCONNECTED_LED_PIN    22
#define CONNECTED_LED_PIN       24

#include "MotorControl.h"

class Car
{
    private:
        MotorControl _m1;
        MotorControl _m2;
        int _speed;
        bool _connected;

        void update_controls();


    public:
        Car(int m1_pin_fwd, int m1_pin_bwd, int m2_pin_fwd, int m2_pin_bwd);
        void update();

};

#endif

Car.cpp

#include "Car.h"
#include "Arduino.h"

Car::Car(int m1_pin_fwd, int m1_pin_bwd, int m2_pin_fwd, int m2_pin_bwd) 
    : _m1(m1_pin_fwd, m1_pin_bwd), 
      _m2(m2_pin_fwd, m2_pin_bwd)
{
    _connected = false;

    _m1.speed(255);
    _m2.speed(255);

    pinMode(DISCONNECTED_LED_PIN, OUTPUT);
    pinMode(CONNECTED_LED_PIN, OUTPUT);

    digitalWrite(DISCONNECTED_LED_PIN, HIGH);
    digitalWrite(CONNECTED_LED_PIN, LOW);
}


void Car::update()
{
    if (_connected)
    {
        update_controls();
    }
    else
    {
        if (Serial1.available() > 0)
        {
            String data = Serial1.readString();
            if (data == "hi")
            {
                _connected = true;
                digitalWrite(DISCONNECTED_LED_PIN, LOW);
                digitalWrite(CONNECTED_LED_PIN, HIGH);
            }
        }
    }
}

void Car::update_controls()
{
    if (Serial1.available() > 0)
    {
        String data = Serial1.readString();

        /*if (data.startsWith(BT_SPEED))
        {
            // TODO
        }
        else*/ if (data == BT_FORWARD)
        {
            _m1.forward();
            _m2.forward();
        }
        else if (data == BT_BACKWARD)
        {
            _m1.backward();
            _m2.backward();
        }
        else if (data == BT_LEFT)
        {
            _m1.forward();
            _m2.backward();
        }
        else if (data == BT_RIGHT)
        {
            _m1.backward();
            _m2.forward();
        }
        else if (data == BT_STOP)
        {
            _m1.stop();
            _m2.stop();
        }


    }
}

MotorControl.h

#ifndef MOTOR_CONTROL_H
#define MOTOR_CONTROL_H

enum MotorMode
{
    MOTOR_FORWARD,
    MOTOR_BACKWARD,
    MOTOR_STOP
};

class MotorControl
{
    private:
        int _pin_fwd;
        int _pin_bwd;
        int _speed;
        MotorMode _mode;

    public:
        MotorControl(int pin_fwd, int pin_bwd);

        void forward();
        void backward();
        void stop();
        void speed(int speed);

};

#endif

MotorControl.cpp

#include "Arduino.h"
#include "MotorControl.h"

MotorControl::MotorControl(int pin_fwd, int pin_bwd)
{
    _pin_fwd = pin_fwd;
    _pin_bwd = pin_bwd;
    _speed = 0;
    _mode = MOTOR_STOP;

    pinMode(_pin_fwd, OUTPUT);
    pinMode(_pin_bwd, OUTPUT);

    analogWrite(_pin_fwd, 0);
    analogWrite(_pin_bwd, 0);
}


void MotorControl::forward()
{
    _mode = MOTOR_FORWARD;

    analogWrite(_pin_fwd, _speed);
    analogWrite(_pin_bwd, 0);
}


void MotorControl::backward()
{
    _mode = MOTOR_BACKWARD;

    analogWrite(_pin_bwd, _speed);
    analogWrite(_pin_fwd, 0);
}


void MotorControl::stop()
{
    _mode = MOTOR_STOP;

    analogWrite(_pin_fwd, 0);
    analogWrite(_pin_bwd, 0);
}


void MotorControl::speed(int speed)
{
    _speed = speed;

    switch (_mode)
    {
        case MOTOR_FORWARD:
            analogWrite(_pin_fwd, _speed);
            analogWrite(_pin_bwd, 0);
            break;

        case MOTOR_BACKWARD:
            analogWrite(_pin_fwd, 0);
            analogWrite(_pin_bwd, _speed);
            break;
    }
}

Connect bluetooth module to a computer through a serial adapter, set it up (if needed) manually over serial monitor, and see if there's a delay then.

Nathema: Any signal I send via bluetooth has a delay of about 500ms which can get really annoying when trying to control the car.

You are reading your command strings with a default timeout of ONE SECOND:

String data = Serial1.readString();

How did you manage to find such a silly and slow working function, while you want fast communication?

Hint: If your total communication is existing of only a few different commands, you don't need to send 'strings', but a single character would be enough as a single command. So perhaps transmit a single 'char' as a command, and not a "string".

Perhaps:

#define BT_REGISTER 'h'
#define BT_FORWARD 'f'
#define BT_BACKWARD 'b'
#define BT_LEFT 'l'
#define BT_RIGHT 'r'
#define BT_STOP 's'
#define BT_SPEED1 '1'
#define BT_SPEED2 '2'
#define BT_SPEED3 '3'
#define BT_SPEED4 '4'
#define BT_SPEED5 '5'

And then receive and compare single characters:

char data = Serial1.read();

You are reading your command strings with a default timeout of ONE SECOND:

I admire @jurs patience in finding that in your several chunks of code.

The examples in serial input basics are simple reliable non-blocking ways to receive input. One of them should be suitable.

...R

Holy fuck I'm stupid.

Thanks guys, it's working perfectly now.