Basic Mid-Level control for the rebuilt MorphGI control unit, using PWM to communicate with the low level controllers.

Dependencies:   ros_lib_kinetic

Committer:
WD40andTape
Date:
Wed Jul 25 13:43:59 2018 +0000
Revision:
1:2a43cf183a62
Parent:
0:607bc887b6e0
Child:
2:eea12b149dba
Improved variable names and fixed some real-time issues.

Who changed what in which revision?

UserRevisionLine numberNew 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
dofydoink 0:607bc887b6e0 29 #define PATH_SAMPLE_TIME_S 0.05
dofydoink 0:607bc887b6e0 30
dofydoink 0:607bc887b6e0 31 #define MAX_LENGTH_MM 100.0
dofydoink 0:607bc887b6e0 32 #define MAX_ACTUATOR_LENGTH 50.0
dofydoink 0:607bc887b6e0 33 #define MAX_SPEED_MMPS 24.3457
dofydoink 0:607bc887b6e0 34 #define PATH_TOLERANCE_MM 0.2
dofydoink 0:607bc887b6e0 35
dofydoink 0:607bc887b6e0 36 double dblMaxChamberLengths_mm[N_CHANNELS] = {100.0,50.0,50.0,50.0,50.0,50.0,30.0,30.0};
dofydoink 0:607bc887b6e0 37
dofydoink 0:607bc887b6e0 38
dofydoink 0:607bc887b6e0 39
dofydoink 0:607bc887b6e0 40 int ii,jj,kk; //counting varaibles
dofydoink 0:607bc887b6e0 41
dofydoink 0:607bc887b6e0 42 //-----These are the variables being shared between High-Level and Mid-Level-----------------------------------------------//
dofydoink 0:607bc887b6e0 43
dofydoink 0:607bc887b6e0 44 double dblPSI[3][3]; //the message from high-level containing the chamber lengths in meters in following format:
dofydoink 0:607bc887b6e0 45 /*
dofydoink 0:607bc887b6e0 46 {L(front,1), L(front,2), L(front,3);
dofydoink 0:607bc887b6e0 47 L(mid,1) , L(mid,2) , L(mid,3);
dofydoink 0:607bc887b6e0 48 L(rear,1) , L(rear,2) , L(rear,3);}
dofydoink 0:607bc887b6e0 49 */
dofydoink 0:607bc887b6e0 50
dofydoink 0:607bc887b6e0 51 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 0:607bc887b6e0 52 double dblPressure_bar[N_CHANNELS]; //the pressure in a given chamber in bar (1 bar = 100,000 Pa).
dofydoink 0:607bc887b6e0 53 double dblTargetTime_s; //the time in seconds desired to reach the target (>0...!)
dofydoink 0:607bc887b6e0 54
dofydoink 0:607bc887b6e0 55 //
dofydoink 0:607bc887b6e0 56 Semaphore semReplan(1);// this must be set every time new high-level transmissions are received to allow replanning to take place!
dofydoink 0:607bc887b6e0 57 //--------------------------------------------------------------------------------------------------------------------------//
dofydoink 0:607bc887b6e0 58
dofydoink 0:607bc887b6e0 59 //boolean flag to indicate that new target information has been received
dofydoink 0:607bc887b6e0 60 //bool blnReplan;//set this when new transmission is received over ethernet
dofydoink 0:607bc887b6e0 61
dofydoink 0:607bc887b6e0 62 //path variables
dofydoink 0:607bc887b6e0 63 double dblVelocity_mmps[N_CHANNELS];//the linear path velocity (not sent to actuator)
dofydoink 0:607bc887b6e0 64 double dblLinearPath_mm[N_CHANNELS]; //the current position of the linear path (not sent to actuator)
dofydoink 0:607bc887b6e0 65 double dblSmoothPath_mm[N_CHANNELS]; //the current position of the smooth path (not sent to actuator)
dofydoink 0:607bc887b6e0 66 double dblTargetChambLen_mm[N_CHANNELS]; //the currenly assigned final target position (actuator will reach this at end of path)
dofydoink 0:607bc887b6e0 67 double dblTargetActLen_mm[N_CHANNELS];
dofydoink 0:607bc887b6e0 68 double dblPathToActuator[N_CHANNELS];//the target position for the actuator (sent to actuator)
dofydoink 0:607bc887b6e0 69
WD40andTape 1:2a43cf183a62 70 int intDemandPos_Tx[N_CHANNELS]; //13-bit value to be sent to the actuator
dofydoink 0:607bc887b6e0 71 int intPosSPI_Rx[N_CHANNELS]; //13 bit value received over SPI from the actuator
dofydoink 0:607bc887b6e0 72 int intPosADC_Rx[N_CHANNELS]; //12-bit ADC reading of potentiometer on actuator
dofydoink 0:607bc887b6e0 73
dofydoink 0:607bc887b6e0 74 double dblPathTolerance; //how close the linear path must get to the target position before considering it a success.
dofydoink 0:607bc887b6e0 75
WD40andTape 1:2a43cf183a62 76 double dblActuatorConversion[N_CHANNELS] = {0.24176,0.24176,0.24176,0.24176,0.24176,0.36264,0.36264};// covert from chamber lengths to actuator lengths
dofydoink 0:607bc887b6e0 77
WD40andTape 1:2a43cf183a62 78 double dblSmoothingFactor = 0.5; // 0<x<=1, where 1 is no smoothing
dofydoink 0:607bc887b6e0 79
WD40andTape 1:2a43cf183a62 80 char chrErrorFlag[N_CHANNELS];// 3 error bits from LL
dofydoink 0:607bc887b6e0 81
dofydoink 0:607bc887b6e0 82 Serial pc(USBTX, USBRX); // tx, rx for usb debugging
dofydoink 0:607bc887b6e0 83
dofydoink 0:607bc887b6e0 84 SPI spi(PC_12,PC_11, PC_10); // mosi, miso, sclk
dofydoink 0:607bc887b6e0 85
dofydoink 0:607bc887b6e0 86 DigitalOut cs_LL[N_CHANNELS] = {PF_10, PD_13, PE_7, PD_12, PD_14, PD_11, PD_15, PE_10};//chip select for low level controller
dofydoink 0:607bc887b6e0 87 DigitalOut cs_ADC[N_CHANNELS] = {PF_1, PF_0, PD_1, PD_0, PG_0, PE_1, PG_9, PG_12}; //chip select for ADC
dofydoink 0:607bc887b6e0 88
dofydoink 0:607bc887b6e0 89 InterruptIn pinGate[N_CHANNELS] ={PE_11, PE_13, PF_3, PF_13, PF_15, PF_12, PF_11, PG_14};//gate interrupt pins
dofydoink 0:607bc887b6e0 90
dofydoink 0:607bc887b6e0 91 DigitalOut pinReset(PD_2); //reset pin for all controllers.
dofydoink 0:607bc887b6e0 92
dofydoink 0:607bc887b6e0 93 EventQueue queue(32 * EVENTS_EVENT_SIZE);
dofydoink 0:607bc887b6e0 94
dofydoink 0:607bc887b6e0 95 Thread t(osPriorityRealtime);
dofydoink 0:607bc887b6e0 96
dofydoink 0:607bc887b6e0 97 Thread threadReplan(osPriorityBelowNormal);
dofydoink 0:607bc887b6e0 98 Thread threadPathPlan(osPriorityNormal);
dofydoink 0:607bc887b6e0 99
dofydoink 0:607bc887b6e0 100 Thread threadSimulateDemand(osPriorityHigh);
dofydoink 0:607bc887b6e0 101
WD40andTape 1:2a43cf183a62 102 Mutex mutChannel[N_CHANNELS];
WD40andTape 1:2a43cf183a62 103 Mutex mutPsi;
dofydoink 0:607bc887b6e0 104
dofydoink 0:607bc887b6e0 105 Semaphore semPathPlan(1);//
dofydoink 0:607bc887b6e0 106
dofydoink 0:607bc887b6e0 107 Timer timer;//timers are nice
dofydoink 0:607bc887b6e0 108
dofydoink 0:607bc887b6e0 109
dofydoink 0:607bc887b6e0 110 /*
dofydoink 0:607bc887b6e0 111 unsigned int result1 = 0;
dofydoink 0:607bc887b6e0 112 unsigned int result2 = 0;
dofydoink 0:607bc887b6e0 113 unsigned int result3 = 0;
dofydoink 0:607bc887b6e0 114 unsigned int result4 = 0;
dofydoink 0:607bc887b6e0 115
dofydoink 0:607bc887b6e0 116 unsigned int result1a = 0;
dofydoink 0:607bc887b6e0 117 unsigned int result1b = 0;
dofydoink 0:607bc887b6e0 118 */
dofydoink 0:607bc887b6e0 119
dofydoink 0:607bc887b6e0 120
dofydoink 0:607bc887b6e0 121
WD40andTape 1:2a43cf183a62 122 /*
WD40andTape 1:2a43cf183a62 123 double dblDemandPosition[N_CHANNELS];
dofydoink 0:607bc887b6e0 124 double dblPosition[N_CHANNELS];
dofydoink 0:607bc887b6e0 125 double dblPressure[N_CHANNELS];
WD40andTape 1:2a43cf183a62 126 */
dofydoink 0:607bc887b6e0 127
dofydoink 0:607bc887b6e0 128 int ThreadID[N_CHANNELS];
dofydoink 0:607bc887b6e0 129
WD40andTape 1:2a43cf183a62 130 bool isDataReady[N_CHANNELS]; // flag to indicate path data is ready for transmission to low level.
dofydoink 0:607bc887b6e0 131
dofydoink 0:607bc887b6e0 132 unsigned int ReadADCPosition(int channel)
dofydoink 0:607bc887b6e0 133 {
dofydoink 0:607bc887b6e0 134 unsigned int outputA;
dofydoink 0:607bc887b6e0 135 unsigned int outputB;
dofydoink 0:607bc887b6e0 136 unsigned int output;
dofydoink 0:607bc887b6e0 137
dofydoink 0:607bc887b6e0 138 spi.format(8,0);
dofydoink 0:607bc887b6e0 139 spi.frequency(1000000);
dofydoink 0:607bc887b6e0 140
dofydoink 0:607bc887b6e0 141 cs_ADC[channel] = 0;
dofydoink 0:607bc887b6e0 142 spi.write(PREAMBLE);
dofydoink 0:607bc887b6e0 143 outputA = spi.write(CHAN_3);
dofydoink 0:607bc887b6e0 144 outputB = spi.write(0xFF);
WD40andTape 1:2a43cf183a62 145 cs_ADC[channel]= 1;
dofydoink 0:607bc887b6e0 146
dofydoink 0:607bc887b6e0 147 outputA = outputA & DATA_MASK;
dofydoink 0:607bc887b6e0 148 outputA = outputA<<8;
dofydoink 0:607bc887b6e0 149 output = (outputA | outputB);
dofydoink 0:607bc887b6e0 150
dofydoink 0:607bc887b6e0 151 return output;
dofydoink 0:607bc887b6e0 152 }
dofydoink 0:607bc887b6e0 153
dofydoink 0:607bc887b6e0 154 unsigned int ReadADCPressure(int channel)
dofydoink 0:607bc887b6e0 155 {
dofydoink 0:607bc887b6e0 156 unsigned int outputA;
dofydoink 0:607bc887b6e0 157 unsigned int outputB;
dofydoink 0:607bc887b6e0 158 unsigned int output;
dofydoink 0:607bc887b6e0 159
dofydoink 0:607bc887b6e0 160 spi.format(8,0);
dofydoink 0:607bc887b6e0 161 spi.frequency(1000000);
dofydoink 0:607bc887b6e0 162
dofydoink 0:607bc887b6e0 163 cs_ADC[channel] = 0;
dofydoink 0:607bc887b6e0 164 spi.write(PREAMBLE);
dofydoink 0:607bc887b6e0 165 outputA = spi.write(CHAN_1);
dofydoink 0:607bc887b6e0 166 outputB = spi.write(0xFF);
dofydoink 0:607bc887b6e0 167 cs_ADC[channel] = 1;
dofydoink 0:607bc887b6e0 168
dofydoink 0:607bc887b6e0 169 outputA = outputA & DATA_MASK;
dofydoink 0:607bc887b6e0 170 outputA = outputA<<8;
dofydoink 0:607bc887b6e0 171 output = (outputA | outputB);
dofydoink 0:607bc887b6e0 172
dofydoink 0:607bc887b6e0 173 return output;
dofydoink 0:607bc887b6e0 174 }
dofydoink 0:607bc887b6e0 175
WD40andTape 1:2a43cf183a62 176 void SendReceiveData(int channel)
dofydoink 0:607bc887b6e0 177 {
dofydoink 0:607bc887b6e0 178 //get data from controller
dofydoink 0:607bc887b6e0 179 spi.format(16,2);
dofydoink 0:607bc887b6e0 180 spi.frequency(LOW_LEVEL_SPI_FREQUENCY);
dofydoink 0:607bc887b6e0 181
dofydoink 0:607bc887b6e0 182 cs_LL[channel] = 0;//select relevant chip
WD40andTape 1:2a43cf183a62 183 intPosSPI_Rx[channel] = spi.write(intDemandPos_Tx[channel]); //transmit & receive
dofydoink 0:607bc887b6e0 184 cs_LL[channel] = 1;//deselect chip
WD40andTape 1:2a43cf183a62 185 isDataReady[channel] = 0;//data no longer ready, i.e. we now require new data
WD40andTape 1:2a43cf183a62 186
WD40andTape 1:2a43cf183a62 187 dblPressure_bar[channel] = ReadADCPressure(channel);
WD40andTape 1:2a43cf183a62 188 dblPosition_mtrs[channel] = ReadADCPosition(channel);
dofydoink 0:607bc887b6e0 189
dofydoink 0:607bc887b6e0 190 //sort out received data
dofydoink 0:607bc887b6e0 191 chrErrorFlag[channel] = intPosSPI_Rx[channel]>>13;
dofydoink 0:607bc887b6e0 192 intPosSPI_Rx[channel] = intPosSPI_Rx[channel] & 0x1FFF;
WD40andTape 1:2a43cf183a62 193 dblPosition_mtrs[channel] = (double)intPosSPI_Rx[channel]/8191*(MAX_ACTUATOR_LENGTH/dblActuatorConversion[channel])/1000;
dofydoink 0:607bc887b6e0 194 }
dofydoink 0:607bc887b6e0 195
dofydoink 0:607bc887b6e0 196 //common rise handler function
dofydoink 0:607bc887b6e0 197
dofydoink 0:607bc887b6e0 198 void common_rise_handler(int channel)
dofydoink 0:607bc887b6e0 199 {
dofydoink 0:607bc887b6e0 200 //check if data is ready for tranmission
WD40andTape 1:2a43cf183a62 201 if (isDataReady[channel])
dofydoink 0:607bc887b6e0 202 {
dofydoink 0:607bc887b6e0 203 // Add transmit task to event queue
WD40andTape 1:2a43cf183a62 204 ThreadID[channel] = queue.call(SendReceiveData,channel);//schedule transmission
dofydoink 0:607bc887b6e0 205 }
dofydoink 0:607bc887b6e0 206 }
dofydoink 0:607bc887b6e0 207
dofydoink 0:607bc887b6e0 208
dofydoink 0:607bc887b6e0 209
dofydoink 0:607bc887b6e0 210 //common_fall handler functions
dofydoink 0:607bc887b6e0 211 void common_fall_handler(int channel)
dofydoink 0:607bc887b6e0 212 {
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 1:2a43cf183a62 239 semPathPlan.release(); // Uses threadReplan which is below normal priority to ensure consistent transmission to LL
dofydoink 0:607bc887b6e0 240 }
dofydoink 0:607bc887b6e0 241
dofydoink 0:607bc887b6e0 242 //this function will be called when a new transmission is received from high level
dofydoink 0:607bc887b6e0 243 void ReplanPath()
dofydoink 0:607bc887b6e0 244 {
dofydoink 0:607bc887b6e0 245 //while(1)
dofydoink 0:607bc887b6e0 246 //{
dofydoink 0:607bc887b6e0 247 //semReplan.wait();//wait until called
dofydoink 0:607bc887b6e0 248 //printf("replan!\r\n");
WD40andTape 1:2a43cf183a62 249 //for (ii = 0; ii < N_CHANNELS; ii++)
WD40andTape 1:2a43cf183a62 250 // {
WD40andTape 1:2a43cf183a62 251 // mutChannel[ii].lock();
WD40andTape 1:2a43cf183a62 252 // }
WD40andTape 1:2a43cf183a62 253
WD40andTape 1:2a43cf183a62 254 mutPsi.lock();// lock mutex for PSI to ensure no conflict when receiving new messages while already replanning
dofydoink 0:607bc887b6e0 255
dofydoink 0:607bc887b6e0 256 //update front segment
dofydoink 0:607bc887b6e0 257 dblTargetChambLen_mm[0] = dblPSI[0][0]*1000;
dofydoink 0:607bc887b6e0 258 dblTargetChambLen_mm[1] = dblPSI[0][1]*1000;
dofydoink 0:607bc887b6e0 259 dblTargetChambLen_mm[2] = dblPSI[0][2]*1000;
dofydoink 0:607bc887b6e0 260 //update mid segment
dofydoink 0:607bc887b6e0 261 dblTargetChambLen_mm[6] = dblPSI[1][0]*1000;
dofydoink 0:607bc887b6e0 262 dblTargetChambLen_mm[7] = dblTargetChambLen_mm[6]; //same because two pumps are used
dofydoink 0:607bc887b6e0 263 //update rear segment
dofydoink 0:607bc887b6e0 264 dblTargetChambLen_mm[3] = dblPSI[2][0]*1000;
dofydoink 0:607bc887b6e0 265 dblTargetChambLen_mm[4] = dblPSI[2][1]*1000;
dofydoink 0:607bc887b6e0 266 dblTargetChambLen_mm[5] = dblPSI[2][2]*1000;
dofydoink 0:607bc887b6e0 267
WD40andTape 1:2a43cf183a62 268 mutPsi.unlock();// unlock mutex for PSI to ensure no conflict when receiving new messages while already replanning
WD40andTape 1:2a43cf183a62 269
WD40andTape 1:2a43cf183a62 270 // for (ii = 0; ii < N_CHANNELS; ii++)
WD40andTape 1:2a43cf183a62 271 // {
WD40andTape 1:2a43cf183a62 272 // mutChannel[ii].unlock();
WD40andTape 1:2a43cf183a62 273 // }
dofydoink 0:607bc887b6e0 274
dofydoink 0:607bc887b6e0 275 for (ii = 0; ii< N_CHANNELS; ii++)
dofydoink 0:607bc887b6e0 276 {
WD40andTape 1:2a43cf183a62 277 mutChannel[ii].lock();//lock variables to avoid race condition
dofydoink 0:607bc887b6e0 278
dofydoink 0:607bc887b6e0 279 //check to see if positions are achievable
dofydoink 0:607bc887b6e0 280 if(dblTargetChambLen_mm[ii]>dblMaxChamberLengths_mm[ii])
dofydoink 0:607bc887b6e0 281 {
dofydoink 0:607bc887b6e0 282 dblTargetChambLen_mm[ii] = dblMaxChamberLengths_mm[ii];
dofydoink 0:607bc887b6e0 283 }
dofydoink 0:607bc887b6e0 284
dofydoink 0:607bc887b6e0 285 if(dblTargetChambLen_mm[ii]<0.0)
dofydoink 0:607bc887b6e0 286 {
dofydoink 0:607bc887b6e0 287 dblTargetChambLen_mm[ii] = 0.0;
dofydoink 0:607bc887b6e0 288 }
dofydoink 0:607bc887b6e0 289
dofydoink 0:607bc887b6e0 290 dblTargetActLen_mm[ii] = dblTargetChambLen_mm[ii]*dblActuatorConversion[ii];
dofydoink 0:607bc887b6e0 291
dofydoink 0:607bc887b6e0 292 //work out new velocities
dofydoink 0:607bc887b6e0 293 dblVelocity_mmps[ii] = (dblTargetActLen_mm[ii] - dblLinearPath_mm[ii]) / dblTargetTime_s;
dofydoink 0:607bc887b6e0 294
dofydoink 0:607bc887b6e0 295 //check to see if velocities are achievable
dofydoink 0:607bc887b6e0 296 if(abs(dblVelocity_mmps[ii]) > MAX_SPEED_MMPS)
dofydoink 0:607bc887b6e0 297 {
dofydoink 0:607bc887b6e0 298 if(dblVelocity_mmps[ii]>0)
dofydoink 0:607bc887b6e0 299 {
dofydoink 0:607bc887b6e0 300 dblVelocity_mmps[ii] = MAX_SPEED_MMPS;
dofydoink 0:607bc887b6e0 301 }
dofydoink 0:607bc887b6e0 302 else
dofydoink 0:607bc887b6e0 303 {
dofydoink 0:607bc887b6e0 304 dblVelocity_mmps[ii] = -1*MAX_SPEED_MMPS;
dofydoink 0:607bc887b6e0 305 }
dofydoink 0:607bc887b6e0 306 }
dofydoink 0:607bc887b6e0 307
WD40andTape 1:2a43cf183a62 308 mutChannel[ii].unlock(); //unlock mutex.
dofydoink 0:607bc887b6e0 309 }
dofydoink 0:607bc887b6e0 310 //}
dofydoink 0:607bc887b6e0 311
dofydoink 0:607bc887b6e0 312
dofydoink 0:607bc887b6e0 313 }
dofydoink 0:607bc887b6e0 314
WD40andTape 1:2a43cf183a62 315 void CalculateSmoothPath()
dofydoink 0:607bc887b6e0 316 {
WD40andTape 1:2a43cf183a62 317 double dblMeasuredSampleTime;
dofydoink 0:607bc887b6e0 318 while(1)
dofydoink 0:607bc887b6e0 319 {
dofydoink 0:607bc887b6e0 320 semPathPlan.wait();
dofydoink 0:607bc887b6e0 321 //if(blnReplan)
dofydoink 0:607bc887b6e0 322 // {
dofydoink 0:607bc887b6e0 323 // blnReplan = 0;//remove flag
dofydoink 0:607bc887b6e0 324 // ReplanPath(dblPSI, dblTargetTime_s);
dofydoink 0:607bc887b6e0 325 // }
WD40andTape 1:2a43cf183a62 326
WD40andTape 1:2a43cf183a62 327 // If run time is more than 50 us from expected, calculate from measured time step
WD40andTape 1:2a43cf183a62 328 if (fabs(PATH_SAMPLE_TIME_S*1000000 - timer.read_us()) > 50)
WD40andTape 1:2a43cf183a62 329 {
WD40andTape 1:2a43cf183a62 330 dblMeasuredSampleTime = timer.read();
WD40andTape 1:2a43cf183a62 331 }
WD40andTape 1:2a43cf183a62 332 else
WD40andTape 1:2a43cf183a62 333 {
WD40andTape 1:2a43cf183a62 334 dblMeasuredSampleTime = PATH_SAMPLE_TIME_S;
WD40andTape 1:2a43cf183a62 335 }
WD40andTape 1:2a43cf183a62 336 timer.reset();
WD40andTape 1:2a43cf183a62 337
dofydoink 0:607bc887b6e0 338 for(ii = 0; ii < N_CHANNELS; ii++)
dofydoink 0:607bc887b6e0 339 {
dofydoink 0:607bc887b6e0 340 //calculate next step in linear path
WD40andTape 1:2a43cf183a62 341 mutChannel[ii].lock();//lock relevant mutex
WD40andTape 1:2a43cf183a62 342 dblLinearPath_mm[ii] = dblLinearPath_mm[ii] + dblVelocity_mmps[ii]*dblMeasuredSampleTime; // PATH_SAMPLE_TIME_S SHOULD BE MEASURED
WD40andTape 1:2a43cf183a62 343
dofydoink 0:607bc887b6e0 344 //check tolerance
WD40andTape 1:2a43cf183a62 345 if (fabs(dblLinearPath_mm[ii] - dblTargetActLen_mm[ii]) <= dblPathTolerance)
dofydoink 0:607bc887b6e0 346 {
dofydoink 0:607bc887b6e0 347 dblVelocity_mmps[ii] = 0; //stop linear path generation when linear path is within tolerance of target position.
dofydoink 0:607bc887b6e0 348 }
WD40andTape 1:2a43cf183a62 349 mutChannel[ii].unlock();//unlock relevant mutex
dofydoink 0:607bc887b6e0 350
dofydoink 0:607bc887b6e0 351 //calculate next step in smooth path
dofydoink 0:607bc887b6e0 352 dblSmoothPath_mm[ii] = dblSmoothingFactor*dblLinearPath_mm[ii] + (1.0-dblSmoothingFactor)*dblSmoothPath_mm[ii];
dofydoink 0:607bc887b6e0 353
dofydoink 0:607bc887b6e0 354 //convert to actuator distances
dofydoink 0:607bc887b6e0 355 dblPathToActuator[ii] = dblSmoothPath_mm[ii];
dofydoink 0:607bc887b6e0 356
WD40andTape 1:2a43cf183a62 357 intDemandPos_Tx[ii] = (int) (dblPathToActuator[ii]/MAX_ACTUATOR_LENGTH)*8191;//convert to a 13-bit number;
WD40andTape 1:2a43cf183a62 358 intDemandPos_Tx[ii] = intDemandPos_Tx[ii] & 0x1FFF; //ensure number is 13-bit
dofydoink 0:607bc887b6e0 359
dofydoink 0:607bc887b6e0 360
WD40andTape 1:2a43cf183a62 361 isDataReady[ii] = 1;//signal that data ready
dofydoink 0:607bc887b6e0 362
dofydoink 0:607bc887b6e0 363 }
WD40andTape 1:2a43cf183a62 364
WD40andTape 1:2a43cf183a62 365 //printf("%d, %f,%f,%f, %f\r\n",timer.read_ms(), dblTargetActLen_mm[0] ,dblVelocity_mmps[0], dblLinearPath_mm[0], dblSmoothPath_mm[0]);
dofydoink 0:607bc887b6e0 366 }
dofydoink 0:607bc887b6e0 367 }
dofydoink 0:607bc887b6e0 368
WD40andTape 1:2a43cf183a62 369 void SimulateDemand() // For testing purposes
dofydoink 0:607bc887b6e0 370 {
WD40andTape 1:2a43cf183a62 371 kk = 0;
dofydoink 0:607bc887b6e0 372 while(1)
dofydoink 0:607bc887b6e0 373 {
WD40andTape 1:2a43cf183a62 374 mutChannel[0].lock();
dofydoink 0:607bc887b6e0 375 if(kk == 0)
dofydoink 0:607bc887b6e0 376 {
dofydoink 0:607bc887b6e0 377 dblPSI[0][0] = (double) 10.0;
dofydoink 0:607bc887b6e0 378 dblTargetTime_s = 1.0;
dofydoink 0:607bc887b6e0 379 }
dofydoink 0:607bc887b6e0 380 else
dofydoink 0:607bc887b6e0 381 {
dofydoink 0:607bc887b6e0 382 dblPSI[0][0] = (double) 0.0;
dofydoink 0:607bc887b6e0 383 dblTargetTime_s = 2.0;
dofydoink 0:607bc887b6e0 384 }
dofydoink 0:607bc887b6e0 385
dofydoink 0:607bc887b6e0 386 kk = 1 - kk;
dofydoink 0:607bc887b6e0 387
dofydoink 0:607bc887b6e0 388
dofydoink 0:607bc887b6e0 389 //semReplan.release();
dofydoink 0:607bc887b6e0 390
WD40andTape 1:2a43cf183a62 391 mutChannel[0].unlock();
dofydoink 0:607bc887b6e0 392 ReplanPath();
dofydoink 0:607bc887b6e0 393
dofydoink 0:607bc887b6e0 394 Thread::wait(7000);
dofydoink 0:607bc887b6e0 395 }
dofydoink 0:607bc887b6e0 396 }
dofydoink 0:607bc887b6e0 397
dofydoink 0:607bc887b6e0 398
dofydoink 0:607bc887b6e0 399
dofydoink 0:607bc887b6e0 400 Ticker PathCalculationTicker;
dofydoink 0:607bc887b6e0 401
dofydoink 0:607bc887b6e0 402 int main()
dofydoink 0:607bc887b6e0 403 {
dofydoink 0:607bc887b6e0 404 //initialise relevant variables
dofydoink 0:607bc887b6e0 405 for(ii = 0; ii<N_CHANNELS; ii++)
dofydoink 0:607bc887b6e0 406 {
dofydoink 0:607bc887b6e0 407 //all chip selects in off state
dofydoink 0:607bc887b6e0 408 cs_LL[ii] = 1;
dofydoink 0:607bc887b6e0 409 cs_ADC[ii] = 1;
dofydoink 0:607bc887b6e0 410
dofydoink 0:607bc887b6e0 411 //data ready flags set to not ready
WD40andTape 1:2a43cf183a62 412 isDataReady[ii] = 0;
dofydoink 0:607bc887b6e0 413 }
dofydoink 0:607bc887b6e0 414
dofydoink 0:607bc887b6e0 415 //calculate some control variables
WD40andTape 1:2a43cf183a62 416 dblPathTolerance = 0.1;//MAX_SPEED_MMPS * PATH_SAMPLE_TIME_S * 1.05; //path tolerance in mm.
dofydoink 0:607bc887b6e0 417
dofydoink 0:607bc887b6e0 418 pinReset = 1; //initialise reset pin to not reset the controllers.
dofydoink 0:607bc887b6e0 419
dofydoink 0:607bc887b6e0 420 //say something nice to the user.
dofydoink 0:607bc887b6e0 421 pc.baud(9600);
dofydoink 0:607bc887b6e0 422 printf("Hi, there! I'll be your mid-level controller for today.\r\n");
dofydoink 0:607bc887b6e0 423
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
dofydoink 0:607bc887b6e0 430 pinGate[0].rise(&rise0);
dofydoink 0:607bc887b6e0 431 pinGate[1].rise(&rise1);
dofydoink 0:607bc887b6e0 432 pinGate[2].rise(&rise2);
dofydoink 0:607bc887b6e0 433 pinGate[3].rise(&rise3);
dofydoink 0:607bc887b6e0 434 pinGate[4].rise(&rise4);
dofydoink 0:607bc887b6e0 435 pinGate[5].rise(&rise5);
dofydoink 0:607bc887b6e0 436 pinGate[6].rise(&rise6);
dofydoink 0:607bc887b6e0 437 pinGate[7].rise(&rise7);
dofydoink 0:607bc887b6e0 438
dofydoink 0:607bc887b6e0 439 //set up fall interrupts MIGHT NOT NEED TO BE POINTERS
dofydoink 0:607bc887b6e0 440 pinGate[0].fall(&fall0);
dofydoink 0:607bc887b6e0 441 pinGate[1].fall(&fall1);
dofydoink 0:607bc887b6e0 442 pinGate[2].fall(&fall2);
dofydoink 0:607bc887b6e0 443 pinGate[3].fall(&fall3);
dofydoink 0:607bc887b6e0 444 pinGate[4].fall(&fall4);
dofydoink 0:607bc887b6e0 445 pinGate[5].fall(&fall5);
dofydoink 0:607bc887b6e0 446 pinGate[6].fall(&fall6);
dofydoink 0:607bc887b6e0 447 pinGate[7].fall(&fall7);
dofydoink 0:607bc887b6e0 448
dofydoink 0:607bc887b6e0 449 timer.start();
dofydoink 0:607bc887b6e0 450
dofydoink 0:607bc887b6e0 451 threadSimulateDemand.start(SimulateDemand);
WD40andTape 1:2a43cf183a62 452 threadPathPlan.start(CalculateSmoothPath); //start planning thread
WD40andTape 1:2a43cf183a62 453
dofydoink 0:607bc887b6e0 454 PathCalculationTicker.attach(&startPathPlan, PATH_SAMPLE_TIME_S); //set up planning thread to recur at fixed intervals
WD40andTape 1:2a43cf183a62 455
dofydoink 0:607bc887b6e0 456 threadReplan.start(ReplanPath);//start Replanning thread
dofydoink 0:607bc887b6e0 457 Thread::wait(1);
dofydoink 0:607bc887b6e0 458
dofydoink 0:607bc887b6e0 459
WD40andTape 1:2a43cf183a62 460 while(1) {
WD40andTape 1:2a43cf183a62 461 Thread::wait(osWaitForever);
dofydoink 0:607bc887b6e0 462 }
dofydoink 0:607bc887b6e0 463 }
dofydoink 0:607bc887b6e0 464