Introduction: Brushless Gimbal Balancing Robot

The following project is a result of viewing the Cubli video and becoming interested in the control of unstable equilibrium using brushless motors. The simpler inverted pendulum problem was decided on in order to complete the project before loosing interest. Many people provide better descriptions than I can, therefore I will only focus on the build and try to offer useful links when needed.

Step 1: Parts

As the project title hints, the robot uses parts from a brushless gimbal camera stabilizer. This is ideal as the motor controllers and microcontroller are on the same circuit board and already setup to work with the included brushless motors and inertial measurement unit (IMU). The chosen gimbal system is designed to work with GoPro sized cameras with several iterations found cheaply online.

    • Gimbal control board BGC 2.0, look closely at the provided picture (2X L6234 brushless motor control ICs, mega328p microcontroller, Silabs CP2102 USB to serial)

    Note: other boards may work, it will need to be programmable using the Arduino IDE, therefore must contain a compatible microcontroller and ISP header to burn the bootloader

    • gy-521 IMU (MPU-6050 3-axis gyroscope and 3-axis accelerometer)
    • 2X 2208 brushless gimbal motors (fasteners to mount motor, they were included with my gimbal)
    • LiPo battery 3S (Turnigy nano-tech 460mAh 25-40C 57X31X17mm)
    • Colson Performa wheels 2" X 7/8"
    • 5/8" aluminum plate or bar to CNC robot body from, body made of two halves with finished size 2.50X4.89X0.55" (1/2" plate or bar also works, body will be 0.1" thinner)
    • 2X 6-32 X 1" button head screws
    • 1/8" X 3/4" dowel pin
    • 6" X 1/2" double sided Velcro strap to hold battery in
    • Other assembly stuff: double sided foam tape, hot glue, hook-up wire, 0.8mm piano wire to lengthen Bluetooth antenna, sticky rubber bumpers, battery plugs, indicator LEDs and stuff I have not thought of

    Step 2: SolidWorks Model

    The SolidWorks model is provided for machining and reference. Make sure your electronics, battery, motors and other parts work with the design before starting. Some modification might be needed.

    Step 3: Machining

    The inside diameter of the wheels need to be opened up on a lathe to allow for the motors to be pressed into the wheels. Measure the outer diameter of the motors and turn the inner diameter of the wheels about 0.001-0.002" smaller for a press fit. The depth should match the dimension of the outrunner motor bell. The wheel core is made of a hard plastic and holds decent tolerance. I held the wheels by the rubber exterior, in a six jaw chuck and indicated in off the plastic face.

    Remove the motor bell/shaft assemblies by pulling the snap ring off the shaft on the back side of the motor and drawing the assembly out of the bearings. Press the bells into the wheels by putting pressure on the edge of the bell (not the shaft).

    The body consists of two identical halves except for the alignment pin holes and the fasteners (see provided drawing). The two halves are CNC milled from 5/8" (1/2" also works but robot will be 0.1" thinner) aluminum plate. The SolidWorks part is provided to use with your CAM software of choice. I marked the motor mounting holes, alignment pin hole and fastener holes on the CNC using a center drill before the parts were separated from the plate. The parts should now be deburred and cleaned. I then complete the drilling, tapping and countersinking (this can also be accomplished on the mill before the parts are removed from the plate).

    Step 4: Assembly

    Look at the provided picture for part orientation.

    • Press the dowel pin into place
    • Attach the control board using double sided foam tape on the webs of the aluminum body
    • Attach the brushless motors to the body with the wires on top
    • Hot glue the IMU into place making sure it sits flush on the aluminum tabs and the IC is located inline with the motor shafts
    • Create a full wave antenna (~12.5cm) out of the piano wire for the Bluetooth module and attach so it goes outside the body (I drilled a small hole through the module allowing the antenna to go out the backside and provide more support)
    • Attach the Bluetooth module using double sided foam tape
    • Reset the default values on the HC-05 using AT commands and these instructions. My Bluetooth module had a pushbutton instead of a "KEY" pin, that needed to be held during power up and programming. The device name and password are reset and the baud rate is set to 230400.
    • Connect the Bluetooth TX to RX, Bluetooth RX through a voltage divider to TX to reduce the voltage to 3.3v and supply the needed power
    • Attach a battery connector (I added a 2amp fuse inline to offer a little more protection)
    • Hookup the IMU and motors to the control board (they came with attached connectors)
    • Attach an indicator LED to pin A1 using a 1k ohm resistor (I attached two and pointed them out the bottom of the robot)
    • Other optional stuff: Velcro straps on the top to hold the battery in, hot glue the wires for strain relief, rubber bumpers to protect the floor
    • Both halves should now fit together and be held in place using the two #6-32 fasteners

    Step 5: Arduino Code

    -The code is running on a mega328p and was compiled using Arduino 1.6.6
    -The code cycle time is a constant ~250Hz

    At the heart of the code is a counter that is advanced every time TIMER1 overflows and triggers an interrupt routine. This counter triggers other events at specific intervals allowing the code to run at a known rate and simplify math in the control loop.

    The tilt angle of the robot is calculated using a complementary filter with gyrometer and acceleration values from the MPU6050 IC. This is fed into a control loop with three other values: the time derivative of the tilt angle, robot velocity (acceleration integral) and robot displacement (velocity integral). All four values are added with preset gain to get an output term proportional to robot acceleration. A good explanation of this control loop by David P. Anderson and more information on his balancing robot.

    To move the robot an offset is added to the displacement value in the control loop. To turn left or right an offset is added/subtracted from the left and right wheel velocities. The wheel velocities are fed into the the motor control portion of the code.

    Brushless motors require 3-phase power. Look at this explanation of how angle control of brushless gimbal motors is achieved. The motor control portion of my code is based off of the BruGi brushless gimbal control code. All three timers are set to output 31.25KHZ phase correct PWM (6 PWM outs). A useful article on adjusting Arduino timers.

    A lookup table containing space vector PWM values is used to pull three values with 120 degree phase separation. The values pulled from the lookup table are advanced at a rate proportional to the needed left or right robot wheel velocity.

    The code handles motor power adjustment to correct for torque falloff at higher speeds and greater needed torque during higher acceleration. The battery voltage is monitored to prevent damage to the LiPo batteries. The code also handles Bluetooth communication between a smartphone.

    Step 6: Tuning Control Loop for Balance

    The control loop has four gain values that need to be set.

    1. kp angle gain
    2. kd angle velocity gain
    3. kv velocity gain
    4. kc position gain

    This is how I tuned the robot for balance, it is probably not ideal but it worked. Start with all gain values set to zero. Slowly increase kp gain until the robot no longer falls forward, now increase kd gain until the robot stands but slowly oscillates with growing amplitude until the robot falls over. Increase the kv value until the robot no longer oscillates and recovers from a light push on the top. At this point the robot should have the desired performance. It should stand in one place and recover from a disturbance. Play with the three values to get a better feel for how they behave. Now increase kc gain until the robot returns to the same place after a disturbance but not too large resulting in decreased performance.

    I reset all values to zero and started over several times until I achieved decent results. If it looks like the loop is completely failing make sure all the calculated values in the loop have the correct sign and behavior and the feedback values have the correct sign.

    Step 7: Bluetooth Control

    The android app Joystick BT Commander is used to communicate with the Bluetooth device on the robot. The app is setup to display the robot battery voltage, relative motor output power and the code cycle time. The cycle time is important because it must not exceed the time interval between calls (~4ms) in order to maintain proper timing for derivative and integral calculations. The app also has two buttons setup. A power button "ON" turns on the motor control portion of the code when activated. The second button "Fast" increases the robots top speed by a factor of two when pressed.

    Step 8: Finished

    When the robot is first powered it needs to be set on its front or back within 5 seconds. At this point the indicator LED will flicker for 10 seconds as 1024 gyroscope readings are averaged to obtain a calibration value. If the battery is charged the indicator led should now start to turn on and off every 2 seconds. A connection can now be made between the smartphone Bluetooth application and the robot. Press the "ON" button and place the robot within 1 degree of vertical to start balancing. Use the joystick to drive the robot. Once the battery is depleted the robot will no longer balance and the indicator LED will stay on.


    esmk2 (author)2017-09-16

    please help me

    271828- (author)esmk22017-09-19

    Sounds like you figured out how to upload the bootloader if you have the program uploaded now? Docman100 is correct, the code will do nothing without the Bluetooth connected as it's waiting for an on/off signal from a Bluetooth connected phone. After the "on" signal is sent, the robot must also be placed vertical to start balancing.

    docman100 (author)271828-2017-09-19

    Ok I now just need the files for 3d printing cause I don't think I can get the aluminum. (and it cost a lot apparently)

    docman100 (author)docman1002017-09-19

    I Also cant find any dowel pins but im also not sure that's very important

    docman100 (author)esmk22017-09-18

    I Don't think the code works without the Bluetooth connected.

    docman100 (author)2017-09-18

    I Have a few questions, first I have every single item accept for the gimbal and the motors that you said come with the motors, I cant find any gimbal and motors where do you get them? next, where do you get the aluminum? and how do you get the size right? and last did you use a lazer cutter to cut it?

    271828- (author)docman1002017-09-19

    The controller and motors came from a gimbal camera stabilizer like this one but you need to check if the controller board is the correct style "Gimbal control board BGC 2.0, look closely at the provided picture (2X L6234 brushless motor control ICs, mega328p microcontroller, Silabs CP2102 USB to serial"

    I purchased the aluminum locally as scrap, but you can get it online at places like . The parts are CNC milled, laser cutting will not work. The solid model files contain the part sizes. Other people have 3D printed the parts which also works.

    esmk2 (author)2017-09-16

    program uploaded to boad but not working it. code not working without Bluetooth?

    esmk2 (author)2017-09-16

    sorry for my english

    program uploaded to bode but not working it. code not working without Bluetooth?

    esmk2 (author)2017-09-16

    please send me a video link how to upload bootloder for BGC 1.0 board

    Avasar (author)2017-09-01

    Can you send code me in attchment file..

    271828- (author)Avasar2017-09-05

    The code is provided in step 5.

    271828- (author)eungyoJ2017-08-27

    Nicely done and thank you for posting!

    eungyoJ (author)271828-2017-08-29

    I finished it.

    It's nice & funny. Thank you.

    271828- (author)eungyoJ2017-09-01

    Congratulations! It's looking good! How much control loop tuning did you do?

    AjeetK8 (author)2017-08-07

    I am working on this project.. with some alterations... As i removed the Bluetooth and remove all flags set by app. but motors were not responding. So i only put the following code in loop but motor making hammm sound not running. can anybody please tell what is problem.. Thanks in advance...

    void loop()


    PWM_A_MOTOR0 = (uint8_t)0;

    PWM_B_MOTOR0 = (uint8_t)85;

    PWM_C_MOTOR0 = (uint8_t)170;


    PWM_A_MOTOR1 = (uint8_t)85;

    PWM_B_MOTOR1 = (uint8_t)170;

    PWM_C_MOTOR1 = (uint8_t)255;



    271828- (author)AjeetK82017-08-09

    The motors used are brushless and require three sine waves with a 120 degree offset to run. This is done using a lookup table with one complete sine wave. The values pulled from the table are staggered for motor output A, B, and C for each motor. The staggering allows for the 120 degree offset. These values are fed into the PWM outs. The rate at which they are advanced through the lookup table sets the speed at which the motors run.

    Also as a side note, the amplitude of the sine wave is scaled to adjust the power to the motors to prevent overheating.

    AjeetK8 (author)271828-2017-08-14

    Thank You for your reply...
    i got it..
    still i could not able to make it run. actually i did some changes with this default code.. i removed the bluetooth and set a touch screen LCD on it to set gains and run it...So.. please guide me what to do with JoyX and JoyY variables as those comes from apk. i get managed with ON button from apk..

    271828- (author)AjeetK82017-08-15

    JoyX sets the forward velocity and JoyY rotates the robot. They can be set to a default value of you just want to get the robot balancing and not moving.

    AjeetK8 (author)271828-2017-08-17

    What would be default value for them?
    Thank you

    271828- (author)AjeetK82017-08-19

    JoyX and JoyY have an input range from -100 to 100. No movement corresponds to 0 which should be the default. Looking at the code, JoyY moves the robot forward/backwards and JoyX rotates the robot.

    AjeetK8 (author)271828-2017-08-25

    Thanks dear,

    the code is working, when i tilt IMU motor moves ... but after 2 or 3 tilts it stops and never move...
    can you please give me reason for it..

    and why you have used TIMMER that counts the frequency.. as i am not using bluetooth so should i need this?

    271828- (author)AjeetK82017-08-27

    See other post above.

    AjeetK8 (author)271828-2017-08-18

    I have BGC 3.0, so does code need any changes because of the board?

    271828- (author)AjeetK82017-08-19

    I'm not sure, find a circuit diagram for both boards and compare the wiring between the brushless motor control chips, IMU chip and the microcontroller.

    AjeetK8 (author)271828-2017-08-24

    Thanks dear,

    the code is working, when i tilt IMU motor moves ... but after 2 or 3 tilts it stops and never move...
    can you please give me reason for it..

    and why you have used TIMMER that counts the frequency.. as i am not using bluetooth so should i need this?

    271828- (author)AjeetK82017-08-27

    That's great you have the motors moving! How are you powering the robot, and did you hook the voltage divider resistors up? There is an under voltage shutoff in the code for a 3 cell lipo, so if the voltage goes under a set value the code will not run. If you left the measurement pin floating that would normally measure the voltage it will randomly turn the robot off.

    The loop timer is to make sure the code is running faster than the set code frequency used is the PID loop and motor control. It's good to check this value if changes to the code are made. You can use a serial print to check this value if you are not using Bluetooth.

    jimkan (author)2017-06-23

    Before putting everything in place, try to hook up all electronics load up the sketch without problem, can see IMU values changes in serial console but motors are not moving at all. Any advise?

    271828- (author)jimkan2017-06-24

    There could be a few possible reasons. The robot needs to be connected to the Bluetooth controller on the cellphone and turned on using the app to move. The robot also needs to be almost vertical in order to start balancing, therefore the IMU needs to be held in the vertical orientation that it will be in while the robot is running for the motors to move.

    jimkan (author)271828-2017-07-02

    Hi 271828, I am using BGC 3.0, upload the program fine and Joystick app show voltage changes but that is all, no activities on motors, button one and two seem to do nothing. The board I use does not have an INT is this why it's not working?

    271828- (author)jimkan2017-07-08

    The first button turns the control loop on, it should be green when on. The second button increases the max allowed speed and can stay off. With the app connected, turn the first button on and try to hold the IMU in the vertical position it would be inside the robot when balancing. Look at the assembly photo. The motors should momentary turn on when the IMU reaches vertical. The joystick will do nothing until it's actually balancing.

    jimkan (author)271828-2017-06-28

    yes, you were right, after hooking up the Bluetooth module the motors started to response with the movement of IMU but they don't response to the updated android app, is the older version of the app like the one you posted here still available?


    271828- (author)jimkan2017-06-29

    The linked page under step 7 has the version I used (5.2). You will need to add the labels for the buttons and value within the app manually. The joystick within the app does not directly control the motor motion so you might not see much response if just holding the parts. The app is working if you are able to turn the power on and see the battery voltage.

    Tyde (author)2017-05-19

    Good work

    I have built a house with no turn I have to change wheels

    Did you have a trick to make wheels

    Thank you

    271828- (author)Tyde2017-05-19

    You could try 3D printing wheels that fit the outside of your motors or try and drill out the inside of some wheels using a drill press and a forstner drill bit. Not sure what you have access to.

    ПавелП6 (author)2017-04-28

    How can I change the code for such engines?

    271828- (author)ПавелП62017-05-04

    The linked motors should work for a balancing robot but my code is not what you want to use. A lot of my code is for controlling the brushless motors. The linked DC (direct current) motors are easier to control and are more commonly used for this project. Take a look at the other balancing projects on Instructables for code examples. I would also recommend adding encoders or purchasing motors with encoders built in.

    ItsMe-Phil (author)2016-06-29

    Very cool...

    Newbie question, You say you are using 2208 motors. Does the KV matter for this project?


    271828- (author)ItsMe-Phil2016-06-30


    If the motors are designed for brushless gimbal camera stabilizers they should work. This kind of motor is not the same as the ones used for spinning a propeller. The 2208 motors typical are in the range of 80-100 KV.

    ItsMe-Phil (author)271828-2016-06-30

    Got it! Thank so much.

    Then this is the one I'll buy:

    271828- (author)ItsMe-Phil2016-07-02

    Those should work!

    AndreQ1 (author)2016-05-01
    Hello I found this amazing project, but for me this hard to understand. It would be possible to describethe code for programming the engines in addition to the links between the components?


    271828- (author)AndreQ12016-05-03

    Thank you!

    I would recommend reading about the inverted pendulum problem and once that is understood, try building a balancing robot using brushed motors. A lot of this projects complexity comes from the control of brushless motors. The wiring and code is not easily described in its entirety. I will try to answer any particular questions you have.

    macgverl (author)2016-04-11

    Wow is Very Cool.

    I have doen . But needs tuning PID.

    Thank very match shareing.

    271828- (author)macgverl2016-04-12

    Great job!

    Glad you like it and thanks for linking the video!

    DhamirH (author)2016-03-09

    Great project..
    but i still looking for the wiring scheme and pins configuration.

    is that attached or i just cant found it?

    sorry im a newbie in this

    271828- (author)DhamirH2016-03-09


    I never created a wiring schematic as it uses the gimbal electronics with little modification. Step 4 mentions the Arduino pins used, but there exists several gimbal control boards with different pin configurations so the relation between hardware and software will have to be determined for the board being used.

    Gelstronic (author)2015-12-30

    Hi, i finished building so far and got some problems.

    Of course the bot won't balance :-)

    So, what i've done :

    Check battery power,

    check looptime under 4ms

    check robot_angle (see video, debug_data_field)

    change the motor direction.

    Changing the k-values not effect anything.

    The wheels dither very much and the bot fall over.

    My gimbal motors:

    2208 80KV

    Weight: 39g
    Motor Type:12N14P
    70 turns,3mm shaft

    here's a link with the video:

    any suggestions what to do ?

    271828- (author)Gelstronic2015-12-31

    looking good so far!

    The motor dithering is caused by the loop trying to command wheel movement faster than the wheels can accelerate. This results in the motors stalling and the noise you hear. Because the robot is not moving, the commanded velocity continues to increase, while the motors slip, until a max velocity value in the code is reached and the control loop is turned off.

    Start by setting all the k values to zero except Kp. Set Kp to something small like 0.01 and see if the wheels spin in the proper direction when the robot is tilt while held off the ground. The robot wheel speed should increase as the robot angle increases and the robot should try to move in the direction of tilt.

    Check if the vertical equilibrium angle is measured as zero with everything in place and no external forces acting an the robot (balancing the robot by hand). If it is not close you will need to adjust the mounting of the MPU6050 or add an offset to the angle measurement.

    If everything is working to this point, try following the tuning instructions in the Instructable.

    About This Instructable




    Bio: Hi! You can call me Matt. I'm a problem solver with interests in many fields. Sites like this are a great resource, therefore I ... More »
    More by 271828-:Adjustable CNC Router Dust BootCustom Wye Fittings for Your Dust Collector Simple Slap Bracelet / Cycling Trouser Strap
    Add instructable to: