Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MCP23017 WattBob_TextLCD mbed
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 }
Generated on Tue Aug 9 2022 21:44:24 by
1.7.2