AL-BalanceBot

Self-Balancing Robot Bluetooth Protocol

This document describes the Bluetooth communication protocol for the self-balancing robot firmware.


Bluetooth Settings

Module: HC-05
Baud rate: 9600
Arduino Serial: Hardware Serial D0 / D1
Data format: ASCII text command

Commands can be ended with:

\n
\r
;

The firmware also accepts commands after a short receive timeout, so most app buttons can send plain text such as:

FORWARD

Recommended delimiter:

FORWARD\n

App → Robot Commands

1. Movement Commands

These commands control only movement. They do not turn balancing on/off.

Forward

FORWARD

Effect:

Robot moves forward.
Robot replies OK.
ST telemetry becomes FORWARD.

Important:

The app should keep sending FORWARD repeatedly while the button is held.
If no movement command is received for 2 seconds, the robot automatically stops movement.
Balancing remains active.

Backward

BACKWARD

Effect:

Robot moves backward.
Robot replies OK.
ST telemetry becomes BACKWARD.

Rotate Left

LEFT

Effect:

Robot rotates left.
Robot replies OK.
ST telemetry becomes LEFT.

Rotate Right

RIGHT

Effect:

Robot rotates right.
Robot replies OK.
ST telemetry becomes RIGHT.

Stop Movement

STOP

Effect:

Robot stops forward/backward/left/right movement.
Robot replies OK.
Balancing remains active if already enabled and upright.
ST telemetry returns to BALANCING.

2. Enable / Disable Commands

Enable Balancing

ENABLE

Effect:

Balancing permission is enabled.
This ENABLE state is saved to EEPROM.
Robot replies OK.

Balancing starts only when:

ENABLE state is active
and robot angle is between -1° and +1° from saved balance point

When balancing becomes active:

DRV8825 ENABLE pin D8 goes LOW
Motors are enabled

Disable Balancing

DISABLE

Effect:

Balancing is disabled.
This DISABLE state is saved to EEPROM.
Robot replies OK.
Movement commands are cleared.
Motors are disabled.

When disabled:

DRV8825 ENABLE pin D8 goes HIGH
ST telemetry becomes DISABLED
OLED eyes show disabled / closed-eye mode

Correct command:

DISABLE

Wrong old spelling is not supported:

DESABLE

3. Calibration Commands

Gyro / Accelerometer Calibration

CAL_GYRO

Use when:

Robot is upright
Robot is completely still
Wheels are not moving

Effect:

Stops movement
Disables motor drivers during calibration
Measures MPU6050 gyro offsets
Measures accelerometer balance reference
Saves calibration data to EEPROM
Robot replies OK

Saved to EEPROM:

gyroX_offset
gyroY_offset
gyroZ_offset
angle_acc_offset
current PID values
current ENABLE/DISABLE state

Balance Point Calibration

CAL_BALANCE

Use when:

Robot is held at the real mechanical balance point

Effect:

Current angle becomes the robot balance center.
manual_balance_offset is updated.
Calibration is saved to EEPROM.
Movement and PID memory are cleared.
Robot replies OK.

Saved to EEPROM:

manual_balance_offset
current PID values
gyro / accelerometer calibration values
current ENABLE/DISABLE state

Calibration Reset

CAL_RESET

Current firmware behavior:

Robot replies OK.
No values are changed.
EEPROM is not cleared.
PID is not reset.
Calibration is not reset.

This command exists only for app compatibility.


4. PID Commands

Request Current PID Values

PIDREQUEST

Robot reply format:

PID,KP=3.5,KI=0.000,KD=4.5

Exact format:

PID,KP=<1 decimal>,KI=<3 decimals>,KD=<1 decimal>

Example replies:

PID,KP=3.5,KI=0.000,KD=4.5
PID,KP=4.2,KI=0.002,KD=5.0
PID,KP=18.0,KI=0.500,KD=1.2

Important:

PIDREQUEST does not reply OK.
It replies only the PID data line.

Update PID Values

PID,KP=3.5,KI=0.000,KD=4.5

Effect:

KP, KI, KD are updated immediately.
PID integral memory is cleared.
New PID values are saved to EEPROM.
Robot replies OK.

Invalid PID command:

PID,KP=3.5,KD=4.5

Reply:

ERR

Because KI= is missing.

Firmware-side PID limits:

No PID min/max limits are applied in firmware.
The app may send any float values.
PID tuning must be done carefully by the user.

Recommended app slider ranges:

KP: 0.0 to 8.0
KI: 0.000 to 0.020
KD: 0.0 to 10.0

Firmware does not block values outside these ranges.


5. Config Command

The app may send:

CFG,MAX_SPEED=50.3,MAX_TILT=12.0

Current firmware behavior:

Robot replies OK.
No configuration values are changed.
Nothing is saved to EEPROM.

This command exists only for app compatibility.

Any command starting with:

CFG,

will reply:

OK

Robot → App Messages

1. Startup Messages

After boot, robot sends:

READY

Then initial telemetry:

A:0.00,B:0.00,LM:0,RM:0,ST:READY

2. Command Replies

Most valid commands reply:

OK

Examples:

FORWARD  -> OK
BACKWARD -> OK
LEFT     -> OK
RIGHT    -> OK
STOP     -> OK
ENABLE   -> OK
DISABLE  -> OK
CAL_GYRO -> OK
CAL_BALANCE -> OK
CAL_RESET -> OK
PID,KP=3.5,KI=0.000,KD=4.5 -> OK
CFG,MAX_SPEED=50.3,MAX_TILT=12.0 -> OK

Invalid command reply:

ERR

Example:

HELLO

Reply:

ERR

If the receive buffer overflows:

RX_OVERFLOW

3. PID Response

When app sends:

PIDREQUEST

Robot replies:

PID,KP=3.5,KI=0.000,KD=4.5

No OK is sent after this.


Telemetry Packet

Robot sends telemetry every:

200 ms

Format:

A:<angle>,B:<battery_voltage>,LM:<left_motor>,RM:<right_motor>,ST:<state>

Example:

A:0.24,B:12.18,LM:15,RM:15,ST:BALANCING

Telemetry Fields

A

A:<angle>

Example:

A:0.24

Meaning:

When balancing is active:

A = balance error angle

So when the robot is stable, A should be close to:

0.00

When balancing is inactive:

A = raw angle relative to saved CAL_BALANCE point

Decimal places:

2 decimals

B

B:<battery_voltage>

Example:

B:12.18

Meaning:

Battery voltage measured from A6 through voltage divider.

Decimal places:

2 decimals

Battery input wiring expected by firmware:

Battery +  -> R1 -> A6 -> R2 -> GND
Battery -  -> Arduino GND

Default resistor values in firmware:

R1 = 100k
R2 = 33k

Never connect battery voltage directly to A6.


LM

LM:<left_motor_output>

Example:

LM:15

Meaning:

Left motor target output value.
This is not RPM.
This is an internal motor command value used by the firmware.

RM

RM:<right_motor_output>

Example:

RM:15

Meaning:

Right motor target output value.
This is not RPM.
This is an internal motor command value used by the firmware.

ST

ST:<state>

Possible values:

DISABLED
READY
FALLEN
FORWARD
BACKWARD
LEFT
RIGHT
BALANCING

State Meaning

DISABLED

Balancing is disabled.
D8 is HIGH.
Motor drivers are disabled.

READY

ENABLE state is active, but robot has not armed balancing yet.
Usually angle is not inside -1° to +1° arming window.

FALLEN

Robot angle is greater than TIP_OVER_ANGLE_LIMIT.
Balancing is deactivated.
D8 is HIGH.

BALANCING

Robot is actively self-balancing.
No movement command is currently active.

FORWARD

Robot is balancing and forward command is active.

BACKWARD

Robot is balancing and backward command is active.

LEFT

Robot is balancing and left rotation command is active.

Robot is balancing and right rotation command is active.

Recommended App Button Behavior

For movement buttons:

When button pressed:
  send FORWARD / BACKWARD / LEFT / RIGHT immediately

While button is held:
  repeat the same command every 100 ms to 300 ms

When button released:
  send STOP

Reason:

Firmware has a 2 second movement timeout.
If movement commands stop arriving, robot stops movement automatically.
Balancing continues.

Recommended repeat interval:

100 ms

Full Command Summary

App → Robot

FORWARD
BACKWARD
LEFT
RIGHT
STOP
ENABLE
DISABLE
CAL_GYRO
CAL_BALANCE
CAL_RESET
PIDREQUEST
PID,KP=<value>,KI=<value>,KD=<value>
CFG,<anything>

Robot → App

READY
OK
ERR
RX_OVERFLOW
PID,KP=<value>,KI=<value>,KD=<value>
A:<angle>,B:<battery>,LM:<left>,RM:<right>,ST:<state>

Example Communication Flow

First-time setup

App -> Robot: CAL_GYRO
Robot -> App: OK

App -> Robot: CAL_BALANCE
Robot -> App: OK

App -> Robot: PID,KP=3.5,KI=0.000,KD=4.5
Robot -> App: OK

App -> Robot: ENABLE
Robot -> App: OK

Request PID

App -> Robot: PIDREQUEST
Robot -> App: PID,KP=3.5,KI=0.000,KD=4.5

Move forward

App -> Robot: FORWARD
Robot -> App: OK

Robot -> App: A:0.12,B:12.18,LM:14,RM:14,ST:FORWARD

App -> Robot: STOP
Robot -> App: OK

Disable robot

App -> Robot: DISABLE
Robot -> App: OK

Robot -> App: A:2.45,B:12.10,LM:0,RM:0,ST:DISABLED