Balancing Robot

The Arduino SDK  https://www.arduino.cc/en/Main/Software has been updated since I last worked on this, and the latest version gave me this error when compiling.
This was due to where the libraries were.

libraries\MPU6050\xxxI2Cdev.cpp.o (symbol from plugin): In function `I2Cdev::I2Cdev()’:
(.text+0x0): multiple definition of `I2Cdev::I2Cdev()’

You won’t get an error if you put the header files in with the program file like so

But if like me you prefer to keep your libraries in the Arduino Libraries folder
and add them using the Include Library tab like this

Then
because the header file MPU6050_6Axis_MotionApps20.h already includes (#include”I2Cdev.h”)

#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_
#define _MPU6050_6AXIS_MOTIONAPPS20_H_
#include “I2Cdev.h”
#include “helper_3dmath.h”
// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board
#define MPU6050_INCLUDE_DMP_MOTIONAPPS20

#include “MPU6050.h”

you may see the above error. The compiler looks for I2Cdev.h in the MPU6050 folder
but its not there! So copy I2Cdev.cpp & I2Cdev.h from I2Cdev Folder to
the MPU6050 Folder then add libraries….

Shopping list of objects you will need.
1.  Compatible Nano V3.0 – ATmega328

2.  L298N DC Stepper Motor Dual H Bridge

3. MPU-6050 3 Axis Gyroscope And Accelerometer
To calibrate your MPU-6050 watch this  https://www.youtube.com/watch?v=nlXqIe9-R7s  not a little helpful

4. SYB-170  Breadboard

5. Smart Car Robot Wheels

6.  10V 3900uf Capaictor

7. Ferrite core noise filters 25mm long 5mm core hole

You will need the I2Cdev & MPU6050  files available here  https://github.com/jrowberg/i2cdevlib/tree/master/Arduino
courtesy Jeff Rowberg

//   Most of this code is other peoples read below!!
// the bits I have hacked are indicated thusly//********************************************************************************************************************************************************
// MY STUFF

// i found PlyAlex  https://www.youtube.com/watch?v=nlXqIe9-R7s  not a little helpful
//
// if you get the   ERROR NO LIBRARY FOUND   edit sketch book location in File-> Preferences
// default location of sketch book is not where you think it is.

//   Most of this code is other peoples read below!!
// the bits I have hacked are indicated thusly

//********************************************************************************************************************************************************
// MY STUFF

// i found PlyAlex  https://www.youtube.com/watch?v=nlXqIe9-R7s  not a little helpful
//
// if you get the   ERROR NO LIBRARY FOUND   edit sketch book location in File-> Preferences
// default location of sketch book is not where you think it is.

//*********************************************************************************************************************************************************

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//      2013-05-08 – added seamless Fastwire support
//                 – added note about gyro calibration
//      2012-06-21 – added note about Arduino 1.0.1 + Leonardo compatibility error
//      2012-06-20 – improved FIFO overflow handling and simplified read process
//      2012-06-19 – completely rearranged DMP initialization code and simplification
//      2012-06-13 – pull gyro and accel data from FIFO packet instead of reading directly
//      2012-06-09 – fix broken FIFO read sequence and change interrupt detection to RISING
//      2012-06-05 – add gravity-compensated initial reference frame acceleration output
//                 – add 3D math helper file to DMP6 example sketch
//                 – add Euler output and Yaw/Pitch/Roll output formats
//      2012-06-04 – remove accel offset clearing for better results (thanks Sungon Lee)
//      2012-06-01 – fixed gyro sensitivity to be 2000 deg/sec instead of 250
//      2012-05-30 – basic DMP initialization working

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include “I2Cdev.h”

#include “MPU6050_6Axis_MotionApps20.h”
//#include “MPU6050.h” // not necessary if using MotionApps include file

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include “Wire.h”
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <– use for AD0 high

/* =========================================================================
NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
depends on the MPU-6050’s INT pin being connected to the Arduino’s
external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
digital I/O pin 2.
* ========================================================================= */

/* =========================================================================
NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
when using Serial.write(buf, len). The Teapot output uses this method.
The solution requires a modification to the Arduino USBAPI.h file, which
is fortunately simple, but annoying. This will be fixed in the next IDE
release. For more info, see these links:

http://arduino.cc/forum/index.php/topic,109987.0.html
http://code.google.com/p/arduino/issues/detail?id=958
* ========================================================================= */

// uncomment “OUTPUT_READABLE_QUATERNION” if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION

// uncomment “OUTPUT_READABLE_EULER” if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER

// uncomment “OUTPUT_READABLE_YAWPITCHROLL” if you want to see the yaw/
// pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL

// uncomment “OUTPUT_READABLE_REALACCEL” if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL

// uncomment “OUTPUT_READABLE_WORLDACCEL” if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
//#define OUTPUT_READABLE_WORLDACCEL

// uncomment “OUTPUT_TEAPOT” if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { ‘$’, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, ‘\r’, ‘\n’ };
//*************************************************************************************************************************************************************************
//                                                 MY Variables

float OldP = 0;         // Previous value used to calculate change in P //  DELTA P
float P = 0;            //  Proportional component
float I = 0;            //  Integral        just the sum of P over time
float OldI = 0;         //  previous value of I for calculation of Delta I
float D = 0;            //  Differential       D = P – OldP
float bp = -60;         // balance point
float pwm = 0;          // value of Pulse Width Modulation  to ENA ENB
long a = 0;             // L298N to IN 1 to 4
long b = 0;             //
const int PinR1 = 5;    //  arduino  pin 5 to l298  pin IN4
const int PinR2 = 6;    //  arduino  pin 6 to l298  pin IN3
const int PinL1 = 7;    //  arduino  pin 7 to l298  pin IN1
const int PinL2 = 8;    //  arduino  pin 8 to l298  pin IN2
const int PwmR  = 9;    //  arduino  pin 9 to l298  pin ENB
const int PwmL  = 10;   //  arduino  pin 10 to l298  pin ENA
//****************************************************************************************************************************************************

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
//*********************************************************************************************************************************************************
// arduino to l298 pins hopefully self explanatory
pinMode(PinR1,OUTPUT);
pinMode(PinR2,OUTPUT);
pinMode(PinL1,OUTPUT);
pinMode(PinL2,OUTPUT);
//**********************************************************************************************************************************************************
// join I2C bus (I2Cdev library doesn’t do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif

// initialize serial communication
// (115200 chosen because it is required for Teapot Demo output, but it’s
// really up to you depending on your project)
Serial.begin(57600);
while (!Serial); // wait for Leonardo enumeration, others continue immediately

// NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
// Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
// the baud timing being too misaligned with processor ticks. You must use
// 38400 or slower in these cases, or use some kind of external separate
// crystal solution for the UART timer.

// initialize device
Serial.println(F(“Initializing I2C devices…”));
mpu.initialize();

// verify connection
Serial.println(F(“Testing device connections…”));
Serial.println(mpu.testConnection() ? F(“MPU6050 connection successful”) : F(“MPU6050 connection failed”));

//****************************************************************************************************************************************
//     Commented out so that program dose not wait for imput,but gets straight to work
/*
// wait for ready
Serial.println(F(“\nSend any character to begin DMP programming and demo: “));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available());                 // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
*/
//*****************************************************************************************************************************************
// load and configure the DMP
Serial.println(F(“Initializing DMP…”));
devStatus = mpu.dmpInitialize();

// supply your own gyro offsets here, scaled for min sensitivity
//****************************************************************************************************************************************
//  use calibration program to get your own values
mpu.setXGyroOffset(44);//(220);
mpu.setYGyroOffset(-21);//(76);
mpu.setZGyroOffset(-30);//(-85);
mpu.setXAccelOffset(-1875);//(1788); // 1688 factory default for my test chip
mpu.setYAccelOffset(-1426);
mpu.setZAccelOffset(2215);
//****************************************************************************************************************************************
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it’s ready
Serial.println(F(“Enabling DMP…”));
mpu.setDMPEnabled(true);

// enable Arduino interrupt detection
Serial.println(F(“Enabling interrupt detection (Arduino external interrupt 0)…”));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it’s okay to use it
Serial.println(F(“DMP ready! Waiting for first interrupt…”));
dmpReady = true;

// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it’s going to break, usually the code will be 1)
Serial.print(F(“DMP Initialization failed (code “));
Serial.print(devStatus);
Serial.println(F(“)”));
}

// configure LED for output
pinMode(LED_PIN, OUTPUT);

}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
// if programming failed, don’t try to do anything
if (!dmpReady) return;

// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// other program behavior stuff here

}

// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();

// get current FIFO count
fifoCount = mpu.getFIFOCount();

// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F(“FIFO overflow!”));

// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);

// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;

#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

//*********************************************************************************************************************************************************************
//                                                                      My Code
// PID control based on Pseudocode from https://en.wikipedia.org/wiki/PID_controller
// and the balance point idea from https://www.youtube.com/user/jmhrvy1947

OldP =P;                     // save value of P
P = (ypr[2] * 1000) + bp;    // update P from MPU add bp to correct for balance
OldI = I;                    // save old I
I = I + (P * 0.05) ;
I = I + ((I – OldI)*2  );     // calulate new I
if( I >  250 ) I =  250;           // LIMIT  Stop I building up too high
if( I < -250 ) I = -250;           // or too low value
D = P – OldP;                      //  D differential   change in P
pwm = ( P * 1 ) + ( I  ) + ( D * 10 ) ; // P I D

a = 0;
b = 0;
if(pwm < 0){
a = 0;
b = 1;
bp = bp – 0.01;
digitalWrite(13, 0);
}
if(pwm > 0){
a = 1;
b = 0;
bp = bp + 0.01;
digitalWrite(13, 1);
}
/////////////////////////////
// remove sign from PWM as – value has no meaning
pwm  = abs(pwm);
if ( pwm < 0) pwm = 0;
if ( pwm > 255) pwm = 255;

if(abs(ypr[2]) < abs(1.1)){
analogWrite(PwmR, pwm);
digitalWrite(PinR1, a);
digitalWrite(PinR2 ,b);

analogWrite(PwmL ,pwm);
digitalWrite(PinL1 ,a);
digitalWrite(PinL2 ,b);
}
else{
analogWrite(PwmR , 0);
analogWrite(PwmL , 0);
I = 0;
bp = -98;
delay(1000);
}

//********************************************************************************************************************************************************
#endif
}
}

Self-Balancing Two-Wheel Robot Is Controlled By Android

ANDROID APK

apk download link:

ROBOT  PARTS

-Plastic Tire Wheel with DC 3-6V Gear Motor for Robot 65*27MM   x2

-UNO R3 MEGA328P ATMEGA16U2 Development Board   x1
-Plastic Box For Robotic Body   x2

-Pololu TB6612FNG Dual Motor Driver
-MPU6050 6 Axis Acceleration and Gyro Sensor
-HC-05 Bluetooth Module
-Samsung ICR18650-22F 2200mAh(Green)Battery

Circuit  Diagram

ARDUINO CODES

arduino code download link:
denge_robot

Kod listesi

Franko – Arduino Self Balancing Robot

My latest Arduino DIY project is a self balancing robot.

Arduino Uno R3 microcontroller board is used for this project. MPU6050, an 6DOF IMU (with accelerometer and gyroscope) is used to get the angle and L298N motor controller board controls the 2 motors.

The motors are 12V 122rpm and the wheels are 8cm in diameter.

Robot size is 17x10x30 cm. Three plexiglas plates are used to hold the frame and parts. Standard PID controller is used to control the robot. To tune the PID controller parameters 3 potentiometers are used.

You may find the Arduino sketch and libs on my GitHub repo: https://github.com/lukagabric/Franko

Parts:
1 x Arduino Uno R3
1 x MPU6050 (IMU)
1 x L298N Motor Driver Controller
2 x 12V 122 RPM Gear Motors + 80mm Wheels
3 x 10k Potentiometer

Two-wheel self-balancing robot

After my first fast made self balancing robot, I want to better understand it and especially to try different control methods. For me it is necessary to simulate the whole stuff on computer (robot + control law).

The first step is therefore to model the robot with mathematical equations. Because of the complexity of the model I do make some assumption and simplification.

The model is separated into three part: the DC motor, the wheel and the inverted pendulum

The DC motor

electrical model:

motor

Va=Ldidt+VEMF+iRVa=Ldidt+VEMF+iR

wtih

VEMF=keωVEMF=keω

equation of motion for the motor:rotor

Irω˙=τmτaτfIrω˙=τm−τa−τf

with

τm=kmiτm=kmi
τf=kfωτf=kfω

If the motor inductance and friction torque are neglected, then

dwdt=kmkeIrRω+kmIrRVa1Irτadwdt=−kmkeIrRω+kmIrRVa−1Irτa

in state space form:

[θ˙ω˙]=[001kmkeIrR][θω]+[0kmIrR01Ir][θ˙ω˙]=[010−kmkeIrR][θω]+[00kmIrR−1Ir]

The inputs to the motor is the applied voltage and applied torque on the rotor.

The wheel

text4756-4

in horizontal (x direction):

Mwx¨=NfNMwx¨=Nf−N

rotation equation around the center of the wheel:

Iwθω¨=τmNfrIwθω¨=τm−Nfr

by using motor dynamic equations, one can get

Nf=Iwrωw˙kmkerRωw+kmrRVaNf=−Iwrωw˙−kmkerRωw+kmrRVa

with

ωw=θw˙ωw=θw˙

then

Mwx¨=Iwrωw˙kmkerRωw+kmrRVaNMwx¨=−Iwrωw˙−kmkerRωw+kmrRVa−N

Above equation is valid for both wheels.

With following equations, one can translate the angular rotate to linear motion:

rωw˙=rθw¨=x¨rωw˙=rθw¨=x¨
rωw=rθw˙=x˙rωw=rθw˙=x˙

then

Mwx¨=Iwr2x¨kmker2Rx˙+kmrRVaNMwx¨=−Iwr2x¨−kmker2Rx˙+kmrRVa−N

After rearrangement, one has:

(Mw+Iwr2)x¨=kmker2Rx˙+kmrRVaN(Mw+Iwr2)x¨=−kmker2Rx˙+kmrRVa−N

The inverted pendulum

pendulum

horizontal:

2N+mlθp˙2sinθp=mlθp¨cosθp+mx¨2N+mlθp˙2sinθp=mlθp¨cosθp+mx¨

The sum of forces perpendicular to the pendulum:

2Ncosθp2Psinθp+mgsinθp=mlθp¨+mx¨cosθp2Ncosθp−2Psinθp+mgsinθp=mlθp¨+mx¨cosθp

The sum of motions around the center of mass of pendulum:

2τm2lNcosθp+2lPsinθp=Ipθp¨−2τm−2lNcosθp+2lPsinθp=Ipθp¨

with

τm=kmkeRω+kmRVa=kmkeRx˙r+kmRVaτm=−kmkeRω+kmRVa=−kmkeRx˙r+kmRVa

one has:

2kmkeRx˙r2kmRVa2lNcosθp+2lPsinθp=Ipθp¨2kmkeRx˙r−2kmRVa−2lNcosθp+2lPsinθp=Ipθp¨

then

2kmkeRx˙r2kmRVa+mglsinθp=Ipθp¨+ml2θp¨+mlx¨cosθp2kmkeRx˙r−2kmRVa+mglsinθp=Ipθp¨+ml2θp¨+mlx¨cosθp

then

Ipθp¨2kmkeRx˙r+2kmRVa+ml2θp¨mglsinθp=mlx¨cosθpIpθp¨−2kmkeRx˙r+2kmRVa+ml2θp¨−mglsinθp=−mlx¨cosθp

and

2(Mw+Iwr2)x¨+mlθp¨cosθp+mx¨=2kmker2Rx˙+2kmrRVa+mlθp˙2sinθp2(Mw+Iwr2)x¨+mlθp¨cosθp+mx¨=−2kmker2Rx˙+2kmrRVa+mlθp˙2sinθp

after arrangement, one can get the following state space expression:

⎡⎣⎢⎢⎢⎢x˙x¨θp˙θp¨⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢000012kmke(T+rml)r2Rα02kmke(ml+rS)r2Rα0m2gl2α0mglSα0010⎤⎦⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢xx˙θpθp˙⎤⎦⎥⎥⎥⎥+⎡⎣⎢⎢⎢⎢⎢02km(rml+T)rRα02km(ml+rS)rRα⎤⎦⎥⎥⎥⎥⎥Va[x˙x¨θp˙θp¨]=[01000−2kmke(T+rml)r2Rα−m2gl2α0000102kmke(ml+rS)r2RαmglSα0][xx˙θpθp˙]+[02km(rml+T)rRα0−2km(ml+rS)rRα]Va

with

S=2Mw+2Iwr2+mS=2Mw+2Iwr2+m
T=Ip+ml2T=Ip+ml2
α=STm2l2α=ST−m2l2

On my first two-wheel self-balancing robot, I didn’t use the encoder for speed measurement.
So it can basically stand still and balance its weight with small movements of its two
wheels simultaneously. I preferred that the robot would work very soon without much effort
and then I could improve it by adding speed control, RC, etc.

1.Hardware

It’s not difficult to gather all the parts. Here is my list:
1.glass fiber board
2.control board (arduino uno)
3.sensor board (MPU6050 gyroscope + accelerameter)
4.two-channel motor driver (L298N)
5.two geared DC motors (25GA370)
6.two toy wheels and fixation kit

Following is my assembly diagram:

assembly

Following is the wiring diagram:

wiring_SBR

In L298N, each motor is controlled by a full bridge circuit (or H-bridge) composed of two legs. Following figure is a simplified diagram coming from wikipedia. S1 and S2 are always controlled in complementary manner. When S1 closes, S2 opens. S1 and S2 close simultaneously is not allowed since that creates a short circuit of the power supply. Idem for S3 and S4.

H-bridge

When S1 and S4 close simultaneously, the motor rotates in one direction. When S3 and S2 close simultaneously, the motor rotates in the other direction. I use PWM control to set the motors’ speed. the switching frequency is about 1kHz which is the default value of Arduino module.

After the wiring, the robot looks like:

2.Control

Then comes the control part. The following figure shows the control diagram. Only the inner
loop in blue is implemented this time. I use it to regulate the tilt angle of the robot. As
I want the robot stands straight, I simply set the reference angle (REF_ANGLE) to 0. The
gyro+acc sensor gives the information needed to calculate the actual tilt angle. The error
between the reference and the measurement is used by the PID controller to give the command
to the robot (the two wheel motors).

loop

2.1 PID controller

The PID controller is a complexe topic. With google you can find tons of material about it.
Fortunately it is relatively simple to implement it in a microcontroller. With some basic
understanding and tuning techniques, one can make it work very easily.

The general mathematical form of the PID controller is (extracted from wikipedia):

Here is a simple software loop that implements a PID algorithm (extracted from wikipedia):

previous_error = 0
integral = 0 
start:
  error = setpoint - measured_value
  integral = integral + error*dt
  derivative = (error - previous_error)/dt
  output = Kp*error + Ki*integral + Kd*derivative
  previous_error = error
  wait(dt)
  goto start

The purpose of the PID controller is to generate a suitable command to the system (the self
balancing robot in this case) so that the system is stable and reactive. There are some
creteria of both the static and dynamic performance. But they are out of the scope. The PID
controller uses three parameters to do the job, the proportional (Kp), integral (Ki),
derivative(Kd) parameter. The big Kp makes the tilt angle error small and the reaction fast. The
Ki makes the static angle error dispear. This is important since I want the robot stands
straight (tilt angle=0) all the time. I choose to put Kd=0 because Ki and Kp achieve
perfectly my desired performance. So in fact I use a PI controller. For the PI parameter
tuning, I follow Ziegler-Nichols method that you can find on wikipedia. Following table is
copied from wikipedia. It works well for me.

PID_ZN

2.2 Tilt angle measurement

A sensor combining a gyroscope and an accelerometer is used to measure the tilt angle. The sensor don’t give the angle directly. Some calculation is needed. I use MP6050 as sensor. You can check its datasheet for more information.

The accelerometer gives the acceleration (unit g) in three dimension. If the robot is perpendicular to the earth (z axis for example), you should have only Z axis which is not zero. If you have another axis not equaling zero besides Z axis in static state, it means the robot has a none zero tilt angle. And you can get easily the tilt angle based on these two axis acceleration. However using accelerometer to get the tilt angle in this way is valid only for static state since we suppose that only gravity acts on the robot. When the two wheels act a force on the robot, the accelerometer can measure the resulting acceleration as well! In consequence, the measures are very noised. The good point is it is accurate in long period of time (or in DC after filtering).

The gyroscope measures the angle speed (unit deg/s) in three dimension. In order to get the angle, we need to do the integration of it. It is accurate dynamically (in short period). But the integration action accumulates the error of measurement, which makes the result drift in long period of time.

I use a complementary filter to combine the two sensor measurements. It is simple and needs little microcontroller calculation. It works well for me (so far). One can implement kalman filter for optimal control. But the knowledge of the system model and more calculation capability are required. It needs definitely more effort. I use following complementary filter to get the tilt angle estimation:

3.Software

The sensor communicates to the microcontroller through I2C bus. By using the WIRE library of arduino, it is easy to read the data. I use analogWrite function to set PWM duty cycle for the motor driver L298N. The command (PID controller’s output) is a value between -255 and 255. Positive sign means the robot moves forward. 255 represents the max speed (100% duty cycle for the first half bridge). I use anti-windup code to prevent the command to be higher than 255 (or lower than -255) which is the limit of PWM register (8 bits) max value.

The calibration of the sensor should be done generally. I calibrated the gyroscope because I see big static offset. My accelerometer’s offset is not obvious. I use 10ms as sampling time.

The total code has only about 50 lines which I believe possible to be optimized. It’s simple, right? :)

4.Conclusion

The robot resists relatively well the disturbance from both sides. The stability and dynamic response are satisfactory. The next step is to install an encoder on each motor, to make the robot possible to move and to add a remote control. Following is a video of it standing still.

 

How to Build an Arduino Self-Balancing Robot

By Roland Pelayo

Ever wonder how Segways work? This tutorial will show you how to build an Arduino self-balancing robot that balances itself — just like a Segway!

How Does Balancing Work?

To keep the robot balanced, the motors must counteract the fall of the robot. This action requires a feedback and a correcting element. The feedback element is the MPU6050 gyroscope + accelerometer, which gives both acceleration and rotation in all three axis (MPU6050 I2C basics) which is used by the Arduino to know the current orientation of the robot. The correcting element is the motor and wheel combination.

Required Materials

  • Arduino (UNO or Nano can be used. I used Nano for this project.)
  • MPU6050 gyro+accelerometer breakout board.
  • L298N driver module
  • 2 x Geared DC Motor+wheels
  • Three platforms (PCB, acrylic, or thick plastic)
  • Posts to hold the platforms
  • Jumper wires
  • Headers
  • Battery Pack

 

Connection Diagram

Complete Fritzing diagram

Connect the MPU6050 to the Arduino first and test the connection using the codes in this IMU interfacing tutorial.  If data is now displayed on the serial monitor, you’re good to go! Proceed to connect the rest of the components as shown above.

The L298N module can provide the +5V needed by the Arduino as long as its input voltage is +7 V or greater.  However, I chose to have separate power sources for the motor and the circuit for isolation. Note that if you are planning to use a supply voltage of more than +12V for the L298N module, you need to remove the jumper just above the +12V input.

Building the Robot

Robot frame (made mostly of acrylic slab) with two geared dc motors

Main circuit board consisting of an Arduino Nano and MPU6050

L298N motor driver module

Geared DC motor with wheel

 

The self-balancing robot is essentially an inverted pendulum. It can be balanced better if the center of mass is higher relative to the wheel axles. A higher center of mass means a higher mass moment of inertia which corresponds to lower angular acceleration (slower fall). This is why I’ve placed the battery pack on top. The height of the robot, however, was chosen based on the availability of materials.

Completed self-balancing robot. At the top are six Ni-Cd batteries for powering the circuit board. In between the motors is a 9V battery for the motor driver.

 

More Self-balancing Theories

In control theory, keeping some variable (in this case, the position of the robot) steady needs a special controller called a PID: P for proportional, I for integral, and D for derivative. Each of these parameters has “gains” normally called Kp, Ki, and Kd.

PID provides correction between the desired value (or input) and the actual value (or output). The difference between the input and the output is called “error”. The PID controller reduces the error to the smallest value possible by continually adjusting the output. In our Arduino self-balancing robot, the input (which is the desired tilt, in degrees) is set by software. The MPU6050 reads the current tilt of the robot and feeds it to the PID algorithm which performs calculations to control the motor and keep the robot in the upright position.

PID requires that the gains Kp, Ki, and Kd values be “tuned” to optimal values. Engineers use software like MATLAB to compute these values automatically. Unfortunately, we can’t use MATLAB in our case because it would further complicate the project. We will tune the PID values manually instead. I’ve outlined the steps on how to do this:

    1. Make Kp, Ki, and Kd equal to zero.
    2. Adjust Kp. Too little Kp will make the robot fall over (not enough correction). Too much Kp will make the robot go back and forth wildly. A good enough Kp will make the robot slightly go back and forth (or oscillate a little).
    3. Once the Kp is set, adjust Kd. A good Kd value will lessen the oscillations until the robot is almost steady.  Also, the right amount of Kd will keep the robot standing even if pushed.
    4. Lastly, set the Ki. The robot will oscillate when turned on even if the Kp and Kd are set but will stabilize in time. The correct Ki value will shorten the time it takes for the robot to stabilize.

 

Arduino Self-balancing Robot Code

I needed four external libraries to make this Arduino self-balancing robot work. The PID library makes it easy to calculate the P, I, and D values. The LMotorController library is used for driving the two motors with the L298N module. The I2Cdev library and MPU6050_6_Axis_MotionApps20 library are for reading data from the MPU6050. You can download the code including the libraries in this repository.

#include <PID_v1.h>
#include <LMotorController.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
 #include "Wire.h"
#endif

#define MIN_ABS_SPEED 20

MPU6050 mpu;

// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector

//PID
double originalSetpoint = 173;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;

//adjust these values to fit your own design
double Kp = 50;   
double Kd = 1.4;
double Ki = 60;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

double motorSpeedFactorLeft = 0.6;
double motorSpeedFactorRight = 0.5;
//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 8;
int IN4 = 9;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);

volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
 mpuInterrupt = true;
}


void setup()
{
 // join I2C bus (I2Cdev library doesn't do this automatically)
 #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
 Wire.begin();
 TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
 #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
 Fastwire::setup(400, true);
 #endif

 mpu.initialize();

 devStatus = mpu.dmpInitialize();

 // supply your own gyro offsets here, scaled for min sensitivity
 mpu.setXGyroOffset(220);
 mpu.setYGyroOffset(76);
 mpu.setZGyroOffset(-85);
 mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

 // make sure it worked (returns 0 if so)
 if (devStatus == 0)
 {
 // turn on the DMP, now that it's ready
 mpu.setDMPEnabled(true);

 // enable Arduino interrupt detection
 attachInterrupt(0, dmpDataReady, RISING);
 mpuIntStatus = mpu.getIntStatus();

 // set our DMP Ready flag so the main loop() function knows it's okay to use it
 dmpReady = true;

 // get expected DMP packet size for later comparison
 packetSize = mpu.dmpGetFIFOPacketSize();
 
 //setup PID
 pid.SetMode(AUTOMATIC);
 pid.SetSampleTime(10);
 pid.SetOutputLimits(-255, 255); 
 }
 else
 {
 // ERROR!
 // 1 = initial memory load failed
 // 2 = DMP configuration updates failed
 // (if it's going to break, usually the code will be 1)
 Serial.print(F("DMP Initialization failed (code "));
 Serial.print(devStatus);
 Serial.println(F(")"));
 }
}


void loop()
{
 // if programming failed, don't try to do anything
 if (!dmpReady) return;

 // wait for MPU interrupt or extra packet(s) available
 while (!mpuInterrupt && fifoCount < packetSize)
 {
 //no mpu data - performing PID calculations and output to motors 
 pid.Compute();
 motorController.move(output, MIN_ABS_SPEED);
 
 }

 // reset interrupt flag and get INT_STATUS byte
 mpuInterrupt = false;
 mpuIntStatus = mpu.getIntStatus();

 // get current FIFO count
 fifoCount = mpu.getFIFOCount();

 // check for overflow (this should never happen unless our code is too inefficient)
 if ((mpuIntStatus & 0x10) || fifoCount == 1024)
 {
 // reset so we can continue cleanly
 mpu.resetFIFO();
 Serial.println(F("FIFO overflow!"));

 // otherwise, check for DMP data ready interrupt (this should happen frequently)
 }
 else if (mpuIntStatus & 0x02)
 {
 // wait for correct available data length, should be a VERY short wait
 while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

 // read a packet from FIFO
 mpu.getFIFOBytes(fifoBuffer, packetSize);
 
 // track FIFO count here in case there is > 1 packet available
 // (this lets us immediately read more without waiting for an interrupt)
 fifoCount -= packetSize;

 mpu.dmpGetQuaternion(&q, fifoBuffer);
 mpu.dmpGetGravity(&gravity, &q);
 mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
 input = ypr[1] * 180/M_PI + 180;
 }
}

My Kp, Ki, Kd values may or may not work you. If it doesn’t, then follow the steps I outlined above. Notice that the input tilt in my code is set to 173 degrees. You can change this value if you’d like but take note that this is the tilt angle to which the robot must be maintained.

Also, if your motors are too fast, you can adjust the motorSpeedFactorLeft and motorSpeedFactorRight values.

Video

Here’s the self-balancing robot in action!

What’s Next?

An improvement for this self-balancing robot would be controlling it remotely. Unfortunately, I can’t make this robot do that unless I make it ultra stable using dc motors with an encoder. An encoder would update the current speed of the motor which I can use to make the robot steadier via a second PID loop. I might do that next time so stay tuned!

Your Arduino Balancing Robot (YABR)

Your Arduino Balancing Robot (YABR) is a self-balancing robot that you can build yourself as a school project or as a fun project with your kids. It might look simple but there is a lot that you can learn from building this self-balancing robot.

In contrast to most self-balancing robots, this one uses stepper motors instead of regular DC motors. The main reason is that stepper motors are precise and have no performance loss when the battery voltage drops. One pulse is always an exact amount of motion. Regular DC motors can have mechanical friction and electric resistance differences. This can cause performance differences. As a result the robot will not move in a straight line.

The total cost to build this robot is approximately $80 if you use the hardware list below. This includes a battery, Nunchuck, charger, stepper motors, etc.

The Arduino program that you can download for free is 100% self-written and not based on any other software. The code is well commented and clearly explained. This makes it possible to further develop the code for your own purpose.

 Click to see the full image

If you encounter any problems during the build or setup please check the Q&A page first. Most questions are already answered in detail.

Step 1 – Software

First download the complete YMFC-AL software package:

YABR.zip (version 1.1)

Step 2 – Hardware

To build this robot you need hardware. I made the following list for convenience purpose alone. You are free to get your own hardware from different sources. But this is the hardware that I used/ordered:

If the 35mm stepper motors are out of stock. You could also use these stepper motors. Please note that these are 42mm in stead of 35mm. So you have to modify the frame.

Most of the following parts can be found in your local electronics store. But in case you don’t have an electronics store nearby I will put links here:

And finally you need an old inner tube and two sheets of plywood. I used 2.5mm and 12.5mm sheets.

Step 3 – Tools

And of course you need some simple tools like a soldering iron, screwdrivers, a fretsaw, compact drill, etc.

Step 4 – The build

Watch the YABR hardware build video and build the robot according to the video and the schematic that is included in the complete software package.

Building the YABR balancing robot.

Detailed pictures of my own YABR balancing robot can be found in the media section of this project page.


4.1 The diode and resistors


The resistor R1 on the schematic is needed for uploading a program to the Arduino. The TXD output of the transceiver is forced high or low. As a result the FTDI programmer cannot change this output anymore and you will get an upload error. By adding this resistor the FTDI programmer can change the voltage on the RX-pin of the Arduino despite the state the transceiver output and the program is uploaded without any problems.

The other two resistors (R2 and R3) form a voltage divider. Meaning that the 12.6 volt of the battery minus the 0.6 volt voltage drop over the diode is divided by 2.5. Resulting in a 4.8 volt on the analog input when the battery fully charged. In the main program this analog input will be used to protect the battery. This is because lipo batteries can be damaged when the voltage drops below 3 volt per cell.

The diode D1 protects all the electronics against reversed polarity. So when you accidentally reverse the connections of the battery the components won’t go up in smoke.


4.2 The MPU-6050 gyro/accelerometer


The only gyro / accelerometer that is supported by the YABR software is the MPU-6050. This is because the self-level feature requires an accelerometer and a gyro as I explain in these two videos:

MPU-6050 6dof IMU tutorial for auto-leveling quadcopters – Part 1
MPU-6050 6dof IMU tutorial for auto-leveling quadcopters – Part 2

The orientation of the gyro is important. Make sure to mount the gyro in the exact same orientation as shown on this picture. Otherwise the YABR software cannot calculate the correct angle and the robot will not work.


4.3 Hardware test


Please note that you are soldering the wires on the back side of the PCB. The schematic is drawn facing the components from the front. So everything is mirrored and you need to double check all the connections before you connect any power to the PCB.

With everything in place it’s time to connect the FTDI programmer to the Arduino pro mini. Don’t connect the battery yet. If the LED’s don’t lit up there is a short circuit in the wiring and you need to disconnect the FTDI programmer as soon as possible. Normally the Arduino pro mini is already programmed with the blink sketch so the LED on the Arduino should start to flash.

To check if the gyro is connected correctly and to check the balancing point of the robot you need to upload the “hardware-check” program that you can find in the software package that you downloaded earlier.

Test the balancing angle of the robot and fix it in that position on a stand as I showed in the video. Upload the “hardware-check” program, open the serial monitor and set the baud rate to 9600.

After uploading the program, open the serial monitor and set the baud rate to 9600.

The program will check if there is any I2C device is connected and if this is a MPU-6050. If everything is working as expected the program will output several raw gyro values on the screen. These are just examples and your values may be different. Note down the balance value that you see in the serial output. You will need it later in the main program.


4.4 Limit the motor current


Next thing on the to do list is to set the stepper controllers to the correct drive current. If the motor current is set to high the stepper controllers will heat up and they might get damaged.

First set the potentiometer at the same position as shown in the picture below. Now always be careful when connecting the lipo battery for the first time. A short circuit can cause high currents, heat, sparks, and burns.

A good alternative is to use a small DC fuse like the one below. This fuse will blow if the wiring on the back side of the pcb holds a short circuit.

The easiest and safest way to set the correct current and to check if the wiring is correctly connected is by measuring the current in the power supply wires with a bench power supply. The power supply is limited to 500milli amps. This is an extra safety feature. If there is a short circuit the power supply will limit the current to 500 milli amps and the wiring will be fine.

First connect one motor. With the potentiometer it’s possible to set the current between 100 and 150mA. This is more than enough to get good performance. Do the same with the other stepper controller.

If you don’t have the possibility to measure the current just set the potentiometer in this position and feel if the stepper driver doesn’t get to hot. But it’s always best to measure the current.


3.5 The remote control


If you open the Nunchuck you can note the wire colors that are connected to the various pins as you can see on the schematic. The Nunchuck works on 3.3V and you can use the 3.3V output of the Arduino Uno to power the Nunchuck.

The 5V output can be used for the transceiver. Again, connect the wires as shown on the schematic to get it to work.

To check if the Nunchuck is connected correctly you need to upload the “hardware-check” program that you can find in the software package that you downloaded earlier. After uploading the program, open the serial monitor and set the baud rate to 9600.

The program will check if there is any I2C device is connected and if this is a Nunchuck. If everything is working as expected the program will output several raw joystick values on the screen.

Step 5 – Upload the software

And finally you can upload the YABR-remote program to the Arduino Uno and the YABR-robot program to the Arduino pro mini.

The YABR-remote program does not need any modification. In the robot program you need to change the accelerometer calibration value to the value that was shown by the hardware test program when the robot was in it’s balancing position.

To start the robot you need to power up the remote. Lay the robot on it’s back and switch on the power. The LED will blink indicating that the gyro is calibrating. When the blinking stops you can slowly lift the robot and it will automatically start to balance itself.

And basically that’s it. You can now control the robot with the Nunchuck.

B-Robot EVO 2 KIT (Plug and Play Robot version)

JJrobots´s B-ROBOT EVO 2 Kit. Created to simplify the set up and integration of all the different devices involved in this project.

This COMPLETE VERSION includes all the electronic and hardware components required to create the B-Robot. You just need to assemble everything  (optional 3D parts)

What you get when you buy this KIT:

  •  jjRobots Brain Shield 
  •  Arduino Leonardo (CLONE) + USB cable (already programmed)
  •  2x High Quality NEMA17 stepper motors +14 cms cables (pair)
  •  2x Stepper motor driver
  •  IMU (gyro+accelerometers) + custom cable
  • Powerful servo: Metal gears (you will need an arm to fight and raise your B-robot…)
  • 6x AA Battery case with ON/OFF Switch  (batteries not included)
  • Bolts+nuts needed to set everything up
  • Pair of nylon bumpers (14×5 cms)
  • Double side tape, googly eyes…
  • Optional: 3D printed parts

NEW: control your B-robot using the JJrobots FREE APP! (Android devices) or the Roverbot APP (for iOS phones. not official)

new B-ROBOT Evo 2 FEATURES:

    • STEM education robot: perfect introduction to a robot that solves the inverted pendulum problem. Modify the B-robot EVO 2 as much as you can (both the robot parts themselves or its code) while you have fun!
    • Control it using your smartphone/tablet via the free jjRobots APP
    • Google Blockly controllable!
    • Perfect to have fun as you learn robotics (Take a look to the Robotics Challenges!)
    • Now can use regular AA batteries (or a 3 cells LIPO battery)
    • Two SERVO outputs (one used for the ARM). Both can be controlled from the jjRobots APP
    • Easier to print and using less plastic
    • PRO MODE can be activated from your smartphone/Tablet (increased agility and velocity)
    • Increased WIFI range (up to 40 meters)
    • Battery status
    • “Tilt angle” displayed in real time on your smartphone screen

 

logo GOOGLE PLAY v2

 

Personalise your B-robot to fight, create your own weapons, increase the size of the wheels… it is up to you! Take a look to some parts (and send us yours!)
Customise your own bumper using the online tool at Thingiverse 

 

B-ROBOT Evo 2 Features:

  • STEM education robot.  In addition to being fun, the B-robot EVO 2 engage beginners and advanced students and incorporate many of the fundamental STEM concepts providing a learning platform that everyone enjoys
  • Control it using your smartphone/tablet using the free jjRobots APP
  • Google Blockly controllable
  • Perfect have fun as you learn about robotics (Take a look to the Robotics Challenges!)
  • Open Robot project: code and 3D design files are open and shared. You could personalise your robot as much as you want.
  • DIY & Hackeable: BROBOT is not a closed final product, BROBOT is an open, modifiable and hackeable platform, perfect to learn and play as much as you want!
  • Develop your own apps: You could modify the source code of BROBOT to perform new tasks but the communication protocol is also open so you can develop your own IOS, Android, PC remote apps to control your BROBOT!
  • Learn: BROBOT is a JJROBOTS product and this mean that you will receive a well documented project (source code and external documentation). We want you know all that is happening inside your Robot! This is ideal for learning and teaching technology. We will provide very good documentation. How we are controlling the motors, how we read and integrate the information from gyros and accelerometers, how we are controlling de stability of the robot, how we communicate with the control apps, etc…

– Build with your kids, at school, for yourself… this is a unique gadget. A perfect STEM education robot

– This self balancing robot has a medium size, perfect to carry your own beer (or mineral water ;-))

– There is a community behind BROBOT so you will have a forum to ask questions, share your experiences, MODs/ Hacks and contact other users…

– You can use these self balancing robot parts to create more robots or gadgets, keep in mind all the devices used in a BROBOT are standard electronic devices with a lot of potential. In the JJROBOTS community we want to show you how! You are now buying a self balancing robot, you are buying your a versatile set of electronics and ancillary devices.

 

B-Robot EVO 2. Much more than a self balancing robot

 

 


REMOTELY CONTROL YOUR B-ROBOT EVO

 

Control and tune-up your B-robot from your own smartphone/ tablet using the Control APP (freely available on Google play).

Modify its PID robotic control in real time and see how that affects to its behaviour and performance.

The new version displays the battery status and robot´s tilt angle in real time. Control the two servo output just tapping on the screen.

 

 

 

HAVE FUN LEARNING ROBOTICS

Learn Robotics and have fun with the STEM Challenges!

How does this robot work? Can I adjust its behaviour? And modify it?

STEM education robot:  In addition to being fun, the B-robot EVO 2 engage beginners and advanced students and incorporate many of the fundamental STEM concepts providing a learning platform that everyone enjoys

Bring a beverage can to the other side of the room not dropping it, race against other B-robots with different configurations and add-ons and understand what it is going on. The B-robot EVO 2 is a very versatile and fun STEM learning robot

CUSTOMISE YOUR ROBOT!

Create your own bumpers and personalise your B-robot with the online customisation tool on Thingiverse

 

USEFUL LINKS

B-Robot EVO 2 Assembly guide

Better than a bunch of photos we have created an Assembly guide video. Some steps, like how to program the Arduino, controlling your robot or Troubleshooting are listed below. The interactive 3D model will help you to get a good idea about how the B-robot EVO looks.

Part list:
  •  jjRobots Brain Shield  (or equivalent: schematic info here)
  •  Arduino Leonardo (CLONE) + USB cable (already programmed)
  •  2x High Quality NEMA17 stepper motors +14 cms cables (pair)
  •  2x Stepper motor driver
  •  IMU (gyro+accelerometers) + custom cable
  • Optional: 3D printed parts (vibrant colours)
  • Powerful servo: Metal gears (you will need an arm to fight and raise your B-robot…)
  • 6x AA Battery case with ON/OFF Switch  (batteries not included)
  • Bolts+nuts needed to set everything up
  • Pair of nylon bumpers (14×5 cms)
  • Double side tape, googly eyes…

Have questions/ comments? Refer to the B-robot EVO community!

HOW TO:

UPLOAD the ARDUINO CODE to the ARDUINO LEONARDO

(skip this step if you got the Plug & Play B-robot EVO kit version. The Arduino is already programmed)

a) Install the Arduino IDE on your PC from (skip this step if you have the Arduino IDE already installed)
This B-robot code has been tested and developed on IDE version 1.6.5 and later versions. If you have a problem compiling the code, let us know
b) Download all the arduino files from GITHUB (https://github.com/jjrobots/B-ROBOT_EVO2/tree/master/Arduino/BROBOT_EVO2) or from here
Copy the files inside the BROBOT_EVO2 folder in your hard drive
c) Compile and send the code to the Arduino Leonardo
  1. Open your Arduino IDE
  2. Open the main code in /BROBOT_EVO2/BROBOT_EVO2-XX.ino
  3. Connect your Leonardo board with the USB to the PC
  4. Note: If this is the first time you connect a Leonardo board to your PC maybe you might need to install the driver.
  5. Select the board Leonardo (tools->board)
  6. Select the serial port that appears on the tools->Serial port
Send the code to the board (UPLOAD button: Arrow pointing to the RIGHT)
upload
d) Done!

CONTROL YOUR B-ROBOT EVO 2:

Android users:

We have developed a FREE APP to control the Brobot (and future JJrobots) for your Android based Smartphone/Tablet:

logo GOOGLE PLAY v2
Download it for FREE

It works sending UDP packets to the B-robot. It uses a simple layout with Throttle and Steering slicers and several buttons.

Steps to follow:

  1. Install the JJRobots control APP
  2. After turning the Brobot EVO ON, connect your smartphone/tablet to the B-robot EVO´s wifi network (remember, the WIFI´s password is 87654321)
  3. Launch the JJrobots control APP and play with your B-robot EVO!

Above: Screen capture of the JJrobots B-robot control APP (available for free in GOOGLE PLAY)

iOS users. App Store App or TouchOSC :

iOS  B-robot control APP (thanks to Xuyen for this great contribution!)ios tiny2

It is quite straightforward to use. Just connect your iPhone/iPad to the B-robot EVO´s wifi (use the password “87654321“) and launch the App.

(thanks to Xuyen for this great contribution!)

iOS TouchOSC APP: Alternative way to control the B-robot EVO. Setup guide and files here 

USEFUL LINKS:

Arduino CODE (latest version V.2.0) and the GITHUB REPOSITORY

3D PARTS (STL) Files

B-robot Challenges (robotics, Academy)

B-robot alternative frames: Stealth versionCompact version (credits to s199)

B-robot EVO 2: 3D MODEL

TROUBLESHOOTING:

My B-robot is not responding to the command sent from my smartphone/tablet

Check you are connected to the JJROBOTS_XX netwrok using the correct password (by default: 87654321) and your device has not blocked the data traffic to the B-robot (stay always connected to the robot)

The IMU gets loose/ the i2C cable is too short

The gyroscope (IMU) is one of the most important element in this robot. It provides the current angle of the robot updating its value hundred times per second. The protocol used to send the data is quite sensitive to any electromagnetic interference so a very short cable is needed to connect the IMU and the Brain Shield. At the same time, vibrations create false angle measurements so we have to isolate the Brobot´s main frame vibrations from the IMU: that is the reason to use a double sided sticky pad to fix the IMU to the Brain Shield.

Place the IMU as indicated above: Close to the Brain Shield´s i2C connector. Bend the cable if needed. If you place the IMU as above, there should not be any lateral force pushing the IMU out of place

My B-robot lacks of power or fall without reason

Adjust the current delivered by the stepper motors drivers. Use a screwdriver and gently rotate the screws indicated on the photo below. Rotating 10º-30º is more than enough.

Clockwise rotation: increase the power delivered to the motors

 

A4988 STEPPER MOTOR DRIVERS output current potentiometer

My B-robot can not stand up by itself.

If everything is ok, the B-robot only needs a little bit of help from the servo to stand up by itself. Take a look to the video below. If your robot does not behave like in the video, adjust the stepper motor drivers output power (instructions above). Keep in mind that the bumpers have two functions here: protect the electronics+robot and help it to stand up easily.

Video Player

DEBUG MODE

There is a DEBUG MODE inside the B-robot CODE. This MODE will allow you the debug the behaviour of the robot if you are having issues.  Please, refer to the B-robot community if you have problems or questions.

Look at the sketch line “#define DEBUG 0″ and change the 0 to 1…8 depending on what info you want to get. Take a look to the CODE below:

#if DEBUG==8
Serial.print(throttle);
Serial.print(” “);
Serial.print(steering);
Serial.print(” “);
Serial.println(mode);
#endif

//angle_adjusted_radians = angle_adjusted*GRAD2RAD;

#if DEBUG==1
Serial.println(angle_adjusted);

#endif

//Serial.print(“\t”);
mpu.resetFIFO(); // We always reset FIFO

// We calculate the estimated robot speed:
// Estimated_Speed = angular_velocity_of_stepper_motors(combined) – angular_velocity_of_robot(angle measured by IMU)
actual_robot_speed_Old = actual_robot_speed;
actual_robot_speed = (speed_M1 + speed_M2)/2; // Positive: forward

int16_t angular_velocity = (angle_adjusted-angle_adjusted_Old)*90.0; // 90 is an empirical extracted factor to adjust for real units
int16_t estimated_speed = -actual_robot_speed_Old – angular_velocity; // We use robot_speed(t-1) or (t-2) to compensate the delay
estimated_speed_filtered = estimated_speed_filtered*0.95 + (float)estimated_speed*0.05;

#if DEBUG==2
Serial.print(” “);
Serial.println(estimated_speed_filtered);
#endif

// SPEED CONTROL: This is a PI controller.
// input:user throttle, variable: estimated robot speed, output: target robot angle to get the desired speed
//target_angle = (target_angle + speedPControl(estimated_speed_filtered,throttle,Kp_thr))/2.0; // Some filtering : Average with previous output
//target_angle = target_angle*0.3 + speedPIControl(dt,estimated_speed_filtered,throttle,Kp_thr,Ki_thr)*0.7; // Some filtering
target_angle = speedPIControl(dt,estimated_speed_filtered,throttle,Kp_thr,Ki_thr);
target_angle = constrain(target_angle,-max_target_angle,max_target_angle); // limited output

#if DEBUG==3
Serial.print(” “);
Serial.println(estimated_speed_filtered);
Serial.print(” “);
Serial.println(target_angle);
#endif

#if DEBUG==10
Serial.print(angle_adjusted);
Serial.print(” “);
Serial.println(debugVariable);
#endif

#if DEBUG==6 //BATTERY STATUS
Serial.print(“B”);
Serial.println(battery);
Serial.print(” “);
#endif
#if DEBUG==7
Serial.print(distance_sensor);
Serial.print(” A”);
Serial.println(autonomous_mode_status);

 

USEFUL INFO: ARDUINO LEONARDO, IMU 6050 & STEPPER MOTOR DRIVER(A4988):

Arduino Leonardo:

  • Schematic can be found here
  • Info about this Arduino model here

MPU-6050 (gyro+accelerometers)

  • MPU-6050 series info can be found here
  • How to integrate it with any Arduino, here
  • Schematic and connection info, here

Stepper motor driver A4988:

 

FAQ (frequently asked questions):

Why are you using Stepper motors?

There are several options for motors: DC, Brushless, Steppers… We choose stepper motors because they have enough torque, you could connect the wheels directly without gears that generate some backslash (this is a common problem in balancing robots), they have good bearings and you will be able to control the speed of the motors with accuracy. In standard sizes these motors are cheap (we use the same motors used on a regular 3D printers) and the drivers are cheap and easy to interface with Arduino too.

Why you use a Wifi connection?

Using a Wifi connection allow us to work with a lot of devices (Smartphones, Tablets, PCs…) Bluetooth devices are cheaper but their range is usually shorter. Old devices are not supported and you could not connect it to Internet easily. The Wifi module that we recommend, allow us to create an Access Point, so you don’t need to use an existing Wifi infrastructure (cheap Wifi modules don´t let you do this). You can connect your device directly to the Robot anywhere but if you prefer you can hack it and use your own infrastructure therefore controlling your robot (or whatever you have created) over the Internet from any remote place in the world! (Cool, isn´t it?)

Why BROBOT?

Self balancing robots are fun to see and play. A self balancing robot requires sensors and control algorithms. You will find all the HOWTO and technical documents which explains the “behind the scenes” in JJROBOTS. Learn electronics and robotics creating your own BROBOT from scratch!.

There are some commercial solutions to the balancing robot, but here we want to share knowledge and thoughts. You can use the BROBOT parts to create more robots or gadgets, keep in mind all the devices used in a BROBOT are standard devices/electronics with a lot of potential. In the JJROBOTS community we want to show you how! You are now buying a self balancing robot, your are buying your own electronic and ancillary devices!

Thinking about creating a GPS self guidance robot? a modified version of BROBOT is your robot!

How much payload could carry BROBOT?

BROBOT could easily carry your soft-drink cans. We have tested with 500g of payload with success. More weight makes the robot more unstable but this could be fun also, isn’t it?

Why use stepper motors for a balancing robot?

There are several options for motors, DC, Brushless, Steppers… We choose stepper motors because they have enough torque, you could connect the wheels directly without gears that generate some backslash, they have good bearings and you could control the speed of the motors very precisely. Also they are cheap and the drivers too…

Could I use rechargeable batteries of Lipo batteries?

Yes, you could use standard AA batteries (alkaline recommended), AA rechargeable batteries (e.g. NiMh) or you could optionally use a 3S Lipo battery. Run Lipo batteries at your own responsibility.

What is the runtime of BROBOT?

With rechargeable AA batteries (e.g. Ni-Mh 2100mAh) you could expect around half to an hour of runtime

Could BROBOT work without the wifi module?

Yes, BROBOT could work and keep its stability. But, of course you could not control it without the module.

 

Could I change the name of the Wifi network that BROBOT generate?

Yes, on the configuration sketch you could change the name and also some other internet configurations. You could also connect BROBOT with your existing Wifi network

Is this a project for an Arduino beginner?

Well, BROBOT is not an easy “beginner project”, but it has a lot of documentation so you have a platform to grow your skills. You could first mount your BROBOT following the instructions and it should work OK, then you could start understanding some parts of the code and finally writing your own pieces of code…

For example it could be easily (there are tutorials for this) to write your code so the robot automatically move the arm and spin itself if you don’t send a command in 10 seconds…

More advanced hacks: Convert to a totally autonomous robot with obstacle avoiding adding a SONAR, convert to a follow line robot, and so on…

Why BROBOT electronics are not so cheap?

We are a really small startup (2 persons in our free time) and now we could only run small batch of electronics. As yo know the price of electronics drops quickly in high volume productions but we are starting… If we sell many boards and we could run more volume productions we will drop the prices!!. JJROBOTS didn´t born to get money, our spirit is to sell “good products” to found our next projects and spread the robotics knowledge

Have fun!

LINK: B-robot EVO original assembly guide 

Creating a Remotely Controlled Arduino Self Balancing Robot: B-robot EVO

How does it work?

B-ROBOT EVO is a remotely controlled self balancing arduino robot created with 3D printed parts. With only two wheels, B-ROBOT is able to maintain its balance all the time by using his internal sensors and driving the motors. You can control your Robot, making him move or spin, by sending commands via a Smartphone, Tablet or PC while it maintains its balance.

This self balancing robot reads his inertial sensors (accelerometers and gyroscopes integrated on the MPU6000 chip) 200 times per second. He calculates his attitude (angle with respect to the horizon) and compares this angle with the target angle (0º if he wants to maintain balance without moving, or a positive or negative angle if he wants to move forward or backwards). Using the difference between the target angle (let’s say 0º) and actual angle (let’s say 3º) he drives a Control System to send the right commands to the motors to maintain his balance. The commands to the motors are accelerations. For example if the robot is tilted forward (angle of robot is 3º) then he sends a command to the motors to accelerate forward until this angle is reduced to zero to preserve the balance.

Step 1: A Bit More in Depth…

The physical problem that B-ROBOT solves is called the Inverted Pendulum. This is the same mechanism you need to balance an umbrella above your hand. The pivot point is under the center of mass of the object. More information on Inverted Pendulum here. The mathematical solution to the problem is not easy but we don’t need to understand it in order to solve our robot´s balance issue. What we need to know is how should do to restore the robot´s balance so we can implement a Control Algorithm to resolve the problem.

Control System is very useful in Robotics (an Industrial automation). Basically it´s a code that receives information from sensors and target commands as inputs and creates, in consequence, output signals to drive the Robot actuators (the motors in our example) in order to regulate the system. We are using a PID controller (Proportional + Derivative + Integral). This type of control has 3 constants to adjust kP,kD,kI. From Wikipedia: “A PID controller calculates an ‘error’ value as the difference between a measured [Input] and a desired setpoint. The controller attempts to minimize the error by adjusting [an Output].” So, you tell the PID what to measure (the “Input”),where you want that measurement to be (the “Setpoint”,) and the variable you wish to adjust to make that happen (the “Output”.)

The PID then adjusts the output trying to make the input equal the setpoint. For reference, a water tank we want to fill up to a level, the Input, Setpoint, and Output would be the level according to the water level sensor, the desired water level and the water pumped into the tank. kP is the Proportional part and is the main part of the control, this part is proportional to the error. kD is the Derivative part and is applied to the derivative of the error. This part depends on the dynamics of the system (depends on the robot,´s weight motors, inertias…). The last one, kI is applied to the integral of the error and is used to reduce steady errors, it is like a trim on the final output (think in the trim buttons on an RC car steering wheel to make the car go totally straight, kI removes the offset between the target required and the actual value).

On B-ROBOT the steering command from the user is added to the motors output (one motor with a positive sign and the other with a negative sign). For example if the user sends the steering command 6 to turn to the right (from -10 to 10) we need to add 6 to the left motor value and subtract 6 from the right motor. If the robot is not moving forward or backwards, the result of the steering command is a spin of the robot

Step 2: What About the Remote Control?

We wanted B-ROBOT to be controlled by the user from almost any existing device, but we don´t want to develop a lot of different interfaces for different systems (Android, IOS, PC-windows…). Moreover, we decided to use existing (and powerful) protocols to control “things” and we found (some years ago) a protocol called OSC(Open Sound Control, more info here) used to control musical instruments like synthesizers. Very visual and powerful (we can display volume control, equalizers, lights…and create our own). To remotely control B-robot, we use OSC protocol over an Internet connection (Wifi module) using UDP packets. This is a lightweight and efficient way to send commands to our Robots!. We could also personalize the Interface we are using in our device so we will be able to control anything! (well…almost) What we need to do is to implement a lightweight library for Arduino in order to support this protocol (easy). We only use a subset of the OSC protocol to keep things small.

More info in the jjrobots webpage

Step 3: FIRST! Check You Have Everything You Need

  1. B-ROBOT electronic brain shield (or create your own PCB board using the info available here)
  2. B-Robot 3D printed plastic parts (STL models available here)
  3. Arduino LEONARDO
  4. 2x Stepper motor DRIVER (A4988)
  5. IMU MPU-6050 (gyro+accelerometer)
  6. 2x NEMA 17 stepper motors (40mm length, example:42BYGHW609)
  7. 8xAA battery holder (for NiMh or alkaline batteries)
  8. OPTIONAL: Mini servo (21g) to move the arm (this is a fun feature)

The easy way to get everything is buying from us (and that encourages us to keep doing these robots) here (plus bolts, nuts, strap…)

HINT:

We are working on other robots that are using the same electronics and ancillary elements. If you get the items above you will be capable of assemble new different robots soon. Take a look to them at the last step

Step 4: ​Programming the ARDUINO LEONARDO

a) Install the Arduino IDE on your PC from (skip this step if you have arduino already installed)

This B-robot code has been tested and developed on IDE version 1.6.5

b) Install the libraries (https://github.com/jjrobots/B-ROBOT/tree/master/libraries) Copy the folders inside the /libraries into the Arduino/libraries folder on your hard drive

JJROBOTS_BROBOT

JJROBOTS_OSC

I2Cdev

MPU6050

c)  Get the main CODE (https://github.com/jjrobots/B-ROBOT/tree/master/BROBOT).

d) Compile and send the code to the Arduino Leonardo:

  1. Open your Arduino IDE
  2. Open the main code in /BROBOT/BROBOT.ino
  3. Connect your Leonardo board with the USB to the PC
  4. Note: If this is the first time you connect a Leonardo board to your PC maybe you will need to install the driver.
  5. Select the board Leonardo (tools->board)
  6. Select the serial port that appears on the tools->Serial port
  7. Send the code to the board

Step 5: Assemble the B-robot Frame+ Ancillary Elements

Step 6: (Optional But Recommended) Controlling the B-robot Using WIFI

Setting up the TouchOSC software: If you are going to use the Touch OSC software to control the B-robot (and according to the current B-robot´s CODE available for the Arduino Leonardo), you will need to set these parameters in the TouchOSC like is shown in the images above.

Download the B-robot control layout (you can modify it if you want to) and install it using the OSCtouch APP

LINK: OSC layout used to control B-robot

Once the B.robot is switched on, a new WIFI signal will appear: “JJROBOTS-XX”. You will need to connect the controlling device to this network using the default WIFI password: 87654321

An OSC control software alternative: OSCillation and how to use it (Thanks Patrick!)

Step 7: ​Powering Up the B-robot:

  1. Lay down the B-robot on a static horizontal position in order to let it calibrate itself after powering it up.
  2. Turn the B-robot ON
  3. Let the B-robot 10 seconds to calibrate itself. Once self-calibrated, B-robot will spin its wheels a little.
  4. Time to stand up!: Use its arm or help it to stand up.

HINT: If the stepper motors do not have enough power to spin the wheels, try to adjust the current output in the A4988 stepper motor drivers rotating the screw indicated in the photo

QUESTIONS?

have a look to the B-robot forum

Step 8:

Other robots created (or under the last stage of development) which use the same electronics and ancillary elements.