counts digital frequency based on interrupt and timer, triggers on rising edge

Committer:
awmiller
Date:
Tue Aug 09 20:03:10 2016 +0000
Revision:
0:91a906dbf731
first edition;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
awmiller 0:91a906dbf731 1 #include "FrequencyCounter.h"
awmiller 0:91a906dbf731 2 #include <mbed.h>
awmiller 0:91a906dbf731 3
awmiller 0:91a906dbf731 4 #ifndef INF
awmiller 0:91a906dbf731 5 #define INF ((double)(1.0/0.0))
awmiller 0:91a906dbf731 6 #endif
awmiller 0:91a906dbf731 7
awmiller 0:91a906dbf731 8 /*
awmiller 0:91a906dbf731 9 * Class constructor initializes interrupt and starts rising edge triggering
awmiller 0:91a906dbf731 10 */
awmiller 0:91a906dbf731 11 FrequencyCounter::FrequencyCounter(PinName pin) : _cPin(pin){
awmiller 0:91a906dbf731 12 this->_cPin.rise(this,&FrequencyCounter::_irqs);
awmiller 0:91a906dbf731 13 this->_cPin.disable_irq(); //justin case
awmiller 0:91a906dbf731 14 this->_iircoef = 0.9f;
awmiller 0:91a906dbf731 15 this->_lastTime =0;
awmiller 0:91a906dbf731 16 this->_fq = 0;
awmiller 0:91a906dbf731 17 }
awmiller 0:91a906dbf731 18
awmiller 0:91a906dbf731 19 /*
awmiller 0:91a906dbf731 20 * Getter method for reading the averaged freqency
awmiller 0:91a906dbf731 21 */
awmiller 0:91a906dbf731 22 double FrequencyCounter::getFrequency() {
awmiller 0:91a906dbf731 23 return this->_fq;
awmiller 0:91a906dbf731 24 }
awmiller 0:91a906dbf731 25
awmiller 0:91a906dbf731 26 /*
awmiller 0:91a906dbf731 27 * Getter method for reading the averaged freqency
awmiller 0:91a906dbf731 28 */
awmiller 0:91a906dbf731 29 double FrequencyCounter::getTime() {
awmiller 0:91a906dbf731 30 return this->_lastTime;
awmiller 0:91a906dbf731 31 }
awmiller 0:91a906dbf731 32
awmiller 0:91a906dbf731 33 /*
awmiller 0:91a906dbf731 34 * Setter for modifying the coefficient of the averaging IIR filter
awmiller 0:91a906dbf731 35 * the IIR Coefficient is the fraction of old data to keep, typically 0.9
awmiller 0:91a906dbf731 36 * Incoming data is multiplied by (1 - coeff) and added to (coeff * old_data)
awmiller 0:91a906dbf731 37 */
awmiller 0:91a906dbf731 38 void FrequencyCounter::setIIRCoeff(double D) {
awmiller 0:91a906dbf731 39 this->_iircoef = D;
awmiller 0:91a906dbf731 40 }
awmiller 0:91a906dbf731 41
awmiller 0:91a906dbf731 42 /*
awmiller 0:91a906dbf731 43 * Starts the IRQ service
awmiller 0:91a906dbf731 44 */
awmiller 0:91a906dbf731 45 void FrequencyCounter::start() {
awmiller 0:91a906dbf731 46 this->_lastTime = 0;
awmiller 0:91a906dbf731 47 this->_cPin.enable_irq();
awmiller 0:91a906dbf731 48 this->_fq = 0.0f;
awmiller 0:91a906dbf731 49 this->_mtime.start();
awmiller 0:91a906dbf731 50 }
awmiller 0:91a906dbf731 51
awmiller 0:91a906dbf731 52 /*
awmiller 0:91a906dbf731 53 * Stops the IRQ service
awmiller 0:91a906dbf731 54 */
awmiller 0:91a906dbf731 55 void FrequencyCounter::stop() {
awmiller 0:91a906dbf731 56 this->_cPin.disable_irq(); //justin case
awmiller 0:91a906dbf731 57 this->_mtime.stop();
awmiller 0:91a906dbf731 58 }
awmiller 0:91a906dbf731 59
awmiller 0:91a906dbf731 60 /*
awmiller 0:91a906dbf731 61 * IRQ service (private) implements a simple IIR LPF
awmiller 0:91a906dbf731 62 */
awmiller 0:91a906dbf731 63 void FrequencyCounter::_irqs() {
awmiller 0:91a906dbf731 64 //written long-hand for clarity, should get optimized out
awmiller 0:91a906dbf731 65 double delta = (double)(this->_mtime.read_us());
awmiller 0:91a906dbf731 66 delta = delta/(10^6);
awmiller 0:91a906dbf731 67 double nfq = 1/delta;
awmiller 0:91a906dbf731 68 if(nfq == INF){
awmiller 0:91a906dbf731 69 nfq=0;
awmiller 0:91a906dbf731 70 }else if(nfq < 0.01){
awmiller 0:91a906dbf731 71 nfq = 0.01;
awmiller 0:91a906dbf731 72 }
awmiller 0:91a906dbf731 73 this->_fq = this->_fq*this->_iircoef + (1-this->_iircoef)*nfq; // basic LPF
awmiller 0:91a906dbf731 74 this->_mtime.reset();
awmiller 0:91a906dbf731 75 this->_lastTime = delta;
awmiller 0:91a906dbf731 76 }