A multifunctional and modular Firmware for Multitech's mDot based on ARM mBed provides a widerange of functionality for several Sensors such as MAX44009, BME280, MPU9250, SI1143 and uBlox. It allows you to quickly build a Sensornode that measures specific data with its sensors and sends it via LoRaWAN.

Dependencies:   mDot_LoRa_Sensornode_Flowmeter_impl mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FlowMeter.cpp Source File

FlowMeter.cpp

00001 /*
00002  * FlowMeter.cpp
00003  *
00004  *  Created on: 23.10.2018
00005  *      Author: Adrian
00006  */
00007 
00008 #include "FlowMeter.h"
00009 #include "math.h"
00010 
00011 FlowMeter::FlowMeter(InterruptIn* interruptPin, FlowSensorProperties prop) :
00012     _properties(prop),
00013     _currentCorrection(0.0f),
00014     _currentDuration(0.0f),
00015     _currentFlowrate(0.0f),
00016     _currentVolume(0.0f),
00017     _totalDuration(0.0f),
00018     _totalVolume(0.0f),
00019     _totalCorrection(0.0f),
00020     _currentPulses(0.0f),
00021     _currentFrequency(0.0f)//!< store sensor properties
00022 {
00023     this->pulseInput = interruptPin;
00024     this->pulseInput->rise(this,&FlowMeter::count);
00025     this->ticker = new Ticker();
00026     this->tickDuration_ms = 1000;
00027     this->ticker->attach(this,&FlowMeter::tick,this->tickDuration_ms/1000);
00028     this->_currentCorrection = 0.0f;
00029 }
00030 
00031 double FlowMeter::getCurrentFlowrate() {
00032     return this->_currentFlowrate;                                          //!< in l/min
00033 }
00034 
00035 double FlowMeter::getCurrentVolume() {
00036     return this->_currentVolume;                                            //!< in l
00037 }
00038 
00039 double FlowMeter::getTotalFlowrate() {
00040     return this->_totalVolume / (this->_totalDuration / 1000.0f) * 60.0f;   //!< in l/min
00041 }
00042 
00043 double FlowMeter::getTotalVolume() {
00044     return this->_totalVolume;                                              //!< in l
00045 }
00046 
00047 void FlowMeter::tick() {
00048     /* sampling and normalisation */
00049     double seconds = this->tickDuration_ms / 1000.0f;                                    //!< normalised duration (in s, i.e. per 1000ms)
00050     //todo get rid of it cli();                                                                  //!< going to change interrupt variable(s)
00051     double frequency = this->_currentPulses / seconds;                      //!< normalised frequency (in 1/s)
00052     this->_currentPulses = 0;                                               //!< reset pulse counter after successfull sampling
00053     //todo get rid of it sei();                                                                  //!< done changing interrupt variable(s)
00054 
00055     /* determine current correction factor (from sensor properties) */
00056     unsigned int decile = floor(10.0f * frequency / (this->_properties.capacity * this->_properties.kFactor));          //!< decile of current flow relative to sensor capacity
00057     unsigned int ceiling =  9;
00058     unsigned int min;
00059     if(ceiling < decile){
00060         min = ceiling;  
00061     }
00062     else{
00063         min = decile;
00064     }                                                                                          //!< highest possible decile index
00065     this->_currentCorrection = this->_properties.kFactor / this->_properties.mFactor[min];             //!< combine constant k-factor and m-factor for decile
00066 
00067     /* update current calculations: */
00068     this->_currentFlowrate = frequency / this->_currentCorrection;          //!< get flow rate (in l/min) from normalised frequency and combined correction factor
00069     this->_currentVolume = this->_currentFlowrate / (60.0f/seconds);        //!< get volume (in l) from normalised flow rate and normalised time
00070 
00071     /* update statistics: */
00072     this->_currentDuration = this->tickDuration_ms;                                      //!< store current tick duration (convenience, in ms)
00073     this->_currentFrequency = frequency;                                    //!< store current pulses per second (convenience, in 1/s)
00074     this->_totalDuration += this->tickDuration_ms;                                       //!< accumulate total duration (in ms)
00075     this->_totalVolume += this->_currentVolume;                             //!< accumulate total volume (in l)
00076     this->_totalCorrection += this->_currentCorrection * this->tickDuration_ms;          //!< accumulate corrections over time
00077 }
00078 
00079 void FlowMeter::count(void) {
00080     this->_currentPulses++;                                                 //!< this should be called from an interrupt service routine
00081 }
00082 
00083 void FlowMeter::reset() {
00084     //todo get rid of it  cli();                                                                  //!< going to change interrupt variable(s)
00085     this->_currentPulses = 0;                                               //!< reset pulse counter
00086     //todo get rid of it sei();                                                                  //!< done changing interrupt variable(s)
00087 
00088     this->_currentFrequency = 0.0f;
00089     this->_currentDuration = 0.0f;
00090     this->_currentFlowrate = 0.0f;
00091     this->_currentVolume = 0.0f;
00092     this->_currentCorrection = 0.0f;
00093 }
00094 
00095 InterruptIn* FlowMeter::getPin() {
00096     return this->pulseInput;
00097 }
00098 
00099 unsigned long FlowMeter::getCurrentDuration() {
00100     return this->_currentDuration;                                          //!< in ms
00101 }
00102 
00103 double FlowMeter::getCurrentFrequency() {
00104     return this->_currentFrequency;                                         //!< in 1/s
00105 }
00106 
00107 double FlowMeter::getCurrentError() {
00108     /// error (in %) = error * 100
00109     /// error = correction rate - 1
00110     /// correction rate = k-factor / correction
00111     return (this->_properties.kFactor / this->_currentCorrection - 1) * 100;  //!< in %
00112 }
00113 
00114 unsigned long FlowMeter::getTotalDuration() {
00115     return this->_totalDuration;                                            //!< in ms
00116 }
00117 
00118 double FlowMeter::getTotalError() {
00119     /// average error (in %) = average error * 100
00120     /// average error = average correction rate - 1
00121     /// average correction rate = k-factor / corrections over time * total time
00122     return (this->_properties.kFactor / this->_totalCorrection * this->_totalDuration - 1) * 100;
00123 }
00124 
00125 FlowMeter* FlowMeter::setTotalDuration(unsigned long totalDuration) {
00126     this->_totalDuration = totalDuration;
00127     return this;
00128 }
00129 
00130 FlowMeter* FlowMeter::setTotalVolume(double totalVolume) {
00131     this->_totalVolume = totalVolume;
00132     return this;
00133 }
00134 
00135 FlowMeter* FlowMeter::setTotalCorrection(double totalCorrection) {
00136     this->_totalCorrection = totalCorrection;
00137     return this;
00138 }
00139 
00140 FlowSensorProperties UncalibratedSensor = {60.0f, 5.0f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
00141 FlowSensorProperties FS300A = {60.0f, 5.5f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
00142 FlowSensorProperties FS400A = {60.0f, 4.8f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
00143 
00144 
00145 void pulesInputInterrupt(void){
00146     int i = 0;
00147 }