Example software for a Cyclic Executive

Dependencies:   MCP23017 SDFileSystem WattBob_TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
sk398
Date:
Wed Mar 02 13:38:27 2016 +0000
Parent:
9:46408a8dea0c
Commit message:
Final version - all operational

Changed in this revision

Tasks.cpp Show annotated file Show diff for this revision Revisions of this file
Tasks.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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();
     }
 }