Balancing robot for dummies

as mentioned above , showing the effect of the full balance equation
angle+Vbody+Vbase+position, when stepping a 256mm change in requested (x) position every 8 seconds, 0, 0x100,repeated step.

has anyone tried graphing live data in excel, I have a one channel prototype , it lags a bit but its better than cut and paste.

Thanks for all the info about the placement of the sensors on the robot. I think a have a idea now on how to build the robot..

I want to ask you guys also what you think should be the best settings for my accelerometer and may gyro.

LPR510AL Dual-Axis (Pitch and Roll or XY) Gyro with ±100°/s and 400°/s Ranges

MMA7341L 3-Axis Accelerometer ±3/11g with Voltage Regulator

3g or 11g
100 degrees/s or 400 degrees/s

My jig is now complete so I can start testing some things:

You can see more info on my blog

@Gibby623

The Accelerometer sense translational accelerations, not angular acceleration.

Hoops :-[ I fully agree, the angular acceleration is obtained from two orthogonal accelererometers, using Arctg function.
Thanks for those very precise comments
What is the precise subject of your thesis ???

Looking at your video, your bot balances pretty well
You won't get much better without motor encoders

Care to share your code??
I will post the end of my tutorial and KasBot V1 code probably this week end

Ok I have one more question just to clarify something for me. The X-axis of the accelerometer should be in the rotational axis of the wheels. But should the axis from the gyro be a perpendicular axis to the X-axis of the accelerometer like an Y-axis?

Should i use the Gyro Y-axis on the IMU? I'm cute sure I should use the Y-axis...

I see to different things below, just to clarify this

// Main module   K_bot angle    angles in Quids, 10 bit ADC -----------------------------
// 5 - angle and rate calculation       display ACC_Angle and GYRO_rate

#include <math.h>

#define   GYR_Y                 0                              // Gyro Y (IMU pin #4)
#define   ACC_Z                 1                              // Acc  Z (IMU pin #7)
#define   ACC_X                 2                              // Acc  X (IMU pin #9)

The sensors values vs position should read as follow:
Horizontal ( 0° = 0 Quid ) ACC_X: 0 ACC_Z: XX GYR_X: 0
Left side (-90° = -256 Quid) ACC_X: XX ACC_Z: 0 GYR_X: 0
Right side (+90° = +256 Quid) ACC_X:-XX ACC_Z: 0 GYR_X: 0
Reversed (180° = +512 Quid) ACC_X: 0 ACC_Z:-XX GYR_X: 0

I want to ask you guys also what you think should be the best settings for my accelerometer and may gyro.
LPR510AL Dual-Axis (Pitch and Roll or XY) Gyro with ±100°/s and 400°/s Ranges
MMA7341L 3-Axis Accelerometer ±3/11g with Voltage Regulator
3g or 11g
100 degrees/s or 400 degrees/s

I would definitly go for the shortest range (3g and 100°/s)
Mines are 3g 500°/s and I would appreciate more resolution for the gyro

Ok I have one more question just to clarify something for me. The X-axis of the accelerometer should be in the rotational axis of the wheels. But should the axis from the gyro be a perpendicular axis to the X-axis of the accelerometer like an Y-axis?
Should i use the Gyro Y-axis on the IMU? I'm cute sure I should use the Y-axis...

:-? :-? Lets make it clear, you need:

  • one gyro
  • two accelerometers (could work with one)
    The gyro should parallel to the rotational axis of the wheels
    one Acc axis according to horizontal
    one Acc axis according to vertical

I see to different things below, just to clarify this

Please elaborate

@beautifulsmall

Thanks for the information :slight_smile:
I will study the code and come back to you soon

Please post a link to the motors you are using and possibly a close up photo of your bot. Seems that this gearless setup should solve the backlash problem.

Kas, the motors are the dog's B'llks, and cost me ,about £60 uk,each, after tax, ect.ie, not a commertial product, plenty of bal rob videos are with cheap motors so ive ordered some 120rpm, 6v from china, photo shows a bit of back axel so im hoping i can attatch a mouse encoder, ball.
on Earwig are RE-max 29, neobium magnet, coreless. DC motors, non-cogging,
I will explain the construction because i once took one apart. re-assembly was not in a clean room.
A commutated DC motor has a rotating core surrounded by a set of magnets , the coreless design has a solid magnet bar in the centre and the wire winding is spun into a tube which surrounds the magnetic core. 7-11 poles are used but the winding pattern effectivley gives an analoge effect , BUT they will vibrate at 1Khz, and anything less, they are super twitchy!very low inertia.
Backlash, belt systems are good, belt tension matters, on earwig i have M3 HTD belts and 1:8 ratio, aluminium motor pulley, plastic wheel pulley. The motors are 20N side load max, the belts are 100N max, so I do run with a loose belt, and backlash.
Backlash compensation, in wheel velocity calculation :

if velocity changes direction , velocity =0 for next two loops

because im rubbish at code, I set a loop to count time and let it loose every 4ms , before this the loop ran at its natural speed and despite having a dt in all the calculations, I needed to reset all the pid values constantly.
the velocity at direction change should be around zero or at least trying to get there so setting wheel velocity to zero cuts out the velocity jump as the motor changes direction and the belt tension changes from one side to the other. this does not affect encoder absolute position which must be read at static zero up.

blackfin , stereo vision,
Kas, its so hard to teach kids there 0xff times table :smiley: ;D

Reply #46 - Today at 02:51:56

beautifulsmall, on which side of the Atlantic ocean are you living ??
Should you live on the "wrong side" ;), I hope you have another life for sleeping :smiley: :smiley:

Thanks for you coreless motor description, I was confusing "coreless" and "brushless" motors (the ones with separate ESC controllers)

ive ordered some 120rpm, 6v from china

Depending on wheels size and bot weight, you may find 120rpm a bit slow for proper operation

Planetary geared motor are supposed to have no mecanical backlash
Still trying to identify adequate units with attached encoders

Finally after a lot of stupid questions I got the kalman filter to work. I need to tune the zero ACC_Z value some more and some other things but it works. The effect is quite amazing, see the video here and see for yourself. (Values in quids).

I was to say the least confused about the unit quids and the arrangement of the acc. and the gyro. But now I understands it and man it's smart to be able to us int values...


I will post some more information about the tests on my blog later this weekend...

Very clean signal :sunglasses: :sunglasses:
Also check signal quality when sensor is upside down
My sensor combo gives poor result when inversed and couldn't be positioned as per your photo

For ACC_Z, gravity correction = (0° value - 180° value)/2

Quids are nice for integer math
Those are basic 10 bits Quids (360° = 1204 Quids)
For better resolution, we may use Quids12 (360° = 4096 Quids) :wink:

@patrick
If your are still looking for a 12V battery, look at this one
http://cgi.ebay.co.uk/ws/eBayISAPI.dll?ViewItem&item=150447448378
3800 mAh, 22 bucks shipped

@Kas

I have some small things I wanted to ask you that I don't really understand. I used the greyed sensor inputs like in the image below is that correct:

I changed the following in your code:
I recalculated the zero value for Acc_Z
440/3300*1024 = 136

void calibrateSensors() {    // Set zero sensor values
  long v7
  for(int n=0; n<5; n++) {
    v = 0;
    for(int i=0; i<50; i++)       v += readSensor(n);
    sensorZero[n] = v/50;
  }                                                          
  sensorZero[ACC_Z] -= 137;                        
}

I changed the gyro rate and also changed to my GYR_X instead of using GYR_Y. I also changed the sign off the return value;

int getGyroRate() {                                             // ARef=3.3V, Gyro sensitivity=2mV/(deg/sec)
  return int((sensorValue[GYR_X] * 0.88888888889)*-1);                 // in quid/sec:(1024/360)/1024 * 3.3/0.010)
}

int getAccAngle() {                      
  return (arctan2(-sensorValue[ACC_Z], -sensorValue[ACC_X]) + 256);    // in Quid: 1024/(2*PI))
}

What I don't really understand is why I didn't need to change the sign of the ACC_X value to get it like your values.

Why do you enter the values as negative in to the function arctan2 and why adding 256?

(arctan2(-sensorValue[ACC_Z], -sensorValue[ACC_X]) + 256)

I'm not that good at math so you have to excuse my sometimes stupid questions..

@kas
Thanks for the tips.

I had planed to by a lipo battery from Hobbyking but they are on 11,7V I think so this suited me just fine and free shipping also :slight_smile:

@patrick
If your are still looking for a 12V battery, look at this one
http://cgi.ebay.co.uk/ws/eBayISAPI.dll?ViewItem&item=150447448378
3800 mAh, 22 bucks shipped

I used the greyed sensor inputs like in the image below is that correct:

Nice drawing ;), my setup is actually as per your drawing

I recalculated the zero value for Acc_Z
440/3300*1024 = 136

I looked at the MMA7341L Accelerometer datasheet:

Please keep in mind that quoted sensitivity (440 mV/g) is a typical value. Your specific sensor may be as low as 413, or as high as 466.
I suggest you calculate Acc_Z zero value using the experimental way as described above

What I don't really understand is why I didn't need to change the sign of the ACC_X value to get it like your values.
Why do you enter the values as negative in to the function arctan2 and why adding 256?
Quote:

(arctan2(-sensorValue[ACC_Z], -sensorValue[ACC_X]) + 256)

Signs are related to axis orientation.
Just adjust the signs by experimenting and make sure you get data format as described in reply #7.
256 is an offset (90°) to get a 0 angle value when the bot is vertical

@kas

Tanks for the replay of all my questions and I bought the battery you gave me a link to.

I will make some more experiments with the kalman filter and also add the other axis so I can see if the bot is tilting side wise as well.

Under the week I will start moving the motors and make some experiments with the encoders.

In the weekend I will start building the body to the robot...

you may experiment with the encoders, but I strongly advise not to implemente them in the bot yet.
You can balance pretty well w/o encoders
Encoders will reduce potential forward/backward drifting

Good luck :wink:

** Balancing robot for dummies **

Part five (final): DC motor control and V1 code

The updatePid function (see part 4) returns a -255 +255 range value for the motors commands
0 stop (bot is vertical)
+255 fast forward
-255 fast backward

Motor controllers only understand 0 +255 range values
This is taken care of in the Drive_Motor code

int Drive_Motor(int torque)  {
  if (torque >= 0)  {                                        // drive motors forward
    digitalWrite(InA_R, LOW);                         
    digitalWrite(InB_R, HIGH);
    digitalWrite(InA_L, LOW);                     
    digitalWrite(InB_L, HIGH);
  }  else {                                                  // drive motors backward
    digitalWrite(InA_R, HIGH);                       
    digitalWrite(InB_R, LOW);
    digitalWrite(InA_L, HIGH);                      
    digitalWrite(InB_L, LOW);
    torque = abs(torque);
  }
  analogWrite(PWM_R,torque);
  analogWrite(PWM_L,torque * 0.9);                           // motors are not built equal...

Please refer to http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282384853/0
for additional informations

The first part of this tutorial is now terminated (finally... :-X :-X :-X)
I am impressed by the number of time this thread has been viewed, I hope the info was clear and detailed enough
If you started your own project or intend to do so in the near future, please jump in now and just leave a comment here

KasBot V1 complete code file:
** EDIT ** can't find the trick to upload a file any hint ???

KasBot V1 is fully functional and should balance for ever
Just modify the code according to your own gyro sensitivity

int getGyroRate() {                                          // ARef=3.3V, Gyro sensitivity=2mV/(deg/sec)
  return int(sensorValue[GYR_Y] * 4.583333333);              // in quid/sec:(1024/360)/1024 * 3.3/0.002)   
}

My gyro (IDG300) is 2mV/deg/sec
For Accelerators, adjust gravity offset in calibrateSensors()
PID parameters should also be tuned according to your own bot geometry and weight

More to come:
V1.5 will bring "utilities" for live tuning without re uploading the code
V1.7 will replace Arduino 10 bit ADC with MPC3208 12 bit ADC (increased resolution)
V2.0 should combine encoders info in PID to suppress potential forward/backward drifting
V3.0 should bring RC remote control features (Xbee technology)
V4.0 will add IR Ping))) sensor for obstacle avoidance
V5.0 will add... your own ideas :wink: :wink:

Long (probably endless) roadmap ::slight_smile:

I have to say this is awesome! You managed to write it for dummies, I hope I'm dumb enough to get it, hehe. I have different acc and gyro sensors, old ones, I have to dig up some data sheets to find out the resolution for them. Other than that, I should be fine, except for motors speed, that is lower than 200 rpm. Oh well, I'll use them for now. I'll add some 10k pots to adjust the PID parameters. I'll report my progress probably next weekend, during the week I don't have much time. This weekend will be the chassis manufacturing out of some plywood. After I get to the final tweaks I'll cut a nicer one from acrylic. Wish me luck!

Hi Ro-Bot-X
Thanks for the nice comments

...Wish me luck!

I do!!! :slight_smile: :slight_smile: :slight_smile:

I need the infomation about the PID which you stated.

How come in your error terms is a speed, and the return part is a pwm duty ratio?

What is the K stands for? Gain? or others?
How can I calculate it?