Pressure control for drive segment in rebuild of control unit.
Dependencies: mbed QEI FastAnalogIn mbed-rtos FastPWM
main.cpp@5:4e710cef655e, 2019-04-01 (annotated)
- Committer:
- dofydoink
- Date:
- Mon Apr 01 14:15:31 2019 +0000
- Revision:
- 5:4e710cef655e
- Parent:
- 4:3bab17dfae4e
- Child:
- 6:6142902e20d1
Fixed quantization error in sensor position message to ML. Was caused by incorrectly casting to an int (use brackets to force order of operations!).
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dofydoink | 0:20018747657d | 1 | #include "mbed.h" |
dofydoink | 0:20018747657d | 2 | #include "math.h" |
dofydoink | 0:20018747657d | 3 | |
dofydoink | 0:20018747657d | 4 | #include "QEI.h" |
dofydoink | 0:20018747657d | 5 | |
dofydoink | 0:20018747657d | 6 | #include "rtos.h" |
dofydoink | 0:20018747657d | 7 | #include "FastPWM.h" |
dofydoink | 0:20018747657d | 8 | |
dofydoink | 0:20018747657d | 9 | #define ERROR_LIMIT_POS 0.008 //limits for when any error measurement is considered to be zero. |
dofydoink | 0:20018747657d | 10 | #define ERROR_LIMIT_NEG -0.008 |
dofydoink | 0:20018747657d | 11 | |
dofydoink | 0:20018747657d | 12 | #define CHAN_1 0x80 |
dofydoink | 0:20018747657d | 13 | #define CHAN_2 0x90 |
dofydoink | 0:20018747657d | 14 | #define CHAN_3 0xA0 |
dofydoink | 0:20018747657d | 15 | #define CHAN_4 0xB0 |
dofydoink | 0:20018747657d | 16 | |
dofydoink | 0:20018747657d | 17 | #define PRESSURE_CHAN 1 |
dofydoink | 0:20018747657d | 18 | #define POSITION_CHAN 3 |
dofydoink | 0:20018747657d | 19 | |
dofydoink | 0:20018747657d | 20 | |
dofydoink | 0:20018747657d | 21 | |
dofydoink | 3:9bd35e5b05ba | 22 | const double MAX_SPEED_MMPS = 24.3457; |
dofydoink | 2:aee7d4724915 | 23 | int intDummy; |
dofydoink | 0:20018747657d | 24 | SPISlave slave(PA_7, PA_6, PA_5, PA_4 ); // mosi, miso, sclk, ssel |
dofydoink | 0:20018747657d | 25 | |
dofydoink | 0:20018747657d | 26 | QEI wheel (PB_5, PB_4, NC, 256, QEI::X4_ENCODING); |
dofydoink | 0:20018747657d | 27 | |
dofydoink | 0:20018747657d | 28 | DigitalOut Mntr(D3); |
dofydoink | 2:aee7d4724915 | 29 | DigitalOut Mntr2(PB_8); |
dofydoink | 0:20018747657d | 30 | |
dofydoink | 3:9bd35e5b05ba | 31 | #define EXTERNAL_CLOCK_MODE 0x08 |
dofydoink | 3:9bd35e5b05ba | 32 | #define RANGE_CONFIG 0x03 |
dofydoink | 0:20018747657d | 33 | |
dofydoink | 0:20018747657d | 34 | #define EXTERNAL_CLOCK_MODE 0x08 |
dofydoink | 0:20018747657d | 35 | #define RANGE_CONFIG 0x03 //config for 1.5*Vref = 6.144V |
dofydoink | 0:20018747657d | 36 | |
dofydoink | 0:20018747657d | 37 | #define PRESSURE_BIAS_VOLTAGE 0.15151515151515 |
dofydoink | 3:9bd35e5b05ba | 38 | |
dofydoink | 3:9bd35e5b05ba | 39 | const double MAX_ACTUATOR_LENGTH = 52.2; |
dofydoink | 3:9bd35e5b05ba | 40 | |
dofydoink | 3:9bd35e5b05ba | 41 | const double MAX_POSITION_MM = 40.0; //maximum actuator position position in mm |
dofydoink | 3:9bd35e5b05ba | 42 | |
dofydoink | 3:9bd35e5b05ba | 43 | //sample time variables |
dofydoink | 3:9bd35e5b05ba | 44 | double dblSampleTime_s = 0.001; |
dofydoink | 0:20018747657d | 45 | |
dofydoink | 0:20018747657d | 46 | #define POT_2_MM 0.006750412 //convert potentiometer reading to mm (Tested and is right) |
dofydoink | 0:20018747657d | 47 | #define POT_OFFSET 7500//6666 |
dofydoink | 0:20018747657d | 48 | |
dofydoink | 0:20018747657d | 49 | Serial pc(USBTX, USBRX); // tx, rx |
dofydoink | 0:20018747657d | 50 | |
dofydoink | 0:20018747657d | 51 | Thread PositionControlThread(osPriorityHigh); |
dofydoink | 0:20018747657d | 52 | Thread DebugThread(osPriorityNormal); |
dofydoink | 0:20018747657d | 53 | Thread GateControlThread(osPriorityNormal); |
dofydoink | 0:20018747657d | 54 | |
dofydoink | 0:20018747657d | 55 | Thread DutyCycleThread(osPriorityRealtime); |
dofydoink | 0:20018747657d | 56 | Mutex mutDutyCycle; |
dofydoink | 0:20018747657d | 57 | Semaphore semDutyCycle(1); |
dofydoink | 0:20018747657d | 58 | Timer timerDutyCycle; |
dofydoink | 0:20018747657d | 59 | |
dofydoink | 0:20018747657d | 60 | volatile unsigned int intT; |
dofydoink | 0:20018747657d | 61 | volatile unsigned int intDeltaT; |
dofydoink | 0:20018747657d | 62 | double dblDutyCycle; |
dofydoink | 0:20018747657d | 63 | |
dofydoink | 0:20018747657d | 64 | double dblSensorDriftError; |
dofydoink | 0:20018747657d | 65 | |
dofydoink | 0:20018747657d | 66 | short randomvar; |
dofydoink | 0:20018747657d | 67 | |
dofydoink | 0:20018747657d | 68 | volatile int dataRx; |
dofydoink | 0:20018747657d | 69 | |
dofydoink | 0:20018747657d | 70 | void CalculateDutyCycle() |
dofydoink | 0:20018747657d | 71 | { |
dofydoink | 0:20018747657d | 72 | while(1) |
dofydoink | 0:20018747657d | 73 | { |
dofydoink | 0:20018747657d | 74 | semDutyCycle.wait(); |
dofydoink | 0:20018747657d | 75 | mutDutyCycle.lock(); |
dofydoink | 0:20018747657d | 76 | dblDutyCycle = (double) intDeltaT/intT; |
dofydoink | 0:20018747657d | 77 | mutDutyCycle.unlock(); |
dofydoink | 0:20018747657d | 78 | } |
dofydoink | 0:20018747657d | 79 | } |
dofydoink | 0:20018747657d | 80 | |
dofydoink | 0:20018747657d | 81 | Semaphore semPosCtrl(1); |
dofydoink | 0:20018747657d | 82 | Semaphore semDebug(1); |
dofydoink | 0:20018747657d | 83 | Semaphore semGate(1); |
dofydoink | 0:20018747657d | 84 | |
dofydoink | 0:20018747657d | 85 | Timer timer; |
dofydoink | 0:20018747657d | 86 | |
dofydoink | 0:20018747657d | 87 | long pulsesTest; |
dofydoink | 0:20018747657d | 88 | |
dofydoink | 0:20018747657d | 89 | //define all pins |
dofydoink | 3:9bd35e5b05ba | 90 | SPI spi(PB_15, PB_14, PB_13); // mosi, miso, sclk //DO NOT USE D4 OR D5 !!! |
dofydoink | 3:9bd35e5b05ba | 91 | |
dofydoink | 3:9bd35e5b05ba | 92 | DigitalOut cs_ADC(PB_12); |
dofydoink | 3:9bd35e5b05ba | 93 | |
dofydoink | 3:9bd35e5b05ba | 94 | DigitalOut pinGate(PA_8); |
dofydoink | 3:9bd35e5b05ba | 95 | |
dofydoink | 3:9bd35e5b05ba | 96 | AnalogIn pinDemand1(PA_0); |
dofydoink | 3:9bd35e5b05ba | 97 | AnalogIn pinDemand2(PA_1); |
dofydoink | 3:9bd35e5b05ba | 98 | |
dofydoink | 3:9bd35e5b05ba | 99 | AnalogIn pinCurSense(PB_0); |
dofydoink | 0:20018747657d | 100 | |
dofydoink | 3:9bd35e5b05ba | 101 | FastPWM pinPwmOutput(PC_8); |
dofydoink | 3:9bd35e5b05ba | 102 | |
dofydoink | 3:9bd35e5b05ba | 103 | FastPWM pinSigOut(D2); |
dofydoink | 3:9bd35e5b05ba | 104 | |
dofydoink | 3:9bd35e5b05ba | 105 | DigitalOut pinDirectionFwd(PA_13);//INB |
dofydoink | 3:9bd35e5b05ba | 106 | DigitalOut pinDirectionRev(PA_14);//INA |
dofydoink | 1:cb2859df7a4c | 107 | |
dofydoink | 3:9bd35e5b05ba | 108 | //define all variables |
dofydoink | 3:9bd35e5b05ba | 109 | |
dofydoink | 3:9bd35e5b05ba | 110 | int ii,jj,kk,nn, spiTick; //counting variables |
dofydoink | 3:9bd35e5b05ba | 111 | |
dofydoink | 3:9bd35e5b05ba | 112 | volatile int slaveReceivePos; |
dofydoink | 3:9bd35e5b05ba | 113 | volatile int slaveReceiveVel; |
dofydoink | 0:20018747657d | 114 | |
dofydoink | 3:9bd35e5b05ba | 115 | volatile int dataFlag; |
dofydoink | 3:9bd35e5b05ba | 116 | volatile int intFeedBack_pos; |
dofydoink | 3:9bd35e5b05ba | 117 | volatile int intFeedBack_pres; |
dofydoink | 3:9bd35e5b05ba | 118 | |
dofydoink | 3:9bd35e5b05ba | 119 | int intChkSum_pos; |
dofydoink | 3:9bd35e5b05ba | 120 | int intChkSum_vel; |
dofydoink | 3:9bd35e5b05ba | 121 | |
dofydoink | 3:9bd35e5b05ba | 122 | int intPar_pos; |
dofydoink | 3:9bd35e5b05ba | 123 | int intPar_vel; |
dofydoink | 3:9bd35e5b05ba | 124 | |
dofydoink | 3:9bd35e5b05ba | 125 | //raw Data Readings |
dofydoink | 3:9bd35e5b05ba | 126 | int intPotRead = 0; |
dofydoink | 3:9bd35e5b05ba | 127 | int intPressureRead = 0; |
dofydoink | 3:9bd35e5b05ba | 128 | double analogReadingDemPos; |
dofydoink | 3:9bd35e5b05ba | 129 | double analogReadingDemVel; |
dofydoink | 3:9bd35e5b05ba | 130 | double analogReadingCurSens; |
dofydoink | 3:9bd35e5b05ba | 131 | |
dofydoink | 3:9bd35e5b05ba | 132 | char buf[10]; |
dofydoink | 3:9bd35e5b05ba | 133 | int dataReceived; |
dofydoink | 3:9bd35e5b05ba | 134 | |
dofydoink | 3:9bd35e5b05ba | 135 | |
dofydoink | 3:9bd35e5b05ba | 136 | |
dofydoink | 3:9bd35e5b05ba | 137 | |
dofydoink | 3:9bd35e5b05ba | 138 | //system state variables |
dofydoink | 3:9bd35e5b05ba | 139 | double dblPos[10];//current position in mm |
dofydoink | 3:9bd35e5b05ba | 140 | double dblPosFil[10];//current position in mm |
dofydoink | 3:9bd35e5b05ba | 141 | double dblLastPos;//previous position in mm |
dofydoink | 3:9bd35e5b05ba | 142 | double dblVel[10];//velocity in mm/s |
dofydoink | 3:9bd35e5b05ba | 143 | double dblAccel; //acceleration in mm/s^2 |
dofydoink | 3:9bd35e5b05ba | 144 | double dblIntegral = 0;//integral of position; |
dofydoink | 3:9bd35e5b05ba | 145 | |
dofydoink | 3:9bd35e5b05ba | 146 | double dblPotPositionRead; |
dofydoink | 3:9bd35e5b05ba | 147 | |
dofydoink | 3:9bd35e5b05ba | 148 | double dblPosBias = 48.0; |
dofydoink | 3:9bd35e5b05ba | 149 | |
dofydoink | 3:9bd35e5b05ba | 150 | double dblStartingPos; |
dofydoink | 3:9bd35e5b05ba | 151 | |
dofydoink | 3:9bd35e5b05ba | 152 | //demand variables |
dofydoink | 3:9bd35e5b05ba | 153 | double dblPosD[10]; |
dofydoink | 3:9bd35e5b05ba | 154 | double dblLastPosD; |
dofydoink | 3:9bd35e5b05ba | 155 | double dblVelD[10]; |
dofydoink | 3:9bd35e5b05ba | 156 | double dblAccelD; |
dofydoink | 3:9bd35e5b05ba | 157 | |
dofydoink | 3:9bd35e5b05ba | 158 | double dblTargetPos; |
dofydoink | 3:9bd35e5b05ba | 159 | double dblTargetVel; |
dofydoink | 3:9bd35e5b05ba | 160 | double dblLinearPath; |
dofydoink | 3:9bd35e5b05ba | 161 | double dblLastLinearPath; |
dofydoink | 3:9bd35e5b05ba | 162 | double dblPathSign; |
dofydoink | 3:9bd35e5b05ba | 163 | |
dofydoink | 3:9bd35e5b05ba | 164 | |
dofydoink | 3:9bd35e5b05ba | 165 | |
dofydoink | 3:9bd35e5b05ba | 166 | double dblError; |
dofydoink | 3:9bd35e5b05ba | 167 | double dblLastError; |
dofydoink | 3:9bd35e5b05ba | 168 | double dblErrorDot; |
dofydoink | 3:9bd35e5b05ba | 169 | |
dofydoink | 3:9bd35e5b05ba | 170 | //filter Variables |
dofydoink | 4:3bab17dfae4e | 171 | int intPosFilOrder = 0; |
dofydoink | 3:9bd35e5b05ba | 172 | int intVelFilOrder = 1; |
dofydoink | 3:9bd35e5b05ba | 173 | int intDemPosFilOrder = 6; |
dofydoink | 3:9bd35e5b05ba | 174 | int intDemVelFilOrder = 6; |
dofydoink | 3:9bd35e5b05ba | 175 | int intOutFilOrder = 0; |
dofydoink | 3:9bd35e5b05ba | 176 | |
dofydoink | 3:9bd35e5b05ba | 177 | double dblPressureVal_bar; |
dofydoink | 3:9bd35e5b05ba | 178 | |
dofydoink | 3:9bd35e5b05ba | 179 | //controller variables |
dofydoink | 3:9bd35e5b05ba | 180 | double omega; |
dofydoink | 3:9bd35e5b05ba | 181 | double zeta; |
dofydoink | 3:9bd35e5b05ba | 182 | |
dofydoink | 3:9bd35e5b05ba | 183 | double Kp = 20.0; |
dofydoink | 3:9bd35e5b05ba | 184 | double Ki = 2.0; |
dofydoink | 3:9bd35e5b05ba | 185 | double Kd = 1.5; |
dofydoink | 3:9bd35e5b05ba | 186 | double dblIntTerm; |
dofydoink | 3:9bd35e5b05ba | 187 | double dblIntLimit = 0.8; |
dofydoink | 3:9bd35e5b05ba | 188 | int RXFlag; |
dofydoink | 3:9bd35e5b05ba | 189 | double dblControlBias = 0.0; |
dofydoink | 3:9bd35e5b05ba | 190 | |
dofydoink | 3:9bd35e5b05ba | 191 | double dblMotorVoltage = 12.0; |
dofydoink | 0:20018747657d | 192 | |
dofydoink | 3:9bd35e5b05ba | 193 | double output[10];//controller output |
dofydoink | 3:9bd35e5b05ba | 194 | |
dofydoink | 3:9bd35e5b05ba | 195 | //current limit variables |
dofydoink | 3:9bd35e5b05ba | 196 | double CurrentLimitSet; |
dofydoink | 3:9bd35e5b05ba | 197 | double dblCurrentLimitAmps = 3.0; |
dofydoink | 3:9bd35e5b05ba | 198 | double currentBuck; |
dofydoink | 3:9bd35e5b05ba | 199 | double currentBuckGain = 3.0; |
dofydoink | 3:9bd35e5b05ba | 200 | |
dofydoink | 3:9bd35e5b05ba | 201 | Timer gateTimer; |
dofydoink | 3:9bd35e5b05ba | 202 | |
dofydoink | 3:9bd35e5b05ba | 203 | //define custom Functions |
dofydoink | 3:9bd35e5b05ba | 204 | |
dofydoink | 3:9bd35e5b05ba | 205 | bool CheckMessage(int msg) { |
dofydoink | 3:9bd35e5b05ba | 206 | // Find message parity |
dofydoink | 3:9bd35e5b05ba | 207 | short int count = 0; |
dofydoink | 3:9bd35e5b05ba | 208 | for(short int i=0; i<32; i++) { |
dofydoink | 3:9bd35e5b05ba | 209 | if( msg>>1 & (1<<i) ) count++; |
dofydoink | 3:9bd35e5b05ba | 210 | } |
dofydoink | 3:9bd35e5b05ba | 211 | int intParity = !(count%2); |
dofydoink | 3:9bd35e5b05ba | 212 | // Find message CheckSum |
dofydoink | 3:9bd35e5b05ba | 213 | int intChkSum = 0; |
dofydoink | 3:9bd35e5b05ba | 214 | int intTempVar = msg>>7; |
dofydoink | 3:9bd35e5b05ba | 215 | while(intTempVar > 0) { |
dofydoink | 3:9bd35e5b05ba | 216 | intChkSum += intTempVar%10; |
dofydoink | 3:9bd35e5b05ba | 217 | intTempVar = int(intTempVar/10); |
dofydoink | 3:9bd35e5b05ba | 218 | } |
dofydoink | 3:9bd35e5b05ba | 219 | // Check if parity, CheckSum and mesage type match |
dofydoink | 3:9bd35e5b05ba | 220 | bool isParityCorrect = (intParity == (msg&0x1)); |
dofydoink | 3:9bd35e5b05ba | 221 | bool isChkSumCorrect = (intChkSum == ((msg>>2)&0x1F)); |
dofydoink | 3:9bd35e5b05ba | 222 | bool isCheckPassed = (isParityCorrect && isChkSumCorrect); |
dofydoink | 3:9bd35e5b05ba | 223 | return isCheckPassed; |
dofydoink | 3:9bd35e5b05ba | 224 | } |
dofydoink | 3:9bd35e5b05ba | 225 | |
dofydoink | 3:9bd35e5b05ba | 226 | bool PerformSlaveSPI(SPISlave *spiSlave, unsigned int outboundMsgs[], unsigned int inboundMsgsData[]) { |
dofydoink | 0:20018747657d | 227 | |
dofydoink | 3:9bd35e5b05ba | 228 | unsigned int dummyMsg = 0x5555; |
dofydoink | 3:9bd35e5b05ba | 229 | bool isSuccess = true; |
dofydoink | 3:9bd35e5b05ba | 230 | unsigned int inboundMsg, typeBit; |
dofydoink | 3:9bd35e5b05ba | 231 | short int numPacketsReceived = 0; |
dofydoink | 3:9bd35e5b05ba | 232 | for(short int i=0; i<3; i++) { // Loop 3 times for 3 SPI messages |
dofydoink | 3:9bd35e5b05ba | 233 | while( gateTimer.read_us() < 500 ) { |
dofydoink | 3:9bd35e5b05ba | 234 | if( spiSlave->receive() ) { |
dofydoink | 3:9bd35e5b05ba | 235 | numPacketsReceived++; |
dofydoink | 3:9bd35e5b05ba | 236 | |
dofydoink | 3:9bd35e5b05ba | 237 | inboundMsg = spiSlave->read(); |
dofydoink | 3:9bd35e5b05ba | 238 | Mntr = 1; |
dofydoink | 3:9bd35e5b05ba | 239 | if(i==0) { |
dofydoink | 3:9bd35e5b05ba | 240 | spiSlave->reply(outboundMsgs[0]); |
dofydoink | 3:9bd35e5b05ba | 241 | } else if(i==1) { |
dofydoink | 3:9bd35e5b05ba | 242 | spiSlave->reply(outboundMsgs[1]); |
dofydoink | 3:9bd35e5b05ba | 243 | } else { |
dofydoink | 3:9bd35e5b05ba | 244 | spiSlave->reply(dummyMsg); |
dofydoink | 3:9bd35e5b05ba | 245 | } |
dofydoink | 3:9bd35e5b05ba | 246 | Mntr = 0; |
dofydoink | 3:9bd35e5b05ba | 247 | |
dofydoink | 3:9bd35e5b05ba | 248 | if((unsigned int)inboundMsg != dummyMsg) { // Message is not dummy which is only used for reply |
dofydoink | 3:9bd35e5b05ba | 249 | typeBit = inboundMsg>>1 & 0x1; |
dofydoink | 3:9bd35e5b05ba | 250 | inboundMsgsData[typeBit] = inboundMsg>>7 & 0x1FF; |
dofydoink | 3:9bd35e5b05ba | 251 | if( !CheckMessage(inboundMsg) ) { |
dofydoink | 3:9bd35e5b05ba | 252 | isSuccess = false; |
dofydoink | 3:9bd35e5b05ba | 253 | } |
dofydoink | 3:9bd35e5b05ba | 254 | } |
dofydoink | 3:9bd35e5b05ba | 255 | break; |
dofydoink | 3:9bd35e5b05ba | 256 | } |
dofydoink | 3:9bd35e5b05ba | 257 | } |
dofydoink | 3:9bd35e5b05ba | 258 | } |
dofydoink | 3:9bd35e5b05ba | 259 | if( numPacketsReceived != 3 ) { |
dofydoink | 3:9bd35e5b05ba | 260 | isSuccess = false; |
dofydoink | 3:9bd35e5b05ba | 261 | } |
dofydoink | 3:9bd35e5b05ba | 262 | return isSuccess; |
dofydoink | 3:9bd35e5b05ba | 263 | } |
dofydoink | 3:9bd35e5b05ba | 264 | |
dofydoink | 3:9bd35e5b05ba | 265 | int Read14BitADC(int channel, DigitalOut CSpin) |
dofydoink | 3:9bd35e5b05ba | 266 | { |
dofydoink | 3:9bd35e5b05ba | 267 | char message; |
dofydoink | 3:9bd35e5b05ba | 268 | unsigned int outputA; |
dofydoink | 3:9bd35e5b05ba | 269 | unsigned int outputB; |
dofydoink | 3:9bd35e5b05ba | 270 | int output; |
dofydoink | 3:9bd35e5b05ba | 271 | |
dofydoink | 3:9bd35e5b05ba | 272 | switch(channel) |
dofydoink | 0:20018747657d | 273 | { |
dofydoink | 3:9bd35e5b05ba | 274 | case 1: |
dofydoink | 0:20018747657d | 275 | message = CHAN_1; |
dofydoink | 3:9bd35e5b05ba | 276 | break; |
dofydoink | 3:9bd35e5b05ba | 277 | |
dofydoink | 3:9bd35e5b05ba | 278 | case 2: |
dofydoink | 3:9bd35e5b05ba | 279 | message = CHAN_2; |
dofydoink | 3:9bd35e5b05ba | 280 | break; |
dofydoink | 3:9bd35e5b05ba | 281 | |
dofydoink | 3:9bd35e5b05ba | 282 | case 3: |
dofydoink | 3:9bd35e5b05ba | 283 | message = CHAN_3; |
dofydoink | 3:9bd35e5b05ba | 284 | break; |
dofydoink | 3:9bd35e5b05ba | 285 | case 4: |
dofydoink | 3:9bd35e5b05ba | 286 | message = CHAN_4; |
dofydoink | 3:9bd35e5b05ba | 287 | break; |
dofydoink | 3:9bd35e5b05ba | 288 | |
dofydoink | 3:9bd35e5b05ba | 289 | default: |
dofydoink | 3:9bd35e5b05ba | 290 | message = CHAN_1; |
dofydoink | 0:20018747657d | 291 | } |
dofydoink | 0:20018747657d | 292 | |
dofydoink | 3:9bd35e5b05ba | 293 | spi.format(8,0); |
dofydoink | 3:9bd35e5b05ba | 294 | spi.frequency(3000000);//3MHz clock speed (3.67MHz max) |
dofydoink | 3:9bd35e5b05ba | 295 | |
dofydoink | 3:9bd35e5b05ba | 296 | CSpin.write(0); |
dofydoink | 3:9bd35e5b05ba | 297 | spi.write(message); |
dofydoink | 3:9bd35e5b05ba | 298 | spi.write(0x00); |
dofydoink | 3:9bd35e5b05ba | 299 | outputA = spi.write(0x00); |
dofydoink | 3:9bd35e5b05ba | 300 | outputB = spi.write(0x00); |
dofydoink | 3:9bd35e5b05ba | 301 | CSpin.write(1); |
dofydoink | 3:9bd35e5b05ba | 302 | |
dofydoink | 3:9bd35e5b05ba | 303 | //convert result to sensible value |
dofydoink | 3:9bd35e5b05ba | 304 | outputA = outputA<<8; |
dofydoink | 3:9bd35e5b05ba | 305 | output = outputA | outputB; |
dofydoink | 3:9bd35e5b05ba | 306 | output = output>>2; |
dofydoink | 3:9bd35e5b05ba | 307 | |
dofydoink | 3:9bd35e5b05ba | 308 | return output; |
dofydoink | 3:9bd35e5b05ba | 309 | } |
dofydoink | 3:9bd35e5b05ba | 310 | |
dofydoink | 3:9bd35e5b05ba | 311 | void ADC_Config() |
dofydoink | 3:9bd35e5b05ba | 312 | { |
dofydoink | 3:9bd35e5b05ba | 313 | |
dofydoink | 3:9bd35e5b05ba | 314 | unsigned int msg; |
dofydoink | 3:9bd35e5b05ba | 315 | spi.format(8,0); |
dofydoink | 3:9bd35e5b05ba | 316 | spi.frequency(3000000);//3MHz clock speed (3.67MHz max) |
dofydoink | 3:9bd35e5b05ba | 317 | |
dofydoink | 3:9bd35e5b05ba | 318 | msg = CHAN_1 | RANGE_CONFIG; //config channel 1 set Vref as |
dofydoink | 3:9bd35e5b05ba | 319 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 320 | spi.write(msg); |
dofydoink | 3:9bd35e5b05ba | 321 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 322 | |
dofydoink | 3:9bd35e5b05ba | 323 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 324 | spi.write(EXTERNAL_CLOCK_MODE); |
dofydoink | 3:9bd35e5b05ba | 325 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 326 | |
dofydoink | 3:9bd35e5b05ba | 327 | msg = CHAN_2 | RANGE_CONFIG; //config channel 2 |
dofydoink | 3:9bd35e5b05ba | 328 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 329 | spi.write(msg); |
dofydoink | 3:9bd35e5b05ba | 330 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 331 | |
dofydoink | 3:9bd35e5b05ba | 332 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 333 | spi.write(EXTERNAL_CLOCK_MODE); |
dofydoink | 3:9bd35e5b05ba | 334 | cs_ADC = 1; |
dofydoink | 0:20018747657d | 335 | |
dofydoink | 3:9bd35e5b05ba | 336 | msg = CHAN_3 | RANGE_CONFIG; //config channel 3 |
dofydoink | 3:9bd35e5b05ba | 337 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 338 | spi.write(msg); |
dofydoink | 3:9bd35e5b05ba | 339 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 340 | |
dofydoink | 3:9bd35e5b05ba | 341 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 342 | spi.write(EXTERNAL_CLOCK_MODE); |
dofydoink | 3:9bd35e5b05ba | 343 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 344 | |
dofydoink | 3:9bd35e5b05ba | 345 | msg = CHAN_4 | RANGE_CONFIG; //config channel 4 |
dofydoink | 3:9bd35e5b05ba | 346 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 347 | spi.write(msg); |
dofydoink | 3:9bd35e5b05ba | 348 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 349 | |
dofydoink | 3:9bd35e5b05ba | 350 | cs_ADC = 0; |
dofydoink | 3:9bd35e5b05ba | 351 | spi.write(EXTERNAL_CLOCK_MODE); |
dofydoink | 3:9bd35e5b05ba | 352 | cs_ADC = 1; |
dofydoink | 3:9bd35e5b05ba | 353 | |
dofydoink | 3:9bd35e5b05ba | 354 | } |
dofydoink | 0:20018747657d | 355 | |
dofydoink | 0:20018747657d | 356 | |
dofydoink | 0:20018747657d | 357 | int SumDigits(int var) |
dofydoink | 0:20018747657d | 358 | { |
dofydoink | 0:20018747657d | 359 | int intSumResult = 0; |
dofydoink | 0:20018747657d | 360 | int intTempVar = var; |
dofydoink | 0:20018747657d | 361 | while (intTempVar >0) |
dofydoink | 0:20018747657d | 362 | { |
dofydoink | 0:20018747657d | 363 | intSumResult += intTempVar%10; |
dofydoink | 0:20018747657d | 364 | intTempVar = int(intTempVar/10); |
dofydoink | 0:20018747657d | 365 | //intSumResult += int(var/100)%100; |
dofydoink | 0:20018747657d | 366 | } |
dofydoink | 0:20018747657d | 367 | |
dofydoink | 0:20018747657d | 368 | return intSumResult; |
dofydoink | 0:20018747657d | 369 | } |
dofydoink | 0:20018747657d | 370 | |
dofydoink | 3:9bd35e5b05ba | 371 | //int EvenParityBitGen(int var) |
dofydoink | 3:9bd35e5b05ba | 372 | int OddParityBitGen(int var) |
dofydoink | 0:20018747657d | 373 | { |
dofydoink | 0:20018747657d | 374 | unsigned int count = 0, i, b = 1; |
dofydoink | 0:20018747657d | 375 | |
dofydoink | 0:20018747657d | 376 | for(i = 0; i < 32; i++){ |
dofydoink | 0:20018747657d | 377 | if( var & (b << i) ){count++;} |
dofydoink | 0:20018747657d | 378 | } |
dofydoink | 0:20018747657d | 379 | |
dofydoink | 3:9bd35e5b05ba | 380 | if( (count % 2) ){ |
dofydoink | 3:9bd35e5b05ba | 381 | return 0; |
dofydoink | 3:9bd35e5b05ba | 382 | } |
dofydoink | 0:20018747657d | 383 | |
dofydoink | 0:20018747657d | 384 | return 1; |
dofydoink | 0:20018747657d | 385 | } |
dofydoink | 0:20018747657d | 386 | |
dofydoink | 0:20018747657d | 387 | void CloseGate() |
dofydoink | 0:20018747657d | 388 | { |
dofydoink | 0:20018747657d | 389 | pinGate = 0; |
dofydoink | 0:20018747657d | 390 | |
dofydoink | 0:20018747657d | 391 | } |
dofydoink | 0:20018747657d | 392 | |
dofydoink | 3:9bd35e5b05ba | 393 | |
dofydoink | 0:20018747657d | 394 | |
dofydoink | 0:20018747657d | 395 | |
dofydoink | 3:9bd35e5b05ba | 396 | void PositionControlPID() |
dofydoink | 3:9bd35e5b05ba | 397 | { |
dofydoink | 3:9bd35e5b05ba | 398 | while(1) |
dofydoink | 0:20018747657d | 399 | { |
dofydoink | 3:9bd35e5b05ba | 400 | semPosCtrl.wait(); |
dofydoink | 3:9bd35e5b05ba | 401 | |
dofydoink | 3:9bd35e5b05ba | 402 | Mntr2 = !Mntr2; |
dofydoink | 3:9bd35e5b05ba | 403 | //Mntr2 = 1 - Mntr2;//!led; |
dofydoink | 3:9bd35e5b05ba | 404 | pulsesTest = wheel.getPulses(); |
dofydoink | 3:9bd35e5b05ba | 405 | |
dofydoink | 3:9bd35e5b05ba | 406 | double testy = (double) abs(pulsesTest)/2000; |
dofydoink | 3:9bd35e5b05ba | 407 | pinSigOut.write(testy); |
dofydoink | 3:9bd35e5b05ba | 408 | |
dofydoink | 3:9bd35e5b05ba | 409 | //take all readings |
dofydoink | 3:9bd35e5b05ba | 410 | |
dofydoink | 3:9bd35e5b05ba | 411 | //sensor readings |
dofydoink | 3:9bd35e5b05ba | 412 | |
dofydoink | 3:9bd35e5b05ba | 413 | intPressureRead = (Read14BitADC(PRESSURE_CHAN, cs_ADC));//read pressure |
dofydoink | 3:9bd35e5b05ba | 414 | intPressureRead = intPressureRead-1334; |
dofydoink | 3:9bd35e5b05ba | 415 | |
dofydoink | 3:9bd35e5b05ba | 416 | dblPressureVal_bar = ( (double) intPressureRead/10667)*10.0; |
dofydoink | 3:9bd35e5b05ba | 417 | |
dofydoink | 3:9bd35e5b05ba | 418 | |
dofydoink | 3:9bd35e5b05ba | 419 | intFeedBack_pres = (int)(((double)intPressureRead/10667) * 511); |
dofydoink | 3:9bd35e5b05ba | 420 | //printf("%d\r\n",intFeedBack_pres); |
dofydoink | 3:9bd35e5b05ba | 421 | |
dofydoink | 3:9bd35e5b05ba | 422 | |
dofydoink | 3:9bd35e5b05ba | 423 | //intFeedBack_pres = intFeedBack_pres>>5; |
dofydoink | 3:9bd35e5b05ba | 424 | |
dofydoink | 3:9bd35e5b05ba | 425 | intFeedBack_pres = (intFeedBack_pres<<5) | SumDigits(intFeedBack_pres);//add checksum |
dofydoink | 3:9bd35e5b05ba | 426 | intFeedBack_pres = (intFeedBack_pres<<1); |
dofydoink | 3:9bd35e5b05ba | 427 | intFeedBack_pres = intFeedBack_pres | 0x0001; //add type (1 for pressure) |
dofydoink | 3:9bd35e5b05ba | 428 | intFeedBack_pres = (intFeedBack_pres <<1) | OddParityBitGen(intFeedBack_pres);//add parity |
dofydoink | 3:9bd35e5b05ba | 429 | intFeedBack_pres = intFeedBack_pres & 0xFFFF; |
dofydoink | 0:20018747657d | 430 | |
dofydoink | 3:9bd35e5b05ba | 431 | unsigned short garb = 0x01; |
dofydoink | 3:9bd35e5b05ba | 432 | |
dofydoink | 3:9bd35e5b05ba | 433 | intPotRead = (16383-Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer |
dofydoink | 3:9bd35e5b05ba | 434 | dblPotPositionRead = (double) POT_2_MM*(intPotRead - POT_OFFSET); |
dofydoink | 3:9bd35e5b05ba | 435 | |
dofydoink | 3:9bd35e5b05ba | 436 | |
dofydoink | 3:9bd35e5b05ba | 437 | //demand Readings |
dofydoink | 2:aee7d4724915 | 438 | |
dofydoink | 3:9bd35e5b05ba | 439 | |
dofydoink | 3:9bd35e5b05ba | 440 | //current reading |
dofydoink | 3:9bd35e5b05ba | 441 | analogReadingCurSens = (double) 0.3*pinCurSense.read()+0.7*analogReadingCurSens; |
dofydoink | 3:9bd35e5b05ba | 442 | |
dofydoink | 3:9bd35e5b05ba | 443 | //convert units and filter |
dofydoink | 3:9bd35e5b05ba | 444 | |
dofydoink | 3:9bd35e5b05ba | 445 | //get position and filter |
dofydoink | 3:9bd35e5b05ba | 446 | dblPos[0] = (double) pulsesTest*-0.0078125 + dblStartingPos; |
dofydoink | 3:9bd35e5b05ba | 447 | dblSensorDriftError = dblPotPositionRead - dblPos[0]; |
dofydoink | 3:9bd35e5b05ba | 448 | |
dofydoink | 3:9bd35e5b05ba | 449 | if(dblSensorDriftError > 2.0)//if encoder reading is seriously wrong |
dofydoink | 3:9bd35e5b05ba | 450 | { |
dofydoink | 3:9bd35e5b05ba | 451 | //dblPos[0] = dblPotPositionRead; |
dofydoink | 3:9bd35e5b05ba | 452 | } |
dofydoink | 3:9bd35e5b05ba | 453 | |
dofydoink | 3:9bd35e5b05ba | 454 | //printf("%d, %f, %f\r\n",pulsesTest,dblPos[0],dblPotPositionRead); |
dofydoink | 3:9bd35e5b05ba | 455 | if(intPosFilOrder > 0) |
dofydoink | 3:9bd35e5b05ba | 456 | { |
dofydoink | 3:9bd35e5b05ba | 457 | for (ii = 1; ii<intPosFilOrder+1; ii++) |
dofydoink | 3:9bd35e5b05ba | 458 | { |
dofydoink | 3:9bd35e5b05ba | 459 | dblPos[ii] = (double) 0.7*dblPos[ii-1] + 0.3*dblPos[ii]; |
dofydoink | 3:9bd35e5b05ba | 460 | } |
dofydoink | 3:9bd35e5b05ba | 461 | } |
dofydoink | 3:9bd35e5b05ba | 462 | else |
dofydoink | 3:9bd35e5b05ba | 463 | { |
dofydoink | 3:9bd35e5b05ba | 464 | dblPos[intPosFilOrder] = dblPos[0]; |
dofydoink | 3:9bd35e5b05ba | 465 | } |
dofydoink | 0:20018747657d | 466 | |
dofydoink | 3:9bd35e5b05ba | 467 | //get velocity and filter |
dofydoink | 3:9bd35e5b05ba | 468 | dblVel[0] = dblPos[intPosFilOrder] - dblLastPos; |
dofydoink | 3:9bd35e5b05ba | 469 | if(intVelFilOrder>0) |
dofydoink | 3:9bd35e5b05ba | 470 | { |
dofydoink | 3:9bd35e5b05ba | 471 | for (ii = 1; ii<intVelFilOrder+1; ii++) |
dofydoink | 0:20018747657d | 472 | { |
dofydoink | 3:9bd35e5b05ba | 473 | dblVel[ii] = (double) 0.7*dblVel[ii-1] + 0.3*dblVel[ii]; |
dofydoink | 0:20018747657d | 474 | } |
dofydoink | 3:9bd35e5b05ba | 475 | } |
dofydoink | 3:9bd35e5b05ba | 476 | else |
dofydoink | 3:9bd35e5b05ba | 477 | { |
dofydoink | 3:9bd35e5b05ba | 478 | dblVel[intVelFilOrder] = dblVel[0]; |
dofydoink | 3:9bd35e5b05ba | 479 | } |
dofydoink | 3:9bd35e5b05ba | 480 | |
dofydoink | 3:9bd35e5b05ba | 481 | |
dofydoink | 3:9bd35e5b05ba | 482 | //printf("%f\r\n",dblPosD[intDemPosFilOrder]); |
dofydoink | 3:9bd35e5b05ba | 483 | |
dofydoink | 5:4e710cef655e | 484 | intFeedBack_pos = (int) ((dblPos[intPosFilOrder]/MAX_ACTUATOR_LENGTH)*511); |
dofydoink | 3:9bd35e5b05ba | 485 | |
dofydoink | 3:9bd35e5b05ba | 486 | if(intFeedBack_pos>511) |
dofydoink | 3:9bd35e5b05ba | 487 | { |
dofydoink | 3:9bd35e5b05ba | 488 | intFeedBack_pos = 511; |
dofydoink | 3:9bd35e5b05ba | 489 | } |
dofydoink | 3:9bd35e5b05ba | 490 | |
dofydoink | 3:9bd35e5b05ba | 491 | if(intFeedBack_pos<0) |
dofydoink | 3:9bd35e5b05ba | 492 | { |
dofydoink | 3:9bd35e5b05ba | 493 | intFeedBack_pos = 0; |
dofydoink | 3:9bd35e5b05ba | 494 | } |
dofydoink | 3:9bd35e5b05ba | 495 | |
dofydoink | 3:9bd35e5b05ba | 496 | |
dofydoink | 3:9bd35e5b05ba | 497 | intFeedBack_pos = (intFeedBack_pos<<5) | SumDigits(intFeedBack_pos);//add checkSum |
dofydoink | 3:9bd35e5b05ba | 498 | intFeedBack_pos = intFeedBack_pos <<1; // add type (0 for position) |
dofydoink | 3:9bd35e5b05ba | 499 | intFeedBack_pos = (intFeedBack_pos <<1) | OddParityBitGen(intFeedBack_pos);//add parity |
dofydoink | 3:9bd35e5b05ba | 500 | |
dofydoink | 3:9bd35e5b05ba | 501 | //intFeedBack = dblSensorDriftError*8191; |
dofydoink | 3:9bd35e5b05ba | 502 | |
dofydoink | 3:9bd35e5b05ba | 503 | |
dofydoink | 3:9bd35e5b05ba | 504 | ///////////////PATH GENERATION//////////////////////// |
dofydoink | 3:9bd35e5b05ba | 505 | //work out next path point |
dofydoink | 3:9bd35e5b05ba | 506 | double dblPathDifference; |
dofydoink | 3:9bd35e5b05ba | 507 | dblPathDifference = dblTargetPos - dblLinearPath; |
dofydoink | 3:9bd35e5b05ba | 508 | dblPathSign = dblPathDifference/fabs(dblPathDifference); //is velocity positive or negative? |
dofydoink | 0:20018747657d | 509 | |
dofydoink | 3:9bd35e5b05ba | 510 | //check if target has not been reached (with additional 1% of step to be sure) |
dofydoink | 3:9bd35e5b05ba | 511 | if (fabs(dblPathDifference) > 1.01*dblTargetVel*dblSampleTime_s) { |
dofydoink | 3:9bd35e5b05ba | 512 | dblLinearPath = dblLinearPath + dblPathSign*dblTargetVel*dblSampleTime_s;//next point in path |
dofydoink | 3:9bd35e5b05ba | 513 | } |
dofydoink | 3:9bd35e5b05ba | 514 | else { //if path is very close to target position |
dofydoink | 3:9bd35e5b05ba | 515 | dblLinearPath = dblTargetPos; |
dofydoink | 3:9bd35e5b05ba | 516 | } |
dofydoink | 3:9bd35e5b05ba | 517 | |
dofydoink | 3:9bd35e5b05ba | 518 | //limit position |
dofydoink | 3:9bd35e5b05ba | 519 | if(dblLinearPath > MAX_POSITION_MM){ |
dofydoink | 3:9bd35e5b05ba | 520 | dblLinearPath = MAX_POSITION_MM; |
dofydoink | 3:9bd35e5b05ba | 521 | } |
dofydoink | 3:9bd35e5b05ba | 522 | if (dblLinearPath < 0.0){ |
dofydoink | 3:9bd35e5b05ba | 523 | dblLinearPath = 0.0; |
dofydoink | 3:9bd35e5b05ba | 524 | } |
dofydoink | 3:9bd35e5b05ba | 525 | |
dofydoink | 4:3bab17dfae4e | 526 | dblPosD[intDemPosFilOrder] = 0.07*dblLinearPath + 0.93*dblPosD[intDemPosFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 527 | |
dofydoink | 3:9bd35e5b05ba | 528 | //make sure path is safe |
dofydoink | 3:9bd35e5b05ba | 529 | if (dblPosD[intDemPosFilOrder] > MAX_POSITION_MM) { |
dofydoink | 3:9bd35e5b05ba | 530 | dblPosD[intDemPosFilOrder] = MAX_POSITION_MM; |
dofydoink | 3:9bd35e5b05ba | 531 | } |
dofydoink | 3:9bd35e5b05ba | 532 | if (dblPosD[intDemPosFilOrder] < 0.0) { |
dofydoink | 3:9bd35e5b05ba | 533 | dblPosD[intDemPosFilOrder] = 0.0; |
dofydoink | 3:9bd35e5b05ba | 534 | } |
dofydoink | 3:9bd35e5b05ba | 535 | |
dofydoink | 3:9bd35e5b05ba | 536 | dblVelD[0] = dblPosD[intDemPosFilOrder] - dblLastPosD; |
dofydoink | 3:9bd35e5b05ba | 537 | |
dofydoink | 3:9bd35e5b05ba | 538 | ///////////////////////////////////////////////////// End of Path Generation |
dofydoink | 3:9bd35e5b05ba | 539 | |
dofydoink | 3:9bd35e5b05ba | 540 | |
dofydoink | 3:9bd35e5b05ba | 541 | //run PID calculations |
dofydoink | 3:9bd35e5b05ba | 542 | //get errors |
dofydoink | 3:9bd35e5b05ba | 543 | dblError = dblPosD[intDemPosFilOrder] - dblPos[intPosFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 544 | dblErrorDot = dblVelD[intDemVelFilOrder] - dblVel[intVelFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 545 | //get integral |
dofydoink | 3:9bd35e5b05ba | 546 | //printf("%f\r\n",dblError); |
dofydoink | 3:9bd35e5b05ba | 547 | |
dofydoink | 3:9bd35e5b05ba | 548 | |
dofydoink | 3:9bd35e5b05ba | 549 | dblIntTerm = dblIntTerm + Ki*dblError; |
dofydoink | 3:9bd35e5b05ba | 550 | |
dofydoink | 3:9bd35e5b05ba | 551 | //limit integral term |
dofydoink | 3:9bd35e5b05ba | 552 | if (dblIntTerm > dblIntLimit) |
dofydoink | 3:9bd35e5b05ba | 553 | { |
dofydoink | 3:9bd35e5b05ba | 554 | dblIntTerm = dblIntLimit; |
dofydoink | 3:9bd35e5b05ba | 555 | } |
dofydoink | 3:9bd35e5b05ba | 556 | if (dblIntTerm < -1.0*dblIntLimit) |
dofydoink | 3:9bd35e5b05ba | 557 | { |
dofydoink | 3:9bd35e5b05ba | 558 | dblIntTerm = (double) -1.0*dblIntLimit; |
dofydoink | 3:9bd35e5b05ba | 559 | } |
dofydoink | 3:9bd35e5b05ba | 560 | |
dofydoink | 3:9bd35e5b05ba | 561 | if(fabs(dblError) <0.01) |
dofydoink | 3:9bd35e5b05ba | 562 | { |
dofydoink | 3:9bd35e5b05ba | 563 | dblError = 0.0; |
dofydoink | 3:9bd35e5b05ba | 564 | dblErrorDot = 0.0; |
dofydoink | 0:20018747657d | 565 | |
dofydoink | 3:9bd35e5b05ba | 566 | } |
dofydoink | 0:20018747657d | 567 | |
dofydoink | 3:9bd35e5b05ba | 568 | if (fabs(dblErrorDot) < 0.1) |
dofydoink | 3:9bd35e5b05ba | 569 | { |
dofydoink | 3:9bd35e5b05ba | 570 | dblErrorDot = 0.0; |
dofydoink | 3:9bd35e5b05ba | 571 | } |
dofydoink | 3:9bd35e5b05ba | 572 | |
dofydoink | 3:9bd35e5b05ba | 573 | //calculate output |
dofydoink | 3:9bd35e5b05ba | 574 | output[0] = Kp*dblError + dblIntTerm + Kd*dblErrorDot; |
dofydoink | 3:9bd35e5b05ba | 575 | |
dofydoink | 3:9bd35e5b05ba | 576 | //limit output |
dofydoink | 3:9bd35e5b05ba | 577 | if (output[0] > 0.95) |
dofydoink | 3:9bd35e5b05ba | 578 | { |
dofydoink | 3:9bd35e5b05ba | 579 | output[0] = 0.95; |
dofydoink | 3:9bd35e5b05ba | 580 | } |
dofydoink | 3:9bd35e5b05ba | 581 | if (output[0] < -0.95) |
dofydoink | 3:9bd35e5b05ba | 582 | { |
dofydoink | 3:9bd35e5b05ba | 583 | output[0] = -0.95; |
dofydoink | 3:9bd35e5b05ba | 584 | } |
dofydoink | 3:9bd35e5b05ba | 585 | |
dofydoink | 3:9bd35e5b05ba | 586 | if(intOutFilOrder>0) |
dofydoink | 3:9bd35e5b05ba | 587 | { |
dofydoink | 3:9bd35e5b05ba | 588 | for (ii = 1; ii < intOutFilOrder+1; ii++) |
dofydoink | 0:20018747657d | 589 | { |
dofydoink | 3:9bd35e5b05ba | 590 | output[ii] = 0.7*output[ii-1] + 0.3*output[ii]; |
dofydoink | 0:20018747657d | 591 | } |
dofydoink | 3:9bd35e5b05ba | 592 | } |
dofydoink | 3:9bd35e5b05ba | 593 | else |
dofydoink | 3:9bd35e5b05ba | 594 | { |
dofydoink | 3:9bd35e5b05ba | 595 | output[intOutFilOrder] = output[0]; |
dofydoink | 3:9bd35e5b05ba | 596 | } |
dofydoink | 3:9bd35e5b05ba | 597 | |
dofydoink | 3:9bd35e5b05ba | 598 | //limit current |
dofydoink | 3:9bd35e5b05ba | 599 | if (analogReadingCurSens> CurrentLimitSet) |
dofydoink | 3:9bd35e5b05ba | 600 | { |
dofydoink | 3:9bd35e5b05ba | 601 | currentBuck = CurrentLimitSet / analogReadingCurSens / currentBuckGain; |
dofydoink | 3:9bd35e5b05ba | 602 | } |
dofydoink | 3:9bd35e5b05ba | 603 | else |
dofydoink | 3:9bd35e5b05ba | 604 | { |
dofydoink | 3:9bd35e5b05ba | 605 | currentBuck = 1.0; |
dofydoink | 3:9bd35e5b05ba | 606 | } |
dofydoink | 3:9bd35e5b05ba | 607 | |
dofydoink | 3:9bd35e5b05ba | 608 | output[intOutFilOrder] = currentBuck*output[intOutFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 609 | //end Current limit |
dofydoink | 3:9bd35e5b05ba | 610 | |
dofydoink | 3:9bd35e5b05ba | 611 | //find direction |
dofydoink | 3:9bd35e5b05ba | 612 | if(output[intOutFilOrder] >=0.0) |
dofydoink | 3:9bd35e5b05ba | 613 | { |
dofydoink | 3:9bd35e5b05ba | 614 | pinDirectionFwd = 1; |
dofydoink | 3:9bd35e5b05ba | 615 | pinDirectionRev = 0; |
dofydoink | 3:9bd35e5b05ba | 616 | dblControlBias = 0.0; |
dofydoink | 3:9bd35e5b05ba | 617 | } |
dofydoink | 3:9bd35e5b05ba | 618 | else |
dofydoink | 3:9bd35e5b05ba | 619 | { |
dofydoink | 3:9bd35e5b05ba | 620 | pinDirectionFwd = 0; |
dofydoink | 3:9bd35e5b05ba | 621 | pinDirectionRev = 1; |
dofydoink | 3:9bd35e5b05ba | 622 | dblControlBias = 0.0; |
dofydoink | 3:9bd35e5b05ba | 623 | } |
dofydoink | 3:9bd35e5b05ba | 624 | |
dofydoink | 3:9bd35e5b05ba | 625 | pinPwmOutput.write(abs(output[intOutFilOrder])+dblControlBias); |
dofydoink | 3:9bd35e5b05ba | 626 | |
dofydoink | 3:9bd35e5b05ba | 627 | //update all past variables |
dofydoink | 3:9bd35e5b05ba | 628 | dblLastPos = dblPos[intPosFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 629 | dblLastPosD = dblPosD[intDemPosFilOrder]; |
dofydoink | 3:9bd35e5b05ba | 630 | |
dofydoink | 3:9bd35e5b05ba | 631 | //GateControl(); |
dofydoink | 3:9bd35e5b05ba | 632 | gateTimer.reset(); |
dofydoink | 3:9bd35e5b05ba | 633 | pinGate = 1; |
dofydoink | 3:9bd35e5b05ba | 634 | unsigned int outboundMsgs[2] = { intFeedBack_pos , intFeedBack_pres }; |
dofydoink | 3:9bd35e5b05ba | 635 | unsigned int inboundMsgsData[2] = {0,0}; |
dofydoink | 3:9bd35e5b05ba | 636 | while(gateTimer.read_us() < 500) { |
dofydoink | 0:20018747657d | 637 | |
dofydoink | 3:9bd35e5b05ba | 638 | if(slave.receive()) { |
dofydoink | 3:9bd35e5b05ba | 639 | |
dofydoink | 3:9bd35e5b05ba | 640 | bool isSPIsuccess = PerformSlaveSPI(&slave,outboundMsgs,inboundMsgsData); |
dofydoink | 0:20018747657d | 641 | |
dofydoink | 3:9bd35e5b05ba | 642 | if( isSPIsuccess ) { |
dofydoink | 3:9bd35e5b05ba | 643 | dblTargetPos = (double)MAX_POSITION_MM*inboundMsgsData[0]/511; // dblMaxPos should be a constant double MAX_POSITION_MM |
dofydoink | 3:9bd35e5b05ba | 644 | if(dblTargetPos>MAX_POSITION_MM) { // Limit demand to ensure safety |
dofydoink | 3:9bd35e5b05ba | 645 | dblTargetPos = MAX_POSITION_MM; |
dofydoink | 3:9bd35e5b05ba | 646 | } else if(dblTargetPos<0.0) { |
dofydoink | 3:9bd35e5b05ba | 647 | dblTargetPos = 0.0; |
dofydoink | 3:9bd35e5b05ba | 648 | } |
dofydoink | 3:9bd35e5b05ba | 649 | |
dofydoink | 3:9bd35e5b05ba | 650 | dblTargetVel = (double)MAX_SPEED_MMPS*inboundMsgsData[1]/511; |
dofydoink | 3:9bd35e5b05ba | 651 | |
dofydoink | 3:9bd35e5b05ba | 652 | if(dblTargetVel>MAX_SPEED_MMPS) { |
dofydoink | 3:9bd35e5b05ba | 653 | dblTargetVel = MAX_SPEED_MMPS; |
dofydoink | 3:9bd35e5b05ba | 654 | } else if(dblTargetVel<0.0) { |
dofydoink | 3:9bd35e5b05ba | 655 | dblTargetPos = 0.0; |
dofydoink | 3:9bd35e5b05ba | 656 | } |
dofydoink | 3:9bd35e5b05ba | 657 | |
dofydoink | 3:9bd35e5b05ba | 658 | break; |
dofydoink | 2:aee7d4724915 | 659 | } |
dofydoink | 0:20018747657d | 660 | |
dofydoink | 0:20018747657d | 661 | } |
dofydoink | 0:20018747657d | 662 | |
dofydoink | 0:20018747657d | 663 | } |
dofydoink | 3:9bd35e5b05ba | 664 | |
dofydoink | 3:9bd35e5b05ba | 665 | pinGate = 0; |
dofydoink | 3:9bd35e5b05ba | 666 | //printf("EncPos: %f \t TargetPos: %f \t TargetVel: %f \t LinPath: %f \t DemPos: %f\r\n", dblPos[intPosFilOrder],dblTargetPos, dblTargetVel,dblLinearPath, dblPosD[intDemPosFilOrder]); |
dofydoink | 3:9bd35e5b05ba | 667 | |
dofydoink | 3:9bd35e5b05ba | 668 | //printf("Demand Pos: %f\t RXFlag: %d\t parity?%d \r\n",dblTargetPos, RXFlag, parityFail); |
dofydoink | 3:9bd35e5b05ba | 669 | |
dofydoink | 3:9bd35e5b05ba | 670 | } |
dofydoink | 3:9bd35e5b05ba | 671 | } |
dofydoink | 0:20018747657d | 672 | |
dofydoink | 0:20018747657d | 673 | |
dofydoink | 3:9bd35e5b05ba | 674 | //configure all control parameters |
dofydoink | 3:9bd35e5b05ba | 675 | void ControlParameterConfig() |
dofydoink | 3:9bd35e5b05ba | 676 | { |
dofydoink | 3:9bd35e5b05ba | 677 | Kp = Kp/dblMotorVoltage; |
dofydoink | 3:9bd35e5b05ba | 678 | Kd = Kd/dblSampleTime_s/dblMotorVoltage; |
dofydoink | 3:9bd35e5b05ba | 679 | Ki = Ki*dblSampleTime_s/dblMotorVoltage; |
dofydoink | 3:9bd35e5b05ba | 680 | } |
dofydoink | 0:20018747657d | 681 | |
dofydoink | 0:20018747657d | 682 | Ticker debugTicker; |
dofydoink | 0:20018747657d | 683 | |
dofydoink | 0:20018747657d | 684 | void startPositionControl() |
dofydoink | 0:20018747657d | 685 | { |
dofydoink | 0:20018747657d | 686 | semPosCtrl.release(); |
dofydoink | 0:20018747657d | 687 | } |
dofydoink | 0:20018747657d | 688 | |
dofydoink | 0:20018747657d | 689 | void startDebug() |
dofydoink | 0:20018747657d | 690 | { |
dofydoink | 0:20018747657d | 691 | semDebug.release(); |
dofydoink | 0:20018747657d | 692 | } |
dofydoink | 0:20018747657d | 693 | |
dofydoink | 0:20018747657d | 694 | Ticker positionCtrlTicker; |
dofydoink | 0:20018747657d | 695 | |
dofydoink | 0:20018747657d | 696 | int main() { |
dofydoink | 2:aee7d4724915 | 697 | pinGate = 0; |
dofydoink | 2:aee7d4724915 | 698 | |
dofydoink | 0:20018747657d | 699 | cs_ADC = 1; |
dofydoink | 2:aee7d4724915 | 700 | Mntr = 0; |
dofydoink | 2:aee7d4724915 | 701 | Mntr2 = 0; |
dofydoink | 0:20018747657d | 702 | pinPwmOutput.period_us(50); |
dofydoink | 0:20018747657d | 703 | printf("\r\nYo Yo Yo, Low Level innit\r\n\n\n"); |
dofydoink | 0:20018747657d | 704 | wait(0.5); |
dofydoink | 0:20018747657d | 705 | |
dofydoink | 0:20018747657d | 706 | timer.start(); |
dofydoink | 0:20018747657d | 707 | gateTimer.start(); |
dofydoink | 0:20018747657d | 708 | //cs_ADC = 1; |
dofydoink | 0:20018747657d | 709 | |
dofydoink | 0:20018747657d | 710 | ControlParameterConfig(); |
dofydoink | 0:20018747657d | 711 | // for (ii = 0; ii< 10; ii++) |
dofydoink | 0:20018747657d | 712 | // { |
dofydoink | 0:20018747657d | 713 | // uintPotRead = Read14BitADC(3, cs_ADC);//read potentiometer |
dofydoink | 0:20018747657d | 714 | // dblStartingPos = (double) POT_2_MM*uintPotRead - dblPosBias; |
dofydoink | 0:20018747657d | 715 | // } |
dofydoink | 0:20018747657d | 716 | // |
dofydoink | 0:20018747657d | 717 | slave.format(16,2); |
dofydoink | 0:20018747657d | 718 | slave.frequency(10000000); |
dofydoink | 2:aee7d4724915 | 719 | |
dofydoink | 0:20018747657d | 720 | dblPosD[intDemPosFilOrder] = 0.0; |
dofydoink | 0:20018747657d | 721 | slaveReceivePos = 0.0; |
dofydoink | 0:20018747657d | 722 | slaveReceiveVel = 0.0; |
dofydoink | 0:20018747657d | 723 | wait(0.1); |
dofydoink | 0:20018747657d | 724 | ADC_Config(); |
dofydoink | 0:20018747657d | 725 | wait(0.1); |
dofydoink | 0:20018747657d | 726 | ADC_Config(); |
dofydoink | 0:20018747657d | 727 | wait(0.1); |
dofydoink | 0:20018747657d | 728 | intPotRead = (16383-Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer |
dofydoink | 0:20018747657d | 729 | //intPotRead = (Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer |
dofydoink | 0:20018747657d | 730 | dblStartingPos = (double) POT_2_MM*(intPotRead - POT_OFFSET); |
dofydoink | 2:aee7d4724915 | 731 | dblLinearPath = dblStartingPos; |
dofydoink | 0:20018747657d | 732 | dblTargetPos = dblStartingPos; |
dofydoink | 3:9bd35e5b05ba | 733 | dblPos[intPosFilOrder] = dblStartingPos; |
dofydoink | 2:aee7d4724915 | 734 | dblTargetVel = 0.0; |
dofydoink | 0:20018747657d | 735 | dblPosD[intDemPosFilOrder] = dblStartingPos; |
dofydoink | 0:20018747657d | 736 | |
dofydoink | 2:aee7d4724915 | 737 | printf("\r\nPotRead: %d, Current Pos: %f, Target Pos: %f\r\n", intPotRead, dblStartingPos, dblTargetPos); |
dofydoink | 0:20018747657d | 738 | |
dofydoink | 0:20018747657d | 739 | //calculate/convert variables |
dofydoink | 0:20018747657d | 740 | |
dofydoink | 0:20018747657d | 741 | CurrentLimitSet = dblCurrentLimitAmps *0.14/3.3; |
dofydoink | 2:aee7d4724915 | 742 | slave.reply(0x5555); |
dofydoink | 0:20018747657d | 743 | PositionControlThread.start(PositionControlPID); |
dofydoink | 3:9bd35e5b05ba | 744 | |
dofydoink | 0:20018747657d | 745 | positionCtrlTicker.attach(&startPositionControl, dblSampleTime_s); |
dofydoink | 0:20018747657d | 746 | |
dofydoink | 0:20018747657d | 747 | intFeedBack_pos = 0; |
dofydoink | 0:20018747657d | 748 | intFeedBack_pres = 0; |
dofydoink | 0:20018747657d | 749 | |
dofydoink | 0:20018747657d | 750 | |
dofydoink | 0:20018747657d | 751 | while(1) |
dofydoink | 0:20018747657d | 752 | { |
dofydoink | 0:20018747657d | 753 | Thread::wait(osWaitForever); |
dofydoink | 0:20018747657d | 754 | } |
dofydoink | 3:9bd35e5b05ba | 755 | } |