waterish_os_rev3_public/libraries/FlowMeter-master/src/FlowMeter.h

172 lines
7.2 KiB
Arduino

/**
* Flow Meter
*
* An Arduino flow meter library that provides calibrated liquid flow and volume measurement with flow sensors.
*
* @author sekdiy (https://github.com/sekdiy/FlowMeter)
* @date 14.07.2015 Initial release.
* @version See git comments for changes.
*/
#ifndef FLOWMETER_H
#define FLOWMETER_H
#include "Arduino.h"
/**
* FlowSensorProperties
*
* Structure that holds essential information about a flow sensor.
* Stores general sensor properties and calibration points.
*
* See file G34_Flow_rate_to_frequency.jpg for reference.
*/
typedef struct {
double capacity; //!< capacity, upper limit of flow rate (in l/min)
double kFactor; //!< "k-factor" (in (pulses/s) / (l/min)), e.g.: 1 pulse/s = kFactor * l/min
double mFactor[10]; //!< multiplicative correction factor near unity, "meter factor" (per decile of flow)
} FlowSensorProperties;
extern FlowSensorProperties UncalibratedSensor; //!< default sensor
extern FlowSensorProperties FS300A; //!< see documentation about FS300A/SEN02141B
extern FlowSensorProperties FS400A; //!< see documentation about FS400A/USN-HS10TA
/**
* FlowMeter
*/
class FlowMeter {
public:
/**
* Initializes a new flow meter object.
*
* @param pin The pin that the flow sensor is connected to (has to be interrupt capable, default: INT0).
* @param prop The properties of the actual flow sensor being used (default: UncalibratedSensor).
*/
FlowMeter(unsigned int pin = 2, FlowSensorProperties prop = UncalibratedSensor);
double getCurrentFlowrate(); //!< Returns the current flow rate since last reset (in l/min).
double getCurrentVolume(); //!< Returns the current volume since last reset (in l).
double getTotalFlowrate(); //!< Returns the (linear) average flow rate in this flow meter instance (in l/min).
double getTotalVolume(); //!< Returns the total volume flown trough this flow meter instance (in l).
/**
* The tick method updates all internal calculations at the end of a measurement period.
*
* We're calculating flow and volume data over time.
* The actual pulses have to be sampled using the count method (i.e. via an interrupt service routine).
*
* Flow sensor formulae:
*
* Let K: pulses per second per unit of measure (i.e. (1/s)/(l/min)),
* f: pulse frequency (1/s),
* Q: flow rate (l/min),
* p: sensor pulses (no dimension/unit),
* t: time since last measurements (s).
*
* K = f / Q | units: (1/s) / (l/min) = (1/s) / (l/min)
* <=> | Substitute p / t for f in order to allow for different measurement intervals
* K = (p / t) / Q | units: ((1/s)/(l/min)) = (1/s) / (l/min)
* <=> | Solve for Q:
* Q = (p / t) / K | untis: l/min = 1/s / (1/s / (l/min))
* <=> | Volume in l:
* V = Q / 60 | units: l = (l/min) / (min)
*
* The property K is sometimes stated in pulses per liter or pulses per gallon.
* In these cases the unit of measure has to be converted accordingly (e.g. from gal/s to l/min).
* See file G34_Flow_rate_to_frequency.jpg for reference.
*
* @param duration The tick duration (in ms).
*/
void tick(unsigned long duration = 1000);
void count(); //!< Increments the internal pulse counter. Serves as an interrupt callback routine.
void reset(); //!< Prepares the flow meter for a fresh measurement. Resets all current values, but not the totals.
/*
* setters enabling continued metering across power cycles
*/
FlowMeter* setTotalDuration(unsigned long totalDuration); //!< Sets the total (overall) duration (i.e. after power up).
FlowMeter* setTotalVolume(double totalVolume); //!< Sets the total (overall) volume (i.e. after power up).
FlowMeter* setTotalCorrection(double totalCorrection); //!< Sets the total (overall) correction factor (i.e. after power up).
/*
* convenience methods and calibration helpers
*/
unsigned int getPin(); //!< Returns the Arduino pin number that the flow sensor is connected to.
unsigned long getCurrentDuration(); //!< Returns the duration of the current tick (in ms).
double getCurrentFrequency(); //!< Returns the pulse rate in the current tick (in 1/s).
double getCurrentError(); //!< Returns the error resulting from the current measurement (in %).
unsigned long getTotalDuration(); //!< Returns the total run time of this flow meter instance (in ms).
double getTotalError(); //!< Returns the (linear) average error of this flow meter instance (in %).
protected:
unsigned int _pin; //!< connection pin (has to be interrupt capable!)
FlowSensorProperties _properties; //!< sensor properties (including calibration data)
unsigned long _currentDuration; //!< current tick duration (convenience, in ms)
double _currentFrequency; //!< current pulses per second (convenience, in 1/s)
double _currentFlowrate = 0.0f; //!< current flow rate (in l/tick), e.g.: 1 l / min = 1 pulse / s / (pulses / s / l / min)
double _currentVolume = 0.0f; //!< current volume (in l), e.g.: 1 l = 1 (l / min) / (60 * s)
double _currentCorrection; //!< currently applied correction factor
unsigned long _totalDuration = 0.0f; //!< total measured duration since begin of measurement (in ms)
double _totalVolume = 0.0f; //!< total volume since begin of measurement (in l)
double _totalCorrection = 0.0f; //!< accumulated correction factors
volatile unsigned long _currentPulses = 0; //!< pulses within current sample period
};
/**
* FlowSensorCalibration
*
* Convenience class for manipulating sensor properties.
*/
class FlowSensorCalibration {
public:
FlowSensorCalibration() {};
FlowSensorCalibration(FlowSensorProperties properties): _properties(properties) {};
FlowSensorCalibration* setProperties(FlowSensorProperties properties) {
this->_properties = properties;
return this;
};
FlowSensorCalibration* setCapacity(double capacity) {
this->_properties.capacity = capacity;
return this;
}
FlowSensorCalibration* setKFactor(double kFactor) {
this->_properties.kFactor = kFactor;
return this;
}
FlowSensorCalibration* setMeterFactorPerDecile(unsigned int decile, unsigned int mFactor) {
this->_properties.mFactor[decile] = mFactor;
return this;
}
FlowSensorProperties getProperties() {
return this->_properties;
}
double getCapacity() {
return this->_properties.capacity;
}
double getKFactor() {
return this->_properties.kFactor;
}
unsigned int getMeterFactorPerDecile(unsigned int decile) {
return this->_properties.mFactor[decile];
}
protected:
FlowSensorProperties _properties;
};
#endif // FLOWMETER_H