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

LoRa-Sensornode Firmware for Multitech mDot

A multifunctional and modular Firmware for Multitech's mDot which provides a widerange of functionality for several Sensors. It allows you to quickly build a Sensornode that measures specific data with its sensors and sends it via LoRaWAN.

/media/uploads/mitea1/logo-lora-600x370.png /media/uploads/mitea1/mt_mdot_family_642px.png

Supported Sensors

Idea

The Firmware has some predefined Application Modes running different Tasks(Measurements). Each mode can be used in a different Scenario. Application_Modes define which sensors are used, how often they aquire data and how often the data has to be sent via LoRa. Lets say you just want to measure the Light then you choose an Application_Mode (or define one) that only runs TaskLight for light measurement. As a standard all measurements are taken every second and sent via LoRa but you can change that interval depending on your usage Scenario

Committer:
mitea1
Date:
Fri Nov 02 16:58:23 2018 +0000
Revision:
9:c4e378f4801d
[MOD]initial commit for flowsensor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mitea1 9:c4e378f4801d 1 /*
mitea1 9:c4e378f4801d 2 * FlowMeter.cpp
mitea1 9:c4e378f4801d 3 *
mitea1 9:c4e378f4801d 4 * Created on: 23.10.2018
mitea1 9:c4e378f4801d 5 * Author: Adrian
mitea1 9:c4e378f4801d 6 */
mitea1 9:c4e378f4801d 7
mitea1 9:c4e378f4801d 8 #include "FlowMeter.h"
mitea1 9:c4e378f4801d 9 #include "math.h"
mitea1 9:c4e378f4801d 10
mitea1 9:c4e378f4801d 11 FlowMeter::FlowMeter(InterruptIn* interruptPin, FlowSensorProperties prop) :
mitea1 9:c4e378f4801d 12 _properties(prop),
mitea1 9:c4e378f4801d 13 _currentCorrection(0.0f),
mitea1 9:c4e378f4801d 14 _currentDuration(0.0f),
mitea1 9:c4e378f4801d 15 _currentFlowrate(0.0f),
mitea1 9:c4e378f4801d 16 _currentVolume(0.0f),
mitea1 9:c4e378f4801d 17 _totalDuration(0.0f),
mitea1 9:c4e378f4801d 18 _totalVolume(0.0f),
mitea1 9:c4e378f4801d 19 _totalCorrection(0.0f),
mitea1 9:c4e378f4801d 20 _currentPulses(0.0f),
mitea1 9:c4e378f4801d 21 _currentFrequency(0.0f)//!< store sensor properties
mitea1 9:c4e378f4801d 22 {
mitea1 9:c4e378f4801d 23 this->pulseInput = interruptPin;
mitea1 9:c4e378f4801d 24 this->pulseInput->rise(this,&FlowMeter::count);
mitea1 9:c4e378f4801d 25 this->ticker = new Ticker();
mitea1 9:c4e378f4801d 26 this->tickDuration_ms = 1000;
mitea1 9:c4e378f4801d 27 this->ticker->attach(this,&FlowMeter::tick,this->tickDuration_ms/1000);
mitea1 9:c4e378f4801d 28 this->_currentCorrection = 0.0f;
mitea1 9:c4e378f4801d 29 }
mitea1 9:c4e378f4801d 30
mitea1 9:c4e378f4801d 31 double FlowMeter::getCurrentFlowrate() {
mitea1 9:c4e378f4801d 32 return this->_currentFlowrate; //!< in l/min
mitea1 9:c4e378f4801d 33 }
mitea1 9:c4e378f4801d 34
mitea1 9:c4e378f4801d 35 double FlowMeter::getCurrentVolume() {
mitea1 9:c4e378f4801d 36 return this->_currentVolume; //!< in l
mitea1 9:c4e378f4801d 37 }
mitea1 9:c4e378f4801d 38
mitea1 9:c4e378f4801d 39 double FlowMeter::getTotalFlowrate() {
mitea1 9:c4e378f4801d 40 return this->_totalVolume / (this->_totalDuration / 1000.0f) * 60.0f; //!< in l/min
mitea1 9:c4e378f4801d 41 }
mitea1 9:c4e378f4801d 42
mitea1 9:c4e378f4801d 43 double FlowMeter::getTotalVolume() {
mitea1 9:c4e378f4801d 44 return this->_totalVolume; //!< in l
mitea1 9:c4e378f4801d 45 }
mitea1 9:c4e378f4801d 46
mitea1 9:c4e378f4801d 47 void FlowMeter::tick() {
mitea1 9:c4e378f4801d 48 /* sampling and normalisation */
mitea1 9:c4e378f4801d 49 double seconds = this->tickDuration_ms / 1000.0f; //!< normalised duration (in s, i.e. per 1000ms)
mitea1 9:c4e378f4801d 50 //todo get rid of it cli(); //!< going to change interrupt variable(s)
mitea1 9:c4e378f4801d 51 double frequency = this->_currentPulses / seconds; //!< normalised frequency (in 1/s)
mitea1 9:c4e378f4801d 52 this->_currentPulses = 0; //!< reset pulse counter after successfull sampling
mitea1 9:c4e378f4801d 53 //todo get rid of it sei(); //!< done changing interrupt variable(s)
mitea1 9:c4e378f4801d 54
mitea1 9:c4e378f4801d 55 /* determine current correction factor (from sensor properties) */
mitea1 9:c4e378f4801d 56 unsigned int decile = floor(10.0f * frequency / (this->_properties.capacity * this->_properties.kFactor)); //!< decile of current flow relative to sensor capacity
mitea1 9:c4e378f4801d 57 unsigned int ceiling = 9;
mitea1 9:c4e378f4801d 58 unsigned int min;
mitea1 9:c4e378f4801d 59 if(ceiling < decile){
mitea1 9:c4e378f4801d 60 min = ceiling;
mitea1 9:c4e378f4801d 61 }
mitea1 9:c4e378f4801d 62 else{
mitea1 9:c4e378f4801d 63 min = decile;
mitea1 9:c4e378f4801d 64 } //!< highest possible decile index
mitea1 9:c4e378f4801d 65 this->_currentCorrection = this->_properties.kFactor / this->_properties.mFactor[min]; //!< combine constant k-factor and m-factor for decile
mitea1 9:c4e378f4801d 66
mitea1 9:c4e378f4801d 67 /* update current calculations: */
mitea1 9:c4e378f4801d 68 this->_currentFlowrate = frequency / this->_currentCorrection; //!< get flow rate (in l/min) from normalised frequency and combined correction factor
mitea1 9:c4e378f4801d 69 this->_currentVolume = this->_currentFlowrate / (60.0f/seconds); //!< get volume (in l) from normalised flow rate and normalised time
mitea1 9:c4e378f4801d 70
mitea1 9:c4e378f4801d 71 /* update statistics: */
mitea1 9:c4e378f4801d 72 this->_currentDuration = this->tickDuration_ms; //!< store current tick duration (convenience, in ms)
mitea1 9:c4e378f4801d 73 this->_currentFrequency = frequency; //!< store current pulses per second (convenience, in 1/s)
mitea1 9:c4e378f4801d 74 this->_totalDuration += this->tickDuration_ms; //!< accumulate total duration (in ms)
mitea1 9:c4e378f4801d 75 this->_totalVolume += this->_currentVolume; //!< accumulate total volume (in l)
mitea1 9:c4e378f4801d 76 this->_totalCorrection += this->_currentCorrection * this->tickDuration_ms; //!< accumulate corrections over time
mitea1 9:c4e378f4801d 77 }
mitea1 9:c4e378f4801d 78
mitea1 9:c4e378f4801d 79 void FlowMeter::count(void) {
mitea1 9:c4e378f4801d 80 this->_currentPulses++; //!< this should be called from an interrupt service routine
mitea1 9:c4e378f4801d 81 }
mitea1 9:c4e378f4801d 82
mitea1 9:c4e378f4801d 83 void FlowMeter::reset() {
mitea1 9:c4e378f4801d 84 //todo get rid of it cli(); //!< going to change interrupt variable(s)
mitea1 9:c4e378f4801d 85 this->_currentPulses = 0; //!< reset pulse counter
mitea1 9:c4e378f4801d 86 //todo get rid of it sei(); //!< done changing interrupt variable(s)
mitea1 9:c4e378f4801d 87
mitea1 9:c4e378f4801d 88 this->_currentFrequency = 0.0f;
mitea1 9:c4e378f4801d 89 this->_currentDuration = 0.0f;
mitea1 9:c4e378f4801d 90 this->_currentFlowrate = 0.0f;
mitea1 9:c4e378f4801d 91 this->_currentVolume = 0.0f;
mitea1 9:c4e378f4801d 92 this->_currentCorrection = 0.0f;
mitea1 9:c4e378f4801d 93 }
mitea1 9:c4e378f4801d 94
mitea1 9:c4e378f4801d 95 InterruptIn* FlowMeter::getPin() {
mitea1 9:c4e378f4801d 96 return this->pulseInput;
mitea1 9:c4e378f4801d 97 }
mitea1 9:c4e378f4801d 98
mitea1 9:c4e378f4801d 99 unsigned long FlowMeter::getCurrentDuration() {
mitea1 9:c4e378f4801d 100 return this->_currentDuration; //!< in ms
mitea1 9:c4e378f4801d 101 }
mitea1 9:c4e378f4801d 102
mitea1 9:c4e378f4801d 103 double FlowMeter::getCurrentFrequency() {
mitea1 9:c4e378f4801d 104 return this->_currentFrequency; //!< in 1/s
mitea1 9:c4e378f4801d 105 }
mitea1 9:c4e378f4801d 106
mitea1 9:c4e378f4801d 107 double FlowMeter::getCurrentError() {
mitea1 9:c4e378f4801d 108 /// error (in %) = error * 100
mitea1 9:c4e378f4801d 109 /// error = correction rate - 1
mitea1 9:c4e378f4801d 110 /// correction rate = k-factor / correction
mitea1 9:c4e378f4801d 111 return (this->_properties.kFactor / this->_currentCorrection - 1) * 100; //!< in %
mitea1 9:c4e378f4801d 112 }
mitea1 9:c4e378f4801d 113
mitea1 9:c4e378f4801d 114 unsigned long FlowMeter::getTotalDuration() {
mitea1 9:c4e378f4801d 115 return this->_totalDuration; //!< in ms
mitea1 9:c4e378f4801d 116 }
mitea1 9:c4e378f4801d 117
mitea1 9:c4e378f4801d 118 double FlowMeter::getTotalError() {
mitea1 9:c4e378f4801d 119 /// average error (in %) = average error * 100
mitea1 9:c4e378f4801d 120 /// average error = average correction rate - 1
mitea1 9:c4e378f4801d 121 /// average correction rate = k-factor / corrections over time * total time
mitea1 9:c4e378f4801d 122 return (this->_properties.kFactor / this->_totalCorrection * this->_totalDuration - 1) * 100;
mitea1 9:c4e378f4801d 123 }
mitea1 9:c4e378f4801d 124
mitea1 9:c4e378f4801d 125 FlowMeter* FlowMeter::setTotalDuration(unsigned long totalDuration) {
mitea1 9:c4e378f4801d 126 this->_totalDuration = totalDuration;
mitea1 9:c4e378f4801d 127 return this;
mitea1 9:c4e378f4801d 128 }
mitea1 9:c4e378f4801d 129
mitea1 9:c4e378f4801d 130 FlowMeter* FlowMeter::setTotalVolume(double totalVolume) {
mitea1 9:c4e378f4801d 131 this->_totalVolume = totalVolume;
mitea1 9:c4e378f4801d 132 return this;
mitea1 9:c4e378f4801d 133 }
mitea1 9:c4e378f4801d 134
mitea1 9:c4e378f4801d 135 FlowMeter* FlowMeter::setTotalCorrection(double totalCorrection) {
mitea1 9:c4e378f4801d 136 this->_totalCorrection = totalCorrection;
mitea1 9:c4e378f4801d 137 return this;
mitea1 9:c4e378f4801d 138 }
mitea1 9:c4e378f4801d 139
mitea1 9:c4e378f4801d 140 FlowSensorProperties UncalibratedSensor = {60.0f, 5.0f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
mitea1 9:c4e378f4801d 141 FlowSensorProperties FS300A = {60.0f, 5.5f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
mitea1 9:c4e378f4801d 142 FlowSensorProperties FS400A = {60.0f, 4.8f, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
mitea1 9:c4e378f4801d 143
mitea1 9:c4e378f4801d 144
mitea1 9:c4e378f4801d 145 void pulesInputInterrupt(void){
mitea1 9:c4e378f4801d 146 int i = 0;
mitea1 9:c4e378f4801d 147 }