Dependencies: mbed QEI HIDScope biquadFilter MODSERIAL FXOS8700Q FastPWM
Diff: main.cpp
- Revision:
- 21:a316452da8cd
- Parent:
- 20:0f6a88f29a71
- Parent:
- 19:fb3d570a115e
- Child:
- 22:335a30b0825d
--- a/main.cpp Mon Oct 21 12:09:28 2019 +0000 +++ b/main.cpp Mon Oct 21 13:23:11 2019 +0000 @@ -6,6 +6,8 @@ #include "FastPWM.h" #include <iostream> MODSERIAL pc(USBTX, USBRX); +QEI motor2_pos (D8, D9, NC, 32); +QEI motor1_pos (D12, D13, NC, 32); AnalogIn ain2(A2); AnalogIn ain1(A3); DigitalOut dir2(D4); @@ -23,7 +25,7 @@ Timeout EMG_peak; Timeout turn; Ticker sample_timer; -HIDScope scope( 2); +HIDScope scope( 4); DigitalOut ledred(LED_RED); DigitalOut ledblue(LED_BLUE); DigitalOut ledgreen(LED_GREEN); @@ -40,6 +42,7 @@ volatile bool ignore_turn=true; enum states{Waiting,Position_calibration,EMG_calibration,Homing,Operating,Demo,Failure}; states currentState=Waiting; +volatile bool motor1_calibrated=false; static float v_refx; //reference speeds static float v_refy; @@ -48,14 +51,9 @@ volatile float theta1_old = 0.0; //feedback variables volatile float theta2_old = 0.0; -int m1_count; -float m1_angle; -int m2_count; -float m2_angle; -float pi = 3.14; -float error_x; -float error_y; +float error_1; +float error_2; //PID controller variables bool q = true; @@ -67,10 +65,16 @@ float u_p; float u_i; float u_d; -float error_integral = 0.0; +float error_integral1 = 0.0; +float error_integral2 = 0.0; float u_1; float u_2; +const float angle2_offset=asin(0.2); +const float angle1_offset=asin(3.8/35.0); +const double pi=3.1415926535897932384626; +volatile float theta1; +volatile float theta2; void read_emg() { @@ -112,18 +116,69 @@ RMS1[count1%150]=If1; /* Set the sampled emg values in channel 0 (the first channel) and 1 (the second channel) in the 'HIDScope' instance named 'scope' */ P1=sqrt(RMS_value1); - scope.set(0, P0 ); // send root mean squared - scope.set(1, notched0); /* Repeat the step above if required for more channels of required (channel 0 up to 5 = 6 channels) * Ensure that enough channels are available (HIDScope scope( 2 )) * Finally, send all channels to the PC at once */ - scope.send(); /* To indicate that the function is working, the LED is toggled */ ledred=1; ledgreen=0; ledblue=1; } +void get_angles(void) +{ + float pulses1=motor1_pos.getPulses(); + float pulses2=motor2_pos.getPulses(); + theta1=angle1_offset+pulses1*17.0/16.0*2*pi/131.0/32.0; + theta2=angle2_offset+pulses2*17.0/16.0*2*pi/131.0/32.0; +} + +void pos_cal(void) +{ + float t=state_time.read(); + static int pos_time_counter=0; + static int last_ticks=10000; + float pulses; + pos_time_counter+=1; + if(!motor1_calibrated&&t>1.0f) + { + dir1=1; //??? + motor1_pwm.write(0.8f); + pulses=motor1_pos.getPulses(); + if(pos_time_counter%500==0&&fabs(pulses-last_ticks)<1) + { + ledblue=!ledblue; + motor1_pos.reset(); + last_ticks=10000; + state_time.reset(); + dir1=!dir1; + } + else if(pos_time_counter%500==0) + { + last_ticks=motor1_pos.getPulses(); + } + + } + else if(t>1.0f) + { + motor1_pwm.write(0.0f); + dir2=1; //??? + motor2_pwm.write(0.8f); + pulses=motor2_pos.getPulses(); + if(pos_time_counter%500==0&&fabs(pulses-last_ticks)<1) + { + ledblue=!ledblue; + motor2_pos.reset(); + motor2_pwm.write(0.0f); + } + else if(pos_time_counter%500==0) + { + last_ticks=motor2_pos.getPulses(); + } + } + +} + void record_min_max(void) { float t=state_time.read(); @@ -195,39 +250,71 @@ } void error(void){ - m1_count = motor1.getPulses(); // Read out both motor counts and convert them to rads. - m1_angle = (float)m1_count / 4200.0f * (2.0f * pi); - m2_count = motor2.getPulses(); - m2_angle = (float)m1_count / 4200.0f * (2.0f * pi); - float dvd=L * (tan(m2_angle) * pow(tan(m1_angle),2) - tan(m1_angle) * pow(tan(m2_angle),2)); + float dvd=L * (tan(theta2) * pow(tan(theta1),2) - tan(theta1) * pow(tan(theta2),2)); - float a = ( -pow(cos(m1_angle),2) * pow((tan(m1_angle)+tan(m2_angle)),2) * pow(tan(m1_angle),2) ) / dvd; // inverse matrix components of differential x and differential y - float b = ( pow(cos(m1_angle),2) * pow((tan(m1_angle)+tan(m2_angle)),2) * tan(m1_angle) ) / dvd; - float c = ( pow(cos(m2_angle),2) * pow((tan(m1_angle)+tan(m2_angle)),2) * pow(tan(m2_angle),2) ) / dvd; - float d = ( pow(cos(m2_angle),2) * pow((tan(m1_angle)+tan(m2_angle)),2) * pow(tan(m2_angle),2) ) / dvd; + float a = ( -pow(cos(theta1),2) * pow((tan(theta1)+tan(theta2)),2) * pow(tan(theta1),2) ) / dvd; // inverse matrix components of differential x and differential y + float b = ( pow(cos(theta1),2) * pow((tan(theta1)+tan(theta2)),2) * tan(theta1) ) / dvd; + float c = ( pow(cos(theta2),2) * pow((tan(theta1)+tan(theta2)),2) * pow(tan(theta2),2) ) / dvd; + float d = ( pow(cos(theta2),2) * pow((tan(theta1)+tan(theta2)),2) * pow(tan(theta2),2) ) / dvd; float theta1_dot = a*v_refx + b*v_refy; float theta2_dot = c*v_refx + d*v_refy; - float theta1_ref = theta1_old+theta1_dot*T; - float theta2_ref = theta2_old+theta2_dot*T; - - error_x = m1_angle - theta1_ref; - error_y = m2_angle - theta2_ref; + float theta1_ref; + float theta2_ref; + if(currentState==Operating) + { + theta1_ref = theta1_old+theta1_dot*T; + theta2_ref = theta2_old+theta2_dot*T; + } + else if(currentState==Homing) + { + theta1_ref=pi/4.0f; + theta2_ref=pi/4.0f; + } + error_1 = theta1 - theta1_ref; + error_2 = theta2 - theta2_ref; theta1_old = theta1_ref; theta2_old = theta2_ref; } -float PID(float err){ +float PID1(float err){ //P action - u_p = Kp * fabs(err); + u_p = Kp * err; //I action - error_integral = error_integral + err * T; - u_i = Ki * error_integral; + error_integral1 = error_integral1 + err * T; + u_i = Ki * error_integral1; + +/* + //D action + if(q){ + error_prev = err; + q=false; + } + + float error_derivative = (err - error_prev)/T; + float filtered_error_derivative = LowPassFilter.step(error_derivative); + u_d = Kd * filtered_error_derivative; + error_prev = err; + +*/ + + u = u_p + u_i; + + return u; + } + +float PID2(float err){ + //P action + u_p = Kp * err; + + //I action + error_integral2 = error_integral2 + err * T; + u_i = Ki * error_integral2; /* //D action @@ -249,20 +336,21 @@ } void setPWM_controller(void){ - u_1 = PID(error_x); - u_2 = PID(error_y); + error(); + u_1 = PID1(error_1); + u_2 = PID2(error_2); if(u_1 < 0.0f){ - dir1 = 1; + dir1 = 0; }else{ - dir1 = 0; + dir1 = 1; } motor1_pwm.write(fabs(u_1)); if(u_2 < 0.0f){ - dir2 = 1; + dir2 = 0; }else{ - dir2 = 0; + dir2 = 1; } motor2_pwm.write(fabs(u_1)); @@ -270,6 +358,12 @@ void sample() { + get_angles(); + scope.set(0,P0); + scope.set(1,P1); + scope.set(2,theta1); + scope.set(3,theta2); + scope.send(); switch(currentState) { case Waiting: @@ -281,6 +375,7 @@ ledred=1; ledgreen=1; ledblue=0; + pos_cal(); break; case EMG_calibration: ledred=1; @@ -290,6 +385,7 @@ record_min_max(); break; case Homing: + setPWM_controller(); ledred=0; ledgreen=1; ledblue=0; @@ -314,6 +410,15 @@ motor2_pwm.write(0.0); break; } + //Preventing the machine from breaking + if(theta1>=1.6f) + { + dir1=1; + } + if(theta2>=1.6f) + { + dir2=2; + } } void error_occur() @@ -321,10 +426,10 @@ currentState=Failure; } -void button_press() +void button_press(void) //Press button to change state { - state_time.start(); + state_time.reset(); switch(currentState) { case Waiting: @@ -332,7 +437,15 @@ wait(1); break; case Position_calibration: - currentState=EMG_calibration; + if(!motor1_calibrated) + { + motor1_calibrated=true; + wait(1); + } + else + { + currentState=EMG_calibration; + } wait(1); break; case EMG_calibration: @@ -365,7 +478,7 @@ int frequency_pwm=10000; motor1_pwm.period(1.0/frequency_pwm); motor2_pwm.period(1.0/frequency_pwm); - + state_time.start(); while (true) { wait(10); }