Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FastPWM MODSERIAL QEI biquadFilter mbed
Fork of state_program by
main.cpp@8:5896424eb539, 2018-11-06 (annotated)
- Committer:
- JesseLohman
- Date:
- Tue Nov 06 14:45:19 2018 +0000
- Revision:
- 8:5896424eb539
- Parent:
- 7:1906d404cd1e
Alles netjes gemaakt met comments. Inverse kinematics en EMG gedeelte moeten nog gecontroleerd worden
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| JesseLohman | 0:2a5dd6cc0008 | 1 | #include "mbed.h" | 
| JesseLohman | 0:2a5dd6cc0008 | 2 | #include "FastPWM.h" | 
| JesseLohman | 0:2a5dd6cc0008 | 3 | #include "QEI.h" | 
| JesseLohman | 0:2a5dd6cc0008 | 4 | #include "BiQuad.h" | 
| JesseLohman | 3:be922ea2415f | 5 | #include <iostream> | 
| JesseLohman | 3:be922ea2415f | 6 | #include <string> | 
| JesseLohman | 0:2a5dd6cc0008 | 7 | |
| JesseLohman | 8:5896424eb539 | 8 | enum States {WaitState, MotorCalState, EMGCalState, HomingState, MovingState, GrippingState, ScrewingState, FailureState}; | 
| JesseLohman | 0:2a5dd6cc0008 | 9 | States currentState = WaitState; | 
| JesseLohman | 0:2a5dd6cc0008 | 10 | |
| JesseLohman | 0:2a5dd6cc0008 | 11 | DigitalIn startButton(D0); | 
| JesseLohman | 0:2a5dd6cc0008 | 12 | InterruptIn failureButton(D1); | 
| KingMufasa | 7:1906d404cd1e | 13 | DigitalIn gripperButton(D2); | 
| KingMufasa | 7:1906d404cd1e | 14 | DigitalIn directionSwitch(D3); | 
| KingMufasa | 7:1906d404cd1e | 15 | DigitalIn gripperMotorButton(D14); | 
| KingMufasa | 7:1906d404cd1e | 16 | |
| KingMufasa | 5:a1843b698d0d | 17 | |
| KingMufasa | 5:a1843b698d0d | 18 | Serial pc(USBTX, USBRX); | 
| KingMufasa | 5:a1843b698d0d | 19 | |
| JesseLohman | 1:4cb9af313c26 | 20 | DigitalOut led1(LED1); // Red led | 
| JesseLohman | 1:4cb9af313c26 | 21 | DigitalOut led2(LED2); // Green led | 
| JesseLohman | 1:4cb9af313c26 | 22 | DigitalOut led3(LED3); // Blue led | 
| KingMufasa | 6:e67250b8b100 | 23 | QEI encoder1(D10, D11, NC, 8400, QEI::X4_ENCODING); | 
| JesseLohman | 3:be922ea2415f | 24 | QEI encoder2(D12, D13, NC, 8400, QEI::X4_ENCODING); | 
| KingMufasa | 5:a1843b698d0d | 25 | |
| KingMufasa | 5:a1843b698d0d | 26 | AnalogIn emg0(A0); | 
| KingMufasa | 5:a1843b698d0d | 27 | AnalogIn emg1(A1); | 
| KingMufasa | 5:a1843b698d0d | 28 | AnalogIn emg2(A2); | 
| KingMufasa | 5:a1843b698d0d | 29 | AnalogIn emg3(A3); | 
| JesseLohman | 0:2a5dd6cc0008 | 30 | |
| JesseLohman | 0:2a5dd6cc0008 | 31 | bool stateChanged = true; | 
| JesseLohman | 0:2a5dd6cc0008 | 32 | |
| JesseLohman | 0:2a5dd6cc0008 | 33 | Ticker mainTicker; | 
| JesseLohman | 0:2a5dd6cc0008 | 34 | Timer stateTimer; | 
| JesseLohman | 8:5896424eb539 | 35 | Ticker calTimer; //Ticker that waits (to prepare the person) | 
| JesseLohman | 8:5896424eb539 | 36 | Ticker EMGsampler; //Ticker that samples the EMG | 
| JesseLohman | 2:5cace74299e7 | 37 | |
| JesseLohman | 2:5cace74299e7 | 38 | const double sampleTime = 0.001; | 
| JesseLohman | 2:5cace74299e7 | 39 | const double PI = 3.141592653589793238463; | 
| JesseLohman | 3:be922ea2415f | 40 | const double L1 = 0.328; | 
| JesseLohman | 3:be922ea2415f | 41 | const double L2 = 0.218; | 
| KingMufasa | 7:1906d404cd1e | 42 | double T1[3][3] { | 
| JesseLohman | 3:be922ea2415f | 43 | {0, -1, 0}, | 
| JesseLohman | 3:be922ea2415f | 44 | {1, 0, 0,}, | 
| JesseLohman | 3:be922ea2415f | 45 | {0, 0, 0,} | 
| JesseLohman | 3:be922ea2415f | 46 | }; | 
| KingMufasa | 7:1906d404cd1e | 47 | double T20[3][3] { | 
| JesseLohman | 3:be922ea2415f | 48 | {0, -1, 0}, | 
| JesseLohman | 3:be922ea2415f | 49 | {1, 0, -L1,}, | 
| JesseLohman | 3:be922ea2415f | 50 | {0, 0, 0,} | 
| JesseLohman | 3:be922ea2415f | 51 | }; | 
| KingMufasa | 7:1906d404cd1e | 52 | double H200[3][3] { | 
| JesseLohman | 3:be922ea2415f | 53 | {1, 0, L1+L2}, | 
| JesseLohman | 3:be922ea2415f | 54 | {0, 1, 0,}, | 
| JesseLohman | 3:be922ea2415f | 55 | {0, 0, 1,} | 
| JesseLohman | 3:be922ea2415f | 56 | }; | 
| KingMufasa | 7:1906d404cd1e | 57 | double Pe2 [3][1] { | 
| JesseLohman | 3:be922ea2415f | 58 | {0}, | 
| JesseLohman | 3:be922ea2415f | 59 | {0}, | 
| JesseLohman | 3:be922ea2415f | 60 | {1} | 
| JesseLohman | 3:be922ea2415f | 61 | }; | 
| JesseLohman | 3:be922ea2415f | 62 | |
| JesseLohman | 8:5896424eb539 | 63 | double u1; // Motor output of the long link | 
| JesseLohman | 8:5896424eb539 | 64 | double u2; // Motor of the short link | 
| JesseLohman | 8:5896424eb539 | 65 | double u3; // Motor of the gripper | 
| JesseLohman | 8:5896424eb539 | 66 | double u4; // Motor of the screwer | 
| JesseLohman | 8:5896424eb539 | 67 | FastPWM pwmpin1(D5); // Motor pwm | 
| JesseLohman | 8:5896424eb539 | 68 | DigitalOut directionpin1(D4); // Motor direction | 
| JesseLohman | 3:be922ea2415f | 69 | FastPWM pwmpin2 (D6); | 
| JesseLohman | 3:be922ea2415f | 70 | DigitalOut directionpin2 (D7); | 
| JesseLohman | 8:5896424eb539 | 71 | FastPWM pwmpin3(A4); | 
| JesseLohman | 8:5896424eb539 | 72 | DigitalOut directionpin3(D8); | 
| KingMufasa | 7:1906d404cd1e | 73 | FastPWM pwmpin4(A5); | 
| KingMufasa | 7:1906d404cd1e | 74 | DigitalOut directionpin4(D9); | 
| KingMufasa | 7:1906d404cd1e | 75 | |
| KingMufasa | 7:1906d404cd1e | 76 | double setPointX = 0.3; | 
| KingMufasa | 7:1906d404cd1e | 77 | double setPointY = 0.28; | 
| JesseLohman | 3:be922ea2415f | 78 | double qRef1; | 
| JesseLohman | 3:be922ea2415f | 79 | double qRef2; | 
| JesseLohman | 3:be922ea2415f | 80 | double qMeas1; | 
| JesseLohman | 3:be922ea2415f | 81 | double qMeas2; | 
| JesseLohman | 2:5cace74299e7 | 82 | |
| JesseLohman | 3:be922ea2415f | 83 | double C[5][5]; | 
| JesseLohman | 3:be922ea2415f | 84 | |
| KingMufasa | 7:1906d404cd1e | 85 | double Kp1 = 10; | 
| KingMufasa | 7:1906d404cd1e | 86 | double Ki1 = 0; | 
| KingMufasa | 7:1906d404cd1e | 87 | double Kd1 = 2; | 
| KingMufasa | 7:1906d404cd1e | 88 | double Kp2 = 10; | 
| KingMufasa | 7:1906d404cd1e | 89 | double Ki2 = 0; | 
| KingMufasa | 7:1906d404cd1e | 90 | double Kd2 = 2; | 
| KingMufasa | 5:a1843b698d0d | 91 | |
| JesseLohman | 8:5896424eb539 | 92 | const int samplepack = 250; // Amount of data points before one cycle completes | 
| JesseLohman | 8:5896424eb539 | 93 | volatile int counter = 0; // Counts the amount of readings this cycle | 
| JesseLohman | 8:5896424eb539 | 94 | volatile double total[4] = {0,0,0,0}; // Total difference between data points and the calibration value this cycle (x+, x-, y+, y-) | 
| JesseLohman | 8:5896424eb539 | 95 | double refvaluebic = 10; // Minimum total value for the motor to move (biceps) | 
| JesseLohman | 8:5896424eb539 | 96 | double refvaluecalf = 50; // Minimum total value for the motor to move (calfs) | 
| JesseLohman | 8:5896424eb539 | 97 | double incr = 0.00002; // Increment | 
| KingMufasa | 5:a1843b698d0d | 98 | bool moving[4] = {0,0,0,0}; //x+, x-, y+, y- | 
| KingMufasa | 5:a1843b698d0d | 99 | |
| JesseLohman | 8:5896424eb539 | 100 | volatile int waitingcounter = 0; //How many iterations of waiting have been done | 
| JesseLohman | 8:5896424eb539 | 101 | int countermax = 20; //counter until when should be waited | 
| JesseLohman | 8:5896424eb539 | 102 | volatile int processnow = 0; //Point in the calibration process | 
| JesseLohman | 8:5896424eb539 | 103 | volatile double armresttot = 0; | 
| JesseLohman | 8:5896424eb539 | 104 | volatile double armflextot = 0; | 
| JesseLohman | 8:5896424eb539 | 105 | volatile double legresttot = 0; | 
| JesseLohman | 8:5896424eb539 | 106 | volatile double legflextot = 0; | 
| JesseLohman | 8:5896424eb539 | 107 | const int samplecal = 2500; //Amount of data points to consider in the calibration | 
| JesseLohman | 8:5896424eb539 | 108 | double ratio = samplecal/samplepack; | 
| JesseLohman | 8:5896424eb539 | 109 | volatile double tot = 0; //Total measured EMG of the current type. | 
| JesseLohman | 8:5896424eb539 | 110 | volatile double armcal; //Calibated value for arm measurements | 
| JesseLohman | 8:5896424eb539 | 111 | volatile double legcal; //Calibrated value for leg measurements | 
| JesseLohman | 8:5896424eb539 | 112 | |
| JesseLohman | 8:5896424eb539 | 113 | BiQuad hpf(0.8635,-1.7269,0.8635,-1.9359,0.9394); //5 Hz High pass filter | 
| KingMufasa | 5:a1843b698d0d | 114 | BiQuad notch(0.9922,-1.6054,0.9922,-1.6054,0.9844); //50 Hz Notch filter | 
| KingMufasa | 5:a1843b698d0d | 115 | BiQuad lpf(0.9780,1.9561,0.9780,1.9556,0.9565); //250Hz Low pass filter | 
| KingMufasa | 5:a1843b698d0d | 116 | BiQuadChain bqc; | 
| JesseLohman | 0:2a5dd6cc0008 | 117 | |
| JesseLohman | 0:2a5dd6cc0008 | 118 | void switchToFailureState () | 
| JesseLohman | 0:2a5dd6cc0008 | 119 | { | 
| JesseLohman | 0:2a5dd6cc0008 | 120 | failureButton.fall(NULL); // Detaches button, so it can only be activated once | 
| JesseLohman | 1:4cb9af313c26 | 121 | led1 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 122 | led2 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 123 | led3 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 124 | pc.printf("SYSTEM FAILED\n"); | 
| JesseLohman | 0:2a5dd6cc0008 | 125 | currentState = FailureState; | 
| JesseLohman | 0:2a5dd6cc0008 | 126 | stateChanged = true; | 
| JesseLohman | 0:2a5dd6cc0008 | 127 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 128 | |
| KingMufasa | 5:a1843b698d0d | 129 | void measureEMG () | 
| KingMufasa | 5:a1843b698d0d | 130 | { | 
| KingMufasa | 7:1906d404cd1e | 131 | if (currentState == MovingState) { | 
| KingMufasa | 7:1906d404cd1e | 132 | total[0] += abs(bqc.step(emg0.read())); | 
| KingMufasa | 7:1906d404cd1e | 133 | total[1] += abs(bqc.step(emg1.read())); | 
| KingMufasa | 7:1906d404cd1e | 134 | total[2] += abs(bqc.step(emg2.read())); | 
| KingMufasa | 7:1906d404cd1e | 135 | total[3] += abs(bqc.step(emg3.read())); | 
| KingMufasa | 7:1906d404cd1e | 136 | counter++; | 
| KingMufasa | 7:1906d404cd1e | 137 | if (counter >= samplepack) { | 
| KingMufasa | 7:1906d404cd1e | 138 | moving[0] = 0; | 
| KingMufasa | 7:1906d404cd1e | 139 | moving[1] = 0; | 
| KingMufasa | 7:1906d404cd1e | 140 | moving[2] = 0; | 
| KingMufasa | 7:1906d404cd1e | 141 | moving[3] = 0; | 
| KingMufasa | 7:1906d404cd1e | 142 | if (total[0] >= refvaluebic) { | 
| KingMufasa | 7:1906d404cd1e | 143 | moving[0] = 1; | 
| KingMufasa | 7:1906d404cd1e | 144 | } | 
| KingMufasa | 7:1906d404cd1e | 145 | if (total[1] >= refvaluebic) { | 
| KingMufasa | 7:1906d404cd1e | 146 | moving[1] = 1; | 
| KingMufasa | 7:1906d404cd1e | 147 | } | 
| KingMufasa | 7:1906d404cd1e | 148 | if (total[2] >= refvaluecalf) { | 
| KingMufasa | 7:1906d404cd1e | 149 | moving[2] = 1; | 
| KingMufasa | 7:1906d404cd1e | 150 | } | 
| KingMufasa | 7:1906d404cd1e | 151 | if (total[3] >= refvaluecalf) { | 
| KingMufasa | 7:1906d404cd1e | 152 | moving[3] = 1; | 
| KingMufasa | 7:1906d404cd1e | 153 | } | 
| KingMufasa | 7:1906d404cd1e | 154 | pc.printf("Totals of {x+,x-,y+,y-} are %f, %f, %f, %f \r\n",total[0],total[1],total[2],total[3]); | 
| KingMufasa | 7:1906d404cd1e | 155 | pc.printf("Coordinates: (%f,%f)\r\n", setPointX, setPointY); | 
| JesseLohman | 8:5896424eb539 | 156 | counter = 0; // Reset for next cycle | 
| JesseLohman | 8:5896424eb539 | 157 | for (int i=0; i<4; i++) { // Clear 'total' array | 
| KingMufasa | 7:1906d404cd1e | 158 | total[i] = 0; | 
| KingMufasa | 7:1906d404cd1e | 159 | } | 
| KingMufasa | 5:a1843b698d0d | 160 | } | 
| KingMufasa | 7:1906d404cd1e | 161 | |
| KingMufasa | 7:1906d404cd1e | 162 | if(moving[0]) { | 
| KingMufasa | 7:1906d404cd1e | 163 | setPointX += incr; | 
| KingMufasa | 5:a1843b698d0d | 164 | } | 
| KingMufasa | 7:1906d404cd1e | 165 | if (moving[1]) { | 
| KingMufasa | 7:1906d404cd1e | 166 | setPointX -= incr; | 
| KingMufasa | 5:a1843b698d0d | 167 | } | 
| KingMufasa | 7:1906d404cd1e | 168 | if (moving[2]) { | 
| KingMufasa | 7:1906d404cd1e | 169 | setPointY += incr; | 
| KingMufasa | 7:1906d404cd1e | 170 | } | 
| KingMufasa | 7:1906d404cd1e | 171 | if (moving[3]) { | 
| KingMufasa | 7:1906d404cd1e | 172 | setPointY -= incr; | 
| KingMufasa | 5:a1843b698d0d | 173 | } | 
| KingMufasa | 5:a1843b698d0d | 174 | } | 
| KingMufasa | 5:a1843b698d0d | 175 | } | 
| KingMufasa | 5:a1843b698d0d | 176 | |
| JesseLohman | 2:5cace74299e7 | 177 | double measureVelocity (int motor) | 
| JesseLohman | 2:5cace74299e7 | 178 | { | 
| JesseLohman | 2:5cace74299e7 | 179 | static double lastPulses = 0; | 
| JesseLohman | 2:5cace74299e7 | 180 | double currentPulses; | 
| JesseLohman | 2:5cace74299e7 | 181 | static double velocity = 0; | 
| JesseLohman | 3:be922ea2415f | 182 | |
| JesseLohman | 2:5cace74299e7 | 183 | static int i = 0; | 
| JesseLohman | 2:5cace74299e7 | 184 | if (i == 10) { // Encoder is not accurate enough, so with 1000 Hz the velocity can only be 0, 1000, 2000 or 3000 pulses/s | 
| JesseLohman | 3:be922ea2415f | 185 | switch (motor) { // Check which motor to measure | 
| JesseLohman | 3:be922ea2415f | 186 | case 1: | 
| JesseLohman | 3:be922ea2415f | 187 | currentPulses = encoder1.getPulses(); | 
| JesseLohman | 3:be922ea2415f | 188 | break; | 
| JesseLohman | 3:be922ea2415f | 189 | case 2: | 
| JesseLohman | 8:5896424eb539 | 190 | currentPulses = encoder2.getPulses(); | 
| JesseLohman | 3:be922ea2415f | 191 | break; | 
| JesseLohman | 3:be922ea2415f | 192 | } | 
| JesseLohman | 2:5cace74299e7 | 193 | |
| JesseLohman | 3:be922ea2415f | 194 | double deltaPulses = currentPulses - lastPulses; | 
| JesseLohman | 3:be922ea2415f | 195 | velocity = deltaPulses / (sampleTime * 10); // Velocity in pulses/s | 
| JesseLohman | 3:be922ea2415f | 196 | lastPulses = currentPulses; | 
| JesseLohman | 3:be922ea2415f | 197 | i = 0; | 
| JesseLohman | 2:5cace74299e7 | 198 | } else { | 
| JesseLohman | 2:5cace74299e7 | 199 | i += 1; | 
| JesseLohman | 2:5cace74299e7 | 200 | } | 
| JesseLohman | 2:5cace74299e7 | 201 | return velocity; | 
| JesseLohman | 2:5cace74299e7 | 202 | } | 
| JesseLohman | 2:5cace74299e7 | 203 | |
| JesseLohman | 3:be922ea2415f | 204 | void measurePosition() // Measure actual angle position with the encoder | 
| JesseLohman | 2:5cace74299e7 | 205 | { | 
| JesseLohman | 8:5896424eb539 | 206 | double pulses1 = encoder2.getPulses(); // motor 1 is on M2 and ENC2 of biorobotics shield | 
| JesseLohman | 8:5896424eb539 | 207 | double pulses2 = encoder1.getPulses(); // motor 2 is on M1 and ENC1 of biorobotics shield | 
| JesseLohman | 8:5896424eb539 | 208 | // Calculate the angle relative to the '0' point + offset (we have 8400 pulses per revolution) | 
| JesseLohman | 8:5896424eb539 | 209 | qMeas1 = (pulses1) * 2 * PI / 8400 +140.7 * PI / 180; | 
| JesseLohman | 8:5896424eb539 | 210 | qMeas2 = (pulses2) * 2 * PI / 8400 -87 * PI / 180; | 
| JesseLohman | 2:5cace74299e7 | 211 | |
| JesseLohman | 3:be922ea2415f | 212 | } | 
| JesseLohman | 3:be922ea2415f | 213 | |
| JesseLohman | 3:be922ea2415f | 214 | template<std::size_t N, std::size_t M, std::size_t P> | 
| JesseLohman | 3:be922ea2415f | 215 | void mult(double A[N][M], double B[M][P]) | 
| JesseLohman | 3:be922ea2415f | 216 | { | 
| JesseLohman | 3:be922ea2415f | 217 | |
| JesseLohman | 3:be922ea2415f | 218 | for( int n =0; n < 5; n++) { | 
| JesseLohman | 3:be922ea2415f | 219 | for(int p =0; p < 5; p++) { | 
| JesseLohman | 3:be922ea2415f | 220 | C[n][p] =0; | 
| JesseLohman | 3:be922ea2415f | 221 | } | 
| JesseLohman | 3:be922ea2415f | 222 | } | 
| JesseLohman | 3:be922ea2415f | 223 | for (int n = 0; n < N; n++) { | 
| JesseLohman | 3:be922ea2415f | 224 | for (int p = 0; p < P; p++) { | 
| JesseLohman | 3:be922ea2415f | 225 | double num = 0; | 
| JesseLohman | 3:be922ea2415f | 226 | for (int m = 0; m < M; m++) { | 
| JesseLohman | 3:be922ea2415f | 227 | num += A[n][m] * B[m][p]; | 
| JesseLohman | 3:be922ea2415f | 228 | |
| JesseLohman | 3:be922ea2415f | 229 | } | 
| JesseLohman | 3:be922ea2415f | 230 | |
| JesseLohman | 3:be922ea2415f | 231 | C[n][p] = num; | 
| JesseLohman | 3:be922ea2415f | 232 | |
| JesseLohman | 3:be922ea2415f | 233 | } | 
| JesseLohman | 3:be922ea2415f | 234 | } | 
| JesseLohman | 3:be922ea2415f | 235 | |
| JesseLohman | 3:be922ea2415f | 236 | } | 
| JesseLohman | 3:be922ea2415f | 237 | |
| JesseLohman | 3:be922ea2415f | 238 | void inverseKinematics () | 
| JesseLohman | 3:be922ea2415f | 239 | { | 
| JesseLohman | 8:5896424eb539 | 240 | if (currentState == MovingState) { // Only in the MovingState should the qRef1, qRef2 change every sampleTime | 
| KingMufasa | 7:1906d404cd1e | 241 | |
| JesseLohman | 8:5896424eb539 | 242 | double Pe_set[3][1] { // Defining setpoint location of end effector | 
| JesseLohman | 8:5896424eb539 | 243 | {setPointX}, // Setting xcoord to setPointX | 
| JesseLohman | 8:5896424eb539 | 244 | {setPointY}, // Setting ycoord to setPointY | 
| JesseLohman | 3:be922ea2415f | 245 | {1} | 
| JesseLohman | 3:be922ea2415f | 246 | }; | 
| JesseLohman | 3:be922ea2415f | 247 | |
| JesseLohman | 8:5896424eb539 | 248 | // Calculating new H matrix | 
| JesseLohman | 3:be922ea2415f | 249 | double T1e[3][3] { | 
| JesseLohman | 3:be922ea2415f | 250 | {cos(qRef1), -sin(qRef1), 0}, | 
| JesseLohman | 3:be922ea2415f | 251 | {sin(qRef1), cos(qRef1), 0}, | 
| JesseLohman | 3:be922ea2415f | 252 | {0, 0, 1} | 
| JesseLohman | 3:be922ea2415f | 253 | }; | 
| JesseLohman | 3:be922ea2415f | 254 | double T20e[3][3] { | 
| JesseLohman | 3:be922ea2415f | 255 | {cos(qRef2), -sin(qRef2), L1-L1*cos(qRef2)}, | 
| JesseLohman | 3:be922ea2415f | 256 | {sin(qRef2), cos(qRef2), -L1*sin(qRef2)}, | 
| JesseLohman | 3:be922ea2415f | 257 | {0, 0, 1} | 
| JesseLohman | 3:be922ea2415f | 258 | }; | 
| JesseLohman | 3:be922ea2415f | 259 | |
| JesseLohman | 3:be922ea2415f | 260 | |
| JesseLohman | 8:5896424eb539 | 261 | mult<3,3,3>(T1e,T20e); // Matrix multiplication | 
| JesseLohman | 3:be922ea2415f | 262 | double H201[3][3] { | 
| JesseLohman | 3:be922ea2415f | 263 | {C[0][0],C[0][1],C[0][2]}, | 
| JesseLohman | 3:be922ea2415f | 264 | {C[1][0],C[1][1],C[1][2]}, | 
| JesseLohman | 3:be922ea2415f | 265 | {C[2][0],C[2][1],C[2][2]} | 
| JesseLohman | 3:be922ea2415f | 266 | }; | 
| JesseLohman | 3:be922ea2415f | 267 | |
| JesseLohman | 8:5896424eb539 | 268 | mult<3,3,3>(H201,H200); // Matrix multiplication | 
| JesseLohman | 3:be922ea2415f | 269 | double H20 [3][3] { | 
| JesseLohman | 3:be922ea2415f | 270 | {C[0][0],C[0][1],C[0][2]}, | 
| JesseLohman | 3:be922ea2415f | 271 | {C[1][0],C[1][1],C[1][2]}, | 
| JesseLohman | 3:be922ea2415f | 272 | {C[2][0],C[2][1],C[2][2]} | 
| JesseLohman | 3:be922ea2415f | 273 | }; | 
| JesseLohman | 3:be922ea2415f | 274 | |
| JesseLohman | 8:5896424eb539 | 275 | mult<3,3,1>(H20,Pe2); // Matrix multiplication | 
| JesseLohman | 3:be922ea2415f | 276 | double Pe0[3][1] { | 
| JesseLohman | 3:be922ea2415f | 277 | {C[0][0]}, | 
| JesseLohman | 3:be922ea2415f | 278 | {C[1][0]}, | 
| JesseLohman | 3:be922ea2415f | 279 | {C[2][0]} | 
| JesseLohman | 3:be922ea2415f | 280 | }; | 
| JesseLohman | 3:be922ea2415f | 281 | |
| JesseLohman | 8:5896424eb539 | 282 | double pe0x = Pe0[0][0]; // Seperating coordinates of end effector location | 
| JesseLohman | 3:be922ea2415f | 283 | double pe0y = Pe0[1][0]; | 
| JesseLohman | 3:be922ea2415f | 284 | |
| JesseLohman | 3:be922ea2415f | 285 | // Determing the jacobian | 
| JesseLohman | 3:be922ea2415f | 286 | |
| JesseLohman | 3:be922ea2415f | 287 | double T_1[3][1] { | 
| JesseLohman | 3:be922ea2415f | 288 | {1}, | 
| JesseLohman | 3:be922ea2415f | 289 | {T1[0][2]}, | 
| JesseLohman | 3:be922ea2415f | 290 | {T1[1][2]} | 
| JesseLohman | 3:be922ea2415f | 291 | }; | 
| JesseLohman | 3:be922ea2415f | 292 | |
| JesseLohman | 3:be922ea2415f | 293 | double T_2[3][1] { | 
| JesseLohman | 3:be922ea2415f | 294 | {1}, | 
| JesseLohman | 3:be922ea2415f | 295 | {L1*sin(qRef1)}, | 
| JesseLohman | 3:be922ea2415f | 296 | {-L1*cos(qRef1)} | 
| JesseLohman | 3:be922ea2415f | 297 | }; | 
| JesseLohman | 3:be922ea2415f | 298 | |
| JesseLohman | 3:be922ea2415f | 299 | double J[3][2] { | 
| JesseLohman | 3:be922ea2415f | 300 | {T_1[0][0], T_2[0][0]}, | 
| JesseLohman | 3:be922ea2415f | 301 | {T_1[1][0], T_2[1][0]}, | 
| JesseLohman | 3:be922ea2415f | 302 | {T_1[2][0], T_2[2][0]} | 
| JesseLohman | 3:be922ea2415f | 303 | }; | 
| JesseLohman | 3:be922ea2415f | 304 | |
| JesseLohman | 8:5896424eb539 | 305 | // Determing 'Pulling" force to setpoint | 
| JesseLohman | 3:be922ea2415f | 306 | |
| JesseLohman | 8:5896424eb539 | 307 | double kspring= 0.1; // Virtual stifness of the force | 
| JesseLohman | 8:5896424eb539 | 308 | double Fs[3][1] { // Force vector from end effector to setpoint | 
| KingMufasa | 6:e67250b8b100 | 309 | {kspring*Pe_set[0][0] - kspring*Pe0[0][0]}, | 
| KingMufasa | 6:e67250b8b100 | 310 | {kspring*Pe_set[1][0] - kspring*Pe0[1][0]}, | 
| KingMufasa | 6:e67250b8b100 | 311 | {kspring*Pe_set[2][0] - kspring*Pe0[2][0]} | 
| JesseLohman | 3:be922ea2415f | 312 | }; | 
| KingMufasa | 6:e67250b8b100 | 313 | double Fx = kspring*setPointX - kspring*pe0x; | 
| KingMufasa | 6:e67250b8b100 | 314 | double Fy = kspring*setPointY - kspring*pe0y; | 
| JesseLohman | 3:be922ea2415f | 315 | double W0t[3][1] { | 
| JesseLohman | 3:be922ea2415f | 316 | {pe0x*Fy - pe0y*Fx}, | 
| JesseLohman | 3:be922ea2415f | 317 | {Fx}, | 
| JesseLohman | 3:be922ea2415f | 318 | {Fy} | 
| JesseLohman | 3:be922ea2415f | 319 | }; | 
| JesseLohman | 3:be922ea2415f | 320 | |
| JesseLohman | 8:5896424eb539 | 321 | double Jt[2][3] { // Transposing jacobian matrix | 
| JesseLohman | 3:be922ea2415f | 322 | {J[0][0], J[1][0], J[2][0]}, | 
| JesseLohman | 3:be922ea2415f | 323 | {T_2[0][0], T_2[1][0], T_2[2][0]} | 
| JesseLohman | 3:be922ea2415f | 324 | }; | 
| JesseLohman | 3:be922ea2415f | 325 | |
| JesseLohman | 3:be922ea2415f | 326 | mult<2,3,1>(Jt,W0t); | 
| JesseLohman | 3:be922ea2415f | 327 | double tau_st1 = C[0][0]; | 
| JesseLohman | 3:be922ea2415f | 328 | double tau_st2 = C[1][0]; | 
| JesseLohman | 3:be922ea2415f | 329 | |
| JesseLohman | 8:5896424eb539 | 330 | // Calculating joint behaviour | 
| JesseLohman | 3:be922ea2415f | 331 | |
| KingMufasa | 7:1906d404cd1e | 332 | double b1 =1; | 
| KingMufasa | 5:a1843b698d0d | 333 | double b2 =1; | 
| JesseLohman | 8:5896424eb539 | 334 | // Joint friction coefficent | 
| JesseLohman | 8:5896424eb539 | 335 | double w_s1 = tau_st1/b1; // Angular velocity | 
| JesseLohman | 8:5896424eb539 | 336 | double w_s2 = tau_st2/b2; // Angular velocity | 
| JesseLohman | 8:5896424eb539 | 337 | // Checking angle boundaries | 
| JesseLohman | 8:5896424eb539 | 338 | qRef1 = qRef1 +w_s1*1; // Calculating new angle of qRef1 in time step sampleTime | 
| JesseLohman | 3:be922ea2415f | 339 | if (qRef1 > 2*PI/3) { | 
| JesseLohman | 3:be922ea2415f | 340 | qRef1 = 2*PI/3; | 
| JesseLohman | 3:be922ea2415f | 341 | } else if (qRef1 < PI/6) { | 
| JesseLohman | 3:be922ea2415f | 342 | qRef1= PI/6; | 
| JesseLohman | 3:be922ea2415f | 343 | } | 
| JesseLohman | 3:be922ea2415f | 344 | |
| JesseLohman | 8:5896424eb539 | 345 | qRef2 = qRef2 + w_s2*1; // Calculating new angle of qRef2 in time step sampleTime | 
| JesseLohman | 3:be922ea2415f | 346 | if (qRef2 > -PI/4) { | 
| JesseLohman | 3:be922ea2415f | 347 | qRef2 = -PI/4; | 
| JesseLohman | 3:be922ea2415f | 348 | } else if (qRef2 < -PI/2) { | 
| JesseLohman | 3:be922ea2415f | 349 | qRef2= -PI/2; | 
| JesseLohman | 3:be922ea2415f | 350 | } | 
| JesseLohman | 3:be922ea2415f | 351 | } | 
| JesseLohman | 3:be922ea2415f | 352 | } | 
| JesseLohman | 3:be922ea2415f | 353 | void PID_controller() // Put the error trough PID control to make output 'u' | 
| JesseLohman | 3:be922ea2415f | 354 | { | 
| KingMufasa | 7:1906d404cd1e | 355 | if (currentState >= HomingState && currentState < FailureState) { | 
| KingMufasa | 7:1906d404cd1e | 356 | // Should only work when we move the robot to a defined position | 
| JesseLohman | 8:5896424eb539 | 357 | double error1 = qRef1 - qMeas1; | 
| JesseLohman | 8:5896424eb539 | 358 | double error2 = qRef2 - qMeas2; | 
| JesseLohman | 3:be922ea2415f | 359 | |
| JesseLohman | 3:be922ea2415f | 360 | static double errorIntegral1 = 0; | 
| JesseLohman | 3:be922ea2415f | 361 | static double errorIntegral2 = 0; | 
| JesseLohman | 3:be922ea2415f | 362 | static double errorPrev1 = error1; | 
| JesseLohman | 3:be922ea2415f | 363 | static double errorPrev2 = error2; | 
| JesseLohman | 3:be922ea2415f | 364 | static BiQuad LowPassFilter(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); | 
| JesseLohman | 3:be922ea2415f | 365 | |
| KingMufasa | 4:8f25ecb74221 | 366 | // Proportional part: | 
| KingMufasa | 4:8f25ecb74221 | 367 | double u_k1 = Kp1 * error1; | 
| KingMufasa | 4:8f25ecb74221 | 368 | double u_k2 = Kp2 * error2; | 
| JesseLohman | 3:be922ea2415f | 369 | |
| JesseLohman | 3:be922ea2415f | 370 | //Integral part: | 
| JesseLohman | 3:be922ea2415f | 371 | errorIntegral1 = errorIntegral1 + error1 * sampleTime; | 
| KingMufasa | 4:8f25ecb74221 | 372 | double u_i1 = Ki1 * errorIntegral1; | 
| JesseLohman | 3:be922ea2415f | 373 | errorIntegral2 = errorIntegral2 + error2 * sampleTime; | 
| KingMufasa | 4:8f25ecb74221 | 374 | double u_i2 = Ki2 * errorIntegral2; | 
| JesseLohman | 3:be922ea2415f | 375 | |
| JesseLohman | 3:be922ea2415f | 376 | // Derivative part | 
| JesseLohman | 3:be922ea2415f | 377 | double errorDerivative1 = (error1 - errorPrev1)/sampleTime; | 
| JesseLohman | 3:be922ea2415f | 378 | double filteredErrorDerivative1 = LowPassFilter.step(errorDerivative1); | 
| KingMufasa | 4:8f25ecb74221 | 379 | double u_d1 = Kd1 * filteredErrorDerivative1; | 
| JesseLohman | 3:be922ea2415f | 380 | errorPrev1 = error1; | 
| JesseLohman | 3:be922ea2415f | 381 | double errorDerivative2 = (error2 - errorPrev2)/sampleTime; | 
| JesseLohman | 3:be922ea2415f | 382 | double filteredErrorDerivative2 = LowPassFilter.step(errorDerivative2); | 
| KingMufasa | 4:8f25ecb74221 | 383 | double u_d2 = Kd2 * filteredErrorDerivative2; | 
| JesseLohman | 3:be922ea2415f | 384 | errorPrev2 = error2; | 
| JesseLohman | 3:be922ea2415f | 385 | |
| JesseLohman | 8:5896424eb539 | 386 | // Sum all parts | 
| JesseLohman | 3:be922ea2415f | 387 | u1 = u_k1 + u_i1 + u_d1; | 
| JesseLohman | 3:be922ea2415f | 388 | u2 = u_k2 + u_i2 + u_d2; | 
| KingMufasa | 5:a1843b698d0d | 389 | } | 
| JesseLohman | 2:5cace74299e7 | 390 | } | 
| JesseLohman | 2:5cace74299e7 | 391 | |
| JesseLohman | 2:5cace74299e7 | 392 | void controlMotor () // Control direction and speed | 
| JesseLohman | 2:5cace74299e7 | 393 | { | 
| JesseLohman | 2:5cace74299e7 | 394 | directionpin1 = u1 > 0.0f; // Either true or false | 
| JesseLohman | 2:5cace74299e7 | 395 | pwmpin1 = fabs(u1); | 
| JesseLohman | 3:be922ea2415f | 396 | directionpin2 = u2 > 0.0f; // Either true or false | 
| JesseLohman | 3:be922ea2415f | 397 | pwmpin2 = fabs(u2); | 
| KingMufasa | 7:1906d404cd1e | 398 | directionpin3 = u3 > 0.0f; // Either true or false | 
| KingMufasa | 7:1906d404cd1e | 399 | pwmpin3 = fabs(u3); | 
| KingMufasa | 7:1906d404cd1e | 400 | directionpin4 = u4 > 0.0f; // Either true or false | 
| KingMufasa | 7:1906d404cd1e | 401 | pwmpin4 = fabs(u4); | 
| JesseLohman | 2:5cace74299e7 | 402 | } | 
| JesseLohman | 2:5cace74299e7 | 403 | |
| JesseLohman | 8:5896424eb539 | 404 | void EMGwaiting(){ //Flashes LED | 
| JesseLohman | 8:5896424eb539 | 405 | led3 = !led3; | 
| JesseLohman | 8:5896424eb539 | 406 | waitingcounter++; | 
| JesseLohman | 8:5896424eb539 | 407 | } | 
| JesseLohman | 8:5896424eb539 | 408 | |
| JesseLohman | 8:5896424eb539 | 409 | void EMGsampling(){ //Ticker function of EMG | 
| JesseLohman | 8:5896424eb539 | 410 | switch(processnow){ | 
| JesseLohman | 8:5896424eb539 | 411 | case 0: | 
| JesseLohman | 8:5896424eb539 | 412 | case 1: | 
| JesseLohman | 8:5896424eb539 | 413 | tot += abs(bqc.step(emg0.read())); | 
| JesseLohman | 8:5896424eb539 | 414 | break; | 
| JesseLohman | 8:5896424eb539 | 415 | case 2: | 
| JesseLohman | 8:5896424eb539 | 416 | case 3: | 
| JesseLohman | 8:5896424eb539 | 417 | tot += abs(bqc.step(emg2.read())); | 
| JesseLohman | 8:5896424eb539 | 418 | break; | 
| JesseLohman | 8:5896424eb539 | 419 | } | 
| JesseLohman | 8:5896424eb539 | 420 | counter++; | 
| JesseLohman | 8:5896424eb539 | 421 | if (counter >= samplecal){ | 
| JesseLohman | 8:5896424eb539 | 422 | tot = tot/ratio; | 
| JesseLohman | 8:5896424eb539 | 423 | switch(processnow){ | 
| JesseLohman | 8:5896424eb539 | 424 | case 0: | 
| JesseLohman | 8:5896424eb539 | 425 | armresttot = tot; | 
| JesseLohman | 8:5896424eb539 | 426 | pc.printf("<Result> Average area of arm signal in rest: %f.\r\n",armresttot); | 
| JesseLohman | 8:5896424eb539 | 427 | break; | 
| JesseLohman | 8:5896424eb539 | 428 | case 1: | 
| JesseLohman | 8:5896424eb539 | 429 | armflextot = tot; | 
| JesseLohman | 8:5896424eb539 | 430 | pc.printf("<Result>Average area of arm signal while flexing: %f.\r\n",armflextot); | 
| JesseLohman | 8:5896424eb539 | 431 | armcal = (armflextot + armresttot)/2.0; | 
| JesseLohman | 8:5896424eb539 | 432 | pc.printf("<Result> Calibration value for arms determined at %f.\r\n",armcal); | 
| JesseLohman | 8:5896424eb539 | 433 | break; | 
| JesseLohman | 8:5896424eb539 | 434 | case 2: | 
| JesseLohman | 8:5896424eb539 | 435 | legresttot = tot; | 
| JesseLohman | 8:5896424eb539 | 436 | pc.printf("<Result> Average area of leg signal in rest: %f.\r\n",legresttot); | 
| JesseLohman | 8:5896424eb539 | 437 | break; | 
| JesseLohman | 8:5896424eb539 | 438 | case 3: | 
| JesseLohman | 8:5896424eb539 | 439 | legflextot = tot; | 
| JesseLohman | 8:5896424eb539 | 440 | pc.printf("<Result> Average area of leg signal while flexing: %f.\r\n",legflextot); | 
| JesseLohman | 8:5896424eb539 | 441 | legcal = (legflextot + legresttot)/2; | 
| JesseLohman | 8:5896424eb539 | 442 | pc.printf("<Result> Calibration value for legs determined at %f.\r\n",legcal); | 
| JesseLohman | 8:5896424eb539 | 443 | break; | 
| JesseLohman | 8:5896424eb539 | 444 | } | 
| JesseLohman | 8:5896424eb539 | 445 | processnow++; | 
| JesseLohman | 8:5896424eb539 | 446 | tot = 0; | 
| JesseLohman | 8:5896424eb539 | 447 | counter = 0; | 
| JesseLohman | 8:5896424eb539 | 448 | } | 
| JesseLohman | 8:5896424eb539 | 449 | } | 
| JesseLohman | 8:5896424eb539 | 450 | |
| JesseLohman | 0:2a5dd6cc0008 | 451 | void stateMachine () | 
| JesseLohman | 0:2a5dd6cc0008 | 452 | { | 
| JesseLohman | 0:2a5dd6cc0008 | 453 | switch (currentState) { | 
| JesseLohman | 0:2a5dd6cc0008 | 454 | case WaitState: | 
| JesseLohman | 0:2a5dd6cc0008 | 455 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 456 | // Everything that needs to be done when this state is entered the first time | 
| JesseLohman | 8:5896424eb539 | 457 | led1 = 0; // Green | 
| JesseLohman | 1:4cb9af313c26 | 458 | led2 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 459 | led3 = 1; | 
| JesseLohman | 2:5cace74299e7 | 460 | u1 = 0; // Turn off all motors | 
| JesseLohman | 2:5cace74299e7 | 461 | u2 = 0; | 
| JesseLohman | 2:5cace74299e7 | 462 | u3 = 0; | 
| JesseLohman | 2:5cace74299e7 | 463 | u4 = 0; | 
| JesseLohman | 0:2a5dd6cc0008 | 464 | stateChanged = false; | 
| JesseLohman | 0:2a5dd6cc0008 | 465 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 466 | |
| JesseLohman | 2:5cace74299e7 | 467 | if (startButton.read() == false) { // When button is pressed, value is false | 
| JesseLohman | 8:5896424eb539 | 468 | // Everything that needs to be done when leaving this state | 
| JesseLohman | 1:4cb9af313c26 | 469 | led1 = 1; | 
| JesseLohman | 0:2a5dd6cc0008 | 470 | currentState = MotorCalState; | 
| JesseLohman | 0:2a5dd6cc0008 | 471 | stateChanged = true; | 
| JesseLohman | 0:2a5dd6cc0008 | 472 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 473 | |
| JesseLohman | 0:2a5dd6cc0008 | 474 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 475 | case MotorCalState: | 
| JesseLohman | 0:2a5dd6cc0008 | 476 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 477 | led2 = 0; // Red | 
| JesseLohman | 8:5896424eb539 | 478 | u1 = 0.3; // Motor is set to 'low' value | 
| JesseLohman | 8:5896424eb539 | 479 | u2 = -0.3; | 
| JesseLohman | 0:2a5dd6cc0008 | 480 | stateTimer.reset(); | 
| JesseLohman | 0:2a5dd6cc0008 | 481 | stateTimer.start(); | 
| JesseLohman | 0:2a5dd6cc0008 | 482 | stateChanged = false; | 
| JesseLohman | 0:2a5dd6cc0008 | 483 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 484 | |
| JesseLohman | 8:5896424eb539 | 485 | // The robot can only go to the next state after 3s, when the motor velocities are close to 0 and the start button is pressed | 
| JesseLohman | 8:5896424eb539 | 486 | if (stateTimer >= 3.0f && fabs(measureVelocity(1)) < 100 && fabs(measureVelocity(2)) < 100 && startButton.read() == false) { | 
| JesseLohman | 1:4cb9af313c26 | 487 | led2 = 1; | 
| JesseLohman | 2:5cace74299e7 | 488 | encoder1.reset(); // Reset encoder for the 0 position | 
| JesseLohman | 8:5896424eb539 | 489 | encoder2.reset(); | 
| JesseLohman | 0:2a5dd6cc0008 | 490 | currentState = EMGCalState; | 
| JesseLohman | 0:2a5dd6cc0008 | 491 | stateChanged = true; | 
| JesseLohman | 2:5cace74299e7 | 492 | u1 = 0; // Turn off motors | 
| JesseLohman | 2:5cace74299e7 | 493 | u2 = 0; | 
| JesseLohman | 0:2a5dd6cc0008 | 494 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 495 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 496 | case EMGCalState: | 
| JesseLohman | 0:2a5dd6cc0008 | 497 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 498 | led3 = 0; // Blue | 
| JesseLohman | 0:2a5dd6cc0008 | 499 | stateChanged = false; | 
| JesseLohman | 8:5896424eb539 | 500 | |
| JesseLohman | 8:5896424eb539 | 501 | pc.printf("<----------Now entering EMG calibration state ---------->\r\n"); | 
| JesseLohman | 8:5896424eb539 | 502 | pc.printf("<Waiting> Get ready for calibration of resting arms.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 503 | calTimer.attach(&EMGwaiting,0.5); //Wait | 
| JesseLohman | 8:5896424eb539 | 504 | while (waitingcounter < countermax) {} | 
| JesseLohman | 8:5896424eb539 | 505 | waitingcounter = 0; | 
| JesseLohman | 8:5896424eb539 | 506 | calTimer.detach(); | 
| JesseLohman | 8:5896424eb539 | 507 | |
| JesseLohman | 8:5896424eb539 | 508 | pc.printf("<Measuring> Measuring arm signal at rest. Hold still.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 509 | EMGsampler.attach(&EMGsampling,sampleTime); //Measure arms rest | 
| JesseLohman | 8:5896424eb539 | 510 | while (processnow == 0) {} | 
| JesseLohman | 8:5896424eb539 | 511 | EMGsampler.detach(); | 
| JesseLohman | 8:5896424eb539 | 512 | |
| JesseLohman | 8:5896424eb539 | 513 | pc.printf("<Waiting> Get ready for calibration of flexing arms.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 514 | calTimer.attach(&EMGwaiting,0.5); // Wait | 
| JesseLohman | 8:5896424eb539 | 515 | while (waitingcounter < countermax) {} | 
| JesseLohman | 8:5896424eb539 | 516 | waitingcounter = 0; | 
| JesseLohman | 8:5896424eb539 | 517 | calTimer.detach(); | 
| JesseLohman | 8:5896424eb539 | 518 | |
| JesseLohman | 8:5896424eb539 | 519 | pc.printf("<Measuring> Measuring arm signal while flexing.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 520 | EMGsampler.attach(&EMGsampling,sampleTime); //Measure arms flexing | 
| JesseLohman | 8:5896424eb539 | 521 | while (processnow == 1) {} | 
| JesseLohman | 8:5896424eb539 | 522 | EMGsampler.detach(); | 
| JesseLohman | 8:5896424eb539 | 523 | |
| JesseLohman | 8:5896424eb539 | 524 | pc.printf("<Waiting> Get ready for calibration of resting legs.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 525 | calTimer.attach(&EMGwaiting,0.5); //Wait | 
| JesseLohman | 8:5896424eb539 | 526 | while (waitingcounter < countermax) {} | 
| JesseLohman | 8:5896424eb539 | 527 | waitingcounter = 0; | 
| JesseLohman | 8:5896424eb539 | 528 | calTimer.detach(); | 
| JesseLohman | 8:5896424eb539 | 529 | |
| JesseLohman | 8:5896424eb539 | 530 | pc.printf("<Measuring> Measuring leg signal at rest. Hold still.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 531 | EMGsampler.attach(&EMGsampling,sampleTime); //Measure legs rest | 
| JesseLohman | 8:5896424eb539 | 532 | while (processnow == 2) {} | 
| JesseLohman | 8:5896424eb539 | 533 | EMGsampler.detach(); | 
| JesseLohman | 8:5896424eb539 | 534 | |
| JesseLohman | 8:5896424eb539 | 535 | pc.printf("<Waiting> Get ready for calibration of flexing legs.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 536 | calTimer.attach(&EMGwaiting,0.5); // Wait | 
| JesseLohman | 8:5896424eb539 | 537 | while (waitingcounter < countermax) {} | 
| JesseLohman | 8:5896424eb539 | 538 | waitingcounter = 0; | 
| JesseLohman | 8:5896424eb539 | 539 | calTimer.detach(); | 
| JesseLohman | 8:5896424eb539 | 540 | |
| JesseLohman | 8:5896424eb539 | 541 | pc.printf("<Measuring> Measuring leg signal while flexing.\r\n"); | 
| JesseLohman | 8:5896424eb539 | 542 | EMGsampler.attach(&EMGsampling,sampleTime); //Measure legs flexing | 
| JesseLohman | 8:5896424eb539 | 543 | while (processnow == 3) {} | 
| JesseLohman | 8:5896424eb539 | 544 | EMGsampler.detach(); | 
| JesseLohman | 8:5896424eb539 | 545 | |
| JesseLohman | 8:5896424eb539 | 546 | pc.printf("<Result> EMG calibrations complete.\r\n"); | 
| JesseLohman | 0:2a5dd6cc0008 | 547 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 548 | |
| JesseLohman | 0:2a5dd6cc0008 | 549 | if (stateTimer >= 3.0f) { | 
| JesseLohman | 1:4cb9af313c26 | 550 | led3 = 1; | 
| JesseLohman | 0:2a5dd6cc0008 | 551 | currentState = HomingState; | 
| JesseLohman | 0:2a5dd6cc0008 | 552 | stateChanged = true; | 
| JesseLohman | 0:2a5dd6cc0008 | 553 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 554 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 555 | case HomingState: | 
| JesseLohman | 0:2a5dd6cc0008 | 556 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 557 | led1 = 0; // Yellow | 
| JesseLohman | 8:5896424eb539 | 558 | led2 = 0; | 
| JesseLohman | 8:5896424eb539 | 559 | // qRef1 and qRef2 are set, so the motors will move to that position | 
| KingMufasa | 7:1906d404cd1e | 560 | qRef1 = 60 * PI / 180; | 
| JesseLohman | 8:5896424eb539 | 561 | qRef2 = -90 * PI / 180; | 
| JesseLohman | 0:2a5dd6cc0008 | 562 | stateChanged = false; | 
| JesseLohman | 0:2a5dd6cc0008 | 563 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 564 | |
| JesseLohman | 1:4cb9af313c26 | 565 | if (startButton.read() == false) { //TODO: Also add position condition | 
| JesseLohman | 1:4cb9af313c26 | 566 | led1 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 567 | led2 = 1; | 
| JesseLohman | 0:2a5dd6cc0008 | 568 | currentState = MovingState; | 
| JesseLohman | 0:2a5dd6cc0008 | 569 | stateChanged = true; | 
| JesseLohman | 0:2a5dd6cc0008 | 570 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 571 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 572 | case MovingState: | 
| JesseLohman | 1:4cb9af313c26 | 573 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 574 | led1 = 0; // White | 
| JesseLohman | 1:4cb9af313c26 | 575 | led2 = 0; | 
| JesseLohman | 8:5896424eb539 | 576 | led3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 577 | stateChanged = false; | 
| JesseLohman | 1:4cb9af313c26 | 578 | } | 
| JesseLohman | 1:4cb9af313c26 | 579 | |
| KingMufasa | 7:1906d404cd1e | 580 | if (gripperButton.read() == false) { | 
| JesseLohman | 0:2a5dd6cc0008 | 581 | led1 = 1; | 
| JesseLohman | 0:2a5dd6cc0008 | 582 | led2 = 1; | 
| JesseLohman | 0:2a5dd6cc0008 | 583 | led3 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 584 | currentState = GrippingState; | 
| JesseLohman | 1:4cb9af313c26 | 585 | stateChanged = true; | 
| JesseLohman | 1:4cb9af313c26 | 586 | } | 
| JesseLohman | 1:4cb9af313c26 | 587 | |
| JesseLohman | 1:4cb9af313c26 | 588 | break; | 
| JesseLohman | 1:4cb9af313c26 | 589 | case GrippingState: | 
| JesseLohman | 1:4cb9af313c26 | 590 | if (stateChanged == true) { | 
| JesseLohman | 8:5896424eb539 | 591 | led2 = 0; // Light blue | 
| JesseLohman | 8:5896424eb539 | 592 | led3 = 0; | 
| KingMufasa | 7:1906d404cd1e | 593 | stateTimer.reset(); | 
| KingMufasa | 7:1906d404cd1e | 594 | stateTimer.start(); | 
| JesseLohman | 0:2a5dd6cc0008 | 595 | stateChanged = false; | 
| JesseLohman | 0:2a5dd6cc0008 | 596 | } | 
| JesseLohman | 1:4cb9af313c26 | 597 | |
| KingMufasa | 7:1906d404cd1e | 598 | if (gripperMotorButton.read() == false) { | 
| JesseLohman | 8:5896424eb539 | 599 | // Gripper motor is activated | 
| KingMufasa | 7:1906d404cd1e | 600 | u3 = 0.4; | 
| KingMufasa | 7:1906d404cd1e | 601 | if (directionSwitch == true) { | 
| KingMufasa | 7:1906d404cd1e | 602 | // Close gripper, so positive direction | 
| KingMufasa | 7:1906d404cd1e | 603 | } else { | 
| KingMufasa | 7:1906d404cd1e | 604 | // Open gripper | 
| KingMufasa | 7:1906d404cd1e | 605 | u3 = u3 * -1; | 
| KingMufasa | 7:1906d404cd1e | 606 | } | 
| KingMufasa | 7:1906d404cd1e | 607 | } else { // If the button isn't pressed, turn off motor | 
| KingMufasa | 7:1906d404cd1e | 608 | u3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 609 | } | 
| JesseLohman | 1:4cb9af313c26 | 610 | |
| JesseLohman | 8:5896424eb539 | 611 | // Due to the lack of buttons, we use a delay, so that when we don't immediately go to the next state when we enter this state | 
| KingMufasa | 7:1906d404cd1e | 612 | if (gripperButton.read() == false && stateTimer >= 2.0f) { | 
| JesseLohman | 1:4cb9af313c26 | 613 | led2 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 614 | led3 = 1; | 
| KingMufasa | 7:1906d404cd1e | 615 | u3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 616 | currentState = ScrewingState; | 
| JesseLohman | 1:4cb9af313c26 | 617 | stateChanged = true; | 
| JesseLohman | 1:4cb9af313c26 | 618 | } | 
| JesseLohman | 1:4cb9af313c26 | 619 | if (startButton.read() == false) { | 
| JesseLohman | 1:4cb9af313c26 | 620 | led2 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 621 | led3 = 1; | 
| KingMufasa | 7:1906d404cd1e | 622 | u3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 623 | currentState = MovingState; | 
| JesseLohman | 1:4cb9af313c26 | 624 | stateChanged = true; | 
| JesseLohman | 1:4cb9af313c26 | 625 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 626 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 627 | case ScrewingState: | 
| JesseLohman | 1:4cb9af313c26 | 628 | if (stateChanged == true) { | 
| JesseLohman | 1:4cb9af313c26 | 629 | // Entry action: all the things you do once in this state; | 
| JesseLohman | 8:5896424eb539 | 630 | led1 = 0; // Pink | 
| JesseLohman | 8:5896424eb539 | 631 | led3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 632 | stateChanged = false; | 
| JesseLohman | 1:4cb9af313c26 | 633 | } | 
| JesseLohman | 2:5cace74299e7 | 634 | |
| KingMufasa | 7:1906d404cd1e | 635 | if (gripperMotorButton.read() == false) { | 
| JesseLohman | 8:5896424eb539 | 636 | u4 = 0.3; // Screwing motor is activated | 
| JesseLohman | 8:5896424eb539 | 637 | u3 = -0.35; // Gripper motor is activated with a slightly higher output to make sure the gripper doesn't open | 
| KingMufasa | 7:1906d404cd1e | 638 | if (directionSwitch == true) { | 
| KingMufasa | 7:1906d404cd1e | 639 | // Screw | 
| KingMufasa | 7:1906d404cd1e | 640 | } else { | 
| KingMufasa | 7:1906d404cd1e | 641 | // Unscrew | 
| KingMufasa | 7:1906d404cd1e | 642 | u4 = u4 * -1; | 
| KingMufasa | 7:1906d404cd1e | 643 | u3 = u3 * -1; | 
| KingMufasa | 7:1906d404cd1e | 644 | } | 
| JesseLohman | 8:5896424eb539 | 645 | } else { // If the button isn't pressed, turn off motors | 
| KingMufasa | 7:1906d404cd1e | 646 | u4 = 0; | 
| KingMufasa | 7:1906d404cd1e | 647 | u3 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 648 | } | 
| JesseLohman | 2:5cace74299e7 | 649 | |
| JesseLohman | 1:4cb9af313c26 | 650 | if (startButton.read() == false) { | 
| JesseLohman | 1:4cb9af313c26 | 651 | led1 = 1; | 
| JesseLohman | 1:4cb9af313c26 | 652 | led3 = 1; | 
| JesseLohman | 8:5896424eb539 | 653 | u3 = 0; // Turn off motors | 
| KingMufasa | 7:1906d404cd1e | 654 | u4 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 655 | currentState = MovingState; | 
| JesseLohman | 1:4cb9af313c26 | 656 | stateChanged = true; | 
| JesseLohman | 1:4cb9af313c26 | 657 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 658 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 659 | case FailureState: | 
| JesseLohman | 0:2a5dd6cc0008 | 660 | if (stateChanged == true) { | 
| JesseLohman | 0:2a5dd6cc0008 | 661 | // Entry action: all the things you do once in this state | 
| JesseLohman | 2:5cace74299e7 | 662 | u1 = 0; // Turn off all motors | 
| JesseLohman | 2:5cace74299e7 | 663 | u2 = 0; | 
| JesseLohman | 2:5cace74299e7 | 664 | u3 = 0; | 
| JesseLohman | 2:5cace74299e7 | 665 | u4 = 0; | 
| JesseLohman | 0:2a5dd6cc0008 | 666 | stateChanged = false; | 
| JesseLohman | 0:2a5dd6cc0008 | 667 | } | 
| JesseLohman | 1:4cb9af313c26 | 668 | |
| KingMufasa | 7:1906d404cd1e | 669 | static double blinkTimer2 = 0; | 
| JesseLohman | 8:5896424eb539 | 670 | if (blinkTimer2 >= 0.5) { // The red LED is flashing at 1 Hz | 
| JesseLohman | 1:4cb9af313c26 | 671 | led1 = !led1; | 
| KingMufasa | 7:1906d404cd1e | 672 | blinkTimer2 = 0; | 
| JesseLohman | 1:4cb9af313c26 | 673 | } | 
| KingMufasa | 7:1906d404cd1e | 674 | blinkTimer2 += sampleTime; | 
| JesseLohman | 1:4cb9af313c26 | 675 | break; | 
| JesseLohman | 0:2a5dd6cc0008 | 676 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 677 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 678 | |
| JesseLohman | 3:be922ea2415f | 679 | void measureAll () | 
| JesseLohman | 3:be922ea2415f | 680 | { | 
| JesseLohman | 3:be922ea2415f | 681 | measurePosition(); | 
| KingMufasa | 5:a1843b698d0d | 682 | measureEMG(); | 
| JesseLohman | 3:be922ea2415f | 683 | inverseKinematics(); | 
| JesseLohman | 3:be922ea2415f | 684 | } | 
| JesseLohman | 3:be922ea2415f | 685 | |
| JesseLohman | 8:5896424eb539 | 686 | void mainLoop () // All the major functions are looped every 0.001s | 
| JesseLohman | 0:2a5dd6cc0008 | 687 | { | 
| JesseLohman | 2:5cace74299e7 | 688 | measureAll(); | 
| JesseLohman | 0:2a5dd6cc0008 | 689 | stateMachine(); | 
| JesseLohman | 3:be922ea2415f | 690 | PID_controller(); | 
| JesseLohman | 2:5cace74299e7 | 691 | controlMotor(); | 
| JesseLohman | 0:2a5dd6cc0008 | 692 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 693 | |
| JesseLohman | 0:2a5dd6cc0008 | 694 | int main() | 
| JesseLohman | 0:2a5dd6cc0008 | 695 | { | 
| JesseLohman | 8:5896424eb539 | 696 | startButton.mode(PullUp); // Makes the button active | 
| KingMufasa | 7:1906d404cd1e | 697 | failureButton.mode(PullUp); | 
| KingMufasa | 7:1906d404cd1e | 698 | gripperButton.mode(PullUp); | 
| KingMufasa | 7:1906d404cd1e | 699 | directionSwitch.mode(PullUp); | 
| KingMufasa | 7:1906d404cd1e | 700 | gripperMotorButton.mode(PullUp); | 
| KingMufasa | 5:a1843b698d0d | 701 | pc.baud(115200); | 
| JesseLohman | 8:5896424eb539 | 702 | bqc.add(&hpf).add(¬ch).add(&lpf); // Add bqfilters to bqc | 
| JesseLohman | 0:2a5dd6cc0008 | 703 | mainTicker.attach(mainLoop, sampleTime); | 
| JesseLohman | 0:2a5dd6cc0008 | 704 | failureButton.fall(&switchToFailureState); // When button is pressed FailureState is activated | 
| JesseLohman | 0:2a5dd6cc0008 | 705 | |
| JesseLohman | 0:2a5dd6cc0008 | 706 | while (true) { | 
| JesseLohman | 0:2a5dd6cc0008 | 707 | } | 
| JesseLohman | 0:2a5dd6cc0008 | 708 | } | 
