Home > Arduino, Balanduino, Bluetooth, Guides, TKJ Electronics > Full size DIY Balancing Robot

Full size DIY Balancing Robot

It has been quite a while since my last blog post, but I am finally ready to reveal what I have been working on the last months. Ever since I made my first balancing robot: http://blog.tkjelectronics.dk/2012/03/the-balancing-robot/ and the Balanduino I wanted to build myself a full size version which I would be able to ride just like a regular Segway.

Finally I decided to make one together with a good friend of mine Mads Friis Bornebusch in a course at my university DTU (Danish Technical University).

Video demonstration

Mechanical construction
The main frame is an aluminium checker plate that is 500x360x7mm which the motors are bolted onto. This width was chosen, so it would be able to go through a normal door opening. The motors used are two MY1020Z 500W, 24V, 12.6Nm brushed DC motors.

I ordered them from Germany, as I needed them right away, but you should be able to get them much cheaper by ordering them directly from China.

Below is an image of the aluminium checker plate after we have drilled the holes for the 8mm steel bolts. Note that these are countersunk, so they are flush with the surface. I would recommend using lock nuts to ensure that the bolts will stay in place – you can also use Loctite instead.

Aluminium checker plate - ready to mount the motors

Aluminium checker plate – ready to mount the motors

Motor with hub

Motor with hub



Countersunk bolt

Countersunk bolt

Motor bolted onto frame

Motor bolted onto frame


After that we drilled four countersunk 10mm holes. These are used to bolt two SKF Y bearings to the middle of the frame. Inside these are mounted a 300mm ½″ steel water pipe with some custom made fittings for the 25mm bearing.

Custom fitting on the pipe

Custom fitting on the pipe

Finished assembly

Finished assembly


In one end is mounted a 10kΩ potentiometer which is used to tell the position of the steering rod. It is mounted to a hole in the endcap secured using some epoxy. The potentiometer is then bolted to a square aluminum bracket secured to the main frame using screw holes we made.
In the other end is mounted a 90° bracket – note that we have welded a solid iron rod inside the rod, at the bracket, as it broke off during testing. All pipes are just ½″ steel water pipe that you should be able to get at your local hardware store.

Potentiometer for steering mechanism

Potentiometer for steering mechanism

90° bracket

90° bracket



Mounted to the other end of the 90° bracket is the steering rod. This is 1050mm long with a T-bracket in the other end. Two 180mm pieces with an endcap are then used as the handlebar. I decided to put some tape used for bicycles around the handlebars to give them a more comfortable grip.

Two springs from an old washing machine are connected from the edge of the frame to 230mm up on the steering rod. This ensures that the steering rod will always center itself. The hose clamps are there to ensure that both are equally tight.

Spring mechanism

Spring mechanism

On the handlebar is also a deadman button which is connected to the reset pin on the motor drivers. This needs to be held in while riding it and will prevent the motors from turning if it is released.

Deadman button

Deadman button

In order to mount the wheels onto the motors we made a custom motor hub.
A 3D-rendering of the motor hub can be seen below (not supported on mobile devices and some browsers). Note that the cylinder going out from the hub is meant to add support, as it will fit around the motor shaft. We did this as we were worried that the load might damage the gearing inside the motors.

The 3D-drawings are available at the Github repository.

Finished motor hub

Finished motor hub

The electronics

The heart of the main board is a 16MHz Arduino Pro Mini running at 5V it reads a MPU-6050, 3-axis accelerometer and gyroscope in order to estimate the angle. This is done by reading the accelerometer and gyroscope at 500Hz. The measurements are then fusioned together using the Kalman filter I wrote some time ago.
It then uses the angle as an input to a manually tuned PID-controller which will output the PWM value needed to keep the robot balanced.

A Bluetooth SPP module is connected to the microcontroller as well. This allows it to communicate with an Android phone via Bluetooth using an application I have written.

Two inputs on a LM324 operational amplifier is used as a buffer. This buffers the signal coming from the deadman switch. This is needed as there is a 20kΩ pull-up resistor on each of the motor drivers reset inputs. The diode D1 is there to ensure that the microcontroller will never be able to drive the signal going to the reset pins on the motor drivers high.
Furthermore one input is also used to buffer the voltage measurement read from the batteries.

One input is used as a inverted amplifier in order to amplify the signal coming from the potentiometer connected to the steering mechanism. The 10kΩ potentiometer is used to adjust the output until it is roughly 2.5V.

A buzzer is also connected. This is used for basic feedback, as it will beep when the robot is turned on and will be turned on in case the battery voltage gets too low.

Headers for signal going to the two motor drives are also available.

Main board schematic

Main board schematic


Below is a picture of the finished PCB. Note that the MPU-6050 is mounted using some double sticky foam – this is to reduce vibrations.
The final PCB can be found at the following link: https://github.com/Lauszus/BalancingRobotFullSize/tree/master/PCB.

Etched PCB

Etched PCB

Main board almost done

Main board almost done


In order to control the two motors you will need two high power motor drivers. We decided use the Pololu High-Power Motor Driver 24V/23A. Each motor driver is rated at 23A continuous current without a heatsink. We have mounted heat sinks on the motor drivers to ensure that they can handle the current, as the motors have a peak current of 26.7A according to its specification. In this setup the motor drivers does not even get hot.

Motor driver front

Motor driver front

Motor driver back

Motor driver back


In order to control the motors you simply apply a PWM signal to PWMH and control the direction using the DIR input. This allows you to easily control the motors with only two pins. Note that PWML is not used in the final setup. Furthermore the motor driver has two “Fault flag indicators” labeled FF1 and FF2. These will be drive high in case of a fault. The motor driver can be reset by driving the RESET pin low – this is done if the deadman button is released.
Finally it also features a current sense output. The current sensor is powered by soldering a jumper on the PCB – more information can be found at the product page.

I decided to use this motor driver, as I can control it directly using the I/O on the microcontroller instead of using a serial interface which is also used on some motor drivers. I did not want to use this, as the serial communication is slow compared to just controlling it directly using the pins on the microcontroller.

Also note that the microcontroller and motor driver are both grounded via the same battery. If you intend to power the microcontroller from a separate battery. You will need to solder a wire to GND as well.

Below is a picture of the motor drivers before and after we mounted the heatsink. Note that we cut away the heat shrink at the MOSFETs and applied some cooling paste before mounting the heatsink to the motor drives using some long bolts.

Motor drivers

Motor drivers

Motor driver with heatsink

Motor driver with heatsink


To power everything we decided to use three 6S LiPo 3000mAh batteries in parallel giving a total capacity of 9000mAh.
I have not actually made an endurance test, but they seem to last a pretty long time – it lasted from 10am to 4pm at a conference with only two batteries.

As the maximum voltage of the LiPo batteries is 25.2V (4.2V per cell) you can not simply connect the batteries directly to the VIN/RAW pin on the Arduino Pro Mini. Instead we are using a LM2596 step down switch mode regulator in order to step down the voltage to 8V. This is then stepped down by a 7805 5V linear regulator which is located on the main PCB.

It is very important that all you apply a good amount of solder to all your connections, so they can handle the high power needed. Below is a picture of the custom parallel cable I made. This was done by first applying solder to a 10AWG wire. Three 12AWG wires were then soldered to one end and a wire was wrapped around them in order to keep them in place. The same thing was then done for the other side. Finally a wire was wrapped around the entire joint and solder was applied. This will require a good soldering iron and a large tip in order to reflow the entire soldering joint.

Before connectors and heat shrink

Before connectors and heat shrink

Finished battery cable

Finished battery cable


Below is a picture of the three batteries connected to the parallel cable I made. The three female XT60 connectors are connect to the two motor drivers and the last one is connect to the LM2596 switch mode regulator.

Batteries with parallel cable

Batteries with parallel cable

The finished PCB is then mounted inside a electronic enclosure on the bottomside of the robot. It is mounted using double sided sticky foam in order to reduce the vibrations to the MPU-6050.

Electronics mounted inside enclosure

Electronics mounted inside enclosure


Robot bottom side

Robot bottom side


Robot overview

Robot overview

Me driving the robot

Me driving the robot


The code

Flowchart of the code

Flowchart of the code

The code was inspired by the Balanduino code: https://github.com/tkjelectronics/Balanduino and the basic structure is basically the same. It is written in C/C++ using some libraries and functions from the Arduino platform – these are the Wire (I2C) library and the timekeeping functions millis and micros.

A flowchart of the main loop of the code can be seen to the right.

At first the microcontroller is powered on by connecting the battery to the LM2596 regulator. Then it initializes an input which makes it able to read the current status of the deadman button. After that it sets the pin connected to the buzzer to output and reads the different values from the EEPROM including PID-values, Kalman values etc. If it detects that the EEPROM values should be restored (if the structure of the values have changed due to a value being added or removed to the configuration struct) it will turn on the buzzer for 1 second and proceed afterwards.
The next step is to initialize the UART (Universal asynchronous receiver/transmitter) at 57600 baud rate, the pins connected to the motor drivers and configure the MPU-6050 at a sample rate of 500Hz and set the accelerometer ±2g and the gyroscope range to ±250deg/s. It then calibrates the steering and finally turns on the buzzer for 100ms and initializes the timers it uses for timekeeping.

Now the main loop is running. As it can be seen on the flowchart it will run forever until power is removed. The first step is to check if any of the diagnostic pins on the motor driver are high, this means that there is some kind of fault. If that is the case it will turn on the buzzer to alert the user that something is wrong. The next is to check if any new IMU data is available. The MPU-6050 is configured so it will hold its INT pin high if there are new measurements available.
If there is no new data from the IMU it will check if any data is available at the serial port. This is used to configure PID-values, Kalman values, the amount of turning etc.
If new measurements are available it will read the sensors and calculate the angle using the Kalman filter. Then it reads the steering input from the potentiometer and checks if the robot is upright and the deadman button is pressed. If that is not the case it either means that the robot has fallen over or the user has let go of the button. In this case it will turn off the motors. If not it will calculate new PWM-values for the motors using a PID-controller.

To turn the robot a value is simply added to one motor’s PWM value and subtracted from the other. This value depends on the value read from the potentiometer connected to the steering rod. The specific code can be found inside PID.cpp.

Finally the battery voltage is checked. If the battery is too low it will start the buzzer. After this final step it will go back to the start of the loop.

One key difference between this hardware and the Balanduino is that there is no encoders on the full size version, so it is actually not possible for it to balance on its own.
This also makes it harder to estimate the speed of the robot. This is instead estimated by integrating the PWM value. This is used to tilt the robot backwards as the speed increases to prevent it from falling over.

To control the robot you simply lean forward/backward which will make the robot start to travel in the given direction. You tilt the steering rod to either side in order to turn. The full source code is available at Github: https://github.com/Lauszus/BalancingRobotFullSize.


Android application

In order to easily tune the PID-values and get data from the robot I wrote an Android application.

Below is a picture showing an overview of the Android application.

At the first screen the user is able to see the current draw of the motors, the turning value, battery level, run time and finally the PWM-value on a custom speedometer.

The next screen allows the user to adjust the PID-values, target angle and adjust how fast the robot should be able to turn.

The third screen shows the current position on a map. The position is obtained using the built-in GPS module on the Android device.

The fourth and final screen shows a graph of the current angle calculated using the accelerometer, gyroscope and the angle estimated using the Kalman filter. It also allows the users to adjust the Kalman filter coefficients.

The communication between the microcontroller and Android application is done via Bluetooth. In order to make sure that the data is parsed properly a protocol for this was implemented. It consist of a constant string header, then one byte to indicate the command and then one byte indicating the length of the data to follow. After the data there is a simple checksum. This checksum is calculated by taking XOR of each byte in the message excluding the header. The full serial protocol can be seen in the source codes: Protocol.cpp, BluetoothChatService.java and BluetoothProtocol.java

The phone is mounted on a smartphone dock that is simply zip tied to the steering rod.

Application screenshots

Application screenshots


Further documentation

Part of the assignment was to write a very brief six pages paper. The paper can be found at the following link: GRP12_AUT2_Two_wheeled_robot.pdf. I would really recommend you read through it if you are new to the concept of balancing robots as it explains the basic of how two wheeled balancing robot works and some of the theory behind it.

Furthermore we also did a presentation. A link to the poster is available as well: POSTER_GRP12_AUT2_Two_wheeled_robot.pdf

Future improvements
The final product turned out just as we planned, but there is still room for some improvements that we left out due to time constraints.

First of is to replace the current tires, as they are made of solid rubber. I believe it would help replacing these with some pneumatic tires instead in order to reduce vibrations on rough terrain.

Furthermore I would like to mount some encoders, so it would be able to balance on its own. This would allow me to remote control it! This would also allow me to measure the speed of the robot precisely instead of just integrating the PWM-value. Which should make it travel a bit smoother.

If I had to built it again I would consider making a slot for the steering rod, so it did not land on it if the robot fall over. It would also be nice if I could take the steering arm off in order to ease transportation.

I have also considered replacing the deadman switch with some kind of weight enabled mechanism, so you did not have to hold in the deadman button while riding it.

An obvious improvement would also be to upgrade the motors as they are not nearly as powerful as the ones on the Segway – these are 1500W each. This would enable it to handle rough terrain better and allow it to go faster. I would like to try some hub brushless motors so the ride could be as smooth as possible.

Finally I still need to mount the batteries and motor drivers inside some enclosures in order to protect them from water and physical damage.

Also I would like to built some custom motor drivers, as the ones I use have already broken twice. The first time a IC with its marking scrapped off broke and the next time one of the MOSFETs stopped working. I could easily repair it the second time by replacing the MOSFET, but I ended up buying a new motor driver the first time, as it is not open source, so the identity of the IC on the board is unknown!
While driving, the motor drivers does not get hot at all, so I suspect that there is a design flaw on the motor driver. So if Pololu fixes this and open sourced the design, then I might recommend them, but for now you should be aware of these issues.


If you got any questions or comments. Please do not hesitate to leave them below. Also if you want a picture of some details on the robot just tell and I will upload it!

Part list

  1. Anonym
    August 26th, 2014 at 07:02 | #1

    Jeg er dybt imponeret. :-)
    Hvor svært kan det være at efterligne en Segway?
    Håber at I får lidt mediedækning for det er den slags der kunne motivere andre unge til at lave lignende “skøre” ting.
    Godt gået guys.

  2. August 26th, 2014 at 07:13 | #2

    @Anonym
    Haha ja præcis ;) Mange tak!

  3. tirupathi reddy
    August 26th, 2014 at 09:18 | #3

    Hi, nice project, for the given battery specification, how much distance we can travel.
    Thank you

  4. August 26th, 2014 at 18:11 | #4

    @tirupathi reddy
    I’m not sure, as I haven’t tested it, but my guess would be about 10km. But you could easily use more batteries if you like.

  5. roscoopc
    September 8th, 2014 at 21:57 | #5

    Good work! Whit the motor datasheet (450 rpm, 6,7:1 gear ratio) and the wheel diameter I have calculated a maximum speed slightly higher than 4 km/h. It’s correct? If the robot has so much torque is possible enlarge the wheels…
    Ps I’m planning my robot ;-)

  6. September 8th, 2014 at 22:04 | #6

    @roscoopc
    No we have measured a maximum speed of approximately 15 km/h :)

  7. kang
    September 21st, 2014 at 15:36 | #7

    hi, Good work! i’m studying on control system and i have studied the segway’s mechanism.
    I have a question about your work.
    Does your wheel system have tilting motion?
    i can’t know the solution of my question in your video.
    please, let me know.

  8. September 21st, 2014 at 20:33 | #8

    @kang
    What exactly do you mean by tilting motion? The wheels are bolted directly to the motors.

  9. scphil
    September 29th, 2014 at 21:31 | #9

    Hi, ever thought of doing a kick start for the full size? I am looking to see if there is any way to build this for disabled (sitting position)? I assume it would work as long as there is adequate balancing? Any idea what would happen with stairs ? / curbs ?

  10. September 29th, 2014 at 22:13 | #10

    @scphil
    We haven’t any specific plans to do a Kickstarter, but you can never say never ;)

    You can already buy a kit to convert a regular Segway to a balancing wheelchair: http://www.allychair.com/. I believe it can handle smaller curbs fine, but differently not stairs.

  11. tk
    October 1st, 2014 at 11:43 | #11

    Hi…. very fun project. could you tell me change this” Pololu High-Power Motor Driver ” in to DIY IR2184 driver….Thank you

  12. October 2nd, 2014 at 00:40 | #12

    @tk
    Please post a link to the exact driver you are talking about?

  13. tk
    October 2nd, 2014 at 05:40 | #13

    Hi….this link is use ir2184 driver …. http://www.open-electronics.org/discover-openwheels-electronics-and-test-it/
    Because in my cities easily purchase ir2184 .
    Thank you for your answer.
    tk

  14. October 4th, 2014 at 08:41 | #14

    @tk
    Yes that MOSFET seems to be fine.

  15. Thamanoon
    October 18th, 2014 at 06:16 | #15

    Hi, Thank you for your tutorial. I will make a new one with stm32f3discovery board. Can I use android appication to control stm32f3discovery via bluetooth?
    Thanks

  16. October 18th, 2014 at 06:17 | #16

    @Thamanoon
    What do you mean by control? My application simple sends out a data via Bluetooth which are then received on the UART port on the ATmega328P.

  17. October 21st, 2014 at 20:47 | #17

    Hi,
    I decided to build balancing robot with heart from this tutorial, but with completly different body. Posts are written in polish, but I’m also publishing a lot of photos, so I think that will be understandable :). Maybe someone will be inspired with that. Visit: https://www.facebook.com/ZbLaB

  18. October 22nd, 2014 at 03:41 | #18

    @ZbLaB
    Thanks for sharing ZbLab :)

  1. No trackbacks yet.