changed the location of all constants to Constants.h
Dependencies: HIDScope QEI biquadFilter mbed
Fork of State_machine by
main.cpp@2:3f67b4833256, 2018-10-30 (annotated)
- Committer:
- CasperK
- Date:
- Tue Oct 30 15:58:07 2018 +0000
- Revision:
- 2:3f67b4833256
- Parent:
- 1:afb820c6fc0d
- Child:
- 3:ed4676f76a5c
Added emg and emg-calibration, not tested yet
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
CasperK | 0:1b2c842eca42 | 1 | #include "mbed.h" |
CasperK | 1:afb820c6fc0d | 2 | #include "QEI.h" |
CasperK | 1:afb820c6fc0d | 3 | #include "HIDScope.h" |
CasperK | 1:afb820c6fc0d | 4 | #include "MODSERIAL.h" |
CasperK | 2:3f67b4833256 | 5 | #include "BiQuad.h" |
CasperK | 2:3f67b4833256 | 6 | #include "math.h" |
CasperK | 2:3f67b4833256 | 7 | |
CasperK | 2:3f67b4833256 | 8 | #define IGNORECOUNT 100 |
CasperK | 1:afb820c6fc0d | 9 | |
CasperK | 1:afb820c6fc0d | 10 | PwmOut pwmpin1(D6); |
CasperK | 1:afb820c6fc0d | 11 | PwmOut pwmpin2(D5); |
CasperK | 1:afb820c6fc0d | 12 | AnalogIn potmeter1(A5); |
CasperK | 1:afb820c6fc0d | 13 | AnalogIn potmeter2(A4); |
CasperK | 1:afb820c6fc0d | 14 | DigitalIn button1(D2); |
CasperK | 1:afb820c6fc0d | 15 | DigitalIn button2(D3); |
CasperK | 1:afb820c6fc0d | 16 | DigitalOut directionpin1(D4); |
CasperK | 1:afb820c6fc0d | 17 | DigitalOut directionpin2(D7); |
CasperK | 1:afb820c6fc0d | 18 | QEI motor1(D13,D12,NC, 32); |
CasperK | 1:afb820c6fc0d | 19 | QEI motor2(D11,D10,NC, 32); |
CasperK | 1:afb820c6fc0d | 20 | |
CasperK | 2:3f67b4833256 | 21 | //Define objects |
CasperK | 2:3f67b4833256 | 22 | AnalogIn emg0( A0 ); // EMG at A0 |
CasperK | 2:3f67b4833256 | 23 | BiQuad emg0bq1(0.8848578, -1.7697156, 0.8848578, -1.7539023, 0.7855289); // highpass at 30Hz Q at around 1 |
CasperK | 2:3f67b4833256 | 24 | BiQuad emg0bq2(0.0773021,0.1546042,0.0773021,-1.3098283,0.6190368); // lowpass at 130 Hz Q at around .6 |
CasperK | 2:3f67b4833256 | 25 | BiQuad emg0bq3(0.9556457,-1.81774618, 0.955645, -1.817746, 0.9112914); // 50 Hz notch Q at 4.5 |
CasperK | 2:3f67b4833256 | 26 | BiQuadChain emg0bqc; // merged chain of three filters |
CasperK | 2:3f67b4833256 | 27 | |
CasperK | 2:3f67b4833256 | 28 | AnalogIn emg1( A1 ); // EMG at A1 |
CasperK | 2:3f67b4833256 | 29 | BiQuad emg1bq1(0.8848578, -1.7697156, 0.8848578, -1.7539023, 0.7855289); // highpass at 30Hz Q at around 1 |
CasperK | 2:3f67b4833256 | 30 | BiQuad emg1bq2(0.0773021,0.1546042,0.0773021,-1.3098283,0.6190368); // lowpass at 130 Hz Q at around .6 |
CasperK | 2:3f67b4833256 | 31 | BiQuad emg1bq3(0.9556457,-1.81774618, 0.955645, -1.817746, 0.9112914); // 50 Hz notch Q at 4.5 |
CasperK | 2:3f67b4833256 | 32 | BiQuadChain emg1bqc; // merged chain of three filters |
CasperK | 2:3f67b4833256 | 33 | |
CasperK | 2:3f67b4833256 | 34 | |
CasperK | 2:3f67b4833256 | 35 | AnalogIn emg2( A2 ); // EMG at A2 |
CasperK | 2:3f67b4833256 | 36 | BiQuad emg2bq1(0.8848578, -1.7697156, 0.8848578, -1.7539023, 0.7855289); // highpass at 30Hz Q at around 1 |
CasperK | 2:3f67b4833256 | 37 | BiQuad emg2bq2(0.0773021,0.1546042,0.0773021,-1.3098283,0.6190368); // lowpass at 130 Hz Q at around .6 |
CasperK | 2:3f67b4833256 | 38 | BiQuad emg2bq3(0.9556457,-1.81774618, 0.955645, -1.817746, 0.9112914); // 50 Hz notch Q at 4.5 |
CasperK | 2:3f67b4833256 | 39 | BiQuadChain emg2bqc; // merged chain of three filters |
CasperK | 2:3f67b4833256 | 40 | |
CasperK | 1:afb820c6fc0d | 41 | DigitalIn kill_switch(SW2); //position has to be changed |
CasperK | 1:afb820c6fc0d | 42 | DigitalIn next_switch(SW3); //name and position should be replaced |
CasperK | 1:afb820c6fc0d | 43 | |
CasperK | 2:3f67b4833256 | 44 | enum states{PositionCalibration, EmgCalibration, Movement, KILL}; |
CasperK | 2:3f67b4833256 | 45 | states CurrentState; |
CasperK | 2:3f67b4833256 | 46 | Ticker sample_timer; |
CasperK | 2:3f67b4833256 | 47 | Ticker MotorsTicker; |
CasperK | 2:3f67b4833256 | 48 | Timer timer; |
CasperK | 2:3f67b4833256 | 49 | |
CasperK | 1:afb820c6fc0d | 50 | //for testing purposes |
CasperK | 1:afb820c6fc0d | 51 | DigitalOut ledred(LED_RED); |
CasperK | 1:afb820c6fc0d | 52 | DigitalOut ledgreen(LED_GREEN); |
CasperK | 1:afb820c6fc0d | 53 | DigitalOut ledblue(LED_BLUE); |
CasperK | 2:3f67b4833256 | 54 | MODSERIAL pc(USBTX, USBRX); |
CasperK | 2:3f67b4833256 | 55 | HIDScope scope(2); |
CasperK | 1:afb820c6fc0d | 56 | |
CasperK | 2:3f67b4833256 | 57 | bool emg0Bool = 0; // I don't know if these NEED to be global, but when I tried to put them in they wouldn't work... |
CasperK | 2:3f67b4833256 | 58 | int emg0Ignore = 0; |
CasperK | 2:3f67b4833256 | 59 | bool emg1Bool = 0; |
CasperK | 2:3f67b4833256 | 60 | int emg1Ignore = 0; |
CasperK | 2:3f67b4833256 | 61 | bool emg2Bool = 0; |
CasperK | 2:3f67b4833256 | 62 | int emg2Ignore = 0; |
CasperK | 1:afb820c6fc0d | 63 | |
CasperK | 2:3f67b4833256 | 64 | float threshold0; |
CasperK | 2:3f67b4833256 | 65 | float threshold1; |
CasperK | 2:3f67b4833256 | 66 | float threshold2; |
CasperK | 1:afb820c6fc0d | 67 | |
CasperK | 1:afb820c6fc0d | 68 | volatile float pwm_value1 = 0.0; |
CasperK | 1:afb820c6fc0d | 69 | volatile float pwm_value2 = 0.0; |
CasperK | 0:1b2c842eca42 | 70 | |
CasperK | 2:3f67b4833256 | 71 | /** Sample functions |
CasperK | 2:3f67b4833256 | 72 | * these functions sample the emg and send it to HIDScope |
CasperK | 2:3f67b4833256 | 73 | **/ |
CasperK | 2:3f67b4833256 | 74 | bool emg0Filter(void){ |
CasperK | 2:3f67b4833256 | 75 | double emg0filteredAbs = fabs( emg0bqc.step(emg0.read())); // Filter and make absolute, |
CasperK | 2:3f67b4833256 | 76 | /* this is the threshhold */ |
CasperK | 2:3f67b4833256 | 77 | if (emg0filteredAbs > threshold0) { // when above threshold set bool to 1, here can the parameters be changed using global variables |
CasperK | 2:3f67b4833256 | 78 | emg0Bool = true; |
CasperK | 2:3f67b4833256 | 79 | emg0Ignore = IGNORECOUNT; // here is the counter increased ( at 1000 Hz, this is 0.1 sec) |
CasperK | 2:3f67b4833256 | 80 | } |
CasperK | 2:3f67b4833256 | 81 | else if (emg0Ignore < 0){ // if the ignore-counter is down to zero, set the bool back to 0 |
CasperK | 2:3f67b4833256 | 82 | emg0Bool = false; |
CasperK | 2:3f67b4833256 | 83 | } |
CasperK | 2:3f67b4833256 | 84 | else { |
CasperK | 2:3f67b4833256 | 85 | emg0Ignore--; // else decrease counter by one each time has passed without threshold being met |
CasperK | 2:3f67b4833256 | 86 | } |
CasperK | 2:3f67b4833256 | 87 | return emg0Bool; |
CasperK | 2:3f67b4833256 | 88 | } |
CasperK | 2:3f67b4833256 | 89 | |
CasperK | 2:3f67b4833256 | 90 | bool emg1Filter(void){ |
CasperK | 2:3f67b4833256 | 91 | double emg1filteredAbs = fabs( emg1bqc.step(emg1.read())); // Filter and make absolute |
CasperK | 2:3f67b4833256 | 92 | /* this is the threshhold */ |
CasperK | 2:3f67b4833256 | 93 | if (emg1filteredAbs > threshold1) { // when above threshold set bool to 1 here can the parameters be changed using global variables |
CasperK | 2:3f67b4833256 | 94 | emg1Bool = true; |
CasperK | 2:3f67b4833256 | 95 | emg1Ignore = IGNORECOUNT; // here is the counter increased ( at 1000 Hz, this is 0.1 sec) |
CasperK | 2:3f67b4833256 | 96 | } |
CasperK | 2:3f67b4833256 | 97 | else if (emg1Ignore < 0){ // if the ignore-counter is down to zero, set the bool back to 0 |
CasperK | 2:3f67b4833256 | 98 | emg1Bool = false; |
CasperK | 2:3f67b4833256 | 99 | } |
CasperK | 2:3f67b4833256 | 100 | else { |
CasperK | 2:3f67b4833256 | 101 | emg1Ignore--; // else decrease counter by one each time has passed without threshold being met |
CasperK | 2:3f67b4833256 | 102 | } |
CasperK | 2:3f67b4833256 | 103 | return emg1Bool; |
CasperK | 2:3f67b4833256 | 104 | } |
CasperK | 2:3f67b4833256 | 105 | |
CasperK | 2:3f67b4833256 | 106 | bool emg2Filter(void){ |
CasperK | 2:3f67b4833256 | 107 | double emg2filteredAbs = fabs( emg2bqc.step(emg2.read())); // Filter and make absolute |
CasperK | 2:3f67b4833256 | 108 | /* this is the threshhold */ |
CasperK | 2:3f67b4833256 | 109 | if (emg2filteredAbs > threshold2) { // when above threshold set bool to 1 here can the parameters be changed using global variables |
CasperK | 2:3f67b4833256 | 110 | emg2Bool = true; |
CasperK | 2:3f67b4833256 | 111 | emg2Ignore = IGNORECOUNT; // here is the counter increased ( at 1000 Hz, this is 0.1 sec) |
CasperK | 2:3f67b4833256 | 112 | } |
CasperK | 2:3f67b4833256 | 113 | else if (emg2Ignore < 0){ // if the ignore-counter is down to zero, set the bool back to 0 |
CasperK | 2:3f67b4833256 | 114 | emg2Bool = false; |
CasperK | 2:3f67b4833256 | 115 | } |
CasperK | 2:3f67b4833256 | 116 | else { |
CasperK | 2:3f67b4833256 | 117 | emg2Ignore--; // else decrease counter by one each time has passed without threshold being met |
CasperK | 2:3f67b4833256 | 118 | } |
CasperK | 2:3f67b4833256 | 119 | return emg2Bool; |
CasperK | 2:3f67b4833256 | 120 | } |
CasperK | 2:3f67b4833256 | 121 | void sample() { |
CasperK | 2:3f67b4833256 | 122 | bool Bool1 = emg0Filter(); // whatever name casper uses for the bool |
CasperK | 2:3f67b4833256 | 123 | bool Bool2 = emg1Filter(); |
CasperK | 2:3f67b4833256 | 124 | bool Bool3 = emg2Filter(); |
CasperK | 2:3f67b4833256 | 125 | } |
CasperK | 2:3f67b4833256 | 126 | |
CasperK | 1:afb820c6fc0d | 127 | void positionCalibration() { |
CasperK | 1:afb820c6fc0d | 128 | while(!button1){ |
CasperK | 2:3f67b4833256 | 129 | directionpin1 = true; |
CasperK | 2:3f67b4833256 | 130 | pwm_value1 = 0.7f; |
CasperK | 1:afb820c6fc0d | 131 | } |
CasperK | 2:3f67b4833256 | 132 | pwm_value1 = 0.0f; |
CasperK | 1:afb820c6fc0d | 133 | while(!button2){ |
CasperK | 1:afb820c6fc0d | 134 | directionpin2 = true; |
CasperK | 1:afb820c6fc0d | 135 | pwm_value2 = 0.7f; |
CasperK | 1:afb820c6fc0d | 136 | } |
CasperK | 1:afb820c6fc0d | 137 | pwm_value2 = 0.0f; |
CasperK | 1:afb820c6fc0d | 138 | |
CasperK | 1:afb820c6fc0d | 139 | // pwm_value1 = potmeter1; |
CasperK | 1:afb820c6fc0d | 140 | // pwm_value2 = potmeter2; |
CasperK | 1:afb820c6fc0d | 141 | |
CasperK | 1:afb820c6fc0d | 142 | if (!next_switch) { |
CasperK | 1:afb820c6fc0d | 143 | CurrentState = EmgCalibration; |
CasperK | 1:afb820c6fc0d | 144 | pc.printf("current state = EmgCalibration\n\r"); |
CasperK | 1:afb820c6fc0d | 145 | } |
CasperK | 1:afb820c6fc0d | 146 | } |
CasperK | 1:afb820c6fc0d | 147 | |
CasperK | 2:3f67b4833256 | 148 | void emg0Calibration() { |
CasperK | 2:3f67b4833256 | 149 | int C = 500; // half a second at 1000Hz |
CasperK | 2:3f67b4833256 | 150 | double A0=0, A1=0, A2=0, A3=0, A4=0; |
CasperK | 2:3f67b4833256 | 151 | double emg0FiAbs; |
CasperK | 2:3f67b4833256 | 152 | while (C > 0){ |
CasperK | 2:3f67b4833256 | 153 | emg0FiAbs = fabs( emg1bqc.step(emg0.read())); |
CasperK | 2:3f67b4833256 | 154 | if (C==500){ //first instance make all values the first in case this is the highest |
CasperK | 2:3f67b4833256 | 155 | A0=A1=A2=A3=A4=emg0FiAbs; |
CasperK | 2:3f67b4833256 | 156 | } |
CasperK | 2:3f67b4833256 | 157 | else if(emg0FiAbs > A0){ // if there is a higher value change the inputs to be the highest 5 |
CasperK | 2:3f67b4833256 | 158 | A4=A3; |
CasperK | 2:3f67b4833256 | 159 | A3=A2; |
CasperK | 2:3f67b4833256 | 160 | A2=A1; |
CasperK | 2:3f67b4833256 | 161 | A1=A0; |
CasperK | 2:3f67b4833256 | 162 | A0=emg0FiAbs; |
CasperK | 2:3f67b4833256 | 163 | } |
CasperK | 2:3f67b4833256 | 164 | C--; |
CasperK | 2:3f67b4833256 | 165 | wait(0.001f); |
CasperK | 2:3f67b4833256 | 166 | threshold0 = (A0+A1+A2+A3+A4)/5*0.4; // average of the 5 highest values x 0,4 to create the threshold |
CasperK | 2:3f67b4833256 | 167 | } |
CasperK | 2:3f67b4833256 | 168 | |
CasperK | 2:3f67b4833256 | 169 | if (!next_switch) { |
CasperK | 1:afb820c6fc0d | 170 | CurrentState = Movement; |
CasperK | 1:afb820c6fc0d | 171 | pc.printf("current state = Movement\n\r"); |
CasperK | 1:afb820c6fc0d | 172 | } |
CasperK | 1:afb820c6fc0d | 173 | } |
CasperK | 1:afb820c6fc0d | 174 | |
CasperK | 2:3f67b4833256 | 175 | void emg1Calibration() { |
CasperK | 2:3f67b4833256 | 176 | |
CasperK | 2:3f67b4833256 | 177 | } |
CasperK | 2:3f67b4833256 | 178 | |
CasperK | 2:3f67b4833256 | 179 | void emg2Calibration() { |
CasperK | 2:3f67b4833256 | 180 | |
CasperK | 2:3f67b4833256 | 181 | } |
CasperK | 2:3f67b4833256 | 182 | |
CasperK | 1:afb820c6fc0d | 183 | void movement() { |
CasperK | 1:afb820c6fc0d | 184 | |
CasperK | 1:afb820c6fc0d | 185 | } |
CasperK | 1:afb820c6fc0d | 186 | |
CasperK | 1:afb820c6fc0d | 187 | void move_motors() { |
CasperK | 1:afb820c6fc0d | 188 | pwmpin1 = pwm_value1; |
CasperK | 1:afb820c6fc0d | 189 | pwmpin2 = pwm_value2; |
CasperK | 1:afb820c6fc0d | 190 | } |
CasperK | 0:1b2c842eca42 | 191 | |
CasperK | 0:1b2c842eca42 | 192 | int main() |
CasperK | 0:1b2c842eca42 | 193 | { |
CasperK | 1:afb820c6fc0d | 194 | pc.baud(115200); |
CasperK | 1:afb820c6fc0d | 195 | pc.printf(" ** program reset **\n\r"); |
CasperK | 1:afb820c6fc0d | 196 | pwmpin1.period_us(60); |
CasperK | 1:afb820c6fc0d | 197 | pwmpin2.period_us(60); |
CasperK | 1:afb820c6fc0d | 198 | directionpin1 = true; |
CasperK | 1:afb820c6fc0d | 199 | directionpin2 = true; |
CasperK | 1:afb820c6fc0d | 200 | |
CasperK | 2:3f67b4833256 | 201 | // emg filters |
CasperK | 2:3f67b4833256 | 202 | // combining biquad chains is done in main, before the ticker, so only once. |
CasperK | 2:3f67b4833256 | 203 | emg0bqc.add( &emg0bq1 ).add( &emg0bq2 ).add ( &emg0bq3 ); |
CasperK | 2:3f67b4833256 | 204 | emg1bqc.add( &emg1bq1 ).add( &emg1bq2 ).add ( &emg1bq3 ); |
CasperK | 2:3f67b4833256 | 205 | emg1bqc.add( &emg1bq1 ).add( &emg1bq2 ).add ( &emg1bq3 ); |
CasperK | 2:3f67b4833256 | 206 | |
CasperK | 2:3f67b4833256 | 207 | MotorsTicker.attach(&move_motors, 0.02f); //ticker at 50Hz |
CasperK | 2:3f67b4833256 | 208 | sample_timer.attach(&sample, 0.001); //ticker at 1000Hz |
CasperK | 2:3f67b4833256 | 209 | |
CasperK | 1:afb820c6fc0d | 210 | CurrentState = PositionCalibration; |
CasperK | 1:afb820c6fc0d | 211 | pc.printf("current state = PositionCalibration\n\r"); |
CasperK | 0:1b2c842eca42 | 212 | |
CasperK | 0:1b2c842eca42 | 213 | while (true) { |
CasperK | 1:afb820c6fc0d | 214 | switch(CurrentState) { |
CasperK | 0:1b2c842eca42 | 215 | case PositionCalibration: |
CasperK | 1:afb820c6fc0d | 216 | positionCalibration(); |
CasperK | 1:afb820c6fc0d | 217 | if (!kill_switch) { |
CasperK | 1:afb820c6fc0d | 218 | CurrentState = KILL; |
CasperK | 1:afb820c6fc0d | 219 | pc.printf("current state = KILL\n\r"); |
CasperK | 1:afb820c6fc0d | 220 | } |
CasperK | 1:afb820c6fc0d | 221 | break; |
CasperK | 1:afb820c6fc0d | 222 | |
CasperK | 0:1b2c842eca42 | 223 | case EmgCalibration: |
CasperK | 2:3f67b4833256 | 224 | emg0Calibration(); |
CasperK | 2:3f67b4833256 | 225 | emg1Calibration(); |
CasperK | 2:3f67b4833256 | 226 | emg2Calibration(); |
CasperK | 1:afb820c6fc0d | 227 | |
CasperK | 1:afb820c6fc0d | 228 | if (!kill_switch) { |
CasperK | 1:afb820c6fc0d | 229 | CurrentState = KILL; |
CasperK | 1:afb820c6fc0d | 230 | pc.printf("current state = KILL\n\r"); |
CasperK | 0:1b2c842eca42 | 231 | } |
CasperK | 1:afb820c6fc0d | 232 | break; |
CasperK | 0:1b2c842eca42 | 233 | |
CasperK | 0:1b2c842eca42 | 234 | case Movement: |
CasperK | 1:afb820c6fc0d | 235 | movement(); |
CasperK | 1:afb820c6fc0d | 236 | |
CasperK | 1:afb820c6fc0d | 237 | if (!kill_switch) { |
CasperK | 1:afb820c6fc0d | 238 | CurrentState = KILL; |
CasperK | 1:afb820c6fc0d | 239 | pc.printf("current state = KILL\n\r"); |
CasperK | 0:1b2c842eca42 | 240 | } |
CasperK | 1:afb820c6fc0d | 241 | break; |
CasperK | 0:1b2c842eca42 | 242 | |
CasperK | 0:1b2c842eca42 | 243 | case KILL: |
CasperK | 1:afb820c6fc0d | 244 | bool u = true; |
CasperK | 1:afb820c6fc0d | 245 | ledgreen = true; |
CasperK | 1:afb820c6fc0d | 246 | ledblue = true; |
CasperK | 1:afb820c6fc0d | 247 | ledred = false; |
CasperK | 2:3f67b4833256 | 248 | |
CasperK | 2:3f67b4833256 | 249 | pwm_value1 = 0; |
CasperK | 2:3f67b4833256 | 250 | pwm_value2 = 0; |
CasperK | 2:3f67b4833256 | 251 | |
CasperK | 2:3f67b4833256 | 252 | timer.start(); |
CasperK | 2:3f67b4833256 | 253 | if (timer.read_ms()> 2000) { |
CasperK | 2:3f67b4833256 | 254 | timer.stop(); |
CasperK | 2:3f67b4833256 | 255 | timer.reset(); |
CasperK | 2:3f67b4833256 | 256 | while(u) { |
CasperK | 2:3f67b4833256 | 257 | if (!kill_switch) { |
CasperK | 2:3f67b4833256 | 258 | timer.start(); |
CasperK | 2:3f67b4833256 | 259 | u = false; |
CasperK | 2:3f67b4833256 | 260 | ledred = true; |
CasperK | 2:3f67b4833256 | 261 | CurrentState = PositionCalibration; |
CasperK | 2:3f67b4833256 | 262 | pc.printf("current state = PositionCalibration\n\r"); |
CasperK | 2:3f67b4833256 | 263 | wait(1.0f); |
CasperK | 2:3f67b4833256 | 264 | } |
CasperK | 1:afb820c6fc0d | 265 | } |
CasperK | 0:1b2c842eca42 | 266 | } |
CasperK | 1:afb820c6fc0d | 267 | break; |
CasperK | 1:afb820c6fc0d | 268 | } |
CasperK | 1:afb820c6fc0d | 269 | wait(0.2f); |
CasperK | 0:1b2c842eca42 | 270 | } |
CasperK | 0:1b2c842eca42 | 271 | } |