From 738d4e6e7ffa1f79728657566f3343e7db64a7e0 Mon Sep 17 00:00:00 2001 From: user2684 <you@example.com> Date: Wed, 12 Apr 2017 15:55:53 +0200 Subject: [PATCH] Add forecast output to BME280 #56 --- NodeManager.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++++++- NodeManager.h | 11 +++++ README.md | 6 +++ 3 files changed, 132 insertions(+), 2 deletions(-) diff --git a/NodeManager.cpp b/NodeManager.cpp index e220ccf..c7bdd76 100644 --- a/NodeManager.cpp +++ b/NodeManager.cpp @@ -1174,7 +1174,7 @@ void SensorMLX90614::onReceive(const MyMessage & message) { #if MODULE_BME280 == 1 // contructor SensorBME280::SensorBME280(int child_id, Adafruit_BME280* bme, int sensor_type): Sensor(child_id,A4) { - // store the sensor type (0: temperature, 1: humidity, 2: pressure) + // sensor type (0: temperature, 1: humidity, 2: pressure, 3: forecast) _sensor_type = sensor_type; if (_sensor_type == 0) { // temperature sensor @@ -1194,10 +1194,23 @@ SensorBME280::SensorBME280(int child_id, Adafruit_BME280* bme, int sensor_type): setType(V_PRESSURE); setValueType(TYPE_FLOAT); } + else if (_sensor_type == 3) { + // pressure sensor + setPresentation(S_BARO); + setType(V_FORECAST); + setValueType(TYPE_STRING); + } +} + +// setter/getter +void SensorBME280::setForecastSamplesCount(int value) { + _forecast_samples_count = value; } // what do to during before void SensorBME280::onBefore() { + // initialize the forecast samples array + _forecast_samples = new float[_forecast_samples_count]; } // what do to during setup @@ -1237,7 +1250,7 @@ void SensorBME280::onLoop() { } // Pressure Sensor else if (_sensor_type == 2) { - // read humidity + // read pressure float pressure = _bme->readPressure() / 100.0F; if (isnan(pressure)) return; #if DEBUG == 1 @@ -1249,12 +1262,98 @@ void SensorBME280::onLoop() { // store the value if (! isnan(pressure)) _value_float = pressure; } + // Forecast Sensor + else if (_sensor_type == 3) { + // read pressure + float pressure = _bme->readPressure() / 100.0F; + if (isnan(pressure)) return; + // Calculate the average of the last n minutes. + int index = _minute_count % _forecast_samples_count; + _forecast_samples[index] = pressure; + _minute_count++; + if (_minute_count > 185) _minute_count = 6; + if (_minute_count == 5) _pressure_avg = _getLastPressureSamplesAverage(); + else if (_minute_count == 35) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + float change = (last_pressure_avg - _pressure_avg) * 0.1; + // first time initial 3 hour + if (_first_round) _dP_dt = change * 2; // note this is for t = 0.5hour + else _dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value. + } + else if (_minute_count == 65) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + float change = (last_pressure_avg - _pressure_avg) * 0.1; + //first time initial 3 hour + if (_first_round) _dP_dt = change; //note this is for t = 1 hour + else _dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value + } + else if (_minute_count == 95) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + float change = (last_pressure_avg - _pressure_avg) * 0.1; + // first time initial 3 hour + if (_first_round)_dP_dt = change / 1.5; // note this is for t = 1.5 hour + else _dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value + } + else if (_minute_count == 125) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + // store for later use. + _pressure_avg2 = last_pressure_avg; + float change = (last_pressure_avg - _pressure_avg) * 0.1; + if (_first_round) _dP_dt = change / 2; // note this is for t = 2 hour + else _dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value + } + else if (_minute_count == 155) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + float change = (last_pressure_avg - _pressure_avg) * 0.1; + if (_first_round) _dP_dt = change / 2.5; // note this is for t = 2.5 hour + else _dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value + } + else if (_minute_count == 185) { + float last_pressure_avg = _getLastPressureSamplesAverage(); + float change = (last_pressure_avg - _pressure_avg) * 0.1; + if (_first_round) _dP_dt = change / 3; // note this is for t = 3 hour + else _dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value + } + // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. + _pressure_avg = _pressure_avg2; + // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. + _first_round = false; + // calculate the forecast (STABLE = 0, SUNNY = 1, CLOUDY = 2, UNSTABLE = 3, THUNDERSTORM = 4, UNKNOWN = 5) + int forecast = 5; + //if time is less than 35 min on the first 3 hour interval. + if (_minute_count < 35 && _first_round) forecast = 5; + else if (_dP_dt < (-0.25)) forecast = 5; + else if (_dP_dt > 0.25) forecast = 4; + else if ((_dP_dt > (-0.25)) && (_dP_dt < (-0.05))) forecast = 2; + else if ((_dP_dt > 0.05) && (_dP_dt < 0.25)) forecast = 1; + else if ((_dP_dt >(-0.05)) && (_dP_dt < 0.05)) forecast = 0; + else forecast = 5; + _value_string = _weather[forecast]; + #if DEBUG == 1 + Serial.print(F("BME I=")); + Serial.print(_child_id); + Serial.print(F(" M=")); + Serial.print(_minute_count); + Serial.print(F(" dP=")); + Serial.print(_dP_dt); + Serial.print(F(" F=")); + Serial.println(_value_string); + #endif + } } // what do to as the main task when receiving a message void SensorBME280::onReceive(const MyMessage & message) { onLoop(); } + +// returns the average of the latest pressure samples +float SensorBME280::_getLastPressureSamplesAverage() { + float avg = 0; + for (int i = 0; i < _forecast_samples_count; i++) avg += _forecast_samples[i]; + avg /= _forecast_samples_count; + return avg; +} #endif @@ -1371,19 +1470,25 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) { else if (sensor_type == SENSOR_DHT11 || sensor_type == SENSOR_DHT22) { int dht_type = sensor_type == SENSOR_DHT11 ? DHT11 : DHT22; DHT* dht = new DHT(pin,dht_type); + // register temperature sensor registerSensor(new SensorDHT(child_id,pin,dht,0,dht_type)); + // register humidity sensor child_id = _getAvailableChildId(); return registerSensor(new SensorDHT(child_id,pin,dht,1,dht_type)); } #endif #if MODULE_SHT21 == 1 else if (sensor_type == SENSOR_SHT21) { + // register temperature sensor registerSensor(new SensorSHT21(child_id,0)); + // register humidity sensor child_id = _getAvailableChildId(); return registerSensor(new SensorSHT21(child_id,1)); } else if (sensor_type == SENSOR_HTU21D) { + // register temperature sensor registerSensor(new SensorHTU21D(child_id,0)); + // register humidity sensor child_id = _getAvailableChildId(); return registerSensor(new SensorHTU21D(child_id,1)); } @@ -1427,7 +1532,9 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) { #if MODULE_MLX90614 == 1 else if (sensor_type == SENSOR_MLX90614) { Adafruit_MLX90614* mlx = new Adafruit_MLX90614(); + // register ambient temperature sensor registerSensor(new SensorMLX90614(child_id,mlx,0)); + // register object temperature sensor child_id = _getAvailableChildId(); return registerSensor(new SensorMLX90614(child_id,mlx,1)); } @@ -1441,11 +1548,17 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) { #endif return -1; } + // register temperature sensor registerSensor(new SensorBME280(child_id,bme,0)); child_id = _getAvailableChildId(); + // register humidity sensor registerSensor(new SensorBME280(child_id,bme,1)); + // register pressure sensor child_id = _getAvailableChildId(); return registerSensor(new SensorBME280(child_id,bme,2)); + // register forecast sensor + child_id = _getAvailableChildId(); + return registerSensor(new SensorBME280(child_id,bme,3)); } #endif else { diff --git a/NodeManager.h b/NodeManager.h index 4eb5b89..5a60a87 100644 --- a/NodeManager.h +++ b/NodeManager.h @@ -692,6 +692,8 @@ class SensorMLX90614: public Sensor { class SensorBME280: public Sensor { public: SensorBME280(int child_id, Adafruit_BME280* bme, int sensor_type); + // define how many pressure samples to keep track of for calculating the forecast (default: 5) + void setForecastSamplesCount(int value); // define what to do at each stage of the sketch void onBefore(); void onSetup(); @@ -700,6 +702,15 @@ class SensorBME280: public Sensor { protected: Adafruit_BME280* _bme; int _sensor_type; + char* _weather[6] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" }; + int _forecast_samples_count = 5; + float* _forecast_samples; + int _minute_count = 0; + float _pressure_avg; + float _pressure_avg2; + float _dP_dt; + bool _first_round = true; + float _getLastPressureSamplesAverage(); }; #endif diff --git a/README.md b/README.md index 2284eb1..9daace7 100644 --- a/README.md +++ b/README.md @@ -374,6 +374,12 @@ Each sensor class can expose additional methods. void setResolution(int value); ~~~ +#### SensorBME280 +~~~c + // define how many pressure samples to keep track of for calculating the forecast (default: 5) + void setForecastSamplesCount(int value); +~~~ + ## Upload your sketch Upload your sketch to your arduino board as you are used to. -- GitLab