Low level control code for syringe pumps

Dependencies:   mbed QEI FastAnalogIn mbed-rtos FastPWM

Committer:
dofydoink
Date:
Fri Jun 25 07:38:21 2021 +0000
Revision:
6:f4d91041b8af
Parent:
5:4e710cef655e
Control Code for Low Level controllers;

Who changed what in which revision?

UserRevisionLine numberNew 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 6:f4d91041b8af 177 double dblPressureVal_norm;
dofydoink 3:9bd35e5b05ba 178 double dblPressureVal_bar;
dofydoink 3:9bd35e5b05ba 179
dofydoink 3:9bd35e5b05ba 180 //controller variables
dofydoink 3:9bd35e5b05ba 181 double omega;
dofydoink 3:9bd35e5b05ba 182 double zeta;
dofydoink 3:9bd35e5b05ba 183
dofydoink 3:9bd35e5b05ba 184 double Kp = 20.0;
dofydoink 3:9bd35e5b05ba 185 double Ki = 2.0;
dofydoink 3:9bd35e5b05ba 186 double Kd = 1.5;
dofydoink 6:f4d91041b8af 187
dofydoink 6:f4d91041b8af 188
dofydoink 3:9bd35e5b05ba 189 double dblIntTerm;
dofydoink 3:9bd35e5b05ba 190 double dblIntLimit = 0.8;
dofydoink 3:9bd35e5b05ba 191 int RXFlag;
dofydoink 3:9bd35e5b05ba 192 double dblControlBias = 0.0;
dofydoink 3:9bd35e5b05ba 193
dofydoink 3:9bd35e5b05ba 194 double dblMotorVoltage = 12.0;
dofydoink 0:20018747657d 195
dofydoink 3:9bd35e5b05ba 196 double output[10];//controller output
dofydoink 3:9bd35e5b05ba 197
dofydoink 3:9bd35e5b05ba 198 //current limit variables
dofydoink 3:9bd35e5b05ba 199 double CurrentLimitSet;
dofydoink 3:9bd35e5b05ba 200 double dblCurrentLimitAmps = 3.0;
dofydoink 3:9bd35e5b05ba 201 double currentBuck;
dofydoink 3:9bd35e5b05ba 202 double currentBuckGain = 3.0;
dofydoink 3:9bd35e5b05ba 203
dofydoink 6:f4d91041b8af 204 //Pressure Limitation
dofydoink 6:f4d91041b8af 205 const double dblPressureLimitBar = 10.0;
dofydoink 6:f4d91041b8af 206 double dblPressureLimitGain = 2.0;
dofydoink 6:f4d91041b8af 207 double dblPressureLimitBuck;
dofydoink 6:f4d91041b8af 208 double dblPressureLimitDerivativeGain = 0.1;
dofydoink 6:f4d91041b8af 209 double dblLastErrorPressure;
dofydoink 6:f4d91041b8af 210 double dblErrorPressure;
dofydoink 6:f4d91041b8af 211 double dblDeltaErrorPressure;
dofydoink 6:f4d91041b8af 212
dofydoink 3:9bd35e5b05ba 213 Timer gateTimer;
dofydoink 3:9bd35e5b05ba 214
dofydoink 3:9bd35e5b05ba 215 //define custom Functions
dofydoink 3:9bd35e5b05ba 216
dofydoink 6:f4d91041b8af 217 bool CheckMessage(int msg) {//checks if message was corrupted
dofydoink 3:9bd35e5b05ba 218 // Find message parity
dofydoink 3:9bd35e5b05ba 219 short int count = 0;
dofydoink 3:9bd35e5b05ba 220 for(short int i=0; i<32; i++) {
dofydoink 3:9bd35e5b05ba 221 if( msg>>1 & (1<<i) ) count++;
dofydoink 3:9bd35e5b05ba 222 }
dofydoink 3:9bd35e5b05ba 223 int intParity = !(count%2);
dofydoink 3:9bd35e5b05ba 224 // Find message CheckSum
dofydoink 3:9bd35e5b05ba 225 int intChkSum = 0;
dofydoink 3:9bd35e5b05ba 226 int intTempVar = msg>>7;
dofydoink 3:9bd35e5b05ba 227 while(intTempVar > 0) {
dofydoink 3:9bd35e5b05ba 228 intChkSum += intTempVar%10;
dofydoink 3:9bd35e5b05ba 229 intTempVar = int(intTempVar/10);
dofydoink 3:9bd35e5b05ba 230 }
dofydoink 3:9bd35e5b05ba 231 // Check if parity, CheckSum and mesage type match
dofydoink 3:9bd35e5b05ba 232 bool isParityCorrect = (intParity == (msg&0x1));
dofydoink 3:9bd35e5b05ba 233 bool isChkSumCorrect = (intChkSum == ((msg>>2)&0x1F));
dofydoink 3:9bd35e5b05ba 234 bool isCheckPassed = (isParityCorrect && isChkSumCorrect);
dofydoink 3:9bd35e5b05ba 235 return isCheckPassed;
dofydoink 3:9bd35e5b05ba 236 }
dofydoink 3:9bd35e5b05ba 237
dofydoink 6:f4d91041b8af 238 ////////For Carafino: Start/////////
dofydoink 6:f4d91041b8af 239
dofydoink 6:f4d91041b8af 240
dofydoink 6:f4d91041b8af 241 //Message checking (For Carafino)
dofydoink 6:f4d91041b8af 242 bool PerformSlaveSPI(SPISlave *spiSlave, unsigned int outboundMsgs[], unsigned int inboundMsgsData[]) {//performs the SPI transaction
dofydoink 0:20018747657d 243
dofydoink 3:9bd35e5b05ba 244 unsigned int dummyMsg = 0x5555;
dofydoink 3:9bd35e5b05ba 245 bool isSuccess = true;
dofydoink 3:9bd35e5b05ba 246 unsigned int inboundMsg, typeBit;
dofydoink 3:9bd35e5b05ba 247 short int numPacketsReceived = 0;
dofydoink 3:9bd35e5b05ba 248 for(short int i=0; i<3; i++) { // Loop 3 times for 3 SPI messages
dofydoink 3:9bd35e5b05ba 249 while( gateTimer.read_us() < 500 ) {
dofydoink 3:9bd35e5b05ba 250 if( spiSlave->receive() ) {
dofydoink 3:9bd35e5b05ba 251 numPacketsReceived++;
dofydoink 3:9bd35e5b05ba 252
dofydoink 3:9bd35e5b05ba 253 inboundMsg = spiSlave->read();
dofydoink 6:f4d91041b8af 254 Mntr = 1;//dummy variable used to check function
dofydoink 3:9bd35e5b05ba 255 if(i==0) {
dofydoink 3:9bd35e5b05ba 256 spiSlave->reply(outboundMsgs[0]);
dofydoink 3:9bd35e5b05ba 257 } else if(i==1) {
dofydoink 3:9bd35e5b05ba 258 spiSlave->reply(outboundMsgs[1]);
dofydoink 3:9bd35e5b05ba 259 } else {
dofydoink 3:9bd35e5b05ba 260 spiSlave->reply(dummyMsg);
dofydoink 3:9bd35e5b05ba 261 }
dofydoink 3:9bd35e5b05ba 262 Mntr = 0;
dofydoink 3:9bd35e5b05ba 263
dofydoink 3:9bd35e5b05ba 264 if((unsigned int)inboundMsg != dummyMsg) { // Message is not dummy which is only used for reply
dofydoink 6:f4d91041b8af 265 typeBit = inboundMsg>>1 & 0x1;//extracts type bit from message, 0 = target Position; 1 = target Velocity
dofydoink 6:f4d91041b8af 266 inboundMsgsData[typeBit] = inboundMsg>>7 & 0x1FF;//this contains the data recieved from master
dofydoink 3:9bd35e5b05ba 267 if( !CheckMessage(inboundMsg) ) {
dofydoink 3:9bd35e5b05ba 268 isSuccess = false;
dofydoink 3:9bd35e5b05ba 269 }
dofydoink 3:9bd35e5b05ba 270 }
dofydoink 3:9bd35e5b05ba 271 break;
dofydoink 3:9bd35e5b05ba 272 }
dofydoink 3:9bd35e5b05ba 273 }
dofydoink 3:9bd35e5b05ba 274 }
dofydoink 6:f4d91041b8af 275 if( numPacketsReceived != 3 ) {//if it hasn't received three messages, it failed.
dofydoink 3:9bd35e5b05ba 276 isSuccess = false;
dofydoink 3:9bd35e5b05ba 277 }
dofydoink 3:9bd35e5b05ba 278 return isSuccess;
dofydoink 3:9bd35e5b05ba 279 }
dofydoink 6:f4d91041b8af 280
dofydoink 6:f4d91041b8af 281 ////////For Carafino: End/////////
dofydoink 3:9bd35e5b05ba 282
dofydoink 3:9bd35e5b05ba 283 int Read14BitADC(int channel, DigitalOut CSpin)
dofydoink 3:9bd35e5b05ba 284 {
dofydoink 3:9bd35e5b05ba 285 char message;
dofydoink 3:9bd35e5b05ba 286 unsigned int outputA;
dofydoink 3:9bd35e5b05ba 287 unsigned int outputB;
dofydoink 3:9bd35e5b05ba 288 int output;
dofydoink 3:9bd35e5b05ba 289
dofydoink 3:9bd35e5b05ba 290 switch(channel)
dofydoink 0:20018747657d 291 {
dofydoink 3:9bd35e5b05ba 292 case 1:
dofydoink 0:20018747657d 293 message = CHAN_1;
dofydoink 3:9bd35e5b05ba 294 break;
dofydoink 3:9bd35e5b05ba 295
dofydoink 3:9bd35e5b05ba 296 case 2:
dofydoink 3:9bd35e5b05ba 297 message = CHAN_2;
dofydoink 3:9bd35e5b05ba 298 break;
dofydoink 3:9bd35e5b05ba 299
dofydoink 3:9bd35e5b05ba 300 case 3:
dofydoink 3:9bd35e5b05ba 301 message = CHAN_3;
dofydoink 3:9bd35e5b05ba 302 break;
dofydoink 3:9bd35e5b05ba 303 case 4:
dofydoink 3:9bd35e5b05ba 304 message = CHAN_4;
dofydoink 3:9bd35e5b05ba 305 break;
dofydoink 3:9bd35e5b05ba 306
dofydoink 3:9bd35e5b05ba 307 default:
dofydoink 3:9bd35e5b05ba 308 message = CHAN_1;
dofydoink 0:20018747657d 309 }
dofydoink 0:20018747657d 310
dofydoink 3:9bd35e5b05ba 311 spi.format(8,0);
dofydoink 3:9bd35e5b05ba 312 spi.frequency(3000000);//3MHz clock speed (3.67MHz max)
dofydoink 3:9bd35e5b05ba 313
dofydoink 3:9bd35e5b05ba 314 CSpin.write(0);
dofydoink 3:9bd35e5b05ba 315 spi.write(message);
dofydoink 3:9bd35e5b05ba 316 spi.write(0x00);
dofydoink 3:9bd35e5b05ba 317 outputA = spi.write(0x00);
dofydoink 3:9bd35e5b05ba 318 outputB = spi.write(0x00);
dofydoink 3:9bd35e5b05ba 319 CSpin.write(1);
dofydoink 3:9bd35e5b05ba 320
dofydoink 3:9bd35e5b05ba 321 //convert result to sensible value
dofydoink 3:9bd35e5b05ba 322 outputA = outputA<<8;
dofydoink 3:9bd35e5b05ba 323 output = outputA | outputB;
dofydoink 3:9bd35e5b05ba 324 output = output>>2;
dofydoink 3:9bd35e5b05ba 325
dofydoink 3:9bd35e5b05ba 326 return output;
dofydoink 3:9bd35e5b05ba 327 }
dofydoink 3:9bd35e5b05ba 328
dofydoink 3:9bd35e5b05ba 329 void ADC_Config()
dofydoink 3:9bd35e5b05ba 330 {
dofydoink 3:9bd35e5b05ba 331
dofydoink 3:9bd35e5b05ba 332 unsigned int msg;
dofydoink 3:9bd35e5b05ba 333 spi.format(8,0);
dofydoink 3:9bd35e5b05ba 334 spi.frequency(3000000);//3MHz clock speed (3.67MHz max)
dofydoink 3:9bd35e5b05ba 335
dofydoink 3:9bd35e5b05ba 336 msg = CHAN_1 | RANGE_CONFIG; //config channel 1 set Vref as
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_2 | RANGE_CONFIG; //config channel 2
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 0:20018747657d 353
dofydoink 3:9bd35e5b05ba 354 msg = CHAN_3 | RANGE_CONFIG; //config channel 3
dofydoink 3:9bd35e5b05ba 355 cs_ADC = 0;
dofydoink 3:9bd35e5b05ba 356 spi.write(msg);
dofydoink 3:9bd35e5b05ba 357 cs_ADC = 1;
dofydoink 3:9bd35e5b05ba 358
dofydoink 3:9bd35e5b05ba 359 cs_ADC = 0;
dofydoink 3:9bd35e5b05ba 360 spi.write(EXTERNAL_CLOCK_MODE);
dofydoink 3:9bd35e5b05ba 361 cs_ADC = 1;
dofydoink 3:9bd35e5b05ba 362
dofydoink 3:9bd35e5b05ba 363 msg = CHAN_4 | RANGE_CONFIG; //config channel 4
dofydoink 3:9bd35e5b05ba 364 cs_ADC = 0;
dofydoink 3:9bd35e5b05ba 365 spi.write(msg);
dofydoink 3:9bd35e5b05ba 366 cs_ADC = 1;
dofydoink 3:9bd35e5b05ba 367
dofydoink 3:9bd35e5b05ba 368 cs_ADC = 0;
dofydoink 3:9bd35e5b05ba 369 spi.write(EXTERNAL_CLOCK_MODE);
dofydoink 3:9bd35e5b05ba 370 cs_ADC = 1;
dofydoink 3:9bd35e5b05ba 371
dofydoink 3:9bd35e5b05ba 372 }
dofydoink 0:20018747657d 373
dofydoink 0:20018747657d 374
dofydoink 0:20018747657d 375 int SumDigits(int var)
dofydoink 0:20018747657d 376 {
dofydoink 0:20018747657d 377 int intSumResult = 0;
dofydoink 0:20018747657d 378 int intTempVar = var;
dofydoink 0:20018747657d 379 while (intTempVar >0)
dofydoink 0:20018747657d 380 {
dofydoink 0:20018747657d 381 intSumResult += intTempVar%10;
dofydoink 0:20018747657d 382 intTempVar = int(intTempVar/10);
dofydoink 0:20018747657d 383 //intSumResult += int(var/100)%100;
dofydoink 0:20018747657d 384 }
dofydoink 0:20018747657d 385
dofydoink 0:20018747657d 386 return intSumResult;
dofydoink 0:20018747657d 387 }
dofydoink 0:20018747657d 388
dofydoink 3:9bd35e5b05ba 389 //int EvenParityBitGen(int var)
dofydoink 3:9bd35e5b05ba 390 int OddParityBitGen(int var)
dofydoink 0:20018747657d 391 {
dofydoink 0:20018747657d 392 unsigned int count = 0, i, b = 1;
dofydoink 0:20018747657d 393
dofydoink 0:20018747657d 394 for(i = 0; i < 32; i++){
dofydoink 0:20018747657d 395 if( var & (b << i) ){count++;}
dofydoink 0:20018747657d 396 }
dofydoink 0:20018747657d 397
dofydoink 3:9bd35e5b05ba 398 if( (count % 2) ){
dofydoink 3:9bd35e5b05ba 399 return 0;
dofydoink 3:9bd35e5b05ba 400 }
dofydoink 0:20018747657d 401
dofydoink 0:20018747657d 402 return 1;
dofydoink 0:20018747657d 403 }
dofydoink 0:20018747657d 404
dofydoink 0:20018747657d 405 void CloseGate()
dofydoink 0:20018747657d 406 {
dofydoink 0:20018747657d 407 pinGate = 0;
dofydoink 0:20018747657d 408
dofydoink 0:20018747657d 409 }
dofydoink 0:20018747657d 410
dofydoink 3:9bd35e5b05ba 411
dofydoink 0:20018747657d 412
dofydoink 0:20018747657d 413
dofydoink 3:9bd35e5b05ba 414 void PositionControlPID()
dofydoink 3:9bd35e5b05ba 415 {
dofydoink 3:9bd35e5b05ba 416 while(1)
dofydoink 0:20018747657d 417 {
dofydoink 3:9bd35e5b05ba 418 semPosCtrl.wait();
dofydoink 3:9bd35e5b05ba 419
dofydoink 3:9bd35e5b05ba 420 Mntr2 = !Mntr2;
dofydoink 3:9bd35e5b05ba 421 //Mntr2 = 1 - Mntr2;//!led;
dofydoink 3:9bd35e5b05ba 422 pulsesTest = wheel.getPulses();
dofydoink 3:9bd35e5b05ba 423
dofydoink 3:9bd35e5b05ba 424 double testy = (double) abs(pulsesTest)/2000;
dofydoink 3:9bd35e5b05ba 425 pinSigOut.write(testy);
dofydoink 3:9bd35e5b05ba 426
dofydoink 3:9bd35e5b05ba 427 //take all readings
dofydoink 3:9bd35e5b05ba 428
dofydoink 3:9bd35e5b05ba 429 //sensor readings
dofydoink 3:9bd35e5b05ba 430
dofydoink 3:9bd35e5b05ba 431 intPressureRead = (Read14BitADC(PRESSURE_CHAN, cs_ADC));//read pressure
dofydoink 6:f4d91041b8af 432
dofydoink 6:f4d91041b8af 433 dblPressureVal_norm = ((double) intPressureRead/16383.0);
dofydoink 6:f4d91041b8af 434 dblPressureVal_norm = dblPressureVal_norm*6.144;//convert to voltage
dofydoink 6:f4d91041b8af 435 dblPressureVal_norm = dblPressureVal_norm - 0.5;//subtract offset
dofydoink 6:f4d91041b8af 436 dblPressureVal_norm = dblPressureVal_norm/4.0;//calculate normalised pressure
dofydoink 3:9bd35e5b05ba 437
dofydoink 6:f4d91041b8af 438 if (dblPressureVal_norm >1.0)
dofydoink 6:f4d91041b8af 439 {
dofydoink 6:f4d91041b8af 440 dblPressureVal_norm = 1.0;
dofydoink 6:f4d91041b8af 441 }
dofydoink 6:f4d91041b8af 442 if (dblPressureVal_norm < 0.0)
dofydoink 6:f4d91041b8af 443 {
dofydoink 6:f4d91041b8af 444 dblPressureVal_norm = 0.0;
dofydoink 6:f4d91041b8af 445 }
dofydoink 6:f4d91041b8af 446
dofydoink 6:f4d91041b8af 447 double pressureCheck;
dofydoink 6:f4d91041b8af 448
dofydoink 6:f4d91041b8af 449 //intPressureRead = intPressureRead-1334;
dofydoink 6:f4d91041b8af 450 //intPressureRead = intPressureRead-1679;
dofydoink 3:9bd35e5b05ba 451
dofydoink 6:f4d91041b8af 452 //dblPressureVal_bar = ( (double) intPressureRead/10667)*10.0;
dofydoink 6:f4d91041b8af 453 //pressureCheck = ( (double) intPressureRead/10667)*10.0;
dofydoink 6:f4d91041b8af 454 dblPressureVal_bar = dblPressureVal_norm * 25.0;
dofydoink 3:9bd35e5b05ba 455
dofydoink 6:f4d91041b8af 456 //intFeedBack_pres = (int)(((double)intPressureRead/10667) * 511);
dofydoink 6:f4d91041b8af 457 intFeedBack_pres = (int) (dblPressureVal_bar/12*511);
dofydoink 6:f4d91041b8af 458
dofydoink 6:f4d91041b8af 459 if(intFeedBack_pres > 511)
dofydoink 6:f4d91041b8af 460 {
dofydoink 6:f4d91041b8af 461 intFeedBack_pres = 511;
dofydoink 6:f4d91041b8af 462 }
dofydoink 6:f4d91041b8af 463 if(intFeedBack_pres < 0)
dofydoink 6:f4d91041b8af 464 {
dofydoink 6:f4d91041b8af 465 intFeedBack_pres = 0;
dofydoink 6:f4d91041b8af 466 }
dofydoink 6:f4d91041b8af 467
dofydoink 6:f4d91041b8af 468 //printf("%f\t",dblPos[0]);
dofydoink 6:f4d91041b8af 469 //printf("%d\t",intPressureRead);
dofydoink 6:f4d91041b8af 470 //printf("\r\n");
dofydoink 3:9bd35e5b05ba 471
dofydoink 3:9bd35e5b05ba 472
dofydoink 3:9bd35e5b05ba 473 //intFeedBack_pres = intFeedBack_pres>>5;
dofydoink 3:9bd35e5b05ba 474
dofydoink 3:9bd35e5b05ba 475 intFeedBack_pres = (intFeedBack_pres<<5) | SumDigits(intFeedBack_pres);//add checksum
dofydoink 3:9bd35e5b05ba 476 intFeedBack_pres = (intFeedBack_pres<<1);
dofydoink 3:9bd35e5b05ba 477 intFeedBack_pres = intFeedBack_pres | 0x0001; //add type (1 for pressure)
dofydoink 3:9bd35e5b05ba 478 intFeedBack_pres = (intFeedBack_pres <<1) | OddParityBitGen(intFeedBack_pres);//add parity
dofydoink 3:9bd35e5b05ba 479 intFeedBack_pres = intFeedBack_pres & 0xFFFF;
dofydoink 0:20018747657d 480
dofydoink 3:9bd35e5b05ba 481 unsigned short garb = 0x01;
dofydoink 3:9bd35e5b05ba 482
dofydoink 3:9bd35e5b05ba 483 intPotRead = (16383-Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer
dofydoink 3:9bd35e5b05ba 484 dblPotPositionRead = (double) POT_2_MM*(intPotRead - POT_OFFSET);
dofydoink 3:9bd35e5b05ba 485
dofydoink 3:9bd35e5b05ba 486
dofydoink 3:9bd35e5b05ba 487 //demand Readings
dofydoink 2:aee7d4724915 488
dofydoink 3:9bd35e5b05ba 489
dofydoink 3:9bd35e5b05ba 490 //current reading
dofydoink 3:9bd35e5b05ba 491 analogReadingCurSens = (double) 0.3*pinCurSense.read()+0.7*analogReadingCurSens;
dofydoink 3:9bd35e5b05ba 492
dofydoink 3:9bd35e5b05ba 493 //convert units and filter
dofydoink 3:9bd35e5b05ba 494
dofydoink 3:9bd35e5b05ba 495 //get position and filter
dofydoink 3:9bd35e5b05ba 496 dblPos[0] = (double) pulsesTest*-0.0078125 + dblStartingPos;
dofydoink 3:9bd35e5b05ba 497 dblSensorDriftError = dblPotPositionRead - dblPos[0];
dofydoink 3:9bd35e5b05ba 498
dofydoink 3:9bd35e5b05ba 499 if(dblSensorDriftError > 2.0)//if encoder reading is seriously wrong
dofydoink 3:9bd35e5b05ba 500 {
dofydoink 3:9bd35e5b05ba 501 //dblPos[0] = dblPotPositionRead;
dofydoink 3:9bd35e5b05ba 502 }
dofydoink 3:9bd35e5b05ba 503
dofydoink 6:f4d91041b8af 504
dofydoink 3:9bd35e5b05ba 505 if(intPosFilOrder > 0)
dofydoink 3:9bd35e5b05ba 506 {
dofydoink 3:9bd35e5b05ba 507 for (ii = 1; ii<intPosFilOrder+1; ii++)
dofydoink 3:9bd35e5b05ba 508 {
dofydoink 3:9bd35e5b05ba 509 dblPos[ii] = (double) 0.7*dblPos[ii-1] + 0.3*dblPos[ii];
dofydoink 3:9bd35e5b05ba 510 }
dofydoink 3:9bd35e5b05ba 511 }
dofydoink 3:9bd35e5b05ba 512 else
dofydoink 3:9bd35e5b05ba 513 {
dofydoink 3:9bd35e5b05ba 514 dblPos[intPosFilOrder] = dblPos[0];
dofydoink 3:9bd35e5b05ba 515 }
dofydoink 0:20018747657d 516
dofydoink 3:9bd35e5b05ba 517 //get velocity and filter
dofydoink 3:9bd35e5b05ba 518 dblVel[0] = dblPos[intPosFilOrder] - dblLastPos;
dofydoink 3:9bd35e5b05ba 519 if(intVelFilOrder>0)
dofydoink 3:9bd35e5b05ba 520 {
dofydoink 3:9bd35e5b05ba 521 for (ii = 1; ii<intVelFilOrder+1; ii++)
dofydoink 0:20018747657d 522 {
dofydoink 3:9bd35e5b05ba 523 dblVel[ii] = (double) 0.7*dblVel[ii-1] + 0.3*dblVel[ii];
dofydoink 0:20018747657d 524 }
dofydoink 3:9bd35e5b05ba 525 }
dofydoink 3:9bd35e5b05ba 526 else
dofydoink 3:9bd35e5b05ba 527 {
dofydoink 3:9bd35e5b05ba 528 dblVel[intVelFilOrder] = dblVel[0];
dofydoink 3:9bd35e5b05ba 529 }
dofydoink 3:9bd35e5b05ba 530
dofydoink 3:9bd35e5b05ba 531
dofydoink 3:9bd35e5b05ba 532
dofydoink 5:4e710cef655e 533 intFeedBack_pos = (int) ((dblPos[intPosFilOrder]/MAX_ACTUATOR_LENGTH)*511);
dofydoink 3:9bd35e5b05ba 534
dofydoink 3:9bd35e5b05ba 535 if(intFeedBack_pos>511)
dofydoink 3:9bd35e5b05ba 536 {
dofydoink 3:9bd35e5b05ba 537 intFeedBack_pos = 511;
dofydoink 3:9bd35e5b05ba 538 }
dofydoink 3:9bd35e5b05ba 539
dofydoink 3:9bd35e5b05ba 540 if(intFeedBack_pos<0)
dofydoink 3:9bd35e5b05ba 541 {
dofydoink 3:9bd35e5b05ba 542 intFeedBack_pos = 0;
dofydoink 3:9bd35e5b05ba 543 }
dofydoink 3:9bd35e5b05ba 544
dofydoink 6:f4d91041b8af 545 //printf("%d\r\n",dblPos[intPosFilOrder]);
dofydoink 3:9bd35e5b05ba 546 intFeedBack_pos = (intFeedBack_pos<<5) | SumDigits(intFeedBack_pos);//add checkSum
dofydoink 3:9bd35e5b05ba 547 intFeedBack_pos = intFeedBack_pos <<1; // add type (0 for position)
dofydoink 3:9bd35e5b05ba 548 intFeedBack_pos = (intFeedBack_pos <<1) | OddParityBitGen(intFeedBack_pos);//add parity
dofydoink 3:9bd35e5b05ba 549
dofydoink 3:9bd35e5b05ba 550 //intFeedBack = dblSensorDriftError*8191;
dofydoink 6:f4d91041b8af 551
dofydoink 3:9bd35e5b05ba 552
dofydoink 3:9bd35e5b05ba 553 ///////////////PATH GENERATION////////////////////////
dofydoink 3:9bd35e5b05ba 554 //work out next path point
dofydoink 3:9bd35e5b05ba 555 double dblPathDifference;
dofydoink 3:9bd35e5b05ba 556 dblPathDifference = dblTargetPos - dblLinearPath;
dofydoink 3:9bd35e5b05ba 557 dblPathSign = dblPathDifference/fabs(dblPathDifference); //is velocity positive or negative?
dofydoink 0:20018747657d 558
dofydoink 3:9bd35e5b05ba 559 //check if target has not been reached (with additional 1% of step to be sure)
dofydoink 3:9bd35e5b05ba 560 if (fabs(dblPathDifference) > 1.01*dblTargetVel*dblSampleTime_s) {
dofydoink 3:9bd35e5b05ba 561 dblLinearPath = dblLinearPath + dblPathSign*dblTargetVel*dblSampleTime_s;//next point in path
dofydoink 3:9bd35e5b05ba 562 }
dofydoink 3:9bd35e5b05ba 563 else { //if path is very close to target position
dofydoink 3:9bd35e5b05ba 564 dblLinearPath = dblTargetPos;
dofydoink 3:9bd35e5b05ba 565 }
dofydoink 3:9bd35e5b05ba 566
dofydoink 3:9bd35e5b05ba 567 //limit position
dofydoink 3:9bd35e5b05ba 568 if(dblLinearPath > MAX_POSITION_MM){
dofydoink 3:9bd35e5b05ba 569 dblLinearPath = MAX_POSITION_MM;
dofydoink 3:9bd35e5b05ba 570 }
dofydoink 3:9bd35e5b05ba 571 if (dblLinearPath < 0.0){
dofydoink 3:9bd35e5b05ba 572 dblLinearPath = 0.0;
dofydoink 3:9bd35e5b05ba 573 }
dofydoink 3:9bd35e5b05ba 574
dofydoink 4:3bab17dfae4e 575 dblPosD[intDemPosFilOrder] = 0.07*dblLinearPath + 0.93*dblPosD[intDemPosFilOrder];
dofydoink 3:9bd35e5b05ba 576
dofydoink 3:9bd35e5b05ba 577 //make sure path is safe
dofydoink 3:9bd35e5b05ba 578 if (dblPosD[intDemPosFilOrder] > MAX_POSITION_MM) {
dofydoink 3:9bd35e5b05ba 579 dblPosD[intDemPosFilOrder] = MAX_POSITION_MM;
dofydoink 3:9bd35e5b05ba 580 }
dofydoink 3:9bd35e5b05ba 581 if (dblPosD[intDemPosFilOrder] < 0.0) {
dofydoink 3:9bd35e5b05ba 582 dblPosD[intDemPosFilOrder] = 0.0;
dofydoink 3:9bd35e5b05ba 583 }
dofydoink 3:9bd35e5b05ba 584
dofydoink 3:9bd35e5b05ba 585 dblVelD[0] = dblPosD[intDemPosFilOrder] - dblLastPosD;
dofydoink 3:9bd35e5b05ba 586
dofydoink 3:9bd35e5b05ba 587 ///////////////////////////////////////////////////// End of Path Generation
dofydoink 3:9bd35e5b05ba 588
dofydoink 3:9bd35e5b05ba 589
dofydoink 3:9bd35e5b05ba 590 //run PID calculations
dofydoink 3:9bd35e5b05ba 591 //get errors
dofydoink 3:9bd35e5b05ba 592 dblError = dblPosD[intDemPosFilOrder] - dblPos[intPosFilOrder];
dofydoink 3:9bd35e5b05ba 593 dblErrorDot = dblVelD[intDemVelFilOrder] - dblVel[intVelFilOrder];
dofydoink 3:9bd35e5b05ba 594 //get integral
dofydoink 3:9bd35e5b05ba 595
dofydoink 3:9bd35e5b05ba 596
dofydoink 3:9bd35e5b05ba 597 dblIntTerm = dblIntTerm + Ki*dblError;
dofydoink 3:9bd35e5b05ba 598
dofydoink 3:9bd35e5b05ba 599 //limit integral term
dofydoink 3:9bd35e5b05ba 600 if (dblIntTerm > dblIntLimit)
dofydoink 3:9bd35e5b05ba 601 {
dofydoink 3:9bd35e5b05ba 602 dblIntTerm = dblIntLimit;
dofydoink 3:9bd35e5b05ba 603 }
dofydoink 3:9bd35e5b05ba 604 if (dblIntTerm < -1.0*dblIntLimit)
dofydoink 3:9bd35e5b05ba 605 {
dofydoink 3:9bd35e5b05ba 606 dblIntTerm = (double) -1.0*dblIntLimit;
dofydoink 3:9bd35e5b05ba 607 }
dofydoink 3:9bd35e5b05ba 608
dofydoink 3:9bd35e5b05ba 609 if(fabs(dblError) <0.01)
dofydoink 3:9bd35e5b05ba 610 {
dofydoink 3:9bd35e5b05ba 611 dblError = 0.0;
dofydoink 3:9bd35e5b05ba 612 dblErrorDot = 0.0;
dofydoink 0:20018747657d 613
dofydoink 3:9bd35e5b05ba 614 }
dofydoink 0:20018747657d 615
dofydoink 3:9bd35e5b05ba 616 if (fabs(dblErrorDot) < 0.1)
dofydoink 3:9bd35e5b05ba 617 {
dofydoink 3:9bd35e5b05ba 618 dblErrorDot = 0.0;
dofydoink 3:9bd35e5b05ba 619 }
dofydoink 3:9bd35e5b05ba 620
dofydoink 3:9bd35e5b05ba 621 //calculate output
dofydoink 6:f4d91041b8af 622
dofydoink 6:f4d91041b8af 623
dofydoink 3:9bd35e5b05ba 624 output[0] = Kp*dblError + dblIntTerm + Kd*dblErrorDot;
dofydoink 3:9bd35e5b05ba 625
dofydoink 6:f4d91041b8af 626 //tryPressureControl
dofydoink 6:f4d91041b8af 627 // double dblPosCtrlOut = Kp*dblError + dblIntTerm + Kd*dblErrorDot;
dofydoink 6:f4d91041b8af 628 //
dofydoink 6:f4d91041b8af 629 // double Ki_pres = 10.0;
dofydoink 6:f4d91041b8af 630 // double Kp_pres = 1;
dofydoink 6:f4d91041b8af 631 //
dofydoink 6:f4d91041b8af 632 // double dblPressureError;
dofydoink 6:f4d91041b8af 633 // double dblPressureErrorIntTerm;
dofydoink 6:f4d91041b8af 634 //
dofydoink 6:f4d91041b8af 635 // dblPressureError = dblPosCtrlOut - Pressure
dofydoink 6:f4d91041b8af 636
dofydoink 3:9bd35e5b05ba 637 //limit output
dofydoink 3:9bd35e5b05ba 638 if (output[0] > 0.95)
dofydoink 3:9bd35e5b05ba 639 {
dofydoink 3:9bd35e5b05ba 640 output[0] = 0.95;
dofydoink 3:9bd35e5b05ba 641 }
dofydoink 3:9bd35e5b05ba 642 if (output[0] < -0.95)
dofydoink 3:9bd35e5b05ba 643 {
dofydoink 3:9bd35e5b05ba 644 output[0] = -0.95;
dofydoink 3:9bd35e5b05ba 645 }
dofydoink 3:9bd35e5b05ba 646
dofydoink 3:9bd35e5b05ba 647 if(intOutFilOrder>0)
dofydoink 3:9bd35e5b05ba 648 {
dofydoink 3:9bd35e5b05ba 649 for (ii = 1; ii < intOutFilOrder+1; ii++)
dofydoink 0:20018747657d 650 {
dofydoink 3:9bd35e5b05ba 651 output[ii] = 0.7*output[ii-1] + 0.3*output[ii];
dofydoink 0:20018747657d 652 }
dofydoink 3:9bd35e5b05ba 653 }
dofydoink 3:9bd35e5b05ba 654 else
dofydoink 3:9bd35e5b05ba 655 {
dofydoink 3:9bd35e5b05ba 656 output[intOutFilOrder] = output[0];
dofydoink 3:9bd35e5b05ba 657 }
dofydoink 6:f4d91041b8af 658
dofydoink 6:f4d91041b8af 659
dofydoink 6:f4d91041b8af 660
dofydoink 6:f4d91041b8af 661 //limit pressure
dofydoink 6:f4d91041b8af 662 if (dblPressureVal_bar >dblPressureLimitBar)
dofydoink 6:f4d91041b8af 663 {
dofydoink 6:f4d91041b8af 664 dblErrorPressure = dblPressureVal_bar - dblPressureLimitBar;
dofydoink 6:f4d91041b8af 665 dblDeltaErrorPressure = dblErrorPressure - dblLastErrorPressure;
dofydoink 6:f4d91041b8af 666
dofydoink 6:f4d91041b8af 667 dblPressureLimitBuck = dblPressureLimitGain * dblErrorPressure;
dofydoink 6:f4d91041b8af 668 dblPressureLimitBuck = dblPressureLimitBuck + (dblPressureLimitDerivativeGain*dblDeltaErrorPressure);
dofydoink 6:f4d91041b8af 669 dblPressureLimitBuck = dblPressureLimitBuck *1.9/2.0;
dofydoink 6:f4d91041b8af 670 dblLastErrorPressure = dblErrorPressure;
dofydoink 6:f4d91041b8af 671 }
dofydoink 6:f4d91041b8af 672 else
dofydoink 6:f4d91041b8af 673 {
dofydoink 6:f4d91041b8af 674 dblPressureLimitBuck = 0.0;
dofydoink 6:f4d91041b8af 675 }
dofydoink 6:f4d91041b8af 676
dofydoink 6:f4d91041b8af 677 if (dblPressureLimitBuck < 0.0)
dofydoink 6:f4d91041b8af 678 {
dofydoink 6:f4d91041b8af 679 dblPressureLimitBuck = 0.0;
dofydoink 6:f4d91041b8af 680 }
dofydoink 6:f4d91041b8af 681 if (dblPressureLimitBuck > 1.9)
dofydoink 6:f4d91041b8af 682 {
dofydoink 6:f4d91041b8af 683 dblPressureLimitBuck = 1.9;
dofydoink 6:f4d91041b8af 684 }
dofydoink 6:f4d91041b8af 685
dofydoink 6:f4d91041b8af 686 output[intOutFilOrder] = output[intOutFilOrder] - dblPressureLimitBuck;
dofydoink 6:f4d91041b8af 687
dofydoink 6:f4d91041b8af 688 //limit output
dofydoink 6:f4d91041b8af 689 if (output[intOutFilOrder] > 0.95)
dofydoink 6:f4d91041b8af 690 {
dofydoink 6:f4d91041b8af 691 output[intOutFilOrder] = 0.95;
dofydoink 6:f4d91041b8af 692 }
dofydoink 6:f4d91041b8af 693 if (output[intOutFilOrder] < -0.95)
dofydoink 6:f4d91041b8af 694 {
dofydoink 6:f4d91041b8af 695 output[intOutFilOrder] = -0.95;
dofydoink 6:f4d91041b8af 696 }
dofydoink 6:f4d91041b8af 697
dofydoink 3:9bd35e5b05ba 698 //limit current
dofydoink 3:9bd35e5b05ba 699 if (analogReadingCurSens> CurrentLimitSet)
dofydoink 3:9bd35e5b05ba 700 {
dofydoink 3:9bd35e5b05ba 701 currentBuck = CurrentLimitSet / analogReadingCurSens / currentBuckGain;
dofydoink 3:9bd35e5b05ba 702 }
dofydoink 3:9bd35e5b05ba 703 else
dofydoink 3:9bd35e5b05ba 704 {
dofydoink 3:9bd35e5b05ba 705 currentBuck = 1.0;
dofydoink 3:9bd35e5b05ba 706 }
dofydoink 6:f4d91041b8af 707
dofydoink 6:f4d91041b8af 708 if (currentBuck >1.0)
dofydoink 6:f4d91041b8af 709 {
dofydoink 6:f4d91041b8af 710 currentBuck = 1.0;
dofydoink 6:f4d91041b8af 711 }
dofydoink 6:f4d91041b8af 712
dofydoink 6:f4d91041b8af 713 if (currentBuck <0.0)
dofydoink 6:f4d91041b8af 714 {
dofydoink 6:f4d91041b8af 715 currentBuck = 0.0;
dofydoink 6:f4d91041b8af 716 }
dofydoink 3:9bd35e5b05ba 717
dofydoink 3:9bd35e5b05ba 718 output[intOutFilOrder] = currentBuck*output[intOutFilOrder];
dofydoink 3:9bd35e5b05ba 719 //end Current limit
dofydoink 3:9bd35e5b05ba 720
dofydoink 3:9bd35e5b05ba 721 //find direction
dofydoink 3:9bd35e5b05ba 722 if(output[intOutFilOrder] >=0.0)
dofydoink 3:9bd35e5b05ba 723 {
dofydoink 3:9bd35e5b05ba 724 pinDirectionFwd = 1;
dofydoink 3:9bd35e5b05ba 725 pinDirectionRev = 0;
dofydoink 3:9bd35e5b05ba 726 dblControlBias = 0.0;
dofydoink 3:9bd35e5b05ba 727 }
dofydoink 3:9bd35e5b05ba 728 else
dofydoink 3:9bd35e5b05ba 729 {
dofydoink 3:9bd35e5b05ba 730 pinDirectionFwd = 0;
dofydoink 3:9bd35e5b05ba 731 pinDirectionRev = 1;
dofydoink 3:9bd35e5b05ba 732 dblControlBias = 0.0;
dofydoink 3:9bd35e5b05ba 733 }
dofydoink 3:9bd35e5b05ba 734
dofydoink 3:9bd35e5b05ba 735 pinPwmOutput.write(abs(output[intOutFilOrder])+dblControlBias);
dofydoink 3:9bd35e5b05ba 736
dofydoink 3:9bd35e5b05ba 737 //update all past variables
dofydoink 3:9bd35e5b05ba 738 dblLastPos = dblPos[intPosFilOrder];
dofydoink 3:9bd35e5b05ba 739 dblLastPosD = dblPosD[intDemPosFilOrder];
dofydoink 3:9bd35e5b05ba 740
dofydoink 6:f4d91041b8af 741 ///////////////////Communication (For Carafino: Start)////////////////////////////////
dofydoink 6:f4d91041b8af 742
dofydoink 6:f4d91041b8af 743 //Message handling MCU can only receive messages when gate is 'open'. Gate opens for 500us every 1ms.
dofydoink 6:f4d91041b8af 744 gateTimer.reset();//resets the gate timer
dofydoink 6:f4d91041b8af 745 pinGate = 1;//gate is open. Sets digital output pin to HIGH
dofydoink 6:f4d91041b8af 746 unsigned int outboundMsgs[2] = { intFeedBack_pos , intFeedBack_pres };//prepare feedback messages
dofydoink 3:9bd35e5b05ba 747 unsigned int inboundMsgsData[2] = {0,0};
dofydoink 6:f4d91041b8af 748 while(gateTimer.read_us() < 500) {//while gate is open
dofydoink 0:20018747657d 749
dofydoink 6:f4d91041b8af 750 if(slave.receive()) {//when a message is received
dofydoink 3:9bd35e5b05ba 751
dofydoink 6:f4d91041b8af 752 bool isSPIsuccess = PerformSlaveSPI(&slave,outboundMsgs,inboundMsgsData);//process the data and check if it was corrupted
dofydoink 0:20018747657d 753
dofydoink 6:f4d91041b8af 754 if( isSPIsuccess ) {//if message looks OK
dofydoink 6:f4d91041b8af 755 dblTargetPos = (double)MAX_POSITION_MM*inboundMsgsData[0]/511; //set target position (9-bit value)
dofydoink 3:9bd35e5b05ba 756 if(dblTargetPos>MAX_POSITION_MM) { // Limit demand to ensure safety
dofydoink 3:9bd35e5b05ba 757 dblTargetPos = MAX_POSITION_MM;
dofydoink 3:9bd35e5b05ba 758 } else if(dblTargetPos<0.0) {
dofydoink 3:9bd35e5b05ba 759 dblTargetPos = 0.0;
dofydoink 3:9bd35e5b05ba 760 }
dofydoink 3:9bd35e5b05ba 761
dofydoink 6:f4d91041b8af 762 dblTargetVel = (double)MAX_SPEED_MMPS*inboundMsgsData[1]/511;//set target velocity (9-bit value)
dofydoink 3:9bd35e5b05ba 763
dofydoink 3:9bd35e5b05ba 764 if(dblTargetVel>MAX_SPEED_MMPS) {
dofydoink 3:9bd35e5b05ba 765 dblTargetVel = MAX_SPEED_MMPS;
dofydoink 3:9bd35e5b05ba 766 } else if(dblTargetVel<0.0) {
dofydoink 3:9bd35e5b05ba 767 dblTargetPos = 0.0;
dofydoink 3:9bd35e5b05ba 768 }
dofydoink 3:9bd35e5b05ba 769
dofydoink 6:f4d91041b8af 770 break;//bail out of while loop
dofydoink 2:aee7d4724915 771 }
dofydoink 0:20018747657d 772
dofydoink 0:20018747657d 773 }
dofydoink 0:20018747657d 774
dofydoink 0:20018747657d 775 }
dofydoink 3:9bd35e5b05ba 776
dofydoink 6:f4d91041b8af 777 pinGate = 0;//close gate
dofydoink 6:f4d91041b8af 778
dofydoink 6:f4d91041b8af 779 /*
dofydoink 6:f4d91041b8af 780 printf("%f\t",dblPos[intPosFilOrder]);
dofydoink 6:f4d91041b8af 781 printf("%f\t",dblPosD[intDemPosFilOrder]);
dofydoink 6:f4d91041b8af 782 printf("%f\t",dblTargetPos);
dofydoink 6:f4d91041b8af 783 printf("%f\t",dblError);
dofydoink 6:f4d91041b8af 784 printf("\r\n");
dofydoink 6:f4d91041b8af 785 */
dofydoink 3:9bd35e5b05ba 786
dofydoink 3:9bd35e5b05ba 787 }
dofydoink 3:9bd35e5b05ba 788 }
dofydoink 6:f4d91041b8af 789 //////////////////////////////////////////////////For Carafino: End
dofydoink 0:20018747657d 790
dofydoink 0:20018747657d 791
dofydoink 3:9bd35e5b05ba 792 //configure all control parameters
dofydoink 3:9bd35e5b05ba 793 void ControlParameterConfig()
dofydoink 3:9bd35e5b05ba 794 {
dofydoink 3:9bd35e5b05ba 795 Kp = Kp/dblMotorVoltage;
dofydoink 3:9bd35e5b05ba 796 Kd = Kd/dblSampleTime_s/dblMotorVoltage;
dofydoink 3:9bd35e5b05ba 797 Ki = Ki*dblSampleTime_s/dblMotorVoltage;
dofydoink 3:9bd35e5b05ba 798 }
dofydoink 0:20018747657d 799
dofydoink 0:20018747657d 800 Ticker debugTicker;
dofydoink 0:20018747657d 801
dofydoink 0:20018747657d 802 void startPositionControl()
dofydoink 0:20018747657d 803 {
dofydoink 0:20018747657d 804 semPosCtrl.release();
dofydoink 0:20018747657d 805 }
dofydoink 0:20018747657d 806
dofydoink 0:20018747657d 807 void startDebug()
dofydoink 0:20018747657d 808 {
dofydoink 0:20018747657d 809 semDebug.release();
dofydoink 0:20018747657d 810 }
dofydoink 0:20018747657d 811
dofydoink 0:20018747657d 812 Ticker positionCtrlTicker;
dofydoink 0:20018747657d 813
dofydoink 0:20018747657d 814 int main() {
dofydoink 2:aee7d4724915 815 pinGate = 0;
dofydoink 6:f4d91041b8af 816 pc.baud(115200);
dofydoink 0:20018747657d 817 cs_ADC = 1;
dofydoink 2:aee7d4724915 818 Mntr = 0;
dofydoink 2:aee7d4724915 819 Mntr2 = 0;
dofydoink 0:20018747657d 820 pinPwmOutput.period_us(50);
dofydoink 0:20018747657d 821 printf("\r\nYo Yo Yo, Low Level innit\r\n\n\n");
dofydoink 0:20018747657d 822 wait(0.5);
dofydoink 0:20018747657d 823
dofydoink 0:20018747657d 824 timer.start();
dofydoink 0:20018747657d 825 gateTimer.start();
dofydoink 0:20018747657d 826 //cs_ADC = 1;
dofydoink 0:20018747657d 827
dofydoink 0:20018747657d 828 ControlParameterConfig();
dofydoink 0:20018747657d 829 // for (ii = 0; ii< 10; ii++)
dofydoink 0:20018747657d 830 // {
dofydoink 0:20018747657d 831 // uintPotRead = Read14BitADC(3, cs_ADC);//read potentiometer
dofydoink 0:20018747657d 832 // dblStartingPos = (double) POT_2_MM*uintPotRead - dblPosBias;
dofydoink 0:20018747657d 833 // }
dofydoink 0:20018747657d 834 //
dofydoink 0:20018747657d 835 slave.format(16,2);
dofydoink 0:20018747657d 836 slave.frequency(10000000);
dofydoink 2:aee7d4724915 837
dofydoink 0:20018747657d 838 dblPosD[intDemPosFilOrder] = 0.0;
dofydoink 0:20018747657d 839 slaveReceivePos = 0.0;
dofydoink 0:20018747657d 840 slaveReceiveVel = 0.0;
dofydoink 0:20018747657d 841 wait(0.1);
dofydoink 0:20018747657d 842 ADC_Config();
dofydoink 0:20018747657d 843 wait(0.1);
dofydoink 0:20018747657d 844 ADC_Config();
dofydoink 0:20018747657d 845 wait(0.1);
dofydoink 0:20018747657d 846 intPotRead = (16383-Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer
dofydoink 0:20018747657d 847 //intPotRead = (Read14BitADC(POSITION_CHAN, cs_ADC));//read potentiometer
dofydoink 0:20018747657d 848 dblStartingPos = (double) POT_2_MM*(intPotRead - POT_OFFSET);
dofydoink 2:aee7d4724915 849 dblLinearPath = dblStartingPos;
dofydoink 0:20018747657d 850 dblTargetPos = dblStartingPos;
dofydoink 3:9bd35e5b05ba 851 dblPos[intPosFilOrder] = dblStartingPos;
dofydoink 2:aee7d4724915 852 dblTargetVel = 0.0;
dofydoink 0:20018747657d 853 dblPosD[intDemPosFilOrder] = dblStartingPos;
dofydoink 0:20018747657d 854
dofydoink 6:f4d91041b8af 855 dblTargetPos = 0.0;
dofydoink 6:f4d91041b8af 856 dblPos[intPosFilOrder] = dblStartingPos;
dofydoink 6:f4d91041b8af 857 dblTargetVel = 3.0;
dofydoink 6:f4d91041b8af 858
dofydoink 2:aee7d4724915 859 printf("\r\nPotRead: %d, Current Pos: %f, Target Pos: %f\r\n", intPotRead, dblStartingPos, dblTargetPos);
dofydoink 0:20018747657d 860
dofydoink 0:20018747657d 861 //calculate/convert variables
dofydoink 0:20018747657d 862
dofydoink 0:20018747657d 863 CurrentLimitSet = dblCurrentLimitAmps *0.14/3.3;
dofydoink 2:aee7d4724915 864 slave.reply(0x5555);
dofydoink 0:20018747657d 865 PositionControlThread.start(PositionControlPID);
dofydoink 3:9bd35e5b05ba 866
dofydoink 0:20018747657d 867 positionCtrlTicker.attach(&startPositionControl, dblSampleTime_s);
dofydoink 0:20018747657d 868
dofydoink 0:20018747657d 869 intFeedBack_pos = 0;
dofydoink 0:20018747657d 870 intFeedBack_pres = 0;
dofydoink 0:20018747657d 871
dofydoink 0:20018747657d 872
dofydoink 0:20018747657d 873 while(1)
dofydoink 0:20018747657d 874 {
dofydoink 0:20018747657d 875 Thread::wait(osWaitForever);
dofydoink 0:20018747657d 876 }
dofydoink 3:9bd35e5b05ba 877 }