Example software of using the mbed-rtos to control a simple vehicle's on board computer
Dependencies: MCP23017 WattBob_TextLCD mbed-rtos mbed
main.cpp@9:c236eaaacf08, 2016-03-30 (annotated)
- Committer:
- sk398
- Date:
- Wed Mar 30 13:10:09 2016 +0000
- Revision:
- 9:c236eaaacf08
- Parent:
- 8:6fad4bd89240
All Tasks operational. All Code Commented.; ; Final Submission Revision;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sk398 | 7:f09208f9a4f7 | 1 | /* ##################################################################### |
sk398 | 7:f09208f9a4f7 | 2 | main.cpp |
sk398 | 7:f09208f9a4f7 | 3 | --------- |
sk398 | 7:f09208f9a4f7 | 4 | |
sk398 | 7:f09208f9a4f7 | 5 | Embedded Software - Assignment 3 |
sk398 | 7:f09208f9a4f7 | 6 | -------------------------------- |
sk398 | 7:f09208f9a4f7 | 7 | |
sk398 | 7:f09208f9a4f7 | 8 | Written by: Steven Kay |
sk398 | 7:f09208f9a4f7 | 9 | |
sk398 | 7:f09208f9a4f7 | 10 | Date: March 2016 |
sk398 | 7:f09208f9a4f7 | 11 | |
sk398 | 9:c236eaaacf08 | 12 | Function: This code operates to simulate the operation of a Car's |
sk398 | 9:c236eaaacf08 | 13 | control system. It does so by taking external input for |
sk398 | 9:c236eaaacf08 | 14 | elements of a Car; Light Indicators, Engine State and Pedal values |
sk398 | 9:c236eaaacf08 | 15 | and using a simple Car Simulation model, derives a speed |
sk398 | 9:c236eaaacf08 | 16 | from which several tasks are included to act upon. |
sk398 | 9:c236eaaacf08 | 17 | An average speed is generated at a given frequency |
sk398 | 9:c236eaaacf08 | 18 | and a total distance is estimated using this average speed. |
sk398 | 9:c236eaaacf08 | 19 | Output comes in the form of LED's when specific indicators |
sk398 | 9:c236eaaacf08 | 20 | are true, and on a LCD screen and Servo Wiper to indicate speed. |
sk398 | 9:c236eaaacf08 | 21 | Furthermore, a PC Connection is established and a data dump of |
sk398 | 9:c236eaaacf08 | 22 | current Accelerometer, Brake and Average speed is presented |
sk398 | 9:c236eaaacf08 | 23 | to the user every 20 seconds. |
sk398 | 9:c236eaaacf08 | 24 | |
sk398 | 9:c236eaaacf08 | 25 | This system is constructed using the MBED-RTOS and |
sk398 | 9:c236eaaacf08 | 26 | as such, each Task has an associated frequency, found in main, below. |
sk398 | 9:c236eaaacf08 | 27 | Note that no priority is given to the tasks and no |
sk398 | 9:c236eaaacf08 | 28 | extra scheduler controls the synchronisation of tasks, |
sk398 | 7:f09208f9a4f7 | 29 | |
sk398 | 7:f09208f9a4f7 | 30 | ##################################################################### */ |
sk398 | 7:f09208f9a4f7 | 31 | |
sk398 | 0:f7d6ed1dfe3e | 32 | #include "mbed.h" |
sk398 | 0:f7d6ed1dfe3e | 33 | #include "rtos.h" |
sk398 | 4:b4bcb329a930 | 34 | #include "MCP23017.h" |
sk398 | 4:b4bcb329a930 | 35 | #include "WattBob_TextLCD.h" |
sk398 | 4:b4bcb329a930 | 36 | |
sk398 | 7:f09208f9a4f7 | 37 | // ============================================================================ |
sk398 | 7:f09208f9a4f7 | 38 | // Define Statements |
sk398 | 7:f09208f9a4f7 | 39 | // ============================================================================ |
sk398 | 8:6fad4bd89240 | 40 | |
sk398 | 8:6fad4bd89240 | 41 | // LCD Definitions |
sk398 | 4:b4bcb329a930 | 42 | #define BACK_LIGHT_ON(INTERFACE) INTERFACE->write_bit(1,BL_BIT) |
sk398 | 4:b4bcb329a930 | 43 | #define BACK_LIGHT_OFF(INTERFACE) INTERFACE->write_bit(0,BL_BIT) |
sk398 | 4:b4bcb329a930 | 44 | |
sk398 | 8:6fad4bd89240 | 45 | // General Logical Assignments |
sk398 | 2:13a9394ba2e0 | 46 | #define HIGH 1 |
sk398 | 2:13a9394ba2e0 | 47 | #define LOW 0 |
sk398 | 2:13a9394ba2e0 | 48 | |
sk398 | 8:6fad4bd89240 | 49 | // Car Sim, Maximum Car Speed (mph) |
sk398 | 8:6fad4bd89240 | 50 | #define MAX_SPEED 100 |
sk398 | 8:6fad4bd89240 | 51 | |
sk398 | 2:13a9394ba2e0 | 52 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 53 | // MBED Pin Assignments |
sk398 | 2:13a9394ba2e0 | 54 | // ============================================================================ |
sk398 | 7:f09208f9a4f7 | 55 | |
sk398 | 7:f09208f9a4f7 | 56 | // System Inputs |
sk398 | 8:6fad4bd89240 | 57 | // ---------------------------------------------------------------------------- |
sk398 | 8:6fad4bd89240 | 58 | |
sk398 | 8:6fad4bd89240 | 59 | // Analog Channels |
sk398 | 7:f09208f9a4f7 | 60 | AnalogIn Brake(p19); // Brake Pedal |
sk398 | 7:f09208f9a4f7 | 61 | AnalogIn Accelerometer(p20); // Accelerator Pedal |
sk398 | 0:f7d6ed1dfe3e | 62 | |
sk398 | 8:6fad4bd89240 | 63 | // Digitial Channels |
sk398 | 7:f09208f9a4f7 | 64 | DigitalIn EngineState(p18); // Engine State Switch |
sk398 | 7:f09208f9a4f7 | 65 | DigitalIn LeftIndicator(p17); // Left Indicator Switch |
sk398 | 7:f09208f9a4f7 | 66 | DigitalIn RightIndicator(p16); // Right Indicator Switch |
sk398 | 7:f09208f9a4f7 | 67 | DigitalIn SideLightIndicator(p15); // Side Light Indicator |
sk398 | 7:f09208f9a4f7 | 68 | |
sk398 | 1:cdf851858518 | 69 | |
sk398 | 7:f09208f9a4f7 | 70 | // System Outputs |
sk398 | 8:6fad4bd89240 | 71 | // ---------------------------------------------------------------------------- |
sk398 | 8:6fad4bd89240 | 72 | |
sk398 | 8:6fad4bd89240 | 73 | // LED Indicators (Steady State) |
sk398 | 7:f09208f9a4f7 | 74 | DigitalOut EngineStateInd(LED1); // Engine State LED |
sk398 | 7:f09208f9a4f7 | 75 | DigitalOut SideLightInd(LED2); // Side Light LED |
sk398 | 1:cdf851858518 | 76 | |
sk398 | 8:6fad4bd89240 | 77 | // LED Indicators (Flashing) |
sk398 | 7:f09208f9a4f7 | 78 | PwmOut LeftLightInd(LED3); // Left Indicator LED |
sk398 | 7:f09208f9a4f7 | 79 | PwmOut RightLightInd(LED4); // Right Indicator LED |
sk398 | 7:f09208f9a4f7 | 80 | PwmOut OverSpeedInd(p22); // OverSpeed LED |
sk398 | 2:13a9394ba2e0 | 81 | |
sk398 | 8:6fad4bd89240 | 82 | // Servo Output |
sk398 | 7:f09208f9a4f7 | 83 | PwmOut AvSpeedWiper(p21); // Average Speed Wiper |
sk398 | 2:13a9394ba2e0 | 84 | |
sk398 | 8:6fad4bd89240 | 85 | // USB Connection to PC |
sk398 | 7:f09208f9a4f7 | 86 | Serial PCConn(USBTX,USBRX); // Connection to PC |
sk398 | 4:b4bcb329a930 | 87 | |
sk398 | 8:6fad4bd89240 | 88 | // LCD Objects |
sk398 | 7:f09208f9a4f7 | 89 | MCP23017 *par_port; // Object pointing to Expander |
sk398 | 7:f09208f9a4f7 | 90 | WattBob_TextLCD *lcd; // LCD Connection |
sk398 | 4:b4bcb329a930 | 91 | |
sk398 | 2:13a9394ba2e0 | 92 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 93 | // Global Data Structure Declerations |
sk398 | 2:13a9394ba2e0 | 94 | // ============================================================================ |
sk398 | 7:f09208f9a4f7 | 95 | |
sk398 | 8:6fad4bd89240 | 96 | // Raw Data Structure |
sk398 | 8:6fad4bd89240 | 97 | // ---------------------------------------------------------------------------- |
sk398 | 9:c236eaaacf08 | 98 | |
sk398 | 9:c236eaaacf08 | 99 | // CarRawData is a global memory area and contaims an instance of the Raw data |
sk398 | 9:c236eaaacf08 | 100 | // populated by Task1 and can be accessed through locking Mutex - rawDataMutex |
sk398 | 2:13a9394ba2e0 | 101 | typedef struct |
sk398 | 2:13a9394ba2e0 | 102 | { |
sk398 | 2:13a9394ba2e0 | 103 | bool EngineState; |
sk398 | 2:13a9394ba2e0 | 104 | float RawAccelerometer; |
sk398 | 2:13a9394ba2e0 | 105 | float RawBraking; |
sk398 | 8:6fad4bd89240 | 106 | } CarRawData; |
sk398 | 2:13a9394ba2e0 | 107 | |
sk398 | 9:c236eaaacf08 | 108 | // Create Mutex to control access to CarRawData instance |
sk398 | 8:6fad4bd89240 | 109 | Mutex rawDataMutex; |
sk398 | 9:c236eaaacf08 | 110 | |
sk398 | 9:c236eaaacf08 | 111 | // Create Instance of CarRawData |
sk398 | 8:6fad4bd89240 | 112 | CarRawData rawData; |
sk398 | 2:13a9394ba2e0 | 113 | |
sk398 | 8:6fad4bd89240 | 114 | // Speed Data Structure |
sk398 | 8:6fad4bd89240 | 115 | // ---------------------------------------------------------------------------- |
sk398 | 9:c236eaaacf08 | 116 | |
sk398 | 9:c236eaaacf08 | 117 | // CarSpeedData is a global memory area and contains an instance of the calculated |
sk398 | 9:c236eaaacf08 | 118 | // raw speed values and the index to the next available element in the array to be |
sk398 | 9:c236eaaacf08 | 119 | // written to. rawSpeed is calculated by the CarSim and can be accessed through |
sk398 | 9:c236eaaacf08 | 120 | // locking Mutex - SpeedMutex |
sk398 | 2:13a9394ba2e0 | 121 | typedef struct |
sk398 | 2:13a9394ba2e0 | 122 | { |
sk398 | 5:4f2a072ed289 | 123 | float rawSpeed[3]; |
sk398 | 5:4f2a072ed289 | 124 | int counter; |
sk398 | 8:6fad4bd89240 | 125 | } CarSpeedData; |
sk398 | 4:b4bcb329a930 | 126 | |
sk398 | 9:c236eaaacf08 | 127 | // Create Mutex to control access to CarSpeedData instance |
sk398 | 9:c236eaaacf08 | 128 | Mutex SpeedMutex; |
sk398 | 8:6fad4bd89240 | 129 | |
sk398 | 9:c236eaaacf08 | 130 | // Create instance of CarSpeedData |
sk398 | 8:6fad4bd89240 | 131 | CarSpeedData speedData; |
sk398 | 2:13a9394ba2e0 | 132 | |
sk398 | 8:6fad4bd89240 | 133 | // Filtered Data Structure |
sk398 | 8:6fad4bd89240 | 134 | // ---------------------------------------------------------------------------- |
sk398 | 2:13a9394ba2e0 | 135 | |
sk398 | 9:c236eaaacf08 | 136 | float AverageSpeed; |
sk398 | 9:c236eaaacf08 | 137 | float totalDistance; |
sk398 | 2:13a9394ba2e0 | 138 | |
sk398 | 9:c236eaaacf08 | 139 | // Create Mutex to control access to FilteredData |
sk398 | 9:c236eaaacf08 | 140 | Mutex filteredDataMutex; |
sk398 | 4:b4bcb329a930 | 141 | |
sk398 | 8:6fad4bd89240 | 142 | // Mail Queue Structure |
sk398 | 8:6fad4bd89240 | 143 | // ---------------------------------------------------------------------------- |
sk398 | 9:c236eaaacf08 | 144 | |
sk398 | 9:c236eaaacf08 | 145 | // PCDumpData is a global memory area which is populated by Taak7 and used as |
sk398 | 9:c236eaaacf08 | 146 | // the structure within a MailQueue. Data contained is a copy from the current |
sk398 | 9:c236eaaacf08 | 147 | // state of the Control System at a given instance of time. |
sk398 | 7:f09208f9a4f7 | 148 | typedef struct |
sk398 | 7:f09208f9a4f7 | 149 | { |
sk398 | 7:f09208f9a4f7 | 150 | float currentAverageSpeed; |
sk398 | 7:f09208f9a4f7 | 151 | float currentAccelerometer; |
sk398 | 7:f09208f9a4f7 | 152 | float currentBraking; |
sk398 | 9:c236eaaacf08 | 153 | } PCDumpData; |
sk398 | 9:c236eaaacf08 | 154 | |
sk398 | 9:c236eaaacf08 | 155 | // Construct a 100 Element Mail Queue structure |
sk398 | 9:c236eaaacf08 | 156 | Mail<PCDumpData,100> Memory_Dump; |
sk398 | 7:f09208f9a4f7 | 157 | |
sk398 | 9:c236eaaacf08 | 158 | // Define a Counter to trakc number of entries to Mail Queue |
sk398 | 9:c236eaaacf08 | 159 | int MailQueueCounter; |
sk398 | 7:f09208f9a4f7 | 160 | |
sk398 | 9:c236eaaacf08 | 161 | // Create Mutex to control access to the MailQueueCounter variable |
sk398 | 7:f09208f9a4f7 | 162 | Mutex MailMutex; |
sk398 | 7:f09208f9a4f7 | 163 | |
sk398 | 8:6fad4bd89240 | 164 | |
sk398 | 2:13a9394ba2e0 | 165 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 166 | // Car Simulation |
sk398 | 2:13a9394ba2e0 | 167 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 168 | |
sk398 | 9:c236eaaacf08 | 169 | // The CarSimulator Task updates the rawSpeed parameter at a frequenct of 20Hz |
sk398 | 2:13a9394ba2e0 | 170 | void CarSimulator(void const *arg) |
sk398 | 2:13a9394ba2e0 | 171 | { |
sk398 | 5:4f2a072ed289 | 172 | float newSpeed; |
sk398 | 5:4f2a072ed289 | 173 | |
sk398 | 9:c236eaaacf08 | 174 | // Load Shared resources into local variables within the Task |
sk398 | 9:c236eaaacf08 | 175 | // Shared Resources are; Accelerometer value, Braking value and Engine State |
sk398 | 8:6fad4bd89240 | 176 | rawDataMutex.lock(); |
sk398 | 8:6fad4bd89240 | 177 | float currentAccelerometer = rawData.RawAccelerometer; |
sk398 | 8:6fad4bd89240 | 178 | float currentBrake = rawData.RawBraking; |
sk398 | 8:6fad4bd89240 | 179 | bool currentEngineState = rawData.EngineState; |
sk398 | 8:6fad4bd89240 | 180 | rawDataMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 181 | |
sk398 | 9:c236eaaacf08 | 182 | // Run simple model which estimates the speed, as a fraction of the MAX SPEED |
sk398 | 9:c236eaaacf08 | 183 | // based on the percentage of either accelerator or brake pressed by the user |
sk398 | 9:c236eaaacf08 | 184 | // Further, newSpeed is set to 0 if the currentEngineState is equal to 0 (Engine off) |
sk398 | 5:4f2a072ed289 | 185 | newSpeed = currentAccelerometer*MAX_SPEED*(1-currentBrake)*currentEngineState; |
sk398 | 2:13a9394ba2e0 | 186 | |
sk398 | 9:c236eaaacf08 | 187 | // Check Speed Counter's range, if out of bounds of array length, reset Counter |
sk398 | 9:c236eaaacf08 | 188 | // to 0 |
sk398 | 9:c236eaaacf08 | 189 | // Data contained within Shared Resource therefore the SpeedMutex is used to control access |
sk398 | 5:4f2a072ed289 | 190 | SpeedMutex.lock(); |
sk398 | 8:6fad4bd89240 | 191 | if(speedData.counter > 2) |
sk398 | 2:13a9394ba2e0 | 192 | { |
sk398 | 8:6fad4bd89240 | 193 | speedData.counter = 0; |
sk398 | 4:b4bcb329a930 | 194 | } |
sk398 | 4:b4bcb329a930 | 195 | |
sk398 | 9:c236eaaacf08 | 196 | // Output a rawSpeed value to the next available index of rawSpeed[] and increment Counter |
sk398 | 8:6fad4bd89240 | 197 | speedData.rawSpeed[speedData.counter] = newSpeed; |
sk398 | 9:c236eaaacf08 | 198 | speedData.counter = speedData.counter++; |
sk398 | 5:4f2a072ed289 | 199 | SpeedMutex.unlock(); |
sk398 | 2:13a9394ba2e0 | 200 | } |
sk398 | 2:13a9394ba2e0 | 201 | |
sk398 | 2:13a9394ba2e0 | 202 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 203 | // Control System Tasks |
sk398 | 2:13a9394ba2e0 | 204 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 205 | |
sk398 | 9:c236eaaacf08 | 206 | // Task1_ReadRawData gathers external inputs and updates the rawData structure |
sk398 | 9:c236eaaacf08 | 207 | // It operates at a frequency of 10Hz |
sk398 | 2:13a9394ba2e0 | 208 | void Task1_ReadRawData(void const *arg) |
sk398 | 2:13a9394ba2e0 | 209 | { |
sk398 | 9:c236eaaacf08 | 210 | // Lock Shared Resource - rawData |
sk398 | 9:c236eaaacf08 | 211 | // Update rawData elements directly from AnalogIn channel values |
sk398 | 9:c236eaaacf08 | 212 | // Unlock Shares Resource |
sk398 | 8:6fad4bd89240 | 213 | rawDataMutex.lock(); |
sk398 | 8:6fad4bd89240 | 214 | rawData.RawBraking = Brake.read(); |
sk398 | 8:6fad4bd89240 | 215 | rawData.RawAccelerometer = Accelerometer.read(); |
sk398 | 8:6fad4bd89240 | 216 | rawDataMutex.unlock(); |
sk398 | 2:13a9394ba2e0 | 217 | } |
sk398 | 2:13a9394ba2e0 | 218 | |
sk398 | 2:13a9394ba2e0 | 219 | |
sk398 | 9:c236eaaacf08 | 220 | // Task2_ReadEngineState updates the rawData structure and operates ar a frequency of 2Hz |
sk398 | 2:13a9394ba2e0 | 221 | void Task2_ReadEngineState(void const *arg) |
sk398 | 2:13a9394ba2e0 | 222 | { |
sk398 | 9:c236eaaacf08 | 223 | // Get external input from DigitalIn Channel and store in local variable |
sk398 | 4:b4bcb329a930 | 224 | bool currentEngineState = EngineState.read(); |
sk398 | 9:c236eaaacf08 | 225 | |
sk398 | 9:c236eaaacf08 | 226 | // Lock Shared Resource - rawData |
sk398 | 9:c236eaaacf08 | 227 | // Take a copy of the local variable currentEngineState and store into Global memory |
sk398 | 9:c236eaaacf08 | 228 | // Unlock Shared Resource |
sk398 | 8:6fad4bd89240 | 229 | rawDataMutex.lock(); |
sk398 | 8:6fad4bd89240 | 230 | rawData.EngineState = currentEngineState; |
sk398 | 8:6fad4bd89240 | 231 | rawDataMutex.unlock(); |
sk398 | 2:13a9394ba2e0 | 232 | |
sk398 | 9:c236eaaacf08 | 233 | // Conduct logical check on local varialbe currentEngineState |
sk398 | 9:c236eaaacf08 | 234 | // if currentEngineState is HIGH, set EngineStateInd to HIGH |
sk398 | 9:c236eaaacf08 | 235 | // else set EngineStateInd LOW |
sk398 | 2:13a9394ba2e0 | 236 | if(currentEngineState) |
sk398 | 2:13a9394ba2e0 | 237 | { |
sk398 | 2:13a9394ba2e0 | 238 | EngineStateInd = HIGH; |
sk398 | 2:13a9394ba2e0 | 239 | } |
sk398 | 2:13a9394ba2e0 | 240 | else |
sk398 | 2:13a9394ba2e0 | 241 | { |
sk398 | 2:13a9394ba2e0 | 242 | EngineStateInd = LOW; |
sk398 | 2:13a9394ba2e0 | 243 | } |
sk398 | 2:13a9394ba2e0 | 244 | } |
sk398 | 5:4f2a072ed289 | 245 | |
sk398 | 5:4f2a072ed289 | 246 | |
sk398 | 9:c236eaaacf08 | 247 | // Task3_CalcAvSpeed updates the AverageSpeed global varialbe and operates at a frequency of 5Hz |
sk398 | 4:b4bcb329a930 | 248 | void Task3_CalcAvSpeed(void const *arg) |
sk398 | 4:b4bcb329a930 | 249 | { |
sk398 | 9:c236eaaacf08 | 250 | // Initialise local variable as 0.0 |
sk398 | 4:b4bcb329a930 | 251 | float speedTotal = 0.0; |
sk398 | 5:4f2a072ed289 | 252 | |
sk398 | 9:c236eaaacf08 | 253 | // Lock Shared Resource - speedData |
sk398 | 9:c236eaaacf08 | 254 | // Calculate total from array of rawSpeed values and store locally |
sk398 | 9:c236eaaacf08 | 255 | // Unlock Shared Resource |
sk398 | 9:c236eaaacf08 | 256 | SpeedMutex.lock(); |
sk398 | 4:b4bcb329a930 | 257 | for(int num = 0; num < 3; num++) |
sk398 | 4:b4bcb329a930 | 258 | { |
sk398 | 8:6fad4bd89240 | 259 | speedTotal = speedTotal + speedData.rawSpeed[num]; |
sk398 | 4:b4bcb329a930 | 260 | } |
sk398 | 9:c236eaaacf08 | 261 | SpeedMutex.unlock(); |
sk398 | 2:13a9394ba2e0 | 262 | |
sk398 | 9:c236eaaacf08 | 263 | // Lock Shared Resource - AverageSpeed |
sk398 | 9:c236eaaacf08 | 264 | // Calculate average from local variable speedTotal and store result Globally into AverageSpeed |
sk398 | 9:c236eaaacf08 | 265 | // Unlock Shared Resource |
sk398 | 9:c236eaaacf08 | 266 | filteredDataMutex.lock(); |
sk398 | 9:c236eaaacf08 | 267 | AverageSpeed = (speedTotal/3); |
sk398 | 9:c236eaaacf08 | 268 | filteredDataMutex.unlock(); |
sk398 | 4:b4bcb329a930 | 269 | } |
sk398 | 4:b4bcb329a930 | 270 | |
sk398 | 5:4f2a072ed289 | 271 | |
sk398 | 9:c236eaaacf08 | 272 | // Task4_UpdateRCWiper takes the AverageSpeed global variable at a given time and outputs |
sk398 | 9:c236eaaacf08 | 273 | // a representation of this through a Servo. It operates at a frequenct of 1Hz |
sk398 | 4:b4bcb329a930 | 274 | void Task4_UpdateRCWiper(void const *arg) |
sk398 | 2:13a9394ba2e0 | 275 | { |
sk398 | 9:c236eaaacf08 | 276 | // Lock Shared Resource - AverageSpeed |
sk398 | 9:c236eaaacf08 | 277 | // Take local copy of AverageSpeed |
sk398 | 9:c236eaaacf08 | 278 | // Unlock Shared Resource |
sk398 | 9:c236eaaacf08 | 279 | filteredDataMutex.lock(); |
sk398 | 9:c236eaaacf08 | 280 | float currentAverageSpeed = AverageSpeed; |
sk398 | 9:c236eaaacf08 | 281 | filteredDataMutex.unlock(); |
sk398 | 2:13a9394ba2e0 | 282 | |
sk398 | 9:c236eaaacf08 | 283 | // Update Servo Position based upon the local copy of AverageSpeed |
sk398 | 9:c236eaaacf08 | 284 | |
sk398 | 9:c236eaaacf08 | 285 | // Servo must be controlled in the range of 1000us to 2000us |
sk398 | 9:c236eaaacf08 | 286 | // Thus a base value of 1000 is included, and as currentAverageSpeed cannot exceed 100, |
sk398 | 9:c236eaaacf08 | 287 | // This is simply scaled by 10, to give a maximum of 2000, which allows Servo to operate |
sk398 | 9:c236eaaacf08 | 288 | // Over full operational range |
sk398 | 5:4f2a072ed289 | 289 | AvSpeedWiper.pulsewidth_us(1000+(10*currentAverageSpeed)); |
sk398 | 2:13a9394ba2e0 | 290 | } |
sk398 | 2:13a9394ba2e0 | 291 | |
sk398 | 0:f7d6ed1dfe3e | 292 | |
sk398 | 9:c236eaaacf08 | 293 | // Task5_OverspeedLED takes the 0th Element of the rawSpeed global variable and computes |
sk398 | 9:c236eaaacf08 | 294 | // a logical assessment to detect when the speed is greater than a preset of 70mph and |
sk398 | 9:c236eaaacf08 | 295 | // indicate results through an LED. It operates at a frequency of 0.5Hz |
sk398 | 4:b4bcb329a930 | 296 | void Task5_OverspeedLED(void const *arg) |
sk398 | 0:f7d6ed1dfe3e | 297 | { |
sk398 | 9:c236eaaacf08 | 298 | // Lock Shared Resource - speedData |
sk398 | 9:c236eaaacf08 | 299 | // Take local copy of rawSpeed[0] |
sk398 | 9:c236eaaacf08 | 300 | // // Unlock Shares Resource |
sk398 | 5:4f2a072ed289 | 301 | SpeedMutex.lock(); |
sk398 | 8:6fad4bd89240 | 302 | float currentInstSpeed = speedData.rawSpeed[speedData.counter]; |
sk398 | 5:4f2a072ed289 | 303 | SpeedMutex.unlock(); |
sk398 | 4:b4bcb329a930 | 304 | |
sk398 | 9:c236eaaacf08 | 305 | // Using local copy of rawSpeed[0], if this is above preset threshold of 70, |
sk398 | 9:c236eaaacf08 | 306 | // OverSpeedInd is set HIGH, else it is set LOW |
sk398 | 4:b4bcb329a930 | 307 | if(currentInstSpeed > 70.0) |
sk398 | 4:b4bcb329a930 | 308 | { |
sk398 | 4:b4bcb329a930 | 309 | OverSpeedInd = HIGH; |
sk398 | 1:cdf851858518 | 310 | } |
sk398 | 1:cdf851858518 | 311 | else |
sk398 | 1:cdf851858518 | 312 | { |
sk398 | 4:b4bcb329a930 | 313 | OverSpeedInd = LOW; |
sk398 | 4:b4bcb329a930 | 314 | } |
sk398 | 4:b4bcb329a930 | 315 | } |
sk398 | 4:b4bcb329a930 | 316 | |
sk398 | 4:b4bcb329a930 | 317 | |
sk398 | 9:c236eaaacf08 | 318 | // Task6_UpdateOdometer takes the AverageSpeed global variable and calculates the |
sk398 | 9:c236eaaacf08 | 319 | // distance travelled by the Car over a known time increment (the delta of time between this task being ran) |
sk398 | 9:c236eaaacf08 | 320 | // Once calculated, the distance is stored globally and also, in conjunction with AverageSpeed, displayed onto |
sk398 | 9:c236eaaacf08 | 321 | // a LCD screen. It operates at a frequency of 2Hz |
sk398 | 5:4f2a072ed289 | 322 | void Task6_UpdateOdometer(void const *arg) |
sk398 | 6:572b9755f2c1 | 323 | { |
sk398 | 9:c236eaaacf08 | 324 | // Lock Shared Varialbe - AverageSpeed |
sk398 | 9:c236eaaacf08 | 325 | // Take local copy of AverageSpeed |
sk398 | 9:c236eaaacf08 | 326 | // Unlock Shared Variable |
sk398 | 9:c236eaaacf08 | 327 | filteredDataMutex.lock(); |
sk398 | 9:c236eaaacf08 | 328 | float currentAverageSpeed = AverageSpeed; |
sk398 | 9:c236eaaacf08 | 329 | filteredDataMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 330 | |
sk398 | 9:c236eaaacf08 | 331 | // Compute newTotalDistance from current TotalDistance and average speed |
sk398 | 9:c236eaaacf08 | 332 | |
sk398 | 9:c236eaaacf08 | 333 | // distance = oldDistance +(currentAverageSpeed*timeIncrement) |
sk398 | 9:c236eaaacf08 | 334 | // Note that timeIncrement (0.5 second) is converted from seconds to hours, |
sk398 | 9:c236eaaacf08 | 335 | // To remain consistant with mph units |
sk398 | 9:c236eaaacf08 | 336 | |
sk398 | 9:c236eaaacf08 | 337 | // NOTE |
sk398 | 9:c236eaaacf08 | 338 | // totalDistance does not need to be protected by a Mutex as this is the only task which updates |
sk398 | 9:c236eaaacf08 | 339 | // or uses the variable. It is global in order to keep track of a rolling total |
sk398 | 6:572b9755f2c1 | 340 | totalDistance = totalDistance + (currentAverageSpeed*(0.5/3600)); |
sk398 | 6:572b9755f2c1 | 341 | |
sk398 | 9:c236eaaacf08 | 342 | // Output totalDistance and currentAverageSpeed to LCD |
sk398 | 5:4f2a072ed289 | 343 | lcd -> cls(); |
sk398 | 5:4f2a072ed289 | 344 | lcd -> locate(0,0); |
sk398 | 5:4f2a072ed289 | 345 | lcd -> printf("Dist: %8.2f",totalDistance); |
sk398 | 5:4f2a072ed289 | 346 | lcd -> locate(1,0); |
sk398 | 5:4f2a072ed289 | 347 | lcd -> printf("Speed: %3.1f mph",currentAverageSpeed); |
sk398 | 5:4f2a072ed289 | 348 | } |
sk398 | 5:4f2a072ed289 | 349 | |
sk398 | 5:4f2a072ed289 | 350 | |
sk398 | 9:c236eaaacf08 | 351 | // Task7_SendToMailQueue takes global variables; AverageSpeed, RawAccelerometer and RawBraking and |
sk398 | 9:c236eaaacf08 | 352 | // creates a structure from them, then puts an instanc of this structure onto a Mail Queue, incrementing |
sk398 | 9:c236eaaacf08 | 353 | // a globally defined Counter as it does such. It operates with a frequency of 0.2Hz |
sk398 | 5:4f2a072ed289 | 354 | void Task7_SendToMailQueue(void const *arg) |
sk398 | 5:4f2a072ed289 | 355 | { |
sk398 | 9:c236eaaacf08 | 356 | // Lock Shared Resource - AverageSpeed |
sk398 | 9:c236eaaacf08 | 357 | // Take local copy of AverageSpeed |
sk398 | 9:c236eaaacf08 | 358 | // Unlock Shared Resource |
sk398 | 9:c236eaaacf08 | 359 | filteredDataMutex.lock(); |
sk398 | 9:c236eaaacf08 | 360 | float currentAverageSpeed = AverageSpeed; |
sk398 | 9:c236eaaacf08 | 361 | filteredDataMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 362 | |
sk398 | 9:c236eaaacf08 | 363 | // Lock Shared Resource - rawData |
sk398 | 9:c236eaaacf08 | 364 | // Take local copy of RawAccelerometer and RawBraking |
sk398 | 9:c236eaaacf08 | 365 | // Unlock Shared Resource |
sk398 | 8:6fad4bd89240 | 366 | rawDataMutex.lock(); |
sk398 | 8:6fad4bd89240 | 367 | float currentAccelerometer = rawData.RawAccelerometer; |
sk398 | 8:6fad4bd89240 | 368 | float currentBrake = rawData.RawBraking; |
sk398 | 8:6fad4bd89240 | 369 | rawDataMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 370 | |
sk398 | 9:c236eaaacf08 | 371 | // Allocate Memory for instance of PCDumpData structure |
sk398 | 9:c236eaaacf08 | 372 | PCDumpData *currentPCDump = Memory_Dump.alloc(); |
sk398 | 9:c236eaaacf08 | 373 | |
sk398 | 9:c236eaaacf08 | 374 | // Populate instance of PCDumpData with local copies of desired variables |
sk398 | 7:f09208f9a4f7 | 375 | currentPCDump -> currentAverageSpeed = currentAverageSpeed; |
sk398 | 7:f09208f9a4f7 | 376 | currentPCDump -> currentAccelerometer = currentAccelerometer; |
sk398 | 7:f09208f9a4f7 | 377 | currentPCDump -> currentBraking = currentBrake; |
sk398 | 7:f09208f9a4f7 | 378 | |
sk398 | 9:c236eaaacf08 | 379 | // Push instance of PCDumpData onto Mail Queue |
sk398 | 7:f09208f9a4f7 | 380 | Memory_Dump.put(currentPCDump); |
sk398 | 7:f09208f9a4f7 | 381 | |
sk398 | 9:c236eaaacf08 | 382 | // Lock Shared Resource - MailQueueCounter |
sk398 | 9:c236eaaacf08 | 383 | // Increment MailQueueCounter |
sk398 | 9:c236eaaacf08 | 384 | // Unlock Shared Resource |
sk398 | 7:f09208f9a4f7 | 385 | MailMutex.lock(); |
sk398 | 7:f09208f9a4f7 | 386 | MailQueueCounter++; |
sk398 | 7:f09208f9a4f7 | 387 | MailMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 388 | } |
sk398 | 5:4f2a072ed289 | 389 | |
sk398 | 5:4f2a072ed289 | 390 | |
sk398 | 9:c236eaaacf08 | 391 | // Task8_DumpSerial takes all of the instances of PCDumpData which have been pushed onto the Mail Queue |
sk398 | 9:c236eaaacf08 | 392 | // removes them from the Mail Queue and dumps their values over a PC serial connection. Once complete, the |
sk398 | 9:c236eaaacf08 | 393 | // counter which stores the number of elements in the Mail Queue is reset to 0. It operates at a frequency of 0.05Hz |
sk398 | 5:4f2a072ed289 | 394 | void Task8_DumpSerial(void const *arg) |
sk398 | 5:4f2a072ed289 | 395 | { |
sk398 | 9:c236eaaacf08 | 396 | // Lock Shared Resource - MailQueueCounter |
sk398 | 9:c236eaaacf08 | 397 | // Take local copy of MailQueueCounter |
sk398 | 9:c236eaaacf08 | 398 | // Unlock Shared Resource |
sk398 | 7:f09208f9a4f7 | 399 | MailMutex.lock(); |
sk398 | 7:f09208f9a4f7 | 400 | int currentQueueCounter = MailQueueCounter; |
sk398 | 7:f09208f9a4f7 | 401 | MailMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 402 | |
sk398 | 9:c236eaaacf08 | 403 | // Prompt State of Memory Dump |
sk398 | 7:f09208f9a4f7 | 404 | PCConn.printf("Memory Dump\r\n"); |
sk398 | 5:4f2a072ed289 | 405 | |
sk398 | 9:c236eaaacf08 | 406 | // For each instance of PCDumpData found in the Mail Queue, import the structure and store locally |
sk398 | 9:c236eaaacf08 | 407 | // Then print the contained values and free the element of the Mail Queue |
sk398 | 9:c236eaaacf08 | 408 | // Repeat for all indexes of the Mail Queue |
sk398 | 7:f09208f9a4f7 | 409 | for(int num = 0; num < currentQueueCounter; num++) |
sk398 | 7:f09208f9a4f7 | 410 | { |
sk398 | 7:f09208f9a4f7 | 411 | osEvent evt = Memory_Dump.get(); |
sk398 | 7:f09208f9a4f7 | 412 | if(evt.status == osEventMail) |
sk398 | 7:f09208f9a4f7 | 413 | { |
sk398 | 9:c236eaaacf08 | 414 | PCDumpData *currentPCDump = (PCDumpData*)evt.value.p; |
sk398 | 7:f09208f9a4f7 | 415 | |
sk398 | 7:f09208f9a4f7 | 416 | PCConn.printf("Av Speed: %f\r\nAcceler: %f\r\nBrake: %f\r\n\r\n", currentPCDump -> currentAverageSpeed, |
sk398 | 7:f09208f9a4f7 | 417 | currentPCDump -> currentAccelerometer, |
sk398 | 7:f09208f9a4f7 | 418 | currentPCDump -> currentBraking); |
sk398 | 7:f09208f9a4f7 | 419 | Memory_Dump.free(currentPCDump); |
sk398 | 7:f09208f9a4f7 | 420 | } |
sk398 | 7:f09208f9a4f7 | 421 | } |
sk398 | 7:f09208f9a4f7 | 422 | |
sk398 | 9:c236eaaacf08 | 423 | // Lock Shared Resource - MailQueueCounter |
sk398 | 9:c236eaaacf08 | 424 | // Reset MailQueueCounter |
sk398 | 9:c236eaaacf08 | 425 | // Unlock Shared Resource |
sk398 | 7:f09208f9a4f7 | 426 | MailMutex.lock(); |
sk398 | 7:f09208f9a4f7 | 427 | MailQueueCounter = 0; |
sk398 | 7:f09208f9a4f7 | 428 | MailMutex.unlock(); |
sk398 | 5:4f2a072ed289 | 429 | } |
sk398 | 5:4f2a072ed289 | 430 | |
sk398 | 5:4f2a072ed289 | 431 | |
sk398 | 9:c236eaaacf08 | 432 | // Task9_ReadSideLight takes external input from SideLightIndicator and conducts a logical test. |
sk398 | 9:c236eaaacf08 | 433 | // It operates at a frequency of 1Hz |
sk398 | 4:b4bcb329a930 | 434 | void Task9_ReadSideLight(void const *arg) |
sk398 | 4:b4bcb329a930 | 435 | { |
sk398 | 9:c236eaaacf08 | 436 | // If SideLightIndicator is HIGH, set SideLightInd to HIGH, else set to LOW |
sk398 | 4:b4bcb329a930 | 437 | if(SideLightIndicator) |
sk398 | 4:b4bcb329a930 | 438 | { |
sk398 | 4:b4bcb329a930 | 439 | SideLightInd = HIGH; |
sk398 | 4:b4bcb329a930 | 440 | } |
sk398 | 4:b4bcb329a930 | 441 | else |
sk398 | 4:b4bcb329a930 | 442 | { |
sk398 | 4:b4bcb329a930 | 443 | SideLightInd = LOW; |
sk398 | 1:cdf851858518 | 444 | } |
sk398 | 1:cdf851858518 | 445 | } |
sk398 | 0:f7d6ed1dfe3e | 446 | |
sk398 | 2:13a9394ba2e0 | 447 | |
sk398 | 9:c236eaaacf08 | 448 | // Task10_ReadIndicatorLights takes external input from LeftIndicator and RightIndicator and conducts a |
sk398 | 9:c236eaaacf08 | 449 | // logical test. It operates at a frequency of 0.5Hz |
sk398 | 4:b4bcb329a930 | 450 | void Task10_ReadIndicatorLights(void const *arg) |
sk398 | 0:f7d6ed1dfe3e | 451 | { |
sk398 | 9:c236eaaacf08 | 452 | |
sk398 | 9:c236eaaacf08 | 453 | // If LeftIndicator Only is HIGH, flash LeftLightInd at a frequency of 1Hz, 50% Duty |
sk398 | 1:cdf851858518 | 454 | if(LeftIndicator && !RightIndicator) |
sk398 | 1:cdf851858518 | 455 | { |
sk398 | 2:13a9394ba2e0 | 456 | LeftLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 457 | LeftLightInd.pulsewidth(0.5); |
sk398 | 2:13a9394ba2e0 | 458 | |
sk398 | 2:13a9394ba2e0 | 459 | RightLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 460 | RightLightInd.pulsewidth(0.0); |
sk398 | 1:cdf851858518 | 461 | } |
sk398 | 1:cdf851858518 | 462 | |
sk398 | 9:c236eaaacf08 | 463 | // If RightIndicator Only is HIGH, flash RightLightInd at a frequency of 1Hz, 50% Duty |
sk398 | 1:cdf851858518 | 464 | else if(!LeftIndicator && RightIndicator) |
sk398 | 0:f7d6ed1dfe3e | 465 | { |
sk398 | 2:13a9394ba2e0 | 466 | LeftLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 467 | LeftLightInd.pulsewidth(0.0); |
sk398 | 2:13a9394ba2e0 | 468 | |
sk398 | 2:13a9394ba2e0 | 469 | RightLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 470 | RightLightInd.pulsewidth(0.5); |
sk398 | 1:cdf851858518 | 471 | } |
sk398 | 1:cdf851858518 | 472 | |
sk398 | 9:c236eaaacf08 | 473 | // If LeftIndicator and RightIndicator are HIGH, flash LeftLightInd and RightLightInd |
sk398 | 9:c236eaaacf08 | 474 | // at a frequency of 2Hz, 50% Duty |
sk398 | 1:cdf851858518 | 475 | else if(LeftIndicator && RightIndicator) |
sk398 | 1:cdf851858518 | 476 | { |
sk398 | 2:13a9394ba2e0 | 477 | LeftLightInd.period(0.5); |
sk398 | 2:13a9394ba2e0 | 478 | RightLightInd.period(0.5); |
sk398 | 0:f7d6ed1dfe3e | 479 | |
sk398 | 2:13a9394ba2e0 | 480 | LeftLightInd.pulsewidth(0.25); |
sk398 | 2:13a9394ba2e0 | 481 | RightLightInd.pulsewidth(0.25); |
sk398 | 2:13a9394ba2e0 | 482 | } |
sk398 | 9:c236eaaacf08 | 483 | // Else, turn off both LeftLightInd and RightLightInd |
sk398 | 2:13a9394ba2e0 | 484 | else |
sk398 | 2:13a9394ba2e0 | 485 | { |
sk398 | 2:13a9394ba2e0 | 486 | LeftLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 487 | LeftLightInd.pulsewidth(0.0); |
sk398 | 2:13a9394ba2e0 | 488 | |
sk398 | 2:13a9394ba2e0 | 489 | RightLightInd.period(1.0); |
sk398 | 2:13a9394ba2e0 | 490 | RightLightInd.pulsewidth(0.0); |
sk398 | 0:f7d6ed1dfe3e | 491 | } |
sk398 | 1:cdf851858518 | 492 | } |
sk398 | 3:8192bbde17b3 | 493 | |
sk398 | 3:8192bbde17b3 | 494 | |
sk398 | 3:8192bbde17b3 | 495 | void InitSystem() |
sk398 | 3:8192bbde17b3 | 496 | { |
sk398 | 9:c236eaaacf08 | 497 | // Set AvSpeedWiper to 50Hz frequency, for Servo |
sk398 | 4:b4bcb329a930 | 498 | AvSpeedWiper.period_ms(20); |
sk398 | 4:b4bcb329a930 | 499 | |
sk398 | 9:c236eaaacf08 | 500 | // Initiate LCD by lighting Backlight |
sk398 | 9:c236eaaacf08 | 501 | par_port->write_bit(1,BL_BIT); |
sk398 | 3:8192bbde17b3 | 502 | |
sk398 | 9:c236eaaacf08 | 503 | // Initiate all Global variables to 0 |
sk398 | 8:6fad4bd89240 | 504 | rawData.EngineState = 0; |
sk398 | 8:6fad4bd89240 | 505 | rawData.RawAccelerometer = 0.0; |
sk398 | 8:6fad4bd89240 | 506 | rawData.RawBraking = 0.0; |
sk398 | 8:6fad4bd89240 | 507 | speedData.counter = 0; |
sk398 | 8:6fad4bd89240 | 508 | speedData.rawSpeed[0] = 0.0; |
sk398 | 8:6fad4bd89240 | 509 | speedData.rawSpeed[1] = 0.0; |
sk398 | 8:6fad4bd89240 | 510 | speedData.rawSpeed[2] = 0.0; |
sk398 | 9:c236eaaacf08 | 511 | AverageSpeed = 0.0; |
sk398 | 6:572b9755f2c1 | 512 | totalDistance = 0.0; |
sk398 | 7:f09208f9a4f7 | 513 | MailQueueCounter = 0; |
sk398 | 4:b4bcb329a930 | 514 | } |
sk398 | 3:8192bbde17b3 | 515 | |
sk398 | 9:c236eaaacf08 | 516 | |
sk398 | 2:13a9394ba2e0 | 517 | // ============================================================================ |
sk398 | 2:13a9394ba2e0 | 518 | // Entry Point Thread |
sk398 | 2:13a9394ba2e0 | 519 | // ============================================================================ |
sk398 | 1:cdf851858518 | 520 | |
sk398 | 9:c236eaaacf08 | 521 | // Entry Point Thread, this shall be the initialiser for the Car System and |
sk398 | 9:c236eaaacf08 | 522 | // Contains all of the Tasks and their associated properties, such as frequency. |
sk398 | 1:cdf851858518 | 523 | int main() |
sk398 | 1:cdf851858518 | 524 | { |
sk398 | 9:c236eaaacf08 | 525 | // Construct Objects for LCD |
sk398 | 4:b4bcb329a930 | 526 | par_port = new MCP23017(p9, p10, 0x40); // initialise 16-bit I/O chip |
sk398 | 4:b4bcb329a930 | 527 | lcd = new WattBob_TextLCD(par_port); // initialise 2*26 char display |
sk398 | 4:b4bcb329a930 | 528 | |
sk398 | 9:c236eaaacf08 | 529 | // Set PC Connection Baud Rate |
sk398 | 4:b4bcb329a930 | 530 | PCConn.baud(115200); |
sk398 | 4:b4bcb329a930 | 531 | |
sk398 | 9:c236eaaacf08 | 532 | // Initialise System, including Global Variables |
sk398 | 3:8192bbde17b3 | 533 | InitSystem(); |
sk398 | 3:8192bbde17b3 | 534 | |
sk398 | 9:c236eaaacf08 | 535 | // Construct Tasks as RtosTimer objects |
sk398 | 4:b4bcb329a930 | 536 | RtosTimer CarSim(CarSimulator,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 537 | RtosTimer Task1(Task1_ReadRawData,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 538 | RtosTimer Task2(Task2_ReadEngineState,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 539 | RtosTimer Task3(Task3_CalcAvSpeed,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 540 | RtosTimer Task4(Task4_UpdateRCWiper,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 541 | RtosTimer Task5(Task5_OverspeedLED,osTimerPeriodic); |
sk398 | 5:4f2a072ed289 | 542 | RtosTimer Task6(Task6_UpdateOdometer,osTimerPeriodic); |
sk398 | 5:4f2a072ed289 | 543 | RtosTimer Task7(Task7_SendToMailQueue,osTimerPeriodic); |
sk398 | 5:4f2a072ed289 | 544 | RtosTimer Task8(Task8_DumpSerial,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 545 | RtosTimer Task9(Task9_ReadSideLight,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 546 | RtosTimer Task10(Task10_ReadIndicatorLights,osTimerPeriodic); |
sk398 | 4:b4bcb329a930 | 547 | |
sk398 | 9:c236eaaacf08 | 548 | // Staert RtosTimer objects, with the required frequency |
sk398 | 5:4f2a072ed289 | 549 | CarSim.start(50); // 20Hz |
sk398 | 5:4f2a072ed289 | 550 | Task1.start(100); // 10Hz |
sk398 | 5:4f2a072ed289 | 551 | Task2.start(500); // 2Hz |
sk398 | 5:4f2a072ed289 | 552 | Task3.start(200); // 5Hz |
sk398 | 5:4f2a072ed289 | 553 | Task4.start(1000); // 1Hz |
sk398 | 5:4f2a072ed289 | 554 | Task5.start(2000); // 0.5Hz |
sk398 | 5:4f2a072ed289 | 555 | Task6.start(500); // 2Hz |
sk398 | 5:4f2a072ed289 | 556 | Task7.start(5000); // 0.2Hz |
sk398 | 5:4f2a072ed289 | 557 | Task8.start(20000); // 0.05Hz |
sk398 | 5:4f2a072ed289 | 558 | Task9.start(1000); // 1Hz |
sk398 | 5:4f2a072ed289 | 559 | Task10.start(2000); // 0.5Hz |
sk398 | 1:cdf851858518 | 560 | |
sk398 | 9:c236eaaacf08 | 561 | // Ensure that RtosTimer runs within Infinite loop |
sk398 | 1:cdf851858518 | 562 | Thread::wait(osWaitForever); |
sk398 | 1:cdf851858518 | 563 | |
sk398 | 0:f7d6ed1dfe3e | 564 | |
sk398 | 0:f7d6ed1dfe3e | 565 | } |