Berk Yaşar YAVUZ
/
balancebot
balance
Diff: main.cpp
- Revision:
- 0:9d2ceb7b8ec9
diff -r 000000000000 -r 9d2ceb7b8ec9 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Oct 20 04:32:01 2015 +0000 @@ -0,0 +1,192 @@ +#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); +// } + } +}