Group19-Biorobotics
Dependencies: HIDScope MODSERIAL PID QEI SigInterpreternovember2 biquadFilter mbed
Fork of Robot_control_v3 by
Controller.cpp@1:b9005f2aabf5, 2016-10-21 (annotated)
- Committer:
- fabian101
- Date:
- Fri Oct 21 21:32:20 2016 +0000
- Revision:
- 1:b9005f2aabf5
- Parent:
- 0:d935ea6f5c25
- Child:
- 2:6b913f93bc0b
21-10 11:32
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
fabian101 | 0:d935ea6f5c25 | 1 | #include "initialize.h" |
fabian101 | 0:d935ea6f5c25 | 2 | #include "Controller.h" |
fabian101 | 1:b9005f2aabf5 | 3 | |
fabian101 | 0:d935ea6f5c25 | 4 | int main() { |
fabian101 | 0:d935ea6f5c25 | 5 | calibrateButton.rise(&calibrate); |
fabian101 | 0:d935ea6f5c25 | 6 | motorControl.attach(&setFlag, RATE); |
fabian101 | 1:b9005f2aabf5 | 7 | initMotors(); |
fabian101 | 1:b9005f2aabf5 | 8 | initControllers(); |
fabian101 | 1:b9005f2aabf5 | 9 | calibratePower(); // store max amplitude each emg signal |
fabian101 | 0:d935ea6f5c25 | 10 | run(); |
fabian101 | 0:d935ea6f5c25 | 11 | } |
fabian101 | 0:d935ea6f5c25 | 12 | |
fabian101 | 0:d935ea6f5c25 | 13 | void run() { |
fabian101 | 0:d935ea6f5c25 | 14 | while(true){ |
fabian101 | 0:d935ea6f5c25 | 15 | double r = signal.readValue(1); // returns filtered value |
fabian101 | 0:d935ea6f5c25 | 16 | double l = signal.readValue(2); |
fabian101 | 0:d935ea6f5c25 | 17 | double u = signal.readValue(3); |
fabian101 | 0:d935ea6f5c25 | 18 | double d = signal.readValue(4); |
fabian101 | 0:d935ea6f5c25 | 19 | |
fabian101 | 0:d935ea6f5c25 | 20 | // calculate r,l,u,d in a % of max |
fabian101 | 0:d935ea6f5c25 | 21 | double percentageR = r/rMax; |
fabian101 | 0:d935ea6f5c25 | 22 | double percentageL = l/lMax; |
fabian101 | 0:d935ea6f5c25 | 23 | double percentageU = u/uMax; |
fabian101 | 0:d935ea6f5c25 | 24 | double percentageD = d/dMax; |
fabian101 | 0:d935ea6f5c25 | 25 | |
fabian101 | 0:d935ea6f5c25 | 26 | |
fabian101 | 1:b9005f2aabf5 | 27 | if (flag) { // setting the flag here will cause the edge detection to be ignored if the flag is false for some reason |
fabian101 | 1:b9005f2aabf5 | 28 | // ignore the weaker signal,motorValue calculation, threshold set |
fabian101 | 1:b9005f2aabf5 | 29 | if ( percentageR > percentageL){ // horizontal speed request |
fabian101 | 0:d935ea6f5c25 | 30 | motorValueHor = percentageR; |
fabian101 | 1:b9005f2aabf5 | 31 | minHorThreshold = 0.2*rMax; // set the threshold |
fabian101 | 1:b9005f2aabf5 | 32 | } else {motorValueHor = -percentageL; |
fabian101 | 1:b9005f2aabf5 | 33 | minHorThreshold = 0.2*lMax; |
fabian101 | 1:b9005f2aabf5 | 34 | } |
fabian101 | 1:b9005f2aabf5 | 35 | if (percentageU > percentageD) { // vertical speed request |
fabian101 | 0:d935ea6f5c25 | 36 | motorValueVer = percentageU; |
fabian101 | 1:b9005f2aabf5 | 37 | minVerThreshold = 0.2*uMax; |
fabian101 | 1:b9005f2aabf5 | 38 | } else {motorValueVer = -percentageD; |
fabian101 | 1:b9005f2aabf5 | 39 | minVerThreshold = 0.2*uMax; |
fabian101 | 1:b9005f2aabf5 | 40 | } |
fabian101 | 0:d935ea6f5c25 | 41 | // current pulses and prevpulses calculated |
fabian101 | 0:d935ea6f5c25 | 42 | x += (pulses.getDistanceHor() - prevX); // in pulses |
fabian101 | 0:d935ea6f5c25 | 43 | prevX = x; |
fabian101 | 0:d935ea6f5c25 | 44 | y += (pulses.getDistanceVer() - prevY); |
fabian101 | 0:d935ea6f5c25 | 45 | prevY = y; |
fabian101 | 0:d935ea6f5c25 | 46 | |
fabian101 | 1:b9005f2aabf5 | 47 | //edge detection |
fabian101 | 1:b9005f2aabf5 | 48 | if (x > x_max && motorValueHor > 0) { // right should correspond to positive motorvalue |
fabian101 | 1:b9005f2aabf5 | 49 | motorValueHor = 0; |
fabian101 | 1:b9005f2aabf5 | 50 | } |
fabian101 | 1:b9005f2aabf5 | 51 | if (x < 0 && motorValueHor < 0) { // carefulwith 0 pulses, maybe implement margin |
fabian101 | 1:b9005f2aabf5 | 52 | motorValueHor = 0; |
fabian101 | 0:d935ea6f5c25 | 53 | } |
fabian101 | 1:b9005f2aabf5 | 54 | if (y > y_max && motorValueVer > 0) { // up should correspond to positive motorvalue |
fabian101 | 1:b9005f2aabf5 | 55 | motorValueVer = 0; |
fabian101 | 0:d935ea6f5c25 | 56 | } |
fabian101 | 1:b9005f2aabf5 | 57 | if (y < 0 && motorValueVer < 0) { |
fabian101 | 1:b9005f2aabf5 | 58 | motorValueVer =0; |
fabian101 | 1:b9005f2aabf5 | 59 | } |
fabian101 | 0:d935ea6f5c25 | 60 | |
fabian101 | 1:b9005f2aabf5 | 61 | // Quantize the linear speed request |
fabian101 | 1:b9005f2aabf5 | 62 | // motorValue is a value [-1,1], currently only 0 or 1/-1 |
fabian101 | 1:b9005f2aabf5 | 63 | if (motorValueHor > maxHorValue){motorValueHor = maxHorValue;} // safety |
fabian101 | 1:b9005f2aabf5 | 64 | if (motorValueHor < -maxHorValue){motorValueHor = -maxHorValue;} |
fabian101 | 1:b9005f2aabf5 | 65 | if (motorValueHor > minHorThreshold && motorValueHor < maxHorValue){motorValueHor = maxHorValue;} // if threshold is met pwm is 100%, maybe quantize here |
fabian101 | 1:b9005f2aabf5 | 66 | if (motorValueHor < -minHorThreshold && motorValueHor > -maxHorValue){motorValueHor = -maxHorValue;} |
fabian101 | 0:d935ea6f5c25 | 67 | |
fabian101 | 1:b9005f2aabf5 | 68 | if (motorValueVer > maxVerValue){motorValueVer = maxVerValue;} |
fabian101 | 1:b9005f2aabf5 | 69 | if (motorValueVer < -maxVerValue){motorValueVer = -maxVerValue;} |
fabian101 | 1:b9005f2aabf5 | 70 | if (motorValueVer > minVerThreshold && motorValueVer < maxVerValue){motorValueVer = maxVerValue;} |
fabian101 | 1:b9005f2aabf5 | 71 | if (motorValueVer < -minVerThreshold && motorValueVer > -maxVerValue){motorValueVer = -maxVerValue;} |
fabian101 | 1:b9005f2aabf5 | 72 | |
fabian101 | 1:b9005f2aabf5 | 73 | //current position of pen in degrees |
fabian101 | 1:b9005f2aabf5 | 74 | currentXangle = 360.0f*(pulses.getDistanceHor()/8400); |
fabian101 | 1:b9005f2aabf5 | 75 | currentYangle = 360.0f*(pulses.getDistanceVer()/8400); |
fabian101 | 1:b9005f2aabf5 | 76 | |
fabian101 | 1:b9005f2aabf5 | 77 | // current position of pen in cm |
fabian101 | 1:b9005f2aabf5 | 78 | currentX = (360.0f/(2*PI))*(pulses.getDistanceHor()/8400)*(RmHor/R1); // radiants*revolutions*gearratio is x pos in rad IS RAD EQUAL TO CM????????? |
fabian101 | 1:b9005f2aabf5 | 79 | currentY= (360.0f/(2*PI))*(pulses.getDistanceVer()/8400); // radiants*revolutions 1:1 ratio?? |
fabian101 | 0:d935ea6f5c25 | 80 | |
fabian101 | 1:b9005f2aabf5 | 81 | // desired position of pen in cm |
fabian101 | 1:b9005f2aabf5 | 82 | toX = currentX + motorValueHor*maxSpeed*RATE; |
fabian101 | 1:b9005f2aabf5 | 83 | toY = currentY + motorValueVer*maxSpeed*RATE; |
fabian101 | 1:b9005f2aabf5 | 84 | |
fabian101 | 1:b9005f2aabf5 | 85 | // desired angle of pen in degrees |
fabian101 | 1:b9005f2aabf5 | 86 | toangleX = ((toX-currentX)*(R1/RmHor))*(360.0f/(2*PI)); |
fabian101 | 1:b9005f2aabf5 | 87 | toangleY = (toX-currentX)*(360.0f/(2*PI)); |
fabian101 | 1:b9005f2aabf5 | 88 | |
fabian101 | 1:b9005f2aabf5 | 89 | //requested velocities in degrees/sec |
fabian101 | 1:b9005f2aabf5 | 90 | Xvelrequest = (toangleX - currentXangle) / RATE; |
fabian101 | 1:b9005f2aabf5 | 91 | Yvelrequest = (toangleY - currentYangle) / RATE; |
fabian101 | 1:b9005f2aabf5 | 92 | |
fabian101 | 1:b9005f2aabf5 | 93 | // set setpoint of PID controller here with velrequest, what are the input limits??? |
fabian101 | 0:d935ea6f5c25 | 94 | |
fabian101 | 0:d935ea6f5c25 | 95 | // Calculate current rotational velocity |
fabian101 | 0:d935ea6f5c25 | 96 | |
fabian101 | 1:b9005f2aabf5 | 97 | // give the PID controller the processvariable |
fabian101 | 0:d935ea6f5c25 | 98 | |
fabian101 | 0:d935ea6f5c25 | 99 | // compute PID |
fabian101 | 0:d935ea6f5c25 | 100 | |
fabian101 | 0:d935ea6f5c25 | 101 | // output to motor |
fabian101 | 0:d935ea6f5c25 | 102 | |
fabian101 | 0:d935ea6f5c25 | 103 | // output to hidscope |
fabian101 | 0:d935ea6f5c25 | 104 | flag = false; // only output to motor with RATE |
fabian101 | 0:d935ea6f5c25 | 105 | } |
fabian101 | 0:d935ea6f5c25 | 106 | |
fabian101 | 0:d935ea6f5c25 | 107 | } |
fabian101 | 0:d935ea6f5c25 | 108 | } |
fabian101 | 0:d935ea6f5c25 | 109 | |
fabian101 | 0:d935ea6f5c25 | 110 | void setFlag() { |
fabian101 | 0:d935ea6f5c25 | 111 | flag = true; |
fabian101 | 0:d935ea6f5c25 | 112 | } |
fabian101 | 0:d935ea6f5c25 | 113 | |
fabian101 | 0:d935ea6f5c25 | 114 | void emergencyExit() { |
fabian101 | 0:d935ea6f5c25 | 115 | calibrate(); |
fabian101 | 0:d935ea6f5c25 | 116 | run(); |
fabian101 | 1:b9005f2aabf5 | 117 | } |
fabian101 | 1:b9005f2aabf5 | 118 | |
fabian101 | 1:b9005f2aabf5 | 119 | void calibrate() { |
fabian101 | 1:b9005f2aabf5 | 120 | while ((pulses.getDistanceHor() > margin) && (pulses.getDistanceVer() > margin)){ |
fabian101 | 1:b9005f2aabf5 | 121 | if (pulses.getDistanceHor() > margin){ |
fabian101 | 1:b9005f2aabf5 | 122 | // go direction LEFT |
fabian101 | 1:b9005f2aabf5 | 123 | } |
fabian101 | 1:b9005f2aabf5 | 124 | else { //motormaghor 0 |
fabian101 | 1:b9005f2aabf5 | 125 | } |
fabian101 | 1:b9005f2aabf5 | 126 | if (pulses.getDistanceVer() > margin){ |
fabian101 | 1:b9005f2aabf5 | 127 | // go direction DOWN |
fabian101 | 1:b9005f2aabf5 | 128 | } |
fabian101 | 1:b9005f2aabf5 | 129 | else { //motormagver 0} |
fabian101 | 1:b9005f2aabf5 | 130 | } |
fabian101 | 1:b9005f2aabf5 | 131 | // GO-TO pos (0,0) |
fabian101 | 1:b9005f2aabf5 | 132 | // pulses can only be 0 or positive so reverse the direction until 0 pulses is reached |
fabian101 | 1:b9005f2aabf5 | 133 | // problem with the interrupt button, after calibration the program should re-start the run function instead of going further at the point it left |
fabian101 | 1:b9005f2aabf5 | 134 | // this will cause 1 iteration to be absolutely wrong -> consequences? |
fabian101 | 1:b9005f2aabf5 | 135 | } |
fabian101 | 1:b9005f2aabf5 | 136 | } |
fabian101 | 1:b9005f2aabf5 | 137 | |
fabian101 | 1:b9005f2aabf5 | 138 | void calibratePower(){ |
fabian101 | 1:b9005f2aabf5 | 139 | while((clock()/CLOCKS_PER_SEC) < 5){ // FIXME |
fabian101 | 1:b9005f2aabf5 | 140 | // do this for 5 sec |
fabian101 | 1:b9005f2aabf5 | 141 | double rCal = signal.readValue(1); |
fabian101 | 1:b9005f2aabf5 | 142 | if ( rCal > rMax){ |
fabian101 | 1:b9005f2aabf5 | 143 | rMax = rCal; |
fabian101 | 1:b9005f2aabf5 | 144 | } |
fabian101 | 1:b9005f2aabf5 | 145 | double lCal = signal.readValue(2); |
fabian101 | 1:b9005f2aabf5 | 146 | if ( lCal > lMax){ |
fabian101 | 1:b9005f2aabf5 | 147 | lMax = lCal; |
fabian101 | 1:b9005f2aabf5 | 148 | } |
fabian101 | 1:b9005f2aabf5 | 149 | double uCal = signal.readValue(3); |
fabian101 | 1:b9005f2aabf5 | 150 | if ( uCal > uMax){ |
fabian101 | 1:b9005f2aabf5 | 151 | uMax = uCal; |
fabian101 | 1:b9005f2aabf5 | 152 | } |
fabian101 | 1:b9005f2aabf5 | 153 | double dCal = signal.readValue(4); |
fabian101 | 1:b9005f2aabf5 | 154 | if ( dCal > dMax){ |
fabian101 | 1:b9005f2aabf5 | 155 | dMax = dCal; |
fabian101 | 1:b9005f2aabf5 | 156 | } |
fabian101 | 1:b9005f2aabf5 | 157 | } |
fabian101 | 1:b9005f2aabf5 | 158 | return; |
fabian101 | 1:b9005f2aabf5 | 159 | } |