BMP085 + DHT22
-
Hi
I have a question. Is anybody here who has or can write coode code sketch for Arduino Mini Pro to read data from DHT22 and BMP085 to wrok as Weather Station and send correct to Domoticz ?
Now i use this code but has a problem:// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #include <SPI.h> #include <MySensors.h> #include <Wire.h> #include <Adafruit_BMP085.h> #include <DHT.h> // Set this to the pin you connected the DHT's data pin to #define DHT_DATA_PIN 3 // Set this offset if the sensor has a permanent small offset to the real temperatures #define SENSOR_TEMP_OFFSET 0 // Sleep time between sensor updates (in milliseconds) // Must be >1000ms for DHT22 and >2000ms for DHT11 static const uint64_t UPDATE_INTERVAL = 3000; // Force sending an update of the temperature after n sensor reads, so a controller showing the // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that // the value didn't change since; // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms] static const uint8_t FORCE_UPDATE_N_READS = 10; #define BARO_CHILD 0 #define TEMP_CHILD 1 #define CHILD_ID_HUM 2 #define CHILD_ID_TEMP 3 float lastTemp; float lastHum; uint8_t nNoUpdatesTemp; uint8_t nNoUpdatesHum; bool metric = true; const float ALTITUDE = 206; // <-- adapt this value to your own location's altitude. // Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute. const unsigned long SLEEP_TIME = 60000; const char *weather[] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" }; enum FORECAST { STABLE = 0, // "Stable Weather Pattern" SUNNY = 1, // "Slowly rising Good Weather", "Clear/Sunny " CLOUDY = 2, // "Slowly falling L-Pressure ", "Cloudy/Rain " UNSTABLE = 3, // "Quickly rising H-Press", "Not Stable" THUNDERSTORM = 4, // "Quickly falling L-Press", "Thunderstorm" UNKNOWN = 5 // "Unknown (More Time needed) }; Adafruit_BMP085 bmp = Adafruit_BMP085(); // Digital Pressure Sensor float lastPressure = -1; float lastTemp_C = -1; int lastForecast = -1; const int LAST_SAMPLES_COUNT = 5; float lastPressureSamples[LAST_SAMPLES_COUNT]; // this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm // get kPa/h be dividing hPa by 10 #define CONVERSION_FACTOR (1.0/10.0) int minuteCount = 0; bool firstRound = true; // average value is used in forecast algorithm. float pressureAvg; // average after 2 hours is used as reference value for the next iteration. float pressureAvg2; float dP_dt; MyMessage tempMsg(TEMP_CHILD, V_TEMP); MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); MyMessage forecastMsg(BARO_CHILD, V_FORECAST); MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); DHT dht; void setup() { if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } metric = getConfig().isMetric; dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) { Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!"); } // Sleep for the time of the minimum sampling period to give the sensor time to power up // (otherwise, timeout errors might occure for the first reading) sleep(dht.getMinimumSamplingPeriod()); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Cis.+wilg.+temp.", "1.1"); // Register sensors to gw (they will be created as child devices) present(BARO_CHILD, S_BARO); present(TEMP_CHILD, S_TEMP); present(CHILD_ID_HUM, S_HUM); present(CHILD_ID_TEMP, S_TEMP); metric = getConfig().isMetric; } void loop() { // Force reading sensor, so it works also after sleep() dht.readSensor(true); // Get temperature from DHT library float temperature = dht.getTemperature(); if (isnan(temperature)) { Serial.println("Failed reading temperature from DHT!"); } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) { // Only send temperature if it changed since the last measurement or if we didn't send an update for n times lastTemp = temperature; if (!metric) { temperature = dht.toFahrenheit(temperature); } // Reset no updates counter nNoUpdatesTemp = 0; temperature += SENSOR_TEMP_OFFSET; send(msgTemp.set(temperature, 1)); #ifdef MY_DEBUG Serial.print("T: "); Serial.println(temperature); #endif } else { // Increase no update counter if the temperature stayed the same nNoUpdatesTemp++; } // Get humidity from DHT library float humidity = dht.getHumidity(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) { // Only send humidity if it changed since the last measurement or if we didn't send an update for n times lastHum = humidity; // Reset no updates counter nNoUpdatesHum = 0; send(msgHum.set(humidity, 1)); #ifdef MY_DEBUG Serial.print("H: "); Serial.println(humidity); #endif } else { // Increase no update counter if the humidity stayed the same nNoUpdatesHum++; } float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0; float temperaturec = bmp.readTemperature(); if (!metric) { // Convert to fahrenheit temperaturec = temperaturec * 9.0 / 5.0 + 32.0; } int forecast = sample(pressure); Serial.print("Temperature = "); Serial.print(temperaturec); Serial.println(metric ? " *C" : " *F"); Serial.print("Pressure = "); Serial.print(pressure); Serial.println(" hPa"); Serial.print("Forecast = "); Serial.println(weather[forecast]); if (temperaturec != lastTemp_C) { send(tempMsg.set(temperaturec, 1)); lastTemp_C = temperaturec; } if (pressure != lastPressure) { send(pressureMsg.set(pressure, 0)); lastPressure = pressure; } if (forecast != lastForecast) { send(forecastMsg.set(weather[forecast])); lastForecast = forecast; } // Sleep for a while to save energy sleep(UPDATE_INTERVAL); sleep(SLEEP_TIME); } float getLastPressureSamplesAverage() { float lastPressureSamplesAverage = 0; for (int i = 0; i < LAST_SAMPLES_COUNT; i++) { lastPressureSamplesAverage += lastPressureSamples[i]; } lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; return lastPressureSamplesAverage; } // Algorithm found here // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf // Pressure in hPa --> forecast done by calculating kPa/h int sample(float pressure) { // Calculate the average of the last n minutes. int index = minuteCount % LAST_SAMPLES_COUNT; lastPressureSamples[index] = pressure; minuteCount++; if (minuteCount > 185) { minuteCount = 6; } if (minuteCount == 5) { pressureAvg = getLastPressureSamplesAverage(); } else if (minuteCount == 35) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 65) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) //first time initial 3 hour { 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 (minuteCount == 95) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 125) { float lastPressureAvg = getLastPressureSamplesAverage(); pressureAvg2 = lastPressureAvg; // store for later use. float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 155) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 185) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 } pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. } int forecast = UNKNOWN; if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval. { forecast = UNKNOWN; } else if (dP_dt < (-0.25)) { forecast = THUNDERSTORM; } else if (dP_dt > 0.25) { forecast = UNSTABLE; } else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05))) { forecast = CLOUDY; } else if ((dP_dt > 0.05) && (dP_dt < 0.25)) { forecast = SUNNY; } else if ((dP_dt >(-0.05)) && (dP_dt < 0.05)) { forecast = STABLE; } else { forecast = UNKNOWN; } // uncomment when debugging //Serial.print(F("Forecast at minute ")); //Serial.print(minuteCount); //Serial.print(F(" dP/dt = ")); //Serial.print(dP_dt); //Serial.print(F("kPa/h --> ")); //Serial.println(weather[forecast]); return forecast; }
In Domoticz after communicate this node with Gateway , he find devices as show on screen 1 and in hardware screen 2. But i want to find temp from DHt22, Hum from DHT22, Baro from BMP085 and temp from BMP085.
please help me or correct this code.
-
Please help...
I need merged to one sketch this:
https://www.mysensors.org/build/humidityand this:
https://www.mysensors.org/build/pressure
-
@pepson there is a great guide on combining sketches at https://forum.mysensors.org/topic/115/implementing-multiple-sensors/4
-
https://github.com/mysensors/MySensorsArduinoExamples/tree/master/examples/WeatherStationSensor
or
https://github.com/windkh/mysensors/tree/master/WeatherStationSensorI will port it to mysensors 2.0 soon.
-
I did what you tried to do, and it worked, also in Domoticz two temps are visible.
This is my code:
/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik Ekblad * * DESCRIPTION * Pressure sensor example using BMP085 module * http://www.mysensors.org/build/pressure * Toegevoegd: na 10x dezelfde waarde te hebben gelezen bij TeEmp en Hum toch een waarde aan de GW sturen. */ #include <SPI.h> #include <Wire.h> #include <DHT.h> #include <MySensor.h> #include <Adafruit_BMP085.h> static const uint8_t FORCE_UPDATE_N_READS = 10; uint8_t nNoUpdatesTemp; uint8_t nNoUpdatesHum; #define BARO_CHILD 0 #define TEMP_CHILD 1 #define CHILD_ID_HUM 2 #define CHILD_ID_TEMP 3 #define HUMIDITY_SENSOR_DIGITAL_PIN 3 const float ALTITUDE = 1.05; // <-- adapt this value to your own location's altitude. // Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute. const unsigned long SLEEP_TIME = 60000; const char *weather[] = { "stabiel", "zonnig", "bewolkt", "onstabiel", "onweer", "onbekend" }; enum FORECAST { STABIEL = 0, // "Stable Weather Pattern" ZONNIG = 1, // "Slowly rising Good Weather", "Clear/Sunny " BEWOLKT = 2, // "Slowly falling L-Pressure ", "BEWOLKT/Rain " ONSTABIEL = 3, // "Quickly rising H-Press", "Not Stable" ONWEER = 4, // "Quickly falling L-Press", "ONWEER" ONBEKEND = 5 // "ONBEKEND (More Time needed) }; Adafruit_BMP085 bmp = Adafruit_BMP085(); // Digital Pressure Sensor MySensor gw; float lastPressure = -1; float lastTempBMP = -1; int lastForecast = -1; const int LAST_SAMPLES_COUNT = 5; float lastPressureSamples[LAST_SAMPLES_COUNT]; // this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm // get kPa/h be dividing hPa by 10 #define CONVERSION_FACTOR (1.0/10.0) int minuteCount = 0; bool firstRound = true; // average value is used in forecast algorithm. float pressureAvg; // average after 2 hours is used as reference value for the next iteration. float pressureAvg2; float dP_dt; DHT dht; float lastTempDHT; float lastHum; boolean metric = true; MyMessage tempMsg(TEMP_CHILD, V_TEMP); MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); MyMessage forecastMsg(BARO_CHILD, V_FORECAST); MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); void setup() { gw.begin(); dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("BaroHum", "2.0"); if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } // Register sensors to gw (they will be created as child devices) gw.present(BARO_CHILD, S_BARO); gw.present(TEMP_CHILD, S_TEMP); gw.present(CHILD_ID_HUM, S_HUM); gw.present(CHILD_ID_TEMP, S_TEMP); metric = gw.getConfig().isMetric; } void loop() { float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0; float temperatureBMP = bmp.readTemperature(); if (metric) { // Convert to fahrenheit temperatureBMP = temperatureBMP * 9.0 / 5.0 + 32.0; } int forecast = sample(pressure); Serial.print("Temperature = "); Serial.print(temperatureBMP); Serial.println(metric ? " *C" : " *F"); Serial.print("Pressure = "); Serial.print(pressure); Serial.println(" hPa"); Serial.print("Forecast = "); Serial.println(weather[forecast]); if (temperatureBMP != lastTempBMP) { gw.send(tempMsg.set(temperatureBMP, 1)); lastTempBMP = temperatureBMP; } if (pressure != lastPressure) { gw.send(pressureMsg.set(pressure, 0)); lastPressure = pressure; } if (forecast != lastForecast) { gw.send(forecastMsg.set(weather[forecast])); lastForecast = forecast; } delay(dht.getMinimumSamplingPeriod()); float temperatureDHT = dht.getTemperature(); if (isnan(temperatureDHT)) { Serial.println("Failed reading temperature from DHT"); } else if (temperatureDHT != lastTempDHT || nNoUpdatesTemp == FORCE_UPDATE_N_READS) { lastTempDHT = temperatureDHT; if (!metric) { temperatureDHT = dht.toFahrenheit(temperatureDHT); } nNoUpdatesTemp = 0; gw.send(msgTemp.set(temperatureDHT, 1)); Serial.print("T: "); Serial.println(temperatureDHT); } else { // Increase no update counter if the temperature stayed the same nNoUpdatesTemp++; } float humidity = dht.getHumidity(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) { lastHum = humidity; nNoUpdatesHum = 0; gw.send(msgHum.set(humidity, 1)); Serial.print("H: "); Serial.println(humidity); } else { // Increase no update counter if the temperature stayed the same nNoUpdatesHum++; } gw.sleep(SLEEP_TIME); } float getLastPressureSamplesAverage() { float lastPressureSamplesAverage = 0; for (int i = 0; i < LAST_SAMPLES_COUNT; i++) { lastPressureSamplesAverage += lastPressureSamples[i]; } lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; return lastPressureSamplesAverage; } // Algorithm found here // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf // Pressure in hPa --> forecast done by calculating kPa/h int sample(float pressure) { // Calculate the average of the last n minutes. int index = minuteCount % LAST_SAMPLES_COUNT; lastPressureSamples[index] = pressure; minuteCount++; if (minuteCount > 185) { minuteCount = 6; } if (minuteCount == 5) { pressureAvg = getLastPressureSamplesAverage(); } else if (minuteCount == 35) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 65) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) //first time initial 3 hour { 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 (minuteCount == 95) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 125) { float lastPressureAvg = getLastPressureSamplesAverage(); pressureAvg2 = lastPressureAvg; // store for later use. float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 155) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 185) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 } pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. } int forecast = ONBEKEND; if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval. { forecast = ONBEKEND; } else if (dP_dt < (-0.25)) { forecast = ONWEER; } else if (dP_dt > 0.25) { forecast = ONSTABIEL; } else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05))) { forecast = BEWOLKT; } else if ((dP_dt > 0.05) && (dP_dt < 0.25)) { forecast = ZONNIG; } else if ((dP_dt >(-0.05)) && (dP_dt < 0.05)) { forecast = STABIEL; } else { forecast = ONBEKEND; } // uncomment when debugging //Serial.print(F("Forecast at minute ")); //Serial.print(minuteCount); //Serial.print(F(" dP/dt = ")); //Serial.print(dP_dt); //Serial.print(F("kPa/h --> ")); //Serial.println(weather[forecast]); return forecast; } /** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik Ekblad * * DESCRIPTION * Pressure sensor example using BMP085 module * http://www.mysensors.org/build/pressure * Toegevoegd: na 10x dezelfde waarde te hebben gelezen bij TeEmp en Hum toch een waarde aan de GW sturen. */ #include <SPI.h> #include <Wire.h> #include <DHT.h> #include <MySensor.h> #include <Adafruit_BMP085.h> static const uint8_t FORCE_UPDATE_N_READS = 10; uint8_t nNoUpdatesTemp; uint8_t nNoUpdatesHum; #define BARO_CHILD 0 #define TEMP_CHILD 1 #define CHILD_ID_HUM 2 #define CHILD_ID_TEMP 3 #define HUMIDITY_SENSOR_DIGITAL_PIN 3 const float ALTITUDE = 1.05; // <-- adapt this value to your own location's altitude. // Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute. const unsigned long SLEEP_TIME = 60000; const char *weather[] = { "stabiel", "zonnig", "bewolkt", "onstabiel", "onweer", "onbekend" }; enum FORECAST { STABIEL = 0, // "Stable Weather Pattern" ZONNIG = 1, // "Slowly rising Good Weather", "Clear/Sunny " BEWOLKT = 2, // "Slowly falling L-Pressure ", "BEWOLKT/Rain " ONSTABIEL = 3, // "Quickly rising H-Press", "Not Stable" ONWEER = 4, // "Quickly falling L-Press", "ONWEER" ONBEKEND = 5 // "ONBEKEND (More Time needed) }; Adafruit_BMP085 bmp = Adafruit_BMP085(); // Digital Pressure Sensor MySensor gw; float lastPressure = -1; float lastTempBMP = -1; int lastForecast = -1; const int LAST_SAMPLES_COUNT = 5; float lastPressureSamples[LAST_SAMPLES_COUNT]; // this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm // get kPa/h be dividing hPa by 10 #define CONVERSION_FACTOR (1.0/10.0) int minuteCount = 0; bool firstRound = true; // average value is used in forecast algorithm. float pressureAvg; // average after 2 hours is used as reference value for the next iteration. float pressureAvg2; float dP_dt; DHT dht; float lastTempDHT; float lastHum; boolean metric = true; MyMessage tempMsg(TEMP_CHILD, V_TEMP); MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); MyMessage forecastMsg(BARO_CHILD, V_FORECAST); MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); void setup() { gw.begin(); dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("BaroHum", "2.0"); if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } // Register sensors to gw (they will be created as child devices) gw.present(BARO_CHILD, S_BARO); gw.present(TEMP_CHILD, S_TEMP); gw.present(CHILD_ID_HUM, S_HUM); gw.present(CHILD_ID_TEMP, S_TEMP); metric = gw.getConfig().isMetric; } void loop() { float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0; float temperatureBMP = bmp.readTemperature(); if (metric) { // Convert to fahrenheit temperatureBMP = temperatureBMP * 9.0 / 5.0 + 32.0; } int forecast = sample(pressure); Serial.print("Temperature = "); Serial.print(temperatureBMP); Serial.println(metric ? " *C" : " *F"); Serial.print("Pressure = "); Serial.print(pressure); Serial.println(" hPa"); Serial.print("Forecast = "); Serial.println(weather[forecast]); if (temperatureBMP != lastTempBMP) { gw.send(tempMsg.set(temperatureBMP, 1)); lastTempBMP = temperatureBMP; } if (pressure != lastPressure) { gw.send(pressureMsg.set(pressure, 0)); lastPressure = pressure; } if (forecast != lastForecast) { gw.send(forecastMsg.set(weather[forecast])); lastForecast = forecast; } delay(dht.getMinimumSamplingPeriod()); float temperatureDHT = dht.getTemperature(); if (isnan(temperatureDHT)) { Serial.println("Failed reading temperature from DHT"); } else if (temperatureDHT != lastTempDHT || nNoUpdatesTemp == FORCE_UPDATE_N_READS) { lastTempDHT = temperatureDHT; if (!metric) { temperatureDHT = dht.toFahrenheit(temperatureDHT); } nNoUpdatesTemp = 0; gw.send(msgTemp.set(temperatureDHT, 1)); Serial.print("T: "); Serial.println(temperatureDHT); } else { // Increase no update counter if the temperature stayed the same nNoUpdatesTemp++; } float humidity = dht.getHumidity(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) { lastHum = humidity; nNoUpdatesHum = 0; gw.send(msgHum.set(humidity, 1)); Serial.print("H: "); Serial.println(humidity); } else { // Increase no update counter if the temperature stayed the same nNoUpdatesHum++; } gw.sleep(SLEEP_TIME); } float getLastPressureSamplesAverage() { float lastPressureSamplesAverage = 0; for (int i = 0; i < LAST_SAMPLES_COUNT; i++) { lastPressureSamplesAverage += lastPressureSamples[i]; } lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; return lastPressureSamplesAverage; } // Algorithm found here // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf // Pressure in hPa --> forecast done by calculating kPa/h int sample(float pressure) { // Calculate the average of the last n minutes. int index = minuteCount % LAST_SAMPLES_COUNT; lastPressureSamples[index] = pressure; minuteCount++; if (minuteCount > 185) { minuteCount = 6; } if (minuteCount == 5) { pressureAvg = getLastPressureSamplesAverage(); } else if (minuteCount == 35) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 65) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) //first time initial 3 hour { 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 (minuteCount == 95) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 125) { float lastPressureAvg = getLastPressureSamplesAverage(); pressureAvg2 = lastPressureAvg; // store for later use. float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 155) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 (minuteCount == 185) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; if (firstRound) // first time initial 3 hour { 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 } pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. } int forecast = ONBEKEND; if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval. { forecast = ONBEKEND; } else if (dP_dt < (-0.25)) { forecast = ONWEER; } else if (dP_dt > 0.25) { forecast = ONSTABIEL; } else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05))) { forecast = BEWOLKT; } else if ((dP_dt > 0.05) && (dP_dt < 0.25)) { forecast = ZONNIG; } else if ((dP_dt >(-0.05)) && (dP_dt < 0.05)) { forecast = STABIEL; } else { forecast = ONBEKEND; } // uncomment when debugging //Serial.print(F("Forecast at minute ")); //Serial.print(minuteCount); //Serial.print(F(" dP/dt = ")); //Serial.print(dP_dt); //Serial.print(F("kPa/h --> ")); //Serial.println(weather[forecast]); return forecast; }