Mid level control code

Dependencies:   ros_lib_kinetic

Committer:
WD40andTape
Date:
Tue Jul 31 10:44:10 2018 +0000
Revision:
2:eea12b149dba
Parent:
1:2a43cf183a62
Child:
3:c83291bf9fd2
Changes prior to incorporating HL/ML comms.

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