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. General Discussion
  3. A beginners question

A beginners question

Scheduled Pinned Locked Moved General Discussion
11 Posts 5 Posters 2.8k Views 4 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.
  • HilltanH Hilltan

    I have put a DHT22 sensor to my serial gateway, and in the sketch code for the DHT22 sensor there is sleeping “code”, static const uint64_t UPDATE_INTERVAL = 60000; and on the end sleep(UPDATE_INTERVAL); . Will this affect the gateway forcing it to sleep or will this only affect the DHT sensor? My sketch:

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level. 
    #define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Flash leds on rx/tx/err
    #define MY_LEDS_BLINKING_FEATURE
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    #define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60 
    // Digital pin used for inclusion mode button
    #define MY_INCLUSION_MODE_BUTTON_PIN  3 
    
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <DHT.h>
    #include <SPI.h>
    #include <MySensors.h>  
    
    //DHT Begin
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 8
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 0
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 60000;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    #define CHILD_ID_HUM 10
    #define CHILD_ID_TEMP 11
    
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    DHT dht;
    
    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
    }
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      sendSketchInfo("Getway+DHT", "1.1");
      
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      
      metric = getConfig().isMetric;
    }
    
    void loop()      
    {  
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
      
      // Get temperature from DHT library
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        // Reset no updates counter
        nNoUpdatesTemp = 0;
        temperature += SENSOR_TEMP_OFFSET;
        send(msgTemp.set(temperature, 1));
    
        #ifdef MY_DEBUG
        Serial.print("T: ");
        Serial.println(temperature);
        #endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp++;
      }
    
      // Get humidity from DHT library
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum = humidity;
        // Reset no updates counter
        nNoUpdatesHum = 0;
        send(msgHum.set(humidity, 1));
        
        #ifdef MY_DEBUG
        Serial.print("H: ");
        Serial.println(humidity);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum++;
      }
    
      // Sleep for a while to save energy
      sleep(UPDATE_INTERVAL); 
    }
    
    TheoLT Offline
    TheoLT Offline
    TheoL
    Contest Winner
    wrote on last edited by
    #2

    @Hilltan If you use sleep, an Arduino will go to sleep and is not able to receive any message. By using this

    sleep(UPDATE_INTERVAL);
    

    Your gateway will go to sleep and will not receive messages from other nodes. Which is kind of the main task of a gateway.

    It should be

    wait( UPDATE_INTERVAL );
    

    Basic rule is. Use sleep only on battery powered nodes that don't have any incoming message. Use wait in all other circumstances.

    ps. I put your sketch between 4 `

    1 Reply Last reply
    1
    • HilltanH Offline
      HilltanH Offline
      Hilltan
      wrote on last edited by
      #3

      Thanks for a replay. I change sleep to wait then. What I was concerned about was to “read” to often from the DHT sensor. But I believe "static const uint64_t UPDATE_INTERVAL = 60000; " in the beginning will regulate this, so my gateway will not over read the DHT sensor?

      mfalkviddM 1 Reply Last reply
      0
      • HilltanH Hilltan

        Thanks for a replay. I change sleep to wait then. What I was concerned about was to “read” to often from the DHT sensor. But I believe "static const uint64_t UPDATE_INTERVAL = 60000; " in the beginning will regulate this, so my gateway will not over read the DHT sensor?

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

        @Hilltan the wait call will not return until the specified number of milliseconds has passed. So yes it will prevent from reading the dht too often.

        1 Reply Last reply
        1
        • meanmrgreenM Offline
          meanmrgreenM Offline
          meanmrgreen
          wrote on last edited by
          #5

          About to built a dht / pir / repeater.
          Since i cant Sleep it do i need to change all sleep with wait?

          In the dht example there is a Sleep to let the sensor settle before Reading. Should this be a wait instead then?

          mfalkviddM 1 Reply Last reply
          0
          • meanmrgreenM meanmrgreen

            About to built a dht / pir / repeater.
            Since i cant Sleep it do i need to change all sleep with wait?

            In the dht example there is a Sleep to let the sensor settle before Reading. Should this be a wait instead then?

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

            @meanmrgreen yes

            meanmrgreenM 1 Reply Last reply
            0
            • mfalkviddM mfalkvidd

              @meanmrgreen yes

              meanmrgreenM Offline
              meanmrgreenM Offline
              meanmrgreen
              wrote on last edited by
              #7

              @mfalkvidd

              Hmm i have a combined sketch of the pir and dht example that works fine on a node that Can Sleep for a bit and interrupt with change on the pir.

              But if i take that sketch and change the Sleep with interrupt to a wait(sleep_time) the pir is not registrering movement between wait Times'.

              FIf i remove the wait alltoghter the pir is reporting the status every ms instead with the result that the dht can't read the temp!

              mfalkviddM 1 Reply Last reply
              0
              • meanmrgreenM meanmrgreen

                @mfalkvidd

                Hmm i have a combined sketch of the pir and dht example that works fine on a node that Can Sleep for a bit and interrupt with change on the pir.

                But if i take that sketch and change the Sleep with interrupt to a wait(sleep_time) the pir is not registrering movement between wait Times'.

                FIf i remove the wait alltoghter the pir is reporting the status every ms instead with the result that the dht can't read the temp!

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

                @meanmrgreen could you post your sketch?

                1 Reply Last reply
                0
                • meanmrgreenM Offline
                  meanmrgreenM Offline
                  meanmrgreen
                  wrote on last edited by
                  #9

                  this is it.

                  https://create.arduino.cc/editor/meanmrgreen/e7e0219e-139a-4e89-88da-e02f0864e9c6/preview

                  not sure of link worksge. on phone atm. will paste it from comp later if its not working.

                  1 Reply Last reply
                  0
                  • meanmrgreenM Offline
                    meanmrgreenM Offline
                    meanmrgreen
                    wrote on last edited by
                    #10
                    /**
                     * 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
                     * Motion Sensor example using HC-SR501 
                     * http://www.mysensors.org/build/motion
                     *
                     */
                    //Enable Repeater
                    #define MY_REPEATER_FEATURE
                    
                    // Enable debug prints
                    #define MY_DEBUG
                    
                    // Enable and select radio type attached
                    #define MY_RADIO_NRF24
                    //#define MY_RADIO_RFM69
                    
                    #include <SPI.h>
                    #include <MySensors.h>
                    #include <DHT.h>
                    
                    unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds)
                    #define DIGITAL_INPUT_SENSOR 2   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
                    #define DHT_DATA_PIN 4
                    #define CHILD_ID_MOT 1   // Id of the sensor child
                    #define CHILD_ID_HUM 0
                    #define CHILD_ID_TEMP 2
                    
                    // Set this offset if the sensor has a permanent small offset to the real temperatures
                    #define SENSOR_TEMP_OFFSET 0
                    
                    // Sleep time between sensor updates (in milliseconds)
                    // Must be >1000ms for DHT22 and >2000ms for DHT11
                    static const uint64_t UPDATE_INTERVAL = 120000;
                    
                    // Force sending an update of the temperature after n sensor reads, so a controller showing the
                    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
                    // the value didn't change since;
                    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
                    static const uint8_t FORCE_UPDATE_N_READS = 10;
                    
                    float lastTemp;
                    float lastHum;
                    uint8_t nNoUpdatesTemp;
                    uint8_t nNoUpdatesHum;
                    bool metric = true;
                    
                    // Initialize motion message
                    MyMessage msg(CHILD_ID_MOT, V_TRIPPED);
                    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
                    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
                    DHT dht;
                    
                    void presentation()  {
                      // Send the sketch version information to the gateway and Controller
                      sendSketchInfo("PIR_DHT_REPEATER", "1.0");
                    
                      // Register all sensors to gw (they will be created as child devices)
                      present(CHILD_ID_MOT, S_MOTION);
                      present(CHILD_ID_HUM, S_HUM);
                      present(CHILD_ID_TEMP, S_TEMP);
                    
                      metric = getConfig().isMetric;
                    }
                    
                    void setup()  
                    {  
                      pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
                      
                      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
                      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
                      Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                      } 
                      // Sleep for the time of the minimum sampling period to give the sensor time to power up
                      // (otherwise, timeout errors might occure for the first reading)
                      wait(dht.getMinimumSamplingPeriod());
                    }
                    
                    void loop()     
                    {     
                      // Read digital motion value
                      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
                          
                      Serial.println(tripped);
                      send(msg.set(tripped?"1":"0"));  // Send tripped value to gw 
                      // Force reading sensor, so it works also after wait()
                      dht.readSensor(true);
                      // Get temperature from DHT library
                      float temperature = dht.getTemperature();
                      if (isnan(temperature)) {
                        Serial.println("Failed reading temperature from DHT!");
                      } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
                        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
                        lastTemp = temperature;
                        if (!metric) {
                          temperature = dht.toFahrenheit(temperature);
                        }
                        // Reset no updates counter
                        nNoUpdatesTemp = 0;
                        temperature += SENSOR_TEMP_OFFSET;
                        send(msgTemp.set(temperature, 1));
                    
                        #ifdef MY_DEBUG
                        Serial.print("T: ");
                        Serial.println(temperature);
                        #endif
                      } else {
                        // Increase no update counter if the temperature stayed the same
                        nNoUpdatesTemp++;
                      }
                    
                      // Get humidity from DHT library
                      float humidity = dht.getHumidity();
                      if (isnan(humidity)) {
                        Serial.println("Failed reading humidity from DHT");
                      } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
                        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
                        lastHum = humidity;
                        // Reset no updates counter
                        nNoUpdatesHum = 0;
                        send(msgHum.set(humidity, 1));
                        
                        #ifdef MY_DEBUG
                        Serial.print("H: ");
                        Serial.println(humidity);
                        #endif
                      } else {
                        // Increase no update counter if the humidity stayed the same
                        nNoUpdatesHum++;
                      }
                    
                      // wait until interrupt comes in on motion sensor. Send update every two minute.
                      wait(SLEEP_TIME);
                    }
                    
                    
                    
                    
                    m26872M 1 Reply Last reply
                    0
                    • meanmrgreenM meanmrgreen
                      /**
                       * 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
                       * Motion Sensor example using HC-SR501 
                       * http://www.mysensors.org/build/motion
                       *
                       */
                      //Enable Repeater
                      #define MY_REPEATER_FEATURE
                      
                      // Enable debug prints
                      #define MY_DEBUG
                      
                      // Enable and select radio type attached
                      #define MY_RADIO_NRF24
                      //#define MY_RADIO_RFM69
                      
                      #include <SPI.h>
                      #include <MySensors.h>
                      #include <DHT.h>
                      
                      unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds)
                      #define DIGITAL_INPUT_SENSOR 2   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
                      #define DHT_DATA_PIN 4
                      #define CHILD_ID_MOT 1   // Id of the sensor child
                      #define CHILD_ID_HUM 0
                      #define CHILD_ID_TEMP 2
                      
                      // Set this offset if the sensor has a permanent small offset to the real temperatures
                      #define SENSOR_TEMP_OFFSET 0
                      
                      // Sleep time between sensor updates (in milliseconds)
                      // Must be >1000ms for DHT22 and >2000ms for DHT11
                      static const uint64_t UPDATE_INTERVAL = 120000;
                      
                      // Force sending an update of the temperature after n sensor reads, so a controller showing the
                      // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
                      // the value didn't change since;
                      // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
                      static const uint8_t FORCE_UPDATE_N_READS = 10;
                      
                      float lastTemp;
                      float lastHum;
                      uint8_t nNoUpdatesTemp;
                      uint8_t nNoUpdatesHum;
                      bool metric = true;
                      
                      // Initialize motion message
                      MyMessage msg(CHILD_ID_MOT, V_TRIPPED);
                      MyMessage msgHum(CHILD_ID_HUM, V_HUM);
                      MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
                      DHT dht;
                      
                      void presentation()  {
                        // Send the sketch version information to the gateway and Controller
                        sendSketchInfo("PIR_DHT_REPEATER", "1.0");
                      
                        // Register all sensors to gw (they will be created as child devices)
                        present(CHILD_ID_MOT, S_MOTION);
                        present(CHILD_ID_HUM, S_HUM);
                        present(CHILD_ID_TEMP, S_TEMP);
                      
                        metric = getConfig().isMetric;
                      }
                      
                      void setup()  
                      {  
                        pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
                        
                        dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
                        if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
                        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                        } 
                        // Sleep for the time of the minimum sampling period to give the sensor time to power up
                        // (otherwise, timeout errors might occure for the first reading)
                        wait(dht.getMinimumSamplingPeriod());
                      }
                      
                      void loop()     
                      {     
                        // Read digital motion value
                        boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
                            
                        Serial.println(tripped);
                        send(msg.set(tripped?"1":"0"));  // Send tripped value to gw 
                        // Force reading sensor, so it works also after wait()
                        dht.readSensor(true);
                        // Get temperature from DHT library
                        float temperature = dht.getTemperature();
                        if (isnan(temperature)) {
                          Serial.println("Failed reading temperature from DHT!");
                        } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
                          // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
                          lastTemp = temperature;
                          if (!metric) {
                            temperature = dht.toFahrenheit(temperature);
                          }
                          // Reset no updates counter
                          nNoUpdatesTemp = 0;
                          temperature += SENSOR_TEMP_OFFSET;
                          send(msgTemp.set(temperature, 1));
                      
                          #ifdef MY_DEBUG
                          Serial.print("T: ");
                          Serial.println(temperature);
                          #endif
                        } else {
                          // Increase no update counter if the temperature stayed the same
                          nNoUpdatesTemp++;
                        }
                      
                        // Get humidity from DHT library
                        float humidity = dht.getHumidity();
                        if (isnan(humidity)) {
                          Serial.println("Failed reading humidity from DHT");
                        } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
                          // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
                          lastHum = humidity;
                          // Reset no updates counter
                          nNoUpdatesHum = 0;
                          send(msgHum.set(humidity, 1));
                          
                          #ifdef MY_DEBUG
                          Serial.print("H: ");
                          Serial.println(humidity);
                          #endif
                        } else {
                          // Increase no update counter if the humidity stayed the same
                          nNoUpdatesHum++;
                        }
                      
                        // wait until interrupt comes in on motion sensor. Send update every two minute.
                        wait(SLEEP_TIME);
                      }
                      
                      
                      
                      
                      m26872M Offline
                      m26872M Offline
                      m26872
                      Hardware Contributor
                      wrote on last edited by
                      #11

                      @meanmrgreen You should use non-blocking code with millis() and if{}. Look e.g. at
                      https://forum.mysensors.org/topic/461/motion-sensor
                      https://forum.mysensors.org/topic/2717/repeater-node-with-sensor/12

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


                      19

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.1k

                      Posts


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

                      • Don't have an account? Register

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