kinematic model included

Dependencies:   Encoder MODSERIAL biquadFilter

Committer:
Tetragonia
Date:
Thu Oct 26 14:20:40 2017 +0000
Revision:
0:ef7fd98bf091
Implementation kinematic model

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Tetragonia 0:ef7fd98bf091 1 #include "mbed.h"
Tetragonia 0:ef7fd98bf091 2 #include "encoder.h"
Tetragonia 0:ef7fd98bf091 3 #include "MODSERIAL.h"
Tetragonia 0:ef7fd98bf091 4 #include "BiQuad.h"
Tetragonia 0:ef7fd98bf091 5 #include "math.h"
Tetragonia 0:ef7fd98bf091 6
Tetragonia 0:ef7fd98bf091 7 #define M_Pi 3.141592653589793238462643383279502884L
Tetragonia 0:ef7fd98bf091 8
Tetragonia 0:ef7fd98bf091 9 Serial pc(USBTX, USBRX);
Tetragonia 0:ef7fd98bf091 10
Tetragonia 0:ef7fd98bf091 11 DigitalOut led_red(LED_RED);
Tetragonia 0:ef7fd98bf091 12 DigitalOut led_blue(LED_BLUE);
Tetragonia 0:ef7fd98bf091 13 InterruptIn button1(D2);
Tetragonia 0:ef7fd98bf091 14 InterruptIn button2(D3);
Tetragonia 0:ef7fd98bf091 15 AnalogIn EMG_A0(A0);
Tetragonia 0:ef7fd98bf091 16 AnalogIn EMG_A1(A1);
Tetragonia 0:ef7fd98bf091 17
Tetragonia 0:ef7fd98bf091 18 DigitalOut motor1DirectionPin(D4);
Tetragonia 0:ef7fd98bf091 19 PwmOut motor1MagnitudePin(D5);
Tetragonia 0:ef7fd98bf091 20 DigitalOut motor2DirectionPin(D7); // Sequence? Lines 181-183
Tetragonia 0:ef7fd98bf091 21 PwmOut motor2MagnitudePin(D6);
Tetragonia 0:ef7fd98bf091 22
Tetragonia 0:ef7fd98bf091 23 Ticker measureTick;
Tetragonia 0:ef7fd98bf091 24
Tetragonia 0:ef7fd98bf091 25 Encoder motor1(D13,D12); //On the shield actually M2
Tetragonia 0:ef7fd98bf091 26 Encoder motor2(D11,D10); //On the shield actually M1 (Production mistake?)
Tetragonia 0:ef7fd98bf091 27
Tetragonia 0:ef7fd98bf091 28 int Count1 = 0;
Tetragonia 0:ef7fd98bf091 29 int Count2 = 0;
Tetragonia 0:ef7fd98bf091 30 int MaxEMGcount = 1800; // Split up for motor 1 and 2 AND create a MinEMGCount
Tetragonia 0:ef7fd98bf091 31 int MinEMGcount = -1800;
Tetragonia 0:ef7fd98bf091 32 bool switch1 = 0; // manual switch for when to start calculations (later removed for a state machine
Tetragonia 0:ef7fd98bf091 33 bool direction1 = 1;
Tetragonia 0:ef7fd98bf091 34 bool direction2 = 1;
Tetragonia 0:ef7fd98bf091 35 const double RAD_PER_PULSE = 0.002991; // Value for RAD_PER_PULSE given through the slides (wrong?)
Tetragonia 0:ef7fd98bf091 36 const double DEG_PER_RAD = 180 / M_Pi; // Basic knowledge of how many degrees are in 1 radian.
Tetragonia 0:ef7fd98bf091 37 int MaxAveragerValues = 500;
Tetragonia 0:ef7fd98bf091 38 double Av_A0 = 0;
Tetragonia 0:ef7fd98bf091 39 double Av_A1 = 0;
Tetragonia 0:ef7fd98bf091 40 double q1 = 0; // Angle of arm 1 (upper) in starting position is 0 degrees
Tetragonia 0:ef7fd98bf091 41 double q2 = 179/DEG_PER_RAD; // Angle of arm 2 (lower) in starting position is 180 degrees (but can't be 0 or 180 because of determinant = 0)
Tetragonia 0:ef7fd98bf091 42 int L1 = 47; // Length of arm 1 (upper) in cm
Tetragonia 0:ef7fd98bf091 43 int L2 = 29; // Length of arm 2 (lower) in cm
Tetragonia 0:ef7fd98bf091 44 int xdes = L1-L2 // Desired x coordinate, arm is located at x = L1-L2 in starting position
Tetragonia 0:ef7fd98bf091 45 int ydes = 0; // Disired y coordinate, arm is located at y = 0 in starting position
Tetragonia 0:ef7fd98bf091 46
Tetragonia 0:ef7fd98bf091 47 // Sample time (motor1-timestep)
Tetragonia 0:ef7fd98bf091 48 const double M1_Ts = 0.01; //100 Hz systems
Tetragonia 0:ef7fd98bf091 49 const double M2_Ts = 0.01;
Tetragonia 0:ef7fd98bf091 50
Tetragonia 0:ef7fd98bf091 51 // Controller gains (motor1-Kp,-Ki,...)
Tetragonia 0:ef7fd98bf091 52 const double M1_Kp = 0.1, M1_Ki = 0.02, M1_Kd = 0.00125, M1_N = 100; // THESE VALUES ARE ARBITRARY AT THIS POINT
Tetragonia 0:ef7fd98bf091 53 const double M2_Kp = 0.1, M2_Ki = 0.02, M2_Kd = 0.00125, M2_N = 100; // Inspired by the Ziegler-Nichols Method
Tetragonia 0:ef7fd98bf091 54
Tetragonia 0:ef7fd98bf091 55 // Filter variables (motor1-filter-v1,-v2)
Tetragonia 0:ef7fd98bf091 56 double M1_f_v1 = 0.0, M1_f_v2 = 0.0;
Tetragonia 0:ef7fd98bf091 57 double M2_f_v1 = 0.0, M2_f_v2 = 0.0;
Tetragonia 0:ef7fd98bf091 58
Tetragonia 0:ef7fd98bf091 59 // PROGRAM THAT CALCULATES ANGLE CHANGES
Tetragonia 0:ef7fd98bf091 60
Tetragonia 0:ef7fd98bf091 61
Tetragonia 0:ef7fd98bf091 62 // PROGRAM THAT ANALYSES EMG SIGNAL AND FILTERS IT
Tetragonia 0:ef7fd98bf091 63 // Define the HIDScope and Ticker object
Tetragonia 0:ef7fd98bf091 64 //HIDScope scope(2);
Tetragonia 0:ef7fd98bf091 65 //Ticker scopeTimer;
Tetragonia 0:ef7fd98bf091 66
Tetragonia 0:ef7fd98bf091 67 BiQuadChain bqchain1, bqchain2; //BiQuad Chain. Makes a combination of various BiQuads.
Tetragonia 0:ef7fd98bf091 68
Tetragonia 0:ef7fd98bf091 69 BiQuad bq1(0.960582636413903, -1.921165272827806, 0.960582636413903, -1.916303032724640, 0.926027512930974);//Highpass 8Hz
Tetragonia 0:ef7fd98bf091 70 BiQuad bq2(0.912835456766912, -1.825670913533825, 0.912835456766912, -1.821050358261190, 0.830291468806461);//
Tetragonia 0:ef7fd98bf091 71 BiQuad bq3(0.991153589776121, -1.603846829332603, 0.991153589776121, -1.593257429417890, 0.982171881701343);//Notch 49-51Hz
Tetragonia 0:ef7fd98bf091 72 BiQuad bq4(0.991153589776121, -1.603846829332603, 0.991153589776121, -1.614311809680850, 0.982599066293185);//
Tetragonia 0:ef7fd98bf091 73 BiQuad bq5(0.064591432448980, 0.129182864897960, 0.064591432448980, -1.401313635492332, 0.659679365288253);//Lowpasss 45Hz
Tetragonia 0:ef7fd98bf091 74 BiQuad bq6(0.052062866562661, 0.104125733125322, 0.052062866562661, -1.129505912021716, 0.337757378272360);//
Tetragonia 0:ef7fd98bf091 75
Tetragonia 0:ef7fd98bf091 76 BiQuadChain bqchain3, bqchain4; //BiQuad Chain. Makes a combination of various BiQuads.
Tetragonia 0:ef7fd98bf091 77
Tetragonia 0:ef7fd98bf091 78 BiQuad bq7(0.960582636413903, -1.921165272827806, 0.960582636413903, -1.916303032724640, 0.926027512930974);//Highpass 8Hz
Tetragonia 0:ef7fd98bf091 79 BiQuad bq8(0.912835456766912, -1.825670913533825, 0.912835456766912, -1.821050358261190, 0.830291468806461);//
Tetragonia 0:ef7fd98bf091 80 BiQuad bq9(0.991153589776121, -1.603846829332603, 0.991153589776121, -1.593257429417890, 0.982171881701343);//Notch 49-51Hz
Tetragonia 0:ef7fd98bf091 81 BiQuad bq10(0.991153589776121, -1.603846829332603, 0.991153589776121, -1.614311809680850, 0.982599066293185);//
Tetragonia 0:ef7fd98bf091 82 BiQuad bq11(0.064591432448980, 0.129182864897960, 0.064591432448980, -1.401313635492332, 0.659679365288253);//Lowpasss 45Hz
Tetragonia 0:ef7fd98bf091 83 BiQuad bq12(0.052062866562661, 0.104125733125322, 0.052062866562661, -1.129505912021716, 0.337757378272360);//
Tetragonia 0:ef7fd98bf091 84
Tetragonia 0:ef7fd98bf091 85 double A0t10=0, A0t9=0, A0t8=0, A0t7=0, A0t6=0, A0t5=0, A0t4=0, A0t3=0, A0t2=0, A0t1=0;
Tetragonia 0:ef7fd98bf091 86 double A1t10=0, A1t9=0, A1t8=0, A1t7=0, A1t6=0, A1t5=0, A1t4=0, A1t3=0, A1t2=0, A1t1=0;
Tetragonia 0:ef7fd98bf091 87
Tetragonia 0:ef7fd98bf091 88 double EMGSample1(double Input, double &t10, double &t9, double &t8, double &t7, double &t6, double &t5, double &t4, double &t3, double &t2, double &t1){ // Sample function: read a value from the Analog in
Tetragonia 0:ef7fd98bf091 89 //double MaxSignal = 0;
Tetragonia 0:ef7fd98bf091 90 double Signal = 0.0f;
Tetragonia 0:ef7fd98bf091 91 double EMGFiltered = fabs(bqchain1.step(Input)); // Signal.Read instantly gets filtered.
Tetragonia 0:ef7fd98bf091 92 double EMGSignal = bqchain2.step(EMGFiltered);
Tetragonia 0:ef7fd98bf091 93 double treshhold = 0.6*Av_A0;
Tetragonia 0:ef7fd98bf091 94 // if (EMGSignal > MaxSignal){ MaxSignal = EMGSignal;} // Save the highest value measured.
Tetragonia 0:ef7fd98bf091 95 // double discrete = floor((EMGSignal/MaxSignal)*10.0)/10.0;
Tetragonia 0:ef7fd98bf091 96 if (EMGSignal >= treshhold || t1 >= treshhold || t2 >= treshhold || t3 >= treshhold || t4 >= treshhold || t5 >= treshhold || t6 >= treshhold || t7 >= treshhold || t8 >= treshhold || t9 >= treshhold || t10 >= treshhold ){
Tetragonia 0:ef7fd98bf091 97 Signal = 1;
Tetragonia 0:ef7fd98bf091 98 }
Tetragonia 0:ef7fd98bf091 99 else {
Tetragonia 0:ef7fd98bf091 100 Signal = 0.0f;
Tetragonia 0:ef7fd98bf091 101 }
Tetragonia 0:ef7fd98bf091 102 t10=t9, t9=t8, t8=t7, t7=t6, t6=t5, t5=t4, t4=t3, t3=t2, t2=t1, t1= EMGSignal;
Tetragonia 0:ef7fd98bf091 103
Tetragonia 0:ef7fd98bf091 104 return Signal;
Tetragonia 0:ef7fd98bf091 105 }
Tetragonia 0:ef7fd98bf091 106
Tetragonia 0:ef7fd98bf091 107 double EMGSample2(double Input, double &t10, double &t9, double &t8, double &t7, double &t6, double &t5, double &t4, double &t3, double &t2, double &t1){ // Sample function: read a value from the Analog in
Tetragonia 0:ef7fd98bf091 108 //double MaxSignal = 0;
Tetragonia 0:ef7fd98bf091 109 double Signal = 0.0f;
Tetragonia 0:ef7fd98bf091 110 double EMGFiltered = fabs(bqchain3.step(Input)); // Signal.Read instantly gets filtered.
Tetragonia 0:ef7fd98bf091 111 double EMGSignal = bqchain4.step(EMGFiltered);
Tetragonia 0:ef7fd98bf091 112 double treshhold = 0.6*Av_A1;
Tetragonia 0:ef7fd98bf091 113 // if (EMGSignal > MaxSignal){ MaxSignal = EMGSignal;} // Save the highest value measured.
Tetragonia 0:ef7fd98bf091 114 // double discrete = floor((EMGSignal/MaxSignal)*10.0)/10.0;
Tetragonia 0:ef7fd98bf091 115 if (EMGSignal >= treshhold || t1 >= treshhold || t2 >= treshhold || t3 >= treshhold || t4 >= treshhold || t5 >= treshhold || t6 >= treshhold || t7 >= treshhold || t8 >= treshhold || t9 >= treshhold || t10 >= treshhold ){
Tetragonia 0:ef7fd98bf091 116 Signal = 1;
Tetragonia 0:ef7fd98bf091 117 }
Tetragonia 0:ef7fd98bf091 118 else {
Tetragonia 0:ef7fd98bf091 119 Signal = 0.0f;
Tetragonia 0:ef7fd98bf091 120 }
Tetragonia 0:ef7fd98bf091 121 t10=t9, t9=t8, t8=t7, t7=t6, t6=t5, t5=t4, t4=t3, t3=t2, t2=t1, t1= EMGSignal;
Tetragonia 0:ef7fd98bf091 122
Tetragonia 0:ef7fd98bf091 123 return Signal;
Tetragonia 0:ef7fd98bf091 124 }
Tetragonia 0:ef7fd98bf091 125
Tetragonia 0:ef7fd98bf091 126 // PROGRAM THAT MEASURES AN AMOUNT OF VALUES AND EXPORTS THE AVERAGE
Tetragonia 0:ef7fd98bf091 127 void AverageValue_A0(double &Av_A0)
Tetragonia 0:ef7fd98bf091 128 {
Tetragonia 0:ef7fd98bf091 129 double A[MaxAveragerValues];
Tetragonia 0:ef7fd98bf091 130 double sum = 0;
Tetragonia 0:ef7fd98bf091 131 for( int i = 0; i < MaxAveragerValues; i++){
Tetragonia 0:ef7fd98bf091 132 double EMGFiltered = fabs(bqchain1.step(EMG_A0.read())); // Signal.Read instantly gets filtered.
Tetragonia 0:ef7fd98bf091 133 double Value = bqchain2.step(EMGFiltered);
Tetragonia 0:ef7fd98bf091 134 wait(0.01);
Tetragonia 0:ef7fd98bf091 135 for (int j = 1; j < MaxAveragerValues; j++){
Tetragonia 0:ef7fd98bf091 136 A[MaxAveragerValues-j] = A[MaxAveragerValues-1-j];
Tetragonia 0:ef7fd98bf091 137 }
Tetragonia 0:ef7fd98bf091 138 A[0] = Value;
Tetragonia 0:ef7fd98bf091 139 }
Tetragonia 0:ef7fd98bf091 140 for (int i = 0; i < MaxAveragerValues; i++){
Tetragonia 0:ef7fd98bf091 141 sum = sum + A[i];
Tetragonia 0:ef7fd98bf091 142 }
Tetragonia 0:ef7fd98bf091 143 printf("result = %.0f", (sum/MaxAveragerValues));
Tetragonia 0:ef7fd98bf091 144 Av_A0 = (sum/MaxAveragerValues);
Tetragonia 0:ef7fd98bf091 145 }
Tetragonia 0:ef7fd98bf091 146
Tetragonia 0:ef7fd98bf091 147 void AverageValue_A1(double &Av_A1)
Tetragonia 0:ef7fd98bf091 148 {
Tetragonia 0:ef7fd98bf091 149 double A[MaxAveragerValues];
Tetragonia 0:ef7fd98bf091 150 double sum = 0;
Tetragonia 0:ef7fd98bf091 151 for( int i = 0; i < MaxAveragerValues; i++){
Tetragonia 0:ef7fd98bf091 152 double EMGFiltered = fabs(bqchain3.step(EMG_A1.read()));
Tetragonia 0:ef7fd98bf091 153 double Value = bqchain4.step(EMGFiltered);
Tetragonia 0:ef7fd98bf091 154 wait(0.01);
Tetragonia 0:ef7fd98bf091 155 for (int j = 1; j < MaxAveragerValues; j++){
Tetragonia 0:ef7fd98bf091 156 A[MaxAveragerValues-j] = A[MaxAveragerValues-1-j];
Tetragonia 0:ef7fd98bf091 157 }
Tetragonia 0:ef7fd98bf091 158 A[0] = Value;
Tetragonia 0:ef7fd98bf091 159 }
Tetragonia 0:ef7fd98bf091 160 for (int i = 0; i < MaxAveragerValues; i++){
Tetragonia 0:ef7fd98bf091 161 sum = sum + A[i];
Tetragonia 0:ef7fd98bf091 162 }
Tetragonia 0:ef7fd98bf091 163 printf("result = %.0f", (sum/MaxAveragerValues));
Tetragonia 0:ef7fd98bf091 164 Av_A1 = (sum/MaxAveragerValues);
Tetragonia 0:ef7fd98bf091 165 }
Tetragonia 0:ef7fd98bf091 166
Tetragonia 0:ef7fd98bf091 167 // PROGRAM THAT ENABLES THE SYSTEM TO OPERATE (Later to be replaced by State Machine)
Tetragonia 0:ef7fd98bf091 168 void but1_pressed(void)
Tetragonia 0:ef7fd98bf091 169 {
Tetragonia 0:ef7fd98bf091 170 if (switch1 == 0){
Tetragonia 0:ef7fd98bf091 171 pc.printf("TAKING AVERAGES...");
Tetragonia 0:ef7fd98bf091 172 for(int i = 1; i < 12; i++){
Tetragonia 0:ef7fd98bf091 173 led_blue = !led_blue;
Tetragonia 0:ef7fd98bf091 174 wait(0.1);
Tetragonia 0:ef7fd98bf091 175 }
Tetragonia 0:ef7fd98bf091 176 AverageValue_A0(Av_A0);
Tetragonia 0:ef7fd98bf091 177 pc.printf("Av_A0 = %.3f ", Av_A0);
Tetragonia 0:ef7fd98bf091 178 led_blue = 1;
Tetragonia 0:ef7fd98bf091 179 for(int i = 1; i < 12; i++){
Tetragonia 0:ef7fd98bf091 180 led_blue = !led_blue;
Tetragonia 0:ef7fd98bf091 181 wait(0.1);
Tetragonia 0:ef7fd98bf091 182 }
Tetragonia 0:ef7fd98bf091 183 AverageValue_A1(Av_A1);
Tetragonia 0:ef7fd98bf091 184 pc.printf("Av_A1 = %.3f \r\n\n", Av_A1);
Tetragonia 0:ef7fd98bf091 185 led_blue = 1;
Tetragonia 0:ef7fd98bf091 186 }
Tetragonia 0:ef7fd98bf091 187 wait(10.0);
Tetragonia 0:ef7fd98bf091 188 led_red = !led_red;
Tetragonia 0:ef7fd98bf091 189 switch1 = !switch1;
Tetragonia 0:ef7fd98bf091 190 }
Tetragonia 0:ef7fd98bf091 191
Tetragonia 0:ef7fd98bf091 192 void but2_pressed(void)
Tetragonia 0:ef7fd98bf091 193 {
Tetragonia 0:ef7fd98bf091 194 direction1 = !direction1;
Tetragonia 0:ef7fd98bf091 195 direction2 = !direction2;
Tetragonia 0:ef7fd98bf091 196 }
Tetragonia 0:ef7fd98bf091 197
Tetragonia 0:ef7fd98bf091 198 // PROGRAM THAT CALCULATES THE PID
Tetragonia 0:ef7fd98bf091 199 double PID( double err, const double Kp, const double Ki, const double Kd,
Tetragonia 0:ef7fd98bf091 200 const double Ts, const double N, double &v1, double &v2 ) {
Tetragonia 0:ef7fd98bf091 201
Tetragonia 0:ef7fd98bf091 202 const double a1 = -4/(N*Ts+2), a2 = -(N*Ts-2)/(N*Ts+2), // a1 and a2 are the nominator of our transferfunction
Tetragonia 0:ef7fd98bf091 203 b0 = (4*Kp + 4*Kd*N + 2*Ki*Ts + 2*Kp*N*Ts + Ki*N*pow(Ts,2))/(2*N*Ts + 4),
Tetragonia 0:ef7fd98bf091 204 b1 = (Ki*N*pow(Ts,2) - 4*Kp - 4*Kd*N)/(N*Ts + 2),
Tetragonia 0:ef7fd98bf091 205 b2 = (4*Kp + 4*Kd*N - 2*Ki*Ts - 2*Kp*N*Ts + Ki*N*pow(Ts,2))/(2*N*Ts + 4); // b0, b1 and b2 the denominator
Tetragonia 0:ef7fd98bf091 206
Tetragonia 0:ef7fd98bf091 207 double v = err - a1*v1 - a2*v2; // Memory value are calculated and later on stored. (v is like an input)
Tetragonia 0:ef7fd98bf091 208 double u = b0*v + b1*v1 + b2*v2;
Tetragonia 0:ef7fd98bf091 209 v2 = v1; v1 = v;
Tetragonia 0:ef7fd98bf091 210 return u; // u functions as our output value gained from the transferfunction.
Tetragonia 0:ef7fd98bf091 211 }
Tetragonia 0:ef7fd98bf091 212
Tetragonia 0:ef7fd98bf091 213 // PROGRAM THAT RECEIVES EMG SIGNALS AND CONVERTS THEM TO REFERENCE POSITIONS
Tetragonia 0:ef7fd98bf091 214 double EMG_Referencer(double sig, bool dir, int &n) {
Tetragonia 0:ef7fd98bf091 215 //pc.printf("MEASURING");
Tetragonia 0:ef7fd98bf091 216 if (dir == 1){
Tetragonia 0:ef7fd98bf091 217 if (sig > 0.99){ //Above 0.9 because of inconsistency in received signals
Tetragonia 0:ef7fd98bf091 218 if (n < MaxEMGcount){
Tetragonia 0:ef7fd98bf091 219 n = n++; //Normally in steps of 1 (so n = n++;) but for better visibility we have 36 itterations
Tetragonia 0:ef7fd98bf091 220 }
Tetragonia 0:ef7fd98bf091 221 }
Tetragonia 0:ef7fd98bf091 222 }
Tetragonia 0:ef7fd98bf091 223 else if (dir == 0){
Tetragonia 0:ef7fd98bf091 224 if (sig > 0.99){
Tetragonia 0:ef7fd98bf091 225 if (n > MinEMGcount){ //MinEMGcount
Tetragonia 0:ef7fd98bf091 226 n = n--; // Normally n = n--;
Tetragonia 0:ef7fd98bf091 227 }
Tetragonia 0:ef7fd98bf091 228 }
Tetragonia 0:ef7fd98bf091 229 }
Tetragonia 0:ef7fd98bf091 230 double u = 0.1*n;
Tetragonia 0:ef7fd98bf091 231 return u;
Tetragonia 0:ef7fd98bf091 232 }
Tetragonia 0:ef7fd98bf091 233
Tetragonia 0:ef7fd98bf091 234 //Kinematic model
Tetragonia 0:ef7fd98bf091 235 double Kinematic_referencer(double xdes, bool ydes, int &n) { //weet niet wat ik met die n moet
Tetragonia 0:ef7fd98bf091 236 //printf ("x=%f, y=%f\n", x, y);
Tetragonia 0:ef7fd98bf091 237 double qt = q1 + q2; // current total angle
Tetragonia 0:ef7fd98bf091 238 double xcurrent = L1 * cos (q1) + L2 * cos (qt); // current x position
Tetragonia 0:ef7fd98bf091 239 double ycurrent = L1 * sin (q1) + L2 * sin (qt); // current y position
Tetragonia 0:ef7fd98bf091 240
Tetragonia 0:ef7fd98bf091 241 //Initial twist
Tetragonia 0:ef7fd98bf091 242 double vx = (xdes - xcurrent)/100; // Running on 100 Hz
Tetragonia 0:ef7fd98bf091 243 double vy = (ydes - ycurrent)/100;
Tetragonia 0:ef7fd98bf091 244
Tetragonia 0:ef7fd98bf091 245 //Jacobians
Tetragonia 0:ef7fd98bf091 246 double J11 = -ycurrent;
Tetragonia 0:ef7fd98bf091 247 double J12 = -L2 * sin (qt);
Tetragonia 0:ef7fd98bf091 248 double J21 = xcurrent;
Tetragonia 0:ef7fd98bf091 249 double J22 = L2 * cos (qt);
Tetragonia 0:ef7fd98bf091 250 double Determinant = J11 * J22 - J21 * J12; // calculate determinant
Tetragonia 0:ef7fd98bf091 251
Tetragonia 0:ef7fd98bf091 252 //Calculate angular velocities
Tetragonia 0:ef7fd98bf091 253 double q1der = (J22 * vx - J12 * vy) / Determinant;
Tetragonia 0:ef7fd98bf091 254 double q2der = (-J21 * vx + J11 * vy) / Determinant;
Tetragonia 0:ef7fd98bf091 255
Tetragonia 0:ef7fd98bf091 256 //Calculate new angles
Tetragonia 0:ef7fd98bf091 257 q1new = q1 + q1der/100; //nog fixen met die tijdstappen?
Tetragonia 0:ef7fd98bf091 258 q2new = q2 + q2der/100; //hier ook
Tetragonia 0:ef7fd98bf091 259 //printf ("q1=%f, q2=%f\n", q1 * c, q2 * c);
Tetragonia 0:ef7fd98bf091 260 qtnew = q1new + q2new;
Tetragonia 0:ef7fd98bf091 261
Tetragonia 0:ef7fd98bf091 262 //Calculate new positions
Tetragonia 0:ef7fd98bf091 263 xnew = L1 * cos (q1new) + L2 * cos (qtnew);
Tetragonia 0:ef7fd98bf091 264 ynew = L1 * sin (q1new) + L2 * sin (qtnew);
Tetragonia 0:ef7fd98bf091 265 //printf ("x=%f, y=%f\n", x, y);
Tetragonia 0:ef7fd98bf091 266
Tetragonia 0:ef7fd98bf091 267 // Now check whether the calculated position is desired, determinants close to zero may cause the robot to move weirdly
Tetragonia 0:ef7fd98bf091 268 // New y may not be negative, this means the arm is located in on the plate
Tetragonia 0:ef7fd98bf091 269 // New q1 may not be less than -45 degrees, less means the arm will crash into the base plate
Tetragonia 0:ef7fd98bf091 270 // New q2 may not be more than 185 degrees, more means the lower arm will crash into the upper arm
Tetragonia 0:ef7fd98bf091 271 if (ynew > -1 && q1new > -45 / DEG_PER_RAD && q2new < 185 / DEG_PER_RAD)
Tetragonia 0:ef7fd98bf091 272 {
Tetragonia 0:ef7fd98bf091 273 // If desired, change the angles
Tetragonia 0:ef7fd98bf091 274 q1 = q1new;
Tetragonia 0:ef7fd98bf091 275 q2 = q2new;
Tetragonia 0:ef7fd98bf091 276 }
Tetragonia 0:ef7fd98bf091 277 else
Tetragonia 0:ef7fd98bf091 278 {
Tetragonia 0:ef7fd98bf091 279 // If not desired, don't change the angles, but define current position as desired so the robot ignores the input
Tetragonia 0:ef7fd98bf091 280 xdes = xcurrent;
Tetragonia 0:ef7fd98bf091 281 ydes = ycurrent;
Tetragonia 0:ef7fd98bf091 282 }
Tetragonia 0:ef7fd98bf091 283 return q1,q2;
Tetragonia 0:ef7fd98bf091 284 }
Tetragonia 0:ef7fd98bf091 285
Tetragonia 0:ef7fd98bf091 286 // PROGRAMS THAT CONTROL THE VALUE OUTPUT
Tetragonia 0:ef7fd98bf091 287 double M1_Controller(double Angle1) {
Tetragonia 0:ef7fd98bf091 288 double EMG_Input_A0 = EMG_A0.read();
Tetragonia 0:ef7fd98bf091 289 double sig1 = EMGSample1(EMG_Input_A0, A0t10, A0t9, A0t8, A0t7, A0t6, A0t5, A0t4, A0t3, A0t2, A0t1);
Tetragonia 0:ef7fd98bf091 290
Tetragonia 0:ef7fd98bf091 291 double referencePosition = EMG_Referencer(sig1, direction1, Count1);
Tetragonia 0:ef7fd98bf091 292 pc.printf("D1 = %i, S1 = %.0f ", Count1, sig1);
Tetragonia 0:ef7fd98bf091 293 double motor1Value = PID( referencePosition - Angle1 , M1_Kp, M1_Ki, M1_Kd, M1_Ts, M1_N, M1_f_v1, M1_f_v2); //Find the motorvalue by going through the PID
Tetragonia 0:ef7fd98bf091 294
Tetragonia 0:ef7fd98bf091 295 return motor1Value; // According to the PID its calculations, we get a motor value.
Tetragonia 0:ef7fd98bf091 296 }
Tetragonia 0:ef7fd98bf091 297
Tetragonia 0:ef7fd98bf091 298 double M2_Controller(double Angle2) {
Tetragonia 0:ef7fd98bf091 299 double EMG_Input_A1 = EMG_A1.read();; //EMG_A1.read();
Tetragonia 0:ef7fd98bf091 300 double sig2 = EMGSample2(EMG_Input_A1, A1t10, A1t9, A1t8, A1t7, A1t6, A1t5, A1t4, A1t3, A1t2, A1t1);
Tetragonia 0:ef7fd98bf091 301
Tetragonia 0:ef7fd98bf091 302 double referencePosition = EMG_Referencer(sig2, direction2, Count2);; // Since we have 360 degrees, our potmeter should reach these values as well.
Tetragonia 0:ef7fd98bf091 303 pc.printf("D2 = %i, S2 = %.0f \r\n", Count2, sig2);
Tetragonia 0:ef7fd98bf091 304 double motor2Value = PID( referencePosition - Angle2 , M2_Kp, M2_Ki, M2_Kd, M2_Ts, M2_N, M2_f_v1, M2_f_v2); //Find the motorvalue by going through the PID
Tetragonia 0:ef7fd98bf091 305
Tetragonia 0:ef7fd98bf091 306 return motor2Value; // According to the PID its calculations, we get a motor value.
Tetragonia 0:ef7fd98bf091 307 }
Tetragonia 0:ef7fd98bf091 308
Tetragonia 0:ef7fd98bf091 309 // PROGRAMS FOR POWERING THE MOTOR ACCORDING TO THE ERROR (P VARIANT)
Tetragonia 0:ef7fd98bf091 310 void SetMotor1(double motor1Value) // function that actually changes the output for the motor
Tetragonia 0:ef7fd98bf091 311 {
Tetragonia 0:ef7fd98bf091 312 if(motor1Value >= 0 ) //Function sets direction and strength
Tetragonia 0:ef7fd98bf091 313 motor1DirectionPin = 1; //If the reference value is positive, we will turn clockwise
Tetragonia 0:ef7fd98bf091 314 else
Tetragonia 0:ef7fd98bf091 315 motor1DirectionPin = 0; // if not, counterclockwise
Tetragonia 0:ef7fd98bf091 316
Tetragonia 0:ef7fd98bf091 317 if(fabs(motor1Value) > 0.2 ) // Next, check the absolute motor value, which is the magnitude
Tetragonia 0:ef7fd98bf091 318 motor1MagnitudePin = 0.2; // This is a safety. We never want to exceed 1
Tetragonia 0:ef7fd98bf091 319 else
Tetragonia 0:ef7fd98bf091 320 motor1MagnitudePin = fabs(motor1Value); // if we fall underneath the safety, take the magnitude
Tetragonia 0:ef7fd98bf091 321 }
Tetragonia 0:ef7fd98bf091 322
Tetragonia 0:ef7fd98bf091 323 void SetMotor2(double motor2Value) // function that actually changes the output for the motor
Tetragonia 0:ef7fd98bf091 324 {
Tetragonia 0:ef7fd98bf091 325 if(motor2Value >= 0 ) //Function sets direction and strength
Tetragonia 0:ef7fd98bf091 326 motor2DirectionPin = 0; //If the reference value is positive, we will turn clockwise
Tetragonia 0:ef7fd98bf091 327 else
Tetragonia 0:ef7fd98bf091 328 motor2DirectionPin = 1; // if not, counterclockwise
Tetragonia 0:ef7fd98bf091 329
Tetragonia 0:ef7fd98bf091 330 if(fabs(motor2Value) > 0.2 ) // Next, check the absolute motor value, which is the magnitude
Tetragonia 0:ef7fd98bf091 331 motor2MagnitudePin = 0.2; // This is a safety. We never want to exceed 1
Tetragonia 0:ef7fd98bf091 332 else
Tetragonia 0:ef7fd98bf091 333 motor2MagnitudePin = fabs(motor2Value); // if we fall underneath the safety, take the magnitude
Tetragonia 0:ef7fd98bf091 334 }
Tetragonia 0:ef7fd98bf091 335
Tetragonia 0:ef7fd98bf091 336 // PROGRAM THAT MEASURES AND CONTROLES THE MOTOR OUTPUT
Tetragonia 0:ef7fd98bf091 337 void MeasureAndControl() // Pure values being calculated and send to the Mbed.
Tetragonia 0:ef7fd98bf091 338 {
Tetragonia 0:ef7fd98bf091 339 double Angle1 = DEG_PER_RAD * RAD_PER_PULSE * motor1.getPosition(); // Angle is equal to the degrees per pulse measured (NOT TRUE AT THIS MOMENT, '360' != 2 * M_Pi
Tetragonia 0:ef7fd98bf091 340 double Angle2 = DEG_PER_RAD * RAD_PER_PULSE * motor2.getPosition(); // Angle is equal to the degrees per pulse measured (NOT TRUE AT THIS MOMENT, '360' != 2 * M_Pi
Tetragonia 0:ef7fd98bf091 341
Tetragonia 0:ef7fd98bf091 342 if (switch1 == 1){ // If the switch is pressed
Tetragonia 0:ef7fd98bf091 343 double motor1Value = M1_Controller(Angle1); // create a motorvalue to give to motor 1 according to the control and angle
Tetragonia 0:ef7fd98bf091 344 double motor2Value = M2_Controller(Angle2); // create a motorvalue to give to motor 1 according to the control and angle
Tetragonia 0:ef7fd98bf091 345
Tetragonia 0:ef7fd98bf091 346 SetMotor1(motor1Value);
Tetragonia 0:ef7fd98bf091 347 SetMotor2(motor2Value);
Tetragonia 0:ef7fd98bf091 348 }
Tetragonia 0:ef7fd98bf091 349 else {
Tetragonia 0:ef7fd98bf091 350 SetMotor1(0);
Tetragonia 0:ef7fd98bf091 351 SetMotor2(0); }
Tetragonia 0:ef7fd98bf091 352 }
Tetragonia 0:ef7fd98bf091 353
Tetragonia 0:ef7fd98bf091 354 int main() // Main function
Tetragonia 0:ef7fd98bf091 355 {
Tetragonia 0:ef7fd98bf091 356 pc.baud(115200); // For post analysis, seeing if the plug works etc.
Tetragonia 0:ef7fd98bf091 357 pc.printf("STARTING SEQUENCE \r\n"); //Merely checking if there is a serial connection at all
Tetragonia 0:ef7fd98bf091 358 bqchain1.add(&bq1).add(&bq2).add(&bq3).add(&bq4); // Combine the BiQuads bq1, bq2 and bq3 in the Chain.
Tetragonia 0:ef7fd98bf091 359 bqchain2.add(&bq5).add(&bq6);
Tetragonia 0:ef7fd98bf091 360 bqchain3.add(&bq7).add(&bq8).add(&bq9).add(&bq10); // Combine the BiQuads bq1, bq2 and bq3 in the Chain.
Tetragonia 0:ef7fd98bf091 361 bqchain4.add(&bq11).add(&bq12);
Tetragonia 0:ef7fd98bf091 362 measureTick.attach(&MeasureAndControl, M1_Ts); // Tick that changes the motor (currently 1Hz)
Tetragonia 0:ef7fd98bf091 363 led_red = 1; // Set the LED off in the positive direction, on in the negative direction
Tetragonia 0:ef7fd98bf091 364 led_blue = 1;
Tetragonia 0:ef7fd98bf091 365 button1.fall(&but1_pressed); // Trigger the InterruptIn of the button.
Tetragonia 0:ef7fd98bf091 366 button2.fall(&but2_pressed);
Tetragonia 0:ef7fd98bf091 367 //scopeTimer.attach_us(&scopeSend, 1e4); // Attach in Microseconds
Tetragonia 0:ef7fd98bf091 368 }
Tetragonia 0:ef7fd98bf091 369