Dependencies: HIDScope MODSERIAL QEI biquadFilter mbed Servo
main.cpp@45:829a3992d689, 2018-11-01 (annotated)
- Committer:
- Spekdon
- Date:
- Thu Nov 01 19:48:22 2018 +0000
- Revision:
- 45:829a3992d689
- Parent:
- 44:25eec278c623
- Child:
- 46:9b60a3c1acab
Working code;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MaikOvermars | 0:4cb1de41d049 | 1 | #include "mbed.h" |
MaikOvermars | 0:4cb1de41d049 | 2 | #include "MODSERIAL.h" |
MaikOvermars | 0:4cb1de41d049 | 3 | #include "QEI.h" |
MaikOvermars | 0:4cb1de41d049 | 4 | #include "HIDScope.h" |
MaikOvermars | 0:4cb1de41d049 | 5 | #include "BiQuad.h" |
MaikOvermars | 0:4cb1de41d049 | 6 | #include "PID_controller.h" |
Spekdon | 45:829a3992d689 | 7 | //#include "kinematics.h" |
Spekdon | 45:829a3992d689 | 8 | #include "Servo.h" |
MaikOvermars | 17:1f93c83e211f | 9 | #include "processing_chain_emg.h" |
Spekdon | 43:8e2ea92fee01 | 10 | #include <vector> |
Spekdon | 43:8e2ea92fee01 | 11 | |
Spekdon | 45:829a3992d689 | 12 | //pc |
Spekdon | 45:829a3992d689 | 13 | MODSERIAL pc(USBTX, USBRX); |
MaikOvermars | 0:4cb1de41d049 | 14 | |
MaikOvermars | 10:7339dca7d604 | 15 | // emg inputs |
MaikOvermars | 0:4cb1de41d049 | 16 | AnalogIn emg0( A0 ); |
MaikOvermars | 0:4cb1de41d049 | 17 | AnalogIn emg1( A1 ); |
Spekdon | 45:829a3992d689 | 18 | AnalogIn emg2( A2 ); |
Spekdon | 45:829a3992d689 | 19 | AnalogIn emg3( A3 ); |
Spekdon | 45:829a3992d689 | 20 | //Servo myservo(A5); |
Spekdon | 45:829a3992d689 | 21 | //InterruptIn button1(SW2); |
Spekdon | 45:829a3992d689 | 22 | //InterruptIn button2(SW3); |
Spekdon | 45:829a3992d689 | 23 | double range; |
MaikOvermars | 0:4cb1de41d049 | 24 | |
MaikOvermars | 10:7339dca7d604 | 25 | // motor ouptuts |
MaikOvermars | 0:4cb1de41d049 | 26 | PwmOut motor1_pwm(D5); |
MaikOvermars | 0:4cb1de41d049 | 27 | DigitalOut motor1_dir(D4); |
bjonkheer | 38:0f824c45f717 | 28 | PwmOut motor2_pwm(D6); |
bjonkheer | 38:0f824c45f717 | 29 | DigitalOut motor2_dir(D7); |
Spekdon | 45:829a3992d689 | 30 | AnalogIn vx_adjustment(A4); |
Spekdon | 45:829a3992d689 | 31 | AnalogIn vy_adjustment(A5); |
MaikOvermars | 0:4cb1de41d049 | 32 | |
SvenD97 | 14:4744cc6c90f4 | 33 | // defining encoders |
MaikOvermars | 16:0280a604cf7e | 34 | QEI motor_1_encoder(D12,D13,NC,32); |
MaikOvermars | 16:0280a604cf7e | 35 | QEI motor_2_encoder(D10,D11,NC,32); |
SvenD97 | 14:4744cc6c90f4 | 36 | |
MaikOvermars | 17:1f93c83e211f | 37 | // other objects |
MaikOvermars | 0:4cb1de41d049 | 38 | DigitalIn button(D0); |
MaikOvermars | 40:e217056584be | 39 | DigitalIn emgstop(SW2); |
SvenD97 | 31:393a7ec1d396 | 40 | DigitalOut led_R(LED_RED); |
SvenD97 | 31:393a7ec1d396 | 41 | DigitalOut led_B(LED_BLUE); |
SvenD97 | 31:393a7ec1d396 | 42 | DigitalOut led_G(LED_GREEN); |
MaikOvermars | 0:4cb1de41d049 | 43 | |
SvenD97 | 14:4744cc6c90f4 | 44 | // tickers and timers |
MaikOvermars | 16:0280a604cf7e | 45 | Ticker loop_ticker; |
MaikOvermars | 0:4cb1de41d049 | 46 | Timer state_timer; |
SvenD97 | 27:eee900e0a47d | 47 | Timer emg_timer; |
MaikOvermars | 0:4cb1de41d049 | 48 | |
SvenD97 | 34:7d672cd04486 | 49 | // Timeouts and related variables |
SvenD97 | 34:7d672cd04486 | 50 | Timeout make_button_active; |
SvenD97 | 34:7d672cd04486 | 51 | bool button_suppressed = false; |
SvenD97 | 34:7d672cd04486 | 52 | |
SvenD97 | 34:7d672cd04486 | 53 | // States |
SvenD97 | 31:393a7ec1d396 | 54 | enum States {failure, waiting, calib_emg, calib_enc, operational, demo, homing}; //All possible robot states |
SvenD97 | 27:eee900e0a47d | 55 | enum Emg_measures_states {not_in_calib_emg, calib_right_bicep, calib_right_tricep, calib_left_bicep, calib_left_tricep}; // States inside |
SvenD97 | 37:5ddfd9e6cdb2 | 56 | enum calib_enc_states {not_in_calib_enc, calib_enc_q1, calib_enc_q2}; |
MaikOvermars | 0:4cb1de41d049 | 57 | |
MaikOvermars | 0:4cb1de41d049 | 58 | //Global variables/objects |
MaikOvermars | 0:4cb1de41d049 | 59 | States current_state; |
SvenD97 | 31:393a7ec1d396 | 60 | Emg_measures_states current_emg_calibration_state = not_in_calib_emg; |
SvenD97 | 37:5ddfd9e6cdb2 | 61 | calib_enc_states calib_enc_state = not_in_calib_enc; |
MaikOvermars | 16:0280a604cf7e | 62 | |
Spekdon | 45:829a3992d689 | 63 | double des_vx, des_vy, x, y, q1, q2, e1, e2, x_norm, y_norm; //will be set by the motor_controller function |
bjonkheer | 38:0f824c45f717 | 64 | double u1, u2; |
MaikOvermars | 17:1f93c83e211f | 65 | double vxmax = 1.0, vymax = 1.0; |
SvenD97 | 27:eee900e0a47d | 66 | double right_bicep_max = 0.0, right_tricep_max = 0.0, left_bicep_max= 0.0, left_tricep_max = 0.0; |
MaikOvermars | 40:e217056584be | 67 | double scaling_right_bicep = 1.0, scaling_right_tricep = 1.0, scaling_left_bicep = 1.0, scaling_left_tricep = 1.0; |
SvenD97 | 27:eee900e0a47d | 68 | |
SvenD97 | 31:393a7ec1d396 | 69 | // Variables for emg |
SvenD97 | 31:393a7ec1d396 | 70 | double raw_emg_0, process_emg_0; |
SvenD97 | 31:393a7ec1d396 | 71 | double raw_emg_1, process_emg_1; |
SvenD97 | 31:393a7ec1d396 | 72 | double raw_emg_2, process_emg_2; |
SvenD97 | 31:393a7ec1d396 | 73 | double raw_emg_3, process_emg_3; |
SvenD97 | 31:393a7ec1d396 | 74 | |
SvenD97 | 31:393a7ec1d396 | 75 | |
SvenD97 | 33:eb77ed8d167c | 76 | // Variables for calibration |
SvenD97 | 35:6110d0b5513b | 77 | double calib_q1 = 3.1415926535f; |
SvenD97 | 37:5ddfd9e6cdb2 | 78 | double calib_q2 = double(7)/double(6) * 3.1415926535f; |
Spekdon | 45:829a3992d689 | 79 | double off_set_q1 = 0.5f*3.1415926535f; // This variable is used to determine the off set from our definition from q1 and q2. |
Spekdon | 45:829a3992d689 | 80 | double off_set_q2 = 3.1415926535f; |
SvenD97 | 33:eb77ed8d167c | 81 | |
SvenD97 | 30:7a66951a0122 | 82 | // Variables defined for the homing state |
SvenD97 | 35:6110d0b5513b | 83 | double q1_homing = 0.5f*3.1415926535f, q2_homing = 3.1415926535f; |
Spekdon | 45:829a3992d689 | 84 | double qref1 = 0.5f*3.1415926535f, qref2 = 3.1415926535f; |
Spekdon | 45:829a3992d689 | 85 | double beta = 0.05; |
Spekdon | 45:829a3992d689 | 86 | double k_hom = 0.05; |
SvenD97 | 31:393a7ec1d396 | 87 | |
SvenD97 | 31:393a7ec1d396 | 88 | // For the state calib_enc |
SvenD97 | 31:393a7ec1d396 | 89 | double q1old; |
SvenD97 | 31:393a7ec1d396 | 90 | double q2old; |
SvenD97 | 30:7a66951a0122 | 91 | |
Spekdon | 43:8e2ea92fee01 | 92 | vector<double> currentconfig; |
Spekdon | 43:8e2ea92fee01 | 93 | vector<double> newconfig; |
Spekdon | 43:8e2ea92fee01 | 94 | vector<double> ref; |
Spekdon | 45:829a3992d689 | 95 | vector<double> testconfig; |
Spekdon | 43:8e2ea92fee01 | 96 | |
Spekdon | 43:8e2ea92fee01 | 97 | double currentx; |
Spekdon | 43:8e2ea92fee01 | 98 | double currenty; |
Spekdon | 43:8e2ea92fee01 | 99 | |
Spekdon | 43:8e2ea92fee01 | 100 | double L1 = 0.4388; |
Spekdon | 43:8e2ea92fee01 | 101 | double L2 = 0.4508; |
Spekdon | 43:8e2ea92fee01 | 102 | |
SvenD97 | 27:eee900e0a47d | 103 | // Meaning of process_emg_0 and such |
SvenD97 | 27:eee900e0a47d | 104 | // - process_emg_0 is right biceps |
SvenD97 | 27:eee900e0a47d | 105 | // - process_emg_1 is right triceps |
SvenD97 | 27:eee900e0a47d | 106 | // - process_emg_2 is left biceps |
SvenD97 | 27:eee900e0a47d | 107 | // - process_emg_3 is left triceps |
bjonkheer | 23:7d83af123c43 | 108 | |
MaikOvermars | 0:4cb1de41d049 | 109 | int counts_per_rotation = 32; |
MaikOvermars | 0:4cb1de41d049 | 110 | bool state_changed = false; |
SvenD97 | 8:bba05e863b68 | 111 | const double T = 0.001; |
bjonkheer | 23:7d83af123c43 | 112 | |
Spekdon | 45:829a3992d689 | 113 | bool gripperclosed = false; |
Spekdon | 45:829a3992d689 | 114 | |
SvenD97 | 30:7a66951a0122 | 115 | // Resolution of the encoder at the output axle |
SvenD97 | 30:7a66951a0122 | 116 | double resolution = (2.0f*3.1415926535f/double(counts_per_rotation))*(1.0/131.0); // In radians |
SvenD97 | 30:7a66951a0122 | 117 | |
MaikOvermars | 17:1f93c83e211f | 118 | // Functions |
Spekdon | 43:8e2ea92fee01 | 119 | |
Spekdon | 45:829a3992d689 | 120 | //void open_gripper(){ |
Spekdon | 45:829a3992d689 | 121 | // myservo=0; |
Spekdon | 45:829a3992d689 | 122 | //} |
Spekdon | 45:829a3992d689 | 123 | // |
Spekdon | 45:829a3992d689 | 124 | //void close_gripper(){ |
Spekdon | 45:829a3992d689 | 125 | // myservo=1; |
Spekdon | 45:829a3992d689 | 126 | //} |
Spekdon | 45:829a3992d689 | 127 | |
Spekdon | 43:8e2ea92fee01 | 128 | vector<double> forwardkinematics_function(double& q1, double& q2) { |
Spekdon | 43:8e2ea92fee01 | 129 | // input are joint angles, output are x and y position of end effector |
Spekdon | 43:8e2ea92fee01 | 130 | |
Spekdon | 43:8e2ea92fee01 | 131 | //previously +x01 and +y01 |
Spekdon | 43:8e2ea92fee01 | 132 | currentx = L1*cos(q1)-L2*cos(q2); |
Spekdon | 43:8e2ea92fee01 | 133 | currenty = L1 * sin(q1) - L2 * sin(q2); |
Spekdon | 43:8e2ea92fee01 | 134 | |
Spekdon | 43:8e2ea92fee01 | 135 | vector<double> xy; |
Spekdon | 43:8e2ea92fee01 | 136 | xy.push_back(currentx); |
Spekdon | 43:8e2ea92fee01 | 137 | xy.push_back(currenty); |
Spekdon | 43:8e2ea92fee01 | 138 | return xy; |
Spekdon | 43:8e2ea92fee01 | 139 | |
Spekdon | 43:8e2ea92fee01 | 140 | } |
Spekdon | 43:8e2ea92fee01 | 141 | |
Spekdon | 45:829a3992d689 | 142 | vector<double> inversekinematics_function(const double& T, double ref1, double ref2, double& q1, double& q2, double& des_vx, double& des_vy) { |
Spekdon | 43:8e2ea92fee01 | 143 | // x, y: positions of end effector | T: time to hold current velocity | qref1, qref2: reference thetas | q1, q2: current thetas | vx, vy: desired x, y velocities |
Spekdon | 43:8e2ea92fee01 | 144 | |
Spekdon | 43:8e2ea92fee01 | 145 | // pseudo inverse jacobian to get joint speeds |
Spekdon | 43:8e2ea92fee01 | 146 | // input are desired vx and vy of end effector, output joint angle speeds |
Spekdon | 43:8e2ea92fee01 | 147 | |
Spekdon | 43:8e2ea92fee01 | 148 | double q1_star_des; // desired joint velocity of q1_star |
Spekdon | 43:8e2ea92fee01 | 149 | double q2_star_des; // same as above but then for q2_star |
Spekdon | 43:8e2ea92fee01 | 150 | double C; |
Spekdon | 43:8e2ea92fee01 | 151 | |
Spekdon | 43:8e2ea92fee01 | 152 | // The calculation below assumes that the end effector position is calculated before this function is executed |
Spekdon | 43:8e2ea92fee01 | 153 | // In our case the determinant will not equal zero, hence no problems with singularies I think. |
Spekdon | 43:8e2ea92fee01 | 154 | |
Spekdon | 43:8e2ea92fee01 | 155 | C = L1*L2*sin(ref1)*cos(ref2) - L1*L2*sin(ref2)*cos(ref1); |
Spekdon | 45:829a3992d689 | 156 | q1_star_des = double(1/C)*(-L2*cos(ref2)*des_vx - L2*sin(ref2)*des_vy); |
Spekdon | 45:829a3992d689 | 157 | q2_star_des = double(1/C)*((L2*cos(ref2)-L1*cos(ref1))*des_vx + (L2*sin(ref2)-L1*sin(ref1))*des_vy); |
Spekdon | 43:8e2ea92fee01 | 158 | |
Spekdon | 43:8e2ea92fee01 | 159 | qref1 = T*q1_star_des; |
Spekdon | 43:8e2ea92fee01 | 160 | qref2 = T*(q2_star_des+q1_star_des); |
Spekdon | 43:8e2ea92fee01 | 161 | |
Spekdon | 43:8e2ea92fee01 | 162 | double testq1 = ref1+qref1; |
Spekdon | 43:8e2ea92fee01 | 163 | double testq2 = ref2+qref2; |
Spekdon | 43:8e2ea92fee01 | 164 | newconfig = forwardkinematics_function(testq1, testq2); |
Spekdon | 43:8e2ea92fee01 | 165 | |
Spekdon | 45:829a3992d689 | 166 | if (sqrt(pow(newconfig[0],2)+pow(newconfig[1],2)) > 1) |
Spekdon | 43:8e2ea92fee01 | 167 | { |
Spekdon | 43:8e2ea92fee01 | 168 | qref1 = ref1; |
Spekdon | 43:8e2ea92fee01 | 169 | qref2 = ref2; |
Spekdon | 43:8e2ea92fee01 | 170 | } |
Spekdon | 43:8e2ea92fee01 | 171 | else |
Spekdon | 43:8e2ea92fee01 | 172 | { |
Spekdon | 43:8e2ea92fee01 | 173 | qref1 = ref1 + qref1; |
Spekdon | 43:8e2ea92fee01 | 174 | qref2 = ref2 + qref2; |
Spekdon | 43:8e2ea92fee01 | 175 | } |
Spekdon | 43:8e2ea92fee01 | 176 | |
Spekdon | 43:8e2ea92fee01 | 177 | vector<double> thetas; |
Spekdon | 43:8e2ea92fee01 | 178 | thetas.push_back(qref1); |
Spekdon | 43:8e2ea92fee01 | 179 | thetas.push_back(qref2); |
Spekdon | 43:8e2ea92fee01 | 180 | return thetas; |
Spekdon | 43:8e2ea92fee01 | 181 | } |
Spekdon | 43:8e2ea92fee01 | 182 | |
MaikOvermars | 0:4cb1de41d049 | 183 | void measure_all() |
MaikOvermars | 0:4cb1de41d049 | 184 | { |
Spekdon | 45:829a3992d689 | 185 | q1 = (motor_1_encoder.getPulses()*2.0f*3.1415926535f/counts_per_rotation)*(1.0/131.0) + off_set_q1; //do this here, and not in the encoder interrupt, to reduce computational load |
Spekdon | 45:829a3992d689 | 186 | q2 = (motor_2_encoder.getPulses()*2.0f*3.1415926535f/counts_per_rotation)*(1.0/131.0) + off_set_q2; |
Spekdon | 43:8e2ea92fee01 | 187 | currentconfig = forwardkinematics_function(q1,q2); //previously x,y also input |
MaikOvermars | 17:1f93c83e211f | 188 | raw_emg_0 = emg0.read(); //sample analog voltages (all sampling theory applies, you might get aliasing etc.) |
MaikOvermars | 17:1f93c83e211f | 189 | raw_emg_1 = emg1.read(); |
Spekdon | 45:829a3992d689 | 190 | raw_emg_2 = emg2.read(); |
Spekdon | 45:829a3992d689 | 191 | raw_emg_3 = emg3.read(); |
MaikOvermars | 41:e9d6fdf02074 | 192 | processing_chain_emg(raw_emg_0, raw_emg_1, raw_emg_2, raw_emg_3, process_emg_0, process_emg_1, process_emg_2, process_emg_3); // processes the emg signals |
MaikOvermars | 0:4cb1de41d049 | 193 | } |
MaikOvermars | 0:4cb1de41d049 | 194 | |
MaikOvermars | 0:4cb1de41d049 | 195 | void output_all() { |
MaikOvermars | 0:4cb1de41d049 | 196 | motor1_pwm = fabs(u1); |
Spekdon | 45:829a3992d689 | 197 | if (motor1_pwm > 1.0f){ |
Spekdon | 45:829a3992d689 | 198 | motor1_pwm = 1.0f; |
Spekdon | 45:829a3992d689 | 199 | } |
MaikOvermars | 16:0280a604cf7e | 200 | motor1_dir = u1 > 0.0f; |
MaikOvermars | 0:4cb1de41d049 | 201 | motor2_pwm = fabs(u2); |
Spekdon | 45:829a3992d689 | 202 | if (motor2_pwm > 1.0f){ |
Spekdon | 45:829a3992d689 | 203 | motor2_pwm = 1.0f; |
Spekdon | 45:829a3992d689 | 204 | } |
MaikOvermars | 16:0280a604cf7e | 205 | motor2_dir = u2 > 0.0f; |
MaikOvermars | 0:4cb1de41d049 | 206 | static int output_counter = 0; |
MaikOvermars | 0:4cb1de41d049 | 207 | output_counter++; |
MaikOvermars | 0:4cb1de41d049 | 208 | } |
MaikOvermars | 0:4cb1de41d049 | 209 | |
SvenD97 | 34:7d672cd04486 | 210 | void unsuppressing_button(){ |
SvenD97 | 34:7d672cd04486 | 211 | button_suppressed = false; |
SvenD97 | 34:7d672cd04486 | 212 | } |
SvenD97 | 34:7d672cd04486 | 213 | |
MaikOvermars | 0:4cb1de41d049 | 214 | void state_machine() { |
MaikOvermars | 0:4cb1de41d049 | 215 | switch(current_state) { //States can be: failure, wait, calib_enc, calib_emg, operational, demo, |
MaikOvermars | 0:4cb1de41d049 | 216 | case waiting: //Nothing useful here, maybe a blinking LED for fun and communication to the user |
SvenD97 | 37:5ddfd9e6cdb2 | 217 | if (button.read()==false) |
MaikOvermars | 0:4cb1de41d049 | 218 | { |
Spekdon | 45:829a3992d689 | 219 | current_state = calib_emg; //the NEXT loop we will be in calib_enc state |
Spekdon | 45:829a3992d689 | 220 | current_emg_calibration_state = calib_right_bicep; |
SvenD97 | 37:5ddfd9e6cdb2 | 221 | calib_enc_state = calib_enc_q2; |
SvenD97 | 31:393a7ec1d396 | 222 | state_changed = true; |
MaikOvermars | 0:4cb1de41d049 | 223 | } |
bjonkheer | 29:d1e8eb135e6c | 224 | |
MaikOvermars | 0:4cb1de41d049 | 225 | break; //to avoid falling through to the next state, although this can sometimes be very useful. |
MaikOvermars | 0:4cb1de41d049 | 226 | |
MaikOvermars | 0:4cb1de41d049 | 227 | case calib_enc: |
bjonkheer | 29:d1e8eb135e6c | 228 | |
MaikOvermars | 0:4cb1de41d049 | 229 | if (state_changed==true) |
MaikOvermars | 0:4cb1de41d049 | 230 | { |
MaikOvermars | 0:4cb1de41d049 | 231 | state_timer.reset(); |
MaikOvermars | 0:4cb1de41d049 | 232 | state_timer.start(); |
MaikOvermars | 0:4cb1de41d049 | 233 | state_changed = false; |
bjonkheer | 29:d1e8eb135e6c | 234 | led_G = 0; |
bjonkheer | 29:d1e8eb135e6c | 235 | led_B = 1; |
bjonkheer | 29:d1e8eb135e6c | 236 | led_R = 1; |
SvenD97 | 44:25eec278c623 | 237 | //u1 = 0.2; |
SvenD97 | 44:25eec278c623 | 238 | //u2 = -0.65f; |
bjonkheer | 29:d1e8eb135e6c | 239 | q1old = 0; |
bjonkheer | 29:d1e8eb135e6c | 240 | q2old = 0; |
MaikOvermars | 0:4cb1de41d049 | 241 | } |
bjonkheer | 29:d1e8eb135e6c | 242 | |
SvenD97 | 37:5ddfd9e6cdb2 | 243 | switch(calib_enc_state){ |
SvenD97 | 37:5ddfd9e6cdb2 | 244 | case calib_enc_q2: |
SvenD97 | 37:5ddfd9e6cdb2 | 245 | if (q2 - q2old == 0.0 && state_timer.read() > 5.0f) |
SvenD97 | 37:5ddfd9e6cdb2 | 246 | { |
SvenD97 | 37:5ddfd9e6cdb2 | 247 | calib_enc_state = calib_enc_q1; |
SvenD97 | 37:5ddfd9e6cdb2 | 248 | off_set_q2 = calib_q2 - q2; |
SvenD97 | 44:25eec278c623 | 249 | //u2 = -0.4; |
SvenD97 | 44:25eec278c623 | 250 | //u1 = -0.75; |
SvenD97 | 37:5ddfd9e6cdb2 | 251 | state_timer.reset(); |
SvenD97 | 37:5ddfd9e6cdb2 | 252 | state_timer.start(); |
SvenD97 | 37:5ddfd9e6cdb2 | 253 | } |
SvenD97 | 37:5ddfd9e6cdb2 | 254 | q2old = q2; |
SvenD97 | 37:5ddfd9e6cdb2 | 255 | break; |
SvenD97 | 37:5ddfd9e6cdb2 | 256 | case calib_enc_q1: |
SvenD97 | 37:5ddfd9e6cdb2 | 257 | if (q1 - q1old == 0.0 && state_timer.read() > 5.0f) |
SvenD97 | 37:5ddfd9e6cdb2 | 258 | { |
SvenD97 | 37:5ddfd9e6cdb2 | 259 | calib_enc_state = not_in_calib_enc; |
SvenD97 | 37:5ddfd9e6cdb2 | 260 | current_emg_calibration_state = calib_right_bicep; |
Spekdon | 43:8e2ea92fee01 | 261 | current_state = calib_emg; |
SvenD97 | 37:5ddfd9e6cdb2 | 262 | state_changed = true; |
SvenD97 | 37:5ddfd9e6cdb2 | 263 | off_set_q1 = calib_q1 - q1; |
SvenD97 | 44:25eec278c623 | 264 | //u1 = 0; |
SvenD97 | 37:5ddfd9e6cdb2 | 265 | state_timer.reset(); |
SvenD97 | 37:5ddfd9e6cdb2 | 266 | state_timer.start(); |
SvenD97 | 37:5ddfd9e6cdb2 | 267 | } |
bjonkheer | 38:0f824c45f717 | 268 | q1old = q1; |
SvenD97 | 37:5ddfd9e6cdb2 | 269 | break; |
SvenD97 | 37:5ddfd9e6cdb2 | 270 | default: |
SvenD97 | 37:5ddfd9e6cdb2 | 271 | current_state = failure; |
MaikOvermars | 0:4cb1de41d049 | 272 | } |
MaikOvermars | 0:4cb1de41d049 | 273 | break; |
MaikOvermars | 0:4cb1de41d049 | 274 | |
MaikOvermars | 0:4cb1de41d049 | 275 | case calib_emg: //calibrate emg-signals |
SvenD97 | 27:eee900e0a47d | 276 | if (state_changed == true){ |
SvenD97 | 27:eee900e0a47d | 277 | state_timer.reset(); |
SvenD97 | 27:eee900e0a47d | 278 | state_timer.start(); |
SvenD97 | 27:eee900e0a47d | 279 | emg_timer.reset(); |
SvenD97 | 27:eee900e0a47d | 280 | emg_timer.start(); |
SvenD97 | 27:eee900e0a47d | 281 | state_changed = false; |
SvenD97 | 27:eee900e0a47d | 282 | } |
MaikOvermars | 42:bcd496523c66 | 283 | // first the led will be purple, during this time the right biceps should be maximally contracted |
MaikOvermars | 42:bcd496523c66 | 284 | // after five seconds and when the right biceps are relaxed, it switches to a blue led |
MaikOvermars | 42:bcd496523c66 | 285 | // when the blue led is active the right triceps should be maximally contracted |
MaikOvermars | 42:bcd496523c66 | 286 | // then again it switches to purple for left biceps and after that blue for left triceps |
MaikOvermars | 42:bcd496523c66 | 287 | // after this, the emg signals are calibrated |
SvenD97 | 31:393a7ec1d396 | 288 | switch(current_emg_calibration_state){ |
SvenD97 | 27:eee900e0a47d | 289 | case calib_right_bicep: |
MaikOvermars | 40:e217056584be | 290 | led_R = 0; |
MaikOvermars | 40:e217056584be | 291 | led_G = 1; |
MaikOvermars | 42:bcd496523c66 | 292 | led_B = 0; |
SvenD97 | 27:eee900e0a47d | 293 | if(emg_timer < 5.0f){ |
SvenD97 | 27:eee900e0a47d | 294 | if (process_emg_0 > right_bicep_max){ |
SvenD97 | 27:eee900e0a47d | 295 | right_bicep_max = process_emg_0; |
SvenD97 | 27:eee900e0a47d | 296 | } |
SvenD97 | 27:eee900e0a47d | 297 | } |
MaikOvermars | 40:e217056584be | 298 | else if ((process_emg_0 < 0.1*right_bicep_max) || (emgstop.read() == false)){ |
MaikOvermars | 40:e217056584be | 299 | scaling_right_bicep = 1.0/ right_bicep_max; |
SvenD97 | 27:eee900e0a47d | 300 | current_emg_calibration_state = calib_right_tricep; |
SvenD97 | 27:eee900e0a47d | 301 | emg_timer.reset(); |
SvenD97 | 27:eee900e0a47d | 302 | emg_timer.start(); |
SvenD97 | 27:eee900e0a47d | 303 | } |
SvenD97 | 27:eee900e0a47d | 304 | break; |
SvenD97 | 27:eee900e0a47d | 305 | case calib_right_tricep: |
MaikOvermars | 40:e217056584be | 306 | led_R = 1; |
MaikOvermars | 40:e217056584be | 307 | led_G = 1; |
MaikOvermars | 40:e217056584be | 308 | led_B = 0; |
SvenD97 | 27:eee900e0a47d | 309 | if(emg_timer < 5.0f){ |
SvenD97 | 27:eee900e0a47d | 310 | if (process_emg_1 > right_tricep_max){ |
SvenD97 | 27:eee900e0a47d | 311 | right_tricep_max = process_emg_1; |
SvenD97 | 27:eee900e0a47d | 312 | } |
SvenD97 | 27:eee900e0a47d | 313 | } |
MaikOvermars | 40:e217056584be | 314 | else if ((process_emg_1 < 0.1*right_tricep_max) || (emgstop.read() == false)){ |
MaikOvermars | 40:e217056584be | 315 | scaling_right_tricep = 1.0/ right_tricep_max; |
SvenD97 | 30:7a66951a0122 | 316 | current_emg_calibration_state = calib_left_bicep; |
SvenD97 | 30:7a66951a0122 | 317 | emg_timer.reset(); |
SvenD97 | 30:7a66951a0122 | 318 | emg_timer.start(); |
SvenD97 | 30:7a66951a0122 | 319 | } |
SvenD97 | 27:eee900e0a47d | 320 | break; |
MaikOvermars | 40:e217056584be | 321 | case calib_left_bicep: |
MaikOvermars | 40:e217056584be | 322 | led_R = 0; |
MaikOvermars | 40:e217056584be | 323 | led_G = 1; |
MaikOvermars | 42:bcd496523c66 | 324 | led_B = 0; |
SvenD97 | 30:7a66951a0122 | 325 | if(emg_timer < 5.0f){ |
SvenD97 | 30:7a66951a0122 | 326 | if (process_emg_2 > left_bicep_max){ |
SvenD97 | 30:7a66951a0122 | 327 | left_bicep_max = process_emg_2; |
SvenD97 | 27:eee900e0a47d | 328 | } |
SvenD97 | 30:7a66951a0122 | 329 | } |
MaikOvermars | 40:e217056584be | 330 | else if ((process_emg_2 < 0.1*left_bicep_max) || (emgstop.read() == false)){ |
MaikOvermars | 40:e217056584be | 331 | scaling_left_bicep = 1.0/ left_bicep_max; |
SvenD97 | 30:7a66951a0122 | 332 | current_emg_calibration_state = calib_left_tricep; |
SvenD97 | 30:7a66951a0122 | 333 | emg_timer.reset(); |
SvenD97 | 30:7a66951a0122 | 334 | emg_timer.start(); |
SvenD97 | 30:7a66951a0122 | 335 | } |
SvenD97 | 27:eee900e0a47d | 336 | break; |
SvenD97 | 27:eee900e0a47d | 337 | case calib_left_tricep: |
MaikOvermars | 40:e217056584be | 338 | led_R = 1; |
MaikOvermars | 40:e217056584be | 339 | led_G = 1; |
MaikOvermars | 40:e217056584be | 340 | led_B = 0; |
MaikOvermars | 40:e217056584be | 341 | if(emg_timer < 5.0f){ |
MaikOvermars | 40:e217056584be | 342 | if (process_emg_3 > left_tricep_max){ |
MaikOvermars | 40:e217056584be | 343 | left_tricep_max = process_emg_3; |
MaikOvermars | 40:e217056584be | 344 | } |
MaikOvermars | 40:e217056584be | 345 | } |
MaikOvermars | 40:e217056584be | 346 | else if ((process_emg_3 < 0.1*left_tricep_max) || (emgstop.read() == false)){ |
MaikOvermars | 40:e217056584be | 347 | scaling_left_tricep = 1.0/ left_tricep_max; |
MaikOvermars | 40:e217056584be | 348 | current_emg_calibration_state = not_in_calib_emg; |
MaikOvermars | 42:bcd496523c66 | 349 | current_state = operational; |
MaikOvermars | 40:e217056584be | 350 | state_changed = true; |
MaikOvermars | 40:e217056584be | 351 | emg_timer.reset(); |
MaikOvermars | 42:bcd496523c66 | 352 | led_R = 1; |
MaikOvermars | 42:bcd496523c66 | 353 | led_G = 1; |
MaikOvermars | 42:bcd496523c66 | 354 | led_B = 1; |
MaikOvermars | 40:e217056584be | 355 | } |
SvenD97 | 27:eee900e0a47d | 356 | break; |
SvenD97 | 27:eee900e0a47d | 357 | default: |
SvenD97 | 27:eee900e0a47d | 358 | current_state = failure; |
SvenD97 | 27:eee900e0a47d | 359 | state_changed = true; |
SvenD97 | 31:393a7ec1d396 | 360 | } |
SvenD97 | 31:393a7ec1d396 | 361 | |
SvenD97 | 31:393a7ec1d396 | 362 | break; |
SvenD97 | 27:eee900e0a47d | 363 | |
SvenD97 | 30:7a66951a0122 | 364 | case homing: |
SvenD97 | 30:7a66951a0122 | 365 | if (state_changed == true){ |
SvenD97 | 30:7a66951a0122 | 366 | state_timer.reset(); |
SvenD97 | 30:7a66951a0122 | 367 | state_timer.start(); |
SvenD97 | 30:7a66951a0122 | 368 | qref1 = q1; //NOT SURE IF WE NEED THIS. I do not think so, but just to be sure. |
SvenD97 | 30:7a66951a0122 | 369 | qref2 = q2; |
SvenD97 | 30:7a66951a0122 | 370 | } |
SvenD97 | 33:eb77ed8d167c | 371 | des_vx = min(beta, k_hom*(q1 - q1_homing)); // Little bit different then that Arvid told us, but now it works with the motor controller |
SvenD97 | 33:eb77ed8d167c | 372 | des_vy = min(beta, k_hom*(q2 - q2_homing)); |
SvenD97 | 30:7a66951a0122 | 373 | |
SvenD97 | 31:393a7ec1d396 | 374 | // The value of 3.0 and 2*resolution can be changed |
SvenD97 | 31:393a7ec1d396 | 375 | if (fabs(q1-q1_homing) <= 2*resolution && fabs(q2-q2_homing) <= 2 * resolution ){ |
SvenD97 | 31:393a7ec1d396 | 376 | if (state_timer > 3.0f){ |
SvenD97 | 31:393a7ec1d396 | 377 | current_state = operational; |
SvenD97 | 31:393a7ec1d396 | 378 | state_changed = true; |
SvenD97 | 33:eb77ed8d167c | 379 | des_vx = 0; // Not sure if needed but added it anyways. |
SvenD97 | 33:eb77ed8d167c | 380 | des_vy = 0; |
SvenD97 | 30:7a66951a0122 | 381 | } |
SvenD97 | 30:7a66951a0122 | 382 | } |
SvenD97 | 31:393a7ec1d396 | 383 | else{ |
SvenD97 | 31:393a7ec1d396 | 384 | state_timer.reset(); |
SvenD97 | 31:393a7ec1d396 | 385 | } |
SvenD97 | 31:393a7ec1d396 | 386 | break; |
MaikOvermars | 0:4cb1de41d049 | 387 | |
MaikOvermars | 0:4cb1de41d049 | 388 | case operational: //interpreting emg-signals to move the end effector |
SvenD97 | 30:7a66951a0122 | 389 | if (state_changed == true){ |
SvenD97 | 30:7a66951a0122 | 390 | state_changed = false; |
MaikOvermars | 39:5db36ce5e620 | 391 | } |
MaikOvermars | 40:e217056584be | 392 | |
MaikOvermars | 40:e217056584be | 393 | // normalization |
Spekdon | 45:829a3992d689 | 394 | x_norm = process_emg_0 * scaling_right_bicep - process_emg_1 * scaling_right_tricep; |
Spekdon | 45:829a3992d689 | 395 | y_norm = process_emg_2 * scaling_left_bicep - process_emg_3 * scaling_left_tricep; |
Spekdon | 45:829a3992d689 | 396 | |
Spekdon | 45:829a3992d689 | 397 | //x_norm = -1+2*vx_adjustment.read(); |
Spekdon | 45:829a3992d689 | 398 | //y_norm = -1+2*vy_adjustment.read(); |
MaikOvermars | 40:e217056584be | 399 | |
MaikOvermars | 17:1f93c83e211f | 400 | // here we have to determine the desired velocity based on the processed emg signals and calibration |
MaikOvermars | 40:e217056584be | 401 | // x velocity |
Spekdon | 43:8e2ea92fee01 | 402 | if (x_norm >= 0.8) { des_vx = 0.2; } |
Spekdon | 43:8e2ea92fee01 | 403 | else if(x_norm >= 0.6) { des_vx = 0.15; } |
Spekdon | 43:8e2ea92fee01 | 404 | else if(x_norm >= 0.4) { des_vx = 0.1; } |
Spekdon | 43:8e2ea92fee01 | 405 | else if(x_norm >= 0.2) { des_vx = 0.05; } |
Spekdon | 43:8e2ea92fee01 | 406 | else if(x_norm <= -0.8) { des_vx = -0.2; } |
Spekdon | 43:8e2ea92fee01 | 407 | else if(x_norm <= -0.6) { des_vx = -0.15; } |
Spekdon | 43:8e2ea92fee01 | 408 | else if(x_norm <= -0.4) { des_vx = -0.1; } |
Spekdon | 43:8e2ea92fee01 | 409 | else if(x_norm <= -0.2) { des_vx = -0.05; } |
MaikOvermars | 17:1f93c83e211f | 410 | else { des_vx = 0; } |
MaikOvermars | 17:1f93c83e211f | 411 | |
MaikOvermars | 40:e217056584be | 412 | // y velocity |
Spekdon | 43:8e2ea92fee01 | 413 | if (y_norm >= 0.8) { des_vy = 0.2; } |
Spekdon | 43:8e2ea92fee01 | 414 | else if(y_norm >= 0.6) { des_vy = 0.15; } |
Spekdon | 43:8e2ea92fee01 | 415 | else if(y_norm >= 0.4) { des_vy = 0.1; } |
Spekdon | 43:8e2ea92fee01 | 416 | else if(y_norm >= 0.2) { des_vy = 0.05; } |
Spekdon | 43:8e2ea92fee01 | 417 | else if(y_norm <= -0.8) { des_vy = -0.2; } |
Spekdon | 43:8e2ea92fee01 | 418 | else if(y_norm <= -0.6) { des_vy = -0.15; } |
Spekdon | 43:8e2ea92fee01 | 419 | else if(y_norm <= -0.4) { des_vy = -0.1; } |
Spekdon | 43:8e2ea92fee01 | 420 | else if(y_norm <= -0.2) { des_vy = -0.05; } |
MaikOvermars | 17:1f93c83e211f | 421 | else { des_vy = 0; } |
Spekdon | 45:829a3992d689 | 422 | |
Spekdon | 45:829a3992d689 | 423 | if (button.read() == false && button_suppressed == false ) { |
SvenD97 | 30:7a66951a0122 | 424 | current_state = demo; |
SvenD97 | 30:7a66951a0122 | 425 | state_changed = true; |
SvenD97 | 34:7d672cd04486 | 426 | button_suppressed = true; |
SvenD97 | 34:7d672cd04486 | 427 | |
SvenD97 | 34:7d672cd04486 | 428 | make_button_active.attach(&unsuppressing_button,0.5); |
SvenD97 | 34:7d672cd04486 | 429 | |
MaikOvermars | 39:5db36ce5e620 | 430 | } |
Spekdon | 45:829a3992d689 | 431 | |
MaikOvermars | 0:4cb1de41d049 | 432 | break; |
MaikOvermars | 0:4cb1de41d049 | 433 | |
MaikOvermars | 0:4cb1de41d049 | 434 | case demo: //moving according to a specified trajectory |
SvenD97 | 33:eb77ed8d167c | 435 | // We want to draw a square. Hence, first move to a certain point and then start moving a square. |
SvenD97 | 30:7a66951a0122 | 436 | if (state_changed == true){ |
SvenD97 | 30:7a66951a0122 | 437 | state_changed = false; |
MaikOvermars | 39:5db36ce5e620 | 438 | state_timer.reset(); |
MaikOvermars | 39:5db36ce5e620 | 439 | state_timer.start(); |
Spekdon | 45:829a3992d689 | 440 | des_vx = 0.1; |
Spekdon | 45:829a3992d689 | 441 | des_vy = 0; |
Spekdon | 45:829a3992d689 | 442 | } |
Spekdon | 43:8e2ea92fee01 | 443 | double old_vx; |
Spekdon | 43:8e2ea92fee01 | 444 | double old_vy; |
Spekdon | 43:8e2ea92fee01 | 445 | if (state_timer > 2.0f){ |
Spekdon | 43:8e2ea92fee01 | 446 | old_vx = des_vx; |
Spekdon | 43:8e2ea92fee01 | 447 | old_vy = des_vy; |
Spekdon | 45:829a3992d689 | 448 | |
Spekdon | 45:829a3992d689 | 449 | des_vy = -old_vx; |
Spekdon | 45:829a3992d689 | 450 | des_vx = old_vy; |
Spekdon | 45:829a3992d689 | 451 | |
Spekdon | 45:829a3992d689 | 452 | state_timer.reset(); |
Spekdon | 45:829a3992d689 | 453 | state_timer.start(); |
Spekdon | 43:8e2ea92fee01 | 454 | } |
Spekdon | 45:829a3992d689 | 455 | |
Spekdon | 45:829a3992d689 | 456 | |
MaikOvermars | 42:bcd496523c66 | 457 | // des_vx = 0.1; // first we move to the right |
MaikOvermars | 42:bcd496523c66 | 458 | // des_vy = 0.0; |
MaikOvermars | 42:bcd496523c66 | 459 | |
MaikOvermars | 42:bcd496523c66 | 460 | //static double new_vx, new_vy; |
MaikOvermars | 39:5db36ce5e620 | 461 | |
MaikOvermars | 42:bcd496523c66 | 462 | //if(state_timer > 3.0f){ // after waiting an extra second we start on another side of the square |
MaikOvermars | 42:bcd496523c66 | 463 | // state_timer.reset(); |
MaikOvermars | 42:bcd496523c66 | 464 | // state_timer.start(); |
MaikOvermars | 42:bcd496523c66 | 465 | // des_vx = new_vx; |
MaikOvermars | 42:bcd496523c66 | 466 | // des_vy = new_vy; |
MaikOvermars | 42:bcd496523c66 | 467 | //} |
MaikOvermars | 42:bcd496523c66 | 468 | //else if(state_timer > 2.0f){ // we have a velocity of 0.1 m/s for 2 seconds, so we make a square of 20 by 20 cm |
MaikOvermars | 42:bcd496523c66 | 469 | // if(des_vx > 0){new_vx = 0.0; new_vy = 0.1;} // here we check which side of the square we were on |
MaikOvermars | 42:bcd496523c66 | 470 | // else if(des_vy > 0){new_vx = -0.1; new_vy = 0.0;} |
MaikOvermars | 42:bcd496523c66 | 471 | // else if(des_vx < 0){new_vx = 0.0; new_vy = -0.1;} |
MaikOvermars | 42:bcd496523c66 | 472 | // else if(des_vy < 0){new_vx = 0.1; new_vy = 0.0;} |
MaikOvermars | 42:bcd496523c66 | 473 | // des_vx = 0; |
MaikOvermars | 42:bcd496523c66 | 474 | // des_vy = 0; |
MaikOvermars | 42:bcd496523c66 | 475 | //} |
MaikOvermars | 39:5db36ce5e620 | 476 | |
SvenD97 | 30:7a66951a0122 | 477 | |
Spekdon | 45:829a3992d689 | 478 | if (button.read() == false && button_suppressed == false ) { |
SvenD97 | 30:7a66951a0122 | 479 | current_state = operational; |
SvenD97 | 30:7a66951a0122 | 480 | state_changed = true; |
SvenD97 | 34:7d672cd04486 | 481 | |
SvenD97 | 34:7d672cd04486 | 482 | button_suppressed = true; |
SvenD97 | 34:7d672cd04486 | 483 | |
SvenD97 | 34:7d672cd04486 | 484 | make_button_active.attach(&unsuppressing_button,0.5); |
SvenD97 | 30:7a66951a0122 | 485 | } |
MaikOvermars | 0:4cb1de41d049 | 486 | |
MaikOvermars | 0:4cb1de41d049 | 487 | break; |
MaikOvermars | 0:4cb1de41d049 | 488 | |
MaikOvermars | 0:4cb1de41d049 | 489 | case failure: //no way to get out |
MaikOvermars | 0:4cb1de41d049 | 490 | u1 = 0.0f; |
MaikOvermars | 17:1f93c83e211f | 491 | u2 = 0.0f; |
bjonkheer | 29:d1e8eb135e6c | 492 | led_R = 0; |
bjonkheer | 29:d1e8eb135e6c | 493 | led_G = 1; |
bjonkheer | 29:d1e8eb135e6c | 494 | led_B = 1; |
MaikOvermars | 0:4cb1de41d049 | 495 | break; |
MaikOvermars | 0:4cb1de41d049 | 496 | } |
MaikOvermars | 0:4cb1de41d049 | 497 | } |
MaikOvermars | 0:4cb1de41d049 | 498 | |
MaikOvermars | 0:4cb1de41d049 | 499 | void motor_controller() |
MaikOvermars | 0:4cb1de41d049 | 500 | { |
MaikOvermars | 0:4cb1de41d049 | 501 | if (current_state >= operational) { // we can (ab)use the fact that an enum is actually an integer, so math/logic rules still apply |
Spekdon | 43:8e2ea92fee01 | 502 | ref = inversekinematics_function(T,qref1,qref2,q1,q2,des_vx,des_vy); //many different states can modify your reference position, so just do the inverse kinematics once, here |
Spekdon | 43:8e2ea92fee01 | 503 | qref1 = ref[0]; |
Spekdon | 43:8e2ea92fee01 | 504 | qref2 = ref[1]; |
MaikOvermars | 16:0280a604cf7e | 505 | e1 = qref1 - q1; //tracking error (q_ref - q_meas) |
MaikOvermars | 16:0280a604cf7e | 506 | e2 = qref2 - q2; |
Spekdon | 45:829a3992d689 | 507 | PID_controller(e1*(180/3.14),e2*(180/3.14),u1,u2,T); //feedback controller or with possibly fancy controller additions...; pass by reference |
MaikOvermars | 0:4cb1de41d049 | 508 | } //otherwise we just don’t mess with the value of control variable ‘u’ that is set somewhere in the state-machine. |
MaikOvermars | 0:4cb1de41d049 | 509 | } |
MaikOvermars | 0:4cb1de41d049 | 510 | |
MaikOvermars | 0:4cb1de41d049 | 511 | |
MaikOvermars | 0:4cb1de41d049 | 512 | void loop_function() { |
MaikOvermars | 0:4cb1de41d049 | 513 | measure_all(); //measure all signals |
MaikOvermars | 0:4cb1de41d049 | 514 | state_machine(); //Do relevant state dependent things |
MaikOvermars | 0:4cb1de41d049 | 515 | motor_controller(); //Do not put different motor controllers in the states, because every state can re-use the same motor-controller! |
MaikOvermars | 0:4cb1de41d049 | 516 | output_all(); //Output relevant signals, messages, screen outputs, LEDs etc. |
MaikOvermars | 0:4cb1de41d049 | 517 | } |
MaikOvermars | 0:4cb1de41d049 | 518 | |
MaikOvermars | 0:4cb1de41d049 | 519 | |
MaikOvermars | 0:4cb1de41d049 | 520 | int main() |
MaikOvermars | 0:4cb1de41d049 | 521 | { |
Spekdon | 45:829a3992d689 | 522 | pc.baud(115200); |
MaikOvermars | 0:4cb1de41d049 | 523 | motor1_pwm.period_us(60); |
MaikOvermars | 0:4cb1de41d049 | 524 | motor2_pwm.period_us(60); |
MaikOvermars | 0:4cb1de41d049 | 525 | current_state = waiting; //we start in state ‘waiting’ and current_state can be accessed by all functions |
MaikOvermars | 0:4cb1de41d049 | 526 | u1 = 0.0f; //initial output to motors is 0. |
MaikOvermars | 10:7339dca7d604 | 527 | u2 = 0.0f; |
MaikOvermars | 41:e9d6fdf02074 | 528 | bqc0.add(&bq0high).add(&bq0notch).add(&bq0notch2).add(&bq0notch3).add(&bq0notch4); // filter cascade for emg 0 |
MaikOvermars | 41:e9d6fdf02074 | 529 | bqc1.add(&bq1high).add(&bq1notch).add(&bq1notch2).add(&bq1notch3).add(&bq1notch4); // filter cascade for emg 1 |
MaikOvermars | 41:e9d6fdf02074 | 530 | bqc2.add(&bq2high).add(&bq2notch).add(&bq2notch2).add(&bq2notch3).add(&bq2notch4); // filter cascade for emg 2 |
MaikOvermars | 41:e9d6fdf02074 | 531 | bqc3.add(&bq3high).add(&bq3notch).add(&bq3notch2).add(&bq3notch3).add(&bq3notch4); // filter cascade for emg 3 |
MaikOvermars | 17:1f93c83e211f | 532 | loop_ticker.attach(&loop_function, T); //Run the function loop_function 1000 times per second |
SvenD97 | 32:2596cc9156ec | 533 | led_R = 1; |
SvenD97 | 32:2596cc9156ec | 534 | led_B = 1; |
SvenD97 | 32:2596cc9156ec | 535 | led_G = 1; |
Spekdon | 45:829a3992d689 | 536 | // myservo = 1; |
Spekdon | 45:829a3992d689 | 537 | // button1.fall(&open_gripper); |
Spekdon | 45:829a3992d689 | 538 | // button2.fall(&close_gripper); |
Spekdon | 45:829a3992d689 | 539 | |
Spekdon | 45:829a3992d689 | 540 | while (true) {pc.printf("error1: %f, error2: %f, pwm1: %f, pwm2: %f, qref1: %f, qref2: %f, vx: %f, vy: %f, q1: %f, q2: %f \r\n", e1, e2, u1, u2, qref1, qref2, des_vx, des_vy, x_norm, y_norm); |
Spekdon | 45:829a3992d689 | 541 | testconfig = forwardkinematics_function(qref1,qref2); |
Spekdon | 45:829a3992d689 | 542 | //double x = testconfig[0]; |
Spekdon | 45:829a3992d689 | 543 | //double y = testconfig[1]; |
Spekdon | 45:829a3992d689 | 544 | //pc.printf("x: %f, y: %f \r\n", x,y); |
Spekdon | 45:829a3992d689 | 545 | } //Do nothing here (timing purposes) |
MaikOvermars | 0:4cb1de41d049 | 546 | } |