Example software for a Cyclic Executive
Dependencies: MCP23017 SDFileSystem WattBob_TextLCD mbed
Revision 10:c0531edf4850, committed 2016-03-02
- Comitter:
- sk398
- Date:
- Wed Mar 02 13:38:27 2016 +0000
- Parent:
- 9:46408a8dea0c
- Commit message:
- Final version - all operational
Changed in this revision
--- a/Tasks.cpp Wed Mar 02 09:38:47 2016 +0000 +++ b/Tasks.cpp Wed Mar 02 13:38:27 2016 +0000 @@ -9,17 +9,9 @@ Date: February 2016 - Function: This - - Version: 1.0 - - Version History - --------------- - - 1.1 rgdfgdfgdfggdfgdg - - 1.0 gdgddfdddgd - + Function: This code defines the operations of all of the + methods, or tasks used by the cyclic executive + ##################################################################### */ #include "mbed.h" @@ -28,37 +20,81 @@ /* ==================================== Task 1 ==================================== */ Task1::Task1(PinName squareWaveInPin) { + // Construct new DigitalIn object using the pin number provided _squareWaveIn = new DigitalIn(squareWaveInPin); } void Task1::MeasureFrequency() { - _Task1Timer.start(); - _squareWaveIn -> rise(this,&Task1::StopCounter); -} - -void Task1::StopCounter() -{ + // If pulse is initially low, wait until rising edge before starting timer + if(_squareWaveIn -> read() == LOW) + { + while(_squareWaveIn -> read() == LOW) + { + wait_us(SAMPLE_FREQ); + } + + _Task1Timer.start(); + + // Once timer has started, wait until falling edge before breaking and + // stopping timer + while(_squareWaveIn -> read() == HIGH) + { + wait_us(SAMPLE_FREQ); + } + } + + // If pulse is initially high, wait until falling edge before starting timer + else if(_squareWaveIn -> read()== HIGH) + { + while(_squareWaveIn -> read() == HIGH) + { + wait_us(SAMPLE_FREQ); + } + + _Task1Timer.start(); + + // Once timer has started, wait until rising edge before breaking and + // stopping timer + while(_squareWaveIn -> read() == LOW) + { + wait_us(SAMPLE_FREQ); + } + } + + // Stop timer after breaking while loop conditions _Task1Timer.stop(); - measuredFrequency = _Task1Timer.read_us(); + + // Calculate frequency from timer (either high or low time) + // do this by multiplying the time by 2 (high + low time) and dividing it, + // converting it to a frequency + // Store frequency in private class field + Task1::measuredFrequency = (1000000/(2*_Task1Timer.read_us())); + + // Reset timer _Task1Timer.reset(); + } int Task1::ReadFrequency() { - _squareWaveIn -> rise(this,&Task1::MeasureFrequency); + // Run private method to calculate the frequency + MeasureFrequency(); + // Return private field showing the newest frequency calculation return measuredFrequency; } /* ==================================== Task 2 ==================================== */ Task2::Task2(PinName digitalInCheckPin) { + //Construct new DigitalIn object from provided pin _digitalInCheck = new DigitalIn(digitalInCheckPin); } bool Task2::digitalInState() { + // Check state of pin, returning a TRUE if high, false if LOW if(_digitalInCheck -> read()) { return TRUE; @@ -73,11 +109,13 @@ /* ==================================== Task 3 ==================================== */ Task3::Task3(PinName WatchdogPin) { + // Construct new DigitalOut object using provided pin _Watchdog = new DigitalOut(WatchdogPin); } void Task3::OutputWatchdogPulse() { + // Produce a 15ms pulse when method called _Watchdog -> write(HIGH); wait_ms(WATCHDOG_PULSE_WIDTH); _Watchdog -> write(LOW); @@ -87,41 +125,44 @@ /* ==================================== Task 4 ==================================== */ Task4::Task4(PinName Analog1Pin,PinName Analog2Pin) { + // Construct new AnalogIn objects from provided pins _AnalogIn1 = new AnalogIn(Analog1Pin); _AnalogIn2 = new AnalogIn(Analog2Pin); } float *Task4::returnAnalogReadings() { + // Declare local scope fields to retain current totals float readBuffer_1 = 0.0; float readBuffer_2 = 0.0; - - float outputBuffer[2]; - -// outputBuffer[0] = _AnalogIn1 -> read(); -// outputBuffer[1] = _AnalogIn2 -> read(); + // Read 4 samples from AnalogIn pins for(int readCount = 0;readCount < NUM_ANALOG_SAMPLES; readCount++) { - readBuffer_1 += ((_AnalogIn1 -> read())*3.3); -// printf("Buffer 1 %f\r\n",readBuffer_1); - readBuffer_2 += ((_AnalogIn2 -> read())*3.3); -// printf("Buffer 2 %f\r\n",readBuffer_2); + // Add to readBuffer with new weighted reading. + // 3.3v due to supply voltage + readBuffer_1 += ((_AnalogIn1 -> read())*V_SUPPLY); + readBuffer_2 += ((_AnalogIn2 -> read())*V_SUPPLY); } + // Construct local buffer + float outputBuffer[2]; + + // Construct elements in outputBuffer array as averaged sample outputBuffer[0] = readBuffer_1/NUM_ANALOG_SAMPLES; -// printf("outputBuffer[0] %f\r\n",outputBuffer[0]); outputBuffer[1] = readBuffer_2/NUM_ANALOG_SAMPLES; -// printf("outputBuffer[1] %f\r\n",outputBuffer[1]); + // Construct pointer to return the initial element of the outputBuffer float *outputBufferPtr =&outputBuffer[0]; - + + // Return pointer to first element of outputBuffer return outputBufferPtr; } /* ==================================== Task 5 ==================================== */ Task5::Task5(PinName sda, PinName scl, int address) { + // Declare and initialise the LCD display _par_port = new MCP23017(sda,scl,address); _lcd = new WattBob_TextLCD(_par_port); _par_port -> write_bit(1,BL_BIT); @@ -133,6 +174,7 @@ float task4Channel1, float task4Channel2 ) { + // Print standard expression using input fields _lcd -> cls(); _lcd -> locate(0,0); _lcd -> printf("F-%4dHz S1-%d E%d",task1Param,task2Param,errorState); @@ -143,10 +185,16 @@ /* ==================================== Task 6 ==================================== */ int Task6::updateErrorCode(int switch_1, float analog1, float analog2) { - if(switch_1 == 1 && (analog1 > analog2)) - return ERROR_CODE_CDTN_MET; + // Using input fields, conduct a logical equation7 + // returning CDTN_MET when true, CDTN_FAIL when false + if(switch_1 == HIGH && (analog1 > analog2)) + { + return ERROR_CODE_CDTN_MET; + } else - return ERROR_CODE_CDTN_FAIL; + { + return ERROR_CODE_CDTN_FAIL; + } } /* ==================================== Task 5 ==================================== */ @@ -157,19 +205,26 @@ const char *SDName, const char *dir ) { + // Construct new SDFileSystem object _sd = new SDFileSystem(mosi,miso,sck,cs, SDName); + + // Call private method to create default directory makeDirectory(dir); } void Task7::makeDirectory(const char *dir) { + // Create directory onto sd card mkdir(dir,0777); } int Task7::openFile(const char *dirFile,const char *accessType) { - fp = fopen(dirFile,accessType); - if(fp == NULL) + // Create pointer to FILE object + Task7::fp = fopen(dirFile,accessType); + + // If failed to open file, return 1, indicating error, else return 0 + if(Task7::fp == NULL) { return 1; } @@ -178,10 +233,12 @@ void Task7::writeData(const char *dataStream) { - fprintf(fp,dataStream); + // Print Stream of data to FILE object fp + fprintf(Task7::fp,dataStream); } void Task7::closeFile() { - fclose(fp); + // Close file located at fp + fclose(Task7::fp); } \ No newline at end of file
--- a/Tasks.h Wed Mar 02 09:38:47 2016 +0000 +++ b/Tasks.h Wed Mar 02 13:38:27 2016 +0000 @@ -9,17 +9,11 @@ Date: February 2016 - Function: This - - Version: 1.0 - - Version History - --------------- - - 1.1 rgdfgdfgdfggdfgdg - - 1.0 gdgddfdddgd - + Function: This file contains the function prototypes for the + included classes and methods. It also details some + constants used within the program and includes AUX + files, for instance the LCD system and the SD card. + ##################################################################### */ #ifndef _TASKS_H_ @@ -35,19 +29,20 @@ // Global definitions #define HIGH 1 #define LOW 0 - #define TRUE 1 #define FALSE 0 // Task 1 definitions -#define WATCHDOG_PULSE_WIDTH 15 // ms - +#define SAMPLE_FREQ 1 + // Task 2 definitions // Task 3 definitions +#define WATCHDOG_PULSE_WIDTH 15 // ms // Task 4 definitions #define NUM_ANALOG_SAMPLES 4.0 +#define V_SUPPLY 3.3 // Task 5 definitions #define BACK_LIGHT_ON(INTERFACE) INTERFACE->write_bit(1,BL_BIT) @@ -65,21 +60,26 @@ class Task1 { public: + // Public constructer method Task1(PinName squareWaveInPin); + + // Public method which initiates and returns a frequency measurement int ReadFrequency(); private: + // Private Timer object used to count the high or low time of input signal Timer _Task1Timer; + // Private method which contains the logic to measure frequency void MeasureFrequency(); - void StopCounter(); - - volatile int measuredFrequency; - InterruptIn *_squareWaveIn; - + // Private and volatile field contains most recent frequency + // Volatile to avoid the compiler modifying it for any reason + volatile int measuredFrequency; + protected: - + // Pointer to DigitalIn object + DigitalIn *_squareWaveIn; }; @@ -88,15 +88,18 @@ class Task2 { public: + // Public constructer method Task2(PinName digitalInCheckPin); + + // Public method to return the state of the DigitalIn pin bool digitalInState(); private: protected: + // Pointer to DigitalIn Object DigitalIn *_digitalInCheck; - }; @@ -105,15 +108,18 @@ class Task3 { public: + // Public constructer method Task3(PinName WatchdogPin); + + // Public method to output watchdog pulse opon calling method void OutputWatchdogPulse(); private: protected: + // Pointer to DigitalOut Object DigitalOut *_Watchdog; - }; @@ -122,16 +128,20 @@ class Task4 { public: + // Public constructer method Task4(PinName Analog1Pin,PinName Analog2Pin); + + // Public method to return pointer to array containing + // the filtered analog results, increment pointer once for both results float *returnAnalogReadings(); private: protected: + // Pointers to AnalogIn channels AnalogIn *_AnalogIn1; AnalogIn *_AnalogIn2; - }; //* ==================================== Task 5 ==================================== */ @@ -139,7 +149,10 @@ class Task5 { public: + // Public constructer method Task5(PinName sda, PinName scl, int address); + + // Public method to update display using input values from other tasks void updateDisplay( int task1Param, int task2Param, int errorState, @@ -150,9 +163,9 @@ protected: + // Pointers to required LCD objects MCP23017 *_par_port; WattBob_TextLCD *_lcd; - }; ///* ==================================== Task 6 ==================================== */ @@ -160,6 +173,7 @@ class Task6 { public: + // Public method to calculate condition of error state int updateErrorCode(int switch_1, float analog1, float analog2); private: @@ -175,22 +189,32 @@ class Task7 { public: + // Public constructer method Task7( PinName mosi, PinName miso, PinName sck, PinName cs, const char* SDName, const char *dir ); - + + // Public method to output Stream of data to open FILE void writeData(const char *dataStream); + + // Public method to open FILE int openFile(const char *dirFile, const char *accessType); + + // Public method to close FILE void closeFile(); private: + // Private method to construct a new directory on SD void makeDirectory(const char *dir); protected: + // Pointer to SDFileSystem object SDFileSystem *_sd; + + // Pointer to FILE object FILE *fp; };
--- a/main.cpp Wed Mar 02 09:38:47 2016 +0000 +++ b/main.cpp Wed Mar 02 13:38:27 2016 +0000 @@ -9,17 +9,14 @@ Date: February 2016 - Function: This - - Version: 1.0 + Function: This is the main runner containing the Cyclic executive + There are 7 defined tasks and several Auxillary components + which are logically ran periodically at their required time + by a Cyclic Executive sequencer. + Ticks, or slots, to this Cyclic Executive are provided by + a ticker ever 25ms, and then using logical expressions, the + correct task is initiated and allocated the required time. - Version History - --------------- - - 1.1 rgdfgdfgdfggdfgdg - - 1.0 gdgddfdddgd - ##################################################################### */ #include "mbed.h" @@ -40,10 +37,18 @@ // Cyclic Executive Objects and Declerations // ============================================================================ DigitalOut ErrorLED(LED1); // Error Indicating LED -DigitalOut LenPin(p21); // Pulse Pin -DigitalIn SDRemoval(p18); // Switch state to indicate to remove SD -Timer BusyWait; // Wasted time Timer +DigitalOut LenPin(p25); // Pulse Pin +DigitalIn SDRemoval(p18); // Switch state to indicate remove SD Ticker CyclicTicker; // Ticker object to cycle tasks +Timer stampTime; // Timer to stamp the time between logs + +// NOTE THE FOLLOWING ARE NOT ESSENTIAL TO THE OPERATION OF THIS CYCLIC EXECUTIVE +Timer task1t; // Timer to calculate task1 timing +Timer task2t; // Timer to calculate task2 timing +Timer task3t; // Timer to calculate task3 timing +Timer task4t; // Timer to calculate task4 timing +Timer task5t; // Timer to calculate task5 timing +Timer task6t; // Timer to calculate task6 timing // ============================================================================ // Global Data Parameters used in Cyclic Executive @@ -51,6 +56,9 @@ // Counter to record the number of ticks went through by the Cyclic Executive int cyclicTicks = 1; +// Flag variable to switch priority between Tasks 2 and 3 +int taskNum = 2; + // Global parameter storing the most up to date value of the return from Task 1 volatile int task1Frequency; @@ -66,9 +74,6 @@ // Char array to store the concatenated string for output onto the SD Card char logData[50]; -int slotCounter = 0; -int taskNum = 2; - // ============================================================================ // Cyclic Executive Function Prototypes // ============================================================================ @@ -78,7 +83,7 @@ // Main Execution Program // ============================================================================ int main() { - + // Attempt to open SD file // If open failed, do not run Cyclic Exec if(!task7.openFile("/SD/A2/test.csv","a")) @@ -117,23 +122,144 @@ #define TASK6_TICKS 32 #define TASK7_TICKS 200 -#define HIGH 1 - -Timer stampTime; -Timer task1t; -Timer task2t; -Timer task3t; -Timer task4t; -Timer task5t; -Timer task6t; - void CyclicExec() { + // When called, increment cyclicTicks cyclicTicks++; + + // Run every 1 second (should be 40 ticks, but tuned to 38 through testing) + if(cyclicTicks % 38 == 0) + { + // ---------- Can be removed --------- + task1t.stop(); + printf("T1 %d\r\n",task1t.read_ms()); + // ----------------------------------- + + // Run Task1 + LenPin = 1; + task1Frequency = task1.ReadFrequency(); + LenPin = 0; + + // ---------- Can be removed --------- + task1t.reset(); + task1t.start(); + // ----------------------------------- + } + + // Run every 300ms (should be 12 ticks, but logic dictates double the frequency) + if(cyclicTicks % 6 == 0) + { + // If flag taskNum is assigned to run Task2 + if(taskNum == 2) + { + + // ---------- Can be removed --------- + task2t.stop(); + printf("T2 %d\r\n",task2t.read_ms()); + // ----------------------------------- + + // Run Task 2 + task2SwitchState = task2_switch1.digitalInState(); + + // Set flag to run Task 3 on next iteration + taskNum = 3; + + // ---------- Can be removed --------- + task2t.reset(); + task2t.start(); + // ----------------------------------- + } + + // If flag taskNum is assigned to run Task3 + else if(taskNum == 3) + { + // ---------- Can be removed --------- + task3t.stop(); + printf("T3 %d\r\n",task3t.read_ms()); + // ----------------------------------- + + + // Run Task3 + task3.OutputWatchdogPulse(); + + // Set flag to run Task2 on next iteration + taskNum = 2; + + // ---------- Can be removed --------- + task3t.reset(); + task3t.start(); + // ----------------------------------- + } + } + + // Run every 400ms (16 ticks) + if(cyclicTicks % 16 == 0) + { + // ---------- Can be removed --------- + task4t.stop(); + printf("T4 %d\r\n",task4t.read_ms()); + // ----------------------------------- + + // Run Task4 + float *analogReading = task4.returnAnalogReadings(); + task4AnalogChannels[0] = *(analogReading); + task4AnalogChannels[1]= *(analogReading+1); + + // ---------- Can be removed --------- + task4t.reset(); + task4t.start(); + // ----------------------------------- + } + + // Run every 2 seconds (should be 80 ticks, but tuned to 84 through testing) + if(cyclicTicks % 84 == 0) + { + // ---------- Can be removed --------- + task5t.stop(); + printf("T5 %1.2f\r\n",task5t.read()); + // ----------------------------------- + + // Run Task5 + task5.updateDisplay( task1Frequency, + task2SwitchState, + task6ErrorState, + task4AnalogChannels[0], + task4AnalogChannels[1] ); + + // ---------- Can be removed --------- + task5t.reset(); + task5t.start(); + // ----------------------------------- + } + + // Run every 800ms (32 ticks) + if(cyclicTicks % 32 == 0) + { + // ---------- Can be removed --------- + task6t.stop(); + printf("T6 %d\r\n",task6t.read_ms()); + // ----------------------------------- + + // Run Task6 + task6ErrorState = task6.updateErrorCode( task2SwitchState, + task4AnalogChannels[0], + task4AnalogChannels[1] ); + + // ---------- Can be removed --------- + task6t.reset(); + task6t.start(); + // ----------------------------------- + } + + // Run every 5 seconds (200 ticks) if(cyclicTicks % 200 == 0) { + // ---------- Can be removed --------- + printf("T7\r\n"); + // ----------------------------------- + + // Run Task7 stampTime.stop(); - printf("T7\r\n"); int a = sprintf( logData,"Time=%1.2f,Freq=%d,SW1=%d,A1=%1.3f,A2=%1.3f\n", stampTime.read(), task1Frequency, @@ -141,81 +267,19 @@ task4AnalogChannels[0], task4AnalogChannels[1] ); task7.writeData(logData); + + // ---------- Can be removed --------- stampTime.reset(); stampTime.start(); - } - - if(cyclicTicks % 84 == 0) - { - task5t.stop(); - printf("T5 %1.2f\r\n",task5t.read()); - task5.updateDisplay( task1Frequency, - task2SwitchState, - task6ErrorState, - task4AnalogChannels[0], - task4AnalogChannels[1] ); - task5t.reset(); - task5t.start(); + // ----------------------------------- } - if(cyclicTicks % 38 == 0) - { - task1t.stop(); - printf("T1 %d\r\n",task1t.read_ms()); - task1Frequency = task1.ReadFrequency(); - task1t.reset(); - task1t.start(); - } - - if(cyclicTicks % 32 == 0) - { - task6t.stop(); - printf("T6 %d\r\n",task6t.read_ms()); - task6ErrorState = task6.updateErrorCode( task2SwitchState, - task4AnalogChannels[0], - task4AnalogChannels[1] ); - task6t.reset(); - task6t.start(); - } - - if(cyclicTicks % 16 == 0) - { - task4t.stop(); - printf("T4 %d\r\n",task4t.read_ms()); - float *analogReading = task4.returnAnalogReadings(); - task4AnalogChannels[0] = *(analogReading); - task4AnalogChannels[1]= *(analogReading+1); - task4t.reset(); - task4t.start(); - } - - if(cyclicTicks % 6 == 0) - { - if(taskNum == 2) - { - task2t.stop(); - printf("T2 %d\r\n",task2t.read_ms()); - task2SwitchState = task2_switch1.digitalInState(); - taskNum = 3; - task2t.reset(); - task2t.start(); - } - else if(taskNum == 3) - { - task3t.stop(); - printf("T3 %d\r\n",task3t.read_ms()); - task3.OutputWatchdogPulse(); - taskNum = 2; - task3t.reset(); - task3t.start(); - } - } - + // If SDRemoval Input is high, close FILE and detach the Ticker if(SDRemoval == HIGH) { printf("SD Removed"); task7.closeFile(); - CyclicTicker.detatch(); + CyclicTicker.detach(); } }