Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Weather station

Weather station

Scheduled Pinned Locked Moved Troubleshooting
12 Posts 3 Posters 5.1k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • HeinzH Offline
    HeinzH Offline
    Heinz
    Hero Member
    wrote on last edited by
    #3

    The BMP085 and the DHT have both a temperature: lastTemp of both sketches collide!
    Have a look at this sketch which is a merge of a BMP085 and a DHT
    https://github.com/windkh/mysensors/blob/master/WeatherStationSensor/WeatherStationSensor.ino

    1 Reply Last reply
    0
    • HeinzH Heinz

      Wiring is shown here
      http://www.mysensors.org/build/pressure

      The child ids of BARO and LIGHT are both 2 in your sketch.

      N Offline
      N Offline
      NBM
      wrote on last edited by
      #4

      @Heinz I know. But is it possible to use A2 and A3?

      HeinzH 1 Reply Last reply
      0
      • N NBM

        @Heinz I know. But is it possible to use A2 and A3?

        HeinzH Offline
        HeinzH Offline
        Heinz
        Hero Member
        wrote on last edited by
        #5

        @NBM said:

        @Heinz I know. But is it possible to use A2 and A3?

        I don't know.

        1 Reply Last reply
        0
        • HeinzH Offline
          HeinzH Offline
          Heinz
          Hero Member
          wrote on last edited by Heinz
          #6

          A function is missing in your case:

          void incomingMessage(const MyMessage &message){}
          
          N D 2 Replies Last reply
          0
          • HeinzH Heinz

            A function is missing in your case:

            void incomingMessage(const MyMessage &message){}
            
            N Offline
            N Offline
            NBM
            wrote on last edited by
            #7

            @Heinz Thank you.

            I have made this sketch without errors.

            // DHT-Sensor
            // BMP085 Sensor
            
            #include <SPI.h>
            #include <MySensor.h>
            #include <Wire.h>
            #include <Adafruit_BMP085_U.h>
            #include <Adafruit_Sensor.h>
            #include <DHT.h>  
            
            
            const bool sendAlways = true;
            
            const float SEALEVEL = 688; // Westendorf
            const float SEALEVEL_PRESSURE = 1013.25;
            
            // ----------------------------------------------------------------------------
            #define CHILD_ID_HUM 2
            #define CHILD_ID_TEMP 3
            #define HUMIDITY_SENSOR_DIGITAL_PIN 3
            #define CHILD_ID_LIGHT 1
            #define LIGHT_SENSOR_ANALOG_PIN 1
            
            DHT dht;
            float lastTemp;
            float lastHum;
            boolean metric = true;
            MyMessage msgHum(CHILD_ID_HUM, V_HUM);
            MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
            
            
            // ----------------------------------------------------------------------------
            #define BARO_CHILD 0
            #define TEMP_CHILD 1
            
            unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
            unsigned long SLEEP_TIME1 = 30000; // 1 minute required for forecast algorithm
            unsigned long SLEEP_TIME2 = 30000; // 1 minute required for forecast algorithm
            unsigned long SLEEP_TIME3 = 900000;  // sleep time between reads (seconds * 1000 milliseconds)
            
            
            Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(1);    // Digital Pressure Sensor 
            MySensor gw;
            
            MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
            int lastLightLevel;
            int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
            int oldBatteryPcnt = 0;
            
            /*
            DP/Dt explanation
            0 = "Stable Weather Pattern"
            1 = "Slowly rising Good Weather", "Clear/Sunny "
            2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
            3 = "Quickly rising H-Press",     "Not Stable"
            4 = "Quickly falling L-Press",    "Thunderstorm"
            5 = "Unknown (More Time needed)
            */
            
            const char *weatherStrings[] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" };
            enum FORECAST
            {
              STABLE = 0,     // Stable weather
              SUNNY = 1,      // Slowly rising HP stable good weather
              CLOUDY = 2,     // Slowly falling Low Pressure System, stable rainy weather
              UNSTABLE = 3,   // Quickly rising HP, not stable weather
              THUNDERSTORM = 4, // Quickly falling LP, Thunderstorm, not stable
              UNKNOWN = 5     // Unknown, more time needed
            };
            
            const char *situationStrings[] = { "very low", "low", "normal", "high", "very high" };
            enum WEATHER_SITUATION
            {
              VERY_LOW_PRESSURE = 0,    // Tiefdruck p>-7.5hPa
              LOW_PRESSURE = 1,     // Tiefdruck p>-2.5hPa
              NORMAL_PRESSURE = 2,    // Normal  p <+/-02.5hPa  
              HIGH_PRESSURE = 3,      // Hochdruck p>2.5hPa
              VERY_HIGH_PRESSURE = 4,   // Hochdruck p>7.5hPa
            };
            
            float lastPressure = -1;
            float lastPressureTemp = -1;
            int lastForecast = -1;
            int lastSituation = NORMAL_PRESSURE;
            
            const int LAST_SAMPLES_COUNT = 5;
            float lastPressureSamples[LAST_SAMPLES_COUNT];
            
            // 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 situationMsg(BARO_CHILD, V_VAR1);
            MyMessage forecastMsg2(BARO_CHILD, V_VAR2);
            
            void displaySensorDetails(void)
            {
              sensor_t sensor;
              bmp.getSensor(&sensor);
              Serial.println(F("------------------------------------"));
              Serial.print(F("Sensor:       ")); Serial.println(sensor.name);
              Serial.print(F("Driver Ver:   ")); Serial.println(sensor.version);
              Serial.print(F("Unique ID:    ")); Serial.println(sensor.sensor_id);
              Serial.print(F("Max Value:    ")); Serial.print(sensor.max_value); Serial.println(F(" hPa"));
              Serial.print(F("Min Value:    ")); Serial.print(sensor.min_value); Serial.println(F(" hPa"));
              Serial.print(F("Resolution:   ")); Serial.print(sensor.resolution); Serial.println(F(" hPa"));
              Serial.println(F("------------------------------------"));
              Serial.println(F(""));
              delay(500);
            }
            
            void initPressureSensor()
            {
              if (!bmp.begin())
              {
                Serial.println(F("Could not find a valid BMP085 sensor, check wiring!"));
                while (1) {}
              }
            
              displaySensorDetails();
            }
            
            void initHumiditySensor()
            {
              dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
            }
            
            void setup() 
            {
                 // use the 1.1 V internal reference
              #if defined(__AVR_ATmega2560__)
               analogReference(INTERNAL1V1);
              #else
               analogReference(INTERNAL);
              #endif
              gw.begin();
              gw.sendSketchInfo("Weather Station Sensor", "2.1");
            
              initPressureSensor();
              initHumiditySensor();
            
              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);
              gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
            
              metric = gw.getConfig().isMetric;
            
             int lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; 
              Serial.println(lightLevel);
              if (lightLevel != lastLightLevel) {
                  gw.send(msg.set(lightLevel));
                  lastLightLevel = lightLevel;
              }
               gw.sleep(SLEEP_TIME);  
            }
            
            int getWeatherSituation(float pressure)
            {
              int situation = NORMAL_PRESSURE;
            
              float delta = pressure - SEALEVEL_PRESSURE;
              if (delta > 7.5)
              {
                situation = VERY_HIGH_PRESSURE;
              }
              else if (delta > 2.5)
              {
                situation = HIGH_PRESSURE;
              }
              else if (delta < -7.5)
              {
                situation = VERY_LOW_PRESSURE;
              }
              else if (delta < -2.5)
              {
                situation = LOW_PRESSURE;
              }
              else
              {
                situation = NORMAL_PRESSURE;
              }
            
              return situation;
            }
            
            bool updatePressureSensor()
            {
              bool changed = false;
            
              sensors_event_t event;
              bmp.getEvent(&event);
            
              if (event.pressure)
              {
                float absolutePressure = event.pressure;
                Serial.print(F("abs Pressure = "));
                Serial.print(absolutePressure);
                Serial.println(F(" hPa"));
                
                //float altitude = bmp.pressureToAltitude(SEALEVEL_PRESSURE, pressure);
                //Serial.print(F("Altitude = "));
                //Serial.print(altitude);
                //Serial.println(F(" m"));
            
                //sealevel pressure p0 from absolute pressure.
                float pressure = bmp.seaLevelForAltitude(SEALEVEL, absolutePressure);
            
                float pressureTemperature;
                bmp.getTemperature(&pressureTemperature);
            
                if (!metric) 
                {
                  // Convert to fahrenheit
                  pressureTemperature = pressureTemperature * 9.0 / 5.0 + 32.0;
                }
            
                int forecast = sample(pressure);
                int situation = getWeatherSituation(pressure);
            
            
                if (sendAlways || (pressureTemperature != lastPressureTemp))
                {
                  changed = true;
                  lastPressureTemp = pressureTemperature;
                  Serial.print(F("Temperature = "));
                  Serial.print(pressureTemperature);
                  Serial.println(metric ? F(" *C") : F(" *F"));
                  if (!gw.send(tempMsg.set(lastPressureTemp, 1)))
                  {
                    lastPressureTemp = -1.0;
                  }
                }
            
            
                if (sendAlways || (pressure != lastPressure))
                {
                  changed = true;
                  lastPressure = pressure;
                  Serial.print(F("sealevel Pressure = "));
                  Serial.print(pressure);
                  Serial.println(F(" hPa"));
                  if (!gw.send(pressureMsg.set(lastPressure, 1)))
                  {
                    lastPressure = -1.0;
                  }
                }
            
            
                if (sendAlways || (forecast != lastForecast))
                {
                  changed = true;
                  lastForecast = forecast;
                  Serial.print(F("Forecast = "));
                  Serial.println(weatherStrings[forecast]);
                  if (gw.send(forecastMsg.set(weatherStrings[lastForecast])))
                  {
                    if (!gw.send(forecastMsg2.set(lastForecast)))
                    {
                    }
                  }
                  else
                  {
                    lastForecast = -1.0;
                  }
                }
            
            
                if (sendAlways || (situation != lastSituation))
                {
                  changed = true;
                  lastSituation = situation;
                  Serial.print(F("Situation = "));
                  Serial.println(situationStrings[situation]);
                  if (!gw.send(situationMsg.set(lastSituation, 0)))
                  {
                    lastSituation = -1.0;
                  }
                }
              }
            
              return changed;
            }
            
            bool updateHumiditySensor()
            {
              bool changed = false;
            
              float temperature = dht.getTemperature();
              float humidity = dht.getHumidity();
            
              if (!isnan(temperature))
              {
            #ifdef SEND_WHEN_CHANGED
                if (temperature != lastTemp)
            #endif
                {
                  lastTemp = temperature;
                  if (!metric)
                  {
                    temperature = dht.toFahrenheit(temperature);
                  }
                  changed = true;
                  Serial.print(F("T: "));
                  Serial.println(temperature);
                  if (!gw.send(msgTemp.set(temperature, 1)))
                  {
                    lastTemp = -1.0;
                  }
                }
              }
              else
              {
                Serial.println(F("Failed reading temperature from DHT"));
              }
              
              
              if (!isnan(humidity))
              {
            #ifdef SEND_WHEN_CHANGED
                if (humidity != lastHum)
            #endif
                {
                  lastHum = humidity;
                  changed = true;
                  Serial.print(F("H: "));
                  Serial.println(humidity);
                  if (!gw.send(msgHum.set(lastHum, 1)))
                  {
                    lastHum = -1.0;
                  }
                }
              }
              else
              {
                Serial.println(F("Failed reading humidity from DHT"));
              }
              
              return changed;
            }
            
            void loop() 
            {
               // get the battery Voltage
               int sensorValue = analogRead(BATTERY_SENSE_PIN);
               #ifdef DEBUG
               Serial.println(sensorValue);
               #endif
               
               // 1M, 470K divider across battery and using internal ADC ref of 1.1V
               // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
               // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
               // 3.44/1023 = Volts per bit = 0.003363075
               float batteryV  = sensorValue * 0.003363075;
               int batteryPcnt = sensorValue / 10;
            
               #ifdef DEBUG
               Serial.print("Battery Voltage: ");
               Serial.print(batteryV);
               Serial.println(" V");
            
               Serial.print("Battery percent: ");
               Serial.print(batteryPcnt);
               Serial.println(" %");
               #endif
            
               if (oldBatteryPcnt != batteryPcnt) {
                 // Power up radio after sleep
                 gw.sendBatteryLevel(batteryPcnt);
                 oldBatteryPcnt = batteryPcnt;
               }
              updatePressureSensor();
              gw.sleep(SLEEP_TIME1);
              updateHumiditySensor();
              gw.sleep(SLEEP_TIME2);
            
              gw.sleep(SLEEP_TIME3);
            }
            
            
            float getLastPressureSamplesAverage()
            {
              float lastPressureSamplesAverage = 0;
              for (int i = 0; i < LAST_SAMPLES_COUNT; i++)
              {
                lastPressureSamplesAverage += lastPressureSamples[i];
              }
              lastPressureSamplesAverage /= LAST_SAMPLES_COUNT;
            
              //Serial.print(F("### 5min-Average:"));
              //Serial.print(lastPressureSamplesAverage);
              //Serial.println(F(" hPa"));
            
              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;
              }
            
              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(weatherStrings[forecast]);
            
              return forecast;
            }```
            1 Reply Last reply
            1
            • HeinzH Heinz

              A function is missing in your case:

              void incomingMessage(const MyMessage &message){}
              
              D Offline
              D Offline
              Dylano
              wrote on last edited by
              #8

              @Heinz

              Is this sketch working great now?
              And how is the battery?
              How long can work this sketch, on what type battery?

              Domoticz, with a lot of working hardware, include mysensors :-)
              OpenPLI, RuneAudio, Solarmeter, etc......

              Not a great builder of software and hardware, more a user...
              Only i try to do my best :-(

              1 Reply Last reply
              0
              • HeinzH Offline
                HeinzH Offline
                Heinz
                Hero Member
                wrote on last edited by
                #9

                @Dylano the sketch in this thread is from @NBM, if you mean
                https://github.com/windkh/mysensors/blob/master/WeatherStationSensor/WeatherStationSensor.ino
                then this one is working very well.

                This one is the official mysensors example
                https://github.com/mysensors/Arduino/blob/development/libraries/MySensors/examples/WeatherStationSensor/WeatherStationSensor.ino

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  Dylano
                  wrote on last edited by
                  #10

                  still got an error:
                  C:\Users\DM_PC\Desktop\Mysensors 23-2-2015\Sketches Werkend\sketch_mar05a\sketch_mar05a.ino:8:29: fatal error: Adafruit_Sensor.h: No such file or directory

                  #include <Adafruit_Sensor.h>

                  Only where can i download the adafruit library?

                  Domoticz, with a lot of working hardware, include mysensors :-)
                  OpenPLI, RuneAudio, Solarmeter, etc......

                  Not a great builder of software and hardware, more a user...
                  Only i try to do my best :-(

                  HeinzH 1 Reply Last reply
                  0
                  • D Dylano

                    still got an error:
                    C:\Users\DM_PC\Desktop\Mysensors 23-2-2015\Sketches Werkend\sketch_mar05a\sketch_mar05a.ino:8:29: fatal error: Adafruit_Sensor.h: No such file or directory

                    #include <Adafruit_Sensor.h>

                    Only where can i download the adafruit library?

                    HeinzH Offline
                    HeinzH Offline
                    Heinz
                    Hero Member
                    wrote on last edited by
                    #11

                    @Dylano

                    https://github.com/adafruit/Adafruit_Sensor
                    https://github.com/adafruit/Adafruit_BMP085_Unified

                    D 1 Reply Last reply
                    0
                    • HeinzH Heinz

                      @Dylano

                      https://github.com/adafruit/Adafruit_Sensor
                      https://github.com/adafruit/Adafruit_BMP085_Unified

                      D Offline
                      D Offline
                      Dylano
                      wrote on last edited by
                      #12

                      @Heinz said:

                      @Dylano

                      https://github.com/adafruit/Adafruit_Sensor
                      https://github.com/adafruit/Adafruit_BMP085_Unified

                      Thanks!!!

                      Domoticz, with a lot of working hardware, include mysensors :-)
                      OpenPLI, RuneAudio, Solarmeter, etc......

                      Not a great builder of software and hardware, more a user...
                      Only i try to do my best :-(

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      12

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.1k

                      Posts


                      Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • MySensors
                      • OpenHardware.io
                      • Categories
                      • Recent
                      • Tags
                      • Popular