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. My Project
  3. My outdoor weather-sensor (5v powered combined temp, hum, pressure, and light)

My outdoor weather-sensor (5v powered combined temp, hum, pressure, and light)

Scheduled Pinned Locked Moved My Project
9 Posts 4 Posters 8.3k Views 5 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.
  • sundberg84S Offline
    sundberg84S Offline
    sundberg84
    Hardware Contributor
    wrote on last edited by sundberg84
    #1

    Hello!
    My first sensor not powered with battery - a outdoor sensor.

    A old temp sensor from a weather station was remade as box.
    With some drilling everything fit good inside.

    Inside DHT22 (Temp and Hum), LM393 (Light) and BMP085 (Pressure (Temp disabled)).

    Some build pictures:build.png

    and the final result:
    done.jpg

    Everything seems to work perfect in controller... now i can start making some relays to my window lamps so they can power up only when dark enough :)

    The code as well offcource:

    #include <SPI.h>
    #include <MySensor.h>  
    #include <Wire.h>
    #include <Adafruit_BMP085.h>
    #include <DHT.h>  
    
    //Sketch/Node
    #define SketchName "Ute sensor x4"
    #define SketchVer "1.3"
    #define NodeID 5
    
    //Bmp
    #define BARO_CHILD 0
    #define TEMP_CHILD 1 
    #define MetersAboveSeaLevel 130
    //DHT
    #define CHILD_ID_HUM 2
    #define CHILD_ID_TEMP 3
    #define HUMIDITY_SENSOR_DIGITAL_PIN 3
    //Light/LUX
    #define CHILD_ID_LIGHT 4
    #define LIGHT_SENSOR_ANALOG_PIN 0
    
    unsigned long SLEEP_TIME = 1*60000;
    //unsigned long SLEEP_TIME = 10000; //debug
    
    Adafruit_BMP085 bmp = Adafruit_BMP085();      // Digital Pressure Sensor 
    DHT dht;
    
    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);
    
    MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
    
    MySensor gw;
    
    //BMP
    float lastPressure = -1;
    int lastForecast = -1;
    int heartbeatBMP = 0;
    //float pressureSamples[180];
    
    const char *weather[] = { "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 int LAST_SAMPLES_COUNT = 5;
    float lastPressureSamples[LAST_SAMPLES_COUNT];
    #define MULTIPLIER (65.0/1023.0)
    
    int minuteCount = 0;
    bool firstRound = true;
    float pressureAvg[7];
    float dP_dt;
    boolean metric; 
    
    //DHT
    float lastTemp;
    float lastHum;
    
    //Light/LUX
    int lastLightLevel;
    int heartbeatLUX = 0;
    
    void setup() {
      gw.begin(NULL, NodeID, false);
      //incomingMessageCallback - Callback function for incoming messages from other nodes or controller and request responses. Default is NULL.
      //nodeId - The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller.
      //repeaterMode - Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo(SketchName, SketchVer);
    
      if (!bmp.begin()) {
        Serial.println("Could not find a valid BMP085 sensor, check wiring!");
        while (1) { }
      }
      
      //Setup DHT
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // 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);
    
      gw.present(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
      metric = gw.getConfig().isMetric;
    }
    
    void loop() {
    
      //-----------------------------------------------------------------------------//DHT
      delay(dht.getMinimumSamplingPeriod());
      float temperature = dht.getTemperature();
      
      if (isnan(temperature)) {
          Serial.println("Failed reading temperature from DHT");
      } else if (temperature != lastTemp) {
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        gw.send(msgTemp.set(temperature, 1));
        Serial.print("T: ");
        Serial.println(temperature);
      }
    
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
          Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum) {
          lastHum = humidity;
          gw.send(msgHum.set(humidity, 1));
          Serial.print("H: ");
          Serial.println(humidity);
      }
    
    //-----------------------------------------------------------------------------//BPM 
    
      float pressure = bmp.readSealevelPressure(MetersAboveSeaLevel)/100; // 130 meters above sealevel
      int forecast = sample(pressure);
      //Temp fetched from DHT
    
      Serial.print("Temperature = ");
      Serial.print(temperature);
      Serial.println(metric?" *C":" *F");
      Serial.print("Pressure = ");
      Serial.print(pressure);
      Serial.println(" Pa");
      Serial.println(weather[forecast]);
    
     if (isnan(pressure)) {
      Serial.println("Failed readin pressure");
     } else {
       
       if (pressure != lastPressure) {
        gw.send(pressureMsg.set(pressure, 0));
        lastPressure = pressure;
      heartbeatBMP = 0;
     
      }
      else
      {
        heartbeatBMP++;
        if (heartbeatBMP >= 24) {
          
        gw.send(pressureMsg.set(pressure, 0));
          heartbeatBMP = 0;
        }
      }
    }
    
      if (forecast != lastForecast) {
        gw.send(forecastMsg.set(weather[forecast]));
        lastForecast = forecast;
      }
      
      /*
       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) 
      */
    //-----------------------------------------------------------------------------//LJUS
    
      int lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; 
      Serial.print("Light: ");
      Serial.println(lightLevel);
      if (lightLevel != lastLightLevel) {
          gw.send(msg.set(lightLevel));
          lastLightLevel = lightLevel;
          heartbeatLUX = 0;
     
      }
      else
      {
        heartbeatLUX++;
        if (heartbeatLUX >= 24) {
          
          gw.send(msg.set(lightLevel));
          heartbeatLUX = 0;
        }
      }
    
    //-----------------------------------------------------------------------------//SLEEP
    
    gw.sleep(SLEEP_TIME); //sleep a bit
    }
    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
    
    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[0] = getLastPressureSamplesAverage();
    }
    else if (minuteCount == 35) {
        pressureAvg[1] = getLastPressureSamplesAverage();
        float change = (pressureAvg[1] - pressureAvg[0]);
        if (firstRound) // first time initial 3 hour
            dP_dt = (MULTIPLIER * 2 * change); // note this is for t = 0.5hour
        else
            dP_dt = ((MULTIPLIER * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
    }
    else if (minuteCount == 65) {
        pressureAvg[2] = getLastPressureSamplesAverage();
        float change = (pressureAvg[2] - pressureAvg[0]);
        if (firstRound) //first time initial 3 hour
            dP_dt = (MULTIPLIER * change); //note this is for t = 1 hour
        else
            dP_dt = ((MULTIPLIER * change) / 2); //divide by 2 as this is the difference in time from 0 value
    }
    else if (minuteCount == 95) {
        pressureAvg[3] = getLastPressureSamplesAverage();
        float change = (pressureAvg[3] - pressureAvg[0]);
        if (firstRound) // first time initial 3 hour
            dP_dt = ((MULTIPLIER * change) / 1.5); // note this is for t = 1.5 hour
        else
            dP_dt = ((MULTIPLIER * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
    }
    else if (minuteCount == 125) {
        pressureAvg[4] = getLastPressureSamplesAverage();
        float change = (pressureAvg[4] - pressureAvg[0]);
        if (firstRound) // first time initial 3 hour
            dP_dt = ((MULTIPLIER * change) / 2); // note this is for t = 2 hour
        else
            dP_dt = ((MULTIPLIER * change) / 3); // divide by 3 as this is the difference in time from 0 value
    }
    else if (minuteCount == 155) {
        pressureAvg[5] = getLastPressureSamplesAverage();
        float change = (pressureAvg[5] - pressureAvg[0]);
        if (firstRound) // first time initial 3 hour
            dP_dt = ((MULTIPLIER * change) / 2.5); // note this is for t = 2.5 hour
        else
            dP_dt = ((MULTIPLIER * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
    }
    else if (minuteCount == 185) {
        pressureAvg[6] = getLastPressureSamplesAverage();
        float change = (pressureAvg[6] - pressureAvg[0]);
        if (firstRound) // first time initial 3 hour
            dP_dt = ((MULTIPLIER * change) / 3); // note this is for t = 3 hour
        else
            dP_dt = ((MULTIPLIER * change) / 4); // divide by 4 as this is the difference in time from 0 value
    
        pressureAvg[0] = pressureAvg[5]; // 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; // Unknown
    
    return forecast;
    }
    

    Edit: Updated the code for right forecast algorithm See here

    Controller: Proxmox VM - Home Assistant
    MySensors GW: Arduino Uno - W5100 Ethernet, Gw Shield Nrf24l01+ 2,4Ghz
    MySensors GW: Arduino Uno - Gw Shield RFM69, 433mhz
    RFLink GW - Arduino Mega + RFLink Shield, 433mhz

    1 Reply Last reply
    2
    • m26872M Offline
      m26872M Offline
      m26872
      Hardware Contributor
      wrote on last edited by m26872
      #2

      @sundberg84
      Nice. But don't you miss a gw.process() call in your sketch? It looks like you wanted a repeater node. Just remove the gw.sleep(..) and replace it with gw.process() and some timing if-statement.

      1 Reply Last reply
      0
      • sundberg84S Offline
        sundberg84S Offline
        sundberg84
        Hardware Contributor
        wrote on last edited by
        #3

        @m26872 Yes i did! - Thank you, good feedback.
        I will add that.

        Also i will clean upp the code some, because it send temp both from DHT and BMP now i think.

        Controller: Proxmox VM - Home Assistant
        MySensors GW: Arduino Uno - W5100 Ethernet, Gw Shield Nrf24l01+ 2,4Ghz
        MySensors GW: Arduino Uno - Gw Shield RFM69, 433mhz
        RFLink GW - Arduino Mega + RFLink Shield, 433mhz

        1 Reply Last reply
        0
        • sundberg84S Offline
          sundberg84S Offline
          sundberg84
          Hardware Contributor
          wrote on last edited by sundberg84
          #4

          I ended up not using the process() but sleep() because with three sensors it was spamming the controller.
          I thought about some if statements or something to limit the spam but realised that i didnt needed it bad as a relay so...

          Also attaching a picture of my power supply - a Ipad plug stripped and used as a 240v -> 5v converter inside a outdoor safe box.
          150618-DSC_0063.JPG

          Then ran a telephone wire with the 5v to the sensor.

          Controller: Proxmox VM - Home Assistant
          MySensors GW: Arduino Uno - W5100 Ethernet, Gw Shield Nrf24l01+ 2,4Ghz
          MySensors GW: Arduino Uno - Gw Shield RFM69, 433mhz
          RFLink GW - Arduino Mega + RFLink Shield, 433mhz

          1 Reply Last reply
          0
          • m26872M Offline
            m26872M Offline
            m26872
            Hardware Contributor
            wrote on last edited by
            #5

            To make sure outdoor boxed equipment survive a swedish climate more than a year, I'd put some heater inside each box as well. Even a waterproof design will produce moisture from the inside air due to the temperature variations.

            AWIA 1 Reply Last reply
            0
            • m26872M m26872

              To make sure outdoor boxed equipment survive a swedish climate more than a year, I'd put some heater inside each box as well. Even a waterproof design will produce moisture from the inside air due to the temperature variations.

              AWIA Offline
              AWIA Offline
              AWI
              Hero Member
              wrote on last edited by
              #6

              @m26872 I'm interested in what is best against moisture in outside equipment. Would just ventilation be a good idea? Traffic system controllers are not in heated or waterproof casings.. Any experience somebody?

              SparkmanS 1 Reply Last reply
              0
              • AWIA AWI

                @m26872 I'm interested in what is best against moisture in outside equipment. Would just ventilation be a good idea? Traffic system controllers are not in heated or waterproof casings.. Any experience somebody?

                SparkmanS Offline
                SparkmanS Offline
                Sparkman
                Hero Member
                wrote on last edited by
                #7

                @AWI @m26872 I've had X-10 indoor rated outlets installed outside in northern Canadian climate for 7+ years with no failures. Humidity was not so much a problem, but extreme temperatures were (-45C to +35C). Their fronts were shielded from direct contact with rain & snow and the outlet itself was in an outdoor rated outlet box, but this was not 100% waterproof nor was it heated other than from the waste heat of the electronics.

                Cheers
                Al

                1 Reply Last reply
                0
                • m26872M Offline
                  m26872M Offline
                  m26872
                  Hardware Contributor
                  wrote on last edited by
                  #8

                  I started this thread to continue enclosure protection discussion without polluting this project thread to much.

                  1 Reply Last reply
                  0
                  • sundberg84S Offline
                    sundberg84S Offline
                    sundberg84
                    Hardware Contributor
                    wrote on last edited by
                    #9

                    --- New question on this old post

                    This node has started to behave strange. There is three sensors and lux is working 100% but DHT and LM393 stops working from time to time. It can suddenly stop sending these two values for 24 hours, and then they are back online again. Lux sensor works all the time.

                    Havent bothered to do a serial log yet since its outside and working most of the time - but any thoughs anyone?

                    Controller: Proxmox VM - Home Assistant
                    MySensors GW: Arduino Uno - W5100 Ethernet, Gw Shield Nrf24l01+ 2,4Ghz
                    MySensors GW: Arduino Uno - Gw Shield RFM69, 433mhz
                    RFLink GW - Arduino Mega + RFLink Shield, 433mhz

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


                    14

                    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