Balancing Rover
Overview
This two-wheeled rover is designed to balance and stay upright even on tilted surfaces. It runs on 4 AA batteries and uses a dual H-Bridge to control the wheel motors. Feedback control balancing is implemented using data gathered from Hall effect encoders and an LSM9DS1 IMU. In addition, there is a speaker on the robot that gives auditory feedback to the user. The further the robot is from level, the louder that speaker buzzes.
Members
- Neil Hardy
- Madeleyne Vaca
Parts
- Dual H-Bridge
- LSM9DS1 IMU
- 4 AA batteries with pack
- barrel connector
- 2 DC motors
- Encoder kit
Wiring
mbed | LSM9DS1 |
---|---|
p27 | SDA |
p26 | SCL |
VDD | VOUT |
GND | GND |
mbed | Dual H-Bridge | Left Motor | Right Motor |
---|---|---|---|
p22 | PWMA | - | - |
p20 | AIN2 | - | - |
p19 | AIN1 | - | - |
p16 | ^/STBY | - | - |
p18 | BIN1 | - | - |
p17 | BIN2 | - | - |
p21 | PWMB | - | - |
VOUT | VCC | - | - |
VU | VMOT | - | - |
GND | GND | - | - |
- | AO1 | pos | - |
- | AO2 | neg | - |
- | BO1 | - | pos |
- | BO2 | - | neg |
mbed | Left Encoder | Right Encoder |
---|---|---|
VOUT | pwr+(red) | pwr+(red) |
GND | pwr-(black) | pwr-(black) |
p15 | data (white) | - |
p16 | - | data (white) |
include the mbed library with this snippet
#include "mbed.h" #include "LSM9DS1.h" #define PI 3.14159 #define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA. #include "motordriver.h" #include "MAF.h" //Debugging Serial pc(USBTX, USBRX); //For data //LSM9DS1 IMU(p9, p10, 0x6B, 0x1E); LSM9DS1 IMU(p28, p27, 0xD6, 0x3C); Motor lmotor(p22, p19, p20, 0); Motor rmotor(p21, p18, p17, 0); int count = 0; //data float roll; MAF avg; PwmOut speaker(p23); float printAttitude(float ax, float ay, float az, float mx, float my, float mz) { float roll = atan2(ay, az); float pitch = atan2(-ax, sqrt(ay * ay + az * az)); // touchy trig stuff to use arctan to get compass heading (scale is 0..360) mx = -mx; float heading; if (my == 0.0) heading = (mx < 0.0) ? 180.0 : 0.0; else heading = atan2(mx, my)*360.0/(2.0*PI); //pc.printf("heading atan=%f \n\r",heading); heading -= DECLINATION; //correct for geo location if(heading>180.0) heading = heading - 360.0; else if(heading<-180.0) heading = 360.0 + heading; else if(heading<0.0) heading = 360.0 + heading; // Convert everything from radians to degrees: //heading *= 180.0 / PI; pitch *= 180.0 / PI; roll *= 180.0 / PI; if (count > 10) { roll = avg.update(roll); } else { count++; avg.update(roll); } pc.printf("Pitch: %f, Roll: %f degrees\n\r",pitch,roll); pc.printf("Magnetic Heading: %f degrees\n\r",heading); return roll; } int main() { //Calibrate IMU IMU.begin(); if (!IMU.begin()) { pc.printf("Failed to communicate with LSM9DS1.\n"); } IMU.calibrate(1); IMU.calibrateMag(0); speaker.period(1.0/200.0); // 500hz period while(!IMU.magAvailable(X_AXIS)); IMU.readMag(); while(!IMU.accelAvailable()); IMU.readAccel(); while(!IMU.gyroAvailable()); IMU.readGyro(); roll = printAttitude(IMU.calcAccel(IMU.ax), IMU.calcAccel(IMU.ay), IMU.calcAccel(IMU.az), IMU.calcMag(IMU.mx), IMU.calcMag(IMU.my), IMU.calcMag(IMU.mz)); float prevRoll = roll; float pGain = 1.0/15.0; float dGain = 1.0/10.0; while(1) { while(!IMU.magAvailable(X_AXIS)); IMU.readMag(); while(!IMU.accelAvailable()); IMU.readAccel(); while(!IMU.gyroAvailable()); IMU.readGyro(); /*pc.printf(" X axis Y axis Z axis\n\r"); pc.printf("gyro: %9f %9f %9f in deg/s\n\r", IMU.calcGyro(IMU.gx), IMU.calcGyro(IMU.gy), IMU.calcGyro(IMU.gz)); pc.printf("accel: %9f %9f %9f in Gs\n\r", IMU.calcAccel(IMU.ax), IMU.calcAccel(IMU.ay), IMU.calcAccel(IMU.az));*/ roll = printAttitude(IMU.calcAccel(IMU.ax), IMU.calcAccel(IMU.ay), IMU.calcAccel(IMU.az), IMU.calcMag(IMU.mx), IMU.calcMag(IMU.my), IMU.calcMag(IMU.mz)); /* For differential control create another variable that stores the previous roll value. Subtract it from the current to get the difference. Currently, speed is equal to pgain*roll+dgain*(roll difference)*/ float lmotorSpeed = roll*pGain + (roll - prevRoll)*dGain; float rmotorSpeed = roll*pGain + (roll - prevRoll)*dGain; //adding extra power close to the balancing point to overcome friction. //without this the robot isn't moving fast enough to cover the last tiny distance to balance if (fabs(lmotorSpeed) < .1) lmotorSpeed*=1.2; if (fabs(rmotorSpeed) < .1) rmotorSpeed*=1.2; //set speaker loudness and motor speeds speaker = fabs(lmotorSpeed/20.0); lmotor.speed(lmotorSpeed); rmotor.speed(rmotorSpeed); } }
Please log in to post comments.