#ifndef BAROMETER_H #define BAROMETER_H #include "../../data/Timestamp.h" #include "../../math/MovingAVG.h" #include "BarometerData.h" /** * calculates the pressure realtive to a startup-calibration of a barometer * hereafter all returned values are relative to the calibration * */ class RelativePressure { private: /** barometer history entries (timestamp -> value) */ struct History { Timestamp ts; BarometerData data; History(const Timestamp ts, const BarometerData data) : ts(ts), data(data) {;} }; /** barometer calibration helper */ struct Calibration { Timestamp neededTimeframe = Timestamp::fromMS(5000); std::vector history; bool isCalibrated = false; float baseAvg = 0; float sigma = 0; // prevent sensor-startup-issues and skip the first 25% of measurement values float skipStart = 0.25; void tryToCalibrate() { // determine the timeframe contained within the history const Timestamp timeframe = history.back().ts - history.front().ts; // do we have enough values to perform a calibration? if (timeframe < neededTimeframe) {return;} // we need double as float would lead to huge rounding errors! double sum = 0; double sum2 = 0; int cnt = 0; // calculate sum and sum² for (int i = (int)(skipStart*history.size()); i < (int)history.size(); ++i) { const History& h = history[i]; sum += h.data.hPa; sum2 += ((double)h.data.hPa * (double)h.data.hPa); ++cnt; } // calculate E(x) and E(x²) double avg = sum / (double)cnt; double avg2 = sum2 / (double)cnt; // set calibrated values this->baseAvg = avg; this->sigma = std::sqrt( avg2 - (avg*avg) ); this->isCalibrated = true; } void reset() { history.clear(); isCalibrated = false; sigma = 0; baseAvg = 0; } } calib; float latesthPa; public: /** ctor */ RelativePressure() { } /** set the timeframe used for the startup calibration (e.g. 5 seconds) */ void setCalibrationTimeframe(const Timestamp timeframe) { this->calib.neededTimeframe = timeframe; } /** add new sensor readings that were received at the given timestamp */ void add(const Timestamp& ts, const BarometerData& baro) { // perform calibration? if (!calib.isCalibrated) { calib.history.push_back(History(ts, baro)); calib.tryToCalibrate(); } // most recent pressure reading latesthPa = baro.hPa; } /** get the most recent pressure reading realtive to the startup calibration. returns 0 until the sensor is calibrated */ float getPressureRealtiveToStart() { if (calib.isCalibrated) { return latesthPa - calib.baseAvg; } else { return 0; } } /** reset the sensor's calibration */ void reset() { calib.reset(); } /** get the barometer's calibrated uncertainty determined during the startup calibration */ float getSigma() { return calib.sigma; } /** get the barometer's calibrated average during the startup calibration */ float getBaseAvg() { return calib.baseAvg; } private: }; #endif // BAROMETER_H