
Mid level control code
Dependencies: ros_lib_kinetic
main.cpp@5:712e7634c779, 2018-08-01 (annotated)
- Committer:
- dofydoink
- Date:
- Wed Aug 01 09:51:23 2018 +0000
- Revision:
- 5:712e7634c779
- Parent:
- 4:303584310071
- Child:
- 6:f0a18e28a322
Ttested
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dofydoink | 0:607bc887b6e0 | 1 | #include "mbed.h" |
dofydoink | 0:607bc887b6e0 | 2 | #include "math.h" |
dofydoink | 0:607bc887b6e0 | 3 | |
dofydoink | 0:607bc887b6e0 | 4 | //#include "mbed.h" |
dofydoink | 0:607bc887b6e0 | 5 | #include "mbed_events.h" |
dofydoink | 0:607bc887b6e0 | 6 | |
dofydoink | 0:607bc887b6e0 | 7 | //ADC SPI stuff |
dofydoink | 0:607bc887b6e0 | 8 | #define PREAMBLE 0x06 |
dofydoink | 0:607bc887b6e0 | 9 | #define CHAN_1 0x30 |
dofydoink | 0:607bc887b6e0 | 10 | #define CHAN_2 0x70 |
dofydoink | 0:607bc887b6e0 | 11 | #define CHAN_3 0xB0 |
dofydoink | 0:607bc887b6e0 | 12 | #define CHAN_4 0xF0 |
dofydoink | 0:607bc887b6e0 | 13 | |
dofydoink | 0:607bc887b6e0 | 14 | #define DATA_MASK 0x0F |
dofydoink | 0:607bc887b6e0 | 15 | |
WD40andTape | 1:2a43cf183a62 | 16 | //simple channel selection |
dofydoink | 0:607bc887b6e0 | 17 | #define ADC_PRESSURE 1 |
dofydoink | 0:607bc887b6e0 | 18 | #define ADC_POSITION 3 |
WD40andTape | 1:2a43cf183a62 | 19 | //--------------------- |
dofydoink | 0:607bc887b6e0 | 20 | |
dofydoink | 0:607bc887b6e0 | 21 | #define N_CHANNELS 8 //number of channels to control |
dofydoink | 0:607bc887b6e0 | 22 | //1-3: front segment |
dofydoink | 0:607bc887b6e0 | 23 | //4-6: rear segment |
dofydoink | 0:607bc887b6e0 | 24 | //7-8: mid segment |
dofydoink | 0:607bc887b6e0 | 25 | |
dofydoink | 0:607bc887b6e0 | 26 | //parameters to manually change |
dofydoink | 0:607bc887b6e0 | 27 | #define LOW_LEVEL_SPI_FREQUENCY 10000000 |
dofydoink | 0:607bc887b6e0 | 28 | |
WD40andTape | 4:303584310071 | 29 | #define PATH_SAMPLE_TIME_S 0.005 |
dofydoink | 0:607bc887b6e0 | 30 | |
dofydoink | 0:607bc887b6e0 | 31 | #define MAX_LENGTH_MM 100.0 |
WD40andTape | 3:c83291bf9fd2 | 32 | #define MAX_ACTUATOR_LENGTH 52.2 |
dofydoink | 0:607bc887b6e0 | 33 | #define MAX_SPEED_MMPS 24.3457 |
WD40andTape | 4:303584310071 | 34 | #define PATH_TOLERANCE_MM 0.2 //how close the linear path must get to the target position before considering it a success. |
dofydoink | 0:607bc887b6e0 | 35 | |
dofydoink | 5:712e7634c779 | 36 | const double DBL_MAX_CHAMBER_LENGTHS_MM[N_CHANNELS] = {500.0,50.0,50.0,50.0,50.0,50.0,30.0,30.0}; |
WD40andTape | 4:303584310071 | 37 | const double DBL_ACTUATOR_CONVERSION[N_CHANNELS] = {0.24176,0.24176,0.24176,0.24176,0.24176,0.36264,0.36264};// covert from chamber lengths to actuator lengths |
WD40andTape | 4:303584310071 | 38 | const double DBL_SMOOTHING_FACTOR = 0.5; // 0<x<=1, where 1 is no smoothing |
WD40andTape | 4:303584310071 | 39 | const double DBL_PATH_TOLERANCE = 0.2; |
WD40andTape | 4:303584310071 | 40 | //-----These are the variables being shared between High-Level and Mid-Level-----------------------------------------------// |
dofydoink | 0:607bc887b6e0 | 41 | |
dofydoink | 0:607bc887b6e0 | 42 | // |
dofydoink | 0:607bc887b6e0 | 43 | Semaphore semReplan(1);// this must be set every time new high-level transmissions are received to allow replanning to take place! |
dofydoink | 0:607bc887b6e0 | 44 | //--------------------------------------------------------------------------------------------------------------------------// |
dofydoink | 0:607bc887b6e0 | 45 | |
dofydoink | 0:607bc887b6e0 | 46 | //boolean flag to indicate that new target information has been received |
dofydoink | 0:607bc887b6e0 | 47 | //bool blnReplan;//set this when new transmission is received over ethernet |
dofydoink | 0:607bc887b6e0 | 48 | |
dofydoink | 0:607bc887b6e0 | 49 | //path variables |
WD40andTape | 4:303584310071 | 50 | double dblVelocity_mmps[N_CHANNELS] = { 0.0 };//the linear path velocity (not sent to actuator) KEEP GLOBAL |
WD40andTape | 4:303584310071 | 51 | double dblLinearPathCurrentPos_mm[N_CHANNELS]={ 0.0 }; //the current position of the linear path (not sent to actuator) //KEEP GLOBAL |
WD40andTape | 4:303584310071 | 52 | double dblTargetActPos_mm[N_CHANNELS] = { 0.0 }; //The final target position for the actuator KEEP GLOBAL |
dofydoink | 0:607bc887b6e0 | 53 | |
WD40andTape | 4:303584310071 | 54 | int intDemandPos_Tx[N_CHANNELS]; //13-bit value to be sent to the actuator KEEP GLOBAL |
dofydoink | 0:607bc887b6e0 | 55 | |
WD40andTape | 4:303584310071 | 56 | char chrErrorFlag[N_CHANNELS];// 3 error bits from LL KEEP GLOBAL |
dofydoink | 0:607bc887b6e0 | 57 | |
WD40andTape | 4:303584310071 | 58 | //pin declarations---------------- |
dofydoink | 0:607bc887b6e0 | 59 | Serial pc(USBTX, USBRX); // tx, rx for usb debugging |
dofydoink | 0:607bc887b6e0 | 60 | |
WD40andTape | 3:c83291bf9fd2 | 61 | InterruptIn pinGate6(PE_11); //this pin HAS TO BE defined before SPI set up. No Clue Why. |
WD40andTape | 3:c83291bf9fd2 | 62 | |
WD40andTape | 3:c83291bf9fd2 | 63 | SPI spi(PC_12, PC_11, PC_10); // mosi, miso, sclk |
WD40andTape | 3:c83291bf9fd2 | 64 | |
WD40andTape | 3:c83291bf9fd2 | 65 | DigitalOut cs_LL[N_CHANNELS] = {PD_15, PE_10, PD_14, PD_11, PE_7, PD_12, PF_10, PD_13};//chip select for low level controller |
WD40andTape | 3:c83291bf9fd2 | 66 | DigitalOut cs_ADC[N_CHANNELS] = {PG_12, PG_9, PE_1, PG_0, PD_0, PD_1, PF_0, PF_1}; //chip select for ADC |
WD40andTape | 3:c83291bf9fd2 | 67 | |
WD40andTape | 3:c83291bf9fd2 | 68 | DigitalOut pinCheck(PE_5); |
WD40andTape | 3:c83291bf9fd2 | 69 | |
WD40andTape | 3:c83291bf9fd2 | 70 | //these interrupt pins have to be declared AFTER SPI declaration. No Clue Why. |
WD40andTape | 3:c83291bf9fd2 | 71 | InterruptIn pinGate0(PF_11); |
WD40andTape | 3:c83291bf9fd2 | 72 | InterruptIn pinGate1(PG_14); |
WD40andTape | 3:c83291bf9fd2 | 73 | InterruptIn pinGate2(PF_15); |
WD40andTape | 3:c83291bf9fd2 | 74 | InterruptIn pinGate3(PF_12); |
WD40andTape | 3:c83291bf9fd2 | 75 | InterruptIn pinGate4(PF_3); |
WD40andTape | 3:c83291bf9fd2 | 76 | InterruptIn pinGate5(PF_13); |
WD40andTape | 4:303584310071 | 77 | //InterruptIn pinGate6(PE_11); //see above nonsense |
WD40andTape | 3:c83291bf9fd2 | 78 | InterruptIn pinGate7(PE_13); |
dofydoink | 0:607bc887b6e0 | 79 | |
dofydoink | 0:607bc887b6e0 | 80 | DigitalOut pinReset(PD_2); //reset pin for all controllers. |
dofydoink | 0:607bc887b6e0 | 81 | |
WD40andTape | 3:c83291bf9fd2 | 82 | |
dofydoink | 0:607bc887b6e0 | 83 | EventQueue queue(32 * EVENTS_EVENT_SIZE); |
dofydoink | 0:607bc887b6e0 | 84 | |
dofydoink | 0:607bc887b6e0 | 85 | Thread t(osPriorityRealtime); |
dofydoink | 0:607bc887b6e0 | 86 | |
WD40andTape | 4:303584310071 | 87 | Thread threadReceiveAndReplan(osPriorityBelowNormal); |
WD40andTape | 4:303584310071 | 88 | Thread threadSmoothPathPlan(osPriorityNormal); |
dofydoink | 0:607bc887b6e0 | 89 | |
dofydoink | 0:607bc887b6e0 | 90 | Thread threadSimulateDemand(osPriorityHigh); |
dofydoink | 0:607bc887b6e0 | 91 | |
WD40andTape | 1:2a43cf183a62 | 92 | Mutex mutChannel[N_CHANNELS]; |
WD40andTape | 4:303584310071 | 93 | Mutex mutPathIn; |
dofydoink | 0:607bc887b6e0 | 94 | |
dofydoink | 0:607bc887b6e0 | 95 | Semaphore semPathPlan(1);// |
dofydoink | 0:607bc887b6e0 | 96 | |
dofydoink | 0:607bc887b6e0 | 97 | Timer timer;//timers are nice |
dofydoink | 0:607bc887b6e0 | 98 | |
dofydoink | 0:607bc887b6e0 | 99 | int ThreadID[N_CHANNELS]; |
dofydoink | 0:607bc887b6e0 | 100 | |
WD40andTape | 1:2a43cf183a62 | 101 | bool isDataReady[N_CHANNELS]; // flag to indicate path data is ready for transmission to low level. |
dofydoink | 0:607bc887b6e0 | 102 | |
dofydoink | 5:712e7634c779 | 103 | double dblGlobalTest; |
dofydoink | 5:712e7634c779 | 104 | int intGlobalTest; |
WD40andTape | 4:303584310071 | 105 | double ReadADCPosition_mtrs(int channel) |
dofydoink | 0:607bc887b6e0 | 106 | { |
dofydoink | 0:607bc887b6e0 | 107 | unsigned int outputA; |
dofydoink | 0:607bc887b6e0 | 108 | unsigned int outputB; |
WD40andTape | 3:c83291bf9fd2 | 109 | int output; |
WD40andTape | 3:c83291bf9fd2 | 110 | double dblOutput; |
dofydoink | 0:607bc887b6e0 | 111 | |
dofydoink | 0:607bc887b6e0 | 112 | spi.format(8,0); |
dofydoink | 0:607bc887b6e0 | 113 | spi.frequency(1000000); |
dofydoink | 0:607bc887b6e0 | 114 | |
dofydoink | 0:607bc887b6e0 | 115 | cs_ADC[channel] = 0; |
dofydoink | 0:607bc887b6e0 | 116 | spi.write(PREAMBLE); |
dofydoink | 0:607bc887b6e0 | 117 | outputA = spi.write(CHAN_3); |
dofydoink | 0:607bc887b6e0 | 118 | outputB = spi.write(0xFF); |
WD40andTape | 1:2a43cf183a62 | 119 | cs_ADC[channel]= 1; |
dofydoink | 0:607bc887b6e0 | 120 | |
dofydoink | 0:607bc887b6e0 | 121 | outputA = outputA & DATA_MASK; |
dofydoink | 0:607bc887b6e0 | 122 | outputA = outputA<<8; |
dofydoink | 0:607bc887b6e0 | 123 | output = (outputA | outputB); |
WD40andTape | 3:c83291bf9fd2 | 124 | output = 4095- output; |
dofydoink | 5:712e7634c779 | 125 | dblOutput = (double) (output); |
dofydoink | 5:712e7634c779 | 126 | dblOutput = dblOutput*0.0229 - 21.582; |
dofydoink | 5:712e7634c779 | 127 | //dblOutput = dblOutput - 21.78; |
WD40andTape | 3:c83291bf9fd2 | 128 | return dblOutput; |
dofydoink | 5:712e7634c779 | 129 | //dblOutput = (double) ((output/4095)*100.0); |
dofydoink | 5:712e7634c779 | 130 | // dblOutput = dblOutput - 36.727717; |
dofydoink | 5:712e7634c779 | 131 | // return dblOutput; |
dofydoink | 0:607bc887b6e0 | 132 | } |
dofydoink | 0:607bc887b6e0 | 133 | |
WD40andTape | 4:303584310071 | 134 | double ReadADCPressure_bar(int channel) |
dofydoink | 0:607bc887b6e0 | 135 | { |
dofydoink | 0:607bc887b6e0 | 136 | unsigned int outputA; |
dofydoink | 0:607bc887b6e0 | 137 | unsigned int outputB; |
WD40andTape | 3:c83291bf9fd2 | 138 | int output; |
WD40andTape | 3:c83291bf9fd2 | 139 | double dblOutput; |
dofydoink | 0:607bc887b6e0 | 140 | |
dofydoink | 0:607bc887b6e0 | 141 | spi.format(8,0); |
dofydoink | 0:607bc887b6e0 | 142 | spi.frequency(1000000); |
dofydoink | 0:607bc887b6e0 | 143 | |
dofydoink | 0:607bc887b6e0 | 144 | cs_ADC[channel] = 0; |
dofydoink | 0:607bc887b6e0 | 145 | spi.write(PREAMBLE); |
dofydoink | 0:607bc887b6e0 | 146 | outputA = spi.write(CHAN_1); |
dofydoink | 0:607bc887b6e0 | 147 | outputB = spi.write(0xFF); |
dofydoink | 0:607bc887b6e0 | 148 | cs_ADC[channel] = 1; |
dofydoink | 0:607bc887b6e0 | 149 | |
dofydoink | 0:607bc887b6e0 | 150 | outputA = outputA & DATA_MASK; |
dofydoink | 0:607bc887b6e0 | 151 | outputA = outputA<<8; |
dofydoink | 0:607bc887b6e0 | 152 | output = (outputA | outputB); |
dofydoink | 0:607bc887b6e0 | 153 | |
dofydoink | 5:712e7634c779 | 154 | dblOutput = (double)(output); |
dofydoink | 5:712e7634c779 | 155 | dblOutput = dblOutput-502.0; |
dofydoink | 5:712e7634c779 | 156 | dblOutput = dblOutput/4095.0*8.0; |
WD40andTape | 3:c83291bf9fd2 | 157 | return dblOutput; |
dofydoink | 0:607bc887b6e0 | 158 | } |
dofydoink | 0:607bc887b6e0 | 159 | |
WD40andTape | 1:2a43cf183a62 | 160 | void SendReceiveData(int channel) |
dofydoink | 0:607bc887b6e0 | 161 | { |
WD40andTape | 3:c83291bf9fd2 | 162 | |
WD40andTape | 4:303584310071 | 163 | |
WD40andTape | 4:303584310071 | 164 | int intPosSPI_Rx[N_CHANNELS]; //13 bit value received over SPI from the actuator |
WD40andTape | 4:303584310071 | 165 | |
WD40andTape | 4:303584310071 | 166 | |
dofydoink | 0:607bc887b6e0 | 167 | //get data from controller |
dofydoink | 0:607bc887b6e0 | 168 | spi.format(16,2); |
dofydoink | 0:607bc887b6e0 | 169 | spi.frequency(LOW_LEVEL_SPI_FREQUENCY); |
WD40andTape | 4:303584310071 | 170 | mutChannel[channel].lock();//lock mutex for specific Channel |
dofydoink | 0:607bc887b6e0 | 171 | cs_LL[channel] = 0;//select relevant chip |
WD40andTape | 1:2a43cf183a62 | 172 | intPosSPI_Rx[channel] = spi.write(intDemandPos_Tx[channel]); //transmit & receive |
dofydoink | 0:607bc887b6e0 | 173 | cs_LL[channel] = 1;//deselect chip |
WD40andTape | 1:2a43cf183a62 | 174 | isDataReady[channel] = 0;//data no longer ready, i.e. we now require new data |
dofydoink | 5:712e7634c779 | 175 | if(channel == 0) { |
dofydoink | 5:712e7634c779 | 176 | intGlobalTest = intPosSPI_Rx[channel]; |
dofydoink | 5:712e7634c779 | 177 | dblGlobalTest = ((double) (intPosSPI_Rx[channel])/8191.0*52.2); |
dofydoink | 5:712e7634c779 | 178 | } |
WD40andTape | 1:2a43cf183a62 | 179 | |
dofydoink | 0:607bc887b6e0 | 180 | |
dofydoink | 0:607bc887b6e0 | 181 | //sort out received data |
dofydoink | 0:607bc887b6e0 | 182 | chrErrorFlag[channel] = intPosSPI_Rx[channel]>>13; |
WD40andTape | 4:303584310071 | 183 | |
dofydoink | 0:607bc887b6e0 | 184 | intPosSPI_Rx[channel] = intPosSPI_Rx[channel] & 0x1FFF; |
WD40andTape | 4:303584310071 | 185 | //dblPosition_mtrs[channel] = (double)intPosSPI_Rx[channel]/8191*(MAX_ACTUATOR_LENGTH/DBL_ACTUATOR_CONVERSION[channel])/1000; |
WD40andTape | 4:303584310071 | 186 | mutChannel[channel].unlock();//unlock mutex for specific channel |
WD40andTape | 3:c83291bf9fd2 | 187 | //printf("%d, %d\r\n",intPosSPI_Rx[0],intDemandPos_Tx[0]); |
WD40andTape | 3:c83291bf9fd2 | 188 | |
WD40andTape | 3:c83291bf9fd2 | 189 | } |
WD40andTape | 3:c83291bf9fd2 | 190 | |
WD40andTape | 4:303584310071 | 191 | |
dofydoink | 0:607bc887b6e0 | 192 | |
dofydoink | 0:607bc887b6e0 | 193 | //common rise handler function |
dofydoink | 0:607bc887b6e0 | 194 | |
dofydoink | 0:607bc887b6e0 | 195 | void common_rise_handler(int channel) |
dofydoink | 0:607bc887b6e0 | 196 | { |
WD40andTape | 3:c83291bf9fd2 | 197 | pinCheck = 1; |
dofydoink | 0:607bc887b6e0 | 198 | //check if data is ready for tranmission |
WD40andTape | 1:2a43cf183a62 | 199 | if (isDataReady[channel]) |
dofydoink | 0:607bc887b6e0 | 200 | { |
dofydoink | 0:607bc887b6e0 | 201 | // Add transmit task to event queue |
WD40andTape | 1:2a43cf183a62 | 202 | ThreadID[channel] = queue.call(SendReceiveData,channel);//schedule transmission |
dofydoink | 0:607bc887b6e0 | 203 | } |
dofydoink | 0:607bc887b6e0 | 204 | } |
dofydoink | 0:607bc887b6e0 | 205 | |
WD40andTape | 3:c83291bf9fd2 | 206 | |
dofydoink | 0:607bc887b6e0 | 207 | |
dofydoink | 0:607bc887b6e0 | 208 | |
dofydoink | 0:607bc887b6e0 | 209 | //common_fall handler functions |
dofydoink | 0:607bc887b6e0 | 210 | void common_fall_handler(int channel) |
dofydoink | 0:607bc887b6e0 | 211 | { |
WD40andTape | 3:c83291bf9fd2 | 212 | pinCheck = 0; |
dofydoink | 0:607bc887b6e0 | 213 | //cancel relevant queued event |
dofydoink | 0:607bc887b6e0 | 214 | queue.cancel(ThreadID[channel]); |
dofydoink | 0:607bc887b6e0 | 215 | } |
dofydoink | 0:607bc887b6e0 | 216 | |
dofydoink | 0:607bc887b6e0 | 217 | //stub rise functions |
dofydoink | 0:607bc887b6e0 | 218 | void rise0(void) { common_rise_handler(0); } |
dofydoink | 0:607bc887b6e0 | 219 | void rise1(void) { common_rise_handler(1); } |
dofydoink | 0:607bc887b6e0 | 220 | void rise2(void) { common_rise_handler(2); } |
dofydoink | 0:607bc887b6e0 | 221 | void rise3(void) { common_rise_handler(3); } |
dofydoink | 0:607bc887b6e0 | 222 | void rise4(void) { common_rise_handler(4); } |
dofydoink | 0:607bc887b6e0 | 223 | void rise5(void) { common_rise_handler(5); } |
dofydoink | 0:607bc887b6e0 | 224 | void rise6(void) { common_rise_handler(6); } |
dofydoink | 0:607bc887b6e0 | 225 | void rise7(void) { common_rise_handler(7); } |
dofydoink | 0:607bc887b6e0 | 226 | |
dofydoink | 0:607bc887b6e0 | 227 | //stub fall functions |
dofydoink | 0:607bc887b6e0 | 228 | void fall0(void) { common_fall_handler(0); } |
dofydoink | 0:607bc887b6e0 | 229 | void fall1(void) { common_fall_handler(1); } |
dofydoink | 0:607bc887b6e0 | 230 | void fall2(void) { common_fall_handler(2); } |
dofydoink | 0:607bc887b6e0 | 231 | void fall3(void) { common_fall_handler(3); } |
dofydoink | 0:607bc887b6e0 | 232 | void fall4(void) { common_fall_handler(4); } |
dofydoink | 0:607bc887b6e0 | 233 | void fall5(void) { common_fall_handler(5); } |
dofydoink | 0:607bc887b6e0 | 234 | void fall6(void) { common_fall_handler(6); } |
dofydoink | 0:607bc887b6e0 | 235 | void fall7(void) { common_fall_handler(7); } |
dofydoink | 0:607bc887b6e0 | 236 | |
WD40andTape | 1:2a43cf183a62 | 237 | void startPathPlan() // Plan a new linear path after receiving new target data |
dofydoink | 0:607bc887b6e0 | 238 | { |
WD40andTape | 4:303584310071 | 239 | semPathPlan.release(); // Uses threadReceiveAndReplan which is below normal priority to ensure consistent transmission to LL |
dofydoink | 0:607bc887b6e0 | 240 | } |
dofydoink | 0:607bc887b6e0 | 241 | |
dofydoink | 5:712e7634c779 | 242 | double somedumbthing; |
dofydoink | 5:712e7634c779 | 243 | |
dofydoink | 0:607bc887b6e0 | 244 | //this function will be called when a new transmission is received from high level |
WD40andTape | 4:303584310071 | 245 | void ReceiveAndReplan() |
dofydoink | 0:607bc887b6e0 | 246 | { |
WD40andTape | 4:303584310071 | 247 | int ii; |
WD40andTape | 4:303584310071 | 248 | |
WD40andTape | 4:303584310071 | 249 | double dblPSI[3][3]; //the message from high-level containing the chamber lengths in meters in following format: |
WD40andTape | 4:303584310071 | 250 | /* |
WD40andTape | 4:303584310071 | 251 | {L(front,1), L(front,2), L(front,3); |
WD40andTape | 4:303584310071 | 252 | L(mid,1) , L(mid,2) , L(mid,3); |
WD40andTape | 4:303584310071 | 253 | L(rear,1) , L(rear,2) , L(rear,3);} |
WD40andTape | 4:303584310071 | 254 | */ |
WD40andTape | 4:303584310071 | 255 | double dblTargetTime_s; //the time in seconds desired to reach the target (>0...!) |
dofydoink | 5:712e7634c779 | 256 | //double dblPosition_mtrs[N_CHANNELS]; //the actual chamber lengths in meters given as the change in length relative to neutral (should always be >=0) |
dofydoink | 5:712e7634c779 | 257 | // double dblPressure_bar[N_CHANNELS]; //the pressure in a given chamber in bar (1 bar = 100,000 Pa). |
dofydoink | 5:712e7634c779 | 258 | |
WD40andTape | 4:303584310071 | 259 | |
WD40andTape | 4:303584310071 | 260 | //!!!!!!!!!!!!!!! If received messages faster than path replanning, will get increasingly behind time --> need to throw away some instructions |
WD40andTape | 2:eea12b149dba | 261 | |
WD40andTape | 4:303584310071 | 262 | //receive |
WD40andTape | 4:303584310071 | 263 | |
WD40andTape | 4:303584310071 | 264 | double dblTargetChambLen_mm[N_CHANNELS]; //the currenly assigned final target position (actuator will reach this at end of path) |
WD40andTape | 4:303584310071 | 265 | |
WD40andTape | 4:303584310071 | 266 | bool kk = 0; |
WD40andTape | 4:303584310071 | 267 | while(1) { |
WD40andTape | 1:2a43cf183a62 | 268 | |
WD40andTape | 4:303584310071 | 269 | if(kk == 0) { |
dofydoink | 5:712e7634c779 | 270 | dblPSI[0][0] = (double) 0.20; |
dofydoink | 5:712e7634c779 | 271 | dblTargetTime_s = 3.0; |
WD40andTape | 4:303584310071 | 272 | } else { |
WD40andTape | 4:303584310071 | 273 | dblPSI[0][0] = (double) 0.0; |
dofydoink | 5:712e7634c779 | 274 | dblTargetTime_s = 3.0; |
WD40andTape | 4:303584310071 | 275 | } |
WD40andTape | 4:303584310071 | 276 | kk = !kk; |
WD40andTape | 4:303584310071 | 277 | printf("REPLAN, %f,\r\n", dblPSI[0][0] ); |
dofydoink | 0:607bc887b6e0 | 278 | //update front segment |
dofydoink | 0:607bc887b6e0 | 279 | dblTargetChambLen_mm[0] = dblPSI[0][0]*1000; |
dofydoink | 0:607bc887b6e0 | 280 | dblTargetChambLen_mm[1] = dblPSI[0][1]*1000; |
dofydoink | 0:607bc887b6e0 | 281 | dblTargetChambLen_mm[2] = dblPSI[0][2]*1000; |
dofydoink | 0:607bc887b6e0 | 282 | //update mid segment |
dofydoink | 0:607bc887b6e0 | 283 | dblTargetChambLen_mm[6] = dblPSI[1][0]*1000; |
dofydoink | 0:607bc887b6e0 | 284 | dblTargetChambLen_mm[7] = dblTargetChambLen_mm[6]; //same because two pumps are used |
dofydoink | 0:607bc887b6e0 | 285 | //update rear segment |
dofydoink | 0:607bc887b6e0 | 286 | dblTargetChambLen_mm[3] = dblPSI[2][0]*1000; |
dofydoink | 0:607bc887b6e0 | 287 | dblTargetChambLen_mm[4] = dblPSI[2][1]*1000; |
dofydoink | 0:607bc887b6e0 | 288 | dblTargetChambLen_mm[5] = dblPSI[2][2]*1000; |
dofydoink | 0:607bc887b6e0 | 289 | |
WD40andTape | 4:303584310071 | 290 | for (ii = 0; ii< N_CHANNELS; ii++) { |
dofydoink | 0:607bc887b6e0 | 291 | //check to see if positions are achievable |
WD40andTape | 4:303584310071 | 292 | if(dblTargetChambLen_mm[ii]>DBL_MAX_CHAMBER_LENGTHS_MM[ii]) { |
WD40andTape | 4:303584310071 | 293 | dblTargetChambLen_mm[ii] = DBL_MAX_CHAMBER_LENGTHS_MM[ii]; |
dofydoink | 0:607bc887b6e0 | 294 | } |
WD40andTape | 4:303584310071 | 295 | if(dblTargetChambLen_mm[ii]<0.0) { |
dofydoink | 0:607bc887b6e0 | 296 | dblTargetChambLen_mm[ii] = 0.0; |
dofydoink | 0:607bc887b6e0 | 297 | } |
dofydoink | 0:607bc887b6e0 | 298 | |
dofydoink | 5:712e7634c779 | 299 | mutPathIn.lock();//lock variables to avoid race condition |
dofydoink | 5:712e7634c779 | 300 | dblTargetActPos_mm[ii] = dblTargetChambLen_mm[ii]*DBL_ACTUATOR_CONVERSION[ii]; |
dofydoink | 5:712e7634c779 | 301 | |
dofydoink | 5:712e7634c779 | 302 | //work out new velocities |
dofydoink | 5:712e7634c779 | 303 | dblVelocity_mmps[ii] = (dblTargetActPos_mm[ii] - dblLinearPathCurrentPos_mm[ii]) / dblTargetTime_s; |
dofydoink | 5:712e7634c779 | 304 | |
dofydoink | 5:712e7634c779 | 305 | //check to see if velocities are achievable |
dofydoink | 5:712e7634c779 | 306 | if(abs(dblVelocity_mmps[ii]) > MAX_SPEED_MMPS) { |
dofydoink | 5:712e7634c779 | 307 | if(dblVelocity_mmps[ii]>0) { |
dofydoink | 5:712e7634c779 | 308 | dblVelocity_mmps[ii] = MAX_SPEED_MMPS; |
dofydoink | 5:712e7634c779 | 309 | } else { |
dofydoink | 5:712e7634c779 | 310 | dblVelocity_mmps[ii] = -1*MAX_SPEED_MMPS; |
dofydoink | 5:712e7634c779 | 311 | } |
dofydoink | 5:712e7634c779 | 312 | } |
dofydoink | 5:712e7634c779 | 313 | mutPathIn.unlock(); //unlock mutex. |
dofydoink | 0:607bc887b6e0 | 314 | |
dofydoink | 0:607bc887b6e0 | 315 | |
dofydoink | 5:712e7634c779 | 316 | //dblPressure_bar[ii] = 0.5;//read pressure from channel |
dofydoink | 5:712e7634c779 | 317 | // dblPosition_mtrs[ii] = 0.02; //read position from channel |
WD40andTape | 4:303584310071 | 318 | |
WD40andTape | 4:303584310071 | 319 | //send info back to HL |
WD40andTape | 4:303584310071 | 320 | } // end of for |
WD40andTape | 4:303584310071 | 321 | //printf("%f\r\n", dblVelocity_mmps[0]); |
WD40andTape | 4:303584310071 | 322 | Thread::wait(7000); |
WD40andTape | 4:303584310071 | 323 | } // end of while(1) |
dofydoink | 0:607bc887b6e0 | 324 | } |
dofydoink | 0:607bc887b6e0 | 325 | |
WD40andTape | 2:eea12b149dba | 326 | // lock mutex |
WD40andTape | 2:eea12b149dba | 327 | // get variables |
WD40andTape | 2:eea12b149dba | 328 | // unlock mutex |
WD40andTape | 2:eea12b149dba | 329 | // do calculations |
WD40andTape | 2:eea12b149dba | 330 | // lock mutex |
WD40andTape | 2:eea12b149dba | 331 | // set variables |
WD40andTape | 4:303584310071 | 332 | // unlock mutex |
WD40andTape | 2:eea12b149dba | 333 | |
WD40andTape | 4:303584310071 | 334 | void CalculateSmoothPath() { |
dofydoink | 5:712e7634c779 | 335 | int jj; |
WD40andTape | 1:2a43cf183a62 | 336 | double dblMeasuredSampleTime; |
WD40andTape | 4:303584310071 | 337 | double dblSmoothPathCurrentPos_mm[N_CHANNELS] = { 0.0 }; //the current position of the smooth path (not sent to actuator) |
dofydoink | 5:712e7634c779 | 338 | double dblPosition_mtrs[N_CHANNELS]; //the actual chamber lengths in meters given as the change in length relative to neutral (should always be >=0) |
dofydoink | 5:712e7634c779 | 339 | double dblPressure_bar[N_CHANNELS]; //the pressure in a given chamber in bar (1 bar = 100,000 Pa). |
WD40andTape | 4:303584310071 | 340 | |
WD40andTape | 4:303584310071 | 341 | while(1) { |
dofydoink | 0:607bc887b6e0 | 342 | semPathPlan.wait(); |
WD40andTape | 1:2a43cf183a62 | 343 | |
WD40andTape | 1:2a43cf183a62 | 344 | // If run time is more than 50 us from expected, calculate from measured time step |
WD40andTape | 4:303584310071 | 345 | if (fabs(PATH_SAMPLE_TIME_S*1000000 - timer.read_us()) > 50) { |
dofydoink | 5:712e7634c779 | 346 | dblMeasuredSampleTime = timer.read(); |
WD40andTape | 4:303584310071 | 347 | } else { |
WD40andTape | 1:2a43cf183a62 | 348 | dblMeasuredSampleTime = PATH_SAMPLE_TIME_S; |
WD40andTape | 1:2a43cf183a62 | 349 | } |
WD40andTape | 4:303584310071 | 350 | timer.reset(); |
WD40andTape | 1:2a43cf183a62 | 351 | |
dofydoink | 5:712e7634c779 | 352 | for(jj = 0; jj < N_CHANNELS; jj++) { |
dofydoink | 5:712e7634c779 | 353 | |
dofydoink | 5:712e7634c779 | 354 | dblPressure_bar[jj] = ReadADCPressure_bar(jj);//read pressure from channel |
dofydoink | 5:712e7634c779 | 355 | dblPosition_mtrs[jj] = ReadADCPosition_mtrs(jj); //read position from channel |
dofydoink | 5:712e7634c779 | 356 | //DEBUGGING |
dofydoink | 5:712e7634c779 | 357 | //if(jj == 0) printf("BEFORE: %f, %f, %f\r\n",dblVelocity_mmps[0],dblPosition_mtrs[0], dblMeasuredSampleTime); |
WD40andTape | 1:2a43cf183a62 | 358 | |
dofydoink | 5:712e7634c779 | 359 | //calculate next step in linear path |
dofydoink | 5:712e7634c779 | 360 | mutPathIn.lock();//lock relevant mutex |
dofydoink | 5:712e7634c779 | 361 | dblLinearPathCurrentPos_mm[jj] = dblLinearPathCurrentPos_mm[jj] + dblVelocity_mmps[jj]*dblMeasuredSampleTime; // PATH_SAMPLE_TIME_S SHOULD BE MEASURED |
dofydoink | 5:712e7634c779 | 362 | if(dblLinearPathCurrentPos_mm[jj] < 0.0) { |
dofydoink | 5:712e7634c779 | 363 | dblLinearPathCurrentPos_mm[jj] = 0.00; |
dofydoink | 5:712e7634c779 | 364 | } |
dofydoink | 5:712e7634c779 | 365 | |
dofydoink | 5:712e7634c779 | 366 | //check tolerance |
dofydoink | 5:712e7634c779 | 367 | if (fabs(dblLinearPathCurrentPos_mm[jj] - dblTargetActPos_mm[jj]) <= DBL_PATH_TOLERANCE) { |
dofydoink | 5:712e7634c779 | 368 | dblVelocity_mmps[jj] = 0.0; //stop linear path generation when linear path is within tolerance of target position. |
dofydoink | 5:712e7634c779 | 369 | } |
dofydoink | 5:712e7634c779 | 370 | mutPathIn.unlock();//unlock relevant mutex |
dofydoink | 0:607bc887b6e0 | 371 | |
dofydoink | 0:607bc887b6e0 | 372 | //calculate next step in smooth path |
dofydoink | 5:712e7634c779 | 373 | dblSmoothPathCurrentPos_mm[jj] = DBL_SMOOTHING_FACTOR*dblLinearPathCurrentPos_mm[jj] + (1.0-DBL_SMOOTHING_FACTOR)*dblSmoothPathCurrentPos_mm[jj]; |
dofydoink | 5:712e7634c779 | 374 | |
dofydoink | 5:712e7634c779 | 375 | mutChannel[jj].lock(); //MUTEX LOCK |
dofydoink | 5:712e7634c779 | 376 | intDemandPos_Tx[jj] = (int) ((dblSmoothPathCurrentPos_mm[jj]/MAX_ACTUATOR_LENGTH)*8191);//convert to a 13-bit number; |
dofydoink | 5:712e7634c779 | 377 | intDemandPos_Tx[jj] = intDemandPos_Tx[jj] & 0x1FFF; //ensure number is 13-bit |
dofydoink | 5:712e7634c779 | 378 | mutChannel[jj].unlock(); //MUTEX UNLOCK |
dofydoink | 5:712e7634c779 | 379 | //if(jj == 0) printf("AFTER: %f, %f, %f\r\n",dblLinearPathCurrentPos_mm[jj],dblVelocity_mmps[jj],dblMeasuredSampleTime); |
dofydoink | 0:607bc887b6e0 | 380 | |
dofydoink | 5:712e7634c779 | 381 | isDataReady[jj] = 1;//signal that data ready |
dofydoink | 0:607bc887b6e0 | 382 | |
WD40andTape | 4:303584310071 | 383 | } // end for |
WD40andTape | 4:303584310071 | 384 | //printf("%f, %d\r\n",dblSmoothPathCurrentPos_mm[0], intDemandPos_Tx[0]); |
dofydoink | 5:712e7634c779 | 385 | mutChannel[0].lock(); |
dofydoink | 5:712e7634c779 | 386 | printf("%f, %f, %f\r\n",dblSmoothPathCurrentPos_mm[0],dblPressure_bar[0], dblPosition_mtrs[0]); |
dofydoink | 5:712e7634c779 | 387 | mutChannel[0].unlock(); |
WD40andTape | 4:303584310071 | 388 | } // end while |
WD40andTape | 3:c83291bf9fd2 | 389 | } |
dofydoink | 0:607bc887b6e0 | 390 | |
dofydoink | 0:607bc887b6e0 | 391 | |
dofydoink | 0:607bc887b6e0 | 392 | |
dofydoink | 0:607bc887b6e0 | 393 | Ticker PathCalculationTicker; |
dofydoink | 0:607bc887b6e0 | 394 | |
dofydoink | 0:607bc887b6e0 | 395 | int main() |
dofydoink | 0:607bc887b6e0 | 396 | { |
WD40andTape | 4:303584310071 | 397 | int ii; |
WD40andTape | 3:c83291bf9fd2 | 398 | |
dofydoink | 0:607bc887b6e0 | 399 | //initialise relevant variables |
dofydoink | 0:607bc887b6e0 | 400 | for(ii = 0; ii<N_CHANNELS; ii++) |
dofydoink | 0:607bc887b6e0 | 401 | { |
WD40andTape | 3:c83291bf9fd2 | 402 | |
dofydoink | 0:607bc887b6e0 | 403 | //all chip selects in off state |
dofydoink | 0:607bc887b6e0 | 404 | cs_LL[ii] = 1; |
dofydoink | 0:607bc887b6e0 | 405 | cs_ADC[ii] = 1; |
dofydoink | 0:607bc887b6e0 | 406 | |
dofydoink | 0:607bc887b6e0 | 407 | //data ready flags set to not ready |
WD40andTape | 1:2a43cf183a62 | 408 | isDataReady[ii] = 0; |
dofydoink | 0:607bc887b6e0 | 409 | } |
dofydoink | 0:607bc887b6e0 | 410 | |
dofydoink | 0:607bc887b6e0 | 411 | //calculate some control variables |
WD40andTape | 4:303584310071 | 412 | //dblPathTolerance = 0.1;//MAX_SPEED_MMPS * PATH_SAMPLE_TIME_S * 1.05; //path tolerance in mm. |
dofydoink | 0:607bc887b6e0 | 413 | |
dofydoink | 0:607bc887b6e0 | 414 | pinReset = 1; //initialise reset pin to not reset the controllers. |
dofydoink | 5:712e7634c779 | 415 | wait(0.25); |
WD40andTape | 3:c83291bf9fd2 | 416 | pinReset=0; //reset controllers to be safe |
dofydoink | 5:712e7634c779 | 417 | wait(0.25); |
WD40andTape | 3:c83291bf9fd2 | 418 | pinReset = 1;//ready to go |
dofydoink | 0:607bc887b6e0 | 419 | |
dofydoink | 0:607bc887b6e0 | 420 | //say something nice to the user. |
dofydoink | 5:712e7634c779 | 421 | pc.baud(115200); |
dofydoink | 0:607bc887b6e0 | 422 | printf("Hi, there! I'll be your mid-level controller for today.\r\n"); |
dofydoink | 5:712e7634c779 | 423 | wait(3); |
dofydoink | 0:607bc887b6e0 | 424 | // Start the event queue |
dofydoink | 0:607bc887b6e0 | 425 | t.start(callback(&queue, &EventQueue::dispatch_forever)); |
dofydoink | 0:607bc887b6e0 | 426 | |
dofydoink | 0:607bc887b6e0 | 427 | //set up the interrupts |
dofydoink | 0:607bc887b6e0 | 428 | |
dofydoink | 0:607bc887b6e0 | 429 | //set up rise interrupts MIGHT NOT NEED TO BE POINTERS |
WD40andTape | 3:c83291bf9fd2 | 430 | // |
WD40andTape | 3:c83291bf9fd2 | 431 | //pinGate[0].rise(&testRiseFunction); |
WD40andTape | 3:c83291bf9fd2 | 432 | //testPinGate.rise(&testRiseFunction);//<working |
WD40andTape | 3:c83291bf9fd2 | 433 | //testPinGate.rise(&rise0); |
WD40andTape | 3:c83291bf9fd2 | 434 | |
WD40andTape | 3:c83291bf9fd2 | 435 | pinGate0.rise(&rise0); |
dofydoink | 5:712e7634c779 | 436 | |
WD40andTape | 3:c83291bf9fd2 | 437 | pinGate1.rise(&rise1); |
WD40andTape | 3:c83291bf9fd2 | 438 | pinGate2.rise(&rise2); |
WD40andTape | 3:c83291bf9fd2 | 439 | pinGate3.rise(&rise3); |
WD40andTape | 3:c83291bf9fd2 | 440 | pinGate4.rise(&rise4); |
WD40andTape | 3:c83291bf9fd2 | 441 | pinGate5.rise(&rise5); |
WD40andTape | 3:c83291bf9fd2 | 442 | pinGate6.rise(&rise6); |
WD40andTape | 3:c83291bf9fd2 | 443 | pinGate7.rise(&rise7); |
dofydoink | 5:712e7634c779 | 444 | |
dofydoink | 0:607bc887b6e0 | 445 | |
dofydoink | 0:607bc887b6e0 | 446 | //set up fall interrupts MIGHT NOT NEED TO BE POINTERS |
WD40andTape | 3:c83291bf9fd2 | 447 | // |
WD40andTape | 3:c83291bf9fd2 | 448 | //pinGate[0].fall(&testFallFunction); |
WD40andTape | 3:c83291bf9fd2 | 449 | //testPinGate.fall(&testFallFunction); <working |
WD40andTape | 3:c83291bf9fd2 | 450 | //testPinGate.fall(&fall0); |
WD40andTape | 3:c83291bf9fd2 | 451 | |
WD40andTape | 3:c83291bf9fd2 | 452 | pinGate0.fall(&fall0); |
dofydoink | 5:712e7634c779 | 453 | |
WD40andTape | 3:c83291bf9fd2 | 454 | pinGate1.fall(&fall1); |
WD40andTape | 3:c83291bf9fd2 | 455 | pinGate2.fall(&fall2); |
WD40andTape | 3:c83291bf9fd2 | 456 | pinGate3.fall(&fall3); |
WD40andTape | 3:c83291bf9fd2 | 457 | pinGate4.fall(&fall4); |
WD40andTape | 3:c83291bf9fd2 | 458 | pinGate5.fall(&fall5); |
WD40andTape | 3:c83291bf9fd2 | 459 | pinGate6.fall(&fall6); |
WD40andTape | 3:c83291bf9fd2 | 460 | pinGate7.fall(&fall7); |
dofydoink | 5:712e7634c779 | 461 | |
dofydoink | 0:607bc887b6e0 | 462 | |
dofydoink | 0:607bc887b6e0 | 463 | timer.start(); |
dofydoink | 0:607bc887b6e0 | 464 | |
WD40andTape | 4:303584310071 | 465 | //threadSimulateDemand.start(SimulateDemand); |
WD40andTape | 4:303584310071 | 466 | threadReceiveAndReplan.start(ReceiveAndReplan);//start Replanning thread |
WD40andTape | 4:303584310071 | 467 | //ReceiveAndReplan(); |
WD40andTape | 4:303584310071 | 468 | threadSmoothPathPlan.start(CalculateSmoothPath); //start planning thread |
WD40andTape | 1:2a43cf183a62 | 469 | |
dofydoink | 0:607bc887b6e0 | 470 | PathCalculationTicker.attach(&startPathPlan, PATH_SAMPLE_TIME_S); //set up planning thread to recur at fixed intervals |
WD40andTape | 1:2a43cf183a62 | 471 | |
dofydoink | 0:607bc887b6e0 | 472 | Thread::wait(1); |
WD40andTape | 3:c83291bf9fd2 | 473 | |
dofydoink | 0:607bc887b6e0 | 474 | |
WD40andTape | 1:2a43cf183a62 | 475 | while(1) { |
WD40andTape | 1:2a43cf183a62 | 476 | Thread::wait(osWaitForever); |
dofydoink | 0:607bc887b6e0 | 477 | } |
dofydoink | 0:607bc887b6e0 | 478 | } |
dofydoink | 0:607bc887b6e0 | 479 |