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. Hardware
  3. BME280 temp/humidity/pressure sensor

BME280 temp/humidity/pressure sensor

Scheduled Pinned Locked Moved Hardware
31 Posts 13 Posters 32.6k Views 17 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.
  • hekH Offline
    hekH Offline
    hek
    Admin
    wrote on last edited by
    #13

    Hmm.. I wonder if this change might have interfered with the Vera plugin.

    https://github.com/mysensors/Arduino/commit/bbc6a221f4c153f41993207e521f5531ba853d1a

    https://github.com/mysensors/Arduino/pull/420

    signal15S 1 Reply Last reply
    0
    • hekH hek

      Hmm.. I wonder if this change might have interfered with the Vera plugin.

      https://github.com/mysensors/Arduino/commit/bbc6a221f4c153f41993207e521f5531ba853d1a

      https://github.com/mysensors/Arduino/pull/420

      signal15S Offline
      signal15S Offline
      signal15
      wrote on last edited by
      #14

      @hek

      Let me know if you make a change and need me to test.

      1 Reply Last reply
      0
      • signal15S signal15

        Awesome. I just got it working with a test sketch like 2 minutes ago. If I get a working sketch for MySensors, how can I get it uploaded to the site as an example?

        Also, if anyone has done it before, I'd appreciate any code you might have to save some time. I only get like 5 minutes here an there to work on this.

        Y Offline
        Y Offline
        yoshida
        wrote on last edited by
        #15

        @emc2 or anybody:

        Does anyone have a working BME280 mysensors arduino sketch? The code above states include mysensor.h now it is mysensorS.h, so I have renamed, but it won't compile, it says:

        In function 'void setup()':
        
        bme280:252: error: 'getConfig' was not declared in this scope
        

        I have a MySensors Gateway USB
        Version: 2.1.1 (arduino nano) with Domoticz, and I would like to use the bme280 for a battery powered outdoor temp/humidity/barometer (as DHT22 does not like battery level below 3.3V, and I would run on 2x1.5V AA)

        Thanks

        1 Reply Last reply
        0
        • E Offline
          E Offline
          emc2
          Hardware Contributor
          wrote on last edited by
          #16

          Was modified in 2.1.1, you need to change

          metric = getConfig().isMetric;
          

          to

          metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
          
          Y 1 Reply Last reply
          1
          • A Offline
            A Offline
            anno
            wrote on last edited by anno
            #17

            Still a lot of errors in this sketch, did take some out but this is still in it:

            In file included from C:\Users\x\Documents\Arduino\BME280_sensor\BME280_sensor.ino:48:0:

            C:\Users\x\Documents\Arduino\libraries\BME280/BME280_MOD-1022.h:41:21: warning: extra tokens at end of #ifndef directive

            #ifndef __BME280_MOD-1022_H

                             ^
            

            C:\Users\x\Documents\Arduino\libraries\BME280/BME280_MOD-1022.h:42:21: warning: ISO C99 requires whitespace after the macro name

            #define __BME280_MOD-1022_H

                             ^
            

            In file included from C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp:40:0:

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.h:41:21: warning: extra tokens at end of #ifndef directive

            #ifndef __BME280_MOD-1022_H

                             ^
            

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.h:42:21: warning: ISO C99 requires whitespace after the macro name

            #define __BME280_MOD-1022_H

                             ^
            

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp: In member function 'BME280Class::readCompensationParams()':

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp:276:45: warning: iteration 20 invokes undefined behavior [-Waggressive-loop-optimizations]

            compParams.compArray[count] = Wire.read();
            
                                                     ^
            

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp:275:3: note: containing loop

            for (count = 0; count < 28; count++) { // first 28 bytes we can process like this

            ^

            C:\Users\x\Documents\Arduino\BME280_sensor\BME280_sensor.ino: In function 'loop':

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp:276:45: warning: iteration 20 invokes undefined behavior [-Waggressive-loop-optimizations]

            compParams.compArray[count] = Wire.read();
            
                                                     ^
            

            C:\Users\x\Documents\Arduino\libraries\BME280\BME280_MOD-1022.cpp:275:3: note: containing loop

            for (count = 0; count < 28; count++) { // first 28 bytes we can process like this

            1 Reply Last reply
            0
            • E emc2

              Was modified in 2.1.1, you need to change

              metric = getConfig().isMetric;
              

              to

              metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
              
              Y Offline
              Y Offline
              yoshida
              wrote on last edited by
              #18

              @emc2 Thanks! With this modification the sketch compiled successfully. Today I had time, so put everything together, and the BME280 works with the 2.4GH radio, temp/hum/pressure all reporting like they should.

              Using arduino pro mini, bme280, nrf24, 2XAA Batteries. It reports to the mysensors serial gw, and then shown in domoticz.

              Z 1 Reply Last reply
              2
              • Y yoshida

                @emc2 Thanks! With this modification the sketch compiled successfully. Today I had time, so put everything together, and the BME280 works with the 2.4GH radio, temp/hum/pressure all reporting like they should.

                Using arduino pro mini, bme280, nrf24, 2XAA Batteries. It reports to the mysensors serial gw, and then shown in domoticz.

                Z Offline
                Z Offline
                Zbigniew Ko
                wrote on last edited by
                #19

                @yoshida Hello
                You can share your sketch.
                Please
                I can not make modifications.
                I still have a lot of errors.

                Y 1 Reply Last reply
                0
                • A Offline
                  A Offline
                  anno
                  wrote on last edited by anno
                  #20
                  This post is deleted!
                  1 Reply Last reply
                  0
                  • Z Zbigniew Ko

                    @yoshida Hello
                    You can share your sketch.
                    Please
                    I can not make modifications.
                    I still have a lot of errors.

                    Y Offline
                    Y Offline
                    yoshida
                    wrote on last edited by
                    #21

                    Zbigniew Ko:

                    (2.1.1 mysensors compatible, but first you need to install the BME280_MOD-1022.h library in arduino IDE)

                    /**
                     * 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
                     *
                     */
                    
                    // 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>
                    
                    // BME280 libraries and variables
                    // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                    // Written originally by Embedded Adventures
                    // https://github.com/embeddedadventures/BME280
                    #include <BME280_MOD-1022.h>
                    
                    #define BARO_CHILD 0
                    #define TEMP_CHILD 1
                    #define HUM_CHILD 2
                    
                    const float ALTITUDE = 184; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                    
                    // Sleep time between reads (in ms). 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)
                    };
                    
                    float lastPressure = -1;
                    float lastTemp = -1;
                    float lastHum = -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 the forecast algorithm
                    // get kPa/h by 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;
                    boolean metric;
                    MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                    MyMessage humMsg(HUM_CHILD, V_HUM);
                    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                    MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                    
                    
                    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;
                    }
                    
                    
                    void setup() {
                      metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                      Wire.begin(); // Wire.begin(sda, scl)
                    }
                    
                    void presentation()  {
                      // Send the sketch version information to the gateway and Controller
                      sendSketchInfo("BME280 Sensor", "1.6");
                    
                      // Register sensors to gw (they will be created as child devices)
                      present(BARO_CHILD, S_BARO);
                      present(TEMP_CHILD, S_TEMP);
                      present(HUM_CHILD, S_HUM);
                    }
                    
                    // Loop
                    void loop() {
                      
                      // need to read the NVM compensation parameters
                      BME280.readCompensationParams();
                    
                      /* After taking the measurement the chip goes back to sleep, use when battery powered.
                      // Oversampling settings (os1x, os2x, os4x, os8x or os16x).
                      BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient, higher numbers avoid sudden changes to be accounted for (such as slamming a door)
                      BME280.writeOversamplingPressure(os16x);    // pressure x16
                      BME280.writeOversamplingTemperature(os8x);  // temperature x8
                      BME280.writeOversamplingHumidity(os8x);     // humidity x8
                    
                      BME280.writeMode(smForced);                 // Forced sample.  After taking the measurement the chip goes back to sleep
                      */
                    
                      // Normal mode for regular automatic samples
                      BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                      BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                      BME280.writeOversamplingPressure(os16x);    // pressure x16
                      BME280.writeOversamplingTemperature(os8x);  // temperature x8
                      BME280.writeOversamplingHumidity(os8x);     // humidity x8
                      
                      BME280.writeMode(smNormal);
                      
                      while (1) {
                        // Just to be sure, wait until sensor is done mesuring  
                        while (BME280.isMeasuring()) {
                      }
                      
                      // Read out the data - must do this before calling the getxxxxx routines
                      BME280.readMeasurements();
                    
                      float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                      float humidity = BME280.getHumidityMostAccurate();
                      float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                      float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                      int forecast = sample(pressure);
                      
                      if (!metric) 
                      {
                        // Convert to fahrenheit
                        temperature = temperature * 9.0 / 5.0 + 32.0;
                      }
                    
                      Serial.println();
                      Serial.print("Temperature = ");
                      Serial.print(temperature);
                      Serial.println(metric ? " °C" : " °F");
                      Serial.print("Humidity = ");
                      Serial.print(humidity);
                      Serial.println(" %");
                      Serial.print("Pressure = ");
                      Serial.print(pressure);
                      Serial.println(" hPa");
                      Serial.print("Forecast = ");
                      Serial.println(weather[forecast]);
                      Serial.println();
                    
                    
                      if (temperature != lastTemp) 
                      {
                        send(tempMsg.set(temperature, 1));
                        lastTemp = temperature;
                      }
                    
                    
                      if (humidity != lastHum) 
                      {
                        send(humMsg.set(humidity, 1));
                        lastHum = humidity;
                      }
                    
                      if (pressure != lastPressure) 
                      {
                        send(pressureMsg.set(pressure, 2));
                        lastPressure = pressure;
                      }
                    
                      if (forecast != lastForecast)
                      {
                        send(forecastMsg.set(weather[forecast]));
                        lastForecast = forecast;
                      }
                      
                      sleep(SLEEP_TIME);
                      
                    }
                    }
                    
                    
                    1 Reply Last reply
                    0
                    • Z Offline
                      Z Offline
                      Zbigniew Ko
                      wrote on last edited by Zbigniew Ko
                      #22

                      @yoshida Thank you very much.
                      As soon as I find time I will check it out.

                      Yes checked, sketch works.
                      Thanks yoshida.
                      Please note that the library BME_MOD-1022.h consists of two parts: file-h, and file cpp.

                      1 Reply Last reply
                      0
                      • gohanG Offline
                        gohanG Offline
                        gohan
                        Mod
                        wrote on last edited by
                        #23

                        I am using the one from adafruit : what's the difference with this other library?

                        alexsh1A 1 Reply Last reply
                        0
                        • gohanG gohan

                          I am using the one from adafruit : what's the difference with this other library?

                          alexsh1A Offline
                          alexsh1A Offline
                          alexsh1
                          wrote on last edited by
                          #24

                          @gohan I have been using both libraries with a chinese module I bought from Aliexpress. I did not notice any differences apart from size and maybe a module address, which you can change in either library.

                          1 Reply Last reply
                          0
                          • B Offline
                            B Offline
                            bluezr1
                            wrote on last edited by
                            #25

                            I used the last sketch posed by Yoshida and for some reason whenever the temp and humidity goes through a stretch where there isn't any change, it's as if the node goes into a deep sleep and doesn't come out of it until I hit the reset on a pro mini.

                            I have it plunged in and not on batteries, so no need for any deep sleep. Is there anything I can change in the sketch? I'm still fairly new at this, although I'm having a blast.

                            Thanks,

                            Y 1 Reply Last reply
                            0
                            • B bluezr1

                              I used the last sketch posed by Yoshida and for some reason whenever the temp and humidity goes through a stretch where there isn't any change, it's as if the node goes into a deep sleep and doesn't come out of it until I hit the reset on a pro mini.

                              I have it plunged in and not on batteries, so no need for any deep sleep. Is there anything I can change in the sketch? I'm still fairly new at this, although I'm having a blast.

                              Thanks,

                              Y Offline
                              Y Offline
                              yoshida
                              wrote on last edited by
                              #26

                              @bluezr1 Interesting... :) I used it with a pro mini as well, and my problem was that it ate up the batteries in 2 weeks... :D So I would need more deep sleep for the same sketch :D

                              But for that 2 weeks, it was working well. Temp/Hum/Baro updated every minute.

                              mfalkviddM 1 Reply Last reply
                              0
                              • Y yoshida

                                @bluezr1 Interesting... :) I used it with a pro mini as well, and my problem was that it ate up the batteries in 2 weeks... :D So I would need more deep sleep for the same sketch :D

                                But for that 2 weeks, it was working well. Temp/Hum/Baro updated every minute.

                                mfalkviddM Offline
                                mfalkviddM Offline
                                mfalkvidd
                                Mod
                                wrote on last edited by mfalkvidd
                                #27

                                @yoshida did you do the modifications (remove led and regulator) recommended at https://www.mysensors.org/build/battery ?

                                My storage room sensor (https://forum.mysensors.org/topic/7227/esp8266-wifi-gateway-with-rssi-for-rfm69-and-wifi ) uses the bme280. Not sure if that sketch is any help, but you are welcome to use it. It is much much simpler than the sketch posted above though.

                                Y 1 Reply Last reply
                                0
                                • mfalkviddM mfalkvidd

                                  @yoshida did you do the modifications (remove led and regulator) recommended at https://www.mysensors.org/build/battery ?

                                  My storage room sensor (https://forum.mysensors.org/topic/7227/esp8266-wifi-gateway-with-rssi-for-rfm69-and-wifi ) uses the bme280. Not sure if that sketch is any help, but you are welcome to use it. It is much much simpler than the sketch posted above though.

                                  Y Offline
                                  Y Offline
                                  yoshida
                                  wrote on last edited by
                                  #28

                                  @mfalkvidd good question, yes I have removed the two leds I found, but I am too lame to remove the voltage regulator :( I have read here that the most consuming part is the LED(s)

                                  1 Reply Last reply
                                  1
                                  • S Offline
                                    S Offline
                                    scalpel
                                    wrote on last edited by gohan
                                    #29

                                    @yoshida said in BME280 temp/humidity/pressure sensor:

                                    > /**
                                    >  * 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
                                    >  *
                                    >  */
                                    > 
                                    > // 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>
                                    > 
                                    > // BME280 libraries and variables
                                    > // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                                    > // Written originally by Embedded Adventures
                                    > // https://github.com/embeddedadventures/BME280
                                    > #include <BME280_MOD-1022.h>
                                    > 
                                    > #define BARO_CHILD 0
                                    > #define TEMP_CHILD 1
                                    > #define HUM_CHILD 2
                                    > 
                                    > const float ALTITUDE = 184; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                                    > 
                                    > // Sleep time between reads (in ms). 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)
                                    > };
                                    > 
                                    > float lastPressure = -1;
                                    > float lastTemp = -1;
                                    > float lastHum = -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 the forecast algorithm
                                    > // get kPa/h by 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;
                                    > boolean metric;
                                    > MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                    > MyMessage humMsg(HUM_CHILD, V_HUM);
                                    > MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                    > MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                    > 
                                    > 
                                    > 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;
                                    > }
                                    > 
                                    > 
                                    > void setup() {
                                    >   metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                                    >   Wire.begin(); // Wire.begin(sda, scl)
                                    > }
                                    > 
                                    > void presentation()  {
                                    >   // Send the sketch version information to the gateway and Controller
                                    >   sendSketchInfo("BME280 Sensor", "1.6");
                                    > 
                                    >   // Register sensors to gw (they will be created as child devices)
                                    >   present(BARO_CHILD, S_BARO);
                                    >   present(TEMP_CHILD, S_TEMP);
                                    >   present(HUM_CHILD, S_HUM);
                                    > }
                                    > 
                                    > // Loop
                                    > void loop() {
                                    >   
                                    >   // need to read the NVM compensation parameters
                                    >   BME280.readCompensationParams();
                                    > 
                                    >   /* After taking the measurement the chip goes back to sleep, use when battery powered.
                                    >   // Oversampling settings (os1x, os2x, os4x, os8x or os16x).
                                    >   BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient, higher numbers avoid sudden changes to be accounted for (such as slamming a door)
                                    >   BME280.writeOversamplingPressure(os16x);    // pressure x16
                                    >   BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                    >   BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                    > 
                                    >   BME280.writeMode(smForced);                 // Forced sample.  After taking the measurement the chip goes back to sleep
                                    >   */
                                    > 
                                    >   // Normal mode for regular automatic samples
                                    >   BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                                    >   BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                                    >   BME280.writeOversamplingPressure(os16x);    // pressure x16
                                    >   BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                    >   BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                    >   
                                    >   BME280.writeMode(smNormal);
                                    >   
                                    >   while (1) {
                                    >     // Just to be sure, wait until sensor is done mesuring  
                                    >     while (BME280.isMeasuring()) {
                                    >   }
                                    >   
                                    >   // Read out the data - must do this before calling the getxxxxx routines
                                    >   BME280.readMeasurements();
                                    > 
                                    >   float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                                    >   float humidity = BME280.getHumidityMostAccurate();
                                    >   float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                                    >   float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                                    >   int forecast = sample(pressure);
                                    >   
                                    >   if (!metric) 
                                    >   {
                                    >     // Convert to fahrenheit
                                    >     temperature = temperature * 9.0 / 5.0 + 32.0;
                                    >   }
                                    > 
                                    >   Serial.println();
                                    >   Serial.print("Temperature = ");
                                    >   Serial.print(temperature);
                                    >   Serial.println(metric ? " °C" : " °F");
                                    >   Serial.print("Humidity = ");
                                    >   Serial.print(humidity);
                                    >   Serial.println(" %");
                                    >   Serial.print("Pressure = ");
                                    >   Serial.print(pressure);
                                    >   Serial.println(" hPa");
                                    >   Serial.print("Forecast = ");
                                    >   Serial.println(weather[forecast]);
                                    >   Serial.println();
                                    > 
                                    > 
                                    >   if (temperature != lastTemp) 
                                    >   {
                                    >     send(tempMsg.set(temperature, 1));
                                    >     lastTemp = temperature;
                                    >   }
                                    > 
                                    > 
                                    >   if (humidity != lastHum) 
                                    >   {
                                    >     send(humMsg.set(humidity, 1));
                                    >     lastHum = humidity;
                                    >   }
                                    > 
                                    >   if (pressure != lastPressure) 
                                    >   {
                                    >     send(pressureMsg.set(pressure, 2));
                                    >     lastPressure = pressure;
                                    >   }
                                    > 
                                    >   if (forecast != lastForecast)
                                    >   {
                                    >     send(forecastMsg.set(weather[forecast]));
                                    >     lastForecast = forecast;
                                    >   }
                                    >   
                                    >   sleep(SLEEP_TIME);
                                    >   
                                    > }
                                    > }
                                    

                                    Added to sketch @yoshida battery state send, but its not sending it, please chek it:

                                    /**
                                     * 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
                                     *
                                     */
                                    
                                    // 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>
                                    
                                    // BME280 libraries and variables
                                    // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                                    // Written originally by Embedded Adventures
                                    // https://github.com/embeddedadventures/BME280
                                    #include <BME280_MOD-1022.h>
                                    
                                    #define BARO_CHILD 0
                                    #define TEMP_CHILD 1
                                    #define HUM_CHILD 2
                                    
                                    int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point
                                    int oldBatteryPcnt = 0;
                                    
                                    const float ALTITUDE = 450; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                                    
                                    // Sleep time between reads (in ms). Do not change this value as the forecast algorithm needs a sample every minute.
                                    const unsigned long SLEEP_TIME = 300000; 
                                    
                                    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)
                                    };
                                    
                                    float lastPressure = -1;
                                    float lastTemp = -1;
                                    float lastHum = -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 the forecast algorithm
                                    // get kPa/h by 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;
                                    boolean metric;
                                    MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                    MyMessage humMsg(HUM_CHILD, V_HUM);
                                    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                    MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                    
                                    
                                    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;
                                    }
                                    
                                    
                                    void setup() {
                                      metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                                      Wire.begin(); // Wire.begin(sda, scl)
                                      // use the 1.1 V internal reference
                                      #if defined(__AVR_ATmega2560__)
                                      analogReference(INTERNAL1V1);
                                      #else
                                      analogReference(INTERNAL);
                                      #endif
                                    }
                                    
                                    void presentation()  {
                                      // Send the sketch version information to the gateway and Controller
                                      sendSketchInfo("BME280 Sensor", "1.6");
                                    
                                      // Register sensors to gw (they will be created as child devices)
                                      present(BARO_CHILD, S_BARO);
                                      present(TEMP_CHILD, S_TEMP);
                                      present(HUM_CHILD, S_HUM);
                                    }
                                    
                                    // Loop
                                    void loop() {
                                    
                                      
                                      
                                      // need to read the NVM compensation parameters
                                      BME280.readCompensationParams();
                                    
                                      /* After taking the measurement the chip goes back to sleep, use when battery powered.
                                      // Oversampling settings (os1x, os2x, os4x, os8x or os16x).
                                      BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient, higher numbers avoid sudden changes to be accounted for (such as slamming a door)
                                      BME280.writeOversamplingPressure(os16x);    // pressure x16
                                      BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                      BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                    
                                      BME280.writeMode(smForced);                 // Forced sample.  After taking the measurement the chip goes back to sleep
                                      */
                                    
                                      // Normal mode for regular automatic samples
                                      BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                                      BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                                      BME280.writeOversamplingPressure(os16x);    // pressure x16
                                      BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                      BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                      
                                      BME280.writeMode(smNormal);
                                      
                                      while (1) {
                                        // Just to be sure, wait until sensor is done mesuring  
                                        while (BME280.isMeasuring()) {
                                      }
                                      
                                      // Read out the data - must do this before calling the getxxxxx routines
                                      BME280.readMeasurements();
                                    
                                      float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                                      float humidity = BME280.getHumidityMostAccurate();
                                      float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                                      float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                                      int forecast = sample(pressure);
                                      
                                      if (!metric) 
                                      {
                                        // Convert to fahrenheit
                                        temperature = temperature * 9.0 / 5.0 + 32.0;
                                      }
                                    
                                      Serial.println();
                                      Serial.print("Temperature = ");
                                      Serial.print(temperature);
                                      Serial.println(metric ? " °C" : " °F");
                                      Serial.print("Humidity = ");
                                      Serial.print(humidity);
                                      Serial.println(" %");
                                      Serial.print("Pressure = ");
                                      Serial.print(pressure);
                                      Serial.println(" hPa");
                                      Serial.print("Forecast = ");
                                      Serial.println(weather[forecast]);
                                      Serial.println();
                                    
                                    
                                      if (temperature != lastTemp) 
                                      {
                                        send(tempMsg.set(temperature, 1));
                                        lastTemp = temperature;
                                      }
                                    
                                    
                                      if (humidity != lastHum) 
                                      {
                                        send(humMsg.set(humidity, 1));
                                        lastHum = humidity;
                                      }
                                    
                                      if (pressure != lastPressure) 
                                      {
                                        send(pressureMsg.set(pressure, 2));
                                        lastPressure = pressure;
                                      }
                                    
                                      if (forecast != lastForecast)
                                      {
                                        send(forecastMsg.set(weather[forecast]));
                                        lastForecast = forecast;
                                      }
                                    
                                        int sensorValue = analogRead(BATTERY_SENSE_PIN);
                                        int batteryPcnt = sensorValue / 10;
                                        if (oldBatteryPcnt != batteryPcnt) {
                                        // Power up radio after sleep
                                        sendBatteryLevel(batteryPcnt);
                                        oldBatteryPcnt = batteryPcnt;
                                        }
                                        
                                      sleep(SLEEP_TIME);
                                      
                                    }
                                    }
                                    
                                    sundberg84S 1 Reply Last reply
                                    0
                                    • S scalpel

                                      @yoshida said in BME280 temp/humidity/pressure sensor:

                                      > /**
                                      >  * 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
                                      >  *
                                      >  */
                                      > 
                                      > // 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>
                                      > 
                                      > // BME280 libraries and variables
                                      > // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                                      > // Written originally by Embedded Adventures
                                      > // https://github.com/embeddedadventures/BME280
                                      > #include <BME280_MOD-1022.h>
                                      > 
                                      > #define BARO_CHILD 0
                                      > #define TEMP_CHILD 1
                                      > #define HUM_CHILD 2
                                      > 
                                      > const float ALTITUDE = 184; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                                      > 
                                      > // Sleep time between reads (in ms). 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)
                                      > };
                                      > 
                                      > float lastPressure = -1;
                                      > float lastTemp = -1;
                                      > float lastHum = -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 the forecast algorithm
                                      > // get kPa/h by 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;
                                      > boolean metric;
                                      > MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                      > MyMessage humMsg(HUM_CHILD, V_HUM);
                                      > MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                      > MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                      > 
                                      > 
                                      > 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;
                                      > }
                                      > 
                                      > 
                                      > void setup() {
                                      >   metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                                      >   Wire.begin(); // Wire.begin(sda, scl)
                                      > }
                                      > 
                                      > void presentation()  {
                                      >   // Send the sketch version information to the gateway and Controller
                                      >   sendSketchInfo("BME280 Sensor", "1.6");
                                      > 
                                      >   // Register sensors to gw (they will be created as child devices)
                                      >   present(BARO_CHILD, S_BARO);
                                      >   present(TEMP_CHILD, S_TEMP);
                                      >   present(HUM_CHILD, S_HUM);
                                      > }
                                      > 
                                      > // Loop
                                      > void loop() {
                                      >   
                                      >   // need to read the NVM compensation parameters
                                      >   BME280.readCompensationParams();
                                      > 
                                      >   /* After taking the measurement the chip goes back to sleep, use when battery powered.
                                      >   // Oversampling settings (os1x, os2x, os4x, os8x or os16x).
                                      >   BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient, higher numbers avoid sudden changes to be accounted for (such as slamming a door)
                                      >   BME280.writeOversamplingPressure(os16x);    // pressure x16
                                      >   BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                      >   BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                      > 
                                      >   BME280.writeMode(smForced);                 // Forced sample.  After taking the measurement the chip goes back to sleep
                                      >   */
                                      > 
                                      >   // Normal mode for regular automatic samples
                                      >   BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                                      >   BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                                      >   BME280.writeOversamplingPressure(os16x);    // pressure x16
                                      >   BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                      >   BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                      >   
                                      >   BME280.writeMode(smNormal);
                                      >   
                                      >   while (1) {
                                      >     // Just to be sure, wait until sensor is done mesuring  
                                      >     while (BME280.isMeasuring()) {
                                      >   }
                                      >   
                                      >   // Read out the data - must do this before calling the getxxxxx routines
                                      >   BME280.readMeasurements();
                                      > 
                                      >   float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                                      >   float humidity = BME280.getHumidityMostAccurate();
                                      >   float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                                      >   float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                                      >   int forecast = sample(pressure);
                                      >   
                                      >   if (!metric) 
                                      >   {
                                      >     // Convert to fahrenheit
                                      >     temperature = temperature * 9.0 / 5.0 + 32.0;
                                      >   }
                                      > 
                                      >   Serial.println();
                                      >   Serial.print("Temperature = ");
                                      >   Serial.print(temperature);
                                      >   Serial.println(metric ? " °C" : " °F");
                                      >   Serial.print("Humidity = ");
                                      >   Serial.print(humidity);
                                      >   Serial.println(" %");
                                      >   Serial.print("Pressure = ");
                                      >   Serial.print(pressure);
                                      >   Serial.println(" hPa");
                                      >   Serial.print("Forecast = ");
                                      >   Serial.println(weather[forecast]);
                                      >   Serial.println();
                                      > 
                                      > 
                                      >   if (temperature != lastTemp) 
                                      >   {
                                      >     send(tempMsg.set(temperature, 1));
                                      >     lastTemp = temperature;
                                      >   }
                                      > 
                                      > 
                                      >   if (humidity != lastHum) 
                                      >   {
                                      >     send(humMsg.set(humidity, 1));
                                      >     lastHum = humidity;
                                      >   }
                                      > 
                                      >   if (pressure != lastPressure) 
                                      >   {
                                      >     send(pressureMsg.set(pressure, 2));
                                      >     lastPressure = pressure;
                                      >   }
                                      > 
                                      >   if (forecast != lastForecast)
                                      >   {
                                      >     send(forecastMsg.set(weather[forecast]));
                                      >     lastForecast = forecast;
                                      >   }
                                      >   
                                      >   sleep(SLEEP_TIME);
                                      >   
                                      > }
                                      > }
                                      

                                      Added to sketch @yoshida battery state send, but its not sending it, please chek it:

                                      /**
                                       * 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
                                       *
                                       */
                                      
                                      // 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>
                                      
                                      // BME280 libraries and variables
                                      // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                                      // Written originally by Embedded Adventures
                                      // https://github.com/embeddedadventures/BME280
                                      #include <BME280_MOD-1022.h>
                                      
                                      #define BARO_CHILD 0
                                      #define TEMP_CHILD 1
                                      #define HUM_CHILD 2
                                      
                                      int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point
                                      int oldBatteryPcnt = 0;
                                      
                                      const float ALTITUDE = 450; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                                      
                                      // Sleep time between reads (in ms). Do not change this value as the forecast algorithm needs a sample every minute.
                                      const unsigned long SLEEP_TIME = 300000; 
                                      
                                      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)
                                      };
                                      
                                      float lastPressure = -1;
                                      float lastTemp = -1;
                                      float lastHum = -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 the forecast algorithm
                                      // get kPa/h by 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;
                                      boolean metric;
                                      MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                      MyMessage humMsg(HUM_CHILD, V_HUM);
                                      MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                      MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                      
                                      
                                      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;
                                      }
                                      
                                      
                                      void setup() {
                                        metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                                        Wire.begin(); // Wire.begin(sda, scl)
                                        // use the 1.1 V internal reference
                                        #if defined(__AVR_ATmega2560__)
                                        analogReference(INTERNAL1V1);
                                        #else
                                        analogReference(INTERNAL);
                                        #endif
                                      }
                                      
                                      void presentation()  {
                                        // Send the sketch version information to the gateway and Controller
                                        sendSketchInfo("BME280 Sensor", "1.6");
                                      
                                        // Register sensors to gw (they will be created as child devices)
                                        present(BARO_CHILD, S_BARO);
                                        present(TEMP_CHILD, S_TEMP);
                                        present(HUM_CHILD, S_HUM);
                                      }
                                      
                                      // Loop
                                      void loop() {
                                      
                                        
                                        
                                        // need to read the NVM compensation parameters
                                        BME280.readCompensationParams();
                                      
                                        /* After taking the measurement the chip goes back to sleep, use when battery powered.
                                        // Oversampling settings (os1x, os2x, os4x, os8x or os16x).
                                        BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient, higher numbers avoid sudden changes to be accounted for (such as slamming a door)
                                        BME280.writeOversamplingPressure(os16x);    // pressure x16
                                        BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                        BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                      
                                        BME280.writeMode(smForced);                 // Forced sample.  After taking the measurement the chip goes back to sleep
                                        */
                                      
                                        // Normal mode for regular automatic samples
                                        BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                                        BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                                        BME280.writeOversamplingPressure(os16x);    // pressure x16
                                        BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                        BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                        
                                        BME280.writeMode(smNormal);
                                        
                                        while (1) {
                                          // Just to be sure, wait until sensor is done mesuring  
                                          while (BME280.isMeasuring()) {
                                        }
                                        
                                        // Read out the data - must do this before calling the getxxxxx routines
                                        BME280.readMeasurements();
                                      
                                        float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                                        float humidity = BME280.getHumidityMostAccurate();
                                        float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                                        float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                                        int forecast = sample(pressure);
                                        
                                        if (!metric) 
                                        {
                                          // Convert to fahrenheit
                                          temperature = temperature * 9.0 / 5.0 + 32.0;
                                        }
                                      
                                        Serial.println();
                                        Serial.print("Temperature = ");
                                        Serial.print(temperature);
                                        Serial.println(metric ? " °C" : " °F");
                                        Serial.print("Humidity = ");
                                        Serial.print(humidity);
                                        Serial.println(" %");
                                        Serial.print("Pressure = ");
                                        Serial.print(pressure);
                                        Serial.println(" hPa");
                                        Serial.print("Forecast = ");
                                        Serial.println(weather[forecast]);
                                        Serial.println();
                                      
                                      
                                        if (temperature != lastTemp) 
                                        {
                                          send(tempMsg.set(temperature, 1));
                                          lastTemp = temperature;
                                        }
                                      
                                      
                                        if (humidity != lastHum) 
                                        {
                                          send(humMsg.set(humidity, 1));
                                          lastHum = humidity;
                                        }
                                      
                                        if (pressure != lastPressure) 
                                        {
                                          send(pressureMsg.set(pressure, 2));
                                          lastPressure = pressure;
                                        }
                                      
                                        if (forecast != lastForecast)
                                        {
                                          send(forecastMsg.set(weather[forecast]));
                                          lastForecast = forecast;
                                        }
                                      
                                          int sensorValue = analogRead(BATTERY_SENSE_PIN);
                                          int batteryPcnt = sensorValue / 10;
                                          if (oldBatteryPcnt != batteryPcnt) {
                                          // Power up radio after sleep
                                          sendBatteryLevel(batteryPcnt);
                                          oldBatteryPcnt = batteryPcnt;
                                          }
                                          
                                        sleep(SLEEP_TIME);
                                        
                                      }
                                      }
                                      
                                      sundberg84S Offline
                                      sundberg84S Offline
                                      sundberg84
                                      Hardware Contributor
                                      wrote on last edited by
                                      #30

                                      @scalpel - works great! Thank you!!
                                      Downloaded the library from the link in your sketch and up and running i no time.
                                      Here is my sketch, with some modifications:

                                      • Lightsensor A0
                                      • No sleep (might want to enable repeater function later)
                                      • Sends every 5 minute regardless of prevoius value (I use Domoticz and want to avoid red nodes and combined nodes).
                                      • Fixed node it
                                      // Enable debug prints to serial monitor
                                      //#define MY_DEBUG 
                                      
                                      // Enable and select radio type attached
                                      #define MY_RADIO_NRF24
                                      //#define MY_RADIO_RFM69
                                      
                                      //Fixed ID/Parent?
                                      #define MY_NODE_ID 20                     //To set a fixed ID for your node
                                      //#define MY_PARENT_NODE_ID 100             //To set a fixed parent for this node
                                      
                                      #include <SPI.h>
                                      #include <MySensors.h>  
                                      #include <Wire.h>
                                      
                                      // BME280 libraries and variables
                                      // Bosch BME280 Embedded Adventures MOD-1022 weather multi-sensor Arduino code
                                      // Written originally by Embedded Adventures
                                      // https://github.com/embeddedadventures/BME280
                                      #include <BME280_MOD-1022.h>
                                      
                                      #define BARO_CHILD 0
                                      #define TEMP_CHILD 1
                                      #define HUM_CHILD 2
                                      
                                      long interval = 300000;           // interval at which to send (milliseconds)
                                      long previousMillis = interval;        // will store last time data was sent
                                      
                                      const float ALTITUDE = 135; // <-- adapt this value to your location's altitude (in m). Use your smartphone GPS to get an accurate value!
                                      
                                      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)
                                      };
                                      
                                      
                                      const int LAST_SAMPLES_COUNT = 5;
                                      float lastPressureSamples[LAST_SAMPLES_COUNT];
                                      
                                      
                                      // this CONVERSION_FACTOR is used to convert from Pa to kPa in the forecast algorithm
                                      // get kPa/h by 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;
                                      boolean metric;
                                      MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                      MyMessage humMsg(HUM_CHILD, V_HUM);
                                      MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                      MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                      
                                      //Light
                                      #define CHILD_ID_LIGHT 3
                                      #define LIGHT_SENSOR_ANALOG_PIN A0
                                      MyMessage light_Msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
                                      
                                      
                                      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;
                                      }
                                      
                                      
                                      void setup() {
                                        metric = getControllerConfig().isMetric;  // was getConfig().isMetric; before MySensors v2.1.1
                                        Wire.begin(); // Wire.begin(sda, scl)
                                        // use the 1.1 V internal reference
                                        #if defined(__AVR_ATmega2560__)
                                        analogReference(INTERNAL1V1);
                                        #else
                                        analogReference(INTERNAL);
                                        #endif
                                      }
                                      
                                      void presentation()  {
                                        // Send the sketch version information to the gateway and Controller
                                        sendSketchInfo("WeatherStation #20", "1.0");
                                      
                                        // Register sensors to gw (they will be created as child devices)
                                        present(BARO_CHILD, S_BARO);
                                        present(TEMP_CHILD, S_TEMP);
                                        present(HUM_CHILD, S_HUM);
                                        present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
                                      }
                                      
                                      // Loop
                                      void loop() {
                                      
                                      unsigned long currentMillis = millis();  
                                      
                                      if(currentMillis - previousMillis > interval) {
                                          // save the last time sent the data
                                          previousMillis = currentMillis;
                                      
                                      
                                        analogReference(DEFAULT);
                                        wait(500);
                                         readLightLevel();   //Read Light
                                      
                                        analogReference(INTERNAL);
                                        wait(500);
                                        
                                        // need to read the NVM compensation parameters
                                        BME280.readCompensationParams();
                                      
                                        // Normal mode for regular automatic samples
                                        BME280.writeStandbyTime(tsb_0p5ms);         // tsb = 0.5ms
                                        BME280.writeFilterCoefficient(fc_16);       // IIR Filter coefficient 16
                                        BME280.writeOversamplingPressure(os16x);    // pressure x16
                                        BME280.writeOversamplingTemperature(os8x);  // temperature x8
                                        BME280.writeOversamplingHumidity(os8x);     // humidity x8
                                        
                                        BME280.writeMode(smNormal);
                                      
                                          // Just to be sure, wait until sensor is done mesuring  
                                          while (BME280.isMeasuring()) {
                                        }
                                      
                                        // Read out the data - must do this before calling the getxxxxx routines
                                        BME280.readMeasurements();
                                      
                                        float temperature = BME280.getTemperatureMostAccurate();                    // must get temp first
                                        float humidity = BME280.getHumidityMostAccurate();
                                        float pressure_local = BME280.getPressureMostAccurate();                    // Get pressure at current location
                                        float pressure = pressure_local/pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255); // Adjust to sea level pressure using user altitude
                                        int forecast = sample(pressure);
                                      
                                        if (!metric) 
                                        {
                                          // Convert to fahrenheit
                                          temperature = temperature * 9.0 / 5.0 + 32.0;
                                        }
                                      
                                        Serial.println();
                                        Serial.print("Temperature = ");
                                        Serial.print(temperature);
                                        Serial.println(metric ? " °C" : " °F");
                                        Serial.print("Humidity = ");
                                        Serial.print(humidity);
                                        Serial.println(" %");
                                        Serial.print("Pressure = ");
                                        Serial.print(pressure);
                                        Serial.println(" hPa");
                                        Serial.print("Forecast = ");
                                        Serial.println(weather[forecast]);
                                        Serial.println();
                                      
                                      
                                          send(tempMsg.set(temperature, 1));
                                      wait(50);
                                          send(humMsg.set(humidity, 1));
                                      wait(50);
                                          send(pressureMsg.set(pressure, 2));
                                      wait(50);
                                          send(forecastMsg.set(weather[forecast]));
                                      wait(50);
                                      
                                      }
                                      }
                                      
                                      void readLightLevel()      {
                                        Serial.println(analogRead(A0));  
                                        int lightLevel = (1023 - analogRead(LIGHT_SENSOR_ANALOG_PIN)) / 10.23; //To get a value ranging from 0 (dark) to 100 (bright).
                                      
                                      #ifdef MY_DEBUG
                                        Serial.print("Light: "); Serial.println(lightLevel);
                                      #endif
                                        send(light_Msg.set(lightLevel));
                                      
                                      }
                                      

                                      0_1506074720708_170922-IMG_20170922_103752.jpg

                                      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
                                      • R Offline
                                        R Offline
                                        RickyTerzis
                                        wrote on last edited by RickyTerzis
                                        #31

                                        Hi...i am a new user here. I built a RFM69 gateway and a node.I decided to place the RFM69 node in a basement storage room. The room has been flooded a few times historically, so being able to monitor humidity in the room seems like a good idea.The room has thick brick walls, which the RFM69-433MHz radio is much more capable to handle than the nrf24. Still, I wanted to keep an eye on the signal strength. Because of this, I added code to the gateway to report RSSI from the node.

                                        circuit card assembly

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


                                        18

                                        Online

                                        11.7k

                                        Users

                                        11.2k

                                        Topics

                                        113.0k

                                        Posts


                                        Copyright 2019 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