Measurement of low frequencys based on timing between pulses

Dependents:   Energy_Meter_S0_Example

Pulses.cpp

Committer:
jocis
Date:
2012-11-08
Revision:
3:36dd0d59fdc8
Parent:
2:fc21262db17a

File content as of revision 3:36dd0d59fdc8:

#include "Pulses.h"

//////////////////////////////////////////////////////////////////////////////////

Pulses::Pulses(PinName inPin, PulseType type, unsigned int timeout, unsigned int counter) : _in(inPin) {
    _timer.reset();
    _timer.start();
    
    _lastTimer = 0;
    _ActTime = 0;
    _MinTime = 0;
    _MaxTime = 0;
    _AvrTimeSum = 0;
    _AvrTimeCount = 0;
    _Counter = counter;
    _Factor = 1.0f;
    _bFirst = true;
    
    if ( timeout > 900 ) timeout = 900;   // not more than 15 minutes
    _Timeout = timeout;
    _TimeoutCount = 0;
    
   
    _type = type;
    if ( type & RISE ) {
        _in.rise(this, &Pulses::callback_in);
        _in.mode(PullDown);
    }
    if ( type & FALL ) {
        _in.fall(this, &Pulses::callback_in);
        _in.mode(PullUp);
    }
        
    _timeout.attach(this, &Pulses::callback_timeout, 1);
}

//////////////////////////////////////////////////////////////////////////////////

float Pulses::getAct() {
    if ( _ActTime == 0 ) return 0.0f;
    
    return 1000000.0f * _Factor / (float)_ActTime;
}

//////////////////////////////////////////////////////////////////////////////////

float Pulses::getAverage() {
    unsigned int avrTimeSum = 0;
    unsigned int avrTimeCount = 0;

    __disable_irq();    // Disable Interrupts for atomic copy
    avrTimeSum = _AvrTimeSum;
    avrTimeCount = _AvrTimeCount;
    _AvrTimeSum = 0;
    _AvrTimeCount = 0;
    __enable_irq();     // Enable Interrupts

    if ( avrTimeCount == 0 ) return -1.0f;
    
    return 1000000.0f * _Factor / ( (float)avrTimeSum / (float)avrTimeCount );
}

//////////////////////////////////////////////////////////////////////////////////

void Pulses::get(float *pAverage, float *pMin, float *pMax, float *pSum) {
    unsigned int minTime = 0;
    unsigned int maxTime = 0;
    unsigned int avrTimeSum = 0;
    unsigned int avrTimeCount = 0;

    __disable_irq();    // Disable Interrupts for atomic copy
    minTime = _MinTime;
    maxTime = _MaxTime;
    avrTimeSum = _AvrTimeSum;
    avrTimeCount = _AvrTimeCount;
    _MinTime = 0;
    _MaxTime = 0;
    _AvrTimeSum = 0;
    _AvrTimeCount = 0;
    __enable_irq();     // Enable Interrupts

    if ( pAverage ) {
        if ( avrTimeCount == 0 ) 
            *pAverage = -1.0f;
        else
            *pAverage = 1000000.0f * _Factor / ( (float)avrTimeSum / (float)avrTimeCount );
    }
    
    if ( pMin ) {
        if ( minTime == 0 ) 
            *pMin = -1.0f;
        else
            *pMin = 1000000.0f * _Factor / (float)minTime;
    }
    
    if ( pMax ) {
        if ( maxTime == 0 ) 
            *pMax = -1.0f;
        else
            *pMax = 1000000.0f * _Factor / (float)maxTime;
    }
    
    if ( pSum ) {
        *pSum = _Factor * (float)_Counter;
    }
    
    return;
}

//////////////////////////////////////////////////////////////////////////////////

unsigned int Pulses::getCounter() {
    return _Counter;
}

//////////////////////////////////////////////////////////////////////////////////
    
void Pulses::setFactor(float factor) {
    _Factor = factor;
}

//////////////////////////////////////////////////////////////////////////////////

void Pulses::callback_in() {
    unsigned int act = _timer.read_us();
    unsigned int diff;
        
    diff = act - _lastTimer;   // Note: overflow is handled correctly
    _lastTimer = act;

    _Counter++;
    _TimeoutCount = 0;

    if ( _bFirst ) {   // ignore first pulse to synchronize timer (maybe timer overflow)
        _bFirst = false;
        return;
    }
    
    _ActTime = diff;
    _AvrTimeSum += diff;
    _AvrTimeCount++;
    
    if ( _MinTime==0 || _MinTime<diff )
        _MinTime = diff;
    if ( _MaxTime==0 || _MaxTime>diff )
        _MaxTime = diff;
}

//////////////////////////////////////////////////////////////////////////////////

void Pulses::callback_timeout() {
    _TimeoutCount++;
    if ( _TimeoutCount >= _Timeout ) {
        _TimeoutCount = 0;
        _ActTime = 0;
        _bFirst = true;
        }
}

//////////////////////////////////////////////////////////////////////////////////