Smart Variable Watcher icon Smart Variable Watcher — Efficient ARC Variable Watcher - lower CPU for large projects; slow initial array render but faster updates; shows name, type, value, length Try it →
 
Two Wheel Self Balancing Robot Robot Skill

Two Wheel Self Balancing Robot

by Synthiam Inc

Segway-style self-balancing robot control with live tuning, auto-tune, EEPROM saving, and ARCx drive/status support for Arduino or ESP32.

Requires ARCx v2 (Updated 10/29/2026)
Tags: Movement Panels
Compatible with: Compatible with Microsoft Windows 10 or 11 Windows Compatible with ARM Linux (Raspberry pi, etc) ARM Compatible with Linux Linux Compatible with MacOS MacOS

How to add the Two Wheel Self Balancing Robot robot skill

  1. Load the most recent release of ARCx on a compatible operating system (Get ARCx).
  2. Press the + Skills menu from the top menu bar in ARCx.
  3. Choose the Movement Panels category tab.
  4. Press the Two Wheel Self Balancing Robot icon to add the robot skill to your project.

Don't have a robot yet?

Follow the Getting Started Guide to build a robot and use the Two Wheel Self Balancing Robot robot skill.


How to use the Two Wheel Self Balancing Robot robot skill

The Two Wheel Self Balancing Robot is the Movement Panel for a two wheeled, Segway style robot: two driven wheels on one axle, and a body that stays upright only because the wheels keep driving under it. An Arduino Uno, Nano, Mega or an ESP32 on the robot runs the firmware that comes with this robot skill, reads an MPU6050 and balances the robot 200 times a second. ARCx drives it, shows what it is doing, tunes it live over the serial link, auto-tunes it, and saves the tuning into the robot so it balances the same way without ARCx.

Nothing about the tuning is compiled into the firmware. Every PID gain, the balance point, the speed limits, the motor and encoder directions and the IMU orientation are parameters this robot skill sends to the robot. You edit the firmware once, for the wiring, and never again to tune it.

The robot

Part Notes
Controller Arduino Uno, Nano or Mega, or an ESP32 DevKit.
IMU MPU6050 (GY-521), or an MPU6500 / MPU9250 at address 0x68, mounted firmly. Any orientation: the robot skill detects it.
Motor driver TB6612FNG, L298N, DRV8833, L9110S, BTS7960, or a DIR + PWM driver such as a Cytron.
Motors Two DC gear motors, ideally with quadrature encoders. With encoders the robot holds its position and drives at a real speed in m/s; without them it still balances and drives, but drifts.
Link to ARCx USB cable, Bluetooth serial (HC-05, HC-06), Wi-Fi (the ESP32 firmware runs its own TCP server, as an access point or on your network), a serial bridge such as ser2net or ESP-Link, or an EZB hardware UART.

The robot balances on its own. If the link drops, it keeps standing where it is: it stops driving when the drive commands stop arriving, and goes on balancing.

The firmware

The Firmware tab

The configuration's Firmware tab downloads the sketch and a README. Open the sketch in the Arduino IDE, set the motor driver type and the pins in section 1, and upload. It needs no extra libraries. The README has the default wiring for an Uno, Nano, Mega and ESP32, how the balancing works, the serial protocol, every parameter, and how to adapt the firmware: another motor driver, stepper motors, another IMU, or commands of your own. The sketch is written to be read, in numbered sections that each explain what they do.

The window

The  <a href='/Support/Skills/Skills-Overview' target='_top'>robot skill</a> window, balancing after a drive forward and a stop

The window shows the robot from the side at its current lean, with the lean the robot is aiming for as a dashed line, and its lean, target lean, speed, distance driven, motor power and battery. The chart below draws the lean and target lean over the last 15 seconds: a well tuned robot draws a nearly flat line.

Balance turns balancing on: the robot balances as soon as it is stood upright and held still for a moment. Motors off turns the motors off; a standing robot falls, so hold it first. Stop stops driving at once and leaves the robot balancing. Connect and Disconnect open and close the link; disconnect before uploading new firmware so the Arduino IDE can use the port.

The direction buttons and the speed slider drive the robot. They go through ARCx's movement manager, so joysticks, scripts, the Custom UI and every other robot skill that moves a robot drive it the same way. Forward and reverse with different left and right speeds curve, the way a joystick asks for it.

Configuration

Connection

The Connection tab

Choose the port: a COM port (USB or Bluetooth), TCP (the ESP32's address, 192.168.4.1 when it is its own access point, port 23), or an EZB UART. Leave DTR off for an Uno, Nano or Mega: raising DTR resets them, and a balancing robot then falls every time ARCx connects.

On connecting, the robot skill either sends this project's parameters to the robot (the default) or reads the robot's own, saved in its EEPROM, into the project. Balance on connect turns balancing on as soon as ARCx connects.

The robot's state is published as global variables for scripts: BalanceLean, BalanceSpeed, BalanceDistance, BalanceBattery, BalanceIsBalancing, BalanceState and BalanceConnected, with a prefix you can change.

Robot

The Robot tab

Check the hardware here before tuning, in order. A robot with its IMU, a motor or an encoder backwards cannot balance whatever its gains, and falls the same way every time.

  1. IMU orientation. Hold the robot upright and still and press Upright, then tilt it about 20 degrees forward and press Tilted forward. The up and left axes are found and sent to the robot. Tilting the robot forward must then make the lean positive.
  2. Motors and encoders. Lift the robot so its wheels are off the ground and test each wheel. It spins for a second; say which way it turned, and the motor and encoder directions are fixed from your answer and what the encoder counted. Then set the encoder counts per wheel turn (turn the left wheel five times by hand between Start counting and Done) and the wheel diameter.
  3. Gyro and balance point. The gyro's zero is measured at power up while the robot lies still; measure it again here if the lean drifts. Level here makes the current lean the balance point; the auto-tuner measures it for you.
  4. Safety, motors and battery. The fall angle (past it the motors stop), the restart angle (stood back up within it, the robot balances again), balancing at power up without ARCx, the motor deadband and maximum power, and the battery voltage divider.

Balance

The Balance tab

The gains, with the robot's lean and target lean live above them. Changes go to the robot as you type, so you can watch what each one does; Cancel puts the saved values back.

Setting What it does
Angle KP Motor power per degree of lean. Too low and the robot falls; too high and it shakes.
Angle KI Supplies the power the motors need to keep up as they turn faster, so the robot does not run away when it drives. About 4 x Angle KP.
Angle KD Damps the wobble. Too high and the motors buzz.
Balance point The measured lean at which the robot balances. Wrong, and the robot creeps forward or backward.
Speed KP How far the robot leans to reach the speed it is asked for. Too high and it sways.
Speed KI Holds the robot's position while it stands still.
Max lean The furthest the robot leans to speed up or stop.

Save to robot stores the parameters in the robot's EEPROM so it balances this way without ARCx; the motors stop for a moment while it saves, so hold the robot. Read from robot brings the robot's values into the page. Default gains puts the gains back to the firmware's defaults.

Driving

The Driving tab

The robot's top speed in m/s, how fast it speeds up and slows down, its top turn rate and the turn gains, and how the movement panel's speed maps onto them. The drive timeout stops the robot driving when ARCx stops sending (a dropped link); the drive command is repeated more often than that while driving. The emergency stop and the panic button normally stop driving and keep the robot balancing; tick Emergency turns the motors off to have them drop it instead.

Auto-tune

The auto-tuner running

The auto-tuner tunes the robot on the floor in a few minutes. Stay with it: it tells you, in large text, when to hold the robot, when to let go, and when to stand it back up after a fall (it starts again by itself once upright).

  1. Drop test. Hold the robot upright, and let go when told: it falls with its motors off. How fast it falls sets the ratio of Angle KD to Angle KP. A short robot falls fast and needs quicker damping than a tall one.
  2. Balance gain search. Angle KP, with KI and KD in proportion, is raised until the robot shakes or saturates its motors, and lowered until it gets sloppy or falls. The middle of the range that balanced leaves the most margin both ways.
  3. Balance point. Standing still, the robot's average lean is its true balance point.
  4. Speed loop. The robot drives forward, stops, reverses and stops (about half a metre each way) while Speed KP is tuned for tracking the speed without swaying.

Every trial is listed with how it went: the lean error, the shaking, the wobble frequency, the speed error and how often the motors were at full power. At the end the result is shown beside the values from before. Use these values keeps it (then press Save, and Save to robot); Discard puts the old gains back on the robot. Stop, or driving the robot, ends the tune and puts the old gains back.

A finished auto-tune with its result and every trial

Tips

A robot that falls the same way every time has its IMU orientation, a motor or an encoder backwards: check the Robot tab. A robot that rocks slowly with its wheels still needs some motor deadband. A robot that buzzes has too much Angle KD, or a loose IMU. A robot that creeps one way while standing has a wrong balance point. A robot that runs away when driving needs more Angle KI. Heavy batteries mounted high make a robot easier to balance, not harder: it falls more slowly.


Control Commands for the Two Wheel Self Balancing Robot robot skill

There are Control Commands available for this robot skill which allows the skill to be controlled programmatically from scripts or other robot skills. These commands enable you to automate actions, respond to sensor inputs, and integrate the robot skill with other systems or custom interfaces. If you're new to the concept of Control Commands, we have a comprehensive manual available here that explains how to use them, provides examples to get you started and make the most of this powerful feature.

Control Command Manual

This robot skill has 22 control commands, listed below. Send them from a JavaScript or Python script, from Blockly, or from another robot skill.

The first value is always the window title, which is the name in the title bar of the robot skill on your workspace. It starts out as Two Wheel Self Balancing Robot, which is what every example below uses. If you rename the robot skill, or add a second copy of it to the project, use the title as it appears on that window instead.

ControlCommand() can be shortened to CC(), and both spellings work in JavaScript and in Python. The examples are JavaScript; Python is the same call, except that true and false are written True and False.

CalibrateGyro

Measure the gyro's zero again. The robot must be still with its motors off; it takes a second.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "CalibrateGyro")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "CalibrateGyro");

Connect

Connect to the robot (open the link, check the firmware and send the project's parameters). Returns true when connected. Takes up to a few seconds.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "Connect")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "Connect");

Disconnect

Disconnect from the robot and stay disconnected until Connect, freeing the port (for the Arduino IDE to upload firmware). The robot keeps balancing on its own.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "Disconnect")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "Disconnect");

Drive

Drive with a speed and a turn, like a joystick: forward is -100 (full reverse) to 100 (full forward) percent of the robot's max speed, turn is -100 (left) to 100 (right) percent of its max turn rate. It keeps driving until Stop or another movement command.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "Drive", (Number)forward, (Number)turn)

Parameters

# Name Type What to pass
1 forward Number A number, without quotes
2 turn Number A number, without quotes

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "Drive", 0, 0);

GetBattery

The battery voltage, or 0 when the robot does not measure it.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetBattery")

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetBattery");

GetDistance

The distance driven since power up or ResetDistance, metres, forward positive.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetDistance")

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetDistance");

GetLean

The robot's lean from its balance point, degrees, positive forward.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetLean")

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetLean");

GetParameter

One of the robot's parameters as the robot has it (read from the robot when connected, the project's value otherwise). Name as for SetParameter.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetParameter", (String)name)

Parameters

# Name Type What to pass
1 name Text Your text, in quotes

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetParameter", "name");

GetSpeed

The robot's speed, m/s, positive forward (estimated from the motor power when it has no encoders).

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetSpeed")

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetSpeed");

GetState

What the robot is doing: Motors off, Waiting to be stood up, Balancing, Calibrating the gyro, Drop test, Motor test, IMU not answering, or Not connected.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "GetState")

Returns: String

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "GetState");

IsAutoTuning

Whether the auto-tuner is running.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "IsAutoTuning")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "IsAutoTuning");

IsBalancing

Whether the robot is balancing right now.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "IsBalancing")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "IsBalancing");

IsConnected

Whether ARCx is connected to the robot.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "IsConnected")

Returns: Boolean [true or false]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "IsConnected");

LevelHere

Make the robot's current lean its balance point. Hold it exactly where it balances first. Returns the new balance point, degrees.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "LevelHere")

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "LevelHere");

ResetDistance

Set the distance driven back to 0.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "ResetDistance")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "ResetDistance");

SaveToRobot

Save the robot's current parameters in its EEPROM, so it balances the same way without ARCx. Not while it is balancing (turn the motors off first).

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "SaveToRobot")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "SaveToRobot");

SetParameter

Change one of the robot's parameters now, and in the project (save the project, and SaveToRobot, to keep it). Name is a parameter of the configuration's Parameters, such as AngleKp, AngleKi, AngleKd, SpeedKp, SpeedKi, BalancePoint, MaxSpeed or MaxTurnRate. Returns the value applied after clamping to its range. The names: AngleKp, AngleKi, AngleKd, SpeedKp, SpeedKi, TurnKp, TurnKi, BalancePoint, MaxLean, MaxSpeed, MaxTurnRate, DriveAcceleration, FallAngle, RestartAngle, AutoRestart, BalanceOnPowerUp, MotorDeadband, MotorMaxPower, AngleFilterSeconds, SpeedFilter, CommandTimeoutMs, EncoderCountsPerRevolution, WheelDiameterMm, OpenLoopSpeed, InvertLeftMotor, InvertRightMotor, InvertLeftEncoder, InvertRightEncoder, ImuUpAxis, ImuLeftAxis, BatteryDividerRatio, LowBatteryVolts, AngleIntegralLimit, TurnLimit.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "SetParameter", (String)name, (Number)value)

Parameters

# Name Type What to pass
1 name Text Your text, in quotes
2 value Number A number, without quotes

Returns: Double [5.0e324 to 1.7e308]

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "SetParameter", "name", 0);

StartAutoTune

Start the auto-tuner with the configuration's auto-tune settings. Someone must stand by to hold the robot for the drop test and to stand it up after falls. It runs for a few minutes; the result goes into the project's parameters when it finishes. Returns immediately.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "StartAutoTune")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "StartAutoTune");

StartBalancing

Turn balancing on: the robot balances as soon as it is stood upright. Returns the robot's state.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "StartBalancing")

Returns: String

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "StartBalancing");

Stop

Stop driving at once. The robot keeps balancing in place.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "Stop")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "Stop");

StopAutoTune

Stop the auto-tuner; the gains from before it started go back on the robot.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "StopAutoTune")

Returns: nothing

Example

ControlCommand("Two Wheel Self Balancing Robot", "StopAutoTune");

StopBalancing

Turn the motors off. A standing robot falls over: hold it first. Returns the robot's state.

Syntax

ControlCommand("Two Wheel Self Balancing Robot", "StopBalancing")

Returns: String

Example

var result = ControlCommand("Two Wheel Self Balancing Robot", "StopBalancing");

This list is read out of the robot skill itself each time its package is uploaded, so it matches the published version (v2).


ARC Pro

Upgrade to ARC Pro

Stay on the cutting edge of robotics with ARC Pro, guaranteeing that your robot is always ahead of the game.

#2  

This robot skill has been updated to v2.

What has changed

updated to use some new ARCx UI features for improved performance.