Embedded Software Assignment 2
Dependencies: MCP23017 WattBob_TextLCD mbed
Revision 0:0131c822a391, committed 2016-05-27
- Comitter:
- usmb192
- Date:
- Fri May 27 15:33:42 2016 +0000
- Commit message:
- final public
Changed in this revision
--- /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
--- /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
--- /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
+}
--- /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