Example software for a Cyclic Executive
Dependencies: MCP23017 SDFileSystem WattBob_TextLCD mbed
main.cpp@10:c0531edf4850, 2016-03-02 (annotated)
- Committer:
- sk398
- Date:
- Wed Mar 02 13:38:27 2016 +0000
- Revision:
- 10:c0531edf4850
- Parent:
- 9:46408a8dea0c
Final version - all operational
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sk398 | 4:b85bc0d810e1 | 1 | /* ##################################################################### |
sk398 | 4:b85bc0d810e1 | 2 | main.cpp |
sk398 | 4:b85bc0d810e1 | 3 | --------- |
sk398 | 4:b85bc0d810e1 | 4 | |
sk398 | 4:b85bc0d810e1 | 5 | Embedded Software - Assignment 2 |
sk398 | 4:b85bc0d810e1 | 6 | -------------------------------- |
sk398 | 4:b85bc0d810e1 | 7 | |
sk398 | 4:b85bc0d810e1 | 8 | Written by: Steven Kay |
sk398 | 4:b85bc0d810e1 | 9 | |
sk398 | 4:b85bc0d810e1 | 10 | Date: February 2016 |
sk398 | 4:b85bc0d810e1 | 11 | |
sk398 | 10:c0531edf4850 | 12 | Function: This is the main runner containing the Cyclic executive |
sk398 | 10:c0531edf4850 | 13 | There are 7 defined tasks and several Auxillary components |
sk398 | 10:c0531edf4850 | 14 | which are logically ran periodically at their required time |
sk398 | 10:c0531edf4850 | 15 | by a Cyclic Executive sequencer. |
sk398 | 10:c0531edf4850 | 16 | Ticks, or slots, to this Cyclic Executive are provided by |
sk398 | 10:c0531edf4850 | 17 | a ticker ever 25ms, and then using logical expressions, the |
sk398 | 10:c0531edf4850 | 18 | correct task is initiated and allocated the required time. |
sk398 | 4:b85bc0d810e1 | 19 | |
sk398 | 4:b85bc0d810e1 | 20 | ##################################################################### */ |
sk398 | 2:22ebabd78084 | 21 | |
sk398 | 0:5989ac10c4d3 | 22 | #include "mbed.h" |
sk398 | 1:221d677fe0d3 | 23 | #include "Tasks.h" |
sk398 | 0:5989ac10c4d3 | 24 | |
sk398 | 7:2973bf297f3d | 25 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 26 | // Task Declerations |
sk398 | 7:2973bf297f3d | 27 | // ============================================================================ |
sk398 | 6:ceda53939eb8 | 28 | Task1 task1(p11); // Square wave Measurement |
sk398 | 7:2973bf297f3d | 29 | Task2 task2_switch1(p12); // Read digital Input |
sk398 | 6:ceda53939eb8 | 30 | Task3 task3(p13); // Watchdog Pulse |
sk398 | 6:ceda53939eb8 | 31 | Task4 task4(p15,p16); // Read analog Inputs |
sk398 | 6:ceda53939eb8 | 32 | Task5 task5(p9,p10,0x40); // Output to LCD Display |
sk398 | 6:ceda53939eb8 | 33 | Task6 task6; // Logical checks |
sk398 | 6:ceda53939eb8 | 34 | Task7 task7(p5,p6,p7,p8,"SD","/SD/A2"); // SD Card Write |
sk398 | 0:5989ac10c4d3 | 35 | |
sk398 | 7:2973bf297f3d | 36 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 37 | // Cyclic Executive Objects and Declerations |
sk398 | 7:2973bf297f3d | 38 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 39 | DigitalOut ErrorLED(LED1); // Error Indicating LED |
sk398 | 10:c0531edf4850 | 40 | DigitalOut LenPin(p25); // Pulse Pin |
sk398 | 10:c0531edf4850 | 41 | DigitalIn SDRemoval(p18); // Switch state to indicate remove SD |
sk398 | 7:2973bf297f3d | 42 | Ticker CyclicTicker; // Ticker object to cycle tasks |
sk398 | 10:c0531edf4850 | 43 | Timer stampTime; // Timer to stamp the time between logs |
sk398 | 10:c0531edf4850 | 44 | |
sk398 | 10:c0531edf4850 | 45 | // NOTE THE FOLLOWING ARE NOT ESSENTIAL TO THE OPERATION OF THIS CYCLIC EXECUTIVE |
sk398 | 10:c0531edf4850 | 46 | Timer task1t; // Timer to calculate task1 timing |
sk398 | 10:c0531edf4850 | 47 | Timer task2t; // Timer to calculate task2 timing |
sk398 | 10:c0531edf4850 | 48 | Timer task3t; // Timer to calculate task3 timing |
sk398 | 10:c0531edf4850 | 49 | Timer task4t; // Timer to calculate task4 timing |
sk398 | 10:c0531edf4850 | 50 | Timer task5t; // Timer to calculate task5 timing |
sk398 | 10:c0531edf4850 | 51 | Timer task6t; // Timer to calculate task6 timing |
sk398 | 7:2973bf297f3d | 52 | |
sk398 | 7:2973bf297f3d | 53 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 54 | // Global Data Parameters used in Cyclic Executive |
sk398 | 7:2973bf297f3d | 55 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 56 | // Counter to record the number of ticks went through by the Cyclic Executive |
sk398 | 7:2973bf297f3d | 57 | int cyclicTicks = 1; |
sk398 | 7:2973bf297f3d | 58 | |
sk398 | 10:c0531edf4850 | 59 | // Flag variable to switch priority between Tasks 2 and 3 |
sk398 | 10:c0531edf4850 | 60 | int taskNum = 2; |
sk398 | 10:c0531edf4850 | 61 | |
sk398 | 7:2973bf297f3d | 62 | // Global parameter storing the most up to date value of the return from Task 1 |
sk398 | 7:2973bf297f3d | 63 | volatile int task1Frequency; |
sk398 | 7:2973bf297f3d | 64 | |
sk398 | 7:2973bf297f3d | 65 | // Global parameter storing the most up to date value of the return from Task 2 |
sk398 | 7:2973bf297f3d | 66 | volatile int task2SwitchState; |
sk398 | 7:2973bf297f3d | 67 | |
sk398 | 7:2973bf297f3d | 68 | // Global parameter storing the most up to date value of the return from Task 4 |
sk398 | 7:2973bf297f3d | 69 | volatile float task4AnalogChannels[2]; |
sk398 | 7:2973bf297f3d | 70 | |
sk398 | 7:2973bf297f3d | 71 | // Global parameter storing the most up to date value of the return from Task 6 |
sk398 | 7:2973bf297f3d | 72 | volatile int task6ErrorState; |
sk398 | 7:2973bf297f3d | 73 | |
sk398 | 7:2973bf297f3d | 74 | // Char array to store the concatenated string for output onto the SD Card |
sk398 | 7:2973bf297f3d | 75 | char logData[50]; |
sk398 | 7:2973bf297f3d | 76 | |
sk398 | 7:2973bf297f3d | 77 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 78 | // Cyclic Executive Function Prototypes |
sk398 | 7:2973bf297f3d | 79 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 80 | void CyclicExec(); |
sk398 | 7:2973bf297f3d | 81 | |
sk398 | 7:2973bf297f3d | 82 | // ============================================================================ |
sk398 | 7:2973bf297f3d | 83 | // Main Execution Program |
sk398 | 7:2973bf297f3d | 84 | // ============================================================================ |
sk398 | 0:5989ac10c4d3 | 85 | int main() { |
sk398 | 10:c0531edf4850 | 86 | |
sk398 | 7:2973bf297f3d | 87 | // Attempt to open SD file |
sk398 | 7:2973bf297f3d | 88 | // If open failed, do not run Cyclic Exec |
sk398 | 7:2973bf297f3d | 89 | if(!task7.openFile("/SD/A2/test.csv","a")) |
sk398 | 7:2973bf297f3d | 90 | { |
sk398 | 7:2973bf297f3d | 91 | // Start Cyclic Executive |
sk398 | 7:2973bf297f3d | 92 | CyclicTicker.attach(&CyclicExec,0.025); // 25ms pulses |
sk398 | 7:2973bf297f3d | 93 | |
sk398 | 7:2973bf297f3d | 94 | // Keep program running until RESET |
sk398 | 7:2973bf297f3d | 95 | while(1) |
sk398 | 7:2973bf297f3d | 96 | { |
sk398 | 7:2973bf297f3d | 97 | } |
sk398 | 7:2973bf297f3d | 98 | } |
sk398 | 4:b85bc0d810e1 | 99 | |
sk398 | 7:2973bf297f3d | 100 | // If FIle is not opened, prompt user and show Error on LED |
sk398 | 6:ceda53939eb8 | 101 | else |
sk398 | 6:ceda53939eb8 | 102 | { |
sk398 | 7:2973bf297f3d | 103 | // Prompt user about error |
sk398 | 7:2973bf297f3d | 104 | printf("File not opened\r\nNot executing Cyclic Executive"); |
sk398 | 7:2973bf297f3d | 105 | |
sk398 | 7:2973bf297f3d | 106 | // Execute error code on LED |
sk398 | 7:2973bf297f3d | 107 | while(1) |
sk398 | 7:2973bf297f3d | 108 | { |
sk398 | 7:2973bf297f3d | 109 | ErrorLED = 1; |
sk398 | 7:2973bf297f3d | 110 | wait(1); |
sk398 | 7:2973bf297f3d | 111 | ErrorLED = 0; |
sk398 | 7:2973bf297f3d | 112 | wait(1); |
sk398 | 7:2973bf297f3d | 113 | } |
sk398 | 7:2973bf297f3d | 114 | } |
sk398 | 7:2973bf297f3d | 115 | } |
sk398 | 7:2973bf297f3d | 116 | |
sk398 | 7:2973bf297f3d | 117 | #define TASK1_TICKS 40 |
sk398 | 7:2973bf297f3d | 118 | #define TASK2_TICKS 12 |
sk398 | 7:2973bf297f3d | 119 | #define TASK3_TICKS 12 |
sk398 | 7:2973bf297f3d | 120 | #define TASK4_TICKS 16 |
sk398 | 7:2973bf297f3d | 121 | #define TASK5_TICKS 80 |
sk398 | 7:2973bf297f3d | 122 | #define TASK6_TICKS 32 |
sk398 | 7:2973bf297f3d | 123 | #define TASK7_TICKS 200 |
sk398 | 7:2973bf297f3d | 124 | |
sk398 | 7:2973bf297f3d | 125 | void CyclicExec() |
sk398 | 7:2973bf297f3d | 126 | { |
sk398 | 10:c0531edf4850 | 127 | // When called, increment cyclicTicks |
sk398 | 7:2973bf297f3d | 128 | cyclicTicks++; |
sk398 | 10:c0531edf4850 | 129 | |
sk398 | 10:c0531edf4850 | 130 | // Run every 1 second (should be 40 ticks, but tuned to 38 through testing) |
sk398 | 10:c0531edf4850 | 131 | if(cyclicTicks % 38 == 0) |
sk398 | 10:c0531edf4850 | 132 | { |
sk398 | 10:c0531edf4850 | 133 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 134 | task1t.stop(); |
sk398 | 10:c0531edf4850 | 135 | printf("T1 %d\r\n",task1t.read_ms()); |
sk398 | 10:c0531edf4850 | 136 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 137 | |
sk398 | 10:c0531edf4850 | 138 | // Run Task1 |
sk398 | 10:c0531edf4850 | 139 | LenPin = 1; |
sk398 | 10:c0531edf4850 | 140 | task1Frequency = task1.ReadFrequency(); |
sk398 | 10:c0531edf4850 | 141 | LenPin = 0; |
sk398 | 10:c0531edf4850 | 142 | |
sk398 | 10:c0531edf4850 | 143 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 144 | task1t.reset(); |
sk398 | 10:c0531edf4850 | 145 | task1t.start(); |
sk398 | 10:c0531edf4850 | 146 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 147 | } |
sk398 | 10:c0531edf4850 | 148 | |
sk398 | 10:c0531edf4850 | 149 | // Run every 300ms (should be 12 ticks, but logic dictates double the frequency) |
sk398 | 10:c0531edf4850 | 150 | if(cyclicTicks % 6 == 0) |
sk398 | 10:c0531edf4850 | 151 | { |
sk398 | 10:c0531edf4850 | 152 | // If flag taskNum is assigned to run Task2 |
sk398 | 10:c0531edf4850 | 153 | if(taskNum == 2) |
sk398 | 10:c0531edf4850 | 154 | { |
sk398 | 10:c0531edf4850 | 155 | |
sk398 | 10:c0531edf4850 | 156 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 157 | task2t.stop(); |
sk398 | 10:c0531edf4850 | 158 | printf("T2 %d\r\n",task2t.read_ms()); |
sk398 | 10:c0531edf4850 | 159 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 160 | |
sk398 | 10:c0531edf4850 | 161 | // Run Task 2 |
sk398 | 10:c0531edf4850 | 162 | task2SwitchState = task2_switch1.digitalInState(); |
sk398 | 10:c0531edf4850 | 163 | |
sk398 | 10:c0531edf4850 | 164 | // Set flag to run Task 3 on next iteration |
sk398 | 10:c0531edf4850 | 165 | taskNum = 3; |
sk398 | 10:c0531edf4850 | 166 | |
sk398 | 10:c0531edf4850 | 167 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 168 | task2t.reset(); |
sk398 | 10:c0531edf4850 | 169 | task2t.start(); |
sk398 | 10:c0531edf4850 | 170 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 171 | } |
sk398 | 10:c0531edf4850 | 172 | |
sk398 | 10:c0531edf4850 | 173 | // If flag taskNum is assigned to run Task3 |
sk398 | 10:c0531edf4850 | 174 | else if(taskNum == 3) |
sk398 | 10:c0531edf4850 | 175 | { |
sk398 | 10:c0531edf4850 | 176 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 177 | task3t.stop(); |
sk398 | 10:c0531edf4850 | 178 | printf("T3 %d\r\n",task3t.read_ms()); |
sk398 | 10:c0531edf4850 | 179 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 180 | |
sk398 | 10:c0531edf4850 | 181 | |
sk398 | 10:c0531edf4850 | 182 | // Run Task3 |
sk398 | 10:c0531edf4850 | 183 | task3.OutputWatchdogPulse(); |
sk398 | 10:c0531edf4850 | 184 | |
sk398 | 10:c0531edf4850 | 185 | // Set flag to run Task2 on next iteration |
sk398 | 10:c0531edf4850 | 186 | taskNum = 2; |
sk398 | 10:c0531edf4850 | 187 | |
sk398 | 10:c0531edf4850 | 188 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 189 | task3t.reset(); |
sk398 | 10:c0531edf4850 | 190 | task3t.start(); |
sk398 | 10:c0531edf4850 | 191 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 192 | } |
sk398 | 10:c0531edf4850 | 193 | } |
sk398 | 10:c0531edf4850 | 194 | |
sk398 | 10:c0531edf4850 | 195 | // Run every 400ms (16 ticks) |
sk398 | 10:c0531edf4850 | 196 | if(cyclicTicks % 16 == 0) |
sk398 | 10:c0531edf4850 | 197 | { |
sk398 | 10:c0531edf4850 | 198 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 199 | task4t.stop(); |
sk398 | 10:c0531edf4850 | 200 | printf("T4 %d\r\n",task4t.read_ms()); |
sk398 | 10:c0531edf4850 | 201 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 202 | |
sk398 | 10:c0531edf4850 | 203 | // Run Task4 |
sk398 | 10:c0531edf4850 | 204 | float *analogReading = task4.returnAnalogReadings(); |
sk398 | 10:c0531edf4850 | 205 | task4AnalogChannels[0] = *(analogReading); |
sk398 | 10:c0531edf4850 | 206 | task4AnalogChannels[1]= *(analogReading+1); |
sk398 | 10:c0531edf4850 | 207 | |
sk398 | 10:c0531edf4850 | 208 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 209 | task4t.reset(); |
sk398 | 10:c0531edf4850 | 210 | task4t.start(); |
sk398 | 10:c0531edf4850 | 211 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 212 | } |
sk398 | 10:c0531edf4850 | 213 | |
sk398 | 10:c0531edf4850 | 214 | // Run every 2 seconds (should be 80 ticks, but tuned to 84 through testing) |
sk398 | 10:c0531edf4850 | 215 | if(cyclicTicks % 84 == 0) |
sk398 | 10:c0531edf4850 | 216 | { |
sk398 | 10:c0531edf4850 | 217 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 218 | task5t.stop(); |
sk398 | 10:c0531edf4850 | 219 | printf("T5 %1.2f\r\n",task5t.read()); |
sk398 | 10:c0531edf4850 | 220 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 221 | |
sk398 | 10:c0531edf4850 | 222 | // Run Task5 |
sk398 | 10:c0531edf4850 | 223 | task5.updateDisplay( task1Frequency, |
sk398 | 10:c0531edf4850 | 224 | task2SwitchState, |
sk398 | 10:c0531edf4850 | 225 | task6ErrorState, |
sk398 | 10:c0531edf4850 | 226 | task4AnalogChannels[0], |
sk398 | 10:c0531edf4850 | 227 | task4AnalogChannels[1] ); |
sk398 | 10:c0531edf4850 | 228 | |
sk398 | 10:c0531edf4850 | 229 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 230 | task5t.reset(); |
sk398 | 10:c0531edf4850 | 231 | task5t.start(); |
sk398 | 10:c0531edf4850 | 232 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 233 | } |
sk398 | 10:c0531edf4850 | 234 | |
sk398 | 10:c0531edf4850 | 235 | // Run every 800ms (32 ticks) |
sk398 | 10:c0531edf4850 | 236 | if(cyclicTicks % 32 == 0) |
sk398 | 10:c0531edf4850 | 237 | { |
sk398 | 10:c0531edf4850 | 238 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 239 | task6t.stop(); |
sk398 | 10:c0531edf4850 | 240 | printf("T6 %d\r\n",task6t.read_ms()); |
sk398 | 10:c0531edf4850 | 241 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 242 | |
sk398 | 10:c0531edf4850 | 243 | // Run Task6 |
sk398 | 10:c0531edf4850 | 244 | task6ErrorState = task6.updateErrorCode( task2SwitchState, |
sk398 | 10:c0531edf4850 | 245 | task4AnalogChannels[0], |
sk398 | 10:c0531edf4850 | 246 | task4AnalogChannels[1] ); |
sk398 | 10:c0531edf4850 | 247 | |
sk398 | 10:c0531edf4850 | 248 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 249 | task6t.reset(); |
sk398 | 10:c0531edf4850 | 250 | task6t.start(); |
sk398 | 10:c0531edf4850 | 251 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 252 | } |
sk398 | 10:c0531edf4850 | 253 | |
sk398 | 10:c0531edf4850 | 254 | // Run every 5 seconds (200 ticks) |
sk398 | 7:2973bf297f3d | 255 | if(cyclicTicks % 200 == 0) |
sk398 | 7:2973bf297f3d | 256 | { |
sk398 | 10:c0531edf4850 | 257 | // ---------- Can be removed --------- |
sk398 | 10:c0531edf4850 | 258 | printf("T7\r\n"); |
sk398 | 10:c0531edf4850 | 259 | // ----------------------------------- |
sk398 | 10:c0531edf4850 | 260 | |
sk398 | 10:c0531edf4850 | 261 | // Run Task7 |
sk398 | 7:2973bf297f3d | 262 | stampTime.stop(); |
sk398 | 7:2973bf297f3d | 263 | int a = sprintf( logData,"Time=%1.2f,Freq=%d,SW1=%d,A1=%1.3f,A2=%1.3f\n", |
sk398 | 7:2973bf297f3d | 264 | stampTime.read(), |
sk398 | 7:2973bf297f3d | 265 | task1Frequency, |
sk398 | 7:2973bf297f3d | 266 | task2SwitchState, |
sk398 | 7:2973bf297f3d | 267 | task4AnalogChannels[0], |
sk398 | 7:2973bf297f3d | 268 | task4AnalogChannels[1] ); |
sk398 | 7:2973bf297f3d | 269 | task7.writeData(logData); |
sk398 | 10:c0531edf4850 | 270 | |
sk398 | 10:c0531edf4850 | 271 | // ---------- Can be removed --------- |
sk398 | 7:2973bf297f3d | 272 | stampTime.reset(); |
sk398 | 7:2973bf297f3d | 273 | stampTime.start(); |
sk398 | 10:c0531edf4850 | 274 | // ----------------------------------- |
sk398 | 7:2973bf297f3d | 275 | } |
sk398 | 7:2973bf297f3d | 276 | |
sk398 | 10:c0531edf4850 | 277 | // If SDRemoval Input is high, close FILE and detach the Ticker |
sk398 | 7:2973bf297f3d | 278 | if(SDRemoval == HIGH) |
sk398 | 7:2973bf297f3d | 279 | { |
sk398 | 7:2973bf297f3d | 280 | printf("SD Removed"); |
sk398 | 7:2973bf297f3d | 281 | task7.closeFile(); |
sk398 | 10:c0531edf4850 | 282 | CyclicTicker.detach(); |
sk398 | 7:2973bf297f3d | 283 | } |
sk398 | 7:2973bf297f3d | 284 | } |
sk398 | 7:2973bf297f3d | 285 |