172 lines
7.2 KiB
Arduino
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
|