Dependencies: MODSERIAL QEI biquadFilter mbed
Fork of BioRobotics_Main by
main.cpp@5:224c1fe73a8f, 2018-09-28 (annotated)
- Committer:
- s1680897
- Date:
- Fri Sep 28 09:43:45 2018 +0000
- Revision:
- 5:224c1fe73a8f
- Parent:
- 4:de0923cf6bcc
Biorobotics 2017
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
CasperBerkhout | 0:4141aef83f4b | 1 | #include "QEI.h" |
CasperBerkhout | 0:4141aef83f4b | 2 | #include "math.h" |
CasperBerkhout | 0:4141aef83f4b | 3 | #include "mbed.h" |
CasperBerkhout | 0:4141aef83f4b | 4 | //#include "HIDScope.h" //set mbed library version to 119 for HIDScope to work |
CasperBerkhout | 0:4141aef83f4b | 5 | #include "MODSERIAL.h" |
CasperBerkhout | 0:4141aef83f4b | 6 | #include "BiQuad.h" |
CasperBerkhout | 0:4141aef83f4b | 7 | |
CasperBerkhout | 0:4141aef83f4b | 8 | //left pot to set reference position. |
CasperBerkhout | 0:4141aef83f4b | 9 | //right pot to set Kp, right pot sets Ki when (right)button is pressed down |
CasperBerkhout | 0:4141aef83f4b | 10 | |
CasperBerkhout | 0:4141aef83f4b | 11 | |
CasperBerkhout | 0:4141aef83f4b | 12 | //--------------object creation------------------ |
CasperBerkhout | 0:4141aef83f4b | 13 | Serial pc(USBTX, USBRX); |
CasperBerkhout | 0:4141aef83f4b | 14 | //Use X4 encoding. |
CasperBerkhout | 0:4141aef83f4b | 15 | //QEI wheel(p29, p30, NC, 624, QEI::X4_ENCODING); |
CasperBerkhout | 0:4141aef83f4b | 16 | //Use X2 encoding by default. |
CasperBerkhout | 0:4141aef83f4b | 17 | QEI enc1(D13, D12, NC, 32); //enable the encoder |
CasperBerkhout | 0:4141aef83f4b | 18 | QEI enc2(D15, D14, NC, 32); //enable the encoder |
CasperBerkhout | 0:4141aef83f4b | 19 | PwmOut M1_speed(D6); |
CasperBerkhout | 0:4141aef83f4b | 20 | PwmOut M2_speed(D5); |
CasperBerkhout | 0:4141aef83f4b | 21 | DigitalOut M1_direction(D7); |
CasperBerkhout | 0:4141aef83f4b | 22 | DigitalOut M2_direction(D4); |
CasperBerkhout | 0:4141aef83f4b | 23 | AnalogIn potmeter(A0); //left pot |
CasperBerkhout | 0:4141aef83f4b | 24 | AnalogIn potmeter2(A1); //right pot |
CasperBerkhout | 1:d7299175a12e | 25 | InterruptIn button1(D2); //hardware interrupt for stopping motors - right button |
CasperBerkhout | 1:d7299175a12e | 26 | DigitalIn LimSW1(D9); |
CasperBerkhout | 1:d7299175a12e | 27 | DigitalIn LimSW2(D8); |
CasperBerkhout | 1:d7299175a12e | 28 | DigitalIn HomStart(D3); // - left button |
CasperBerkhout | 1:d7299175a12e | 29 | |
CasperBerkhout | 4:de0923cf6bcc | 30 | BiQuad bqlowpass(0.4354, 0.8709, 0.4354, 0.5179, 0.2238); |
CasperBerkhout | 0:4141aef83f4b | 31 | //create scope objects - note: script won't run when HID usb port is not connected |
CasperBerkhout | 0:4141aef83f4b | 32 | //HIDScope scope(5); //set # of channels |
CasperBerkhout | 1:d7299175a12e | 33 | |
CasperBerkhout | 1:d7299175a12e | 34 | Ticker motor_update1; |
CasperBerkhout | 1:d7299175a12e | 35 | Ticker motor_update2; |
CasperBerkhout | 1:d7299175a12e | 36 | Ticker error_update; |
CasperBerkhout | 0:4141aef83f4b | 37 | |
s1680897 | 5:224c1fe73a8f | 38 | //Define objects EMG filter |
s1680897 | 5:224c1fe73a8f | 39 | AnalogIn emg2( A2 ); |
s1680897 | 5:224c1fe73a8f | 40 | AnalogIn emg3( A3 ); |
s1680897 | 5:224c1fe73a8f | 41 | AnalogIn emg4( A4 ); |
s1680897 | 5:224c1fe73a8f | 42 | AnalogIn emg5( A5 ); |
CasperBerkhout | 0:4141aef83f4b | 43 | |
s1680897 | 5:224c1fe73a8f | 44 | |
s1680897 | 5:224c1fe73a8f | 45 | Ticker sample_timer; |
s1680897 | 5:224c1fe73a8f | 46 | Ticker scope_timer; |
s1680897 | 5:224c1fe73a8f | 47 | |
s1680897 | 5:224c1fe73a8f | 48 | DigitalOut ledred(LED_RED); |
s1680897 | 5:224c1fe73a8f | 49 | DigitalOut ledblue(LED_BLUE); |
s1680897 | 5:224c1fe73a8f | 50 | DigitalOut ledgreen(LED_GREEN); |
s1680897 | 5:224c1fe73a8f | 51 | DigitalOut led2(LED_RED); |
s1680897 | 5:224c1fe73a8f | 52 | DigitalIn button_cal (SW2); |
s1680897 | 5:224c1fe73a8f | 53 | |
s1680897 | 5:224c1fe73a8f | 54 | |
s1680897 | 5:224c1fe73a8f | 55 | //-----------------variable declaration---------------- |
CasperBerkhout | 0:4141aef83f4b | 56 | int pwm_freq = 500; |
CasperBerkhout | 0:4141aef83f4b | 57 | float set_speed; |
CasperBerkhout | 0:4141aef83f4b | 58 | float reference_pos; |
CasperBerkhout | 0:4141aef83f4b | 59 | |
CasperBerkhout | 0:4141aef83f4b | 60 | |
CasperBerkhout | 0:4141aef83f4b | 61 | |
CasperBerkhout | 0:4141aef83f4b | 62 | double M1_home; |
CasperBerkhout | 0:4141aef83f4b | 63 | double M1_error_pos = 0; |
CasperBerkhout | 1:d7299175a12e | 64 | float M1_Kp = 2; |
CasperBerkhout | 1:d7299175a12e | 65 | float M1_Ki = 4; |
CasperBerkhout | 3:455b79d42636 | 66 | float M1_Kd = 0.19; |
CasperBerkhout | 0:4141aef83f4b | 67 | double M1_e_int=0; |
CasperBerkhout | 0:4141aef83f4b | 68 | double M1_e_prior=0; |
CasperBerkhout | 0:4141aef83f4b | 69 | |
CasperBerkhout | 0:4141aef83f4b | 70 | double M2_home; |
CasperBerkhout | 0:4141aef83f4b | 71 | double M2_error_pos = 0; |
CasperBerkhout | 4:de0923cf6bcc | 72 | float M2_Kp = 1.5; |
CasperBerkhout | 4:de0923cf6bcc | 73 | float M2_Ki = 0.5; |
CasperBerkhout | 1:d7299175a12e | 74 | float M2_Kd = 0; |
CasperBerkhout | 0:4141aef83f4b | 75 | double M2_e_int=0; |
CasperBerkhout | 0:4141aef83f4b | 76 | double M2_e_prior=0; |
CasperBerkhout | 0:4141aef83f4b | 77 | |
CasperBerkhout | 2:c7369b41f7ae | 78 | double setpoint = 0; |
CasperBerkhout | 2:c7369b41f7ae | 79 | |
CasperBerkhout | 2:c7369b41f7ae | 80 | double M1_rel_pos; |
CasperBerkhout | 2:c7369b41f7ae | 81 | double M2_rel_pos; |
CasperBerkhout | 2:c7369b41f7ae | 82 | |
CasperBerkhout | 0:4141aef83f4b | 83 | float Ts = 0.002; //500hz sample freq |
CasperBerkhout | 0:4141aef83f4b | 84 | |
s1680897 | 5:224c1fe73a8f | 85 | float gain_factor = 1.5; |
s1680897 | 5:224c1fe73a8f | 86 | double x_vel; |
s1680897 | 5:224c1fe73a8f | 87 | double y_vel; |
s1680897 | 5:224c1fe73a8f | 88 | |
CasperBerkhout | 1:d7299175a12e | 89 | bool M1homflag; |
CasperBerkhout | 1:d7299175a12e | 90 | bool M2homflag; |
CasperBerkhout | 1:d7299175a12e | 91 | bool Homstartflag; |
CasperBerkhout | 1:d7299175a12e | 92 | |
s1680897 | 5:224c1fe73a8f | 93 | /** Sample function |
s1680897 | 5:224c1fe73a8f | 94 | * this function samples the emg and sends it to HIDScope |
s1680897 | 5:224c1fe73a8f | 95 | **/ |
s1680897 | 5:224c1fe73a8f | 96 | int P= 200; |
s1680897 | 5:224c1fe73a8f | 97 | double A[200]; |
s1680897 | 5:224c1fe73a8f | 98 | |
s1680897 | 5:224c1fe73a8f | 99 | double sig_2_abs; |
s1680897 | 5:224c1fe73a8f | 100 | double sig_3_abs; |
s1680897 | 5:224c1fe73a8f | 101 | double sig_4_abs; |
s1680897 | 5:224c1fe73a8f | 102 | double sig_5_abs; |
s1680897 | 5:224c1fe73a8f | 103 | double movmean2; |
s1680897 | 5:224c1fe73a8f | 104 | double movmean3; |
s1680897 | 5:224c1fe73a8f | 105 | double movmean4; |
s1680897 | 5:224c1fe73a8f | 106 | double movmean5; |
s1680897 | 5:224c1fe73a8f | 107 | double emgsample2; |
s1680897 | 5:224c1fe73a8f | 108 | double emgsample3; |
s1680897 | 5:224c1fe73a8f | 109 | double emgsample4; |
s1680897 | 5:224c1fe73a8f | 110 | double emgsample5; |
s1680897 | 5:224c1fe73a8f | 111 | |
s1680897 | 5:224c1fe73a8f | 112 | enum States {cal2,cal3,cal4,cal5}; |
s1680897 | 5:224c1fe73a8f | 113 | int state; |
CasperBerkhout | 1:d7299175a12e | 114 | |
s1680897 | 5:224c1fe73a8f | 115 | double movmean_cal[5000]; |
s1680897 | 5:224c1fe73a8f | 116 | double movmean_max2=0; |
s1680897 | 5:224c1fe73a8f | 117 | double movmean_max3=0; |
s1680897 | 5:224c1fe73a8f | 118 | double movmean_max4=0; |
s1680897 | 5:224c1fe73a8f | 119 | double movmean_max5=0; |
s1680897 | 5:224c1fe73a8f | 120 | |
s1680897 | 5:224c1fe73a8f | 121 | |
s1680897 | 5:224c1fe73a8f | 122 | // Filters |
s1680897 | 5:224c1fe73a8f | 123 | BiQuadChain bqc; |
s1680897 | 5:224c1fe73a8f | 124 | BiQuad bq1( 0.6844323315947305,1.368864663189461, 0.6844323315947305,1.2243497755555954,0.5133795508233265); //lp? |
s1680897 | 5:224c1fe73a8f | 125 | BiQuad bq2( 0.6844323315947306, -1.3688646631894612, 0.6844323315947306, -1.2243497755555959, 0.5133795508233266); //hp? |
s1680897 | 5:224c1fe73a8f | 126 | BiQuad bq3( 0.7566897754116633, -1.2243497755555959, 0.7566897754116633, -1.2243497755555959, 0.5133795508233266); // notch |
s1680897 | 5:224c1fe73a8f | 127 | |
s1680897 | 5:224c1fe73a8f | 128 | |
s1680897 | 5:224c1fe73a8f | 129 | //Function emgfilter signal 2 |
s1680897 | 5:224c1fe73a8f | 130 | double emgfilter2(double emgsample2) |
s1680897 | 5:224c1fe73a8f | 131 | { |
s1680897 | 5:224c1fe73a8f | 132 | //filter and take abs of input |
s1680897 | 5:224c1fe73a8f | 133 | double sig_2_filt = bqc.step(emgsample2); |
s1680897 | 5:224c1fe73a8f | 134 | sig_2_abs = abs(sig_2_filt); |
s1680897 | 5:224c1fe73a8f | 135 | //calculate moving mean of the filtered signal |
s1680897 | 5:224c1fe73a8f | 136 | for(int i = P-1; i >= 0; i--){ |
s1680897 | 5:224c1fe73a8f | 137 | if (i == 0) { |
s1680897 | 5:224c1fe73a8f | 138 | A[i] = sig_2_abs; |
s1680897 | 5:224c1fe73a8f | 139 | } |
s1680897 | 5:224c1fe73a8f | 140 | else { |
s1680897 | 5:224c1fe73a8f | 141 | A[i] = A[i-1]; |
s1680897 | 5:224c1fe73a8f | 142 | } |
s1680897 | 5:224c1fe73a8f | 143 | } |
s1680897 | 5:224c1fe73a8f | 144 | double sum2 = 0; |
s1680897 | 5:224c1fe73a8f | 145 | // deze for-loop sommeert de array |
s1680897 | 5:224c1fe73a8f | 146 | for (int n = 0; n < P-1; n++) |
s1680897 | 5:224c1fe73a8f | 147 | { |
s1680897 | 5:224c1fe73a8f | 148 | sum2 = sum2 + A[n]; |
s1680897 | 5:224c1fe73a8f | 149 | movmean2 = sum2/P; //dit is de moving average waarde |
s1680897 | 5:224c1fe73a8f | 150 | } |
s1680897 | 5:224c1fe73a8f | 151 | double set_speed2=movmean2/movmean_max2; |
s1680897 | 5:224c1fe73a8f | 152 | return(set_speed2); |
s1680897 | 5:224c1fe73a8f | 153 | } |
s1680897 | 5:224c1fe73a8f | 154 | |
s1680897 | 5:224c1fe73a8f | 155 | |
s1680897 | 5:224c1fe73a8f | 156 | //Signal 3 |
s1680897 | 5:224c1fe73a8f | 157 | double emgfilter3(double emgsample3){ |
s1680897 | 5:224c1fe73a8f | 158 | //filter and take abs of input |
s1680897 | 5:224c1fe73a8f | 159 | double sig_3_filt = bqc.step(emgsample3); |
s1680897 | 5:224c1fe73a8f | 160 | sig_3_abs = abs(sig_3_filt); |
s1680897 | 5:224c1fe73a8f | 161 | |
s1680897 | 5:224c1fe73a8f | 162 | //calculate moving mean of the filtered signal |
s1680897 | 5:224c1fe73a8f | 163 | for(int i = P-1; i >= 0; i--){ |
s1680897 | 5:224c1fe73a8f | 164 | if (i == 0) { |
s1680897 | 5:224c1fe73a8f | 165 | A[i] = sig_3_abs; |
s1680897 | 5:224c1fe73a8f | 166 | } |
s1680897 | 5:224c1fe73a8f | 167 | else { |
s1680897 | 5:224c1fe73a8f | 168 | A[i] = A[i-1]; |
s1680897 | 5:224c1fe73a8f | 169 | } |
s1680897 | 5:224c1fe73a8f | 170 | } |
s1680897 | 5:224c1fe73a8f | 171 | double sum3 = 0; |
s1680897 | 5:224c1fe73a8f | 172 | // deze for-loop sommeert de array |
s1680897 | 5:224c1fe73a8f | 173 | for (int n = 0; n < P-1; n++) { |
s1680897 | 5:224c1fe73a8f | 174 | sum3 = sum3 + A[n]; |
s1680897 | 5:224c1fe73a8f | 175 | movmean3 = sum3/P; //dit is de moving average waarde |
s1680897 | 5:224c1fe73a8f | 176 | } |
s1680897 | 5:224c1fe73a8f | 177 | double set_speed3=movmean3/movmean_max3; |
s1680897 | 5:224c1fe73a8f | 178 | return(set_speed3); |
s1680897 | 5:224c1fe73a8f | 179 | } |
s1680897 | 5:224c1fe73a8f | 180 | //Signal 4 |
s1680897 | 5:224c1fe73a8f | 181 | double emgfilter4(double emgsample4) |
s1680897 | 5:224c1fe73a8f | 182 | { |
s1680897 | 5:224c1fe73a8f | 183 | //filter and take abs of input |
s1680897 | 5:224c1fe73a8f | 184 | double sig_4_filt = bqc.step(emgsample4); |
s1680897 | 5:224c1fe73a8f | 185 | sig_4_abs = abs(sig_4_filt); |
s1680897 | 5:224c1fe73a8f | 186 | |
s1680897 | 5:224c1fe73a8f | 187 | //calculate moving mean of the filtered signal |
s1680897 | 5:224c1fe73a8f | 188 | for(int i = P-1; i >= 0; i--){ |
s1680897 | 5:224c1fe73a8f | 189 | if (i == 0) { |
s1680897 | 5:224c1fe73a8f | 190 | A[i] = sig_4_abs; |
s1680897 | 5:224c1fe73a8f | 191 | } |
s1680897 | 5:224c1fe73a8f | 192 | else { |
s1680897 | 5:224c1fe73a8f | 193 | A[i] = A[i-1]; |
s1680897 | 5:224c1fe73a8f | 194 | } |
s1680897 | 5:224c1fe73a8f | 195 | } |
s1680897 | 5:224c1fe73a8f | 196 | double sum4 = 0; |
s1680897 | 5:224c1fe73a8f | 197 | // deze for-loop sommeert de array |
s1680897 | 5:224c1fe73a8f | 198 | for (int n = 0; n < P-1; n++) { |
s1680897 | 5:224c1fe73a8f | 199 | sum4 = sum4 + A[n]; |
s1680897 | 5:224c1fe73a8f | 200 | movmean4 = sum4/P; //dit is de moving average waarde |
s1680897 | 5:224c1fe73a8f | 201 | } |
s1680897 | 5:224c1fe73a8f | 202 | double set_speed4=movmean4/movmean_max4; |
s1680897 | 5:224c1fe73a8f | 203 | return(set_speed4); |
s1680897 | 5:224c1fe73a8f | 204 | } |
s1680897 | 5:224c1fe73a8f | 205 | //Signal 5 |
s1680897 | 5:224c1fe73a8f | 206 | double emgfilter5(double emgsample5) |
s1680897 | 5:224c1fe73a8f | 207 | { |
s1680897 | 5:224c1fe73a8f | 208 | //filter and take abs of input |
s1680897 | 5:224c1fe73a8f | 209 | double sig_5_filt = bqc.step(emgsample5); |
s1680897 | 5:224c1fe73a8f | 210 | sig_5_abs = abs(sig_5_filt); |
s1680897 | 5:224c1fe73a8f | 211 | |
s1680897 | 5:224c1fe73a8f | 212 | //calculate moving mean of the filtered signal |
s1680897 | 5:224c1fe73a8f | 213 | for(int i = P-1; i >= 0; i--){ |
s1680897 | 5:224c1fe73a8f | 214 | if (i == 0) { |
s1680897 | 5:224c1fe73a8f | 215 | A[i] = sig_5_abs; |
s1680897 | 5:224c1fe73a8f | 216 | } |
s1680897 | 5:224c1fe73a8f | 217 | else { |
s1680897 | 5:224c1fe73a8f | 218 | A[i] = A[i-1]; |
s1680897 | 5:224c1fe73a8f | 219 | } |
s1680897 | 5:224c1fe73a8f | 220 | } |
s1680897 | 5:224c1fe73a8f | 221 | double sum5 = 0; |
s1680897 | 5:224c1fe73a8f | 222 | // deze for-loop sommeert de array |
s1680897 | 5:224c1fe73a8f | 223 | for (int n = 0; n < P-1; n++) { |
s1680897 | 5:224c1fe73a8f | 224 | sum5 = sum5 + A[n]; |
s1680897 | 5:224c1fe73a8f | 225 | movmean5 = sum5/P; //dit is de moving average waarde |
s1680897 | 5:224c1fe73a8f | 226 | } |
s1680897 | 5:224c1fe73a8f | 227 | double set_speed5=movmean5/movmean_max5; |
s1680897 | 5:224c1fe73a8f | 228 | return(set_speed5); |
s1680897 | 5:224c1fe73a8f | 229 | } |
s1680897 | 5:224c1fe73a8f | 230 | |
s1680897 | 5:224c1fe73a8f | 231 | void sample(){ |
s1680897 | 5:224c1fe73a8f | 232 | emgsample2 = emg2.read(); |
s1680897 | 5:224c1fe73a8f | 233 | emgsample3 = emg3.read(); |
s1680897 | 5:224c1fe73a8f | 234 | emgsample4 = emg4.read(); |
s1680897 | 5:224c1fe73a8f | 235 | emgsample5 = emg5.read(); |
s1680897 | 5:224c1fe73a8f | 236 | double x_vel = emgfilter2(emgsample2)-emgfilter3(emgsample3); |
s1680897 | 5:224c1fe73a8f | 237 | double y_vel = emgfilter4(emgsample4)-emgfilter5(emgsample5); |
s1680897 | 5:224c1fe73a8f | 238 | } |
s1680897 | 5:224c1fe73a8f | 239 | |
s1680897 | 5:224c1fe73a8f | 240 | //Calibration |
s1680897 | 5:224c1fe73a8f | 241 | void calibration_switch() |
s1680897 | 5:224c1fe73a8f | 242 | { |
s1680897 | 5:224c1fe73a8f | 243 | switch(state) { |
s1680897 | 5:224c1fe73a8f | 244 | case cal2: |
s1680897 | 5:224c1fe73a8f | 245 | ledred=0; |
s1680897 | 5:224c1fe73a8f | 246 | for (int i=0; i<=3500; i++){ |
s1680897 | 5:224c1fe73a8f | 247 | if (movmean2>movmean_max2) { |
s1680897 | 5:224c1fe73a8f | 248 | movmean_max2=movmean2; |
s1680897 | 5:224c1fe73a8f | 249 | }} |
s1680897 | 5:224c1fe73a8f | 250 | state=cal3; |
s1680897 | 5:224c1fe73a8f | 251 | break; |
s1680897 | 5:224c1fe73a8f | 252 | |
s1680897 | 5:224c1fe73a8f | 253 | case cal3: |
s1680897 | 5:224c1fe73a8f | 254 | ledred=1; |
s1680897 | 5:224c1fe73a8f | 255 | ledblue=0; |
s1680897 | 5:224c1fe73a8f | 256 | for (int i=0; i<=3500; i++){ |
s1680897 | 5:224c1fe73a8f | 257 | if (movmean3>movmean_max3) { |
s1680897 | 5:224c1fe73a8f | 258 | movmean_max3=movmean3; |
s1680897 | 5:224c1fe73a8f | 259 | }} |
s1680897 | 5:224c1fe73a8f | 260 | state=cal4; |
s1680897 | 5:224c1fe73a8f | 261 | break; |
s1680897 | 5:224c1fe73a8f | 262 | |
s1680897 | 5:224c1fe73a8f | 263 | case cal4: |
s1680897 | 5:224c1fe73a8f | 264 | ledblue=1; |
s1680897 | 5:224c1fe73a8f | 265 | ledgreen=0; |
s1680897 | 5:224c1fe73a8f | 266 | for (int i=0; i<=3500; i++){ |
s1680897 | 5:224c1fe73a8f | 267 | if (movmean4>movmean_max4) { |
s1680897 | 5:224c1fe73a8f | 268 | movmean_max4=movmean4; |
s1680897 | 5:224c1fe73a8f | 269 | }} |
s1680897 | 5:224c1fe73a8f | 270 | state=cal5; |
s1680897 | 5:224c1fe73a8f | 271 | break; |
s1680897 | 5:224c1fe73a8f | 272 | |
s1680897 | 5:224c1fe73a8f | 273 | case cal5: |
s1680897 | 5:224c1fe73a8f | 274 | ledgreen=1; |
s1680897 | 5:224c1fe73a8f | 275 | ledred=0; |
s1680897 | 5:224c1fe73a8f | 276 | ledblue=0; |
s1680897 | 5:224c1fe73a8f | 277 | for (int i=0; i<=3500; i++){ |
s1680897 | 5:224c1fe73a8f | 278 | if (movmean5>movmean_max5) { |
s1680897 | 5:224c1fe73a8f | 279 | movmean_max5=movmean5; |
s1680897 | 5:224c1fe73a8f | 280 | }} |
s1680897 | 5:224c1fe73a8f | 281 | break; |
s1680897 | 5:224c1fe73a8f | 282 | } //end switch |
s1680897 | 5:224c1fe73a8f | 283 | } //end calibration_switch |
s1680897 | 5:224c1fe73a8f | 284 | |
s1680897 | 5:224c1fe73a8f | 285 | void calibration () { |
s1680897 | 5:224c1fe73a8f | 286 | while(button1==0) { |
s1680897 | 5:224c1fe73a8f | 287 | state=cal2; |
s1680897 | 5:224c1fe73a8f | 288 | calibration_switch(); |
s1680897 | 5:224c1fe73a8f | 289 | } |
s1680897 | 5:224c1fe73a8f | 290 | } |
CasperBerkhout | 0:4141aef83f4b | 291 | |
CasperBerkhout | 0:4141aef83f4b | 292 | |
CasperBerkhout | 0:4141aef83f4b | 293 | void kinemtaica(double q1, double q2, double vdx, double vdy, double &q1_new, double &q2_new){ |
s1680897 | 5:224c1fe73a8f | 294 | vdx=x_vel*gain_factor; |
s1680897 | 5:224c1fe73a8f | 295 | vdy=y_vel*gain_factor; |
CasperBerkhout | 0:4141aef83f4b | 296 | double q1_dot = (2.5*cos(q1+q2))/(sin(q2)) *vdx + (2.5*sin(q1+q2))/(sin(q2))*vdy; |
CasperBerkhout | 0:4141aef83f4b | 297 | double q2_dot = -(0.3*cos(q1+q2)+0.4*cos(q1))/(0.12*sin(q2))*vdx -(0.3*sin(q1+q2)+0.4*sin(q2))/(0.12*sin(q2))*vdy; |
CasperBerkhout | 0:4141aef83f4b | 298 | q1_new = q1 +q1_dot*Ts; |
CasperBerkhout | 0:4141aef83f4b | 299 | q2_new = q2 +q2_dot*Ts; |
CasperBerkhout | 0:4141aef83f4b | 300 | return; |
CasperBerkhout | 0:4141aef83f4b | 301 | } |
CasperBerkhout | 0:4141aef83f4b | 302 | |
CasperBerkhout | 0:4141aef83f4b | 303 | float PID(double e, const double Kp, const double Ki, const double Kd, double Ts, double &e_int, double &e_prior){ //PID calculator |
CasperBerkhout | 0:4141aef83f4b | 304 | e_int += Ts*e; |
CasperBerkhout | 0:4141aef83f4b | 305 | double e_diff = (e-e_prior)/Ts; |
CasperBerkhout | 0:4141aef83f4b | 306 | e_prior = e; |
CasperBerkhout | 0:4141aef83f4b | 307 | double e_diff_filter = bqlowpass.step(e_diff); |
CasperBerkhout | 0:4141aef83f4b | 308 | return(Kp*e+Ki*e_int+Kd*e_diff_filter); |
CasperBerkhout | 0:4141aef83f4b | 309 | } |
CasperBerkhout | 0:4141aef83f4b | 310 | |
CasperBerkhout | 0:4141aef83f4b | 311 | void M1_control(){ |
CasperBerkhout | 0:4141aef83f4b | 312 | |
CasperBerkhout | 0:4141aef83f4b | 313 | //call PID func and set new motor speed |
CasperBerkhout | 0:4141aef83f4b | 314 | set_speed = PID(M1_error_pos,M1_Kp,M1_Ki,M1_Kd,Ts,M1_e_int,M1_e_prior); |
CasperBerkhout | 0:4141aef83f4b | 315 | if(set_speed > 0){ |
CasperBerkhout | 0:4141aef83f4b | 316 | M1_speed.write(abs(set_speed)); |
CasperBerkhout | 0:4141aef83f4b | 317 | M1_direction.write(0); |
CasperBerkhout | 0:4141aef83f4b | 318 | } |
CasperBerkhout | 0:4141aef83f4b | 319 | else if (set_speed < 0){ |
CasperBerkhout | 0:4141aef83f4b | 320 | M1_speed.write(abs(set_speed)); |
CasperBerkhout | 0:4141aef83f4b | 321 | M1_direction.write(1); |
CasperBerkhout | 0:4141aef83f4b | 322 | } |
CasperBerkhout | 0:4141aef83f4b | 323 | else{M1_speed.write(0);} |
CasperBerkhout | 4:de0923cf6bcc | 324 | |
CasperBerkhout | 0:4141aef83f4b | 325 | } |
CasperBerkhout | 0:4141aef83f4b | 326 | |
CasperBerkhout | 0:4141aef83f4b | 327 | void M2_control(){ |
CasperBerkhout | 0:4141aef83f4b | 328 | set_speed = PID(M2_error_pos,M2_Kp,M2_Ki,M2_Kd,Ts,M2_e_int,M2_e_prior); |
CasperBerkhout | 0:4141aef83f4b | 329 | if(set_speed > 0){ |
CasperBerkhout | 0:4141aef83f4b | 330 | M2_speed.write(abs(set_speed)); |
CasperBerkhout | 0:4141aef83f4b | 331 | M2_direction.write(0); |
CasperBerkhout | 0:4141aef83f4b | 332 | } |
CasperBerkhout | 0:4141aef83f4b | 333 | else if (set_speed < 0){ |
CasperBerkhout | 0:4141aef83f4b | 334 | M2_speed.write(abs(set_speed)); |
CasperBerkhout | 0:4141aef83f4b | 335 | M2_direction.write(1); |
CasperBerkhout | 0:4141aef83f4b | 336 | } |
CasperBerkhout | 0:4141aef83f4b | 337 | else{M2_speed.write(0);} |
CasperBerkhout | 4:de0923cf6bcc | 338 | pc.printf("M2 integral = %f\n\r", M2_e_int); |
CasperBerkhout | 0:4141aef83f4b | 339 | } |
CasperBerkhout | 0:4141aef83f4b | 340 | |
CasperBerkhout | 2:c7369b41f7ae | 341 | void homing_system () { |
CasperBerkhout | 2:c7369b41f7ae | 342 | LimSW1.mode(PullDown); |
CasperBerkhout | 2:c7369b41f7ae | 343 | LimSW2.mode(PullDown); |
CasperBerkhout | 2:c7369b41f7ae | 344 | M1_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 345 | M2_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 346 | M1_direction.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 347 | M2_direction.write(1); |
CasperBerkhout | 2:c7369b41f7ae | 348 | |
CasperBerkhout | 2:c7369b41f7ae | 349 | while(1){ |
CasperBerkhout | 3:455b79d42636 | 350 | if (HomStart.read() == 0){ |
CasperBerkhout | 3:455b79d42636 | 351 | setpoint += 0.003; //move setpoint 0.2 radian per second (at 100hz) |
CasperBerkhout | 4:de0923cf6bcc | 352 | pc.printf("Homing... \n\r"); |
CasperBerkhout | 4:de0923cf6bcc | 353 | } |
CasperBerkhout | 4:de0923cf6bcc | 354 | |
CasperBerkhout | 4:de0923cf6bcc | 355 | double M1_rel_pos = enc1.getPulses()/32.0/131.25*2.0*3.1416; |
CasperBerkhout | 4:de0923cf6bcc | 356 | double M2_rel_pos = enc2.getPulses()/32.0/131.25*2.0*3.1416; |
CasperBerkhout | 3:455b79d42636 | 357 | if(LimSW1.read() == 0){ |
CasperBerkhout | 3:455b79d42636 | 358 | M1_error_pos = 1.5*setpoint - M1_rel_pos; |
CasperBerkhout | 3:455b79d42636 | 359 | } |
CasperBerkhout | 3:455b79d42636 | 360 | if(LimSW2.read() == 0){ |
CasperBerkhout | 3:455b79d42636 | 361 | M2_error_pos = -(0.5*setpoint - M2_rel_pos); |
CasperBerkhout | 3:455b79d42636 | 362 | } |
CasperBerkhout | 3:455b79d42636 | 363 | M1_control(); |
CasperBerkhout | 3:455b79d42636 | 364 | M2_control(); |
CasperBerkhout | 4:de0923cf6bcc | 365 | |
CasperBerkhout | 4:de0923cf6bcc | 366 | |
CasperBerkhout | 2:c7369b41f7ae | 367 | if(LimSW1.read() == 1){ |
CasperBerkhout | 2:c7369b41f7ae | 368 | M1_error_pos = 0; |
CasperBerkhout | 2:c7369b41f7ae | 369 | M1_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 370 | M1_home = enc1.getPulses()/32.0/131.25*2.0*3.1416; //in radians |
CasperBerkhout | 2:c7369b41f7ae | 371 | } |
CasperBerkhout | 2:c7369b41f7ae | 372 | if (LimSW2.read() == 1) { |
CasperBerkhout | 2:c7369b41f7ae | 373 | M2_error_pos = 0; |
CasperBerkhout | 2:c7369b41f7ae | 374 | M2_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 375 | M2_home = enc2.getPulses()/32.0/131.25*2.0*3.1416; //in radians |
CasperBerkhout | 2:c7369b41f7ae | 376 | } |
CasperBerkhout | 2:c7369b41f7ae | 377 | |
CasperBerkhout | 2:c7369b41f7ae | 378 | if (LimSW1.read() == 1 && LimSW2.read() ==1) { |
CasperBerkhout | 2:c7369b41f7ae | 379 | pc.printf("Homing finished \n\r"); |
CasperBerkhout | 2:c7369b41f7ae | 380 | M1_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 381 | M2_speed.write(0); |
CasperBerkhout | 2:c7369b41f7ae | 382 | wait(0.5); |
CasperBerkhout | 2:c7369b41f7ae | 383 | M1_home = enc1.getPulses()/32.0/131.25*2.0*3.1416; //in radians |
CasperBerkhout | 2:c7369b41f7ae | 384 | M2_home = enc2.getPulses()/32.0/131.25*2.0*3.1416; //in radians |
CasperBerkhout | 4:de0923cf6bcc | 385 | //break; |
CasperBerkhout | 4:de0923cf6bcc | 386 | while(1); //stop after homing. |
CasperBerkhout | 2:c7369b41f7ae | 387 | } |
CasperBerkhout | 4:de0923cf6bcc | 388 | wait(0.01); |
CasperBerkhout | 2:c7369b41f7ae | 389 | } |
CasperBerkhout | 0:4141aef83f4b | 390 | |
CasperBerkhout | 2:c7369b41f7ae | 391 | } |
CasperBerkhout | 0:4141aef83f4b | 392 | |
CasperBerkhout | 0:4141aef83f4b | 393 | void scopesend(){ |
CasperBerkhout | 0:4141aef83f4b | 394 | |
CasperBerkhout | 0:4141aef83f4b | 395 | |
CasperBerkhout | 0:4141aef83f4b | 396 | |
CasperBerkhout | 0:4141aef83f4b | 397 | } |
CasperBerkhout | 0:4141aef83f4b | 398 | void StopMotors(){ |
CasperBerkhout | 0:4141aef83f4b | 399 | while(1){ |
CasperBerkhout | 0:4141aef83f4b | 400 | M1_speed.write(0); |
CasperBerkhout | 0:4141aef83f4b | 401 | M2_speed.write(0); |
CasperBerkhout | 0:4141aef83f4b | 402 | } |
CasperBerkhout | 0:4141aef83f4b | 403 | } |
CasperBerkhout | 0:4141aef83f4b | 404 | |
CasperBerkhout | 0:4141aef83f4b | 405 | void geterror(){ |
CasperBerkhout | 0:4141aef83f4b | 406 | double M1_rel_pos = enc1.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians |
CasperBerkhout | 0:4141aef83f4b | 407 | double M2_rel_pos = enc2.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians |
CasperBerkhout | 2:c7369b41f7ae | 408 | |
CasperBerkhout | 2:c7369b41f7ae | 409 | float Arm1_home = 122.0/180.0*3.1416;//home position of large link attached to base in radians - 112 degrees |
CasperBerkhout | 2:c7369b41f7ae | 410 | float Arm2_home = 19.0/180.0*3.1416;//home position of small link attached to base |
CasperBerkhout | 0:4141aef83f4b | 411 | |
CasperBerkhout | 2:c7369b41f7ae | 412 | double M1_actual_pos = Arm1_home + (M1_rel_pos - M1_home)/2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle theta |
CasperBerkhout | 2:c7369b41f7ae | 413 | double M2_actual_pos = Arm2_home + (M2_rel_pos - M2_home)/2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle Alpha |
CasperBerkhout | 0:4141aef83f4b | 414 | |
CasperBerkhout | 0:4141aef83f4b | 415 | double q1 = M1_actual_pos; |
CasperBerkhout | 2:c7369b41f7ae | 416 | double q2 = q1 + M2_actual_pos; //see drawing |
CasperBerkhout | 0:4141aef83f4b | 417 | |
CasperBerkhout | 1:d7299175a12e | 418 | //double M1_reference_pos = 1+potmeter.read()*0.5*3.1416; //should cover the right range - radians |
CasperBerkhout | 3:455b79d42636 | 419 | double M1_reference_pos = 0.5*3.1416-potmeter.read(); //should cover the right range - radians |
CasperBerkhout | 1:d7299175a12e | 420 | double M2_reference_pos = 0.5+potmeter2.read()*0.25*3.1416; |
CasperBerkhout | 0:4141aef83f4b | 421 | |
CasperBerkhout | 3:455b79d42636 | 422 | |
CasperBerkhout | 1:d7299175a12e | 423 | //M2_error_pos = M2_reference_pos - M2_actual_pos; |
CasperBerkhout | 1:d7299175a12e | 424 | M2_error_pos = 0; |
CasperBerkhout | 3:455b79d42636 | 425 | if(M1_reference_pos > Arm1_home){ |
CasperBerkhout | 3:455b79d42636 | 426 | M1_reference_pos = Arm1_home; |
CasperBerkhout | 3:455b79d42636 | 427 | } |
CasperBerkhout | 3:455b79d42636 | 428 | else{ |
CasperBerkhout | 3:455b79d42636 | 429 | M1_error_pos = M1_reference_pos - M1_actual_pos; |
CasperBerkhout | 3:455b79d42636 | 430 | } |
CasperBerkhout | 3:455b79d42636 | 431 | if(M2_reference_pos > Arm2_home){ |
CasperBerkhout | 3:455b79d42636 | 432 | M2_reference_pos = Arm2_home; |
CasperBerkhout | 3:455b79d42636 | 433 | } |
CasperBerkhout | 3:455b79d42636 | 434 | else{ |
CasperBerkhout | 3:455b79d42636 | 435 | M2_error_pos = M2_reference_pos - M2_actual_pos; |
CasperBerkhout | 3:455b79d42636 | 436 | } |
CasperBerkhout | 0:4141aef83f4b | 437 | } |
CasperBerkhout | 0:4141aef83f4b | 438 | |
CasperBerkhout | 0:4141aef83f4b | 439 | int main() { |
s1680897 | 5:224c1fe73a8f | 440 | calibration(); |
s1680897 | 5:224c1fe73a8f | 441 | //add biquad sections to the chain |
s1680897 | 5:224c1fe73a8f | 442 | bqc.add( &bq1 ).add( &bq2 ).add( &bq3 ); |
CasperBerkhout | 0:4141aef83f4b | 443 | |
s1680897 | 5:224c1fe73a8f | 444 | sample_timer.attach(&sample, 0.002); |
s1680897 | 5:224c1fe73a8f | 445 | //scope_timer.attach(&scopesend, 0.002); |
s1680897 | 5:224c1fe73a8f | 446 | |
s1680897 | 5:224c1fe73a8f | 447 | /*empty loop, sample() is executed periodically*/ |
s1680897 | 5:224c1fe73a8f | 448 | while(1) {} |
CasperBerkhout | 0:4141aef83f4b | 449 | //initialize serial comm and set motor PWM freq |
CasperBerkhout | 0:4141aef83f4b | 450 | M1_speed.period(1.0/pwm_freq); |
CasperBerkhout | 0:4141aef83f4b | 451 | M2_speed.period(1.0/pwm_freq); |
CasperBerkhout | 0:4141aef83f4b | 452 | pc.baud(115200); |
CasperBerkhout | 1:d7299175a12e | 453 | pc.printf("starting homing function now. Push button to start procedure \n\r"); |
CasperBerkhout | 0:4141aef83f4b | 454 | //commence homing procedure |
CasperBerkhout | 0:4141aef83f4b | 455 | homing_system(); |
CasperBerkhout | 1:d7299175a12e | 456 | pc.printf("Setting home position complete\n\r"); |
CasperBerkhout | 0:4141aef83f4b | 457 | //attach all interrupt |
CasperBerkhout | 1:d7299175a12e | 458 | pc.printf("attaching interrupt tickers now \n\r"); |
CasperBerkhout | 0:4141aef83f4b | 459 | button1.fall(StopMotors); //stop motor interrupt |
CasperBerkhout | 1:d7299175a12e | 460 | motor_update1.attach(&M1_control,0.01); |
CasperBerkhout | 1:d7299175a12e | 461 | motor_update2.attach(&M2_control,0.01); |
CasperBerkhout | 1:d7299175a12e | 462 | error_update.attach(&geterror,0.01); |
CasperBerkhout | 0:4141aef83f4b | 463 | |
CasperBerkhout | 1:d7299175a12e | 464 | pc.printf("initialization complete - position control of motors now active\n\r"); |
CasperBerkhout | 0:4141aef83f4b | 465 | |
CasperBerkhout | 0:4141aef83f4b | 466 | while(1){ |
CasperBerkhout | 0:4141aef83f4b | 467 | |
CasperBerkhout | 0:4141aef83f4b | 468 | |
CasperBerkhout | 0:4141aef83f4b | 469 | } |
CasperBerkhout | 0:4141aef83f4b | 470 | |
CasperBerkhout | 0:4141aef83f4b | 471 | } |