Werkcollege opgave 23 september BMT K9
Dependencies: Encoder HIDScope MODSERIAL mbed QEI biquadFilter
main.cpp@40:7f928b465f8d, 2015-10-21 (annotated)
- Committer:
- ThomasBNL
- Date:
- Wed Oct 21 10:02:10 2015 +0000
- Revision:
- 40:7f928b465f8d
- Parent:
- 39:9fa091753592
- Child:
- 41:9f28072c882d
- Child:
- 47:926669fe14b1
GEHELE SCRIPT: inclusief comments
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ThomasBNL | 40:7f928b465f8d | 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 2 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 3 | ///// //// ////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 4 | ///// //// ////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 5 | //////////// //////////// ////// ////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 6 | //////////// //////////// ////// ////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 7 | //////////// //////////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 8 | //////////// //////////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 9 | //////////// //////////// ////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 10 | //////////// //////////// ////// ////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 11 | //////////// //////////// ////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 12 | //////////// //////////// ////// ////// /////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 13 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 14 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 15 | /////// ////// ////// ////// ////// /////// ////// /////// ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 16 | /////// ////// ////// ////// ////// ///// ////// ///// ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 17 | /////// ///////////////// ////// ////// //////////// //// ////// //// ////// ///////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 18 | /////// ///////////////// ////// ////// //////////// /// ////// /// ////// ///////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 19 | /////// ///////////////// ////// ////// // ////// // ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 20 | /////// ///////////////// ////// ////// // ////// // ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 21 | /////// ///////////////// ////// //////////// /// ////// /// ////// ///////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 22 | /////// ///////////////// ////// ////// //////////// //// ////// //// ////// ///////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 23 | /////// ////// ////// ////// ////// ///// ////// ///// ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 24 | /////// ////// ////// ////// ////// ////// ////// ////// ////// /////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 25 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 26 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 27 | /////// /////////////// ///////////// /////// ////// /////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 28 | /////// ///////////// //////////// ///// ////// ////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 29 | /////// ////// /////////// /////////// //// ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 30 | /////// ////// ////////// // ////////// /// ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 31 | /////// ///////// //// ///////// // ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 32 | /////// //////// ////// //////// // ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 33 | /////// ////// /////// /////// /// ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 34 | /////// ////// ////// ////// //// ////// ///// ///////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 35 | /////// ////// //////////// ///// ///// ////// ////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 36 | /////// ////// ////////////// //// ////// ////// /////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 37 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 38 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 39 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////| |
ThomasBNL | 40:7f928b465f8d | 40 | // Groep 12: The Chenne Band // |
ThomasBNL | 40:7f928b465f8d | 41 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 42 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 43 | // || [Table of content] || |
ThomasBNL | 40:7f928b465f8d | 44 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 45 | // |
ThomasBNL | 40:7f928b465f8d | 46 | // Introduction |
ThomasBNL | 40:7f928b465f8d | 47 | |
ThomasBNL | 40:7f928b465f8d | 48 | // Libraries................................................. |
ThomasBNL | 40:7f928b465f8d | 49 | |
ThomasBNL | 40:7f928b465f8d | 50 | // |
ThomasBNL | 40:7f928b465f8d | 51 | // |
ThomasBNL | 40:7f928b465f8d | 52 | // |
ThomasBNL | 40:7f928b465f8d | 53 | // |
ThomasBNL | 40:7f928b465f8d | 54 | |
ThomasBNL | 40:7f928b465f8d | 55 | |
ThomasBNL | 40:7f928b465f8d | 56 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 57 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 58 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 59 | // || [Libraries] || |
ThomasBNL | 40:7f928b465f8d | 60 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 61 | // |
ThomasBNL | 40:7f928b465f8d | 62 | |
bscheltinga | 0:fe3896c6eeb0 | 63 | #include "mbed.h" |
bscheltinga | 12:0a079e86348e | 64 | #include "HIDScope.h" |
ThomasBNL | 40:7f928b465f8d | 65 | #include "QEI.h" |
bscheltinga | 0:fe3896c6eeb0 | 66 | #include "MODSERIAL.h" |
ThomasBNL | 40:7f928b465f8d | 67 | #include "biquadFilter.h" |
ThomasBNL | 40:7f928b465f8d | 68 | #include "encoder.h" |
ThomasBNL | 40:7f928b465f8d | 69 | |
ThomasBNL | 40:7f928b465f8d | 70 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 71 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 72 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 73 | // || [FLOW AND DEBUGGING TOOLS] || |
ThomasBNL | 40:7f928b465f8d | 74 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 75 | |
ThomasBNL | 40:7f928b465f8d | 76 | //HIDScope scope(1); // DEBUG : HIDSCOPE has the ability to display signals over time and can be used to monitor signals |
ThomasBNL | 40:7f928b465f8d | 77 | |
ThomasBNL | 40:7f928b465f8d | 78 | MODSERIAL pc(USBTX,USBRX); // MODSERIAL : makes it possible to send messages to the computer (eg. inside Putty) |
ThomasBNL | 40:7f928b465f8d | 79 | |
ThomasBNL | 40:7f928b465f8d | 80 | DigitalOut debug_led_red(LED_RED) , debug_led_green(LED_GREEN) , debug_led_blue(LED_BLUE); // DEBUG : Red, Blue and Green LED |
ThomasBNL | 40:7f928b465f8d | 81 | DigitalIn buttonL1(PTC6) , buttonL2(PTA4) , buttonH1(D2) , buttonH2(D1); // DEBUG/CALIBRATION: 4 buttons for calibration and debugging |
ThomasBNL | 40:7f928b465f8d | 82 | Ticker looptimer; // FLOW : Ticker called looptimer to set a looptimerflag that puts the volatile bool control_go to true every sample |
ThomasBNL | 40:7f928b465f8d | 83 | |
ThomasBNL | 40:7f928b465f8d | 84 | volatile bool control_go = false, sample = false, sample_error, sample_error_strike; // EMG : booleans for controlling sample time of moving average and emg signal |
ThomasBNL | 40:7f928b465f8d | 85 | volatile bool looptimerflag; // CONTROLLER : boolean that controls the sample time of the whole controller |
ThomasBNL | 40:7f928b465f8d | 86 | |
ThomasBNL | 40:7f928b465f8d | 87 | double e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, // ACTION : in the action mechanism these variables calculate a current moving average error |
ThomasBNL | 40:7f928b465f8d | 88 | e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, |
ThomasBNL | 40:7f928b465f8d | 89 | e8, e7, e6, e5, e4, e3, e2, e1, er, error_count, error_turn_average, error_strike_average; |
ThomasBNL | 40:7f928b465f8d | 90 | |
ThomasBNL | 40:7f928b465f8d | 91 | AnalogIn input1(A0), input2(A1); // EMG : Two AnalogIn EMG inputs, input1 (Left bicep), input2 (Right bicep) |
ThomasBNL | 40:7f928b465f8d | 92 | |
ThomasBNL | 40:7f928b465f8d | 93 | double Sample_EMG_L_1, Sample_EMG_L_2, Sample_EMG_L_3, Sample_EMG_L_4, Sample_EMG_L_5, Sample_EMG_L_6,// EMG : Left/Right bicep moving average memory variables (moving average is calculated over ten values) |
ThomasBNL | 40:7f928b465f8d | 94 | Sample_EMG_L_7, Sample_EMG_L_8, Sample_EMG_L_9, Sample_EMG_L_10, moving_average_left; |
ThomasBNL | 40:7f928b465f8d | 95 | double Sample_EMG_R_1, Sample_EMG_R_2, Sample_EMG_R_3, Sample_EMG_R_4, Sample_EMG_R_5, Sample_EMG_R_6, |
ThomasBNL | 40:7f928b465f8d | 96 | Sample_EMG_R_7, Sample_EMG_R_8, Sample_EMG_R_9, Sample_EMG_R_10, moving_average_right; |
ThomasBNL | 40:7f928b465f8d | 97 | |
ThomasBNL | 40:7f928b465f8d | 98 | double minimum_L, maximum_L, EMG_L_min, EMG_L_max; // EMG CALIBRATION: variables that are used during the EMG calibration |
ThomasBNL | 40:7f928b465f8d | 99 | double minimum_R, maximum_R, EMG_R_min, EMG_R_max; |
ThomasBNL | 40:7f928b465f8d | 100 | |
ThomasBNL | 40:7f928b465f8d | 101 | double EMG_left_Bicep, EMG_Left_Bicep_filtered, |
ThomasBNL | 40:7f928b465f8d | 102 | EMG_Left_Bicep_filtered_notch_1, EMG_Right_Bicep_filtered_notch_1; |
ThomasBNL | 40:7f928b465f8d | 103 | double EMG_Right_Bicep, EMG_Left_Bicep_filtered_notch_2, |
ThomasBNL | 40:7f928b465f8d | 104 | EMG_Right_Bicep_filtered_notch_2, EMG_Right_Bicep_filtered; |
ThomasBNL | 40:7f928b465f8d | 105 | |
ThomasBNL | 40:7f928b465f8d | 106 | double Threshold_Bicep_Left_1, Threshold_Bicep_Left_2, // EMG ACTION: variables to witch the threshold values calculated after the calibration get asigned to |
ThomasBNL | 40:7f928b465f8d | 107 | Threshold_Bicep_Right_1, Threshold_Bicep_Right_2; |
ThomasBNL | 40:7f928b465f8d | 108 | |
ThomasBNL | 40:7f928b465f8d | 109 | double n=0; double c=0; double k=0; double p=0; // FLOW : these flow variables are assigned to certain values through out the script values in order to regulate the flow of the script |
bscheltinga | 0:fe3896c6eeb0 | 110 | |
ThomasBNL | 40:7f928b465f8d | 111 | // FILTERS EMG |
ThomasBNL | 40:7f928b465f8d | 112 | const double low_b0 = 0.05892937945281792 , low_b1 = 0.11785875890563584 , low_b2 = 0.05892937945281792, // Notch 1 LOW : VIA online biquad calculator Lowpass 520-48-0.7071-6 |
ThomasBNL | 40:7f928b465f8d | 113 | low_a1 = -1.205716572226748 , low_a2 = 0.44143409003801976 ; |
ThomasBNL | 40:7f928b465f8d | 114 | const double high_b0 = 0.6389437261127494 , high_b1 = -1.2778874522254988 , high_b2 = 0.6389437261127494, // Notch 2 HIGH: VIA online biquad calculator Highpass 520-52-0.7071-6 |
ThomasBNL | 40:7f928b465f8d | 115 | high_a1 = -1.1429772843080923 , high_a2 = 0.41279762014290533 ; |
ThomasBNL | 40:7f928b465f8d | 116 | const double high_b0_HP = 0.84855234544818812 , high_b1_HP = -1.6970469089637623 , high_b2_HP = 0.8485234544818812, // HIGHPASS : NOG OPZOEKEN!! : >25Hz? sample rate 512Hz |
ThomasBNL | 40:7f928b465f8d | 117 | high_a1_HP = -1.6564788473046559 , high_a2_HP = 0.7376149706228688 ; |
ThomasBNL | 40:7f928b465f8d | 118 | const double low_b0_LP = 0.0013067079602315681, low_b1_LP = 0.0026134159204631363, low_b2_LP = 0.0013067079602315681, // LOWPASS : NOG OPZOEKEN!! <5-10 Hz? sample rate 512Hz |
ThomasBNL | 40:7f928b465f8d | 119 | low_a1_LP = -1.9238184798980429 , low_a2_LP = 0.9290453117389691 ; |
ThomasBNL | 40:7f928b465f8d | 120 | |
ThomasBNL | 40:7f928b465f8d | 121 | //Left bicep Filters |
ThomasBNL | 40:7f928b465f8d | 122 | biquadFilter highpassfilter_1(high_a1_HP, high_a2_HP, high_b0_HP, high_b1_HP, high_b2_HP); // EMG : moeten nog waardes voor gemaakt worden? (>25Hz doorlaten) |
ThomasBNL | 40:7f928b465f8d | 123 | biquadFilter notchL1(high_a1, high_a2, high_b0, high_b1, high_b2); // EMG : moeten nog waardes voor gemaakt worden (>52Hz doorlaten) |
ThomasBNL | 40:7f928b465f8d | 124 | biquadFilter notchL2(low_a1, low_a2, low_b0, low_b1, low_b2); // EMG : moeten nog waardes voor gemaakt worden (<48Hz doorlaten) |
ThomasBNL | 40:7f928b465f8d | 125 | biquadFilter lowpassfilter_1(low_a1_LP, low_a2_LP, low_b0_LP, low_b1_LP, low_b2_LP); |
ThomasBNL | 40:7f928b465f8d | 126 | |
ThomasBNL | 40:7f928b465f8d | 127 | // Right bicep Filters |
ThomasBNL | 40:7f928b465f8d | 128 | biquadFilter highpassfilter_2(high_a1_HP, high_a2_HP, high_b0_HP, high_b1_HP, high_b2_HP); // EMG : moeten nog waardes voor gemaakt worden? |
ThomasBNL | 40:7f928b465f8d | 129 | biquadFilter notchR1(high_a1, high_a2, high_b0, high_b1, high_b2); // EMG : moeten nog waardes voor gemaakt worden |
ThomasBNL | 40:7f928b465f8d | 130 | biquadFilter notchR2(low_a1, low_a2, low_b0, low_b1, low_b2); // EMG : moeten nog waardes voor gemaakt worden |
ThomasBNL | 40:7f928b465f8d | 131 | biquadFilter lowpassfilter_2(low_a1_LP, low_a2_LP, low_b0_LP, low_b1_LP, low_b2_LP); // EMG : moeten nog waardes voor gemaakt worden |
ThomasBNL | 40:7f928b465f8d | 132 | |
ThomasBNL | 36:f29a36683b1a | 133 | |
ThomasBNL | 40:7f928b465f8d | 134 | // MOTORS |
ThomasBNL | 40:7f928b465f8d | 135 | QEI motor_turn(D12,D13,NC,32); QEI motor_strike(D9,D10,NC,32); // TURN - STRIKE : Encoder for motor |
ThomasBNL | 40:7f928b465f8d | 136 | PwmOut pwm_motor_turn(D5); PwmOut pwm_motor_strike(D6); // TURN - STRIKE : Pwm for motor |
ThomasBNL | 40:7f928b465f8d | 137 | DigitalOut motordirection_turn(D4); DigitalOut motordirection_strike(D7); // TURN - STRIKE : Direction of the motor |
ThomasBNL | 40:7f928b465f8d | 138 | |
ThomasBNL | 40:7f928b465f8d | 139 | double integrate_error_turn=0, previous_error_turn=0; double integrate_error_strike=0, previous_error_strike=0; // TURN - STRIKE : previous error and integration error motor |
ThomasBNL | 40:7f928b465f8d | 140 | |
ThomasBNL | 40:7f928b465f8d | 141 | double position_turn, error_turn, reference_turn; double position_strike, error_strike, reference_strike; |
ThomasBNL | 40:7f928b465f8d | 142 | double P_gain_turn; double I_gain_turn; double D_gain_turn; double P_gain_strike; double I_gain_strike; double D_gain_strike; // TURN - STRIKE : these gains get multiplied with the error inside the PID controller // TURN: these gains get multiplied with the error inside the PID controller |
ThomasBNL | 40:7f928b465f8d | 143 | double pwm_motor_turn_P, pwm_motor_turn_I, pwm_motor_turn_D; double pwm_motor_strike_P, pwm_motor_strike_I, pwm_motor_strike_D; // TURN - STRIKE : variables that store the P, I and D action part of the error |
ThomasBNL | 40:7f928b465f8d | 144 | double pwm_to_motor_turn; double pwm_to_motor_strike; // TURN - STRIKE : variable that is constructed by summing the values of the P, I and D action |
ThomasBNL | 40:7f928b465f8d | 145 | |
ThomasBNL | 40:7f928b465f8d | 146 | |
ThomasBNL | 40:7f928b465f8d | 147 | // FILTER: D-action |
ThomasBNL | 40:7f928b465f8d | 148 | const double a0 = 0.000332685098529822, a1 = 0.000665370197059644, a2 = 0.000332685098529822, b1 = -1.9625271814290315, b2 = 0.9638579218231508; |
ThomasBNL | 40:7f928b465f8d | 149 | // const double a0 = 0.000021080713160785432, a1 = 0.000042161426321570865, a2 = 0.000021080713160785432, b1 = -1.990754082898736, b2 = 0.9908384057513788; (0.75Hz) |
ThomasBNL | 40:7f928b465f8d | 150 | // const double a0 = 0.003543360146633312, a1 = 0.007086720293266624, a2 = 0.003543360146633312, b1 = -1.8704759567901301, b2 = 0.8846493973766635; (10Hz) |
ThomasBNL | 40:7f928b465f8d | 151 | // const double a0 = 0.0009129521023626334, a1 = 0.0018259042047252668, a2 = 0.0009129521023626334, b1 = -1.9368516414202819, b2 = 0.9405034498297324; (5Hz) |
ThomasBNL | 40:7f928b465f8d | 152 | biquadFilter Lowpassfilter_derivative(b1,b2,a0,a1,a2); // BiquadFilter used for the filtering of the Derivative action of the PID-action |
ThomasBNL | 40:7f928b465f8d | 153 | |
ThomasBNL | 40:7f928b465f8d | 154 | const double cw=0; // MOTOR: turn direction zero is clockwise (front view) |
ThomasBNL | 40:7f928b465f8d | 155 | const double ccw=1; // MOTOR: turn direction one is counterclockwise (front view) |
sigert | 37:6c04c15d9bbe | 156 | const double off=1; // Led off |
sigert | 37:6c04c15d9bbe | 157 | const double on=0; // Led on |
ThomasBNL | 40:7f928b465f8d | 158 | const int Fs = 512; // sampling frequency (512 Hz) |
ThomasBNL | 40:7f928b465f8d | 159 | const double sample_time = 0.001953125; // duration of one sample |
ThomasBNL | 40:7f928b465f8d | 160 | double conversion_counts_to_degrees=0.085877862594198; // Calculation conversion counts to degrees |
ThomasBNL | 40:7f928b465f8d | 161 | // gear ratio motor = 131 |
ThomasBNL | 40:7f928b465f8d | 162 | // ticks per magnet rotation = 32 (X2 Encoder) |
ThomasBNL | 40:7f928b465f8d | 163 | // One revolution = 360 degrees |
ThomasBNL | 40:7f928b465f8d | 164 | // degrees_per_encoder_tick = 360/(gear_ratio*ticks_per_magnet_rotation)=360/131*32=0.085877862594198 |
ThomasBNL | 40:7f928b465f8d | 165 | const double change_one_bottle=45; |
ThomasBNL | 40:7f928b465f8d | 166 | const double Hit=60; // position when bottle is hit |
bscheltinga | 15:7870f7912904 | 167 | |
ThomasBNL | 40:7f928b465f8d | 168 | |
ThomasBNL | 40:7f928b465f8d | 169 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 170 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 171 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 172 | // || [FUNCTIONS USED] || |
ThomasBNL | 40:7f928b465f8d | 173 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 174 | void execute_plant_turn (); // TURN : Check error -> execute PID controller -> write pwm and direction to motor |
ThomasBNL | 40:7f928b465f8d | 175 | void execute_plant_strike (); |
ThomasBNL | 40:7f928b465f8d | 176 | double PID_control (double reference, double position, double &integrate_error, |
ThomasBNL | 40:7f928b465f8d | 177 | double sample_time, double &previous_error, |
ThomasBNL | 40:7f928b465f8d | 178 | double P_gain, double I_gain, double D_gain); |
ThomasBNL | 40:7f928b465f8d | 179 | |
ThomasBNL | 40:7f928b465f8d | 180 | void keep_in_range (double * in, double min, double max); // Put in a value and makes sure that the value stays between assigned boundary's |
ThomasBNL | 40:7f928b465f8d | 181 | void setlooptimerflag (void); // Sets looptimerflag volatile bool to true |
ThomasBNL | 40:7f928b465f8d | 182 | |
ThomasBNL | 40:7f928b465f8d | 183 | void deactivate_PID_Controller (double& P_gain, double& I_gain, double& D_gain); // STRIKE/TURN: Deactivate PID Controller |
bscheltinga | 15:7870f7912904 | 184 | |
ThomasBNL | 40:7f928b465f8d | 185 | void activate_PID_Controller_strike (double& P_gain, double& I_gain, double& D_gain); // STRIKE: Activate PID Controller |
ThomasBNL | 40:7f928b465f8d | 186 | void activate_PID_Controller_turn (double& P_gain, double& I_gain, double& D_gain); // TURN : Activate PID Controller |
ThomasBNL | 40:7f928b465f8d | 187 | |
ThomasBNL | 40:7f928b465f8d | 188 | void Change_Turn_Position_Left (double& reference, double change_one_bottle); // TURN : Change Reference position one bottle to the left |
ThomasBNL | 40:7f928b465f8d | 189 | void Change_Turn_Position_Right (double& reference, double change_one_bottle); // TURN : Change Reference position one bottle to the right |
ThomasBNL | 40:7f928b465f8d | 190 | |
ThomasBNL | 40:7f928b465f8d | 191 | void countdown_from_5(); // PUTTY : 5 second countdown inside |
ThomasBNL | 40:7f928b465f8d | 192 | void calibrate_motor(); // MOTOR : Calibrate starting position motor |
ThomasBNL | 40:7f928b465f8d | 193 | void calibration(); // EMG : Calibrate the EMG signal (calculate min and max signal and determine threshold values) |
ThomasBNL | 40:7f928b465f8d | 194 | void Filter(); // EMG : Filter the incoming EMG signals |
ThomasBNL | 40:7f928b465f8d | 195 | void sample_filter(); // EMG : Calculate moving average (10 samples, one sample per 25 samples) using sample_filter => moving average over +-0.5 seconds |
ThomasBNL | 40:7f928b465f8d | 196 | void take_sample(); // EMG : Take a sample once every 25 samples that's used to calculate the moving average |
ThomasBNL | 40:7f928b465f8d | 197 | void ControlGo(); // EMG : function that gets a ticker attached and sets a certain loop to true every sample |
ThomasBNL | 40:7f928b465f8d | 198 | |
ThomasBNL | 40:7f928b465f8d | 199 | void red();void blue();void green();void white();void yellow();void cyan();void purple(); void black(); // DEBUG: Different color LEDS |
ThomasBNL | 40:7f928b465f8d | 200 | |
ThomasBNL | 40:7f928b465f8d | 201 | void calibrate_potmeter(); // DEBUG/TEST : Calibration thresholds with potmeter |
bscheltinga | 22:14abcfdd1554 | 202 | |
ThomasBNL | 40:7f928b465f8d | 203 | void Action_Controller(); // CONTROLLER : Decides and executes if the robot needs to turn to the left, right or strike based on the currently measured EMG signal |
ThomasBNL | 40:7f928b465f8d | 204 | |
ThomasBNL | 40:7f928b465f8d | 205 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 206 | /////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 207 | // // |
ThomasBNL | 40:7f928b465f8d | 208 | ///////////////////////////////////////////// [MAIN FUNCTION] ///////////////////////////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 209 | // // |
ThomasBNL | 40:7f928b465f8d | 210 | /////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 211 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 212 | int main() { |
ThomasBNL | 40:7f928b465f8d | 213 | |
ThomasBNL | 40:7f928b465f8d | 214 | black(); // No LED active |
ThomasBNL | 40:7f928b465f8d | 215 | pc.printf("Start of code \n\r"); |
ThomasBNL | 40:7f928b465f8d | 216 | |
ThomasBNL | 40:7f928b465f8d | 217 | pc.baud(115200); // PC contactspeed : Set the baudrate |
ThomasBNL | 40:7f928b465f8d | 218 | |
ThomasBNL | 40:7f928b465f8d | 219 | red(); |
ThomasBNL | 40:7f928b465f8d | 220 | calibrate_motor(); // MOTOR CALIBRATE : The motor starting position (RED LED) |
ThomasBNL | 40:7f928b465f8d | 221 | |
ThomasBNL | 40:7f928b465f8d | 222 | //blue(); |
ThomasBNL | 40:7f928b465f8d | 223 | calibration(); // EMG CALIBRATE : The motor starting position (BLUE LED) |
ThomasBNL | 40:7f928b465f8d | 224 | |
ThomasBNL | 40:7f928b465f8d | 225 | calibrate_potmeter(); // DEBUG/TEST : Calibration thresholds with potmeter |
ThomasBNL | 40:7f928b465f8d | 226 | |
ThomasBNL | 40:7f928b465f8d | 227 | looptimer.attach(setlooptimerflag,(float)1/Fs); // CONTROLLER FLOW : Calls the looptimer flag every sample |
ThomasBNL | 40:7f928b465f8d | 228 | |
ThomasBNL | 40:7f928b465f8d | 229 | black(); |
ThomasBNL | 40:7f928b465f8d | 230 | wait (3); // REST before starting position |
ThomasBNL | 40:7f928b465f8d | 231 | |
ThomasBNL | 40:7f928b465f8d | 232 | green(); // START CONTROLLOOP (GREEN LED) |
ThomasBNL | 40:7f928b465f8d | 233 | |
ThomasBNL | 40:7f928b465f8d | 234 | while(1) |
ThomasBNL | 40:7f928b465f8d | 235 | { |
ThomasBNL | 40:7f928b465f8d | 236 | Action_Controller(); // CONTROLLER : Decides and executes if the robot needs to turn to the left, right or strike based on the currently measured EMG signal |
ThomasBNL | 40:7f928b465f8d | 237 | } |
ThomasBNL | 40:7f928b465f8d | 238 | } |
sigert | 37:6c04c15d9bbe | 239 | |
ThomasBNL | 40:7f928b465f8d | 240 | //============================================================================================================================ |
ThomasBNL | 40:7f928b465f8d | 241 | /////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 242 | // // |
ThomasBNL | 40:7f928b465f8d | 243 | ///////////////////////////////////////////// [FUNCTIONS DESCRIBED] ///////////////////////////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 244 | // // |
ThomasBNL | 40:7f928b465f8d | 245 | /////////////////////////////// |
ThomasBNL | 40:7f928b465f8d | 246 | //============================================================================================================================ |
bscheltinga | 20:d5f5c60adc43 | 247 | |
ThomasBNL | 27:85e5d36bb6c5 | 248 | |
ThomasBNL | 40:7f928b465f8d | 249 | // FUNCTION 1 ___________________________ |
ThomasBNL | 40:7f928b465f8d | 250 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 251 | // || [ACTIONCONTROLLER] || |
ThomasBNL | 40:7f928b465f8d | 252 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 253 | void Action_Controller() |
ThomasBNL | 40:7f928b465f8d | 254 | { // Start while loop |
ThomasBNL | 40:7f928b465f8d | 255 | while(looptimerflag != true); |
ThomasBNL | 40:7f928b465f8d | 256 | looptimerflag = false; |
ThomasBNL | 40:7f928b465f8d | 257 | |
ThomasBNL | 40:7f928b465f8d | 258 | Nieuwe_actie: // Return here if action left, right or strike is executed |
ThomasBNL | 40:7f928b465f8d | 259 | green(); // GREEN LED: ready to fire again |
ThomasBNL | 40:7f928b465f8d | 260 | |
ThomasBNL | 40:7f928b465f8d | 261 | //// sample_filter(); // TIJDELIJK UIT: What is the current EMG value |
ThomasBNL | 40:7f928b465f8d | 262 | |
ThomasBNL | 40:7f928b465f8d | 263 | // POTMETER: SIMULATE EMG SIGNAL |
ThomasBNL | 40:7f928b465f8d | 264 | moving_average_left = (input1.read())*100; // EMG Right bicep (tussen nul en 100%) // DEBUG TEST TOOL: substitute EMG input for potmeter inputs |
ThomasBNL | 40:7f928b465f8d | 265 | moving_average_right = (input2.read())*100; // EMG Left bicep (tussen nul en 100%) // DEBUG TEST TOOL: substitute EMG input for potmeter inputs |
ThomasBNL | 40:7f928b465f8d | 266 | pc.printf("mov_r = %f, mov_l = %f \n\r", moving_average_right, moving_average_left); |
ThomasBNL | 36:f29a36683b1a | 267 | |
ThomasBNL | 40:7f928b465f8d | 268 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 269 | // : [Action 2: Turn Left] : |
ThomasBNL | 40:7f928b465f8d | 270 | // :___________________________: |
ThomasBNL | 40:7f928b465f8d | 271 | // |
ThomasBNL | 40:7f928b465f8d | 272 | // //Blue (strike) - Yellow (return)\\ |
ThomasBNL | 36:f29a36683b1a | 273 | |
ThomasBNL | 40:7f928b465f8d | 274 | // TEMPORARY: TO TEST STRIKE MECHANISM |
ThomasBNL | 40:7f928b465f8d | 275 | moving_average_left = 40; // TIJDELIJK PID TEST |
ThomasBNL | 40:7f928b465f8d | 276 | moving_average_right = 40; // TIJDELIJK PID TEST |
ThomasBNL | 40:7f928b465f8d | 277 | |
ThomasBNL | 40:7f928b465f8d | 278 | if (moving_average_right > Threshold_Bicep_Right_1 && moving_average_left > Threshold_Bicep_Left_1) // Statement 1 (if both are satisfied execute) |
ThomasBNL | 40:7f928b465f8d | 279 | { // Statement 1 start |
ThomasBNL | 40:7f928b465f8d | 280 | blue(); n=0; k=0; p=0; |
ThomasBNL | 40:7f928b465f8d | 281 | pc.printf("Slag \n\r"); |
ThomasBNL | 40:7f928b465f8d | 282 | wait(0.5); // TIJDELIJK?? |
ThomasBNL | 40:7f928b465f8d | 283 | |
ThomasBNL | 40:7f928b465f8d | 284 | if(moving_average_left > Threshold_Bicep_Left_1 && moving_average_right > Threshold_Bicep_Right_1) // Check if statement 1 is still true then continue and start Strike |
ThomasBNL | 40:7f928b465f8d | 285 | { // Statement 2 start |
ThomasBNL | 40:7f928b465f8d | 286 | while(1) |
ThomasBNL | 40:7f928b465f8d | 287 | { // inf while loop strike until finished start |
ThomasBNL | 40:7f928b465f8d | 288 | if (n==0) // Change the reference point of the PID Strike controller |
ThomasBNL | 40:7f928b465f8d | 289 | { reference_strike=90; n=1; error_count=0; } // Execute once (n is set to one and only gets executed if n equals zero) |
ThomasBNL | 40:7f928b465f8d | 290 | |
ThomasBNL | 40:7f928b465f8d | 291 | if (looptimerflag == true) // Loop that executes the strike controller every sample (inside the controller the loudness is regulated) |
ThomasBNL | 40:7f928b465f8d | 292 | { |
ThomasBNL | 40:7f928b465f8d | 293 | looptimerflag=false; |
ThomasBNL | 40:7f928b465f8d | 294 | activate_PID_Controller_strike(P_gain_strike, I_gain_strike, D_gain_strike); |
ThomasBNL | 40:7f928b465f8d | 295 | execute_plant_strike(); |
ThomasBNL | 40:7f928b465f8d | 296 | } |
ThomasBNL | 40:7f928b465f8d | 297 | |
ThomasBNL | 40:7f928b465f8d | 298 | if (fabs(position_strike)>Hit) // If the bottle is hit (hit if the position is greater than the set hit point) then initiate return |
ThomasBNL | 40:7f928b465f8d | 299 | { // Statement Return start |
ThomasBNL | 40:7f928b465f8d | 300 | while(1) |
ThomasBNL | 40:7f928b465f8d | 301 | { // inf while loop return after strike start |
ThomasBNL | 40:7f928b465f8d | 302 | yellow(); |
ThomasBNL | 40:7f928b465f8d | 303 | if(k==0) // Change reference point of the PID Strike controller back to the original position |
ThomasBNL | 40:7f928b465f8d | 304 | { |
ThomasBNL | 40:7f928b465f8d | 305 | p=1; reference_strike=0; error_count=0; k=1; |
ThomasBNL | 40:7f928b465f8d | 306 | pc.printf("return \n\r"); |
ThomasBNL | 40:7f928b465f8d | 307 | } |
ThomasBNL | 40:7f928b465f8d | 308 | //pc.printf("ref_t = %f, e_cnt= %f e_av=%f \n\r k=%f, er_cnt= %f", reference_strike, error_strike, error_strike_average, k, error_count); // LINE USED FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 309 | |
ThomasBNL | 40:7f928b465f8d | 310 | if (looptimerflag == true) // Loop that executes the strike controller every sample (loudness is deactivated by the value of p) |
ThomasBNL | 40:7f928b465f8d | 311 | { |
ThomasBNL | 40:7f928b465f8d | 312 | looptimerflag=false; |
ThomasBNL | 40:7f928b465f8d | 313 | activate_PID_Controller_strike(P_gain_strike, I_gain_strike, D_gain_strike); |
ThomasBNL | 40:7f928b465f8d | 314 | execute_plant_strike(); |
ThomasBNL | 40:7f928b465f8d | 315 | } |
ThomasBNL | 40:7f928b465f8d | 316 | |
ThomasBNL | 40:7f928b465f8d | 317 | printf(" %f \n\r",error_strike_average); // LINE USED FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 318 | |
ThomasBNL | 40:7f928b465f8d | 319 | if (fabs(error_strike_average) < 0.5 && error_count>100) // If error is small enough and at least 100 samples have passed since the return execute new action |
ThomasBNL | 40:7f928b465f8d | 320 | { |
ThomasBNL | 40:7f928b465f8d | 321 | yellow(); |
ThomasBNL | 40:7f928b465f8d | 322 | pc.printf("new action \n\r"); |
ThomasBNL | 40:7f928b465f8d | 323 | deactivate_PID_Controller(P_gain_strike, I_gain_strike, D_gain_strike); |
ThomasBNL | 40:7f928b465f8d | 324 | execute_plant_strike(); |
ThomasBNL | 40:7f928b465f8d | 325 | goto Nieuwe_actie; |
ThomasBNL | 40:7f928b465f8d | 326 | } |
ThomasBNL | 40:7f928b465f8d | 327 | } // inf while loop return after strike end |
ThomasBNL | 40:7f928b465f8d | 328 | } // Statement Return end |
ThomasBNL | 40:7f928b465f8d | 329 | } // inf while loop strike until finished end |
ThomasBNL | 40:7f928b465f8d | 330 | } // Statement 2 end |
ThomasBNL | 40:7f928b465f8d | 331 | } // Statement 1 end |
ThomasBNL | 40:7f928b465f8d | 332 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 333 | // : [Action 2: Turn Left] : |
ThomasBNL | 40:7f928b465f8d | 334 | // :___________________________: |
ThomasBNL | 40:7f928b465f8d | 335 | // |
ThomasBNL | 40:7f928b465f8d | 336 | // //Yellow\\ |
ThomasBNL | 36:f29a36683b1a | 337 | |
ThomasBNL | 40:7f928b465f8d | 338 | if (moving_average_left > Threshold_Bicep_Left_2 && moving_average_right < Threshold_Bicep_Right_1) |
ThomasBNL | 40:7f928b465f8d | 339 | { |
ThomasBNL | 40:7f928b465f8d | 340 | yellow(); n=0; |
ThomasBNL | 40:7f928b465f8d | 341 | pc.printf("LEFT \n\r"); |
ThomasBNL | 40:7f928b465f8d | 342 | wait(2); // TIJDELIJK |
ThomasBNL | 40:7f928b465f8d | 343 | |
ThomasBNL | 40:7f928b465f8d | 344 | while(moving_average_left > Threshold_Bicep_Left_1 && moving_average_right < Threshold_Bicep_Right_1) |
ThomasBNL | 40:7f928b465f8d | 345 | { |
ThomasBNL | 40:7f928b465f8d | 346 | if (n==0) |
ThomasBNL | 40:7f928b465f8d | 347 | { |
ThomasBNL | 40:7f928b465f8d | 348 | Change_Turn_Position_Left(reference_turn, change_one_bottle); |
ThomasBNL | 40:7f928b465f8d | 349 | n=1; error_count=0; |
ThomasBNL | 40:7f928b465f8d | 350 | } |
ThomasBNL | 40:7f928b465f8d | 351 | |
ThomasBNL | 40:7f928b465f8d | 352 | // pc.printf("ref_t = %f, e_cnt= %f e_av=%f \n\r", reference_turn, error_count, error_turn_average); // LINE USED FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 353 | |
ThomasBNL | 40:7f928b465f8d | 354 | if (looptimerflag == true) |
ThomasBNL | 40:7f928b465f8d | 355 | { |
ThomasBNL | 40:7f928b465f8d | 356 | looptimerflag=false; |
ThomasBNL | 40:7f928b465f8d | 357 | activate_PID_Controller_turn(P_gain_turn, I_gain_turn, D_gain_turn); |
ThomasBNL | 40:7f928b465f8d | 358 | execute_plant_turn(); |
ThomasBNL | 40:7f928b465f8d | 359 | } |
ThomasBNL | 40:7f928b465f8d | 360 | |
ThomasBNL | 40:7f928b465f8d | 361 | if (fabs(error_turn_average) < 1 && error_count>250) |
ThomasBNL | 40:7f928b465f8d | 362 | { |
ThomasBNL | 40:7f928b465f8d | 363 | pc.printf("new action \n\r"); |
ThomasBNL | 40:7f928b465f8d | 364 | deactivate_PID_Controller(P_gain_turn, I_gain_turn, D_gain_turn); |
ThomasBNL | 40:7f928b465f8d | 365 | execute_plant_turn(); |
ThomasBNL | 40:7f928b465f8d | 366 | goto Nieuwe_actie; |
ThomasBNL | 40:7f928b465f8d | 367 | } |
ThomasBNL | 40:7f928b465f8d | 368 | } |
ThomasBNL | 40:7f928b465f8d | 369 | } |
ThomasBNL | 40:7f928b465f8d | 370 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 371 | // : [Action 3: Turn Right] : |
ThomasBNL | 40:7f928b465f8d | 372 | // :___________________________: |
ThomasBNL | 40:7f928b465f8d | 373 | // |
ThomasBNL | 40:7f928b465f8d | 374 | // //Purple\\ |
ThomasBNL | 36:f29a36683b1a | 375 | |
ThomasBNL | 40:7f928b465f8d | 376 | if (moving_average_right > Threshold_Bicep_Right_2 && moving_average_left < Threshold_Bicep_Left_1) |
ThomasBNL | 40:7f928b465f8d | 377 | { |
ThomasBNL | 40:7f928b465f8d | 378 | purple(); n=0; |
ThomasBNL | 40:7f928b465f8d | 379 | pc.printf("Right \n\r"); |
ThomasBNL | 40:7f928b465f8d | 380 | wait(2); // TIJDELIJK |
ThomasBNL | 40:7f928b465f8d | 381 | |
ThomasBNL | 40:7f928b465f8d | 382 | while(moving_average_right > Threshold_Bicep_Right_1 && moving_average_left < Threshold_Bicep_Left_1) |
ThomasBNL | 40:7f928b465f8d | 383 | { |
ThomasBNL | 40:7f928b465f8d | 384 | if (n==0) |
ThomasBNL | 40:7f928b465f8d | 385 | { |
ThomasBNL | 40:7f928b465f8d | 386 | Change_Turn_Position_Right(reference_turn, change_one_bottle); |
ThomasBNL | 40:7f928b465f8d | 387 | n=1; error_count=0; |
ThomasBNL | 40:7f928b465f8d | 388 | } |
ThomasBNL | 40:7f928b465f8d | 389 | |
ThomasBNL | 40:7f928b465f8d | 390 | // pc.printf("ref_t = %f, e_cnt= %f e_av=%f \n\r", reference_turn, error_count, error_turn_average); // LINE USED FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 391 | |
ThomasBNL | 40:7f928b465f8d | 392 | if (looptimerflag == true) |
ThomasBNL | 40:7f928b465f8d | 393 | { |
ThomasBNL | 40:7f928b465f8d | 394 | looptimerflag=false; |
ThomasBNL | 40:7f928b465f8d | 395 | activate_PID_Controller_turn(P_gain_turn, I_gain_turn, D_gain_turn); |
ThomasBNL | 40:7f928b465f8d | 396 | execute_plant_turn(); |
ThomasBNL | 40:7f928b465f8d | 397 | } |
ThomasBNL | 40:7f928b465f8d | 398 | |
ThomasBNL | 40:7f928b465f8d | 399 | if (fabs(error_turn_average) < 1 && error_count>250) |
ThomasBNL | 40:7f928b465f8d | 400 | { |
ThomasBNL | 40:7f928b465f8d | 401 | pc.printf("new action \n\r"); |
ThomasBNL | 40:7f928b465f8d | 402 | deactivate_PID_Controller(P_gain_turn, I_gain_turn, D_gain_turn); |
ThomasBNL | 40:7f928b465f8d | 403 | execute_plant_turn(); |
ThomasBNL | 40:7f928b465f8d | 404 | goto Nieuwe_actie; |
ThomasBNL | 40:7f928b465f8d | 405 | } |
ThomasBNL | 40:7f928b465f8d | 406 | } |
ThomasBNL | 40:7f928b465f8d | 407 | } |
ThomasBNL | 40:7f928b465f8d | 408 | } |
ThomasBNL | 36:f29a36683b1a | 409 | |
ThomasBNL | 40:7f928b465f8d | 410 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 411 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 412 | // || [CALIBRATE] || |
ThomasBNL | 40:7f928b465f8d | 413 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 414 | // Calibrate starting postion (RED LED) |
ThomasBNL | 40:7f928b465f8d | 415 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 416 | // : [Starting position motor] : |
ThomasBNL | 40:7f928b465f8d | 417 | // :___________________________: |
ThomasBNL | 40:7f928b465f8d | 418 | // |
ThomasBNL | 40:7f928b465f8d | 419 | |
ThomasBNL | 40:7f928b465f8d | 420 | void calibrate_motor() |
ThomasBNL | 40:7f928b465f8d | 421 | { |
ThomasBNL | 40:7f928b465f8d | 422 | pc.printf("Button calibration \n\r"); |
ThomasBNL | 27:85e5d36bb6c5 | 423 | while(1) |
ThomasBNL | 40:7f928b465f8d | 424 | { |
ThomasBNL | 40:7f928b465f8d | 425 | red();// RED LED |
ThomasBNL | 40:7f928b465f8d | 426 | |
ThomasBNL | 40:7f928b465f8d | 427 | if (buttonL2.read() < 0.5) |
ThomasBNL | 40:7f928b465f8d | 428 | { motordirection_turn = cw; |
ThomasBNL | 40:7f928b465f8d | 429 | pwm_motor_turn = 0.02; } |
ThomasBNL | 40:7f928b465f8d | 430 | |
ThomasBNL | 40:7f928b465f8d | 431 | if (buttonL1.read() < 0.5){ |
ThomasBNL | 40:7f928b465f8d | 432 | { motordirection_turn = ccw; |
ThomasBNL | 40:7f928b465f8d | 433 | pwm_motor_turn = 0.02; } |
ThomasBNL | 40:7f928b465f8d | 434 | |
ThomasBNL | 40:7f928b465f8d | 435 | pwm_motor_turn = 0; |
ThomasBNL | 40:7f928b465f8d | 436 | |
ThomasBNL | 40:7f928b465f8d | 437 | if (buttonH2.read() < 0.5){ |
ThomasBNL | 40:7f928b465f8d | 438 | { motordirection_strike = cw; |
ThomasBNL | 40:7f928b465f8d | 439 | pwm_motor_strike = 0.02; } |
ThomasBNL | 40:7f928b465f8d | 440 | |
ThomasBNL | 40:7f928b465f8d | 441 | if (buttonH1.read() < 0.5){ |
ThomasBNL | 40:7f928b465f8d | 442 | { motordirection_strike = ccw; |
ThomasBNL | 40:7f928b465f8d | 443 | pwm_motor_strike = 0.02; } |
ThomasBNL | 40:7f928b465f8d | 444 | |
ThomasBNL | 40:7f928b465f8d | 445 | pwm_motor_strike = 0; |
ThomasBNL | 40:7f928b465f8d | 446 | |
ThomasBNL | 40:7f928b465f8d | 447 | if ((buttonL2.read() < 0.5) && (buttonL1.read() < 0.5)) // Save current TURN and STRIKE positions as starting position |
ThomasBNL | 40:7f928b465f8d | 448 | { |
ThomasBNL | 40:7f928b465f8d | 449 | motor_turn.reset(); // TURN : Starting Position |
ThomasBNL | 40:7f928b465f8d | 450 | reference_turn=0; // TURN : Set reference position to zero |
ThomasBNL | 40:7f928b465f8d | 451 | motor_strike.reset(); // STRIKE : Starting Position |
ThomasBNL | 40:7f928b465f8d | 452 | goto calibration_starting_position_complete; // Calibration complete (exit while loop) |
ThomasBNL | 40:7f928b465f8d | 453 | } |
ThomasBNL | 40:7f928b465f8d | 454 | } |
ThomasBNL | 40:7f928b465f8d | 455 | calibration_starting_position_complete: |
ThomasBNL | 40:7f928b465f8d | 456 | } |
ThomasBNL | 40:7f928b465f8d | 457 | |
ThomasBNL | 40:7f928b465f8d | 458 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 459 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 460 | // || [EMG_Calibration] || |
ThomasBNL | 40:7f928b465f8d | 461 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 462 | // |
ThomasBNL | 40:7f928b465f8d | 463 | void calibration() |
ThomasBNL | 27:85e5d36bb6c5 | 464 | { |
ThomasBNL | 40:7f928b465f8d | 465 | // ___________________________________ |
ThomasBNL | 40:7f928b465f8d | 466 | // : [Minimum value bicep calibration] : |
ThomasBNL | 40:7f928b465f8d | 467 | // :___________________________________: |
ThomasBNL | 40:7f928b465f8d | 468 | |
ThomasBNL | 40:7f928b465f8d | 469 | blue(); |
ThomasBNL | 40:7f928b465f8d | 470 | pc.printf("Start minimum calibration in 5 seconds \n\r"); |
ThomasBNL | 40:7f928b465f8d | 471 | pc.printf("Keep your biceps as relaxed as possible \n\r"); |
ThomasBNL | 40:7f928b465f8d | 472 | |
ThomasBNL | 40:7f928b465f8d | 473 | countdown_from_5(); |
ThomasBNL | 40:7f928b465f8d | 474 | c=0; |
ThomasBNL | 40:7f928b465f8d | 475 | |
ThomasBNL | 40:7f928b465f8d | 476 | while(c<2560) // 512Hz -> 2560 is equal to five seconds |
ThomasBNL | 40:7f928b465f8d | 477 | { |
ThomasBNL | 40:7f928b465f8d | 478 | Filter(); // Filter EMG signal |
ThomasBNL | 40:7f928b465f8d | 479 | minimum_L=EMG_Left_Bicep_filtered+minimum_L; // Take previous sample EMG_Left_Bicep_filtered and add the new value |
ThomasBNL | 40:7f928b465f8d | 480 | minimum_R=EMG_Right_Bicep_filtered+minimum_R; |
ThomasBNL | 40:7f928b465f8d | 481 | c++; // Every sample c is increased by one until the statement c<2560 is false |
ThomasBNL | 40:7f928b465f8d | 482 | wait(0.001953125); // wait one sample |
ThomasBNL | 40:7f928b465f8d | 483 | } |
ThomasBNL | 40:7f928b465f8d | 484 | |
ThomasBNL | 40:7f928b465f8d | 485 | pc.printf("Finished minimum calibration \n\r"); |
ThomasBNL | 40:7f928b465f8d | 486 | |
ThomasBNL | 40:7f928b465f8d | 487 | EMG_L_min=minimum_L/2560; // Divide the summation by the number of measurements (2560 measurements) to get a mean value over 5 seconds |
ThomasBNL | 40:7f928b465f8d | 488 | EMG_R_min=minimum_R/2560; |
ThomasBNL | 40:7f928b465f8d | 489 | |
ThomasBNL | 40:7f928b465f8d | 490 | pc.printf("EMG_L_min = %f \n\r EMG_R_min = %f \n\r", EMG_L_min, EMG_R_min); |
ThomasBNL | 40:7f928b465f8d | 491 | |
ThomasBNL | 40:7f928b465f8d | 492 | wait (3); // Cooldown |
ThomasBNL | 40:7f928b465f8d | 493 | |
ThomasBNL | 40:7f928b465f8d | 494 | // ___________________________________ |
ThomasBNL | 40:7f928b465f8d | 495 | // : [Maximum value bicep calibration] : |
ThomasBNL | 40:7f928b465f8d | 496 | // :___________________________________: |
ThomasBNL | 40:7f928b465f8d | 497 | // |
ThomasBNL | 40:7f928b465f8d | 498 | pc.printf("start maximum calibration in 5 seconds (start contraction at 3) \n\r"); |
ThomasBNL | 40:7f928b465f8d | 499 | |
ThomasBNL | 40:7f928b465f8d | 500 | countdown_from_5(); |
ThomasBNL | 40:7f928b465f8d | 501 | c=0; |
ThomasBNL | 40:7f928b465f8d | 502 | |
ThomasBNL | 40:7f928b465f8d | 503 | while(c<2560) // 512Hz -> 2560 is equal to five seconds |
ThomasBNL | 40:7f928b465f8d | 504 | { |
ThomasBNL | 40:7f928b465f8d | 505 | Filter(); // Filter EMG signal |
ThomasBNL | 40:7f928b465f8d | 506 | maximum_L=EMG_Left_Bicep_filtered+maximum_L; // Take previous sample EMG_Left_Bicep_filtered and add the new value |
ThomasBNL | 40:7f928b465f8d | 507 | maximum_R=EMG_Right_Bicep_filtered+maximum_R; |
ThomasBNL | 40:7f928b465f8d | 508 | c++; // Every sample c is increased by one until the statement c<2560 is false |
ThomasBNL | 40:7f928b465f8d | 509 | wait(0.001953125); |
ThomasBNL | 40:7f928b465f8d | 510 | } |
ThomasBNL | 40:7f928b465f8d | 511 | |
ThomasBNL | 40:7f928b465f8d | 512 | pc.printf("Finished minimum calibration \n\r"); |
ThomasBNL | 40:7f928b465f8d | 513 | |
ThomasBNL | 40:7f928b465f8d | 514 | EMG_L_max=maximum_L/2560; // Divide the summation by the number of measurements (2560 measurements) to get a mean value over 5 seconds |
ThomasBNL | 40:7f928b465f8d | 515 | EMG_R_max=maximum_R/2560; |
ThomasBNL | 40:7f928b465f8d | 516 | |
ThomasBNL | 40:7f928b465f8d | 517 | pc.printf("EMG_L_max = %f \n\r EMG_R_max = %f \n\r", EMG_L_max, EMG_R_max); |
ThomasBNL | 40:7f928b465f8d | 518 | |
ThomasBNL | 40:7f928b465f8d | 519 | wait (3); // Cooldown |
ThomasBNL | 40:7f928b465f8d | 520 | |
ThomasBNL | 40:7f928b465f8d | 521 | |
ThomasBNL | 40:7f928b465f8d | 522 | // _______________________________________________ |
ThomasBNL | 40:7f928b465f8d | 523 | // : [THRESHOLDS CALCULATION FROM MIN AND MAX EMG] : |
ThomasBNL | 40:7f928b465f8d | 524 | // :_______________________________________________: |
ThomasBNL | 40:7f928b465f8d | 525 | // |
ThomasBNL | 40:7f928b465f8d | 526 | |
ThomasBNL | 40:7f928b465f8d | 527 | const float Threshold_Bicep_Left_1=((EMG_L_max-EMG_L_min)*0.2)+EMG_L_min;; // EMG LEFT: Threshold put at 20% of the EMG range |
ThomasBNL | 40:7f928b465f8d | 528 | const float Threshold_Bicep_Left_2=((EMG_L_max-EMG_L_min)*0.6)+EMG_L_min; // EMG LEFT: Threshold put at 60% of the EMG range |
ThomasBNL | 40:7f928b465f8d | 529 | const float Threshold_Bicep_Right_1=((EMG_R_max-EMG_R_min)*0.2)+EMG_R_min; // EMG RIGHT: Threshold put at 20% of the EMG range |
ThomasBNL | 40:7f928b465f8d | 530 | const float Threshold_Bicep_Right_2=((EMG_R_max-EMG_R_min)*0.6)+EMG_R_min; // EMG RIGHT: Threshold put at 60% of the EMG range |
ThomasBNL | 40:7f928b465f8d | 531 | |
ThomasBNL | 40:7f928b465f8d | 532 | pc.printf("left 1: %f left 2: %f right 1: %f right 2: %f \n\r", Threshold_Bicep_Left_1, Threshold_Bicep_Left_2, Threshold_Bicep_Right_1, Threshold_Bicep_Right_2); |
ThomasBNL | 40:7f928b465f8d | 533 | } |
ThomasBNL | 40:7f928b465f8d | 534 | |
ThomasBNL | 40:7f928b465f8d | 535 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 536 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 537 | // || [TURN PLANT] || |
ThomasBNL | 40:7f928b465f8d | 538 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 539 | |
ThomasBNL | 40:7f928b465f8d | 540 | void execute_plant_turn() |
ThomasBNL | 40:7f928b465f8d | 541 | { |
ThomasBNL | 40:7f928b465f8d | 542 | if ((motor_turn.getPulses()>4200) || (motor_turn.getPulses()<-4200)) // If value exceeds -4200 and 4200 (number of counts equal to one revolution) than reset to zero |
ThomasBNL | 40:7f928b465f8d | 543 | { motor_turn.reset(); } |
ThomasBNL | 40:7f928b465f8d | 544 | |
ThomasBNL | 40:7f928b465f8d | 545 | position_turn = conversion_counts_to_degrees * motor_turn.getPulses(); // Convert counts to degrees |
ThomasBNL | 40:7f928b465f8d | 546 | |
ThomasBNL | 40:7f928b465f8d | 547 | double pwm_to_motor_turn = PID_control(reference_turn, position_turn, integrate_error_turn, sample_time, previous_error_turn, P_gain_turn, I_gain_turn, D_gain_turn); |
ThomasBNL | 40:7f928b465f8d | 548 | // Execute PID controller and calculate the pwm to put to the motor |
ThomasBNL | 40:7f928b465f8d | 549 | |
ThomasBNL | 40:7f928b465f8d | 550 | keep_in_range(&pwm_to_motor_turn, -1,1); // Pass to the plant but make sure the max and min pwm put to the plant stays between -1 and 1 |
ThomasBNL | 40:7f928b465f8d | 551 | |
ThomasBNL | 40:7f928b465f8d | 552 | //pc.printf("pwm %f \n\r", pwm_to_motor_turn); // LINE FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 553 | |
ThomasBNL | 40:7f928b465f8d | 554 | if(pwm_to_motor_turn > 0) // Check error and decide the direction the motor has to turn |
ThomasBNL | 40:7f928b465f8d | 555 | { motordirection_turn=ccw;} |
ThomasBNL | 40:7f928b465f8d | 556 | else |
ThomasBNL | 40:7f928b465f8d | 557 | { motordirection_turn=cw; } |
ThomasBNL | 40:7f928b465f8d | 558 | |
ThomasBNL | 40:7f928b465f8d | 559 | pwm_motor_turn=(abs(pwm_to_motor_turn)); // Put the absolute value of the PID controller to the pwm (negative pwm does not work) |
ThomasBNL | 40:7f928b465f8d | 560 | |
ThomasBNL | 40:7f928b465f8d | 561 | take_sample(); // TEMPORARY -> use sample_filter() normally |
ThomasBNL | 40:7f928b465f8d | 562 | |
ThomasBNL | 40:7f928b465f8d | 563 | // sample_filter(); |
ThomasBNL | 40:7f928b465f8d | 564 | |
ThomasBNL | 40:7f928b465f8d | 565 | if(sample_error) // sample_error -- e10;e9;e8;e7;e6;e5:e4;e3;e2;e1 -- error_turn_average --- er |
ThomasBNL | 40:7f928b465f8d | 566 | { |
ThomasBNL | 40:7f928b465f8d | 567 | sample_error=false; |
ThomasBNL | 40:7f928b465f8d | 568 | e1 = (position_turn - reference_turn); |
ThomasBNL | 40:7f928b465f8d | 569 | e30=e29; e29=e28 ;e28=e27; e27=e26; e26=e25; e25=e24; e24=e23; e23=e22; e22=e21; e21=e20; |
ThomasBNL | 40:7f928b465f8d | 570 | e20=e19; e19=e18 ;e18=e17; e17=e16; e16=e15; e15=e14; e14=e13; e13=e12; e12=e11; e11=e10; |
ThomasBNL | 40:7f928b465f8d | 571 | e10=e9 ;e9=e8; e8=e7; e7=e6; e6=e5; e5=e4; e4=e3; e3=e2; e2=e1; |
ThomasBNL | 40:7f928b465f8d | 572 | } |
ThomasBNL | 40:7f928b465f8d | 573 | |
ThomasBNL | 40:7f928b465f8d | 574 | error_turn_average=(e1+e2+e3+e4+e5+e6+e7+e8+e9+e10+e11+e12+e13+e14+e15+e16+e17+e18+e19+e20+e21+e22+e23+e24+e25+e26+e27+e28+e29+e30)/30; |
ThomasBNL | 40:7f928b465f8d | 575 | er++; |
ThomasBNL | 40:7f928b465f8d | 576 | error_count++; |
ThomasBNL | 40:7f928b465f8d | 577 | } |
ThomasBNL | 40:7f928b465f8d | 578 | |
ThomasBNL | 40:7f928b465f8d | 579 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 580 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 581 | // || [STRIKE PLANT] || |
ThomasBNL | 40:7f928b465f8d | 582 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 583 | // |
ThomasBNL | 40:7f928b465f8d | 584 | void execute_plant_strike() |
ThomasBNL | 40:7f928b465f8d | 585 | { |
ThomasBNL | 40:7f928b465f8d | 586 | if ((motor_strike.getPulses()>4200) || (motor_strike.getPulses()<-4200)) // If value is outside -4200 and 4200 (number of counts equal to one revolution) reset to zero |
ThomasBNL | 40:7f928b465f8d | 587 | { |
ThomasBNL | 40:7f928b465f8d | 588 | motor_strike.reset(); |
ThomasBNL | 40:7f928b465f8d | 589 | pc.printf("RESET \n\r"); |
ThomasBNL | 40:7f928b465f8d | 590 | } |
ThomasBNL | 40:7f928b465f8d | 591 | |
ThomasBNL | 40:7f928b465f8d | 592 | position_strike = conversion_counts_to_degrees * motor_strike.getPulses(); |
ThomasBNL | 40:7f928b465f8d | 593 | |
ThomasBNL | 40:7f928b465f8d | 594 | double pwm_to_motor_strike=PID_control(reference_strike, position_strike, integrate_error_strike, sample_time, previous_error_strike, P_gain_strike, I_gain_strike, D_gain_strike); |
ThomasBNL | 40:7f928b465f8d | 595 | keep_in_range(&pwm_to_motor_strike, -1,1); // Pass to motor controller but keep it in range! |
ThomasBNL | 40:7f928b465f8d | 596 | |
ThomasBNL | 40:7f928b465f8d | 597 | if(pwm_to_motor_strike > 0) // Check error and decide direction to turn |
ThomasBNL | 40:7f928b465f8d | 598 | { motordirection_strike=cw; } |
ThomasBNL | 40:7f928b465f8d | 599 | else |
ThomasBNL | 40:7f928b465f8d | 600 | { motordirection_strike=ccw; } |
ThomasBNL | 40:7f928b465f8d | 601 | |
ThomasBNL | 40:7f928b465f8d | 602 | |
ThomasBNL | 40:7f928b465f8d | 603 | if(p==1) // p is put to one if return action is put to active |
ThomasBNL | 40:7f928b465f8d | 604 | { pwm_motor_strike=(abs(pwm_to_motor_strike)); } |
ThomasBNL | 40:7f928b465f8d | 605 | |
ThomasBNL | 40:7f928b465f8d | 606 | |
ThomasBNL | 40:7f928b465f8d | 607 | // TEMPORARY USAGE WHILE POTMETER ACTIVE |
ThomasBNL | 40:7f928b465f8d | 608 | EMG_L_max = 100; // Calibreren (max average over 5 seconde?) gemeten integraal EMG over tijd / (tijdsample stappen)=100 |
ThomasBNL | 40:7f928b465f8d | 609 | EMG_L_min = 0; |
ThomasBNL | 40:7f928b465f8d | 610 | EMG_R_max = 100; // Calibreren |
ThomasBNL | 40:7f928b465f8d | 611 | EMG_R_min = 0; |
ThomasBNL | 40:7f928b465f8d | 612 | |
ThomasBNL | 40:7f928b465f8d | 613 | const double Threshold_Bicep_Left_1 =((EMG_L_max-EMG_L_min)*0.2)+EMG_L_min;; //(waarde waarop het gemeten EMG signaal 20% van max het maximale is); // LEFT |
ThomasBNL | 40:7f928b465f8d | 614 | const double Threshold_Bicep_Right_1 =((EMG_R_max-EMG_R_min)*0.2)+EMG_R_min; //(waarde waarop het gemeten EMG signaal 20% van max het maximale is); // RIGHT |
ThomasBNL | 40:7f928b465f8d | 615 | |
ThomasBNL | 40:7f928b465f8d | 616 | moving_average_left = 40; // TIJDELIJK PID TEST |
ThomasBNL | 40:7f928b465f8d | 617 | moving_average_right = 40; // TIJDELIJK PID TEST |
ThomasBNL | 40:7f928b465f8d | 618 | double signal_above_threshold=(moving_average_right-Threshold_Bicep_Right_1)+(moving_average_left-Threshold_Bicep_Left_1); |
ThomasBNL | 40:7f928b465f8d | 619 | double max_signal=(EMG_R_max-Threshold_Bicep_Right_1)+(EMG_L_max-Threshold_Bicep_Left_1); |
ThomasBNL | 40:7f928b465f8d | 620 | double pwm_strike=signal_above_threshold/max_signal; |
ThomasBNL | 40:7f928b465f8d | 621 | |
ThomasBNL | 40:7f928b465f8d | 622 | //pc.printf("mov_r = %f, mov_l = %f, pwm_strike = %f position = %f \n\r", moving_average_right, moving_average_left, pwm_strike, position_strike); // LINE FOR TESTING |
ThomasBNL | 40:7f928b465f8d | 623 | |
ThomasBNL | 40:7f928b465f8d | 624 | if(p==0) |
ThomasBNL | 40:7f928b465f8d | 625 | { pwm_motor_strike=pwm_strike; } |
ThomasBNL | 40:7f928b465f8d | 626 | |
ThomasBNL | 40:7f928b465f8d | 627 | take_sample(); // UITEINDELIJK: UIT |
ThomasBNL | 40:7f928b465f8d | 628 | |
ThomasBNL | 40:7f928b465f8d | 629 | // sample_filter(); --> sample filter aan als EMG |
ThomasBNL | 40:7f928b465f8d | 630 | |
ThomasBNL | 40:7f928b465f8d | 631 | if(sample_error_strike) |
ThomasBNL | 40:7f928b465f8d | 632 | { |
ThomasBNL | 40:7f928b465f8d | 633 | sample_error_strike=false; |
ThomasBNL | 40:7f928b465f8d | 634 | e1 = fabs(position_strike - reference_strike); |
ThomasBNL | 40:7f928b465f8d | 635 | e30=e29; e29=e28 ;e28=e27; e27=e26; e26=e25; e25=e24; e24=e23; e23=e22; e22=e21; e21=e20; |
ThomasBNL | 40:7f928b465f8d | 636 | e20=e19; e19=e18 ;e18=e17; e17=e16; e16=e15; e15=e14; e14=e13; e13=e12; e12=e11; e11=e10; |
ThomasBNL | 40:7f928b465f8d | 637 | e10=e9 ;e9=e8; e8=e7; e7=e6; e6=e5; e5=e4; e4=e3; e3=e2; e2=e1; |
ThomasBNL | 40:7f928b465f8d | 638 | } |
ThomasBNL | 40:7f928b465f8d | 639 | |
ThomasBNL | 40:7f928b465f8d | 640 | error_strike_average=(e1+e2+e3+e4+e5+e6+e7+e8+e9+e10+e11+e12+e13+e14+e15+e16+e17+e18+e19+e20+e21+e22+e23+e24+e25+e26+e27+e28+e29+e30)/30; |
ThomasBNL | 40:7f928b465f8d | 641 | er++; |
ThomasBNL | 40:7f928b465f8d | 642 | error_count++; |
ThomasBNL | 40:7f928b465f8d | 643 | } |
ThomasBNL | 40:7f928b465f8d | 644 | |
ThomasBNL | 40:7f928b465f8d | 645 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 646 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 647 | // || [PID CONTROLLER] || |
ThomasBNL | 40:7f928b465f8d | 648 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 649 | // |
ThomasBNL | 40:7f928b465f8d | 650 | double PID_control(double reference, double position, double &integrate_error, double sample_time, double &previous_error, double P_gain, double I_gain, double D_gain) |
ThomasBNL | 27:85e5d36bb6c5 | 651 | { |
ThomasBNL | 40:7f928b465f8d | 652 | double error=(reference - position); // Current error (input controller) |
ThomasBNL | 40:7f928b465f8d | 653 | integrate_error=integrate_error_turn + sample_time*error_turn; // Integral error output |
ThomasBNL | 40:7f928b465f8d | 654 | // overwrite previous integrate error by adding the current error |
ThomasBNL | 40:7f928b465f8d | 655 | // multiplied by the sample time. |
ThomasBNL | 40:7f928b465f8d | 656 | |
ThomasBNL | 40:7f928b465f8d | 657 | double error_derivative=(error - previous_error)/sample_time; // Derivative error output |
ThomasBNL | 40:7f928b465f8d | 658 | error_derivative=Lowpassfilter_derivative.step(error_derivative); // Filter |
ThomasBNL | 40:7f928b465f8d | 659 | |
ThomasBNL | 40:7f928b465f8d | 660 | previous_error_turn=error_turn; // current error is saved to memory constant to be used in |
ThomasBNL | 40:7f928b465f8d | 661 | // the next loop for calculating the derivative error |
ThomasBNL | 40:7f928b465f8d | 662 | |
ThomasBNL | 40:7f928b465f8d | 663 | double pwm_motor_P = error*P_gain; // Output P controller to pwm |
ThomasBNL | 40:7f928b465f8d | 664 | double pwm_motor_I = integrate_error*I_gain; // Output I controller to pwm |
ThomasBNL | 40:7f928b465f8d | 665 | double pwm_motor_D = error_derivative*D_gain; // Output D controller to pwm |
ThomasBNL | 36:f29a36683b1a | 666 | |
ThomasBNL | 40:7f928b465f8d | 667 | double pwm_to_motor = pwm_motor_P + pwm_motor_I + pwm_motor_D; |
ThomasBNL | 40:7f928b465f8d | 668 | |
ThomasBNL | 40:7f928b465f8d | 669 | return pwm_to_motor; |
ThomasBNL | 40:7f928b465f8d | 670 | } |
ThomasBNL | 36:f29a36683b1a | 671 | |
ThomasBNL | 40:7f928b465f8d | 672 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 673 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 674 | // || [SAMPLE] || |
ThomasBNL | 40:7f928b465f8d | 675 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 676 | // |
ThomasBNL | 36:f29a36683b1a | 677 | void sample_filter() |
ThomasBNL | 36:f29a36683b1a | 678 | { |
ThomasBNL | 36:f29a36683b1a | 679 | Filter(); |
ThomasBNL | 36:f29a36683b1a | 680 | take_sample(); |
ThomasBNL | 36:f29a36683b1a | 681 | if(sample) |
ThomasBNL | 36:f29a36683b1a | 682 | { |
ThomasBNL | 36:f29a36683b1a | 683 | sample=false; |
ThomasBNL | 36:f29a36683b1a | 684 | Sample_EMG_L_1 = EMG_Left_Bicep_filtered; Sample_EMG_R_1 = EMG_Right_Bicep_filtered; |
ThomasBNL | 36:f29a36683b1a | 685 | |
ThomasBNL | 36:f29a36683b1a | 686 | Sample_EMG_L_10= Sample_EMG_L_9; Sample_EMG_R_10= Sample_EMG_R_9; |
ThomasBNL | 36:f29a36683b1a | 687 | Sample_EMG_L_9 = Sample_EMG_L_8; Sample_EMG_R_9 = Sample_EMG_R_8; |
ThomasBNL | 36:f29a36683b1a | 688 | Sample_EMG_L_8 = Sample_EMG_L_7; Sample_EMG_R_8 = Sample_EMG_R_7; |
ThomasBNL | 36:f29a36683b1a | 689 | Sample_EMG_L_7 = Sample_EMG_L_6; Sample_EMG_R_7 = Sample_EMG_R_6; |
ThomasBNL | 36:f29a36683b1a | 690 | Sample_EMG_L_6 = Sample_EMG_L_5; Sample_EMG_R_6 = Sample_EMG_R_5; |
ThomasBNL | 36:f29a36683b1a | 691 | Sample_EMG_L_5 = Sample_EMG_L_4; Sample_EMG_R_5 = Sample_EMG_R_4; |
ThomasBNL | 36:f29a36683b1a | 692 | Sample_EMG_L_4 = Sample_EMG_L_3; Sample_EMG_R_4 = Sample_EMG_R_3; |
ThomasBNL | 36:f29a36683b1a | 693 | Sample_EMG_L_3 = Sample_EMG_L_2; Sample_EMG_R_3 = Sample_EMG_R_2; |
ThomasBNL | 36:f29a36683b1a | 694 | Sample_EMG_L_2 = Sample_EMG_L_1; Sample_EMG_R_2 = Sample_EMG_R_1; |
ThomasBNL | 36:f29a36683b1a | 695 | } |
ThomasBNL | 36:f29a36683b1a | 696 | moving_average_left=Sample_EMG_L_1*0.1+Sample_EMG_L_2*0.1+Sample_EMG_L_3*0.1+Sample_EMG_L_4*0.1+Sample_EMG_L_5*0.1+Sample_EMG_L_6*0.1+Sample_EMG_L_7*0.1+Sample_EMG_L_8*0.1+Sample_EMG_L_9*0.1+Sample_EMG_L_10*0.1; |
ThomasBNL | 36:f29a36683b1a | 697 | moving_average_right=Sample_EMG_R_1*0.1+Sample_EMG_R_2*0.1+Sample_EMG_R_3*0.1+Sample_EMG_R_4*0.1+Sample_EMG_R_5*0.1+Sample_EMG_R_6*0.1+Sample_EMG_R_7*0.1+Sample_EMG_R_8*0.1+Sample_EMG_R_9*0.1+Sample_EMG_R_10*0.1; |
ThomasBNL | 36:f29a36683b1a | 698 | n++; |
ThomasBNL | 36:f29a36683b1a | 699 | } |
ThomasBNL | 36:f29a36683b1a | 700 | |
ThomasBNL | 40:7f928b465f8d | 701 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 702 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 703 | // || [ FILTER ] || |
ThomasBNL | 40:7f928b465f8d | 704 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 705 | // |
ThomasBNL | 40:7f928b465f8d | 706 | void Filter() // Unfiltered EMG (input) -> highpass filter -> rectify -> lowpass filter -> Filtered EMG (output) |
ThomasBNL | 36:f29a36683b1a | 707 | { |
ThomasBNL | 40:7f928b465f8d | 708 | EMG_left_Bicep = input1; EMG_Right_Bicep = input2; // Current input EMG left and right |
ThomasBNL | 40:7f928b465f8d | 709 | |
ThomasBNL | 40:7f928b465f8d | 710 | EMG_Left_Bicep_filtered = highpassfilter_1.step(EMG_left_Bicep); EMG_Right_Bicep_filtered = highpassfilter_2.step(EMG_Right_Bicep); // Highpassfilter |
ThomasBNL | 40:7f928b465f8d | 711 | EMG_Left_Bicep_filtered = fabs(EMG_Left_Bicep_filtered); EMG_Right_Bicep_filtered = fabs(EMG_Right_Bicep_filtered); // Rectify |
ThomasBNL | 40:7f928b465f8d | 712 | |
ThomasBNL | 40:7f928b465f8d | 713 | EMG_Left_Bicep_filtered_notch_1 = notchL1.step(EMG_Left_Bicep_filtered); EMG_Right_Bicep_filtered_notch_1 = notchR1.step(EMG_Right_Bicep_filtered); // Notch Filter part 1 |
ThomasBNL | 40:7f928b465f8d | 714 | EMG_Left_Bicep_filtered_notch_2 = notchL2.step(EMG_Left_Bicep_filtered_notch_1); EMG_Right_Bicep_filtered_notch_2 = notchR2.step(EMG_Right_Bicep_filtered_notch_1); // Notch Filter part 2 |
ThomasBNL | 40:7f928b465f8d | 715 | |
ThomasBNL | 40:7f928b465f8d | 716 | EMG_Left_Bicep_filtered = lowpassfilter_1.step(EMG_Left_Bicep_filtered_notch_2); EMG_Right_Bicep_filtered = lowpassfilter_2.step(EMG_Right_Bicep_filtered_notch_2); // Lowpassfilter |
ThomasBNL | 36:f29a36683b1a | 717 | } |
ThomasBNL | 40:7f928b465f8d | 718 | |
ThomasBNL | 40:7f928b465f8d | 719 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 720 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 721 | // || [TAKE SAMPLE] || |
ThomasBNL | 40:7f928b465f8d | 722 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 723 | // |
ThomasBNL | 40:7f928b465f8d | 724 | void take_sample() // Take a sample every 25th sample for moving average, every 5th sample .... |
ThomasBNL | 40:7f928b465f8d | 725 | { |
ThomasBNL | 40:7f928b465f8d | 726 | if(n==25) |
ThomasBNL | 40:7f928b465f8d | 727 | {sample = true; n=0;} |
ThomasBNL | 40:7f928b465f8d | 728 | |
ThomasBNL | 40:7f928b465f8d | 729 | if(er==5) |
ThomasBNL | 40:7f928b465f8d | 730 | {sample_error = true; er=0;} |
ThomasBNL | 40:7f928b465f8d | 731 | |
ThomasBNL | 40:7f928b465f8d | 732 | sample_error_strike = true; |
ThomasBNL | 36:f29a36683b1a | 733 | } |
ThomasBNL | 36:f29a36683b1a | 734 | |
ThomasBNL | 40:7f928b465f8d | 735 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 736 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 737 | // || [CHANGE REFERENCE] || |
ThomasBNL | 40:7f928b465f8d | 738 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 739 | // |
ThomasBNL | 40:7f928b465f8d | 740 | void Change_Turn_Position_Right (double& reference, double change_one_bottle) |
ThomasBNL | 36:f29a36683b1a | 741 | { |
ThomasBNL | 40:7f928b465f8d | 742 | if(reference==90) // If reference value at right boundary bottle and function is executed than immediatly turn 5 bottles to the left (ref to -90) |
ThomasBNL | 40:7f928b465f8d | 743 | { reference=-90; } |
ThomasBNL | 40:7f928b465f8d | 744 | else |
ThomasBNL | 40:7f928b465f8d | 745 | { reference = reference + change_one_bottle; |
ThomasBNL | 40:7f928b465f8d | 746 | keep_in_range(&reference, -90, 90); } // reference position stays between -90 and 90 degrees (IF bottles at -90, -45, 0, 45, 90 degrees) |
ThomasBNL | 36:f29a36683b1a | 747 | } |
ThomasBNL | 36:f29a36683b1a | 748 | |
ThomasBNL | 40:7f928b465f8d | 749 | void Change_Turn_Position_Left (double& reference, double change_one_bottle) |
ThomasBNL | 40:7f928b465f8d | 750 | { |
ThomasBNL | 40:7f928b465f8d | 751 | if(reference==-90) // If reference value at left boundary bottle and function is executed than immediatly turn 5 bottles to the left (ref to +90) |
ThomasBNL | 40:7f928b465f8d | 752 | { reference=90; } |
ThomasBNL | 40:7f928b465f8d | 753 | else |
ThomasBNL | 40:7f928b465f8d | 754 | { reference = reference - change_one_bottle; |
ThomasBNL | 40:7f928b465f8d | 755 | keep_in_range(&reference, -90, 90); } |
ThomasBNL | 40:7f928b465f8d | 756 | } |
ThomasBNL | 40:7f928b465f8d | 757 | |
ThomasBNL | 40:7f928b465f8d | 758 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 759 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 760 | // | [(DE)ACTIVATE PID CONTROLLERS] | |
ThomasBNL | 40:7f928b465f8d | 761 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 762 | // |
ThomasBNL | 40:7f928b465f8d | 763 | void deactivate_PID_Controller(double& P_gain, double& I_gain, double& D_gain) |
ThomasBNL | 40:7f928b465f8d | 764 | { |
ThomasBNL | 40:7f928b465f8d | 765 | P_gain=0; I_gain=0; D_gain=0; // Deactivating values of PID controller |
ThomasBNL | 40:7f928b465f8d | 766 | pwm_motor_turn=0; pwm_motor_strike=0; |
ThomasBNL | 40:7f928b465f8d | 767 | } |
ThomasBNL | 40:7f928b465f8d | 768 | |
ThomasBNL | 40:7f928b465f8d | 769 | void activate_PID_Controller_turn(double& P_gain, double& I_gain, double& D_gain) |
ThomasBNL | 40:7f928b465f8d | 770 | { |
ThomasBNL | 40:7f928b465f8d | 771 | P_gain_turn=0.02; // Change P,I,D values (activate) |
ThomasBNL | 40:7f928b465f8d | 772 | I_gain_turn=0.1; |
ThomasBNL | 40:7f928b465f8d | 773 | D_gain_turn=0; |
ThomasBNL | 40:7f928b465f8d | 774 | } |
ThomasBNL | 40:7f928b465f8d | 775 | |
ThomasBNL | 40:7f928b465f8d | 776 | void activate_PID_Controller_strike(double& P_gain, double& I_gain, double& D_gain) |
ThomasBNL | 40:7f928b465f8d | 777 | { |
ThomasBNL | 40:7f928b465f8d | 778 | double Ku = (input1.read())*1; // EMG Right bicep (tussen nul en 100%) // DEBUG TEST TOOL: substitute EMG input for potmeter inputs |
ThomasBNL | 40:7f928b465f8d | 779 | double Pu = (input2.read())*1; // EMG Left bicep (tussen nul en 100%) |
ThomasBNL | 40:7f928b465f8d | 780 | |
ThomasBNL | 40:7f928b465f8d | 781 | P_gain_strike=0.8*Ku; // Ku=0.2 (ultimate gain Ziegler-Nichols method) |
ThomasBNL | 40:7f928b465f8d | 782 | // Pu=0.25 (ultimate period) (4Hz) |
ThomasBNL | 40:7f928b465f8d | 783 | |
ThomasBNL | 40:7f928b465f8d | 784 | pc.printf("Ku=%f Pu=%f \n\r", Ku, Pu); |
ThomasBNL | 40:7f928b465f8d | 785 | //0.09090909; |
ThomasBNL | 40:7f928b465f8d | 786 | //PI tyreus luyben : 0.0625, 0.55; |
ThomasBNL | 40:7f928b465f8d | 787 | //PID tyreus luyben : 0.09090909, 0.55, 0.0396825; |
ThomasBNL | 40:7f928b465f8d | 788 | // Ku=0.2 (ultimate gain Ziegler-Nichols method) |
ThomasBNL | 40:7f928b465f8d | 789 | // Pu=0.25 (ultimate period) (4Hz) |
ThomasBNL | 40:7f928b465f8d | 790 | // hier waardes P,I,D veranderen (waardes bovenaan doen (tijdelijk) niks meer // 0.00045 // 0.03 |
ThomasBNL | 40:7f928b465f8d | 791 | I_gain_strike=0; //0.55; |
ThomasBNL | 40:7f928b465f8d | 792 | D_gain_strike=Pu/8; //0.0396825; |
ThomasBNL | 40:7f928b465f8d | 793 | } |
ThomasBNL | 40:7f928b465f8d | 794 | |
ThomasBNL | 40:7f928b465f8d | 795 | // ___________________________ |
ThomasBNL | 40:7f928b465f8d | 796 | // // \\ |
ThomasBNL | 40:7f928b465f8d | 797 | // || [OTHER FUNCTIONS] || |
ThomasBNL | 40:7f928b465f8d | 798 | // \\___________________________// |
ThomasBNL | 40:7f928b465f8d | 799 | // |
ThomasBNL | 36:f29a36683b1a | 800 | void countdown_from_5() // Countdown from 5 till 0 inside Putty (interface) |
ThomasBNL | 36:f29a36683b1a | 801 | { |
ThomasBNL | 36:f29a36683b1a | 802 | wait(1); pc.printf("5 \n\r"); wait(1); pc.printf("4 \n\r"); wait(1); pc.printf("3 \n\r"); wait(1); pc.printf("2 Ready \n\r"); |
ThomasBNL | 36:f29a36683b1a | 803 | wait(1); pc.printf("1 Set \n\r"); wait(1); pc.printf("Go \n\r"); |
ThomasBNL | 40:7f928b465f8d | 804 | } |
ThomasBNL | 40:7f928b465f8d | 805 | |
ThomasBNL | 40:7f928b465f8d | 806 | void ControlGo() // Control flag |
ThomasBNL | 40:7f928b465f8d | 807 | { control_go = true; } |
ThomasBNL | 36:f29a36683b1a | 808 | |
ThomasBNL | 40:7f928b465f8d | 809 | void setlooptimerflag(void) // Looptimerflag function |
ThomasBNL | 40:7f928b465f8d | 810 | { looptimerflag = true; } |
ThomasBNL | 36:f29a36683b1a | 811 | |
sigert | 37:6c04c15d9bbe | 812 | void red() { debug_led_red=on; debug_led_blue=off; debug_led_green=off; } |
sigert | 37:6c04c15d9bbe | 813 | void blue() { debug_led_red=off; debug_led_blue=on; debug_led_green=off; } |
sigert | 37:6c04c15d9bbe | 814 | void green() { debug_led_red=off; debug_led_blue=off; debug_led_green=on; } |
sigert | 37:6c04c15d9bbe | 815 | void white() { debug_led_red=on; debug_led_blue=on; debug_led_green=on; } |
sigert | 37:6c04c15d9bbe | 816 | void yellow() { debug_led_red=on; debug_led_blue=off; debug_led_green=on; } |
sigert | 37:6c04c15d9bbe | 817 | void cyan() { debug_led_red=off; debug_led_blue=on; debug_led_green=on; } |
sigert | 37:6c04c15d9bbe | 818 | void purple() { debug_led_red=on; debug_led_blue=on; debug_led_green=off; } |
sigert | 37:6c04c15d9bbe | 819 | void black() { debug_led_red=off; debug_led_blue=off; debug_led_green=off; } |
ThomasBNL | 36:f29a36683b1a | 820 | |
ThomasBNL | 40:7f928b465f8d | 821 | |
ThomasBNL | 40:7f928b465f8d | 822 | void calibrate_potmeter() // DEBUG/TEST: Calibration thresholds with potmeter |
ThomasBNL | 40:7f928b465f8d | 823 | { |
ThomasBNL | 40:7f928b465f8d | 824 | // TEMPORARY USAGE WHILE POTMETER ACTIVE |
ThomasBNL | 40:7f928b465f8d | 825 | EMG_L_max = 100; |
ThomasBNL | 40:7f928b465f8d | 826 | EMG_L_min = 0; |
ThomasBNL | 40:7f928b465f8d | 827 | EMG_R_max = 100; |
ThomasBNL | 40:7f928b465f8d | 828 | EMG_R_min = 0; |
ThomasBNL | 40:7f928b465f8d | 829 | Threshold_Bicep_Left_1 =((EMG_L_max-EMG_L_min)*0.2)+EMG_L_min;; //(waarde waarop het gemeten EMG signaal 20% van max het maximale is); // LEFT |
ThomasBNL | 40:7f928b465f8d | 830 | Threshold_Bicep_Left_2 =((EMG_L_max-EMG_L_min)*0.6)+EMG_L_min; //(waarde waarop het gemeten EMG signaal 60% van max het maximale is); |
ThomasBNL | 40:7f928b465f8d | 831 | Threshold_Bicep_Right_1 =((EMG_R_max-EMG_R_min)*0.2)+EMG_R_min; //(waarde waarop het gemeten EMG signaal 20% van max het maximale is); // RIGHT |
ThomasBNL | 40:7f928b465f8d | 832 | Threshold_Bicep_Right_2 =((EMG_R_max-EMG_R_min)*0.6)+EMG_R_min; //(waarde waarop het gemeten EMG signaal 60% van max het maximale is); |
ThomasBNL | 40:7f928b465f8d | 833 | } |
ThomasBNL | 40:7f928b465f8d | 834 | |
ThomasBNL | 40:7f928b465f8d | 835 | // Keep in range function |
ThomasBNL | 40:7f928b465f8d | 836 | void keep_in_range(double * in, double min, double max) // Put in certain min and max values that the input needs to stay within |
ThomasBNL | 40:7f928b465f8d | 837 | { |
ThomasBNL | 40:7f928b465f8d | 838 | *in > min ? *in < max? : *in = max: *in = min; |
ThomasBNL | 40:7f928b465f8d | 839 | } |