The Breadboarded Self Balancing Robot

by maker_ATOM in Circuits > Robots

14844 Views, 217 Favorites, 0 Comments

The Breadboarded Self Balancing Robot

IMG20210915125302.jpg
The Breadboarded Self Balancing Robot | Demonstration

Being a Robotics enthusiast I always wanted to build a Self Balancing Robot but never build untill now.

Self Balancing Robots are not a new thing to the world, what makes this build different from other Self Balancing Robots is the compact design and modularity of the build. The robot can be build by just plugging in various modules and can be assembled in a matter of minutes.

So let's build one.

The Idea!

model2.PNG
idea1.PNG

The Breadboard

A PCB is generally used to connect electronic components together but as we want our build to be modular and easy to assemble, the best way to do so is to use a breadboard. We will use 2 mini breadboards to connect everything electrically.

Micro-controller

Micro-controller board which we will use to control the motors, sense the angle of tilt and to implement PID algorithm will be Arduino Nano. The processing power of atemga328 (the micro-controller around which Arduino Nano is developed) is just enough and its all pins are breadboard compatible.

Motion tracking Device

To measure the tilt angle we will use MPU6050 a motion tracking device which has 3 axis accelerometer and 3 axis gyroscope and will use a complimentary filter to combine measurements from accelerometer and gyroscope to get noise free and stable angle values.

Motors

Motors used for this build will be 12V 300RPM N20 micro gear motors with compatible wheels and mounting brackets.

Motor Driver

To drive the motors we will be using L293d motor driver. This driver has two full H-bridge driver in a single DIP-package perfect for our application.

Miscellaneous

A 3D printed support will be used to hold things all together and jumper wires will used to connect everything electrically.

Supplies

Electronics Components:

  • Mini breadboard ____________________ x 2 Link
  • Arduino Nano ______________________ x 1 Link
  • MPU6050 _________________________ x 1 Link
  • L293D motor driver - DIP package ______ x 1 Link
  • N20 micro gear motor - 12V 300 RPM ___ x 2 Link
  • N20 motor brackets__________________ x 2 Link
  • Compatible N20 motor wheels _________ x 2 Link
  • 9V batteries________________________ x 2

Supplies

  • Single strand wires - multi colors
  • 3D printer/ printing service
  • Male pin headers
  • Battery snap connector
  • Zip ties
  • Jumper wires
  • 12V power supply
  • dc jack to screw terminal
  • Rubber band

Tools

  • Solder iron
  • Solder wire
  • Plier

A Bit of Theory

IMG_20210915_142127.jpg
IMG_20210915_142834.jpg
20210914_224444.jpg

Working of the Robot

A self Balancing Robot tries to balance itself by some how counter acting the force of gravity acting on it's center of mass. To generate the counter acting force it uses motors.

You can imagine as when we try to balance a stick on our palm we move the base of stick which is resting on our palm to balance it. Same does the Robot, it moves its base using motors wheels.

What is PID?

PID stands for Proportional Integral Derivative. It is a control loop mechanism. What it basically does is continuously monitor the robot tilt angle and controls the motor speed to balance.

What is Complementary Filter?

There two ways we can measure the tilt angle using MPU6050, either by using its accelerometer or by using its gyroscope. The issue with these two is, accelerometer is susceptible to noise and measurements from gyroscope drift from actual values with time. So to avoid these, we combine both the values and filter out the errors using a complementary filter.

Preparing Arduino Nano - the Drivers

s1.PNG
s3.PNG
s4.PNG

If you get the original Arduino Nano it wont be any problem but if you get the clone version of Arduino Nano the computer may not detect the board which uses CH340G chip, a USB to serial converter if in case the driver are not installed or updated.

Having a clone version of Arduino Nano will be fine, it work the same as original.

  • Install the executable file. Download from Here.
  • Run it.
  • Click uninstall then install, to remove any older version residing.
  • To check if everything worked fine go to device manager and plug-in Arduino Nano.
  • The chip and hence the board should be detected in PORTS sub-menu.

Preparing Arduino Nano - Pin Headers

IMG_20210829_20583588.jpg
IMG20210814135836.jpg
IMG20210829212500.jpg
IMG_20210829_20525997.jpg

Arduino Nano has a lot of GPIOs to be used and we wont be using all of them either. Instead of soldering all pin headers we will solder only those pin which are being utilized. This way we get enough room for the jumper wire to route around the breadboard.

The pin which we are going to solder and hence we will use for the build are:

  • VIN
  • GND _____ (both)
  • 5V
  • A4 _______ (SDA)
  • A5 _______ (SCL)
  • D5 _______ (M1power)
  • D6 _______ (M2power)
  • D8 _______ (M1enable)
  • D9 _______ (M2enable)
  • D10 ______ (M2direction)
  • D11 ______ (M1direction)
  • D2, D3, D7 _ (for future use)

Preparing MPU6050

IMG20210814145134.jpg
schematic.PNG
IMG20210830115728.jpg
IMG20210830115806.jpg
IMG20210814145046.jpg

MPU6050 uses I2C communication to transfer the measured data to Arduino Nano.

Solder pin headers to pins VCC, GND, SCL, SDA. We wont we using the remaining pins.

Place the MPU on the second breadboard.

Connect:

___MPU6050__-__Arduino Nano___

  • __VCC ___-______ 5V________
  • __GND___-_____ GND _______
  • __SCL ___-______ A5 ________
  • __SDA ___-______ A4 ________

Library for MPU6050

1s.PNG
5s.PNG
3s.PNG
4s.PNG

As MPU6050 uses I2C communication we could use the Wire library and read each data byte by byte and interpret later, this will make the code more longer and hard to debug.

So instead we will use a library developed by Jeff Rowberg.

  • Head on to this link.
  • Download the ZIP file.
  • Extract the contents of ZIP file.
  • Open the folder and navigate to Arduino folder inside i2cdevlib-master folder
  • Copy MPU6050 and i2cdev folder
  • And paste in libraries folder where all external libraries are stored, for windows it is documents folder
  • Restart Arduino IDE and the libraries should be visible.

Preparing Batteries

IMG20210824220403.jpg
IMG20210824220546.jpg
IMG20210824222501.jpg
IMG20210824213900.jpg
IMG20210824214028.jpg
IMG20210824214203.jpg
IMG20210824222400.jpg
IMG20210824222346.jpg
IMG20210824215121.jpg

As the power source for the robot we will be using two 9V non-rechargeable batteries. Having non-rechargeable makes the build more simple or in other case the rechargeable batteries require extra charging circuitry.

The reason to use two batteries one for motors and other for logic devices (Arduino Nano, MPU6050) is that sometimes the motor induce power surges which may lead to resetting of Arduino Nano.

  • Cut the snap connector's wire to 40mm length.
  • Trim the insulation to expose the wire and bend it.
  • Separate a 1x2 male pin header.
  • Place them on breadboard and solder the battery snap connector to pin header.
  • Ensure the wire bend before soldering because the way they go to battery from pin headers.

We used 1x2 pin header for 1st battery because the pins VIN and GND on Nano are adjacent to each other, but in case of L293d the motor power and GND pins are not adjacent but instead have two pins in between them. We can use two 1x1 pin headers but we will instead use 1x4 and will remove the middle two pins from the spacer.

If we use 2 separate 1x1 pin header, they begin not attached to each other can lead to shorts.

  • Cut and trim snap connector with 35mm length.
  • Separate 1x4 pin header.
  • Now using a plier remove the middle pin from pin header.
  • Solder the wires from snap connector to pin header keeping the wires bend.

Electric Connections

schematic.PNG
IMG20210910091249.jpg
IMG20210910091416.jpg
IMG20210910091957.jpg

After preparing Arduino Nano and MPU6050 by soldering necessary pin headers, now is the time to connect every module and ICs to each other electrically.

  • First connect the two mini breadboard vertically using the male female part provided.
  • Then cut out single strand wire of different colors.
  • I used RED for VCC
  • BLACK for GND
  • YELLOW for I2C
  • WHITE for enable pins.
  • BLUE for right motors inputs and outputs.
  • and GREEN for left motor input and outputs.

Using color coded wires helps in debugging and also makes the build look more attractive.

  • Remove insulation from every wire piece from both the end so that wires can be inserted in breadboard.
  • Now bend the wires and connect to the breadboard as in above pictures.

By doing so we connect the following pins to each other.

_____Arduino Nano__-__MPU6050__-__L293d______

  • ______5V_____ to____Vcc____to____pin 16____
  • _____GND_____-____GND____-____pin 4_____
  • ____A4(SDA)___-____SDA ____-_____________
  • ____A5(SCL)___-____SCL_____-_____________
  • ______D5 _____- ____________-____pin 2_____
  • ______D6 _____-____________ -____pin 15____
  • ______D8 _____-____________ -____pin 1_____
  • ______D9 _____-____________ -____pin 9_____
  • ______D10 ____-____________ -____pin 10____
  • ______D11 ____-____________ -____pin7______

We haven't connected the battery and motors to the build we will do so in the next steps.

3D Prints

IMG20210830161330.jpg
3d print.PNG

I 3D designed the chassis/support in fusion 360.

The wall thickness has been purposefully set to1.6mm so that when printed with standard printer of 0.4mm nozzle everything fuses perfectly.

Parameters:

  • 0.4mm nozzle
  • 0.2mm layer height
  • 20% infill
  • Black PLA
  • Total time - 2hrs

Downloads

Assembly - Installing Brackets

IMG20210830161530.jpg
IMG_20210831_091556.jpg
IMG_20210831_091633.jpg
IMG_20210831_091700.jpg
IMG_20210831_091736.jpg
IMG20210831093925.jpg
IMG20210831093836.jpg

Lets first mount the brackets for N20 motors.

  • First insert m2 nut in the section provided in the brackets.
  • Insert the bolt in 3d print from above and screw the bracket to the support.
  • Don't tighten up the nut bolts completely as we have to insert N20 motors in them.

Installing Motors

IMG20210910114725.jpg
IMG20210910114740.jpg
IMG20210910114750.jpg
IMG20210910114804.jpg

The purpose to first install brackets is, it becomes a bit difficult to handle the motor, bracket, and to bolt them down at one go.

  • As we haven't bolted the brackets tightly, the motors just slide into the bracket.
  • Make sure to insert the motors from outside and the back of motor should go first.
  • If it becomes a bit hard to slide the motor try loosening the bolt a little more.

Installing the Breadboard

IMG20210910120358.jpg
IMG20210910120543.jpg
IMG20210910120419.jpg
IMG20210910120610.jpg

Installing breadboard and batteries is fairly easy as they both slide into support from above.

Make sure USB of arduino nano faces down, to match the orentation

Preparing Motors

IMG20210910112440.jpg
IMG20210830213439.jpg
assembly.PNG
IMG20210830214734.jpg
IMG20210830215128.jpg
IMG_20210903_200833.jpg
IMG20210831093349.jpg
IMG20210910113924.jpg
IMG20210910114019.jpg

The reason why we are connecting motors after the assembly is, if we had to solder the wires to motors before assembly then we would need a 3rd hand or any kind of rig to hold the motors and wires so if the motors are first fixed to build it would be easy to solder them as one end will be attached to breadboard and other to the motor terminal.

We will use single strand wire as well to connect motors as they remain sturdy as compared to multi stranded ones.

  • First cut single strand wire of green and blue color to color code the motors.
  • Remove the insulation from both the ends of wire.
  • Now take a green wire piece and insert in breadboard where it will connect to pin 3 of L293d
  • And solder the other end to the nearest terminal of motor.
  • Similarly connect the remaining 3 motor terminals to the breadboard using single strand wires.

Connections:

  • Left_Motor_terminal_1 ----> L293d pin 3
  • Left_Motor_terminal_2 ----> L293d pin 6
  • Right_Motor_terminal_1 --> L293d pin 11
  • Right_Motor_terminal_2 --> L293d pin 14

Done With Assembly

IMG_20210915_145441.jpg

Once we install the wheels on motor shafts we are complete with the assembly.

The battery might fall off when the robot is tilted, so to secure it firmly we can zip tie or we can use a rubber band.

The Code

library for pid.PNG

To implement PID controller we will use library by Brett Beauregard. It can be installed from library manger of Arduino IDE itself.

The logic of code is fairly simple.

  • We first receive data from MPU6050.
  • Interpret it to get the tilt angle from each accelerometer and gyroscope.
  • Then implement the complementary filter to combine values from both.
  • Then we call the PID.compute function to calculate the output
  • And we power the motor based on output sign and its value.

The complete code is here.

//Include necessary libraries
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>
#include <PID_v1.h>

//define macros
#define LeftMotorDir 11
#define LeftMotorPower 5
#define RightMotorDir 10
#define RightMotorPower 6

#define LeftMotorEnable 8
#define RightMotorEnable 9

//the angle where the robot is stable
double Setpoint = -0.75;

double Input, Output;

//PID controllers
double Kp = 4.6;
double Kd = 0.04;
double Ki = 1;

//required variables
int accY, accZ, gyroX;
float accAngle = 0, gyroAngle = 0, previousAngle = 0;
float gyroRate = 0;
int val = 0;

//instance of class PID
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

//instance of class MPU6050
MPU6050 mpu;

/*.............................SETUP.................................*/
/*...................................................................*/

void setup()
{
  //initializing MPU6050
  mpu.initialize();

  //setting the pinmodes
  pinMode(LeftMotorEnable, OUTPUT);
  pinMode(LeftMotorDir, OUTPUT);
  pinMode(LeftMotorPower, OUTPUT);

  pinMode(RightMotorEnable, OUTPUT);
  pinMode(RightMotorDir, OUTPUT);
  pinMode(RightMotorPower, OUTPUT);

  //making enable pin high
  digitalWrite(LeftMotorEnable, HIGH);
  digitalWrite(RightMotorEnable, HIGH);

  //setting PID parameters
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-255, 255); // may change (50,255);
  myPID.SetSampleTime(5); //how often pid is evaluated in millisec
  myPID.SetControllerDirection(REVERSE);

  //initialize the timer
  initTimer2();

}

/*..............................LOOP.................................*/
/*...................................................................*/

void loop() {

  accZ = mpu.getAccelerationZ();
  accY = mpu.getAccelerationY();

  gyroX = mpu.getRotationX();

  accAngle = atan2(accZ, -accY) * RAD_TO_DEG;

  gyroRate = gyroX / 131;

  Input = 0.97 * (previousAngle + gyroAngle) + 0.03 * (accAngle);
  previousAngle = Input;

  myPID.Compute();

  if (Output > Setpoint)
  {
    digitalWrite(LeftMotorDir, LOW);
    digitalWrite(RightMotorDir, LOW);
    val = map(Output, 0, 255, 18, 255);
    analogWrite(LeftMotorPower, val);
    analogWrite(RightMotorPower, val);
  }

  if (Output < Setpoint)
  {
    digitalWrite(LeftMotorDir, HIGH);
    digitalWrite(RightMotorDir, HIGH);
    val = map(Output, -255, 0, 0, 237);
    analogWrite(LeftMotorPower, val);
    analogWrite(RightMotorPower, val);
  }
}


/*................... ........ISR_TIMER2.............................*/
/*...................................................................*/

ISR(TIMER2_COMPA_vect)
{
  gyroAngle = (float)gyroRate * 0.001;
}

/*...........................iniTimer2...............................*/
/*...................................................................*/

void initTimer2()
{
  //reset timer2 control register A
  TCCR2A = 0;

  //set CTC mode
  TCCR2A |= (1 << WGM21);
  TCCR2A &= ~(1 << WGM20);
  TCCR2B &= ~(1 << WGM22);

  //prescaler of 128
  TCCR2B &= ~(1 << CS21);
  TCCR2B |= ((1 << CS22) | (1 << CS20));

  //reset counter
  TCNT2 = 0;

  //set compare register
  OCR2A = 125;

  //enable timer1 compare match interrupt
  TIMSK2 |= (1 << OCIE2A);

  //enable global interrupt
  sei();
}

Are We Done?

IMG20210915144914.jpg

A mistake I made and so you should avoid in your future builds.

While choosing the power source for build I did not consider if the battery is capable of suppling the utmost current possible for the motor to work properly. Though a dc motor can run on voltage level significant below from rated ones, the 9V battery was not able to provide enough current to motors to work up to mark.

I realised this mistake when assembly was complete and I headed for testing.

So we need to shift to external power source. A 12V lab bench power supply or a wall mount adapter works best as they can provide enough current to work.

If not using the 2nd 9V battery then why keep in the build?

We need to do this because if we remove the 2nd battery it will lead to lowering of the center of mass of the bot and hence will also be difficult to balance. So the 2nd battery just acts as a dead weight.

Final Thoughts!!

It was not a straight forward process to design and build this self balancing robot. Apart from power source everything wad just perfect. In the upcoming version we will fix the power supply and will try to increase the recovery angle of the robot which in this case was very low.

Do follow me on Instagram