Berk Yaşar YAVUZ
/
balancebot
balance
main.cpp
- Committer:
- omidece2035
- Date:
- 2015-10-20
- Revision:
- 0:9d2ceb7b8ec9
File content as of revision 0:9d2ceb7b8ec9:
#include "mbed.h" #include "LSM9DS0.h" #include "math.h" LSM9DS0 imu(p9, p10, 0x6B, 0x1D); Serial pc(USBTX, USBRX); Ticker control; // create Ticker for control algorithm Ticker db; //debugging int debug=0; int wt = 500; DigitalOut led1(LED1); //motor variables PwmOut left_motor_speed(p21); //left motor pwm A PwmOut right_motor_speed(p22); //right motor pwm B DigitalOut left_fwd_enable(p23); //fwd enable of left/A motor DigitalOut left_rev_enable(p24); //rev enable of left/A motor DigitalOut right_fwd_enable(p26); //fwd enable or right/B motor DigitalOut right_rev_enable(p25); //rev enable of right/B motor //angle variables float accelerometer_angle =0; float gyro_data =0; float gyro_angle=0; float current_angle =0; float angle_offset = 0; int i=0; //control variables float Error=0; // I had to capitalize this for some reason unlike the other vars float kp=.5; float ki=.01; float kd= 0; float setpoint=0; //reference angle float angle=0; float integral=0; float derivative = 0; float dt= 0.01; //time period 1/100 (s) float previous_error =0; float actuator_input =0; int ready = 0; float maximum_angle=15; float SCALAR = 0; void initialiation (void) { //with the "initialization" in the control loop, we may not use this //this is where offsets and sensors are set up //need to hold robot balanced at this point imu.readGyro(); angle_offset= float(imu.gy); //maybe take avg. like the other team did in a for loop } void MotorDriver (float speed) { // if speed > 0 then move robot left // if speed < 0 then move robot right if ( speed>0 ) { //move both motors in same direction right_rev_enable = 0; right_fwd_enable = 1; left_fwd_enable = 0; left_rev_enable = 1; right_motor_speed = speed; left_motor_speed = speed; //pc.printf("moving f\n"); } else if ( speed <0 ) { //move both motors in same direction right_fwd_enable = 0; right_rev_enable = 1; left_rev_enable = 0; left_fwd_enable = 1; right_motor_speed = -speed; left_motor_speed= -speed; //pc.printf("moving r\n"); } else { right_fwd_enable = 0; right_rev_enable = 0; left_rev_enable = 0; left_fwd_enable = 0; right_motor_speed = speed; left_motor_speed = speed; //pc.printf("not moving\n"); } } float calcSCALAR(float degrees) { //give it a degree such as 10 degrees, anything past that is the same as 10 degrees Error = 0 - degrees; //this is the maximum error integral = integral + (Error*dt); //Forward Euler approximation derivative = (Error - previous_error) / dt; //change wrt time previous_error = Error; SCALAR = ( (Error*kp) + (integral*ki) + (derivative*kd) ); pc.printf("here in scalar calc and error is %f and integral is %f and derivative is %f \n", Error, integral, derivative); Error=0; integral=0; derivative=0; previous_error=0; return 1; } void controlalgorithm (void) { if (i< wt) //gives you time to balance it upon reset; this is like an initialization code for the imu; { //determine current angle using a complementary filter found online http://www.pieter-jan.com/node/11 //place +z-axis up, + x-axis right, and +y-axis away from the back of the robot when robot can move left to right imu.readGyro(); gyro_data= imu.gy; imu.readAccel(); accelerometer_angle = atan2(imu.ax, imu.az) * 180 / 3.14159; //angle in degrees; positive angle is CCW, negative angle is CW; this gives the angle as determined by the accelerometer current_angle = 0.98 * (current_angle + gyro_data * dt) + 0.02 * (accelerometer_angle); i=i+1; } //if the SCALAR has been calculated and the initilization complete, start controlling if ( ready ==1 ) { imu.readGyro(); gyro_data= imu.gy; //maybe negative?? I don't think so imu.readAccel(); accelerometer_angle = atan2(imu.ax, imu.az) * 180 / 3.14159; //angle in degrees; positive angle is CCW, negative angle is CW current_angle = 0.98 * (current_angle + gyro_data * dt) + 0.02 * (accelerometer_angle); //maybe take into account integral windup Error = setpoint - current_angle; //determine the difference in angle integral = integral + (Error*dt); //Forward Euler approximation derivative = (Error - previous_error) / dt; //change wrt time previous_error = Error; actuator_input = ( (Error*kp) + (integral*ki) + (derivative*kd) ) / SCALAR; //we should scale this???? and write in terms of a PWM value [-1,1]; be careful, SCALAR is negative MotorDriver(actuator_input); } } void debugout (void) { //pc.printf ("setpoint is %f\n", setpoint); pc.printf ("actuator_input is %f\n", actuator_input); //pc.printf("Speed is: %f, angle is: %f\n\n",speed,current_angle); } main() { pc.printf("starting...\n"); uint16_t status = imu.begin(); pc.printf("LSM9DS0 WHO_AM_I's returned: 0x%X\n", status); pc.printf("Should be 0x49D4\n\n"); SCALAR= calcSCALAR(maximum_angle); //scale the actuator inputl depends on lp, kd, and ki, and maximum angle allowed control.attach(&controlalgorithm, dt); //check frequency, 100 Hz if (debug==1) { db.attach(&debugout, 0.1); } while(1) { //put some calcs here if needed; need 0.01 seconds at least if (i==wt) { // setpoint=current_angle / 1000; //take first 1000 samples for current angle then avg. it setpoint=current_angle; ready=1; i=i+1; pc.printf ("i is %d in top if statement\n\n\n\n", i); } //if (debug == 1 && i>20 ) // { // //probably need some kind of wait statement; will a wait statement affect the timer interrupt? no, i checked // pc.printf("accel: x: %f y: %f z: %f\n",imu.ax,imu.ay,imu.az); // pc.printf("gyro: x: %f y: %f z: %f\n",imu.gx,imu.gy,imu.gz); // pc.printf ("current_angle is %f\n", current_angle); // pc.printf ("setpoint is %f\n", setpoint); // pc.printf ("accelerometer_angle is %f\n", accelerometer_angle); // pc.printf ("gyro_angle is %f\n", gyro_angle); // pc.printf ("actuator_input is %f\n", actuator_input); // pc.printf ("SCALAR is %f \n", SCALAR); // pc.printf ("i is %d\n\n\n\n", i); // wait(2); // } } }