Tommie Verouden / Mbed 2 deprecated StateMachine

Dependencies:   biquadFilter FastPWM MODSERIAL QEI mbed

Committer:
efvanmarrewijk
Date:
Fri Nov 02 09:23:28 2018 +0000
Revision:
56:e8d568d455a0
Parent:
55:b297e064ebd9
Values of theta do not change, motors move around and around

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tverouden 0:c0c35b95765f 1 // ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ PREPARATION ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
tverouden 0:c0c35b95765f 2 // Libraries
tverouden 0:c0c35b95765f 3 #include "mbed.h"
tverouden 2:d70795e4e0bf 4 #include "BiQuad.h"
tverouden 0:c0c35b95765f 5 #include "FastPWM.h"
tverouden 0:c0c35b95765f 6 #include "MODSERIAL.h"
efvanmarrewijk 25:ac139331fe51 7 #include "QEI.h"
EvaKrolis 13:4ba8f63e6ff4 8 #include <algorithm>
tverouden 41:5aecc1a27ce6 9 #include <math.h>
tverouden 41:5aecc1a27ce6 10 #include <cmath>
EvaKrolis 14:2c0bf576a0e7 11 #define PI 3.14159265
tverouden 0:c0c35b95765f 12
tverouden 8:8cef1050ebd9 13 // LEDs
tverouden 23:e282bdb9e9b7 14 DigitalOut ledRed(LED_RED,1); // red LED K64F
tverouden 23:e282bdb9e9b7 15 DigitalOut ledGreen(LED_GREEN,1); // green LED K64F
tverouden 23:e282bdb9e9b7 16 DigitalOut ledBlue(LED_BLUE,1); // blue LED K64F
tverouden 8:8cef1050ebd9 17
tverouden 23:e282bdb9e9b7 18 Ticker blinkTimer; // LED ticker
EvaKrolis 36:b233c549dd80 19 Timer EMGtransition_timer; // Timer for the transition from EMG calibration to homing
tverouden 8:8cef1050ebd9 20
tverouden 8:8cef1050ebd9 21 // Buttons/inputs
tverouden 23:e282bdb9e9b7 22 InterruptIn buttonBio1(D0); // button 1 BioRobotics shield
tverouden 23:e282bdb9e9b7 23 InterruptIn buttonBio2(D1); // button 2 BioRobotics shield
tverouden 23:e282bdb9e9b7 24 InterruptIn buttonEmergency(SW2); // emergency button on K64F
tverouden 24:0abc564349e1 25 InterruptIn buttonHome(SW3); // button on K64F
tverouden 0:c0c35b95765f 26
efvanmarrewijk 25:ac139331fe51 27 // Potmeters
efvanmarrewijk 25:ac139331fe51 28 AnalogIn pot2(A2);
efvanmarrewijk 25:ac139331fe51 29
efvanmarrewijk 25:ac139331fe51 30 // Motor pins input
efvanmarrewijk 25:ac139331fe51 31 DigitalIn pin8(D8); // Encoder L B
efvanmarrewijk 25:ac139331fe51 32 DigitalIn pin9(D9); // Encoder L A
efvanmarrewijk 25:ac139331fe51 33 DigitalIn pin10(D10); // Encoder R B
efvanmarrewijk 25:ac139331fe51 34 DigitalIn pin11(D11); // Encoder R A
efvanmarrewijk 25:ac139331fe51 35 DigitalIn pin12(D12); // Encoder F B
efvanmarrewijk 25:ac139331fe51 36 DigitalIn pin13(D13); // Encoder F A
tverouden 8:8cef1050ebd9 37
efvanmarrewijk 25:ac139331fe51 38 // Motor pins output
efvanmarrewijk 25:ac139331fe51 39 DigitalOut pin2(D2); // Motor F direction = motor flip
efvanmarrewijk 25:ac139331fe51 40 FastPWM pin3(A5); // Motor F pwm = motor flip
efvanmarrewijk 25:ac139331fe51 41 DigitalOut pin4(D4); // Motor R direction = motor right
efvanmarrewijk 25:ac139331fe51 42 FastPWM pin5(D5); // Motor R pwm = motor right
efvanmarrewijk 25:ac139331fe51 43 FastPWM pin6(D6); // Motor L pwm = motor left
tverouden 32:a00ff9898574 44 DigitalOut pin7(D7); // Motor L direction = motor left
efvanmarrewijk 25:ac139331fe51 45
efvanmarrewijk 25:ac139331fe51 46 // Utilisation of libraries
tverouden 32:a00ff9898574 47 MODSERIAL pc(USBTX, USBRX); // communication with pc
efvanmarrewijk 25:ac139331fe51 48 QEI encoderL(D9,D8,NC,4200); // Encoder input of motor L
efvanmarrewijk 25:ac139331fe51 49 QEI encoderR(D10,D11,NC,4200); // Encoder input of motor R
efvanmarrewijk 25:ac139331fe51 50 QEI encoderF(D12,D13,NC,4200); // Encoder input of motor F
efvanmarrewijk 25:ac139331fe51 51 Ticker motorL;
efvanmarrewijk 25:ac139331fe51 52 Ticker motorR;
efvanmarrewijk 25:ac139331fe51 53 Ticker motorF;
tverouden 4:5ce2c8864908 54
tverouden 0:c0c35b95765f 55 // Define & initialise state machine
efvanmarrewijk 26:247be0bea9b1 56 const float dt = 0.002f;
tverouden 50:4a7b0a3f64cb 57 enum states { calibratingMotorL, calibratingMotorR, calibratingMotorF,
tverouden 51:78c75cc72d17 58 calibratingEMG, homing, reading, operating, failing, demoing
tverouden 2:d70795e4e0bf 59 };
tverouden 51:78c75cc72d17 60
tverouden 50:4a7b0a3f64cb 61 states currentState = calibratingMotorL; // start in motor L mode
tverouden 23:e282bdb9e9b7 62 bool changeState = true; // initialise the first state
tverouden 2:d70795e4e0bf 63
tverouden 23:e282bdb9e9b7 64 Ticker stateTimer; // state machine ticker
tverouden 19:2797bb471f9f 65
EvaKrolis 14:2c0bf576a0e7 66 //------------------------ Parameters for the EMG ----------------------------
tverouden 3:9c63fc5f157e 67
tverouden 23:e282bdb9e9b7 68 // EMG inputs
tverouden 23:e282bdb9e9b7 69 AnalogIn EMG0In(A0); // EMG input 0
tverouden 23:e282bdb9e9b7 70 AnalogIn EMG1In(A1); // EMG input 1
EvaKrolis 13:4ba8f63e6ff4 71
tverouden 23:e282bdb9e9b7 72 // Timers
tverouden 23:e282bdb9e9b7 73 Ticker FindMax0_timer; // Timer for finding the max muscle
tverouden 23:e282bdb9e9b7 74 Ticker FindMax1_timer; // Timer for finding the max muscle
EvaKrolis 13:4ba8f63e6ff4 75
tverouden 23:e282bdb9e9b7 76 // Constants
tverouden 23:e282bdb9e9b7 77 const int Length = 10000; // Length of the array for the calibration
tverouden 23:e282bdb9e9b7 78 const int Parts = 50; // Mean average filter over 50 values
EvaKrolis 13:4ba8f63e6ff4 79
tverouden 23:e282bdb9e9b7 80 // Parameters for the first EMG signal
tverouden 23:e282bdb9e9b7 81 float EMG0; // float for EMG input
tverouden 23:e282bdb9e9b7 82 float EMG0filt; // float for filtered EMG
tverouden 23:e282bdb9e9b7 83 float EMG0filtArray[Parts]; // Array for the filtered array
tverouden 23:e282bdb9e9b7 84 float EMG0Average; // float for the value after Moving Average Filter
tverouden 23:e282bdb9e9b7 85 float Sum0 = 0; // Sum0 for the moving average filter
tverouden 41:5aecc1a27ce6 86 float EMG0Calibrate[Length]; // Array for the calibration
tverouden 23:e282bdb9e9b7 87 int ReadCal0 = 0; // Integer to read over the calibration array
tverouden 23:e282bdb9e9b7 88 float MaxValue0 = 0; // float to save the max muscle
tverouden 23:e282bdb9e9b7 89 float Threshold0 = 0; // Threshold for the first EMG signal
EvaKrolis 13:4ba8f63e6ff4 90
tverouden 23:e282bdb9e9b7 91 // Parameters for the second EMG signal
tverouden 23:e282bdb9e9b7 92 float EMG1; // float for EMG input
tverouden 23:e282bdb9e9b7 93 float EMG1filt; // float for filtered EMG
tverouden 23:e282bdb9e9b7 94 float EMG1filtArray[Parts]; // Array for the filtered array
tverouden 23:e282bdb9e9b7 95 float EMG1Average; // float for the value after Moving Average Filter
tverouden 23:e282bdb9e9b7 96 float Sum1 = 0; // Sum0 for the moving average filter
tverouden 41:5aecc1a27ce6 97 float EMG1Calibrate[Length]; // Array for the calibration
tverouden 23:e282bdb9e9b7 98 int ReadCal1 = 0; // Integer to read over the calibration array
tverouden 23:e282bdb9e9b7 99 float MaxValue1 = 0; // float to save the max muscle
tverouden 23:e282bdb9e9b7 100 float Threshold1 = 0; // Threshold for the second EMG signal
EvaKrolis 13:4ba8f63e6ff4 101
EvaKrolis 13:4ba8f63e6ff4 102 //Filter variables
EvaKrolis 36:b233c549dd80 103 BiQuad Notch50_0(0.9049,-1.4641,0.9049,-1.4641,0.8098); //Make Notch filter around 50 Hz
EvaKrolis 36:b233c549dd80 104 BiQuad Notch50_1(0.9049,-1.4641,0.9049,-1.4641,0.8098); //Make Notch filter around 50 Hz
EvaKrolis 36:b233c549dd80 105 BiQuad Notch100_0(0.8427,-0.5097,0.8247,-0.5097,0.6494); //Make Notch filter around 100 Hz
EvaKrolis 36:b233c549dd80 106 BiQuad Notch100_1(0.8427,-0.5097,0.8247,-0.5097,0.6494); //Make Notch filter around 100 Hz
EvaKrolis 36:b233c549dd80 107 BiQuad Notch150_0(0.7548,0.4665,0.7544,0.4665,0.5095); //Make Notch filter around 150 Hz
EvaKrolis 36:b233c549dd80 108 BiQuad Notch150_1(0.7548,0.4665,0.7544,0.4665,0.5095); //Make Notch filter around 150 Hz
EvaKrolis 36:b233c549dd80 109 BiQuad Notch200_0(0.6919,1.1196,0.6919,1.1196,0.3839); //Make Notch filter around 200 Hz
EvaKrolis 36:b233c549dd80 110 BiQuad Notch200_1(0.6919,1.1196,0.6919,1.1196,0.3839); //Make Notch filter around 200 Hz
EvaKrolis 36:b233c549dd80 111 BiQuad High_0(0.9150,-1.8299,0.9150,-1.8227,0.8372); //Make high-pass filter
EvaKrolis 36:b233c549dd80 112 BiQuad High_1(0.9150,-1.8299,0.9150,-1.8227,0.8372); //Make high-pass filter
EvaKrolis 36:b233c549dd80 113 BiQuad Low_0(0.6389,1.2779,0.6389,1.143,0.4128); //Make low-pass filter
EvaKrolis 36:b233c549dd80 114 BiQuad Low_1(0.6389,1.2779,0.6389,1.143,0.4128); //Make low-pass filter
EvaKrolis 13:4ba8f63e6ff4 115 BiQuadChain filter0; //Make chain of filters for the first EMG signal
EvaKrolis 13:4ba8f63e6ff4 116 BiQuadChain filter1; //Make chain of filters for the second EMG signal
EvaKrolis 13:4ba8f63e6ff4 117
EvaKrolis 13:4ba8f63e6ff4 118 //Bool for movement
EvaKrolis 13:4ba8f63e6ff4 119 bool xMove = false; //Bool for the x-movement
EvaKrolis 13:4ba8f63e6ff4 120 bool yMove = false; //Bool for the y-movement
tverouden 3:9c63fc5f157e 121
EvaKrolis 14:2c0bf576a0e7 122 // -------------------- Parameters for the kinematics -------------------------
EvaKrolis 14:2c0bf576a0e7 123
EvaKrolis 14:2c0bf576a0e7 124 //Constants
EvaKrolis 14:2c0bf576a0e7 125 const double ll = 230; //Length of the lower arm
EvaKrolis 14:2c0bf576a0e7 126 const double lu = 198; //Length of the upper arm
EvaKrolis 14:2c0bf576a0e7 127 const double lb = 50; //Length of the part between the upper arms
EvaKrolis 14:2c0bf576a0e7 128 const double le = 79; //Length of the end-effector beam
EvaKrolis 14:2c0bf576a0e7 129 const double xbase = 450-lb; //Length between the motors
EvaKrolis 14:2c0bf576a0e7 130
EvaKrolis 14:2c0bf576a0e7 131 //General parameters
efvanmarrewijk 53:75076f9705dc 132 double theta1 = PI*0.40; //Angle of the left motor
efvanmarrewijk 53:75076f9705dc 133 double theta4 = PI*0.40; //Angle of the right motor
EvaKrolis 14:2c0bf576a0e7 134 double thetaflip = 0; //Angle of the flipping motor
EvaKrolis 14:2c0bf576a0e7 135 double prefx; //Desired x velocity
EvaKrolis 14:2c0bf576a0e7 136 double prefy; //Desired y velocity "
tverouden 41:5aecc1a27ce6 137 float iJ[2][2]; //inverse Jacobian matrix
EvaKrolis 14:2c0bf576a0e7 138
tverouden 44:ca74d11a2dac 139 //Kinematics parameters for x
tverouden 44:ca74d11a2dac 140 float xendsum;
tverouden 44:ca74d11a2dac 141 float xendsqrt1;
tverouden 44:ca74d11a2dac 142 float xendsqrt2;
tverouden 44:ca74d11a2dac 143 float xend;
tverouden 44:ca74d11a2dac 144
tverouden 44:ca74d11a2dac 145 //Kinematics parameters for y
tverouden 44:ca74d11a2dac 146 float yendsum;
tverouden 44:ca74d11a2dac 147 float yendsqrt1;
tverouden 44:ca74d11a2dac 148 float yendsqrt2;
tverouden 44:ca74d11a2dac 149 float yend;
tverouden 44:ca74d11a2dac 150
efvanmarrewijk 55:b297e064ebd9 151 float a;
efvanmarrewijk 55:b297e064ebd9 152 float b;
efvanmarrewijk 55:b297e064ebd9 153 float c;
efvanmarrewijk 55:b297e064ebd9 154 float d;
efvanmarrewijk 55:b297e064ebd9 155
efvanmarrewijk 55:b297e064ebd9 156 float xend1;
efvanmarrewijk 55:b297e064ebd9 157 float yend1;
efvanmarrewijk 55:b297e064ebd9 158 float xend2;
efvanmarrewijk 55:b297e064ebd9 159 float yend2;
efvanmarrewijk 55:b297e064ebd9 160 float xend3;
efvanmarrewijk 55:b297e064ebd9 161 float yend3;
efvanmarrewijk 55:b297e064ebd9 162
EvaKrolis 14:2c0bf576a0e7 163 // ---------------------- Parameters for the motors ---------------------------
efvanmarrewijk 26:247be0bea9b1 164 const float countsRad = 4200.0f;
efvanmarrewijk 26:247be0bea9b1 165 int countsL;
efvanmarrewijk 26:247be0bea9b1 166 int countsR;
efvanmarrewijk 26:247be0bea9b1 167 int countsF;
efvanmarrewijk 26:247be0bea9b1 168 int countsCalibratedL;
efvanmarrewijk 26:247be0bea9b1 169 int countsCalibratedR;
efvanmarrewijk 26:247be0bea9b1 170 int countsCalibratedF;
efvanmarrewijk 48:1eb0f9ed6cd9 171 int countsOffsetL;
efvanmarrewijk 48:1eb0f9ed6cd9 172 int countsOffsetR;
efvanmarrewijk 48:1eb0f9ed6cd9 173 int countsOffsetF;
efvanmarrewijk 26:247be0bea9b1 174 float angleCurrentL;
efvanmarrewijk 26:247be0bea9b1 175 float angleCurrentR;
efvanmarrewijk 26:247be0bea9b1 176 float angleCurrentF;
efvanmarrewijk 26:247be0bea9b1 177 float errorL;
efvanmarrewijk 26:247be0bea9b1 178 float errorR;
efvanmarrewijk 26:247be0bea9b1 179 float errorF;
efvanmarrewijk 26:247be0bea9b1 180 float errorCalibratedL;
efvanmarrewijk 26:247be0bea9b1 181 float errorCalibratedR;
efvanmarrewijk 26:247be0bea9b1 182 float errorCalibratedF;
EvaKrolis 14:2c0bf576a0e7 183
efvanmarrewijk 26:247be0bea9b1 184 int countsCalibration = 4200/4;
efvanmarrewijk 25:ac139331fe51 185
tverouden 4:5ce2c8864908 186 // ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ FUNCTIONS ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
tverouden 6:f32352bc5078 187 // ============================ GENERAL FUNCTIONS =============================
tverouden 6:f32352bc5078 188 void stopProgram(void)
tverouden 6:f32352bc5078 189 {
tverouden 6:f32352bc5078 190 // Error message
tverouden 6:f32352bc5078 191 pc.printf("[ERROR] emergency button pressed\r\n");
tverouden 6:f32352bc5078 192 currentState = failing; // change to state
tverouden 6:f32352bc5078 193 changeState = true; // next loop, switch states
tverouden 6:f32352bc5078 194 }
tverouden 8:8cef1050ebd9 195
tverouden 15:6566c5dedeeb 196 void blinkLedRed(void)
tverouden 15:6566c5dedeeb 197 {
tverouden 15:6566c5dedeeb 198 ledRed =! ledRed; // toggle LED
tverouden 10:584b7d2c2d63 199 }
tverouden 15:6566c5dedeeb 200 void blinkLedGreen(void)
tverouden 15:6566c5dedeeb 201 {
tverouden 15:6566c5dedeeb 202 ledGreen =! ledGreen; // toggle LED
tverouden 15:6566c5dedeeb 203 }
tverouden 15:6566c5dedeeb 204 void blinkLedBlue(void)
tverouden 15:6566c5dedeeb 205 {
tverouden 15:6566c5dedeeb 206 ledBlue =! ledBlue; // toggle LED
tverouden 15:6566c5dedeeb 207 }
tverouden 15:6566c5dedeeb 208
efvanmarrewijk 53:75076f9705dc 209 float angleCurrent(float counts) // Calculates the current angle of the motor (between -2*PI to 2*PI) based on the counts from the encoder
efvanmarrewijk 53:75076f9705dc 210 {
efvanmarrewijk 53:75076f9705dc 211 float angle = ((float)counts*2.0f*PI)/countsRad;
efvanmarrewijk 53:75076f9705dc 212 while (angle > 2.0f*PI) {
efvanmarrewijk 53:75076f9705dc 213 angle = angle-2.0f*PI;
efvanmarrewijk 53:75076f9705dc 214 }
efvanmarrewijk 53:75076f9705dc 215 while (angle < -2.0f*PI) {
efvanmarrewijk 53:75076f9705dc 216 angle = angle+2.0f*PI;
efvanmarrewijk 53:75076f9705dc 217 }
efvanmarrewijk 53:75076f9705dc 218 return angle;
efvanmarrewijk 53:75076f9705dc 219 }
efvanmarrewijk 53:75076f9705dc 220
tverouden 4:5ce2c8864908 221 // ============================= EMG FUNCTIONS ===============================
tverouden 4:5ce2c8864908 222
EvaKrolis 13:4ba8f63e6ff4 223 //Function to read and filter the EMG
tverouden 41:5aecc1a27ce6 224 void ReadUseEMG0()
tverouden 41:5aecc1a27ce6 225 {
tverouden 41:5aecc1a27ce6 226 for(int i = Parts ; i > 0 ; i--) { //Make a first in, first out array
EvaKrolis 13:4ba8f63e6ff4 227 EMG0filtArray[i] = EMG0filtArray[i-1]; //Every value moves one up
EvaKrolis 13:4ba8f63e6ff4 228 }
tverouden 41:5aecc1a27ce6 229
EvaKrolis 13:4ba8f63e6ff4 230 Sum0 = 0;
EvaKrolis 13:4ba8f63e6ff4 231 EMG0 = EMG0In; //Save EMG input in float
EvaKrolis 13:4ba8f63e6ff4 232 EMG0filt = filter0.step(EMG0); //Filter the signal
EvaKrolis 13:4ba8f63e6ff4 233 EMG0filt = abs(EMG0filt); //Take the absolute value
EvaKrolis 13:4ba8f63e6ff4 234 EMG0filtArray[0] = EMG0filt; //Save the filtered signal on the first place in the array
tverouden 41:5aecc1a27ce6 235
tverouden 41:5aecc1a27ce6 236 for(int i = 0 ; i < Parts ; i++) { //Moving Average filter
EvaKrolis 13:4ba8f63e6ff4 237 Sum0 += EMG0filtArray[i]; //Sum the new value and the previous 49
EvaKrolis 13:4ba8f63e6ff4 238 }
EvaKrolis 13:4ba8f63e6ff4 239 EMG0Average = (float)Sum0/Parts; //Divide the sum by 50
tverouden 41:5aecc1a27ce6 240
tverouden 41:5aecc1a27ce6 241 if (EMG0Average > Threshold0) { //If the value is higher than the threshold value
EvaKrolis 13:4ba8f63e6ff4 242 xMove = true; //Set movement to true
tverouden 41:5aecc1a27ce6 243 } else {
tverouden 41:5aecc1a27ce6 244 xMove = false; //Otherwise set movement to false
EvaKrolis 13:4ba8f63e6ff4 245 }
EvaKrolis 13:4ba8f63e6ff4 246 }
EvaKrolis 13:4ba8f63e6ff4 247
EvaKrolis 13:4ba8f63e6ff4 248 //Function to read and filter the EMG
tverouden 41:5aecc1a27ce6 249 void ReadUseEMG1()
tverouden 41:5aecc1a27ce6 250 {
tverouden 41:5aecc1a27ce6 251 for(int i = Parts ; i > 0 ; i--) { //Make a first in, first out array
EvaKrolis 13:4ba8f63e6ff4 252 EMG1filtArray[i] = EMG1filtArray[i-1]; //Every value moves one up
EvaKrolis 13:4ba8f63e6ff4 253 }
tverouden 41:5aecc1a27ce6 254
EvaKrolis 13:4ba8f63e6ff4 255 Sum1 = 0;
EvaKrolis 13:4ba8f63e6ff4 256 EMG1 = EMG1In; //Save EMG input in float
EvaKrolis 13:4ba8f63e6ff4 257 EMG1filt = filter1.step(EMG1); //Filter the signal
EvaKrolis 13:4ba8f63e6ff4 258 EMG1filt = abs(EMG1filt); //Take the absolute value
EvaKrolis 13:4ba8f63e6ff4 259 EMG1filtArray[0] = EMG1filt; //Save the filtered signal on the first place in the array
tverouden 41:5aecc1a27ce6 260
tverouden 41:5aecc1a27ce6 261 for(int i = 0 ; i < Parts ; i++) { //Moving Average filter
EvaKrolis 13:4ba8f63e6ff4 262 Sum1 += EMG1filtArray[i]; //Sum the new value and the previous 49
EvaKrolis 13:4ba8f63e6ff4 263 }
EvaKrolis 13:4ba8f63e6ff4 264 EMG1Average = (float)Sum1/Parts; //Divide the sum by 50
tverouden 41:5aecc1a27ce6 265
tverouden 41:5aecc1a27ce6 266 if (EMG1Average > Threshold1) { //If the value is higher than the threshold value
EvaKrolis 13:4ba8f63e6ff4 267 yMove = true; //Set y movement to true
tverouden 41:5aecc1a27ce6 268 } else {
EvaKrolis 13:4ba8f63e6ff4 269 yMove = false; //Otherwise set y movement to false
EvaKrolis 13:4ba8f63e6ff4 270 }
EvaKrolis 13:4ba8f63e6ff4 271 }
EvaKrolis 13:4ba8f63e6ff4 272
EvaKrolis 13:4ba8f63e6ff4 273 //Function to make an array during the calibration
tverouden 41:5aecc1a27ce6 274 void CalibrateEMG0()
tverouden 41:5aecc1a27ce6 275 {
tverouden 41:5aecc1a27ce6 276 for(int i = Parts ; i > 0 ; i--) { //Make a first in, first out array
EvaKrolis 13:4ba8f63e6ff4 277 EMG0filtArray[i] = EMG0filtArray[i-1]; //Every value moves one up
EvaKrolis 13:4ba8f63e6ff4 278 }
tverouden 41:5aecc1a27ce6 279
EvaKrolis 13:4ba8f63e6ff4 280 Sum0 = 0;
EvaKrolis 13:4ba8f63e6ff4 281 EMG0 = EMG0In; //Save EMG input in float
EvaKrolis 13:4ba8f63e6ff4 282 EMG0filt = filter0.step(EMG0); //Filter the signal
EvaKrolis 13:4ba8f63e6ff4 283 EMG0filt = abs(EMG0filt); //Take the absolute value
EvaKrolis 13:4ba8f63e6ff4 284 EMG0filtArray[0] = EMG0filt; //Save the filtered signal on the first place in the array
tverouden 41:5aecc1a27ce6 285
tverouden 41:5aecc1a27ce6 286 for(int i = 0 ; i < Parts ; i++) { //Moving Average filter
EvaKrolis 13:4ba8f63e6ff4 287 Sum0 += EMG0filtArray[i]; //Sum the new value and the previous 49
EvaKrolis 13:4ba8f63e6ff4 288 }
EvaKrolis 13:4ba8f63e6ff4 289 EMG0Calibrate[ReadCal0] = (float)Sum0/Parts; //Divide the sum by 50
tverouden 41:5aecc1a27ce6 290
EvaKrolis 13:4ba8f63e6ff4 291 ReadCal0++;
EvaKrolis 13:4ba8f63e6ff4 292 }
EvaKrolis 13:4ba8f63e6ff4 293
EvaKrolis 13:4ba8f63e6ff4 294 //Function to make an array during the calibration
tverouden 41:5aecc1a27ce6 295 void CalibrateEMG1()
tverouden 41:5aecc1a27ce6 296 {
tverouden 41:5aecc1a27ce6 297 for(int i = Parts ; i > 0 ; i--) { //Make a first in, first out array
EvaKrolis 13:4ba8f63e6ff4 298 EMG1filtArray[i] = EMG1filtArray[i-1]; //Every value moves one up
EvaKrolis 13:4ba8f63e6ff4 299 }
tverouden 41:5aecc1a27ce6 300
EvaKrolis 13:4ba8f63e6ff4 301 Sum1 = 0;
EvaKrolis 13:4ba8f63e6ff4 302 EMG1 = EMG1In; //Save EMG input in float
EvaKrolis 13:4ba8f63e6ff4 303 EMG1filt = filter1.step(EMG1); //Filter the signal
EvaKrolis 13:4ba8f63e6ff4 304 EMG1filt = abs(EMG1filt); //Take the absolute value
EvaKrolis 13:4ba8f63e6ff4 305 EMG1filtArray[0] = EMG1filt; //Save the filtered signal on the first place in the array
tverouden 41:5aecc1a27ce6 306
tverouden 41:5aecc1a27ce6 307 for(int i = 0 ; i < Parts ; i++) { //Moving Average filter
EvaKrolis 13:4ba8f63e6ff4 308 Sum1 += EMG1filtArray[i]; //Sum the new value and the previous 49
EvaKrolis 13:4ba8f63e6ff4 309 }
EvaKrolis 13:4ba8f63e6ff4 310 EMG1Calibrate[ReadCal1] = (float)Sum1/Parts; //Divide the sum by 50
tverouden 41:5aecc1a27ce6 311
EvaKrolis 13:4ba8f63e6ff4 312 ReadCal1++;
EvaKrolis 13:4ba8f63e6ff4 313 }
EvaKrolis 13:4ba8f63e6ff4 314
EvaKrolis 13:4ba8f63e6ff4 315 //Function to find the max value during the calibration
tverouden 41:5aecc1a27ce6 316 void FindMax0()
tverouden 41:5aecc1a27ce6 317 {
EvaKrolis 13:4ba8f63e6ff4 318 MaxValue0 = *max_element(EMG0Calibrate+500,EMG0Calibrate+Length); //Find max value, but discard the first 100 values
EvaKrolis 13:4ba8f63e6ff4 319 Threshold0 = 0.30f*MaxValue0; //The threshold is a percentage of the max value
EvaKrolis 13:4ba8f63e6ff4 320 pc.printf("The calibration value of the first EMG is %f.\n\r The threshold is %f. \n\r",MaxValue0,Threshold0); //Print the max value and the threshold
EvaKrolis 13:4ba8f63e6ff4 321 FindMax0_timer.detach(); //Detach the timer, so you only use this once
EvaKrolis 13:4ba8f63e6ff4 322 }
EvaKrolis 13:4ba8f63e6ff4 323
EvaKrolis 13:4ba8f63e6ff4 324 //Function to find the max value during the calibration
tverouden 41:5aecc1a27ce6 325 void FindMax1()
tverouden 41:5aecc1a27ce6 326 {
EvaKrolis 13:4ba8f63e6ff4 327 MaxValue1 = *max_element(EMG1Calibrate+500,EMG1Calibrate+Length); //Find max value, but discard the first 100 values
EvaKrolis 13:4ba8f63e6ff4 328 Threshold1 = 0.30f*MaxValue1; //The threshold is a percentage of the max value
EvaKrolis 13:4ba8f63e6ff4 329 pc.printf("The calibration value of the second EMG is %f.\n\r The threshold is %f. \n\r",MaxValue1,Threshold1); //Print the Max value and the threshold
EvaKrolis 13:4ba8f63e6ff4 330 FindMax1_timer.detach(); //Detach the timer, so you only use this once
EvaKrolis 13:4ba8f63e6ff4 331 }
tverouden 4:5ce2c8864908 332
tverouden 12:323ac4e27a0d 333 // ========================= KINEMATICS FUNCTIONS ============================
tverouden 12:323ac4e27a0d 334
efvanmarrewijk 55:b297e064ebd9 335
efvanmarrewijk 55:b297e064ebd9 336
tverouden 41:5aecc1a27ce6 337 //forward kinematics function , &xend and&yend are output.
efvanmarrewijk 55:b297e064ebd9 338 void kinematicsForward1(float theta1_, float theta4_)
EvaKrolis 14:2c0bf576a0e7 339 {
tverouden 41:5aecc1a27ce6 340
tverouden 41:5aecc1a27ce6 341 //Below we have the forward kinematics formula. Input should be the measured angles theta1 &theta4. Output
tverouden 41:5aecc1a27ce6 342
tverouden 41:5aecc1a27ce6 343 float xendsum_ = lb + xbase +ll*(cos(theta1_) - cos(theta4_));
tverouden 41:5aecc1a27ce6 344 float xendsqrt1_ = 2*sqrt(-xbase*xbase/4 + lu*lu + ll*(xbase*(cos(theta1_)+cos(theta4_))/2) -ll*(1+ cos(theta1_+theta4_)))*(-sin(theta1_)+sin(theta4_));
tverouden 41:5aecc1a27ce6 345 float xendsqrt2_ = sqrt(pow((-xbase/ll+cos(theta1_)+cos(theta4_)),2)+ pow(sin(theta1_) - sin(theta4_),2));
efvanmarrewijk 55:b297e064ebd9 346 xend1 = (xendsum_ + xendsqrt1_/xendsqrt2_)/2;
efvanmarrewijk 55:b297e064ebd9 347
efvanmarrewijk 55:b297e064ebd9 348 float yendsum_ = -le + ll/2*(sin(theta1_)+sin(theta4_));
efvanmarrewijk 55:b297e064ebd9 349 float yendsqrt1_ = (-xbase/ll + cos(theta1_)+cos(theta4_))*sqrt(-xbase*xbase/4 + lu*lu + ll/2*(xbase*(cos(theta1_)+cos(theta4_))- ll*(1+cos(theta1_+theta4_))));
efvanmarrewijk 55:b297e064ebd9 350 float yendsqrt2_ = sqrt(pow((-xbase/ll + cos(theta1_)+ cos(theta4_)),2)+ pow((sin(theta1_)-sin(theta4_)),2));
efvanmarrewijk 55:b297e064ebd9 351 yend1 = (yendsum_ + yendsqrt1_/yendsqrt2_);
efvanmarrewijk 55:b297e064ebd9 352
efvanmarrewijk 55:b297e064ebd9 353 }
efvanmarrewijk 55:b297e064ebd9 354
efvanmarrewijk 55:b297e064ebd9 355 //forward kinematics function , &xend and&yend are output.
efvanmarrewijk 55:b297e064ebd9 356 void kinematicsForward2(float theta1_, float theta4_)
efvanmarrewijk 55:b297e064ebd9 357 {
efvanmarrewijk 55:b297e064ebd9 358
efvanmarrewijk 55:b297e064ebd9 359 //Below we have the forward kinematics formula. Input should be the measured angles theta1 &theta4. Output
efvanmarrewijk 55:b297e064ebd9 360
efvanmarrewijk 55:b297e064ebd9 361 float xendsum_ = lb + xbase +ll*(cos(theta1_) - cos(theta4_));
efvanmarrewijk 55:b297e064ebd9 362 float xendsqrt1_ = 2*sqrt(-xbase*xbase/4 + lu*lu + ll*(xbase*(cos(theta1_)+cos(theta4_))/2) -ll*(1+ cos(theta1_+theta4_)))*(-sin(theta1_)+sin(theta4_));
efvanmarrewijk 55:b297e064ebd9 363 float xendsqrt2_ = sqrt(pow((-xbase/ll+cos(theta1_)+cos(theta4_)),2)+ pow(sin(theta1_) - sin(theta4_),2));
efvanmarrewijk 55:b297e064ebd9 364 xend2 = (xendsum_ + xendsqrt1_/xendsqrt2_)/2;
EvaKrolis 14:2c0bf576a0e7 365
tverouden 41:5aecc1a27ce6 366 float yendsum_ = -le + ll/2*(sin(theta1_)+sin(theta4_));
tverouden 41:5aecc1a27ce6 367 float yendsqrt1_ = (-xbase/ll + cos(theta1_)+cos(theta4_))*sqrt(-xbase*xbase/4 + lu*lu + ll/2*(xbase*(cos(theta1_)+cos(theta4_))- ll*(1+cos(theta1_+theta4_))));
tverouden 41:5aecc1a27ce6 368 float yendsqrt2_ = sqrt(pow((-xbase/ll + cos(theta1_)+ cos(theta4_)),2)+ pow((sin(theta1_)-sin(theta4_)),2));
efvanmarrewijk 55:b297e064ebd9 369 yend2 = (yendsum_ + yendsqrt1_/yendsqrt2_);
efvanmarrewijk 55:b297e064ebd9 370
tverouden 41:5aecc1a27ce6 371 }
tverouden 41:5aecc1a27ce6 372
efvanmarrewijk 55:b297e064ebd9 373 //forward kinematics function , &xend and&yend are output.
efvanmarrewijk 55:b297e064ebd9 374 void kinematicsForward3(float theta1_, float theta4_)
efvanmarrewijk 55:b297e064ebd9 375 {
efvanmarrewijk 55:b297e064ebd9 376
efvanmarrewijk 55:b297e064ebd9 377 //Below we have the forward kinematics formula. Input should be the measured angles theta1 &theta4. Output
efvanmarrewijk 55:b297e064ebd9 378
efvanmarrewijk 55:b297e064ebd9 379 float xendsum_ = lb + xbase +ll*(cos(theta1_) - cos(theta4_));
efvanmarrewijk 55:b297e064ebd9 380 float xendsqrt1_ = 2*sqrt(-xbase*xbase/4 + lu*lu + ll*(xbase*(cos(theta1_)+cos(theta4_))/2) -ll*(1+ cos(theta1_+theta4_)))*(-sin(theta1_)+sin(theta4_));
efvanmarrewijk 55:b297e064ebd9 381 float xendsqrt2_ = sqrt(pow((-xbase/ll+cos(theta1_)+cos(theta4_)),2)+ pow(sin(theta1_) - sin(theta4_),2));
efvanmarrewijk 55:b297e064ebd9 382 xend3 = (xendsum_ + xendsqrt1_/xendsqrt2_)/2;
efvanmarrewijk 55:b297e064ebd9 383
efvanmarrewijk 55:b297e064ebd9 384 float yendsum_ = -le + ll/2*(sin(theta1_)+sin(theta4_));
efvanmarrewijk 55:b297e064ebd9 385 float yendsqrt1_ = (-xbase/ll + cos(theta1_)+cos(theta4_))*sqrt(-xbase*xbase/4 + lu*lu + ll/2*(xbase*(cos(theta1_)+cos(theta4_))- ll*(1+cos(theta1_+theta4_))));
efvanmarrewijk 55:b297e064ebd9 386 float yendsqrt2_ = sqrt(pow((-xbase/ll + cos(theta1_)+ cos(theta4_)),2)+ pow((sin(theta1_)-sin(theta4_)),2));
efvanmarrewijk 55:b297e064ebd9 387 yend3 = (yendsum_ + yendsqrt1_/yendsqrt2_);
efvanmarrewijk 55:b297e064ebd9 388
efvanmarrewijk 55:b297e064ebd9 389 }
efvanmarrewijk 55:b297e064ebd9 390
efvanmarrewijk 55:b297e064ebd9 391
tverouden 41:5aecc1a27ce6 392 //Below we have the inverse kinematics function.
tverouden 41:5aecc1a27ce6 393 void kinematicsInverse(float prex, float prey)
tverouden 41:5aecc1a27ce6 394 {
tverouden 41:5aecc1a27ce6 395
tverouden 41:5aecc1a27ce6 396 theta1 += (prefx*(iJ[0][0])-iJ[0][1]*prey)*dt; //theta 1 is itself + the desired speeds in x and y direction, both
tverouden 41:5aecc1a27ce6 397 theta4 += (prefx*iJ[1][0]-iJ[1][1]*prey)*dt; //multiplied with a prefactor which comes out of the motor
tverouden 41:5aecc1a27ce6 398 //the iJ values are defined in the "kinematics" function
tverouden 41:5aecc1a27ce6 399
tverouden 41:5aecc1a27ce6 400 //Calling the forward kinematics, to calculate xend and yend
efvanmarrewijk 55:b297e064ebd9 401 kinematicsForward1(/*xend,yend,*/angleCurrent(countsCalibratedL),angleCurrent(countsCalibratedR));
EvaKrolis 14:2c0bf576a0e7 402
EvaKrolis 14:2c0bf576a0e7 403 }
EvaKrolis 14:2c0bf576a0e7 404
EvaKrolis 14:2c0bf576a0e7 405 void kinematics()
EvaKrolis 14:2c0bf576a0e7 406 {
efvanmarrewijk 55:b297e064ebd9 407 //float xend1,xend2,xend3,yend1,yend2,yend3;
EvaKrolis 14:2c0bf576a0e7 408
tverouden 41:5aecc1a27ce6 409 const float dq = 0.001; //benadering van 'delta' hoek
efvanmarrewijk 55:b297e064ebd9 410
efvanmarrewijk 55:b297e064ebd9 411 kinematicsForward1(/*xend1,yend1,*/angleCurrent(countsCalibratedL),angleCurrent(countsCalibratedR));
efvanmarrewijk 55:b297e064ebd9 412 kinematicsForward2(/*xend2,yend2,*/angleCurrent(countsCalibratedL)+dq,angleCurrent(countsCalibratedR));
efvanmarrewijk 55:b297e064ebd9 413 kinematicsForward3(/*xend3,yend3,*/angleCurrent(countsCalibratedL),angleCurrent(countsCalibratedR)+dq);
efvanmarrewijk 55:b297e064ebd9 414
efvanmarrewijk 55:b297e064ebd9 415 //float a,b,c,d;
tverouden 41:5aecc1a27ce6 416 a = xend2-xend1;
tverouden 41:5aecc1a27ce6 417 b = xend3-xend1;
tverouden 41:5aecc1a27ce6 418 c = yend2-yend1;
tverouden 41:5aecc1a27ce6 419 d = yend3-yend1;
tverouden 41:5aecc1a27ce6 420
tverouden 41:5aecc1a27ce6 421 float Q = 1/(a*d-b*c)/dq;
EvaKrolis 14:2c0bf576a0e7 422
tverouden 41:5aecc1a27ce6 423 iJ[0][0] = d*Q;
tverouden 41:5aecc1a27ce6 424 iJ[0][1]= -c*Q;
tverouden 41:5aecc1a27ce6 425 iJ[1][0] = -b*Q;
tverouden 41:5aecc1a27ce6 426 iJ[1][1] = a*Q;
EvaKrolis 14:2c0bf576a0e7 427
efvanmarrewijk 55:b297e064ebd9 428 prefx = 0.00001*xMove; //sw3, Prefx has multiplier one, // Gain aanpassen eventueel??
tverouden 41:5aecc1a27ce6 429 // but that has to become a value
tverouden 41:5aecc1a27ce6 430 // dependant on the motor
efvanmarrewijk 55:b297e064ebd9 431 prefy = 0.00001*yMove; //sw2,
tverouden 41:5aecc1a27ce6 432 kinematicsInverse(prefx, prefy);
tverouden 41:5aecc1a27ce6 433 }
tverouden 41:5aecc1a27ce6 434
tverouden 41:5aecc1a27ce6 435 // these values are printed for controlling purposes (can later be removed)
tverouden 41:5aecc1a27ce6 436 void printvalue()
tverouden 41:5aecc1a27ce6 437 {
tverouden 41:5aecc1a27ce6 438 pc.printf("X-value: %f \t Y-value: %f \n\r \t theta 1 = %f \t theta4 = %f\n\r",xend, yend,theta1,theta4);
tverouden 41:5aecc1a27ce6 439 //pc.printf("%f\n\r",xend1);
EvaKrolis 14:2c0bf576a0e7 440 }
tverouden 12:323ac4e27a0d 441
efvanmarrewijk 25:ac139331fe51 442 // ============================ MOTOR FUNCTIONS ===============================
efvanmarrewijk 25:ac139331fe51 443 // angleDesired now defined as angle of potmeter and not the angle as output from the kinematics
efvanmarrewijk 25:ac139331fe51 444 // So, the angleDesired needs to be defined again and the part in which the potmeter value is calculated needs to be commented
efvanmarrewijk 25:ac139331fe51 445
efvanmarrewijk 25:ac139331fe51 446 // ------------------------ General motor functions ----------------------------
tverouden 41:5aecc1a27ce6 447 int countsInputL() // Gets the counts from encoder 1
tverouden 41:5aecc1a27ce6 448 {
tverouden 41:5aecc1a27ce6 449 countsL = encoderL.getPulses();
tverouden 41:5aecc1a27ce6 450 return countsL;
tverouden 41:5aecc1a27ce6 451 }
tverouden 41:5aecc1a27ce6 452 int countsInputR() // Gets the counts from encoder 2
tverouden 41:5aecc1a27ce6 453 {
tverouden 41:5aecc1a27ce6 454 countsR = encoderR.getPulses();
tverouden 41:5aecc1a27ce6 455 return countsR;
tverouden 41:5aecc1a27ce6 456 }
tverouden 41:5aecc1a27ce6 457 int countsInputF() // Gets the counts from encoder 3
tverouden 41:5aecc1a27ce6 458 {
tverouden 41:5aecc1a27ce6 459 countsF = encoderF.getPulses();
tverouden 41:5aecc1a27ce6 460 return countsF;
tverouden 41:5aecc1a27ce6 461 }
efvanmarrewijk 25:ac139331fe51 462
tverouden 41:5aecc1a27ce6 463 float errorCalc(float angleReference,float angleCurrent) // Calculates the error of the system, based on the current angle and the reference value
tverouden 41:5aecc1a27ce6 464 {
tverouden 41:5aecc1a27ce6 465 float error = angleReference - angleCurrent;
tverouden 41:5aecc1a27ce6 466 return error;
tverouden 41:5aecc1a27ce6 467 }
efvanmarrewijk 25:ac139331fe51 468
efvanmarrewijk 52:17b3aeacb643 469 float angleDesired() // Sets the desired angle for the controller dependent on the scaled angle of potmeter 1
efvanmarrewijk 52:17b3aeacb643 470 {
efvanmarrewijk 52:17b3aeacb643 471 float angle = (pot2*2.0f*PI)-PI;
efvanmarrewijk 52:17b3aeacb643 472 return angle;
efvanmarrewijk 52:17b3aeacb643 473 }
efvanmarrewijk 52:17b3aeacb643 474
efvanmarrewijk 25:ac139331fe51 475 // ------------------------- MOTOR FUNCTIONS FOR MOTOR LEFT --------------------
efvanmarrewijk 49:0ada5a721686 476 float PIDControllerL(float angleReference,float angleCurrent) // PID controller for the motors, based on the reference value and the current angle of the motor
tverouden 41:5aecc1a27ce6 477 {
tverouden 41:5aecc1a27ce6 478 float Kp = 19.24f;
tverouden 41:5aecc1a27ce6 479 float Ki = 1.02f;
tverouden 41:5aecc1a27ce6 480 float Kd = 0.827f;
tverouden 41:5aecc1a27ce6 481 float error = errorCalc(angleReference,angleCurrent);
tverouden 41:5aecc1a27ce6 482 static float errorIntegralL = 0.0;
tverouden 41:5aecc1a27ce6 483 static float errorPreviousL = error; // initialization with this value only done once!
tverouden 41:5aecc1a27ce6 484 static BiQuad PIDFilterL(0.0640, 0.1279, 0.0640, -1.1683, 0.4241);
tverouden 41:5aecc1a27ce6 485 // Proportional part:
tverouden 41:5aecc1a27ce6 486 float u_k = Kp * error;
tverouden 41:5aecc1a27ce6 487 // Integral part
tverouden 41:5aecc1a27ce6 488 errorIntegralL = errorIntegralL + error * dt;
tverouden 41:5aecc1a27ce6 489 float u_i = Ki * errorIntegralL;
tverouden 41:5aecc1a27ce6 490 // Derivative part
tverouden 41:5aecc1a27ce6 491 float errorDerivative = (error - errorPreviousL)/dt;
tverouden 41:5aecc1a27ce6 492 float errorDerivativeFiltered = PIDFilterL.step(errorDerivative);
tverouden 41:5aecc1a27ce6 493 float u_d = Kd * errorDerivativeFiltered;
tverouden 41:5aecc1a27ce6 494 errorPreviousL = error;
tverouden 41:5aecc1a27ce6 495 // Sum all parts and return it
tverouden 41:5aecc1a27ce6 496 return u_k + u_i + u_d;
tverouden 41:5aecc1a27ce6 497 }
efvanmarrewijk 25:ac139331fe51 498
tverouden 51:78c75cc72d17 499 int countsInputCalibratedL() // Gets the counts from encoder 1
tverouden 51:78c75cc72d17 500 {
tverouden 51:78c75cc72d17 501 countsL = encoderL.getPulses()- countsOffsetL + countsCalibration;
tverouden 51:78c75cc72d17 502 return countsL;
tverouden 51:78c75cc72d17 503 }
tverouden 41:5aecc1a27ce6 504
efvanmarrewijk 48:1eb0f9ed6cd9 505 void motorTurnL() // main function for movement of motor 1, all above functions with an extra tab are called
tverouden 41:5aecc1a27ce6 506 {
efvanmarrewijk 55:b297e064ebd9 507 float angleReferenceL = angleDesired(); // insert kinematics output here instead of angleDesired()
efvanmarrewijk 48:1eb0f9ed6cd9 508 angleReferenceL = -angleReferenceL; // different minus sign per motor
efvanmarrewijk 48:1eb0f9ed6cd9 509 countsL = countsInputCalibratedL(); // different encoder pins per motor
efvanmarrewijk 48:1eb0f9ed6cd9 510 angleCurrentL = angleCurrent(countsL); // different minus sign per motor
efvanmarrewijk 48:1eb0f9ed6cd9 511 errorL = errorCalc(angleReferenceL,angleCurrentL); // same for every motor
tverouden 51:78c75cc72d17 512
efvanmarrewijk 48:1eb0f9ed6cd9 513 float PIDControlL = PIDControllerL(angleReferenceL,angleCurrentL); // same for every motor
efvanmarrewijk 48:1eb0f9ed6cd9 514 pin6 = fabs(PIDControlL); // different pins for every motor
efvanmarrewijk 48:1eb0f9ed6cd9 515 pin7 = PIDControlL > 0.0f; // different pins for every motor
tverouden 41:5aecc1a27ce6 516 }
EvaKrolis 13:4ba8f63e6ff4 517
efvanmarrewijk 25:ac139331fe51 518 void calibrationL() // Partially the same as motorTurnL, only with potmeter input
efvanmarrewijk 25:ac139331fe51 519 // How it works: manually turn motor using potmeters until the robot arm touches the bookholder.
efvanmarrewijk 25:ac139331fe51 520 // This program sets the counts from the motor to the reference counts (an angle of PI/4.0)
efvanmarrewijk 25:ac139331fe51 521 // Do this for every motor and after calibrated all motors, press a button
tverouden 41:5aecc1a27ce6 522 {
efvanmarrewijk 52:17b3aeacb643 523 float angleReferenceL = angleDesired(); // insert kinematics output here instead of angleDesired()
efvanmarrewijk 25:ac139331fe51 524 angleReferenceL = -angleReferenceL; // different minus sign per motor
efvanmarrewijk 48:1eb0f9ed6cd9 525 countsL = countsInputL(); // different encoder pins per motor
efvanmarrewijk 25:ac139331fe51 526 angleCurrentL = angleCurrent(countsL); // different minus sign per motor
efvanmarrewijk 25:ac139331fe51 527 errorL = errorCalc(angleReferenceL,angleCurrentL); // same for every motor
tverouden 41:5aecc1a27ce6 528
tverouden 41:5aecc1a27ce6 529 if (fabs(errorL) >= 0.01f) {
tverouden 41:5aecc1a27ce6 530 float PIDControlL = PIDControllerL(angleReferenceL,angleCurrentL); // same for every motor
efvanmarrewijk 25:ac139331fe51 531 pin6 = fabs(PIDControlL); // different pins for every motor
efvanmarrewijk 25:ac139331fe51 532 pin7 = PIDControlL > 0.0f; // different pins for every motor
tverouden 41:5aecc1a27ce6 533 } else if (fabs(errorL) < 0.01f) {
tverouden 51:78c75cc72d17 534 countsOffsetL = countsL;
efvanmarrewijk 56:e8d568d455a0 535 //countsL = countsL - countsOffsetL + countsCalibration;
tverouden 51:78c75cc72d17 536 //countsL = 0;
tverouden 41:5aecc1a27ce6 537 pin6 = 0.0f;
tverouden 41:5aecc1a27ce6 538 // BUTTON PRESS: TO NEXT STATE
tverouden 41:5aecc1a27ce6 539 }
tverouden 41:5aecc1a27ce6 540 }
tverouden 41:5aecc1a27ce6 541
efvanmarrewijk 49:0ada5a721686 542 // ------------------------ MOTOR FUNCTIONS FOR MOTOR RIGHT --------------------
tverouden 41:5aecc1a27ce6 543 float PIDControllerR(float angleReference,float angleCurrent) // PID controller for the motors, based on the reference value and the current angle of the motor
tverouden 41:5aecc1a27ce6 544 {
tverouden 41:5aecc1a27ce6 545 float Kp = 19.24f;
tverouden 41:5aecc1a27ce6 546 float Ki = 1.02f;
tverouden 41:5aecc1a27ce6 547 float Kd = 0.827f;
tverouden 41:5aecc1a27ce6 548 float error = errorCalc(angleReference,angleCurrent);
tverouden 41:5aecc1a27ce6 549 static float errorIntegralR = 0.0;
tverouden 41:5aecc1a27ce6 550 static float errorPreviousR = error; // initialization with this value only done once!
tverouden 41:5aecc1a27ce6 551 static BiQuad PIDFilterR(0.0640, 0.1279, 0.0640, -1.1683, 0.4241);
tverouden 41:5aecc1a27ce6 552 // Proportional part:
tverouden 41:5aecc1a27ce6 553 float u_k = Kp * error;
tverouden 41:5aecc1a27ce6 554 // Integral part
tverouden 41:5aecc1a27ce6 555 errorIntegralR = errorIntegralR + error * dt;
tverouden 41:5aecc1a27ce6 556 float u_i = Ki * errorIntegralR;
tverouden 41:5aecc1a27ce6 557 // Derivative part
tverouden 41:5aecc1a27ce6 558 float errorDerivative = (error - errorPreviousR)/dt;
tverouden 41:5aecc1a27ce6 559 float errorDerivativeFiltered = PIDFilterR.step(errorDerivative);
tverouden 41:5aecc1a27ce6 560 float u_d = Kd * errorDerivativeFiltered;
tverouden 41:5aecc1a27ce6 561 errorPreviousR = error;
tverouden 41:5aecc1a27ce6 562 // Sum all parts and return it
tverouden 41:5aecc1a27ce6 563 return u_k + u_i + u_d;
tverouden 41:5aecc1a27ce6 564 }
efvanmarrewijk 49:0ada5a721686 565
tverouden 51:78c75cc72d17 566 int countsInputCalibratedR() // Gets the counts from encoder 1
tverouden 51:78c75cc72d17 567 {
tverouden 51:78c75cc72d17 568 countsR = encoderR.getPulses()- countsOffsetR + countsCalibration;
tverouden 51:78c75cc72d17 569 return countsR;
tverouden 51:78c75cc72d17 570 }
tverouden 41:5aecc1a27ce6 571
efvanmarrewijk 49:0ada5a721686 572 void motorTurnR() // main function for movement of motor 1, all above functions with an extra tab are called
tverouden 41:5aecc1a27ce6 573 {
efvanmarrewijk 55:b297e064ebd9 574 float angleReferenceR = angleDesired(); // insert kinematics output here instead of angleDesired()
efvanmarrewijk 49:0ada5a721686 575 angleReferenceR = -angleReferenceR; // different minus sign per motor
efvanmarrewijk 49:0ada5a721686 576 countsR = countsInputCalibratedR(); // different encoder pins per motor
efvanmarrewijk 49:0ada5a721686 577 angleCurrentR = angleCurrent(countsR); // different minus sign per motor
efvanmarrewijk 49:0ada5a721686 578 errorR = errorCalc(angleReferenceR,angleCurrentR); // same for every motor
tverouden 51:78c75cc72d17 579
efvanmarrewijk 49:0ada5a721686 580 float PIDControlR = PIDControllerR(angleReferenceR,angleCurrentR); // same for every motor
efvanmarrewijk 49:0ada5a721686 581 pin5 = fabs(PIDControlR); // different pins for every motor
efvanmarrewijk 49:0ada5a721686 582 pin4 = PIDControlR > 0.0f; // different pins for every motor
efvanmarrewijk 49:0ada5a721686 583 }
efvanmarrewijk 49:0ada5a721686 584
efvanmarrewijk 49:0ada5a721686 585 void calibrationR() // Partially the same as motorTurnR, only with potmeter input
efvanmarrewijk 49:0ada5a721686 586 // How it works: manually turn motor using potmeters until the robot arm touches the bookholder.
efvanmarrewijk 49:0ada5a721686 587 // This program sets the counts from the motor to the reference counts (an angle of PI/4.0)
efvanmarrewijk 49:0ada5a721686 588 // Do this for every motor and after calibrated all motors, press a button
tverouden 41:5aecc1a27ce6 589 {
efvanmarrewijk 52:17b3aeacb643 590 float angleReferenceR = angleDesired(); // insert kinematics output here instead of angleDesired()
efvanmarrewijk 49:0ada5a721686 591 angleReferenceR = -angleReferenceR; // different minus sign per motor
efvanmarrewijk 49:0ada5a721686 592 countsR = countsInputR(); // different encoder pins per motor
efvanmarrewijk 49:0ada5a721686 593 angleCurrentR = angleCurrent(countsR); // different minus sign per motor
efvanmarrewijk 49:0ada5a721686 594 errorR = errorCalc(angleReferenceR,angleCurrentR); // same for every motor
tverouden 41:5aecc1a27ce6 595
tverouden 41:5aecc1a27ce6 596 if (fabs(errorR) >= 0.01f) {
tverouden 41:5aecc1a27ce6 597 float PIDControlR = PIDControllerR(angleReferenceR,angleCurrentR); // same for every motor
efvanmarrewijk 49:0ada5a721686 598 pin5 = fabs(PIDControlR); // different pins for every motor
efvanmarrewijk 49:0ada5a721686 599 pin4 = PIDControlR > 0.0f; // different pins for every motor
tverouden 41:5aecc1a27ce6 600 } else if (fabs(errorR) < 0.01f) {
tverouden 51:78c75cc72d17 601 countsOffsetR = countsR;
efvanmarrewijk 56:e8d568d455a0 602 //countsR = countsR - countsOffsetR + countsCalibration;
tverouden 51:78c75cc72d17 603 //countsR = 0;
tverouden 51:78c75cc72d17 604 pin5 = 0.0f;
tverouden 51:78c75cc72d17 605 // BUTTON PRESS: TO NEXT STATE
efvanmarrewijk 49:0ada5a721686 606 }
efvanmarrewijk 25:ac139331fe51 607 }
efvanmarrewijk 25:ac139331fe51 608
efvanmarrewijk 25:ac139331fe51 609 // ------------------------- MOTOR FUNCTIONS FOR MOTOR FLIP --------------------
EvaKrolis 13:4ba8f63e6ff4 610
efvanmarrewijk 52:17b3aeacb643 611 float PIDControllerF(float angleReference,float angleCurrent) // PID controller for the motors, based on the reference value and the current angle of the motor
efvanmarrewijk 52:17b3aeacb643 612 { float Kp = 19.24f;
efvanmarrewijk 52:17b3aeacb643 613 float Ki = 1.02f;
efvanmarrewijk 52:17b3aeacb643 614 float Kd = 0.827f;
efvanmarrewijk 52:17b3aeacb643 615 float error = errorCalc(angleReference,angleCurrent);
efvanmarrewijk 52:17b3aeacb643 616 static float errorIntegralF = 0.0;
efvanmarrewijk 52:17b3aeacb643 617 static float errorPreviousF = error; // initialization with this value only done once!
efvanmarrewijk 52:17b3aeacb643 618 static BiQuad PIDFilterF(0.0640, 0.1279, 0.0640, -1.1683, 0.4241);
efvanmarrewijk 52:17b3aeacb643 619 // Proportional part:
efvanmarrewijk 52:17b3aeacb643 620 float u_k = Kp * error;
efvanmarrewijk 52:17b3aeacb643 621 // Integral part
efvanmarrewijk 52:17b3aeacb643 622 errorIntegralF = errorIntegralF + error * dt;
efvanmarrewijk 52:17b3aeacb643 623 float u_i = Ki * errorIntegralF;
efvanmarrewijk 52:17b3aeacb643 624 // Derivative part
efvanmarrewijk 52:17b3aeacb643 625 float errorDerivative = (error - errorPreviousF)/dt;
efvanmarrewijk 52:17b3aeacb643 626 float errorDerivativeFiltered = PIDFilterF.step(errorDerivative);
efvanmarrewijk 52:17b3aeacb643 627 float u_d = Kd * errorDerivativeFiltered;
efvanmarrewijk 52:17b3aeacb643 628 errorPreviousF = error;
efvanmarrewijk 52:17b3aeacb643 629 // Sum all parts and return it
efvanmarrewijk 52:17b3aeacb643 630 return u_k + u_i + u_d;
efvanmarrewijk 52:17b3aeacb643 631 }
efvanmarrewijk 52:17b3aeacb643 632
efvanmarrewijk 52:17b3aeacb643 633 int countsInputCalibratedF() // Gets the counts from encoder 1
efvanmarrewijk 52:17b3aeacb643 634 { countsF = encoderF.getPulses()- countsOffsetF + countsCalibration;
efvanmarrewijk 52:17b3aeacb643 635 return countsF;
efvanmarrewijk 52:17b3aeacb643 636 }
efvanmarrewijk 52:17b3aeacb643 637
efvanmarrewijk 52:17b3aeacb643 638 void motorTurnF() // main function for movement of motor 1, all above functions with an extra tab are called
efvanmarrewijk 52:17b3aeacb643 639 {
efvanmarrewijk 52:17b3aeacb643 640 float angleReferenceF = 0.0f; // insert kinematics output here instead of angleDesired()
efvanmarrewijk 52:17b3aeacb643 641 angleReferenceF = -angleReferenceF; // different minus sign per motor
efvanmarrewijk 52:17b3aeacb643 642 countsF = countsInputCalibratedF(); // different encoder pins per motor
efvanmarrewijk 52:17b3aeacb643 643 angleCurrentF = angleCurrent(countsF); // different minus sign per motor
efvanmarrewijk 52:17b3aeacb643 644 errorF = errorCalc(angleReferenceF,angleCurrentF); // same for every motor
efvanmarrewijk 52:17b3aeacb643 645
efvanmarrewijk 52:17b3aeacb643 646 float PIDControlF = PIDControllerF(angleReferenceF,angleCurrentF); // same for every motor
efvanmarrewijk 52:17b3aeacb643 647 pin5 = fabs(PIDControlF); // different pins for every motor
efvanmarrewijk 52:17b3aeacb643 648 pin4 = PIDControlF > 0.0f; // different pins for every motor
efvanmarrewijk 52:17b3aeacb643 649 }
efvanmarrewijk 52:17b3aeacb643 650
efvanmarrewijk 52:17b3aeacb643 651 void calibrationF() // Partially the same as motorTurnF, only with potmeter input
efvanmarrewijk 52:17b3aeacb643 652 // How it works: manually turn motor using potmeters until the robot arm touches the bookholder.
efvanmarrewijk 52:17b3aeacb643 653 // This program sets the counts from the motor to the reference counts (an angle of PI/4.0)
efvanmarrewijk 52:17b3aeacb643 654 // Do this for every motor and after calibrated all motors, press a button
efvanmarrewijk 52:17b3aeacb643 655 { float angleReferenceF = 0.0f; // insert kinematics output here instead of angleDesired()
efvanmarrewijk 52:17b3aeacb643 656 angleReferenceF = -angleReferenceF; // different minus sign per motor
efvanmarrewijk 52:17b3aeacb643 657 countsF = countsInputF(); // different encoder pins per motor
efvanmarrewijk 52:17b3aeacb643 658 angleCurrentF = angleCurrent(countsF); // different minus sign per motor
efvanmarrewijk 52:17b3aeacb643 659 errorF = errorCalc(angleReferenceF,angleCurrentF); // same for every motor
efvanmarrewijk 52:17b3aeacb643 660
efvanmarrewijk 52:17b3aeacb643 661 if (fabs(errorF) >= 0.01f)
efvanmarrewijk 52:17b3aeacb643 662 { float PIDControlF = PIDControllerF(angleReferenceF,angleCurrentF); // same for every motor
efvanmarrewijk 52:17b3aeacb643 663 pin5 = fabs(PIDControlF); // different pins for every motor
efvanmarrewijk 52:17b3aeacb643 664 pin4 = PIDControlF > 0.0f; // different pins for every motor
efvanmarrewijk 52:17b3aeacb643 665 }
efvanmarrewijk 52:17b3aeacb643 666 else if (fabs(errorF) < 0.01f)
efvanmarrewijk 52:17b3aeacb643 667 { countsOffsetF = countsF;
efvanmarrewijk 52:17b3aeacb643 668 countsF = countsF - countsOffsetF + countsCalibration;
efvanmarrewijk 52:17b3aeacb643 669 //countsF = 0;
efvanmarrewijk 52:17b3aeacb643 670 pin5 = 0.0f;
efvanmarrewijk 52:17b3aeacb643 671 // BUTTON PRESS: TO NEXT STATE
efvanmarrewijk 52:17b3aeacb643 672 }
efvanmarrewijk 52:17b3aeacb643 673 }
efvanmarrewijk 52:17b3aeacb643 674
tverouden 2:d70795e4e0bf 675 // ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ STATE MACHINE ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
tverouden 51:78c75cc72d17 676 void stateMachine(void)
tverouden 51:78c75cc72d17 677 {
tverouden 51:78c75cc72d17 678 switch (currentState) { // determine which state Odin is in
tverouden 4:5ce2c8864908 679
tverouden 51:78c75cc72d17 680 // ======================== MOTOR L CALIBRATION MODE =========================
tverouden 51:78c75cc72d17 681 case calibratingMotorL:
tverouden 51:78c75cc72d17 682 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 683 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 684 pc.printf("[MODE] calibrating motor L...\r\n");
tverouden 51:78c75cc72d17 685 // print current state
tverouden 51:78c75cc72d17 686 changeState = false; // stay in this state
tverouden 3:9c63fc5f157e 687
tverouden 51:78c75cc72d17 688 // Actions when entering state
tverouden 51:78c75cc72d17 689 ledRed = 1; // green blinking LED
tverouden 51:78c75cc72d17 690 ledGreen = 1;
tverouden 51:78c75cc72d17 691 ledBlue = 1;
tverouden 51:78c75cc72d17 692 blinkTimer.attach(&blinkLedGreen,0.5);
tverouden 51:78c75cc72d17 693
tverouden 51:78c75cc72d17 694 }
tverouden 4:5ce2c8864908 695 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 696 // Actions for each loop iteration
tverouden 51:78c75cc72d17 697 calibrationL();
tverouden 4:5ce2c8864908 698
tverouden 4:5ce2c8864908 699 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 700 // Transition condition: when all motor errors smaller than 0.01,
tverouden 51:78c75cc72d17 701 // start calibrating EMG
efvanmarrewijk 52:17b3aeacb643 702 if (errorL < 0.01f && buttonBio1 == false) {
tverouden 51:78c75cc72d17 703
tverouden 51:78c75cc72d17 704 // Actions when leaving state
tverouden 51:78c75cc72d17 705 blinkTimer.detach();
tverouden 4:5ce2c8864908 706
tverouden 51:78c75cc72d17 707 currentState = calibratingMotorR; // change to state
tverouden 51:78c75cc72d17 708 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 709 }
tverouden 51:78c75cc72d17 710
tverouden 51:78c75cc72d17 711 break; // end case
tverouden 4:5ce2c8864908 712
tverouden 51:78c75cc72d17 713 // ======================== MOTOR R CALIBRATION MODE =========================
tverouden 51:78c75cc72d17 714 case calibratingMotorR:
tverouden 51:78c75cc72d17 715 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 716 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 717 pc.printf("[MODE] calibrating motor R...\r\n");
tverouden 51:78c75cc72d17 718 // print current state
tverouden 51:78c75cc72d17 719 changeState = false; // stay in this state
tverouden 5:04b26b2f536a 720
tverouden 51:78c75cc72d17 721 // Actions when entering state
tverouden 51:78c75cc72d17 722 ledRed = 1; // cyan-green blinking LED
tverouden 51:78c75cc72d17 723 ledGreen = 0;
tverouden 51:78c75cc72d17 724 ledBlue = 1;
tverouden 51:78c75cc72d17 725 blinkTimer.attach(&blinkLedBlue,0.5);
tverouden 5:04b26b2f536a 726
tverouden 51:78c75cc72d17 727 }
tverouden 4:5ce2c8864908 728 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 729 // Actions for each loop iteration
tverouden 51:78c75cc72d17 730 calibrationR();
tverouden 4:5ce2c8864908 731 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 732 // Transition condition: when all motor errors smaller than 0.01,
tverouden 51:78c75cc72d17 733 // start calibrating EMG
efvanmarrewijk 52:17b3aeacb643 734 if (errorR < 0.01f && buttonBio2 == false) {
tverouden 23:e282bdb9e9b7 735
tverouden 51:78c75cc72d17 736 // Actions when leaving state
tverouden 51:78c75cc72d17 737 blinkTimer.detach();
tverouden 5:04b26b2f536a 738
tverouden 51:78c75cc72d17 739 currentState = calibratingMotorF; // change to state
tverouden 51:78c75cc72d17 740 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 741 }
tverouden 5:04b26b2f536a 742
tverouden 51:78c75cc72d17 743 break; // end case
tverouden 51:78c75cc72d17 744
tverouden 51:78c75cc72d17 745 // ======================== MOTOR F CALIBRATION MODE =========================
tverouden 51:78c75cc72d17 746 case calibratingMotorF:
tverouden 4:5ce2c8864908 747 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 748 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 749 pc.printf("[MODE] calibrating motor F...\r\n");
tverouden 51:78c75cc72d17 750 // print current state
tverouden 51:78c75cc72d17 751 changeState = false; // stay in this state
tverouden 4:5ce2c8864908 752
tverouden 51:78c75cc72d17 753 // Actions when entering state
tverouden 51:78c75cc72d17 754 ledRed = 1; // green blinking LED
tverouden 51:78c75cc72d17 755 ledGreen = 1;
tverouden 51:78c75cc72d17 756 ledBlue = 1;
tverouden 51:78c75cc72d17 757 blinkTimer.attach(&blinkLedGreen,0.5);
tverouden 4:5ce2c8864908 758
tverouden 51:78c75cc72d17 759 }
tverouden 51:78c75cc72d17 760 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 761 // Actions for each loop iteration
tverouden 51:78c75cc72d17 762 calibrationF();
tverouden 51:78c75cc72d17 763 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 764 // Transition condition: when all motor errors smaller than 0.01,
tverouden 51:78c75cc72d17 765 // start calibrating EMG
tverouden 51:78c75cc72d17 766 if (errorF < 0.01f && buttonHome == false) {
tverouden 51:78c75cc72d17 767
tverouden 51:78c75cc72d17 768 // Actions when leaving state
tverouden 51:78c75cc72d17 769 blinkTimer.detach();
tverouden 4:5ce2c8864908 770
tverouden 51:78c75cc72d17 771 currentState = calibratingEMG; // change to state
tverouden 51:78c75cc72d17 772 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 773 }
tverouden 4:5ce2c8864908 774
tverouden 51:78c75cc72d17 775 break; // end case
tverouden 51:78c75cc72d17 776
tverouden 51:78c75cc72d17 777 // =========================== EMG CALIBRATION MODE ===========================
tverouden 51:78c75cc72d17 778 case calibratingEMG:
tverouden 51:78c75cc72d17 779 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 780 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 781 pc.printf("[MODE] calibrating EMG...\r\n");
tverouden 51:78c75cc72d17 782 // print current state
tverouden 51:78c75cc72d17 783 changeState = false; // stay in this state
tverouden 41:5aecc1a27ce6 784
tverouden 51:78c75cc72d17 785 // Actions when entering state
tverouden 51:78c75cc72d17 786 ledRed = 1; // cyan-blue blinking LED
tverouden 51:78c75cc72d17 787 ledGreen = 0;
tverouden 51:78c75cc72d17 788 ledBlue = 0;
tverouden 51:78c75cc72d17 789 blinkTimer.attach(&blinkLedGreen,0.5);
tverouden 51:78c75cc72d17 790
tverouden 51:78c75cc72d17 791 FindMax0_timer.attach(&FindMax0,15); //Find the maximum value after 15 seconds
tverouden 51:78c75cc72d17 792 FindMax1_timer.attach(&FindMax1,15); //Find the maximum value after 15 seconds
tverouden 51:78c75cc72d17 793
tverouden 51:78c75cc72d17 794 EMGtransition_timer.reset();
tverouden 51:78c75cc72d17 795 EMGtransition_timer.start();
tverouden 51:78c75cc72d17 796 }
tverouden 4:5ce2c8864908 797 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 798 // Actions for each loop iteration
tverouden 51:78c75cc72d17 799 CalibrateEMG0(); //start emg calibration every 0.005 seconds
tverouden 51:78c75cc72d17 800 CalibrateEMG1(); //Start EMG calibration every 0.005 seconds
tverouden 51:78c75cc72d17 801 /* */
tverouden 41:5aecc1a27ce6 802
tverouden 4:5ce2c8864908 803
tverouden 4:5ce2c8864908 804 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 805 // Transition condition: after 20 sec in state
tverouden 51:78c75cc72d17 806 if (EMGtransition_timer.read() > 20) {
tverouden 51:78c75cc72d17 807 // Actions when leaving state
tverouden 51:78c75cc72d17 808 blinkTimer.detach();
tverouden 5:04b26b2f536a 809
tverouden 51:78c75cc72d17 810 currentState = homing; // change to state
tverouden 51:78c75cc72d17 811 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 812 }
tverouden 51:78c75cc72d17 813 break; // end case
tverouden 4:5ce2c8864908 814
tverouden 4:5ce2c8864908 815 // ============================== HOMING MODE ================================
tverouden 51:78c75cc72d17 816 case homing:
tverouden 41:5aecc1a27ce6 817 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 818 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 819 pc.printf("[MODE] homing...\r\n");
tverouden 51:78c75cc72d17 820 // print current state
tverouden 51:78c75cc72d17 821 changeState = false; // stay in this state
tverouden 4:5ce2c8864908 822
tverouden 4:5ce2c8864908 823
tverouden 51:78c75cc72d17 824 // Actions when entering state
tverouden 51:78c75cc72d17 825 ledRed = 1; // cyan LED on
tverouden 51:78c75cc72d17 826 ledGreen = 0;
tverouden 51:78c75cc72d17 827 ledBlue = 0;
tverouden 4:5ce2c8864908 828
tverouden 51:78c75cc72d17 829 }
tverouden 4:5ce2c8864908 830 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 831 // Actions for each loop iteration
tverouden 51:78c75cc72d17 832 /* */
tverouden 4:5ce2c8864908 833
tverouden 41:5aecc1a27ce6 834 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 835 // Transition condition #1: with button press, enter reading mode,
tverouden 51:78c75cc72d17 836 // but only when velocity == 0
tverouden 51:78c75cc72d17 837 if (errorCalibratedL < 0.01f && errorCalibratedR < 0.01f
tverouden 51:78c75cc72d17 838 && errorCalibratedF < 0.01f && buttonBio1 == false) {
tverouden 51:78c75cc72d17 839 // Actions when leaving state
tverouden 51:78c75cc72d17 840 /* */
tverouden 24:0abc564349e1 841
tverouden 51:78c75cc72d17 842 currentState = reading; // change to state
tverouden 51:78c75cc72d17 843 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 844 }
tverouden 51:78c75cc72d17 845 // Transition condition #2: with button press, enter demo mode
tverouden 51:78c75cc72d17 846 // but only when velocity == 0
tverouden 51:78c75cc72d17 847 if (errorCalibratedL < 0.01f && errorCalibratedR < 0.01f
tverouden 51:78c75cc72d17 848 && errorCalibratedF < 0.01f && buttonBio2 == false) {
tverouden 51:78c75cc72d17 849 // Actions when leaving state
tverouden 51:78c75cc72d17 850 /* */
tverouden 5:04b26b2f536a 851
tverouden 51:78c75cc72d17 852 currentState = demoing; // change to state
tverouden 51:78c75cc72d17 853 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 854 }
tverouden 51:78c75cc72d17 855 break; // end case
tverouden 4:5ce2c8864908 856
tverouden 41:5aecc1a27ce6 857 // ============================== READING MODE ===============================
tverouden 51:78c75cc72d17 858 case reading:
tverouden 17:b04e1938491a 859 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 860 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 861 pc.printf("[MODE] reading...\r\n");
tverouden 51:78c75cc72d17 862 // print current state
tverouden 51:78c75cc72d17 863 changeState = false; // stay in this state
tverouden 17:b04e1938491a 864
tverouden 51:78c75cc72d17 865 // Actions when entering state
tverouden 51:78c75cc72d17 866 ledRed = 1; // blue LED on
tverouden 51:78c75cc72d17 867 ledGreen = 1;
tverouden 51:78c75cc72d17 868 ledBlue = 0;
tverouden 41:5aecc1a27ce6 869
tverouden 51:78c75cc72d17 870 // TERUGKLAPPEN
tverouden 17:b04e1938491a 871
tverouden 51:78c75cc72d17 872 }
tverouden 17:b04e1938491a 873 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 874 // Actions for each loop iteration
tverouden 51:78c75cc72d17 875 ReadUseEMG0(); //Start the use of EMG
tverouden 51:78c75cc72d17 876 ReadUseEMG1(); //Start the use of EMG
tverouden 51:78c75cc72d17 877 /* */
tverouden 17:b04e1938491a 878
tverouden 17:b04e1938491a 879 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 880 // Transition condition #1: when EMG signal detected, enter operating
tverouden 51:78c75cc72d17 881 // mode
tverouden 51:78c75cc72d17 882 if (xMove == true && yMove == true) {
tverouden 51:78c75cc72d17 883 // Actions when leaving state
tverouden 51:78c75cc72d17 884 /* */
tverouden 24:0abc564349e1 885
tverouden 51:78c75cc72d17 886 currentState = operating; // change to state
tverouden 51:78c75cc72d17 887 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 888 }
tverouden 51:78c75cc72d17 889 // Transition condition #2: with button press, back to homing mode
tverouden 51:78c75cc72d17 890 if (buttonHome == false) {
tverouden 51:78c75cc72d17 891 // Actions when leaving state
tverouden 51:78c75cc72d17 892 /* */
tverouden 17:b04e1938491a 893
tverouden 51:78c75cc72d17 894 currentState = homing; // change to state
tverouden 51:78c75cc72d17 895 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 896 }
tverouden 51:78c75cc72d17 897 break; // end case
tverouden 17:b04e1938491a 898
tverouden 4:5ce2c8864908 899 // ============================= OPERATING MODE ==============================
tverouden 51:78c75cc72d17 900 case operating:
tverouden 4:5ce2c8864908 901 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 902 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 903 pc.printf("[MODE] operating...\r\n");
tverouden 51:78c75cc72d17 904 // print current state
tverouden 51:78c75cc72d17 905 changeState = false; // stay in this state
tverouden 5:04b26b2f536a 906
tverouden 51:78c75cc72d17 907 // Actions when entering state
tverouden 51:78c75cc72d17 908 ledRed = 1; // blue fast blinking LED
tverouden 51:78c75cc72d17 909 ledGreen = 1;
tverouden 51:78c75cc72d17 910 ledBlue = 1;
tverouden 51:78c75cc72d17 911 blinkTimer.attach(&blinkLedBlue,0.25);
tverouden 5:04b26b2f536a 912
tverouden 51:78c75cc72d17 913 }
tverouden 5:04b26b2f536a 914 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 915 // Actions for each loop iteration
tverouden 51:78c75cc72d17 916 /* */
tverouden 5:04b26b2f536a 917
tverouden 5:04b26b2f536a 918 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 919 // Transition condition: when path is over, back to reading mode
tverouden 51:78c75cc72d17 920 if (errorCalibratedL < 0.01f && errorCalibratedR < 0.01f) {
tverouden 51:78c75cc72d17 921 // Actions when leaving state
tverouden 51:78c75cc72d17 922 blinkTimer.detach();
tverouden 5:04b26b2f536a 923
tverouden 51:78c75cc72d17 924 currentState = reading; // change to state
tverouden 51:78c75cc72d17 925 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 926 }
tverouden 51:78c75cc72d17 927 break; // end case
tverouden 5:04b26b2f536a 928
tverouden 5:04b26b2f536a 929 // ============================== DEMOING MODE ===============================
tverouden 51:78c75cc72d17 930 case demoing:
tverouden 5:04b26b2f536a 931 // ------------------------- initialisation --------------------------
tverouden 51:78c75cc72d17 932 if (changeState) { // when entering the state
tverouden 51:78c75cc72d17 933 pc.printf("[MODE] demoing...\r\n");
tverouden 51:78c75cc72d17 934 // print current state
tverouden 51:78c75cc72d17 935 changeState = false; // stay in this state
tverouden 5:04b26b2f536a 936
tverouden 51:78c75cc72d17 937 // Actions when entering state
tverouden 51:78c75cc72d17 938 ledRed = 0; // yellow LED on
tverouden 51:78c75cc72d17 939 ledGreen = 0;
tverouden 51:78c75cc72d17 940 ledBlue = 1;
tverouden 5:04b26b2f536a 941
tverouden 51:78c75cc72d17 942 }
tverouden 5:04b26b2f536a 943 // ----------------------------- action ------------------------------
tverouden 51:78c75cc72d17 944 // Actions for each loop iteration
tverouden 51:78c75cc72d17 945 /* */
tverouden 51:78c75cc72d17 946 ReadUseEMG0(); //Start the use of EMG
tverouden 51:78c75cc72d17 947 ReadUseEMG1(); //Start the use of EMG
efvanmarrewijk 56:e8d568d455a0 948 pc.printf("theta1 and 4: %f \t\t %f \n\r",theta1,theta4);
efvanmarrewijk 55:b297e064ebd9 949 //kinematics();
tverouden 51:78c75cc72d17 950 motorTurnL();
tverouden 51:78c75cc72d17 951 motorTurnR();
efvanmarrewijk 52:17b3aeacb643 952
tverouden 5:04b26b2f536a 953
tverouden 5:04b26b2f536a 954 // --------------------------- transition ----------------------------
tverouden 51:78c75cc72d17 955 // Transition condition: with button press, back to homing mode
tverouden 51:78c75cc72d17 956 if (buttonHome == false) {
tverouden 51:78c75cc72d17 957 // Actions when leaving state
tverouden 51:78c75cc72d17 958 /* */
tverouden 5:04b26b2f536a 959
tverouden 51:78c75cc72d17 960 currentState = homing; // change to state
tverouden 51:78c75cc72d17 961 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 962 }
tverouden 51:78c75cc72d17 963 break; // end case
tverouden 5:04b26b2f536a 964
tverouden 5:04b26b2f536a 965 // =============================== FAILING MODE ================================
tverouden 51:78c75cc72d17 966 case failing:
tverouden 51:78c75cc72d17 967 changeState = false; // stay in this state
tverouden 3:9c63fc5f157e 968
tverouden 51:78c75cc72d17 969 // Actions when entering state
tverouden 51:78c75cc72d17 970 ledRed = 0; // red LED on
tverouden 51:78c75cc72d17 971 ledGreen = 1;
tverouden 51:78c75cc72d17 972 ledBlue = 1;
tverouden 4:5ce2c8864908 973
tverouden 51:78c75cc72d17 974 pin3 = 0; // all motor forces to zero
tverouden 51:78c75cc72d17 975 pin5 = 0;
tverouden 51:78c75cc72d17 976 pin6 = 0;
tverouden 51:78c75cc72d17 977 exit (0); // stop all current functions
tverouden 51:78c75cc72d17 978 break; // end case
tverouden 4:5ce2c8864908 979
tverouden 4:5ce2c8864908 980 // ============================== DEFAULT MODE =================================
tverouden 51:78c75cc72d17 981 default:
tverouden 4:5ce2c8864908 982 // ---------------------------- enter failing mode -----------------------------
tverouden 51:78c75cc72d17 983 currentState = failing; // change to state
tverouden 51:78c75cc72d17 984 changeState = true; // next loop, switch states
tverouden 51:78c75cc72d17 985 // print current state
tverouden 51:78c75cc72d17 986 pc.printf("[ERROR] unknown or unimplemented state reached\r\n");
tverouden 3:9c63fc5f157e 987
tverouden 51:78c75cc72d17 988 } // end switch
tverouden 51:78c75cc72d17 989 } // end stateMachine
tverouden 3:9c63fc5f157e 990
tverouden 3:9c63fc5f157e 991
tverouden 2:d70795e4e0bf 992
tverouden 2:d70795e4e0bf 993 // ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ MAIN LOOP ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
tverouden 2:d70795e4e0bf 994
tverouden 51:78c75cc72d17 995 int main()
tverouden 51:78c75cc72d17 996 {
tverouden 8:8cef1050ebd9 997 // ================================ EMERGENCY ================================
tverouden 51:78c75cc72d17 998 //If the emergency button is pressed, stop program via failing state
tverouden 51:78c75cc72d17 999 buttonEmergency.rise(stopProgram); // Automatische triggers voor failure mode? -> ook error message in andere functies plaatsen!
tverouden 15:6566c5dedeeb 1000
tverouden 43:d332aa9f49e0 1001 // ============================= PC-COMMUNICATION ============================
tverouden 51:78c75cc72d17 1002 pc.baud(115200); // communication with terminal
tverouden 51:78c75cc72d17 1003 pc.printf("\n\n[START] starting O.D.I.N\r\n");
tverouden 6:f32352bc5078 1004
tverouden 43:d332aa9f49e0 1005 // ============================= PIN DEFINE PERIOD ===========================
tverouden 51:78c75cc72d17 1006 // If you give a period on one pin, c++ gives all pins this period
tverouden 51:78c75cc72d17 1007 pin3.period_us(15);
tverouden 41:5aecc1a27ce6 1008
tverouden 43:d332aa9f49e0 1009 // ==================================== LOOP ==================================
tverouden 51:78c75cc72d17 1010 // run state machine at 500 Hz
tverouden 51:78c75cc72d17 1011 stateTimer.attach(&stateMachine,dt);
tverouden 43:d332aa9f49e0 1012
tverouden 43:d332aa9f49e0 1013 // =============================== ADD FILTERS ===============================
tverouden 51:78c75cc72d17 1014 //Make filter chain for the first EMG
tverouden 51:78c75cc72d17 1015 filter0.add(&Notch50_0).add(&Notch100_0).add(&Notch150_0).add(&Notch200_0).add(&Low_0).add(&High_0);
tverouden 51:78c75cc72d17 1016 //Make filter chain for the second EMG
tverouden 51:78c75cc72d17 1017 filter1.add(&Notch50_1).add(&Notch100_1).add(&Notch150_1).add(&Notch200_1).add(&Low_1).add(&High_1);
tverouden 51:78c75cc72d17 1018 }