Project BioRobotics Group 19
Dependencies: FastPWM HIDScope MODSERIAL QEI biquadFilter mbed
main.cpp@16:2cf8c2705936, 2017-11-02 (annotated)
- Committer:
- jordiluong
- Date:
- Thu Nov 02 13:47:48 2017 +0000
- Revision:
- 16:2cf8c2705936
- Parent:
- 15:5d24f832bb7b
- Child:
- 17:f8dd5b8e4b52
Direction switch working properly
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jordiluong | 0:80ac024b84cb | 1 | #include "BiQuad.h" |
jordiluong | 0:80ac024b84cb | 2 | #include "FastPWM.h" |
jordiluong | 0:80ac024b84cb | 3 | #include "HIDScope.h" |
jordiluong | 5:0d3e8694726e | 4 | #include <math.h> |
jordiluong | 0:80ac024b84cb | 5 | #include "mbed.h" |
jordiluong | 5:0d3e8694726e | 6 | #include "MODSERIAL.h" |
jordiluong | 0:80ac024b84cb | 7 | #include "QEI.h" |
jordiluong | 13:ec227b229f3d | 8 | |
jordiluong | 5:0d3e8694726e | 9 | const double pi = 3.1415926535897; // Definition of pi |
jordiluong | 14:95acac6a07c7 | 10 | |
jordiluong | 7:757e95b4dc46 | 11 | // SERIAL COMMUNICATION WITH PC //////////////////////////////////////////////// |
jordiluong | 0:80ac024b84cb | 12 | MODSERIAL pc(USBTX, USBRX); |
jordiluong | 12:12b72bd60fd1 | 13 | HIDScope scope(4); |
jordiluong | 13:ec227b229f3d | 14 | |
jordiluong | 7:757e95b4dc46 | 15 | // STATES ////////////////////////////////////////////////////////////////////// |
jordiluong | 14:95acac6a07c7 | 16 | enum states{MOTORS_OFF, CALIBRATING, MOVING, HITTING}; |
jordiluong | 0:80ac024b84cb | 17 | states currentState = MOTORS_OFF; // Start with motors off |
jordiluong | 0:80ac024b84cb | 18 | bool stateChanged = true; // Make sure the initialization of first state is executed |
jordiluong | 13:ec227b229f3d | 19 | |
jordiluong | 7:757e95b4dc46 | 20 | // ENCODER ///////////////////////////////////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 21 | QEI Encoder1(D10,D11,NC,32); // CONNECT ENC1A TO D10, ENC1B TO D11 |
jordiluong | 5:0d3e8694726e | 22 | QEI Encoder2(D12,D13,NC,32); // CONNECT ENC2A TO D12, ENC2B TO D13 |
jordiluong | 13:ec227b229f3d | 23 | |
jordiluong | 7:757e95b4dc46 | 24 | // PINS //////////////////////////////////////////////////////////////////////// |
jordiluong | 4:ea7689bf97e1 | 25 | DigitalOut motor1DirectionPin(D4); // Value 0: CCW; 1: CW |
jordiluong | 3:5c3edcd29448 | 26 | PwmOut motor1MagnitudePin(D5); |
jordiluong | 3:5c3edcd29448 | 27 | DigitalOut motor2DirectionPin(D7); // Value 0: CW or CCW?; 1: CW or CCW? |
jordiluong | 3:5c3edcd29448 | 28 | PwmOut motor2MagnitudePin(D6); |
jordiluong | 4:ea7689bf97e1 | 29 | InterruptIn button1(D2); // CONNECT BUT1 TO D2 |
jordiluong | 4:ea7689bf97e1 | 30 | InterruptIn button2(D3); // CONNECT BUT2 TO D3 |
jordiluong | 14:95acac6a07c7 | 31 | InterruptIn button3(SW2); |
jordiluong | 10:a9e344e440b8 | 32 | InterruptIn button4(SW3); |
jordiluong | 14:95acac6a07c7 | 33 | AnalogIn potmeter1(A0); // CONNECT POT1 TO A0 |
jordiluong | 14:95acac6a07c7 | 34 | AnalogIn potmeter2(A1); // CONNECT POT2 TO A1 |
jordiluong | 14:95acac6a07c7 | 35 | DigitalOut led1(LED_RED); |
jordiluong | 14:95acac6a07c7 | 36 | DigitalOut led2(LED_BLUE); |
jordiluong | 14:95acac6a07c7 | 37 | DigitalOut led3(LED_GREEN); |
jordiluong | 15:5d24f832bb7b | 38 | DigitalOut led4(D8); // CONNECT LED1 TO D8 |
jordiluong | 15:5d24f832bb7b | 39 | DigitalOut led5(D9); // CONNECT LED2 TO D9 |
jordiluong | 14:95acac6a07c7 | 40 | AnalogIn emg_r(A2); // CONNECT EMG TO A2 |
jordiluong | 14:95acac6a07c7 | 41 | AnalogIn emg_l(A3); // CONNECT EMG TO A3 |
jordiluong | 13:ec227b229f3d | 42 | |
jordiluong | 7:757e95b4dc46 | 43 | // MOTOR CONTROL /////////////////////////////////////////////////////////////// |
jordiluong | 14:95acac6a07c7 | 44 | Ticker controllerTicker; // Ticker for the controller |
jordiluong | 14:95acac6a07c7 | 45 | const double controller_Ts = 1/200.1; // Time step for controllerTicker [s] |
jordiluong | 5:0d3e8694726e | 46 | const double motorRatio = 131.25; // Ratio of the gearbox in the motors [] |
jordiluong | 7:757e95b4dc46 | 47 | const double radPerPulse = 2*pi/(32*motorRatio); // Amount of radians the motor rotates per encoder pulse [rad/pulse] |
jordiluong | 14:95acac6a07c7 | 48 | volatile double xVelocity = 0, yVelocity = 0; // X and Y velocities of the end effector at the start |
jordiluong | 16:2cf8c2705936 | 49 | const double velocity = 0.03; // X and Y velocity of the end effector when desired |
jordiluong | 13:ec227b229f3d | 50 | |
jordiluong | 7:757e95b4dc46 | 51 | // MOTOR 1 |
jordiluong | 14:95acac6a07c7 | 52 | volatile double position1; // Position of motor 1 [rad] |
jordiluong | 14:95acac6a07c7 | 53 | volatile double reference1 = 0; // Desired rotation of motor 1 [rad] |
jordiluong | 16:2cf8c2705936 | 54 | const double motor1Max = 0; // Maximum rotation of motor 1 [rad] |
jordiluong | 16:2cf8c2705936 | 55 | const double motor1Min = 2*pi*-40/360; // Minimum rotation of motor 1 [rad] |
jordiluong | 5:0d3e8694726e | 56 | // Controller gains |
jordiluong | 14:95acac6a07c7 | 57 | const double motor1_KP = 13; // Position gain [] |
jordiluong | 13:ec227b229f3d | 58 | const double motor1_KI = 7; // Integral gain [] |
jordiluong | 13:ec227b229f3d | 59 | const double motor1_KD = 0.3; // Derivative gain [] |
jordiluong | 5:0d3e8694726e | 60 | double motor1_err_int = 0, motor1_prev_err = 0; |
jordiluong | 5:0d3e8694726e | 61 | // Derivative filter coefficients |
jordiluong | 14:95acac6a07c7 | 62 | const double motor1_f_a1 = 0.25, motor1_f_a2 = 0.8; // Derivative filter coefficients [] |
jordiluong | 14:95acac6a07c7 | 63 | const double motor1_f_b0 = 1, motor1_f_b1 = 2, motor1_f_b2 = 0.8; // Derivative filter coefficients [] |
jordiluong | 5:0d3e8694726e | 64 | // Filter variables |
jordiluong | 5:0d3e8694726e | 65 | double motor1_f_v1 = 0, motor1_f_v2 = 0; |
jordiluong | 13:ec227b229f3d | 66 | |
jordiluong | 7:757e95b4dc46 | 67 | // MOTOR 2 |
jordiluong | 14:95acac6a07c7 | 68 | volatile double position2; // Position of motor 2 [rad] |
jordiluong | 14:95acac6a07c7 | 69 | volatile double reference2 = 0; // Desired rotation of motor 2 [rad] |
jordiluong | 16:2cf8c2705936 | 70 | const double motor2Max = 2*pi*25/360; // Maximum rotation of motor 2 [rad] |
jordiluong | 16:2cf8c2705936 | 71 | const double motor2Min = 2*pi*-28/360; // Minimum rotation of motor 2 [rad] |
jordiluong | 5:0d3e8694726e | 72 | // Controller gains |
jordiluong | 14:95acac6a07c7 | 73 | const double motor2_KP = 13; // Position gain [] |
jordiluong | 13:ec227b229f3d | 74 | const double motor2_KI = 5; // Integral gain [] |
jordiluong | 13:ec227b229f3d | 75 | const double motor2_KD = 0.1; // Derivative gain [] |
jordiluong | 10:a9e344e440b8 | 76 | double motor2_err_int = 0, motor2_prev_err = 0; |
jordiluong | 5:0d3e8694726e | 77 | // Derivative filter coefficients |
jordiluong | 14:95acac6a07c7 | 78 | const double motor2_f_a1 = 0.25, motor2_f_a2 = 0.8; // Derivative filter coefficients [] |
jordiluong | 14:95acac6a07c7 | 79 | const double motor2_f_b0 = 1, motor2_f_b1 = 2, motor2_f_b2 = 0.8; // Derivative filter coefficients [] |
jordiluong | 5:0d3e8694726e | 80 | // Filter variables |
jordiluong | 10:a9e344e440b8 | 81 | double motor2_f_v1 = 0, motor2_f_v2 = 0; |
jordiluong | 13:ec227b229f3d | 82 | |
jordiluong | 14:95acac6a07c7 | 83 | // EMG ////////////////////////////////////////////////////////////////// |
jordiluong | 14:95acac6a07c7 | 84 | Ticker emgLeft; |
jordiluong | 14:95acac6a07c7 | 85 | Ticker emgRight; |
jordiluong | 16:2cf8c2705936 | 86 | const double emgTs = 0.5; |
jordiluong | 14:95acac6a07c7 | 87 | // Filters |
jordiluong | 14:95acac6a07c7 | 88 | BiQuadChain bqc; |
jordiluong | 14:95acac6a07c7 | 89 | BiQuad bq2_high(0.875182, -1.750364, 0.87518, -1.73472, 0.766004); |
jordiluong | 14:95acac6a07c7 | 90 | BiQuad bq3_notch(-1.1978e-16, 0.9561, 0.9780, -1.1978e-16, 0.9780); |
jordiluong | 14:95acac6a07c7 | 91 | BiQuad bq1_low(3.65747e-2, 7.31495e-2, 3.65747e-2, -1.390892, 0.537191); |
jordiluong | 14:95acac6a07c7 | 92 | // Right arm |
jordiluong | 14:95acac6a07c7 | 93 | volatile double emgFiltered_r; |
jordiluong | 14:95acac6a07c7 | 94 | volatile double filteredAbs_r; |
jordiluong | 14:95acac6a07c7 | 95 | volatile double emg_value_r; |
jordiluong | 14:95acac6a07c7 | 96 | volatile double onoffsignal_r; |
jordiluong | 14:95acac6a07c7 | 97 | volatile bool check_calibration_r=0; |
jordiluong | 14:95acac6a07c7 | 98 | volatile double avg_emg_r; |
jordiluong | 14:95acac6a07c7 | 99 | volatile bool active_r = false; |
jordiluong | 14:95acac6a07c7 | 100 | // Left arm |
jordiluong | 14:95acac6a07c7 | 101 | volatile double emgFiltered_l; |
jordiluong | 14:95acac6a07c7 | 102 | volatile double filteredAbs_l; |
jordiluong | 14:95acac6a07c7 | 103 | volatile double emg_value_l; |
jordiluong | 14:95acac6a07c7 | 104 | volatile double onoffsignal_l; |
jordiluong | 14:95acac6a07c7 | 105 | volatile bool check_calibration_l=0; |
jordiluong | 14:95acac6a07c7 | 106 | volatile double avg_emg_l; |
jordiluong | 14:95acac6a07c7 | 107 | volatile bool active_l = false; |
jordiluong | 13:ec227b229f3d | 108 | |
jordiluong | 14:95acac6a07c7 | 109 | Ticker sampleTicker; |
jordiluong | 14:95acac6a07c7 | 110 | const double sampleTs = 0.05; |
jordiluong | 15:5d24f832bb7b | 111 | |
jordiluong | 15:5d24f832bb7b | 112 | volatile bool xdir = true, ydir = false; |
jordiluong | 15:5d24f832bb7b | 113 | volatile bool timer = false; |
jordiluong | 16:2cf8c2705936 | 114 | volatile int count = 0; |
jordiluong | 13:ec227b229f3d | 115 | |
jordiluong | 7:757e95b4dc46 | 116 | // FUNCTIONS /////////////////////////////////////////////////////////////////// |
jordiluong | 7:757e95b4dc46 | 117 | // BIQUAD FILTER FOR DERIVATIVE OF ERROR /////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 118 | double biquad(double u, double &v1, double &v2, const double a1, |
jordiluong | 5:0d3e8694726e | 119 | const double a2, const double b0, const double b1, const double b2) |
jordiluong | 0:80ac024b84cb | 120 | { |
jordiluong | 5:0d3e8694726e | 121 | double v = u - a1*v1 - a2*v2; |
jordiluong | 5:0d3e8694726e | 122 | double y = b0*v + b1*v1 + b2*v2; |
jordiluong | 5:0d3e8694726e | 123 | v2 = v1; v1 = v; |
jordiluong | 5:0d3e8694726e | 124 | return y; |
jordiluong | 0:80ac024b84cb | 125 | } |
jordiluong | 13:ec227b229f3d | 126 | |
jordiluong | 7:757e95b4dc46 | 127 | // PID-CONTROLLER WITH FILTER ////////////////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 128 | double PID_Controller(double e, const double Kp, const double Ki, |
jordiluong | 5:0d3e8694726e | 129 | const double Kd, double Ts, double &e_int, double &e_prev, double &f_v1, |
jordiluong | 5:0d3e8694726e | 130 | double &f_v2, const double f_a1, const double f_a2, const double f_b0, |
jordiluong | 5:0d3e8694726e | 131 | const double f_b1, const double f_b2) |
jordiluong | 0:80ac024b84cb | 132 | { |
jordiluong | 5:0d3e8694726e | 133 | // Derivative |
jordiluong | 8:78d8ccf84a38 | 134 | double e_der = (e - e_prev)/Ts; // Calculate the derivative of error |
jordiluong | 12:12b72bd60fd1 | 135 | e_der = biquad(e_der, f_v1, f_v2, f_a1, f_a2, f_b0, f_b1, f_b2); // Filter the derivative of error |
jordiluong | 12:12b72bd60fd1 | 136 | //e_der = bq1.step(e_der); |
jordiluong | 5:0d3e8694726e | 137 | e_prev = e; |
jordiluong | 5:0d3e8694726e | 138 | // Integral |
jordiluong | 8:78d8ccf84a38 | 139 | e_int = e_int + Ts*e; // Calculate the integral of error |
jordiluong | 5:0d3e8694726e | 140 | // PID |
jordiluong | 12:12b72bd60fd1 | 141 | //pc.printf("%f --> %f \r\n", e_der, e_derf); |
jordiluong | 11:5c06c97c3673 | 142 | return Kp*e + Ki*e_int + Kd*e_der; |
jordiluong | 3:5c3edcd29448 | 143 | } |
jordiluong | 13:ec227b229f3d | 144 | |
jordiluong | 7:757e95b4dc46 | 145 | // MOTOR 1 ///////////////////////////////////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 146 | void RotateMotor1(double motor1Value) |
jordiluong | 3:5c3edcd29448 | 147 | { |
jordiluong | 10:a9e344e440b8 | 148 | if(currentState == MOVING || currentState == HITTING) // Check if state is MOVING |
jordiluong | 5:0d3e8694726e | 149 | { |
jordiluong | 10:a9e344e440b8 | 150 | if(motor1Value >= 0) motor1DirectionPin = 0; // Rotate motor 1 CW |
jordiluong | 10:a9e344e440b8 | 151 | else motor1DirectionPin = 1; // Rotate motor 1 CCW |
jordiluong | 5:0d3e8694726e | 152 | |
jordiluong | 5:0d3e8694726e | 153 | if(fabs(motor1Value) > 1) motor1MagnitudePin = 1; |
jordiluong | 5:0d3e8694726e | 154 | else motor1MagnitudePin = fabs(motor1Value); |
jordiluong | 5:0d3e8694726e | 155 | } |
jordiluong | 5:0d3e8694726e | 156 | else motor1MagnitudePin = 0; |
jordiluong | 3:5c3edcd29448 | 157 | } |
jordiluong | 13:ec227b229f3d | 158 | |
jordiluong | 10:a9e344e440b8 | 159 | // MOTOR 2 ///////////////////////////////////////////////////////////////////// |
jordiluong | 10:a9e344e440b8 | 160 | void RotateMotor2(double motor2Value) |
jordiluong | 10:a9e344e440b8 | 161 | { |
jordiluong | 10:a9e344e440b8 | 162 | if(currentState == MOVING || currentState == HITTING) // Check if state is MOVING |
jordiluong | 10:a9e344e440b8 | 163 | { |
jordiluong | 10:a9e344e440b8 | 164 | if(motor2Value >= 0) motor2DirectionPin = 1; // Rotate motor 1 CW |
jordiluong | 10:a9e344e440b8 | 165 | else motor2DirectionPin = 0; // Rotate motor 1 CCW |
jordiluong | 10:a9e344e440b8 | 166 | |
jordiluong | 10:a9e344e440b8 | 167 | if(fabs(motor2Value) > 1) motor2MagnitudePin = 1; |
jordiluong | 10:a9e344e440b8 | 168 | else motor2MagnitudePin = fabs(motor2Value); |
jordiluong | 10:a9e344e440b8 | 169 | } |
jordiluong | 10:a9e344e440b8 | 170 | else motor2MagnitudePin = 0; |
jordiluong | 10:a9e344e440b8 | 171 | } |
jordiluong | 13:ec227b229f3d | 172 | |
jordiluong | 7:757e95b4dc46 | 173 | // MOTOR 1 PID-CONTROLLER ////////////////////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 174 | void Motor1Controller() |
jordiluong | 5:0d3e8694726e | 175 | { |
jordiluong | 14:95acac6a07c7 | 176 | if(currentState == MOVING) |
jordiluong | 14:95acac6a07c7 | 177 | { |
jordiluong | 14:95acac6a07c7 | 178 | position1 = radPerPulse * Encoder1.getPulses(); |
jordiluong | 14:95acac6a07c7 | 179 | position2 = radPerPulse * Encoder2.getPulses(); |
jordiluong | 14:95acac6a07c7 | 180 | //pc.printf("error %f \r\n", reference1 - position1); |
jordiluong | 14:95acac6a07c7 | 181 | double motor1Value = PID_Controller(reference1 - position1, motor1_KP, |
jordiluong | 14:95acac6a07c7 | 182 | motor1_KI, motor1_KD, controller_Ts, motor1_err_int, motor1_prev_err, |
jordiluong | 14:95acac6a07c7 | 183 | motor1_f_v1, motor1_f_v2, motor1_f_a1, motor1_f_a2, motor1_f_b0, |
jordiluong | 14:95acac6a07c7 | 184 | motor1_f_b1, motor1_f_b2); |
jordiluong | 14:95acac6a07c7 | 185 | //pc.printf("motor value %f \r\n",motor1Value); |
jordiluong | 14:95acac6a07c7 | 186 | |
jordiluong | 14:95acac6a07c7 | 187 | double motor2Value = PID_Controller(reference2 - position2, motor2_KP, |
jordiluong | 14:95acac6a07c7 | 188 | motor2_KI, motor2_KD, controller_Ts, motor2_err_int, motor2_prev_err, |
jordiluong | 14:95acac6a07c7 | 189 | motor2_f_v1, motor2_f_v2, motor2_f_a1, motor2_f_a2, motor2_f_b0, |
jordiluong | 14:95acac6a07c7 | 190 | motor2_f_b1, motor2_f_b2); |
jordiluong | 14:95acac6a07c7 | 191 | |
jordiluong | 14:95acac6a07c7 | 192 | //pc.printf("%f, %f \r\n", motor1Value, motor2Value); |
jordiluong | 14:95acac6a07c7 | 193 | |
jordiluong | 14:95acac6a07c7 | 194 | RotateMotor1(motor1Value); |
jordiluong | 14:95acac6a07c7 | 195 | RotateMotor2(motor2Value); |
jordiluong | 14:95acac6a07c7 | 196 | } |
jordiluong | 10:a9e344e440b8 | 197 | } |
jordiluong | 13:ec227b229f3d | 198 | |
jordiluong | 12:12b72bd60fd1 | 199 | // MOTOR 2 PID-CONTROLLER ////////////////////////////////////////////////////// |
jordiluong | 12:12b72bd60fd1 | 200 | /*void Motor2Controller() |
jordiluong | 12:12b72bd60fd1 | 201 | { |
jordiluong | 12:12b72bd60fd1 | 202 | position2 = radPerPulse * Encoder2.getPulses(); |
jordiluong | 12:12b72bd60fd1 | 203 | double motor2Value = PID_Controller(reference2 - position2, motor2_KP, |
jordiluong | 12:12b72bd60fd1 | 204 | motor2_KI, motor2_KD, controller2_Ts, motor2_err_int, motor2_prev_err, |
jordiluong | 12:12b72bd60fd1 | 205 | motor2_f_v1, motor2_f_v2, motor2_f_a1, motor2_f_a2, motor2_f_b0, |
jordiluong | 12:12b72bd60fd1 | 206 | motor2_f_b1, motor2_f_b2); |
jordiluong | 12:12b72bd60fd1 | 207 | RotateMotor2(motor2Value); |
jordiluong | 12:12b72bd60fd1 | 208 | } |
jordiluong | 12:12b72bd60fd1 | 209 | */ |
jordiluong | 7:757e95b4dc46 | 210 | // TURN OFF MOTORS ///////////////////////////////////////////////////////////// |
jordiluong | 5:0d3e8694726e | 211 | void TurnMotorsOff() |
jordiluong | 5:0d3e8694726e | 212 | { |
jordiluong | 5:0d3e8694726e | 213 | motor1MagnitudePin = 0; |
jordiluong | 5:0d3e8694726e | 214 | motor2MagnitudePin = 0; |
jordiluong | 5:0d3e8694726e | 215 | } |
jordiluong | 13:ec227b229f3d | 216 | |
jordiluong | 14:95acac6a07c7 | 217 | |
jordiluong | 14:95acac6a07c7 | 218 | // EMG ///////////////////////////////////////////////////////////////////////// |
jordiluong | 14:95acac6a07c7 | 219 | // Filter EMG signal of right arm |
jordiluong | 13:ec227b229f3d | 220 | |
jordiluong | 14:95acac6a07c7 | 221 | void filter_r(){ |
jordiluong | 14:95acac6a07c7 | 222 | if(check_calibration_r==1){ |
jordiluong | 14:95acac6a07c7 | 223 | emg_value_r = emg_r.read(); |
jordiluong | 14:95acac6a07c7 | 224 | emgFiltered_r = bqc.step( emg_value_r ); |
jordiluong | 14:95acac6a07c7 | 225 | filteredAbs_r = abs( emgFiltered_r ); |
jordiluong | 14:95acac6a07c7 | 226 | if (avg_emg_r != 0){ |
jordiluong | 14:95acac6a07c7 | 227 | onoffsignal_r=filteredAbs_r/avg_emg_r; //divide the emg_r signal by the max emg_r to calibrate the signal per person |
jordiluong | 14:95acac6a07c7 | 228 | } |
jordiluong | 14:95acac6a07c7 | 229 | } |
jordiluong | 14:95acac6a07c7 | 230 | } |
jordiluong | 14:95acac6a07c7 | 231 | |
jordiluong | 14:95acac6a07c7 | 232 | // Filter EMG signal of left arm |
jordiluong | 14:95acac6a07c7 | 233 | void filter_l(){ |
jordiluong | 14:95acac6a07c7 | 234 | if(check_calibration_l==1){ |
jordiluong | 14:95acac6a07c7 | 235 | emg_value_l = emg_l.read(); |
jordiluong | 14:95acac6a07c7 | 236 | emgFiltered_l = bqc.step( emg_value_l ); |
jordiluong | 14:95acac6a07c7 | 237 | filteredAbs_l = abs( emgFiltered_l ); |
jordiluong | 14:95acac6a07c7 | 238 | if (avg_emg_l != 0){ |
jordiluong | 14:95acac6a07c7 | 239 | onoffsignal_l=filteredAbs_l/avg_emg_l; //divide the emg_r signal by the avg_emg_l wat staat voor avg emg in gespannen toestand |
jordiluong | 14:95acac6a07c7 | 240 | } |
jordiluong | 10:a9e344e440b8 | 241 | } |
jordiluong | 14:95acac6a07c7 | 242 | } |
jordiluong | 14:95acac6a07c7 | 243 | |
jordiluong | 14:95acac6a07c7 | 244 | // Check threshold right arm |
jordiluong | 14:95acac6a07c7 | 245 | void check_emg_r(){ |
jordiluong | 14:95acac6a07c7 | 246 | double filteredAbs_temp_r; |
jordiluong | 14:95acac6a07c7 | 247 | |
jordiluong | 14:95acac6a07c7 | 248 | if((check_calibration_l==1) &&(check_calibration_r==1)){ |
jordiluong | 14:95acac6a07c7 | 249 | for( int i = 0; i<250;i++){ |
jordiluong | 14:95acac6a07c7 | 250 | filter_r(); |
jordiluong | 14:95acac6a07c7 | 251 | filteredAbs_temp_r = filteredAbs_temp_r + onoffsignal_r; |
jordiluong | 14:95acac6a07c7 | 252 | wait(0.0004); // 0.0004 |
jordiluong | 14:95acac6a07c7 | 253 | } |
jordiluong | 14:95acac6a07c7 | 254 | filteredAbs_temp_r = filteredAbs_temp_r/250; |
jordiluong | 14:95acac6a07c7 | 255 | if(filteredAbs_temp_r<=0.3){ //if signal is lower then 0.5 the blue light goes on |
jordiluong | 14:95acac6a07c7 | 256 | led1.write(1); //led 1 is rood en uit |
jordiluong | 14:95acac6a07c7 | 257 | |
jordiluong | 14:95acac6a07c7 | 258 | active_r = false; |
jordiluong | 14:95acac6a07c7 | 259 | } |
jordiluong | 14:95acac6a07c7 | 260 | else if(filteredAbs_temp_r > 0.3){ //if signal does not pass threshold value, blue light goes on |
jordiluong | 14:95acac6a07c7 | 261 | led1.write(0); |
jordiluong | 14:95acac6a07c7 | 262 | active_r = true; |
jordiluong | 14:95acac6a07c7 | 263 | } |
jordiluong | 10:a9e344e440b8 | 264 | } |
jordiluong | 14:95acac6a07c7 | 265 | } |
jordiluong | 14:95acac6a07c7 | 266 | // Check threshold left arm |
jordiluong | 14:95acac6a07c7 | 267 | void check_emg_l(){ |
jordiluong | 14:95acac6a07c7 | 268 | double filteredAbs_temp_l; |
jordiluong | 14:95acac6a07c7 | 269 | |
jordiluong | 14:95acac6a07c7 | 270 | if((check_calibration_l)==1 &&(check_calibration_r==1) ){ |
jordiluong | 14:95acac6a07c7 | 271 | for( int i = 0; i<250;i++){ |
jordiluong | 14:95acac6a07c7 | 272 | filter_l(); |
jordiluong | 14:95acac6a07c7 | 273 | filteredAbs_temp_l = filteredAbs_temp_l + onoffsignal_l; |
jordiluong | 14:95acac6a07c7 | 274 | wait(0.0004); // 0.0004 |
jordiluong | 14:95acac6a07c7 | 275 | } |
jordiluong | 14:95acac6a07c7 | 276 | filteredAbs_temp_l = filteredAbs_temp_l/250; |
jordiluong | 14:95acac6a07c7 | 277 | if(filteredAbs_temp_l<=0.3){ //if signal is lower then 0.5 the blue light goes on |
jordiluong | 14:95acac6a07c7 | 278 | // led1.write(1); //led 1 is rood en uit |
jordiluong | 14:95acac6a07c7 | 279 | led2.write(1); //led 2 is blauw en aan |
jordiluong | 14:95acac6a07c7 | 280 | active_l = false; |
jordiluong | 14:95acac6a07c7 | 281 | } |
jordiluong | 14:95acac6a07c7 | 282 | else if(filteredAbs_temp_l > 0.3){ //if signal does not pass threshold value, blue light goes on |
jordiluong | 14:95acac6a07c7 | 283 | // led1.write(0); |
jordiluong | 14:95acac6a07c7 | 284 | led2.write(0); |
jordiluong | 14:95acac6a07c7 | 285 | active_l = true; |
jordiluong | 14:95acac6a07c7 | 286 | } |
jordiluong | 14:95acac6a07c7 | 287 | } |
jordiluong | 14:95acac6a07c7 | 288 | |
jordiluong | 10:a9e344e440b8 | 289 | } |
jordiluong | 13:ec227b229f3d | 290 | |
jordiluong | 14:95acac6a07c7 | 291 | // Calibrate right arm |
jordiluong | 14:95acac6a07c7 | 292 | int calibration_r(){ |
jordiluong | 14:95acac6a07c7 | 293 | led3.write(0); |
jordiluong | 14:95acac6a07c7 | 294 | |
jordiluong | 14:95acac6a07c7 | 295 | double signal_verzameling_r = 0; |
jordiluong | 14:95acac6a07c7 | 296 | for(int n =0; n<5000;n++){ |
jordiluong | 14:95acac6a07c7 | 297 | filter_r(); |
jordiluong | 14:95acac6a07c7 | 298 | //read for 5000 samples as calibration |
jordiluong | 14:95acac6a07c7 | 299 | emg_value_r = emg_r.read(); |
jordiluong | 14:95acac6a07c7 | 300 | emgFiltered_r = bqc.step( emg_value_r ); |
jordiluong | 14:95acac6a07c7 | 301 | filteredAbs_r = abs(emgFiltered_r); |
jordiluong | 14:95acac6a07c7 | 302 | |
jordiluong | 14:95acac6a07c7 | 303 | |
jordiluong | 14:95acac6a07c7 | 304 | // signal_verzameling[n]= filteredAbs_r; |
jordiluong | 14:95acac6a07c7 | 305 | signal_verzameling_r = signal_verzameling_r + filteredAbs_r ; |
jordiluong | 14:95acac6a07c7 | 306 | wait(0.0004); |
jordiluong | 14:95acac6a07c7 | 307 | |
jordiluong | 14:95acac6a07c7 | 308 | if (n == 4999){ |
jordiluong | 14:95acac6a07c7 | 309 | avg_emg_r = signal_verzameling_r / n; |
jordiluong | 14:95acac6a07c7 | 310 | |
jordiluong | 14:95acac6a07c7 | 311 | } |
jordiluong | 14:95acac6a07c7 | 312 | } |
jordiluong | 14:95acac6a07c7 | 313 | |
jordiluong | 14:95acac6a07c7 | 314 | led3.write(1); |
jordiluong | 14:95acac6a07c7 | 315 | //pc.printf("calibratie rechts compleet\n\r"); |
jordiluong | 14:95acac6a07c7 | 316 | |
jordiluong | 14:95acac6a07c7 | 317 | check_calibration_r=1; |
jordiluong | 14:95acac6a07c7 | 318 | return 0; |
jordiluong | 14:95acac6a07c7 | 319 | } |
jordiluong | 14:95acac6a07c7 | 320 | |
jordiluong | 14:95acac6a07c7 | 321 | // Calibrate left arm |
jordiluong | 14:95acac6a07c7 | 322 | int calibration_l(){ |
jordiluong | 14:95acac6a07c7 | 323 | led3.write(0); |
jordiluong | 14:95acac6a07c7 | 324 | |
jordiluong | 14:95acac6a07c7 | 325 | double signal_verzameling_l= 0; |
jordiluong | 14:95acac6a07c7 | 326 | for(int n =0; n<5000;n++){ |
jordiluong | 14:95acac6a07c7 | 327 | filter_l(); |
jordiluong | 14:95acac6a07c7 | 328 | //read for 5000 samples as calibration |
jordiluong | 14:95acac6a07c7 | 329 | emg_value_l = emg_l.read(); |
jordiluong | 14:95acac6a07c7 | 330 | emgFiltered_l = bqc.step( emg_value_l ); |
jordiluong | 14:95acac6a07c7 | 331 | filteredAbs_l = abs(emgFiltered_l); |
jordiluong | 14:95acac6a07c7 | 332 | |
jordiluong | 14:95acac6a07c7 | 333 | |
jordiluong | 14:95acac6a07c7 | 334 | // signal_verzameling[n]= filteredAbs_r; |
jordiluong | 14:95acac6a07c7 | 335 | signal_verzameling_l = signal_verzameling_l + filteredAbs_l ; |
jordiluong | 14:95acac6a07c7 | 336 | wait(0.0004); |
jordiluong | 14:95acac6a07c7 | 337 | |
jordiluong | 14:95acac6a07c7 | 338 | if (n == 4999){ |
jordiluong | 14:95acac6a07c7 | 339 | avg_emg_l = signal_verzameling_l / n; |
jordiluong | 14:95acac6a07c7 | 340 | |
jordiluong | 14:95acac6a07c7 | 341 | } |
jordiluong | 14:95acac6a07c7 | 342 | } |
jordiluong | 14:95acac6a07c7 | 343 | led3.write(1); |
jordiluong | 14:95acac6a07c7 | 344 | wait(1); |
jordiluong | 14:95acac6a07c7 | 345 | check_calibration_l=1; |
jordiluong | 14:95acac6a07c7 | 346 | |
jordiluong | 14:95acac6a07c7 | 347 | //pc.printf("calibratie links compleet\n\r"); |
jordiluong | 14:95acac6a07c7 | 348 | // } |
jordiluong | 14:95acac6a07c7 | 349 | return 0; |
jordiluong | 14:95acac6a07c7 | 350 | } |
jordiluong | 14:95acac6a07c7 | 351 | |
jordiluong | 14:95acac6a07c7 | 352 | // DETERMINE JOINT VELOCITIES ////////////////////////////////////////////////// |
jordiluong | 14:95acac6a07c7 | 353 | void JointVelocities() |
jordiluong | 10:a9e344e440b8 | 354 | { |
jordiluong | 10:a9e344e440b8 | 355 | if(currentState == MOVING) |
jordiluong | 10:a9e344e440b8 | 356 | { |
jordiluong | 14:95acac6a07c7 | 357 | position1 = radPerPulse * Encoder1.getPulses(); |
jordiluong | 14:95acac6a07c7 | 358 | position2 = radPerPulse * Encoder2.getPulses(); |
jordiluong | 14:95acac6a07c7 | 359 | |
jordiluong | 16:2cf8c2705936 | 360 | if(active_l && active_r) |
jordiluong | 16:2cf8c2705936 | 361 | { |
jordiluong | 16:2cf8c2705936 | 362 | count += 1; |
jordiluong | 16:2cf8c2705936 | 363 | if(count == 40) |
jordiluong | 16:2cf8c2705936 | 364 | { |
jordiluong | 16:2cf8c2705936 | 365 | active_l = false; |
jordiluong | 16:2cf8c2705936 | 366 | active_r = false; |
jordiluong | 16:2cf8c2705936 | 367 | xdir = !xdir; |
jordiluong | 16:2cf8c2705936 | 368 | ydir = !ydir; |
jordiluong | 16:2cf8c2705936 | 369 | led4 = !led4; |
jordiluong | 16:2cf8c2705936 | 370 | led5 = !led5; |
jordiluong | 16:2cf8c2705936 | 371 | xVelocity = 0; |
jordiluong | 16:2cf8c2705936 | 372 | yVelocity = 0; |
jordiluong | 16:2cf8c2705936 | 373 | } |
jordiluong | 16:2cf8c2705936 | 374 | } |
jordiluong | 16:2cf8c2705936 | 375 | else count = 0; |
jordiluong | 16:2cf8c2705936 | 376 | |
jordiluong | 15:5d24f832bb7b | 377 | if(xdir) |
jordiluong | 14:95acac6a07c7 | 378 | { |
jordiluong | 16:2cf8c2705936 | 379 | if(active_r && count == 0 && reference1 > motor1Min && reference2 < motor2Max) |
jordiluong | 15:5d24f832bb7b | 380 | { |
jordiluong | 15:5d24f832bb7b | 381 | xVelocity = velocity; |
jordiluong | 15:5d24f832bb7b | 382 | pc.printf("x positive \r\n"); |
jordiluong | 15:5d24f832bb7b | 383 | } |
jordiluong | 16:2cf8c2705936 | 384 | else if(active_l && count == 0 && reference1 < motor1Max && reference2 > motor2Min) |
jordiluong | 15:5d24f832bb7b | 385 | { |
jordiluong | 15:5d24f832bb7b | 386 | xVelocity = -velocity; |
jordiluong | 15:5d24f832bb7b | 387 | pc.printf("x negative \r\n"); |
jordiluong | 15:5d24f832bb7b | 388 | } |
jordiluong | 15:5d24f832bb7b | 389 | else xVelocity = 0; |
jordiluong | 14:95acac6a07c7 | 390 | } |
jordiluong | 15:5d24f832bb7b | 391 | else if(ydir) |
jordiluong | 14:95acac6a07c7 | 392 | { |
jordiluong | 16:2cf8c2705936 | 393 | if(active_r && count == 0 && reference2 < motor2Max )//&& reference1 > motor2Min) |
jordiluong | 15:5d24f832bb7b | 394 | { |
jordiluong | 15:5d24f832bb7b | 395 | yVelocity = velocity; |
jordiluong | 15:5d24f832bb7b | 396 | pc.printf("y positive \r\n"); |
jordiluong | 15:5d24f832bb7b | 397 | } |
jordiluong | 16:2cf8c2705936 | 398 | else if(active_l && count == 0 && reference2 > motor2Min )//&& reference1 > motor2Min) |
jordiluong | 15:5d24f832bb7b | 399 | { |
jordiluong | 15:5d24f832bb7b | 400 | yVelocity = -velocity; |
jordiluong | 15:5d24f832bb7b | 401 | pc.printf("y negative \r\n"); |
jordiluong | 15:5d24f832bb7b | 402 | } |
jordiluong | 15:5d24f832bb7b | 403 | else yVelocity = 0; |
jordiluong | 14:95acac6a07c7 | 404 | } |
jordiluong | 14:95acac6a07c7 | 405 | |
jordiluong | 14:95acac6a07c7 | 406 | //pc.printf("x %f, y %f \r\n", xVelocity, yVelocity); |
jordiluong | 14:95acac6a07c7 | 407 | |
jordiluong | 14:95acac6a07c7 | 408 | // Construct Jacobian |
jordiluong | 14:95acac6a07c7 | 409 | double q[4]; |
jordiluong | 14:95acac6a07c7 | 410 | q[0] = position1, q[1] = -position1; |
jordiluong | 14:95acac6a07c7 | 411 | q[2] = position2, q[3] = -position2; |
jordiluong | 14:95acac6a07c7 | 412 | |
jordiluong | 14:95acac6a07c7 | 413 | double T2[3]; // Second column of the jacobian |
jordiluong | 14:95acac6a07c7 | 414 | double T3[3]; // Third column of the jacobian |
jordiluong | 14:95acac6a07c7 | 415 | double T4[3]; // Fourth column of the jacobian |
jordiluong | 14:95acac6a07c7 | 416 | double T1[6]; |
jordiluong | 14:95acac6a07c7 | 417 | static const signed char b_T1[3] = { 1, 0, 0 }; |
jordiluong | 14:95acac6a07c7 | 418 | double J_data[6]; |
jordiluong | 14:95acac6a07c7 | 419 | |
jordiluong | 14:95acac6a07c7 | 420 | T2[0] = 1.0; |
jordiluong | 14:95acac6a07c7 | 421 | T2[1] = 0.365 * cos(q[0]); |
jordiluong | 14:95acac6a07c7 | 422 | T2[2] = 0.365 * sin(q[0]); |
jordiluong | 14:95acac6a07c7 | 423 | T3[0] = 1.0; |
jordiluong | 14:95acac6a07c7 | 424 | T3[1] = 0.365 * cos(q[0]) + 0.2353720459187964 * sin((0.21406068356382149 + |
jordiluong | 14:95acac6a07c7 | 425 | q[0]) + q[1]); |
jordiluong | 14:95acac6a07c7 | 426 | T3[2] = 0.365 * sin(q[0]) - 0.2353720459187964 * cos((0.21406068356382149 + |
jordiluong | 14:95acac6a07c7 | 427 | q[0]) + q[1]); |
jordiluong | 14:95acac6a07c7 | 428 | T4[0] = 1.0; |
jordiluong | 14:95acac6a07c7 | 429 | T4[1] = (0.365 * cos(q[0]) + 0.2353720459187964 * sin((0.21406068356382149 + |
jordiluong | 14:95acac6a07c7 | 430 | q[0]) + q[1])) + 0.265 * sin((q[0] + q[1]) + q[2]); |
jordiluong | 14:95acac6a07c7 | 431 | T4[2] = (0.365 * sin(q[0]) - 0.2353720459187964 * cos((0.21406068356382149 + |
jordiluong | 14:95acac6a07c7 | 432 | q[0]) + q[1])) - 0.265 * cos((q[0] + q[1]) + q[2]); |
jordiluong | 14:95acac6a07c7 | 433 | |
jordiluong | 14:95acac6a07c7 | 434 | for (int i = 0; i < 3; i++) |
jordiluong | 14:95acac6a07c7 | 435 | { |
jordiluong | 14:95acac6a07c7 | 436 | T1[i] = (double)b_T1[i] - T2[i]; |
jordiluong | 14:95acac6a07c7 | 437 | T1[3 + i] = T3[i] - T4[i]; |
jordiluong | 14:95acac6a07c7 | 438 | } |
jordiluong | 14:95acac6a07c7 | 439 | |
jordiluong | 14:95acac6a07c7 | 440 | for (int i = 0; i < 2; i++) |
jordiluong | 14:95acac6a07c7 | 441 | { |
jordiluong | 14:95acac6a07c7 | 442 | for (int j = 0; j < 3; j++) |
jordiluong | 14:95acac6a07c7 | 443 | { |
jordiluong | 14:95acac6a07c7 | 444 | J_data[j + 3 * i] = T1[j + 3 * i]; |
jordiluong | 14:95acac6a07c7 | 445 | } |
jordiluong | 14:95acac6a07c7 | 446 | } |
jordiluong | 14:95acac6a07c7 | 447 | |
jordiluong | 14:95acac6a07c7 | 448 | // Here the first row of the Jacobian is cut off, so we do not take rotation into consideration |
jordiluong | 14:95acac6a07c7 | 449 | // Note: the matrices from now on will we constructed rowwise |
jordiluong | 14:95acac6a07c7 | 450 | double Jvelocity[4]; |
jordiluong | 14:95acac6a07c7 | 451 | Jvelocity[0] = J_data[1]; |
jordiluong | 14:95acac6a07c7 | 452 | Jvelocity[1] = J_data[4]; |
jordiluong | 14:95acac6a07c7 | 453 | Jvelocity[2] = J_data[2]; |
jordiluong | 14:95acac6a07c7 | 454 | Jvelocity[3] = J_data[5]; |
jordiluong | 14:95acac6a07c7 | 455 | |
jordiluong | 14:95acac6a07c7 | 456 | // Creating the inverse Jacobian |
jordiluong | 14:95acac6a07c7 | 457 | double Jvelocity_inv[4]; // The inverse matrix of the jacobian |
jordiluong | 14:95acac6a07c7 | 458 | double determ = Jvelocity[0]*Jvelocity[3]-Jvelocity[1]*Jvelocity[2]; // The determinant of the matrix |
jordiluong | 14:95acac6a07c7 | 459 | Jvelocity_inv[0] = Jvelocity[3]/determ; |
jordiluong | 14:95acac6a07c7 | 460 | Jvelocity_inv[1] = -Jvelocity[1]/determ; |
jordiluong | 14:95acac6a07c7 | 461 | Jvelocity_inv[2] = -Jvelocity[2]/determ; |
jordiluong | 14:95acac6a07c7 | 462 | Jvelocity_inv[3] = Jvelocity[0]/determ; |
jordiluong | 14:95acac6a07c7 | 463 | |
jordiluong | 14:95acac6a07c7 | 464 | // Now the velocity of the joints are found by giving the velocity of the end-effector and the inverse jacobian |
jordiluong | 14:95acac6a07c7 | 465 | double msh[2]; // This is the velocity the joints have to have |
jordiluong | 14:95acac6a07c7 | 466 | msh[0] = xVelocity*Jvelocity_inv[0] + yVelocity*Jvelocity_inv[1]; |
jordiluong | 14:95acac6a07c7 | 467 | msh[1] = xVelocity*Jvelocity_inv[2] + yVelocity*Jvelocity_inv[3]; |
jordiluong | 14:95acac6a07c7 | 468 | |
jordiluong | 14:95acac6a07c7 | 469 | if(reference1 + msh[0]*sampleTs > motor1Max) reference1 = motor1Max; |
jordiluong | 14:95acac6a07c7 | 470 | else if(reference1 + msh[0]*sampleTs < motor1Min) reference1 = motor1Min; |
jordiluong | 14:95acac6a07c7 | 471 | else reference1 = reference1 + msh[0]*sampleTs; |
jordiluong | 14:95acac6a07c7 | 472 | |
jordiluong | 14:95acac6a07c7 | 473 | if(reference2 + msh[1]*sampleTs > motor2Max) reference2 = motor2Max; |
jordiluong | 14:95acac6a07c7 | 474 | else if(reference2 + msh[1]*sampleTs < motor2Min) reference2 = motor2Min; |
jordiluong | 14:95acac6a07c7 | 475 | else reference2 = reference2 + msh[1]*sampleTs; |
jordiluong | 14:95acac6a07c7 | 476 | |
jordiluong | 14:95acac6a07c7 | 477 | scope.set(0,reference1); |
jordiluong | 14:95acac6a07c7 | 478 | scope.set(1,position1); |
jordiluong | 14:95acac6a07c7 | 479 | scope.set(2,reference2); |
jordiluong | 14:95acac6a07c7 | 480 | scope.set(3,position2); |
jordiluong | 14:95acac6a07c7 | 481 | scope.send(); |
jordiluong | 14:95acac6a07c7 | 482 | |
jordiluong | 14:95acac6a07c7 | 483 | pc.printf("position 1 %f, 2 %f \r\n", position1/2/pi*360, position2/2/pi*360); |
jordiluong | 14:95acac6a07c7 | 484 | pc.printf("reference 1 %f, 2 %f \r\n", reference1/2/pi*360, reference2/2/pi*360); |
jordiluong | 14:95acac6a07c7 | 485 | //pc.printf("msh*Ts 1 %f, 2 %f \r\n\n", msh[0]*emg_Ts, msh[1]*emg_Ts); |
jordiluong | 14:95acac6a07c7 | 486 | |
jordiluong | 10:a9e344e440b8 | 487 | } |
jordiluong | 10:a9e344e440b8 | 488 | } |
jordiluong | 13:ec227b229f3d | 489 | |
jordiluong | 7:757e95b4dc46 | 490 | // STATES ////////////////////////////////////////////////////////////////////// |
jordiluong | 0:80ac024b84cb | 491 | void ProcessStateMachine() |
jordiluong | 0:80ac024b84cb | 492 | { |
jordiluong | 0:80ac024b84cb | 493 | switch(currentState) |
jordiluong | 0:80ac024b84cb | 494 | { |
jordiluong | 0:80ac024b84cb | 495 | case MOTORS_OFF: |
jordiluong | 0:80ac024b84cb | 496 | { |
jordiluong | 0:80ac024b84cb | 497 | // State initialization |
jordiluong | 0:80ac024b84cb | 498 | if(stateChanged) |
jordiluong | 0:80ac024b84cb | 499 | { |
jordiluong | 15:5d24f832bb7b | 500 | pc.printf("Entering MOTORS_OFF \r\n" |
jordiluong | 15:5d24f832bb7b | 501 | "Press button 1 to enter CALIBRATING \r\n"); |
jordiluong | 5:0d3e8694726e | 502 | TurnMotorsOff(); // Turn motors off |
jordiluong | 0:80ac024b84cb | 503 | stateChanged = false; |
jordiluong | 0:80ac024b84cb | 504 | } |
jordiluong | 0:80ac024b84cb | 505 | |
jordiluong | 0:80ac024b84cb | 506 | // Home command |
jordiluong | 4:ea7689bf97e1 | 507 | if(!button1) |
jordiluong | 0:80ac024b84cb | 508 | { |
jordiluong | 14:95acac6a07c7 | 509 | currentState = CALIBRATING; |
jordiluong | 14:95acac6a07c7 | 510 | stateChanged = true; |
jordiluong | 14:95acac6a07c7 | 511 | break; |
jordiluong | 14:95acac6a07c7 | 512 | } |
jordiluong | 14:95acac6a07c7 | 513 | break; |
jordiluong | 14:95acac6a07c7 | 514 | } |
jordiluong | 14:95acac6a07c7 | 515 | |
jordiluong | 14:95acac6a07c7 | 516 | case CALIBRATING: |
jordiluong | 14:95acac6a07c7 | 517 | { |
jordiluong | 14:95acac6a07c7 | 518 | // State initialization |
jordiluong | 14:95acac6a07c7 | 519 | if(stateChanged) |
jordiluong | 14:95acac6a07c7 | 520 | { |
jordiluong | 15:5d24f832bb7b | 521 | pc.printf("Entering CALIBRATING \r\n" |
jordiluong | 15:5d24f832bb7b | 522 | "Press button 1 to enter MOVING \r\n"); |
jordiluong | 14:95acac6a07c7 | 523 | stateChanged = false; |
jordiluong | 14:95acac6a07c7 | 524 | calibration_r(); |
jordiluong | 14:95acac6a07c7 | 525 | calibration_l(); |
jordiluong | 14:95acac6a07c7 | 526 | currentState = MOVING; |
jordiluong | 14:95acac6a07c7 | 527 | stateChanged = true; |
jordiluong | 14:95acac6a07c7 | 528 | } |
jordiluong | 14:95acac6a07c7 | 529 | /* |
jordiluong | 14:95acac6a07c7 | 530 | // Home command |
jordiluong | 14:95acac6a07c7 | 531 | if(!button1) |
jordiluong | 14:95acac6a07c7 | 532 | { |
jordiluong | 0:80ac024b84cb | 533 | currentState = MOVING; |
jordiluong | 0:80ac024b84cb | 534 | stateChanged = true; |
jordiluong | 0:80ac024b84cb | 535 | break; |
jordiluong | 0:80ac024b84cb | 536 | } |
jordiluong | 14:95acac6a07c7 | 537 | */ |
jordiluong | 4:ea7689bf97e1 | 538 | break; |
jordiluong | 0:80ac024b84cb | 539 | } |
jordiluong | 0:80ac024b84cb | 540 | |
jordiluong | 0:80ac024b84cb | 541 | case MOVING: |
jordiluong | 0:80ac024b84cb | 542 | { |
jordiluong | 0:80ac024b84cb | 543 | // State initialization |
jordiluong | 0:80ac024b84cb | 544 | if(stateChanged) |
jordiluong | 0:80ac024b84cb | 545 | { |
jordiluong | 15:5d24f832bb7b | 546 | pc.printf("Entering MOVING \r\n"); |
jordiluong | 12:12b72bd60fd1 | 547 | //"Press button 2 to enter HITTING \r\n"); |
jordiluong | 0:80ac024b84cb | 548 | stateChanged = false; |
jordiluong | 0:80ac024b84cb | 549 | } |
jordiluong | 0:80ac024b84cb | 550 | |
jordiluong | 16:2cf8c2705936 | 551 | |
jordiluong | 15:5d24f832bb7b | 552 | |
jordiluong | 0:80ac024b84cb | 553 | // Hit command |
jordiluong | 10:a9e344e440b8 | 554 | /*if(!button2) |
jordiluong | 0:80ac024b84cb | 555 | { |
jordiluong | 0:80ac024b84cb | 556 | currentState = HITTING; |
jordiluong | 0:80ac024b84cb | 557 | stateChanged = true; |
jordiluong | 0:80ac024b84cb | 558 | break; |
jordiluong | 0:80ac024b84cb | 559 | } |
jordiluong | 10:a9e344e440b8 | 560 | */ |
jordiluong | 4:ea7689bf97e1 | 561 | break; |
jordiluong | 0:80ac024b84cb | 562 | } |
jordiluong | 0:80ac024b84cb | 563 | |
jordiluong | 0:80ac024b84cb | 564 | case HITTING: |
jordiluong | 0:80ac024b84cb | 565 | { |
jordiluong | 0:80ac024b84cb | 566 | // State initialization |
jordiluong | 0:80ac024b84cb | 567 | if(stateChanged) |
jordiluong | 0:80ac024b84cb | 568 | { |
jordiluong | 12:12b72bd60fd1 | 569 | //pc.printf("Entering HITTING \r\n"); |
jordiluong | 5:0d3e8694726e | 570 | stateChanged = false; |
jordiluong | 4:ea7689bf97e1 | 571 | //HitBall(); // Hit the ball |
jordiluong | 0:80ac024b84cb | 572 | currentState = MOVING; |
jordiluong | 0:80ac024b84cb | 573 | stateChanged = true; |
jordiluong | 0:80ac024b84cb | 574 | break; |
jordiluong | 0:80ac024b84cb | 575 | } |
jordiluong | 4:ea7689bf97e1 | 576 | break; |
jordiluong | 0:80ac024b84cb | 577 | } |
jordiluong | 0:80ac024b84cb | 578 | |
jordiluong | 0:80ac024b84cb | 579 | default: |
jordiluong | 0:80ac024b84cb | 580 | { |
jordiluong | 5:0d3e8694726e | 581 | TurnMotorsOff(); // Turn motors off for safety |
jordiluong | 4:ea7689bf97e1 | 582 | break; |
jordiluong | 0:80ac024b84cb | 583 | } |
jordiluong | 0:80ac024b84cb | 584 | } |
jordiluong | 0:80ac024b84cb | 585 | } |
jordiluong | 13:ec227b229f3d | 586 | |
jordiluong | 7:757e95b4dc46 | 587 | // MAIN FUNCTION /////////////////////////////////////////////////////////////// |
jordiluong | 0:80ac024b84cb | 588 | int main() |
jordiluong | 0:80ac024b84cb | 589 | { |
jordiluong | 0:80ac024b84cb | 590 | // Serial communication |
jordiluong | 0:80ac024b84cb | 591 | pc.baud(115200); |
jordiluong | 0:80ac024b84cb | 592 | |
jordiluong | 14:95acac6a07c7 | 593 | led1.write(1); |
jordiluong | 14:95acac6a07c7 | 594 | led2.write(1); |
jordiluong | 14:95acac6a07c7 | 595 | led3.write(1); |
jordiluong | 15:5d24f832bb7b | 596 | led4.write(1); |
jordiluong | 15:5d24f832bb7b | 597 | led5.write(0); |
jordiluong | 15:5d24f832bb7b | 598 | |
jordiluong | 4:ea7689bf97e1 | 599 | pc.printf("START \r\n"); |
jordiluong | 4:ea7689bf97e1 | 600 | |
jordiluong | 14:95acac6a07c7 | 601 | bqc.add( &bq1_low ).add( &bq2_high ).add( &bq3_notch ); |
jordiluong | 7:757e95b4dc46 | 602 | |
jordiluong | 14:95acac6a07c7 | 603 | sampleTicker.attach(&JointVelocities, sampleTs); // Ticker to sample EMG |
jordiluong | 12:12b72bd60fd1 | 604 | controllerTicker.attach(&Motor1Controller, controller_Ts); // Ticker to control motor 1 (PID) |
jordiluong | 14:95acac6a07c7 | 605 | emgRight.attach(&check_emg_r, emgTs); //continously execute the motor controller |
jordiluong | 14:95acac6a07c7 | 606 | emgLeft.attach(&check_emg_l, emgTs); |
jordiluong | 12:12b72bd60fd1 | 607 | |
jordiluong | 12:12b72bd60fd1 | 608 | motor1MagnitudePin.period_ms(1); |
jordiluong | 12:12b72bd60fd1 | 609 | motor2MagnitudePin.period_ms(1); |
jordiluong | 12:12b72bd60fd1 | 610 | TurnMotorsOff(); |
jordiluong | 4:ea7689bf97e1 | 611 | |
jordiluong | 0:80ac024b84cb | 612 | while(true) |
jordiluong | 0:80ac024b84cb | 613 | { |
jordiluong | 0:80ac024b84cb | 614 | ProcessStateMachine(); // Execute states function |
jordiluong | 0:80ac024b84cb | 615 | } |
jordiluong | 0:80ac024b84cb | 616 | } |