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

app/FlowMeter.h

Committer:
mitea1
Date:
2018-11-02
Revision:
10:4051c38bf73f
Parent:
9:c4e378f4801d

File content as of revision 10:4051c38bf73f:

/*
 * FlowMeter.h
 *
 *  Created on: 23.10.2018
 *      Author: Adrian
 */

#ifndef DRIVERS_FLOWMETER_H_
#define DRIVERS_FLOWMETER_H_
#include "InterruptIn.h"
#include "Ticker.h"
#include "mbed.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(InterruptIn* pin, 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();
    void count(void);                                //!< 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
     */
    InterruptIn* 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:
    InterruptIn* pulseInput;
    Ticker* ticker;
    unsigned long tickDuration_ms;
    //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;              //!< current flow rate (in l/tick), e.g.: 1 l / min = 1 pulse / s / (pulses / s / l / min)
    double _currentVolume;                //!< current volume (in l), e.g.: 1 l = 1 (l / min) / (60 * s)
    double _currentCorrection;                   //!< currently applied correction factor

    unsigned long _totalDuration;         //!< total measured duration since begin of measurement (in ms)
    double _totalVolume;                  //!< total volume since begin of measurement (in l)
    double _totalCorrection;              //!< accumulated correction factors

    volatile unsigned long _currentPulses;   //!< 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 /* DRIVERS_FLOWMETER_H_ */