M L / Mbed 2 deprecated ES_Assignment_2_Pub

Dependencies:   MCP23017 WattBob_TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*******************************************************************************************
00002 *
00003 *    Cyclic Execution based Frequency Measurement ( Embedded Software Assignment 2 )
00004 *
00005 *                   a program that runs a cyclic execution demo
00006 *                       actions are for example
00007 *               frequency measurement and serial logging
00008 *
00009 *
00010 * @author Markus
00011 * @version 1.0
00012 * @lastupdate 02.03.2016 
00013 *                             
00014 *
00015 *******************************************************************************************/
00016 
00017 // ########
00018 // INCLUDES
00019 // ########
00020 
00021 #include "mbed.h"                                                   // mbed header file
00022 #include "MCP23017.h"                                               // include 16-bit parallel I/O header file
00023 #include "WattBob_TextLCD.h"                                        // include 2*16 character display header file
00024 #include "AnalogIn.h"                                               // include Analog communication
00025 #include <deque>                                                    // used for the avaraging
00026 
00027 // #######################
00028 // CONFIGURATION VARIABLES
00029 // #######################
00030 
00031 #define SAMPLE_FREQ_US 1
00032 #define TICKRATE_US 12500
00033 #define NYQUIST_CORR 2.002
00034 #define WATCHDOG_PULSE_TIME_MS 5
00035 
00036 // ###############################
00037 // ALL PORTS USED ARE DEFINED HERE
00038 // ###############################
00039 
00040 #define AnalogPort1 p17                                             // used for Analog Input 1
00041 #define AnalogPort2 p16                                             // used for Analog Input 2
00042 #define FrequencyPort p15                                           // used to measure frequency
00043 #define SwitchPort p5                                               // used for the error code switch
00044 #define WatchPort p6                                                // used for the watchdog pulse
00045 #define OnOffPort p7                                                // used for the on/off switch
00046 #define TaskExecPort p8                                             // used for the task execution pulse
00047 
00048 
00049 // ####################################
00050 // MISC VARIABLES (shouln't be changed)
00051 // ####################################
00052 
00053 MCP23017            *par_port;                                      // pointer to 16-bit parallel I/O object
00054 WattBob_TextLCD     *lcd;                                           // pointer to 2*16 chacater LCD object
00055 Serial              serpc(USBTX, USBRX);                            // serial usb connection tx, rx
00056 Ticker ticker;                                                      // our ticker that runs the main function
00057 
00058 DigitalIn dInFreq(FrequencyPort);                                   // Port for the frequency measurement
00059 DigitalIn dInSwitch(SwitchPort);                                    // Port for the switch
00060 DigitalOut dOutWatchd(WatchPort);                                   // Port for WatchDog pulse
00061 DigitalIn dInOnOff(OnOffPort);                                      // Port for the On/Off Switch
00062 DigitalOut dOutTaskExec(TaskExecPort);
00063 
00064 std::deque<float> AnalogDB1;                        
00065 std::deque<float> AnalogDB2;
00066 
00067 int tick_counter(0);                                                // used for counting the ticks / slots
00068 bool OnOffSwitchStatus(0);                                          // saving the last switch status
00069 int freq(0);                                                        // saving the last frequency status
00070 int error_last(9);                                                  // we init with an impossible error number only 0 and 3 are
00071                                                                     // possible, using this we force an initialization
00072                                                                     
00073 float avgAn1(0);                                                    // saving the last avarage of analog 1
00074 float avgAn2(0);                                                    // saving the last avarage of analog 2
00075 bool Switch1(0);                                                    // saving the last switch status
00076 
00077 DigitalOut ledd1(LED1);                                             
00078 DigitalOut ledd3(LED3);
00079 
00080 // ################################
00081 // FORWARD DECLARATION OF FUNCTIONS
00082 // ################################
00083 
00084 void SendPulse(int ms, DigitalOut pn);
00085 void tick();
00086 void printLCD(int& freq,bool& sw, float& avgAn1, float& avgAn2);
00087 void logTime(int TaskNumber);
00088 
00089 int MeasureFrequency(DigitalIn& freqIn,int samplingFreqUS);
00090 float ReadAnalogInAVG(std::deque<float>& db,PinName Port);
00091 int CheckError(bool& Switch1,float& avgAn1,float& avgAn2);
00092 
00093 /*
00094 ========================================================================================
00095 =                                                                                      =
00096 =                       MAIN PROCEDURE - generating the Blocks                         =
00097 =                                                                                      =
00098 ========================================================================================
00099 */
00100 // ############################
00101 // the entrance for the program
00102 // ############################
00103 
00104 int main()
00105 {
00106     serpc.baud(19200);                                              // setup the bautrate
00107     serpc.printf("Init Software\r\n");
00108     par_port = new MCP23017(p9, p10, 0x40);                         // initialise 16-bit I/O chip (0x40 = 64)
00109     lcd = new WattBob_TextLCD(par_port);                            // initialise 2*26 char display
00110     par_port->write_bit(1,BL_BIT);                                  // turn LCD backlight ON
00111     lcd->cls();                                                     // clear display
00112     lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
00113     lcd->printf("f0000 S0");                                        // print labels on the lcd
00114     lcd->locate(1,0);                                               
00115     lcd->printf("a1 0.00  a2 0.00");
00116     ticker.attach_us(&tick, TICKRATE_US);                           // attach the ticker to a procedure
00117 }
00118 
00119 // #########################
00120 // the main loop (as ticker)
00121 // #########################
00122 void tick()
00123 {
00124     // use a timing pulse -> extra digi port -> everytime something happens -> sent pulse
00125     
00126     // tickcounter%interval==offset
00127     if((tick_counter%80)==1) {
00128         //every 1000 mS
00129         freq = MeasureFrequency(dInFreq,SAMPLE_FREQ_US);            // measure the frequency
00130 
00131     } else if((tick_counter%24)==2) {
00132         //every 300 mS, check Switch1 (for error)
00133         if (dInSwitch)                                              // check the switch status for later use
00134             Switch1 = true;
00135         else Switch1 = false;
00136 
00137     } else if((tick_counter%24)==3) {
00138         // (460 mS) now 300 mS, send watchdog pulse
00139         SendPulse(WATCHDOG_PULSE_TIME_MS,dOutWatchd);               // send the watchdog pulse
00140 
00141     } else if((tick_counter%32)==4) {
00142         // every 400 mS
00143         // EXECUTION SIGNAL!
00144         SendPulse(10,dOutTaskExec);                                 // sending the execution signal
00145         avgAn1 = ReadAnalogInAVG(AnalogDB1,AnalogPort1);            // reaning analog values
00146         avgAn2 = ReadAnalogInAVG(AnalogDB2,AnalogPort2);            // ^^
00147 
00148     } else if((tick_counter%160)==5) {
00149         // every 2000 Ms
00150         printLCD(freq,Switch1,avgAn1,avgAn2);                       // print to the lcd screen
00151 
00152     } else if((tick_counter%64)==8) {
00153         // every 800 mS
00154         int error_current = CheckError(Switch1,avgAn1,avgAn2);
00155         if (error_last!=error_current) {                            // we check if the error changed (safe to time )
00156             if(!error_current) {                                    // we check if its zero
00157                 ledd1=1;
00158                 ledd3=0;
00159             } else {                                                // else it must be 3
00160                 ledd1=0;
00161                 ledd3=1;
00162             }
00163             error_last=error_current;
00164         }
00165         
00166     } else if((tick_counter%400)==9) {
00167         // every 5000 mS - print to serial
00168            serpc.printf("%i,%i%,%i,%i\r\n",freq,Switch1,(int)avgAn1,(int)avgAn2);
00169 
00170     } else {
00171         // in every other slot, check the on off switch
00172         if(OnOffSwitchStatus!=dInOnOff) {                           // checking the on off switch
00173             OnOffSwitchStatus = dInOnOff;                           // safe the last switch status
00174             par_port->write_bit(OnOffSwitchStatus,BL_BIT);          // turn LCD backlight ON/OFF
00175         }
00176     }
00177 
00178     tick_counter++;
00179 }
00180 
00181 /*
00182 ========================================================================================
00183 =                                                                                      =
00184 =                                  FUNCTIONS BLOCK                                     =
00185 =                                                                                      =
00186 ========================================================================================
00187 */
00188 
00189 // #########################################################################################
00190 // prints to the lcd, only overwrites values that are necesarry to overwrite (safes some mS)
00191 // #########################################################################################
00192 void printLCD(int& freq,bool& sw, float& avgAn1, float& avgAn2)
00193 {
00194     lcd->locate(0,1);
00195     lcd->printf("%04i",freq);                                       // write the frequency to the lcd board
00196     lcd->locate(0,7);
00197     lcd->printf("%i",sw);                                           // write the switch value
00198     lcd->locate(1,3);
00199     lcd->printf("%.2f",avgAn1);                                     // write avarage analog value 1
00200     lcd->locate(1,12);
00201     lcd->printf("%.2f",avgAn2);                                     // write avarage analog value 2
00202 }
00203 
00204 // #################################################
00205 // checks the error status and returns it as integer
00206 // #################################################
00207 int CheckError(bool& Switch1,float& avgAn1,float& avgAn2)
00208 {
00209     if(Switch1 && (avgAn1 > avgAn2))                                // if swicht1 AND averageAnalogValue1 > averageAnalogValue2
00210         return 3;
00211     return 0;
00212 }
00213 
00214 // ####################################################################
00215 // reads analog values and returns the average over the last 4 readings
00216 // ####################################################################
00217 float ReadAnalogInAVG(std::deque<float>& db,PinName Port)           // (we are using deque because you cant iterate over a queue)
00218 {
00219     AnalogIn Ain(Port);
00220     float sum(0);
00221     if(db.size()>=4)                                                // if we already got 4 values, we have to
00222         db.pop_front();                                             // make space by deleting the oldest value
00223     db.push_back(Ain.read());                                       // safe a new reading
00224     for(deque<float>::const_iterator i = db.begin(); i != db.end(); ++i)
00225         sum+= *i;                                                   // calculate the average by iterating over the queue
00226     return sum/db.size();
00227 }
00228 
00229 // ##################################################
00230 // used for sending a short pulse for ms Milliseconds
00231 // ##################################################
00232 void SendPulse(int ms, DigitalOut pn)
00233 {
00234     pn = 1;                                                         // set the analog port high
00235     wait_ms(ms);                                                    // wait for ms Milliseconds
00236     pn = 0;                                                         // set the analog port low
00237 }
00238 
00239 // ###################################################
00240 // measures the frequency and returns an integer in Hz
00241 // ###################################################
00242 int MeasureFrequency(DigitalIn& freqIn,int samplingFreqUS)
00243 {
00244     Timer timer;                                                    // timer used to time
00245     if(!freqIn) {                                                   // if the edge is low
00246         while(!freqIn)                                              // wait for the edge
00247             wait_us(samplingFreqUS);                                // let the cpu do nothing meanwhile
00248         timer.start();                                              // now we can start counting
00249         while(freqIn)                                               // as long as the freq is high
00250             wait_us(samplingFreqUS);
00251     } else {                                                        // else.. it has to be 1
00252         while(freqIn)                                               // wait for the edge
00253             wait_us(samplingFreqUS);                                // let the cpu do nothing meanwhile
00254         timer.start();                                              // now we can start counting
00255         while(!freqIn)                                              // as long as the frequency is slow
00256             wait_us(samplingFreqUS);                                // let the cpu do nothing
00257     }
00258     timer.stop();                                                   // stop the timer - measuring finished
00259     return 1000000.0/(timer.read_us()*NYQUIST_CORR);                // Convert to period multiply by 1mil to get freq and correct by Nequ
00260 }