Balancing robot for dummies

Hi beautifulsmall,

I have "off" discussions with Jon D. via PM
He purchased those motors (w/o encoders)

Yes, applying encoders is definitely the easiest and most accurate solution.
If beautifulsmall succeeds with this I'm absolutely interested in it!
The reason I want to make a estimator is mostly to use some of the theory we have learned at school in practice.
I just think it's very fascinating when these things actually works Having both an estimator for motorspeed and
encoders would be really cool, to be able to compare the result! Well, that project will have to wait until next step

I mentioned your ADNS-7550 project
Any possibility to include Jon D. as another beta tester ?? :wink:

Thanks for all the great information here! I'm new to using motor drivers and have a question on how to choose the correct power supply for this application. I'm using the same 29:1 Pololu gearmotors with a dual motor driver capable of 2.5A continuous and 5A peak output per channel.

My original thought was to use a 12V 5A power supply, but after some forum searching I've read that the motors could draw up to twice the stall current if commanded to switch from full forward to full reverse (for a total of 10A between the two motors).

When picking a power supply for the balancing bot is that 10A the current capacity I need to be accounting for (so then a 12V 10A source?) or since that maximum will probably not be experienced would the 12V 5A work fine?

My other source of consternation is in regards to using a battery to power the unit. I've found many 12V 3800mah batteries from ebay sellers, but no maximum current is listed for them. Is it just safe to assume any 3800mah rating means the battery would be able to discharge 10A for 3.8hours?

Thanks to anyone for help with these newbie questions. I'll edit this with a link to the specific battery / power supply that I'm looking at when I can post a link.

@Paul2
Yes, you are right. The biggest load the motors can pull is 5A each. However, as you are not(hopefully) planning to hold them from turning, they will never pull this much more than for an very short moment. Assuming then you are gonna use them in a balancing robot, which weight isn't of to big dimensions.

You don't say what type of battery you are gonne use, Nicd/NiMh or LiPo. I have always used LiPo for my projects, as they deliver very stable voltage as they don't drop so much as they get charged out, and they are quick to recharge. Drawback is that they can not be completely emptied, as they then will be damaged.

I have no experience with NiCd/NiMh batteries, but what you are gonna look for on a LiPo-battery is a rating "C". It says many amperes it is able to deliver, respective to it's capacity. For example, if the battery you are reffering to is rated with 10C, it is able to deliver 3800mah * 10 = 38A continusly. Usually the battery also got a peak-rating, wich works the same way only that this current can only be delivered for a short amount of time.

If you are new to these kind of batteries it is worth noting that the 2-cell LiPo(2S) is 7.4V and 3-cell(3S) is 11.1V. However, fully charged they measure about respecitve 8.4V and 12.6V, so the last works great on 12V motors.

On my robot a use a battery similar to this one for driving the motors:
http://hobbycity.com/hobbyking/store/uh_viewItem.asp?idProduct=9163
And something like this one to supply the Arduino, Xbee etc.
http://hobbycity.com/hobbyking/store/uh_viewItem.asp?idProduct=9170

The reason I'm using two separate battrypack for driving the motors and the electronics, is to try to avoid noise. The negative pole for both batteries is connected through a 100K resisitor to provide common "ground". Don't know if the motordrivers produces so much noise that this is necessary, though..

Well, good luck Paul2, and merry christmas to you all!

Jon, Norway.

Folks, hoping for some tips. I've built a balancing robot using an IMU 5DOF, the MD25 motor controller and EMG30s but the motors simply don't seem to respond quickly enough.
I've pretty much used the code being discussed on this thread with a few exceptions -
I'm using an arduino mega so have used the internal ref voltage of 2.56V and the amplified gyro outputs on the IDG500 so my gyro conversion looks like this:

int getGyroRate() 
{    
    return int(sensorValue[GYR_Y] * 0.781440781);  // in quid/sec:(1024/360)/1024 * 2.56/0.0091)
}

I'm using I2C for the motor controller which needs a 0 to 255 where 128=stopped so to get my drive value I do:

int updatePid(int targetPosition, int currentPosition)   
{   
    int error = targetPosition - currentPosition;
    pTerm = Kp * error;
    integrated_error += error;
    iTerm = Ki * constrain(integrated_error, -GUARD_GAIN, GUARD_GAIN);
    dTerm = Kd * (error - last_error);
    last_error = error;
    
    int x = -constrain(K*(pTerm + iTerm + dTerm), -255, 255);
    x /= 2;
    x += 128;   
    return x;
}

When calibrating my sensors and getting readings I disregarded any outliers:

int compare (const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
}

void calibrateSensors() 
{
    int allVals[50];   
    long v;
    
    for(int n=0; n<3; ++n) 
    {
        v = 0;
        for(int i=0; i<50; ++i)       
        {
            allVals[i] = readSensor(n);          
        }
        qsort(allVals, 50, sizeof(int), compare);
        
        for(int i=5; i<45; ++i)
        {
            v+= allVals[i];
        }
        sensorZero[n] = v/40;
    }
    sensorZero[ACC_Z] -= 137;
}

void updateSensors() 
{
    int allVals[5];
    long v;
    for(int n=0; n<3; ++n) 
    {
        v = 0;
        for(int i=0; i<5; ++i)      
        { 
            allVals[i] = readSensor(n);
        }
        qsort(allVals, 5, sizeof(int), compare);
        
        for(int i=1; i<4; ++i)
        {
            v+= allVals[i];
        }
        sensorValue[n] = v/3 - sensorZero[n];
    }
}

I also timed my loop over 1000 iterations and found it took about 3.5ms per iteration so I've tried setting the STD_LOOP_TIME to 5 but it didn't help.

My angles look pretty good and if I print out the time, angle and drive as they change they look ok though the time is slowed down by the printing.
However, if I let the robot go from vertical I can see it's almost beyond the point of no return before the motors kick into life.
If I stop it falling too far on each side by hand I can see that the motors are doing the right thing, just not quick enough.
I've mainly just tried increasing the P val for pid so far, I and D are 0, though I've tinkered there too with no joy.

I don't know much about I2C, could it be just to slow for this task? Surely the EMG30s are up to it?

Appreciate any advice!

@richiereynolds

I don't know much about I2C, could it be just to slow for this task? Surely the EMG30s are up to it?

I'm sure I2C is fast enough, it's used widely in gyros and accelerometers with success, so it should work the other way(as output, that is) too. The motors seem pretty similar to pololu motors, and looking at the specifications they should be good for the purpose.

However, if I let the robot go from vertical I can see it's almost beyond the point of no return before the motors kick into life.
If I stop it falling too far on each side by hand I can see that the motors are doing the right thing, just not quick enough.

I have noticed that these motors typically have some delay before they actually starts turning. That means they doesn't start when you apply "1" to the motordriver, but not until you apply "5" or something. This implies that the robot has to "fall" longer until a standalone P-val will get a big enough value to start turning the motors. I solved this by making a offset, so that when the PID-controller puts out "1", the motors will start turning. This is the code I use for driving the motors:

void MotorDriver::setMotor(signed int setting)
 {
   if(setting > 0) setting += 4;//Increase for bigger offset on the + side
   else if(setting < 0) setting -= 4;//Increase for bigger offset on the - side
   
   if(setting > 100) setting = 100;
   else if (setting < -100) setting = -100;
   
   setting = setting * 1.27;
   analogWrite(5, -setting + 127);
   analogWrite(6,  setting + 127);
   analogWrite(9,  setting + 127);
   analogWrite(10,-setting + 127);
 }

Try experiment with different offsets, the weight of the robot and size of the wheels can make the dynamic differ.

The argument for this function should here be -100 -> +100, but you get an idea for what I'm doing :slight_smile:

@All
I have now hosted my balancerobot code, if anyone is interested :slight_smile:
http://code.google.com/p/veltobot/

Jon, Norway

Thanks! I'll give those ideas a go and let you know how I get on.

Kas, Jon-D, theres a good few links there i need to look up, thanks. as for fuzzy i have not tried it but there is a pic app note i will try to post the link for.
RE ADNS-7550 laser optical mouse encoder as a velocity encoder:
so far i have placed the encoder over a flat belt which is connected to a motor which has a heds slotted disk encoder fitted therefore i get quadrature encoder data to compare with the optical .

  1. at constant velocity the two encoders give an average velocity which is comparable within roughly 10%.
  2. the optical encoder gives an erratic reading , over and under the heds encoder.
  3. for zero velocity both read zero
  4. for very low velocity, 1mm/sec the optical reads zero !
  5. for absolute position , ie step changes, the optical very quickily has a large error. this can be tested with a pc mouse, just try to move it repeatedly back to a fixed position and see where the arrow ends up!

I emailed AVAGO with these findings and asked if the sensor has a high pass filter, they said they dont spec low speed, also the absolute accuracy is only 20-30% ! shock. also (area of image is < 2mmsq)
despite this im not giving up hope.
it is possible to read the pixel image data, if a pattern is used where the absolute dimensions are known then surely a more accurate calculation can be done. and don't call me shirley.
I asked if the ADNS-9500 super gaming sensor was any better but no mention was made in their reply, and you cant get one for love or money, same family anyway but it does need a firmware download so theres hope for a special version ?
It may be that my 7550 just didnt have the right surface but one register reports surface quality , i never got better than 75%, i tried
black htd M3 belt- raw - 0%
lightly sprayed with gold xmas metallic - 75%
any colored card 50%
aluminium foil - rubbish
embossed plastic metallized sheet - 30 %
white card with very fine black fibers - 30 %
I still need to test a lumpy dull surface. Ill try it on my brothers wife .

RE motor drivers, check that acceleration control is turned off, current limit, all the saftey features!, im just building with a new one, vn??
merry xmas everyone, :slight_smile: :slight_smile:

I still need to test a lumpy dull surface. Ill try it on my brothers wife

This is either a great insiders joke or a completely WTF comment. ;D

Lefty

Kas, Jon-D, theres a good few links there i need to look up, thanks. as for fuzzy i have not tried it but there is a pic app note i will try to post the link for.
RE ADNS-7550 laser optical mouse encoder as a velocity encoder:
so far i have placed the encoder over a flat belt which is connected to a motor which has a heds slotted disk encoder fitted therefore i get quadrature encoder data to compare with the optical .

  1. at constant velocity the two encoders give an average velocity which is comparable within roughly 10%.
  2. the optical encoder gives an erratic reading , over and under the heds encoder.
  3. for zero velocity both read zero
  4. for very low velocity, 1mm/sec the optical reads zero !
  5. for absolute position , ie step changes, the optical very quickily has a large error. this can be tested with a pc mouse, just try to move it repeatedly back to a fixed position and see where the arrow ends up!

I emailed AVAGO with these findings and asked if the sensor has a high pass filter, they said they dont spec low speed, also the absolute accuracy is only 20-30% ! shock. also (area of image is < 2mmsq)
despite this im not giving up hope.
it is possible to read the pixel image data, if a pattern is used where the absolute dimensions are known then surely a more accurate calculation can be done. and don't call me shirley.
I asked if the ADNS-9500 super gaming sensor was any better but no mention was made in their reply, and you cant get one for love or money, same family anyway but it does need a firmware download so theres hope for a special version ?
It may be that my 7550 just didnt have the right surface but one register reports surface quality , i never got better than 75%, i tried
black htd M3 belt- raw - 0%
lightly sprayed with gold xmas metallic - 75%
any colored card 50%
aluminium foil - rubbish
embossed plastic metallized sheet - 30 %
white card with very fine black fibers - 30 %
I still need to test a lumpy dull surface. Ill try it on my brothers wife .

RE motor drivers, check that acceleration control is turned off, current limit, all the saftey features!, im just building with a new one, vn??
merry xmas everyone,

Hi beautifulsmall, I am impressed :o
I suspect you may end up working for AVAGO :slight_smile:

I am preparing "Balancing robot for dummies part seven" (wireless Xbee control + KasBot V 3.0) and expect to be ready within a week

Hi everybody,

This is my first post at Arduino forum and I'd like to say thank you for creating such a great topic.

Just like you, I am interested in two wheel balancing robots. I have built my own one. My robot's construction is similar to this one:

but mine is bigger. I am sorry I cannot provide you with a photo of it right now. I will do so as soon as I can.

When trying to balance the robot, I have a couple of questions as follow:

  1. Since the two motors are not perfectly identical, there should be two more PID control loops (apart from the main balance PID loop), one for each motor, to guarantee that the real motor's velocity will strictly follow the set one. In my case, this is actually a problem because when I apply an equal voltage to the two motors, they rotate with different speeds. Especially when one wheel hits an obstacle, say a crack on the ground, and cannot cross it, the robot will rotate around the wheel (in stead of stopping or moving forward). But I didn't see such a problem mentioned before at this thread.

  2. Currently I am using the cascaded PID control approach to balance the robot. This approach has been used successfully by Brian Kuschak with his bk-bot:
    BkInnovation.com is for sale | HugeDomains
    My robot can barely balance, in the sense that it doesn't fall, but it oscillates around the equilibrium point with a frequency of 1 to 2 Hz and the oscillation's amplitude is pretty large (the wheel moves back and forth with a travel distance of ~3 inches). I have spent days tuning the PID parameters to reduce this oscillation but so far I have had no improvements. When being pushed, the robot can keep its balance, but it oscillates even more wildly. Please look at this picture to see how my robot responds to a push:

How do you guys think about this? Is this resulted from an improper set of control parameters? If you know a correct procedure for tuning the PID parameters, please show me the way ^^!

  1. The third question is about the wheel size. From my observation, it seems that with bigger wheels it is easier to balance, am I correct? Currently my wheels are made from plastic. They are hard and small (their diameter is about 3 inches, which is quite small because my robot is 1.2 metres in height). Will rubber wheels with bigger diameter be better?

Thank you for reading my questions. Any answer would be very appreciated.

I wish you a happy new year ^^

Villa

Hi Villa, welcome aboard

Please post a photo of the beast as soon as you can

  1. Since the two motors are not perfectly identical, there should be two more PID control loops (apart from the main balance PID loop), one for each motor, to guarantee that the real motor's velocity will strictly follow the set one. In my case, this is actually a problem because when I apply an equal voltage to the two motors, they rotate with different speeds. Especially when one wheel hits an obstacle, say a crack on the ground, and cannot cross it, the robot will rotate around the wheel (in stead of stopping or moving forward). But I didn't see such a problem mentioned before at this thread.

Each motor has a different PWM/speed response. I trim left PWM motor within the code and make adjustments while driving the bot using the RC controller' joystick.
You are right, we need more sophistiated control, a single PID loop doesn't cope with the job.
Also those DC motors don't run well at low speed, below PWM < 20 (no torque)
see DC motor with PID

I am impressed by this control scheme shown on the above link

I will contact Brian and ask him to stop by

  1. Currently I am using the cascaded PID control approach to balance the robot. This approach has been used successfully by Brian Kuschak with his bk-bot:
    BkInnovation.com is for sale | HugeDomains
    My robot can barely balance, in the sense that it doesn't fall, but it oscillates around the equilibrium point with a frequency of 1 to 2 Hz and the oscillation's amplitude is pretty large (the wheel moves back and forth with a travel distance of ~3 inches). I have spent days tuning the PID parameters to reduce this oscillation but so far I have had no improvements. When being pushed, the robot can keep its balance, but it oscillates even more wildly. Please look at this picture to see how my robot responds to a push:
    How do you guys think about this? Is this resulted from an improper set of control parameters? If you know a correct procedure for tuning the PID parameters, please show me the way ^^!

Looking at the above diagram, my first idea would be to increase abs(Kd). You need more damping (see post #32). Others will jump with additional ideas.
Also try changing the sign of Kd (mine is negative)

  1. The third question is about the wheel size. From my observation, it seems that with bigger wheels it is easier to balance, am I correct? Currently my wheels are made from plastic. They are hard and small (their diameter is about 3 inches, which is quite small because my robot is 1.2 metres in height). Will rubber wheels with bigger diameter be better?

I went from 80mm to 90mm wheels, I definitly noticed an improvement due to higher speed and larger contact surface with the ground.
Motors should be strong enough to cope with the additional torque.

From post #148

How about you. It seems you are interested about control as well. Any other interesting projects or something?

...
I started a new exciting project also based on control/balance.
I wont talk about it now to avoid polluting this thread

Here is the new project :slight_smile:


@Ro-Bot-X you know this one don't you ?? :wink:

The objective is to free henpecked husbands from boring domestic duties ;D ;D ;D
I fact I may also develop a balancing vacuum cleaner ::slight_smile:

** Happy New Year to everybody **

Hi, kas. Happy New Year to you!
I am doing my own balancing robot. However, there is something wrong with the fusing.
My filtered angle seems to lag the real angle for about several seconds. My accelerometer is ADXL202, and the gyro is ENC03, the Kalman filtering code which I use is from this thread .Here is the imagine on my filtering.
http://user.qzone.qq.com/513837087?ADUIN=513837087&ADSESSION=1293883100&ADTAG=CLIENT.QQ.3067_MyTip.0&ptlang=2052
Could you give some suggestions on it? Thank you!

void PIDAnglePosition(INT32S* const pGivenSpeed1, INT32S* const pGivenSpeed2, INT32S CarSpeed)
{
      INT32S ADData = 0,Acc = 0,i;
      FP32 MeaAngle,MeaAngleDot;                  FP32 AngleError,temp;
      

      Acc = MeasureAcc() + ACC_OFFSET;
      MeaAngle = asin((FP32)Acc/GRAVITY_G);                  //Measure angle by the accelerometer
      temp = MeaAngle*1000;            //translate the float into integer by multiplying 1000,then send it to PC by serialport
      SendData[4] = (INT32S)temp%1000;
      SendData[3] = (INT32S)(temp/1000);
            
      ADData = ReadTLC4541();                  //measure the anglespeed by the gyro  5000.0*(ADData-RefAD)/65536.0/0.67/K;
      MeaAngleDot = 0.001995*(RefAD-ADData) / K;
      temp = MeaAngleDot*1000;
      SendData[6] = (INT32S)temp%1000;
      SendData[5] = (INT32S)(temp/1000);
      
      kalmanCalculate(MeaAngle,MeaAngleDot);

      temp = x_angle*1000;
      SendData[8] = (INT32S)temp%1000;
      SendData[7] = (INT32S)(temp/1000);
      
      AngleError = - x_angle;
      Position += CarSpeed;                  
       *pGivenSpeed2 = *pGivenSpeed1 = AngleKp*AngleError + AngleKi*FiltAngleDot 
                                                  + PositionKp*Position + PositionKi*CarSpeed;      
}

Hello guys,
At first I want to say a word about bk-bot control algorithm, it will not work correctly, main error is that balance pid output is torgue not speed, so...
Second do not use kalman filter as main angle output, it is a little laggy and not enough accurate. Use only gyro and incremental encoders.
Ok you will say gyro have not angle reference and integration is inaccurate. Yes it is, but here is a trick, in long term equilibrium angle is always 0deg, so you only need to know short term angle. So in long term angle, program artifically slowly averaging angle to 0deg.

Here is my robot:

http://img221.imageshack.us/img221/280/bbcontrol.png

SnakeLT: Very impressive robot, can you give us any details on the algorithms you use? Normal PID loop as anyone else here or anything fancier ;)?

I'm using interactive (series) PID.

Happy New Year!

@kas: yes, that is my long term goal, but I fear it's way too hard for me to do, as I lack solid programming skills and have no time to learn and experiment

Lately I've been swamped by work, but I started some other projects that take me away from my poor balancing bot. I did not built a proper frame for my bot, I've been trying to see if a regular low profile robot can do balancing. I've come to the conclusion that large wheels are important, high COG improves balancing, high speed is required for fast corrections. That being said, my poor low height robot with small wheels and not enough speed has trouble balancing even for a split second.

So keep it up guys, I'll do some more work on my bot in a few weeks when I'll be off work.

Cheers!

@kas: Thank you for your answers. I will try your suggestions when I have access to my robot :slight_smile:

@SnakeLT: Could you explain more about this:

At first I want to say a word about bk-bot control algorithm, it will not work correctly, main error is that balance pid output is torgue not speed, so...

Why is it that the balance pid output must be torque, not speed?

Thank you,

Villa

It does not must be torgue, but in this case it is. At output you got torgue and you interpret it like speed. Look at my algorithm, and dont use motor speed pid.