Go Down

### Topic: Balancing robot for dummies (Read 75487 times)previous topic - next topic

#### Wmgatorfan08

#45
##### Mar 27, 2012, 02:49 am
Also what do you guys think of this IMU.  The goal is to use this on a balancing robot first and if I have success I will move onto a quad copter.

#### Lauszus

#46
##### Mar 28, 2012, 11:29 pm
#rob4white
I followed this guide to find the P, I, and D constants:
http://robotics.ee.uwa.edu.au/theses/2003-Balance-Ooi.pdf see page 42:
1. Select typical operating setting for desired speed, turn off integral and derivative part, and then increase Kp to max or until oscillation occurs.
2. If system oscillates, divide Kp by 2.
3. Increase Kd and observe behaviour when changing desired speed by about 5% and choose a value of Kd that gives a fast damped response.
4. Slowly increase Ki until oscillation starts. Then divide Ki by 2 or 3.
I more or less followed that, but I then fine tuned it myself. I recommend using a wireless application, so you can set them wirelessly, as mentioned in the video, as you have to spend a lot of time finding those values.

#Wmgatorfan08
Yes I think it is possible to make a very low cost segway using those parts, but I don't think the performance will be as good, but I will still be a great learning experience and a fun project. Just take a look at AlphaZeta robot: http://arduino.cc/forum/index.php/topic,60170.msg736106.html#msg736106
That only cost approximately 20\$ excluding the motors!!

#### Wmgatorfan08

#47
##### Mar 29, 2012, 05:19 am
Sorry here is the link http://www.sparkfun.com/products/10121

I feel pretty comfortable with this IMU.  I have been reading a lot about it and have already found several examples of code to get the data that I need.  I have been using arduino for about a year now so I feel pretty confident with my ability to get the board working.  I am not as familiar with I^2C  as I should be but I am reading and working on it now.

My main concern is the motors.  I know that selecting the proper motors and wheels will make or break the project.  Ultimately I am thinking I need something with a lot of torque that can respond quickly.  I don't think I need high rpm, but it must spin fast enough to catch up with itself when falling.

Possibly this type of motor with the encoders.  http://www.robotshop.com/12v-gear-motor-encoder.html

Also correct me if I am wrong, but I am thinking something around a foot to foot and a half tall with the center of mass being around the motors.  From what I am reading the IMU needs to be near the top?

#### AlphaZeta

#48
##### Mar 29, 2012, 05:32 pm
For best results, the IMU needs to be placed near the center of the gravity of your build, wherever that is. Typically, the higher the center of gravity is, the easier it is to balance as the timing becomes less critical.

#### Wmgatorfan08

#49
##### Mar 30, 2012, 02:06 am
Yeah I guess that would be true because of the moment of inertia.  So ill move the battery toward the top and mount the IMU close to it.

#### Wmgatorfan08

#50
##### Mar 31, 2012, 05:48 am
I ordered the 6dof IMU  board from sparkfun tonight!

#### Wmgatorfan08

#51
##### Apr 03, 2012, 05:52 am
What do you guys think of this motor and encoder setup??

http://www.robotshop.com/cytron-12v-430rpm-15-57oz-gear-motor-encoder-2.html

#### AlphaZeta

#52
##### Apr 03, 2012, 05:15 pm
Sounds like you are thinking building a big one . They look pretty powerful for sure, just make sure that your battery source can handle the load. Two of these motors will draw around 2A and the stall current will be much higher.

#### batista1987

#53
##### Apr 03, 2012, 10:44 pmLast Edit: Apr 03, 2012, 11:14 pm by batista1987 Reason: 1
Hi guys, i want to buy this dual driver http://www.pololu.com/catalog/product/1213 for a 29:1 pololu motor. As regard to you it's ok? Why is necessary this driver? i say this because, this driver it's ok until 9 A, but the motor requires 5 A max. Maybe this http://www.robot-italy.com/product_info.php?cPath=83_30&products_id=2386?

#### Wmgatorfan08

#54
##### Apr 04, 2012, 01:39 am
So I am really struggling to pick out the right motor.  I really want to stick with my motor shield but it has a max of 2 amps.  Most motors that I am finding have low free running current but the stall current exceeds my motor shield.  Do these type of bots push the motors to their stall current?  I do not see my design pushing the motor anywhere close to its stall current?

#### batista1987

#55
##### Apr 07, 2012, 11:50 am
I've bought the pololu 29:1 and the relative motor control. So i've a questions: How connect the wires of motor and encoder to arduino and motor control?

#### MAAhelp

#56
##### Apr 09, 2012, 09:10 pm
Hi all,

Started a project around 2 months ago to build an autonomous robot. The wheels and motors I'm using are as follows: http://www.technobotsonline.com/banebot-wheel-124x20mm-1-2-hex-shore-50.html, http://www.pololu.com/catalog/product/1443.

Although I am able to balance the robot using a PID algorithm, I am finding it tough to control the position of the robot (via the encoders). I have a tilt sensor sending me the angle the robot is at and setting the motorspeed accordingly. To control the position of the robot I have been varying the reference angle to try and move the robot towards a reference point(eg: x = 0) to keep the robot in the same position but I have not had great results.

State space control would be best to control multiple inputs/outputs but I am not sure how this can be done on the Arduino Uno, any ideas?
If state space isn't used how is the best way to approach the problem I am encountering with the position?

The code I am using is as follows:
Code: [Select]

#include "DualVNH5019MotorShield.h"
#include "math.h"

enum PinAssignments {
encoderPinA = 2,   // right
encoderPinB = 3,   // left
clearButton = 12    // another two pins
};

DualVNH5019MotorShield md;
int sensorPin = A2;
float setpointang = 501.0;
int oldangle, oldangle_1, oldangle_2, angle, newangle, current_1, current_2, errorpos, a, b, c = 0;
double sumangle, output, oldpos, oldpos_1, oldpos_2, derivpos, integpos = 0.0;
int Kp = 20;
int ZoneA = 2000;
int ZoneB = 1000;
float motorspeed, deriv, error, errorposctrl;
double Kd = 0.3;
float freq = 66.67;
float T = ((1/freq)*1000)-0.5;
float Kp_1 = 1.00 ;
float posScaleA = 500.0;
float posScaleB = 1000.0;
float posScaleC = 2000.0;

volatile unsigned int encoderPos = 0;  // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;

void setup()
{

Serial.begin(115200);
md.init();

TCCR1B = TCCR1B & 0b11111000 | 0x01;

pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(clearButton, INPUT);

// turn on pullup resistors
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinB, HIGH);
digitalWrite(clearButton, HIGH);

attachInterrupt(0, doEncoderB, RISING);  //CHANGE
}

void loop()
{

if ((angle < 300) || (angle > 700))
{
md.setM1Speed(0);
md.setM2Speed(0);
}
else if ((current_1 < 6000) || (current_2 < 6000) )
{

//PID
oldangle_2 = oldangle_1;
oldangle_1 = oldangle;
oldangle = newangle;
newangle = (setpointang - angle);
deriv = ((newangle + (3*oldangle) -(3*oldangle_1) - oldangle_2)*(freq/6));

error = (Kp*(newangle) + Kd*(deriv));

//Translating PID output value to a value within the range of the motor driver
motorspeed = ((error/511)*400);

//Driving the motors
md.setM1Speed(motorspeed);
md.setM2Speed(motorspeed);

//---------------------------------------------------------------------------------------------------------------------------------------------------------------Angle Control End

if (lastReportedPos != encoderPos) {
if (motorspeed < 0)
{
errorpos = errorpos - (lastReportedPos - encoderPos);
}
else if (motorspeed > 0)
{
errorpos = errorpos + (lastReportedPos - encoderPos);
}
lastReportedPos = encoderPos;
}

errorposctrl = errorpos;
Serial.print("   errorposctrl:  ");
Serial.print(errorposctrl);

float a = (errorposctrl/posScaleA);
float b = (errorposctrl/posScaleB);
float c = (errorposctrl/posScaleC);

if (abs(errorposctrl) > ZoneA)
{
setpointang = setpointang - (a);
}
else if (abs(errorposctrl) > ZoneB)
{
setpointang = setpointang - (b);
}
else
{
setpointang = setpointang - (c);
}

Serial.print("     a:  ");
Serial.print(a);
Serial.print("    b:   ");
Serial.print(b);
Serial.print("     c:   ");
Serial.println(c);
//

//Serial.print("    errorpos:   ");
//Serial.print(errorpos);
//Serial.print("     encoderPos:   ");
//Serial.println(encoderPos);

//delay((int)T);

}
}

//// Interrupt on A changing state
//void doEncoderA(){
//      encoderPos += 1;
//}

// Interrupt on B changing state, same as A above
void doEncoderB()
{
encoderPos += 1;
}

MAAhelp

#### MAAhelp

#57
##### Apr 10, 2012, 06:02 pm

Hi all,

Started a project around 2 months ago to build an autonomous robot. The wheels and motors I'm using are as follows: http://www.technobotsonline.com/banebot-wheel-124x20mm-1-2-hex-shore-50.html, http://www.pololu.com/catalog/product/1443.

Although I am able to balance the robot using a PID algorithm, I am finding it tough to control the position of the robot (via the encoders). I have a tilt sensor sending me the angle the robot is at and setting the motorspeed accordingly. To control the position of the robot I have been varying the reference angle to try and move the robot towards a reference point(eg: x = 0) to keep the robot in the same position but I have not had great results.

State space control would be best to control multiple inputs/outputs but I am not sure how this can be done on the Arduino Uno, any ideas?
If state space isn't used how is the best way to approach the problem I am encountering with the position?

The code I am using is as follows:
Code: [Select]

#include "DualVNH5019MotorShield.h"
#include "math.h"

enum PinAssignments {
encoderPinA = 2,   // right
encoderPinB = 3,   // left
clearButton = 12    // another two pins
};

DualVNH5019MotorShield md;
int sensorPin = A2;
float setpointang = 501.0;
int oldangle, oldangle_1, oldangle_2, angle, newangle, current_1, current_2, errorpos, a, b, c = 0;
double sumangle, output, oldpos, oldpos_1, oldpos_2, derivpos, integpos = 0.0;
int Kp = 20;
int ZoneA = 2000;
int ZoneB = 1000;
float motorspeed, deriv, error, errorposctrl;
double Kd = 0.3;
float freq = 66.67;
float T = ((1/freq)*1000)-0.5;
float Kp_1 = 1.00 ;
float posScaleA = 500.0;
float posScaleB = 1000.0;
float posScaleC = 2000.0;

volatile unsigned int encoderPos = 0;  // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;

void setup()
{

Serial.begin(115200);
md.init();

TCCR1B = TCCR1B & 0b11111000 | 0x01;

pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(clearButton, INPUT);

// turn on pullup resistors
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinB, HIGH);
digitalWrite(clearButton, HIGH);

attachInterrupt(0, doEncoderB, RISING);  //CHANGE
}

void loop()
{

if ((angle < 300) || (angle > 700))
{
md.setM1Speed(0);
md.setM2Speed(0);
}
else if ((current_1 < 6000) || (current_2 < 6000) )
{

//PID
oldangle_2 = oldangle_1;
oldangle_1 = oldangle;
oldangle = newangle;
newangle = (setpointang - angle);
deriv = ((newangle + (3*oldangle) -(3*oldangle_1) - oldangle_2)*(freq/6));

error = (Kp*(newangle) + Kd*(deriv));

//Translating PID output value to a value within the range of the motor driver
motorspeed = ((error/511)*400);

//Driving the motors
md.setM1Speed(motorspeed);
md.setM2Speed(motorspeed);

//---------------------------------------------------------------------------------------------------------------------------------------------------------------Angle Control End

if (lastReportedPos != encoderPos) {
if (motorspeed < 0)
{
errorpos = errorpos - (lastReportedPos - encoderPos);
}
else if (motorspeed > 0)
{
errorpos = errorpos + (lastReportedPos - encoderPos);
}
lastReportedPos = encoderPos;
}

errorposctrl = errorpos;
Serial.print("   errorposctrl:  ");
Serial.print(errorposctrl);

float a = (errorposctrl/posScaleA);
float b = (errorposctrl/posScaleB);
float c = (errorposctrl/posScaleC);

if (abs(errorposctrl) > ZoneA)
{
setpointang = setpointang - (a);
}
else if (abs(errorposctrl) > ZoneB)
{
setpointang = setpointang - (b);
}
else
{
setpointang = setpointang - (c);
}

Serial.print("     a:  ");
Serial.print(a);
Serial.print("    b:   ");
Serial.print(b);
Serial.print("     c:   ");
Serial.println(c);
//

//Serial.print("    errorpos:   ");
//Serial.print(errorpos);
//Serial.print("     encoderPos:   ");
//Serial.println(encoderPos);

//delay((int)T);

}
}

//// Interrupt on A changing state
//void doEncoderA(){
//      encoderPos += 1;
//}

// Interrupt on B changing state, same as A above
void doEncoderB()
{
encoderPos += 1;
}

MAAhelp

It seems that the problem I am currently encountering could be easily solved by just adding the integral term with regards to the PID control I am currently trying. Does this make sense?

#### aasanchez

#58
##### Apr 13, 2012, 06:17 pm
I have this motors:
http://www.robotshop.com/world/solutions-cubed-ezr-5.html

And this Motor board controller:
http://www.sparkfun.com/products/9670

I would like to know if you think this hardware is possible to build a robot of this type??

#### Lauszus

#59
##### Apr 13, 2012, 06:31 pm
#aasanchez
Yes I think is possible, but the motors are not that powerfull (only 3.6 kg-cm torque), so start out by making a small version first.
For instance I used these motors from Pololu: http://www.pololu.com/catalog/product/1443/specs which has a torque of 8 kg-cm.
Also I think it is weird, that the peak current is not listed on the website or in the pdf (http://www.robotshop.com/world/PDF/rbsol03_manual.pdf), but if think the motor controller will be okay - if it get's very how, then add a heatsink.

Regards
Lauszus

Go Up