Embedded Software Assignment 2

Dependencies:   MCP23017 WattBob_TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
usmb192
Date:
Fri May 27 15:33:42 2016 +0000
Commit message:
final public

Changed in this revision

MCP23017.lib Show annotated file Show diff for this revision Revisions of this file
WattBob_TextLCD.lib 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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 0131c822a391 MCP23017.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017.lib	Fri May 27 15:33:42 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/jimherd/code/MCP23017/#d57de266cf19
diff -r 000000000000 -r 0131c822a391 WattBob_TextLCD.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WattBob_TextLCD.lib	Fri May 27 15:33:42 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/jimherd/code/WattBob_TextLCD/#3b26cd028e85
diff -r 000000000000 -r 0131c822a391 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri May 27 15:33:42 2016 +0000
@@ -0,0 +1,260 @@
+/*******************************************************************************************
+*
+*    Cyclic Execution based Frequency Measurement ( Embedded Software Assignment 2 )
+*
+*                   a program that runs a cyclic execution demo
+*                       actions are for example
+*               frequency measurement and serial logging
+*
+*
+* @author Markus
+* @version 1.0
+* @lastupdate 02.03.2016 
+*                             
+*
+*******************************************************************************************/
+
+// ########
+// INCLUDES
+// ########
+
+#include "mbed.h"                                                   // mbed header file
+#include "MCP23017.h"                                               // include 16-bit parallel I/O header file
+#include "WattBob_TextLCD.h"                                        // include 2*16 character display header file
+#include "AnalogIn.h"                                               // include Analog communication
+#include <deque>                                                    // used for the avaraging
+
+// #######################
+// CONFIGURATION VARIABLES
+// #######################
+
+#define SAMPLE_FREQ_US 1
+#define TICKRATE_US 12500
+#define NYQUIST_CORR 2.002
+#define WATCHDOG_PULSE_TIME_MS 5
+
+// ###############################
+// ALL PORTS USED ARE DEFINED HERE
+// ###############################
+
+#define AnalogPort1 p17                                             // used for Analog Input 1
+#define AnalogPort2 p16                                             // used for Analog Input 2
+#define FrequencyPort p15                                           // used to measure frequency
+#define SwitchPort p5                                               // used for the error code switch
+#define WatchPort p6                                                // used for the watchdog pulse
+#define OnOffPort p7                                                // used for the on/off switch
+#define TaskExecPort p8                                             // used for the task execution pulse
+
+
+// ####################################
+// MISC VARIABLES (shouln't be changed)
+// ####################################
+
+MCP23017            *par_port;                                      // pointer to 16-bit parallel I/O object
+WattBob_TextLCD     *lcd;                                           // pointer to 2*16 chacater LCD object
+Serial              serpc(USBTX, USBRX);                            // serial usb connection tx, rx
+Ticker ticker;                                                      // our ticker that runs the main function
+
+DigitalIn dInFreq(FrequencyPort);                                   // Port for the frequency measurement
+DigitalIn dInSwitch(SwitchPort);                                    // Port for the switch
+DigitalOut dOutWatchd(WatchPort);                                   // Port for WatchDog pulse
+DigitalIn dInOnOff(OnOffPort);                                      // Port for the On/Off Switch
+DigitalOut dOutTaskExec(TaskExecPort);
+
+std::deque<float> AnalogDB1;                        
+std::deque<float> AnalogDB2;
+
+int tick_counter(0);                                                // used for counting the ticks / slots
+bool OnOffSwitchStatus(0);                                          // saving the last switch status
+int freq(0);                                                        // saving the last frequency status
+int error_last(9);                                                  // we init with an impossible error number only 0 and 3 are
+                                                                    // possible, using this we force an initialization
+                                                                    
+float avgAn1(0);                                                    // saving the last avarage of analog 1
+float avgAn2(0);                                                    // saving the last avarage of analog 2
+bool Switch1(0);                                                    // saving the last switch status
+
+DigitalOut ledd1(LED1);                                             
+DigitalOut ledd3(LED3);
+
+// ################################
+// FORWARD DECLARATION OF FUNCTIONS
+// ################################
+
+void SendPulse(int ms, DigitalOut pn);
+void tick();
+void printLCD(int& freq,bool& sw, float& avgAn1, float& avgAn2);
+void logTime(int TaskNumber);
+
+int MeasureFrequency(DigitalIn& freqIn,int samplingFreqUS);
+float ReadAnalogInAVG(std::deque<float>& db,PinName Port);
+int CheckError(bool& Switch1,float& avgAn1,float& avgAn2);
+
+/*
+========================================================================================
+=                                                                                      =
+=                       MAIN PROCEDURE - generating the Blocks                         =
+=                                                                                      =
+========================================================================================
+*/
+// ############################
+// the entrance for the program
+// ############################
+
+int main()
+{
+    serpc.baud(19200);                                              // setup the bautrate
+    serpc.printf("Init Software\r\n");
+    par_port = new MCP23017(p9, p10, 0x40);                         // initialise 16-bit I/O chip (0x40 = 64)
+    lcd = new WattBob_TextLCD(par_port);                            // initialise 2*26 char display
+    par_port->write_bit(1,BL_BIT);                                  // turn LCD backlight ON
+    lcd->cls();                                                     // clear display
+    lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
+    lcd->printf("f0000 S0");                                        // print labels on the lcd
+    lcd->locate(1,0);                                               
+    lcd->printf("a1 0.00  a2 0.00");
+    ticker.attach_us(&tick, TICKRATE_US);                           // attach the ticker to a procedure
+}
+
+// #########################
+// the main loop (as ticker)
+// #########################
+void tick()
+{
+    // use a timing pulse -> extra digi port -> everytime something happens -> sent pulse
+    
+    // tickcounter%interval==offset
+    if((tick_counter%80)==1) {
+        //every 1000 mS
+        freq = MeasureFrequency(dInFreq,SAMPLE_FREQ_US);            // measure the frequency
+
+    } else if((tick_counter%24)==2) {
+        //every 300 mS, check Switch1 (for error)
+        if (dInSwitch)                                              // check the switch status for later use
+            Switch1 = true;
+        else Switch1 = false;
+
+    } else if((tick_counter%24)==3) {
+        // (460 mS) now 300 mS, send watchdog pulse
+        SendPulse(WATCHDOG_PULSE_TIME_MS,dOutWatchd);               // send the watchdog pulse
+
+    } else if((tick_counter%32)==4) {
+        // every 400 mS
+        // EXECUTION SIGNAL!
+        SendPulse(10,dOutTaskExec);                                 // sending the execution signal
+        avgAn1 = ReadAnalogInAVG(AnalogDB1,AnalogPort1);            // reaning analog values
+        avgAn2 = ReadAnalogInAVG(AnalogDB2,AnalogPort2);            // ^^
+
+    } else if((tick_counter%160)==5) {
+        // every 2000 Ms
+        printLCD(freq,Switch1,avgAn1,avgAn2);                       // print to the lcd screen
+
+    } else if((tick_counter%64)==8) {
+        // every 800 mS
+        int error_current = CheckError(Switch1,avgAn1,avgAn2);
+        if (error_last!=error_current) {                            // we check if the error changed (safe to time )
+            if(!error_current) {                                    // we check if its zero
+                ledd1=1;
+                ledd3=0;
+            } else {                                                // else it must be 3
+                ledd1=0;
+                ledd3=1;
+            }
+            error_last=error_current;
+        }
+        
+    } else if((tick_counter%400)==9) {
+        // every 5000 mS - print to serial
+           serpc.printf("%i,%i%,%i,%i\r\n",freq,Switch1,(int)avgAn1,(int)avgAn2);
+
+    } else {
+        // in every other slot, check the on off switch
+        if(OnOffSwitchStatus!=dInOnOff) {                           // checking the on off switch
+            OnOffSwitchStatus = dInOnOff;                           // safe the last switch status
+            par_port->write_bit(OnOffSwitchStatus,BL_BIT);          // turn LCD backlight ON/OFF
+        }
+    }
+
+    tick_counter++;
+}
+
+/*
+========================================================================================
+=                                                                                      =
+=                                  FUNCTIONS BLOCK                                     =
+=                                                                                      =
+========================================================================================
+*/
+
+// #########################################################################################
+// prints to the lcd, only overwrites values that are necesarry to overwrite (safes some mS)
+// #########################################################################################
+void printLCD(int& freq,bool& sw, float& avgAn1, float& avgAn2)
+{
+    lcd->locate(0,1);
+    lcd->printf("%04i",freq);                                       // write the frequency to the lcd board
+    lcd->locate(0,7);
+    lcd->printf("%i",sw);                                           // write the switch value
+    lcd->locate(1,3);
+    lcd->printf("%.2f",avgAn1);                                     // write avarage analog value 1
+    lcd->locate(1,12);
+    lcd->printf("%.2f",avgAn2);                                     // write avarage analog value 2
+}
+
+// #################################################
+// checks the error status and returns it as integer
+// #################################################
+int CheckError(bool& Switch1,float& avgAn1,float& avgAn2)
+{
+    if(Switch1 && (avgAn1 > avgAn2))                                // if swicht1 AND averageAnalogValue1 > averageAnalogValue2
+        return 3;
+    return 0;
+}
+
+// ####################################################################
+// reads analog values and returns the average over the last 4 readings
+// ####################################################################
+float ReadAnalogInAVG(std::deque<float>& db,PinName Port)           // (we are using deque because you cant iterate over a queue)
+{
+    AnalogIn Ain(Port);
+    float sum(0);
+    if(db.size()>=4)                                                // if we already got 4 values, we have to
+        db.pop_front();                                             // make space by deleting the oldest value
+    db.push_back(Ain.read());                                       // safe a new reading
+    for(deque<float>::const_iterator i = db.begin(); i != db.end(); ++i)
+        sum+= *i;                                                   // calculate the average by iterating over the queue
+    return sum/db.size();
+}
+
+// ##################################################
+// used for sending a short pulse for ms Milliseconds
+// ##################################################
+void SendPulse(int ms, DigitalOut pn)
+{
+    pn = 1;                                                         // set the analog port high
+    wait_ms(ms);                                                    // wait for ms Milliseconds
+    pn = 0;                                                         // set the analog port low
+}
+
+// ###################################################
+// measures the frequency and returns an integer in Hz
+// ###################################################
+int MeasureFrequency(DigitalIn& freqIn,int samplingFreqUS)
+{
+    Timer timer;                                                    // timer used to time
+    if(!freqIn) {                                                   // if the edge is low
+        while(!freqIn)                                              // wait for the edge
+            wait_us(samplingFreqUS);                                // let the cpu do nothing meanwhile
+        timer.start();                                              // now we can start counting
+        while(freqIn)                                               // as long as the freq is high
+            wait_us(samplingFreqUS);
+    } else {                                                        // else.. it has to be 1
+        while(freqIn)                                               // wait for the edge
+            wait_us(samplingFreqUS);                                // let the cpu do nothing meanwhile
+        timer.start();                                              // now we can start counting
+        while(!freqIn)                                              // as long as the frequency is slow
+            wait_us(samplingFreqUS);                                // let the cpu do nothing
+    }
+    timer.stop();                                                   // stop the timer - measuring finished
+    return 1000000.0/(timer.read_us()*NYQUIST_CORR);                // Convert to period multiply by 1mil to get freq and correct by Nequ
+}
diff -r 000000000000 -r 0131c822a391 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri May 27 15:33:42 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/c0f6e94411f5
\ No newline at end of file