Test session
Dependencies: FatFileSystem MCP23017 WattBob_TextLCD mbed
Fork of Assignment_2_herpe by
XG_2.cpp
00001 // XAVIER GOUESNARD 00002 // H00258183 00003 // Assignment 2 00004 // MSc Embeded Systems 2016/2017 00005 // Heriot-Watt University 00006 00007 #include "mbed.h" 00008 #include "MCP23017.h" 00009 #include "WattBob_TextLCD.h" 00010 #include "SDFileSystem.h" 00011 #include "FATFileSystem.h" 00012 00013 #define BACK_LIGHT_ON(INTERFACE) INTERFACE->write_bit(1,BL_BIT) 00014 #define BACK_LIGHT_OFF(INTERFACE) INTERFACE->write_bit(0,BL_BIT) 00015 00016 // Pointers to LCD screen and SD card 00017 MCP23017 *par_port; // pointer to 16-bit parallel I/O chip 00018 WattBob_TextLCD *lcd; // pointer to 2*16 character LCD object 00019 FILE *fp; // Pointer to SD card object 00020 00021 00022 //===================================================================================== 00023 // I/O ports allocation 00024 //===================================================================================== 00025 DigitalIn TTL(p17); // TTL input for frequency measurement 00026 DigitalIn switch_1(p18); // Switch 1 input 00027 DigitalIn switch_2(p19); // Switch 2 input 00028 DigitalIn switch_off(p11); // Switch used to close SD file and stop cyclic executive 00029 AnalogIn analogue_in_1(p15); // POT value 00030 AnalogIn analogue_in_2(p16); // LDR value 00031 PwmOut servo(p21); // Servo output 00032 DigitalOut TestPin(p20); // Pin only used to test program and measure time 00033 SDFileSystem sd(p5, p6, p7, p8, "sd"); // The pinout on the mbed Cool Components workshop board 00034 DigitalIn switch_pin(p14, PullDown); 00035 00036 //===================================================================================== 00037 // Internal objects declaration 00038 // ==================================================================================== 00039 BusOut LEDs(LED4, LED3, LED2, LED1); // Address the four LEDs to a single bus 00040 Timer timer; // Timer used to measure frequency in task 1 00041 Timer DoNothing; // Timer used to measure how long the program does nothing 00042 Ticker ticker; // Ticker used as clock for cyclic executive program 00043 00044 00045 //===================================================================================== 00046 // Constants declaration 00047 //===================================================================================== 00048 const int SampFreq = 100; // Sampling frequency is 10kHz (100us) 00049 00050 //===================================================================================== 00051 // Variables declaration 00052 //===================================================================================== 00053 00054 // Variables for cyclic executive program 00055 long int ticks = 0; // Used to define what task to call in the cyclic executive program 00056 int NoTask = 0; // Used to return how long the program does nothing in ms 00057 int NoTaskCount = 0; // Variable incremented until one total cycle of 10 seconds is reached 00058 00059 // Variables for tasks 1 and 2 00060 int period = 0; // Returned period of the TTL input signal 00061 int frequency = 0; // Returned frequency of the TTL signal 00062 00063 // Varibles for task 4 00064 int switch_1_val = 0; // Used to return how many times the switch is high 00065 int switch_2_val = 0; 00066 bool switch_1_state = 0; // Used to define whether the debounced switch is ON or OFF 00067 bool switch_2_state = 0; 00068 00069 // Variables for task 5 00070 float analogue_1_val = 0; // Used to return the filtered analogue input 00071 float analogue_2_val = 0; 00072 00073 int analogue_1_int = 0; // Used to convert float to int (results in quicker display on LCD in task 6) 00074 int analogue_2_int = 0; 00075 00076 // Variable for task 7 00077 int LogCount = 0; // Used to define logging number 00078 00079 // Variable used for task 8 00080 int BinCount = 0; // Used to increment a binary display on LEDs. Goes from 0 to 15 and then is reset 00081 bool BinEnable = 0; // Used to tell task 5 to display binary pattern on LEDs every 1.5s 00082 int IncCheck = 0; // Check increment to see if 6 cycles have elapsed to light LEDs ( 6 * 250us = 1.5s) 00083 00084 00085 //===================================================================================== 00086 // Task declaration 00087 //===================================================================================== 00088 00089 void CyclEx(); 00090 00091 void Task1(); // Measure TTL input frequency 00092 void Task2(); // Show frequency on LCD screen 00093 void Task3(); // Show speed on servo dial 00094 void Task4(); // Read and debounce two digital inputs 00095 void Task5(); // Read and filter two analogue inputs 00096 void Task6(); // Display digital and analogue inputs on LCD screen 00097 void Task7(); // Log speed, analogue and digital inputs on SD card 00098 void Task8(); // Display error message on LCD screen and display binary pattern on LEDs 00099 00100 void WaitRisEdge(); // Subroutine to detect rising edge 00101 void WaitFalEdge(); // Subroutine to detect falling edge 00102 00103 void Stop(); // Close log file and stop cyclic executive 00104 00105 00106 //===================================================================================== 00107 // Main program 00108 //===================================================================================== 00109 00110 int main() 00111 { 00112 00113 // LCD Screen Initialisation 00114 par_port = new MCP23017(p9, p10, 0x40); // initialise 16-bit I/O chip 00115 lcd = new WattBob_TextLCD(par_port); // initialise 2*26 char display 00116 par_port->write_bit(1,BL_BIT); // turn LCD backlight ON 00117 lcd->cls(); // clear display 00118 00119 // EXEL log file initialisation 00120 fp = fopen("/sd/log.xls", "w"); // pointer to log in text file called "log". (Use "a" to not delete file) 00121 fprintf(fp, "This file is the property of Xavier Gouesnard\n\n"); 00122 00123 // DoNothing timer reset 00124 DoNothing.reset(); 00125 00126 // Internal ticker set to 25ms. Every 25ms, the scheduler is called and selects the task to run 00127 ticker.attach(&CyclEx, 0.025); // Period set to 25ms 00128 while(1)// Run until system shuts down 00129 { 00130 00131 } 00132 } 00133 00134 // Where tasks are scheduled based on an EXEL sheet 00135 void CyclEx() 00136 { 00137 // Stop timer when a new task starts 00138 DoNothing.stop(); 00139 00140 if(ticks % 80 == 4) // Occures every 80 clock cycles (2 seconds). Starts with an offset of 4 clock cycles 00141 { 00142 Task1(); 00143 } 00144 00145 else if(ticks % 200 == 8) // Occures every 200 clock cycles (5 seconds). Starts with an offset of 8 clock cycles 00146 { 00147 Task2(); 00148 } 00149 else if(ticks % 240 == 7) // Occures every 240 clock cycles (6 seconds). Starts with an offset of 7 clock cycles 00150 { 00151 Task3(); 00152 } 00153 else if(ticks % 4 == 0) // Occures every 4 clock cycles (0.1 seconds). Starts with an offset of 0 clock cycles 00154 { 00155 Task4(); 00156 } 00157 else if(ticks % 10 == 1) // Occures every 10 clock cycles (0.25 seconds). Starts with an offset of 1 clock cycles 00158 { 00159 Task5(); 00160 } 00161 else if(ticks % 40 == 3) // Occures every 40 clock cycles (1 seconds). Starts with an offset of 3 clock cycles 00162 { 00163 Task6(); 00164 } 00165 else if(ticks % 400 == 10) // Occures every 400 clock cycles (10 seconds). Starts with an offset of 10 clock cycles 00166 { 00167 Task7(); 00168 } 00169 else if(ticks % 160 == 6) // Occures every 160 clock cycles (4 seconds). Starts with an offset of 6 clock cycles 00170 { 00171 Task8(); 00172 } 00173 00174 if (switch_off == 1) // Pin used to log data on SD card and stop Cyclic executive program 00175 { 00176 Stop(); 00177 } 00178 ticks++; 00179 00180 // Start timer when one task is ended 00181 DoNothing.start(); 00182 NoTaskCount++; 00183 00184 // When one full cycle of 10 seconds is finished, return how long the program was doing nothing (lazy program) 00185 if (NoTaskCount == 400) 00186 { 00187 NoTask = DoNothing.read_ms(); 00188 NoTaskCount = 0; 00189 DoNothing.reset(); 00190 } 00191 } 00192 00193 00194 //===================================================================================== 00195 // Tasks 00196 //===================================================================================== 00197 00198 // Task 1: Measure the freqeuncy of a 3.3v square wave signal 00199 void Task1() 00200 { 00201 task 1 00202 00203 timer.reset(); 00204 while(freqCountPin == 0) {} 00205 timer.start(); 00206 while(freqCountPin == 1) {} 00207 timer.stop(); 00208 frequency = 2000000 / timer.read_us() 00209 00210 00211 // Task 2: display the measured frequency on LCD screen 00212 void Task2() 00213 { 00214 lcd->cls(); // clear display 00215 lcd->locate(0,0); // set cursor to location (0,0) - top left corner 00216 lcd->printf("%d Hz",frequency); // print the frequency calculated in task 1 00217 } 00218 00219 00220 00221 // Task 3: show speed on servo output dial 00222 void Task3() 00223 { 00224 servo.period(0.02); // servo requires a 20ms period 00225 // To rotate the servo from -90 to +90 degrees, the pulse width must varies between 600us to 2300us 00226 // The pulse width is calculated from the speed measured in task one 00227 // 50Hz is equivalent to -90 degrees and 100Hz is equivalent to 90 degrees 00228 // 1Hz change is equal to 34us pulse width change, so pulse width = ((frequency - 50)*34) + 600 00229 servo.pulsewidth_us(2300-((frequency - 50)*34)); 00230 wait_ms(1); // Leave the servo some time to reach its position 00231 } 00232 00233 00234 00235 // Task 4: Read two digital inputs (debounced) 00236 void Task4() 00237 { 00238 switch_1_val = 0; 00239 switch_2_val = 0; 00240 00241 // Read each switch three consecutive times with 100us between readings 00242 for(int i=0; i<3; i++) 00243 { 00244 if (switch_1 == 1) // Increment variable if switch 1 is pressed 00245 { 00246 switch_1_val++; 00247 } 00248 00249 if (switch_2 == 1) // Increment variable if switch 2 is pressed 00250 { 00251 switch_2_val++; 00252 } 00253 00254 wait_us(SampFreq); 00255 } 00256 // Check how many times switch 1 has been high 00257 // if it has been high more than twice, then switch 1 state = 1 00258 if (switch_1_val > 1) 00259 { 00260 switch_1_state = 1; 00261 } 00262 else 00263 { 00264 switch_1_state = 0; 00265 } 00266 00267 // Check how many times switch 1 has been high 00268 // if it has been high more than twice, then switch 2 state = 1 00269 if (switch_2_val > 1) 00270 { 00271 switch_2_state = 1; 00272 } 00273 00274 else 00275 { 00276 switch_2_state = 0; 00277 } 00278 } 00279 00280 00281 00282 // Task 5: Read two analogue inputs (filtered) 00283 void Task5() 00284 { 00285 analogue_1_val = 0; // Reset variables 00286 analogue_2_val = 0; 00287 00288 // Takes four readings of each analogue input. Readings occure every 0.1ms 00289 // Because the analogue.read() function returns a value from 0 to 1, 00290 // we need to multiply the readings by 3.3 to cover 0V to 3.3V 00291 for(int i=0; i<4;i++) 00292 { 00293 analogue_1_val = analogue_1_val + (analogue_in_1*3.3); 00294 analogue_2_val = analogue_2_val + (analogue_in_2*3.3); 00295 wait_us(SampFreq); 00296 } 00297 00298 analogue_1_val = (analogue_1_val / 4); 00299 analogue_2_val = (analogue_2_val / 4); 00300 00301 analogue_1_int = analogue_1_val * 10; // Convert floating point into an integer to reduce display delay 00302 analogue_2_int = analogue_2_val * 10; 00303 00304 // This section of task 5 is used to take over part of task 8. 00305 // Since the LEDs pattern has to be incremented every 1.5s, the pattern is 00306 // incremented every 6 cycles, which correspond to 1.5s. 00307 if(BinEnable == 1) 00308 { 00309 IncCheck++; 00310 00311 if(IncCheck == 6) // Corresponds to 1.5s. Increment binary pattern 00312 { 00313 LEDs = BinCount; 00314 BinCount++; 00315 IncCheck = 0; 00316 00317 if (BinCount > 15) // Used to reset variable once maximum 4-bit binary value is reached 00318 { 00319 BinCount = 0; 00320 } 00321 } 00322 } 00323 } 00324 00325 00326 00327 // Task 6: Display analogue and digital values on LCD screen 00328 void Task6() 00329 { 00330 // lcd->cls(); // clear display (takes too long) 00331 lcd->locate(0,0); // set cursor to location (0,0) - top left corner 00332 lcd->printf("%d %d%d%d",analogue_1_int,analogue_2_int,switch_1_state,switch_2_state); 00333 } 00334 00335 00336 00337 // Task 7: Log values on SD card 00338 void Task7() 00339 { 00340 LogCount++; //Used to print the logging number in file. Starts from 1 00341 fprintf(fp, "Log: %d, Speed: %dHz, Switch_1: %d, Switch_2: %d, POT: %.2fVolts, LDR: %.2fVolts\n",LogCount,frequency,switch_1_state,switch_2_state,analogue_1_val,analogue_2_val); 00342 } 00343 00344 00345 00346 // Task 8: Show error message and light LEDs 00347 void Task8() 00348 { 00349 // If switch_1 = 1 and POT value > 3V, display error message 00350 if(switch_1_state == 1 && analogue_1_val > 3) 00351 { 00352 //lcd->cls(); // clear display 00353 lcd->locate(0,0); // set cursor to location (0,0) - top left corner 00354 lcd->printf(".ERREUR"); 00355 } 00356 00357 // If switch 2 is high, return a command to task 5 to do the incrementing pattern every 1.5 seconds 00358 if(switch_2_state == 1) 00359 { 00360 BinEnable = 1; 00361 } 00362 00363 // If switch 2 is low, stop sending a command to task 5 and light off LEDs 00364 else 00365 { 00366 LEDs = 0; 00367 BinEnable = 0; 00368 BinCount = 0; 00369 } 00370 } 00371 00372 00373 00374 // Stop function to stop cyclic executive and close log file 00375 void Stop() 00376 { 00377 ticker.detach(); 00378 fprintf(fp, "\n The program did nothing for %d ms, which corresponds to %d percent of the time \n",NoTask, NoTask/100); 00379 fprintf(fp, "\n PROGRAM STOPPED"); 00380 fclose(fp); 00381 00382 } 00383 00384 00385 00386 //===================================================================================== 00387 // Subroutines 00388 //===================================================================================== 00389 00390 // Wait for rising edge 00391 void WaitRisEdge() 00392 { 00393 // As soon as it gets high, the subroutine will end and the timer will start 00394 while(TTL == 0) 00395 { 00396 wait_us(SampFreq); 00397 } 00398 } 00399 00400 00401 // Wait for falling edge 00402 void WaitFalEdge() 00403 { 00404 // As soon as it gets low, the subroutine will end and the timer will start 00405 while(TTL == 1) 00406 { 00407 wait_us(SampFreq); 00408 } 00409 }
Generated on Thu Jul 14 2022 10:33:15 by
1.7.2
