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

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Clock with temperature, humidity and CO2 level sensors

Clock with temperature, humidity and CO2 level sensors

Scheduled Pinned Locked Moved My Project
6 Posts 3 Posters 5.7k Views 3 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.
  • U Offline
    U Offline
    user2684
    Contest Winner
    wrote on last edited by
    #1

    My bedside alarm clock recently got broken so I decided to build up one by myself.
    The prototype looks like that:
    0_1529326386412_1.png

    • 1: arduino pro mini 3.3v
    • 2: RFM69 radio
    • 3: MQ135 sensor to measure CO2 level
    • 4: 20k/10k voltage divider to connect the MQ AO pin to an analog pin of the arduino (the MQ sensor runs at 5v, the arduino at 3.3v so we need to "scale" the output)
    • 5: DS3231 RTC so when the power goes down the node will be able to restore its clock even without requesting time to the controller
    • 6: SHT21 sensor for temperature and humidity
    • 7: SSD1306 OLED display 128x64

    The "production" version looks like this:
    0_1529326672488_2.png
    I'm again using the versatile EasyPCB from @sundberg84, here in the middle. The voltage divider has been soldered on the board, where battery measurement level is used to be placed. Of course Vin is not connected but instead it is used for MQ's AO pin connection.
    The SH21 and MQ sensors are just outside the box so to have accurate readings. The project is powered by 0.5€ USB ttl Chinese key which allows to power both the board (3.3v) and the MQ sensor (5v).
    I've also added a push button, hidden within the case which will request the time to the controller for the first initialization of the RTC.

    As for the code this is what I'm using based on NodeManager (with the latest SensorMQ code change not yet merged into the development branch):

    /**********************************
     * MySensors node configuration
     */
    
    // General settings
    #define SKETCH_NAME "Clock"
    #define SKETCH_VERSION "1.0"
    //#define MY_DEBUG
    #define MY_NODE_ID 1
    
    // RFM69 radio settings
    #define MY_RADIO_RFM69
    //#define MY_RFM69_FREQUENCY RFM69_433MHZ
    #define MY_IS_RFM69HW
    #define MY_RFM69_NEW_DRIVER
    
    /***********************************
     * NodeManager modules for supported sensors
     */
    
    #define USE_SIGNAL
    #define USE_SHT21
    #define USE_INTERRUPT
    #define USE_MQ
    #define USE_SSD1306
    
    /***********************************
     * NodeManager built-in features
     */
    
    // Enable/disable NodeManager's features
    #define FEATURE_DEBUG OFF
    #define FEATURE_POWER_MANAGER OFF
    #define FEATURE_INTERRUPTS ON
    #define FEATURE_CONDITIONAL_REPORT OFF
    #define FEATURE_EEPROM OFF
    #define FEATURE_SLEEP OFF
    #define FEATURE_RECEIVE ON
    #define FEATURE_TIME ON
    #define FEATURE_RTC ON
    #define FEATURE_SD OFF
    #define FEATURE_HOOKING ON
    
    /***********************************
     * Load NodeManager Library
     */
    
    #include "NodeManagerLibrary.h"
    NodeManager node;
    
    /***********************************
     * Add your sensors below
     */
    
    // built-in sensors
    SensorSignal signal(node);
    
    // Attached sensors
    SensorSHT21 sht21(node);
    SensorMQ mq(node,A0);
    DisplaySSD1306 ssd1306(node);
    SensorInterrupt button(node,3);
    
    /***********************************
     * Main Sketch
     */
    
    void syncTime(Sensor* sensor) {
      // update the time with the controller
      node.syncTime();
      // update the display
      ssd1306.onLoop(ssd1306.children.get(1));
    }
    
    // before
    void before() {
      // setup the serial port baud rate
      Serial.begin(MY_BAUD_RATE);
      /*
      * Configure your sensors below
      */
    
      // temperature/humidity sensor
      sht21.setReportIntervalMinutes(5);
    
      // gas sensor
      mq.setReportIntervalMinutes(5);
      mq.setRoValue(56842);
      mq.setCurveScalingFactor(38.35);
      mq.setCurveExponent(-2.74);
      
      // display
      ssd1306.setReportIntervalSeconds(30);
    
      // button
      button.setInitialValue(HIGH);
      button.setInterruptMode(FALLING);
      button.setInterruptHook(&syncTime);
      
      /*
      * Configure your sensors above
      */
      node.before();
    }
    
    // presentation
    void presentation() {
      // call NodeManager presentation routine
      node.presentation();
    }
    
    // setup
    void setup() {
      // call NodeManager setup routine
      node.setup();
    }
    
    // loop
    void loop() {
      // call NodeManager loop routine
      node.loop();
    }
    
    #if FEATURE_RECEIVE == ON
    // receive
    void receive(const MyMessage &message) {
      // call NodeManager receive routine
      node.receive(message);
    }
    #endif
    
    #if FEATURE_TIME == ON
    // receiveTime
    void receiveTime(unsigned long ts) {
      // call NodeManager receiveTime routine
      node.receiveTime(ts);
    }
    #endif
    

    To show on the display only the information relevant for this project, I had to override DisplaySSD1306 onLoop() function in this way:

    void DisplaySSD1306::onLoop(Child* child) {
      long timestamp = now()+60*60*2;
      _oled->setCursor(0,0);
      // print the current date
      _oled->setFont(X11fixed7x14);
      _oled->print(F("    "));
      if (day(timestamp) < 10) _oled->print(F("0"));
      _oled->print(day(timestamp));
      _oled->print(F("-"));
      if (month(timestamp) < 10) _oled->print(F("0"));
      _oled->print(month(timestamp));
      _oled->print(F("-"));
      _oled->println(year(timestamp));
      // print the current time
      _oled->setFont(lcdnums12x16);
      _oled->set2X();
      if (hour(timestamp) < 10) _oled->print(F("0"));
      _oled->print(hour(timestamp));
      _oled->print(F(":"));
      if (minute(timestamp) < 10) _oled->print(F("0"));
      _oled->println(minute(timestamp));
      // print the sensors' data
      _oled->setFont(Adafruit5x7);
      _oled->set1X();
      _oled->println("");
      _oled->print(((ChildFloat*)_node->getChild(1))->getValueFloat());
      _oled->print(F("C "));
      _oled->print((int)((ChildFloat*)_node->getChild(2))->getValueFloat());
      _oled->print(F("% "));
      _oled->print(((ChildInt*)_node->getChild(3))->getValueInt());
      _oled->print(F("ppm"));
      _oled->clearToEOL();
    }
    

    Finally some pictures of the project once finalized:
    0_1529327416355_3.png

    0_1529327427911_4.png

    U 1 Reply Last reply
    5
    • U user2684

      My bedside alarm clock recently got broken so I decided to build up one by myself.
      The prototype looks like that:
      0_1529326386412_1.png

      • 1: arduino pro mini 3.3v
      • 2: RFM69 radio
      • 3: MQ135 sensor to measure CO2 level
      • 4: 20k/10k voltage divider to connect the MQ AO pin to an analog pin of the arduino (the MQ sensor runs at 5v, the arduino at 3.3v so we need to "scale" the output)
      • 5: DS3231 RTC so when the power goes down the node will be able to restore its clock even without requesting time to the controller
      • 6: SHT21 sensor for temperature and humidity
      • 7: SSD1306 OLED display 128x64

      The "production" version looks like this:
      0_1529326672488_2.png
      I'm again using the versatile EasyPCB from @sundberg84, here in the middle. The voltage divider has been soldered on the board, where battery measurement level is used to be placed. Of course Vin is not connected but instead it is used for MQ's AO pin connection.
      The SH21 and MQ sensors are just outside the box so to have accurate readings. The project is powered by 0.5€ USB ttl Chinese key which allows to power both the board (3.3v) and the MQ sensor (5v).
      I've also added a push button, hidden within the case which will request the time to the controller for the first initialization of the RTC.

      As for the code this is what I'm using based on NodeManager (with the latest SensorMQ code change not yet merged into the development branch):

      /**********************************
       * MySensors node configuration
       */
      
      // General settings
      #define SKETCH_NAME "Clock"
      #define SKETCH_VERSION "1.0"
      //#define MY_DEBUG
      #define MY_NODE_ID 1
      
      // RFM69 radio settings
      #define MY_RADIO_RFM69
      //#define MY_RFM69_FREQUENCY RFM69_433MHZ
      #define MY_IS_RFM69HW
      #define MY_RFM69_NEW_DRIVER
      
      /***********************************
       * NodeManager modules for supported sensors
       */
      
      #define USE_SIGNAL
      #define USE_SHT21
      #define USE_INTERRUPT
      #define USE_MQ
      #define USE_SSD1306
      
      /***********************************
       * NodeManager built-in features
       */
      
      // Enable/disable NodeManager's features
      #define FEATURE_DEBUG OFF
      #define FEATURE_POWER_MANAGER OFF
      #define FEATURE_INTERRUPTS ON
      #define FEATURE_CONDITIONAL_REPORT OFF
      #define FEATURE_EEPROM OFF
      #define FEATURE_SLEEP OFF
      #define FEATURE_RECEIVE ON
      #define FEATURE_TIME ON
      #define FEATURE_RTC ON
      #define FEATURE_SD OFF
      #define FEATURE_HOOKING ON
      
      /***********************************
       * Load NodeManager Library
       */
      
      #include "NodeManagerLibrary.h"
      NodeManager node;
      
      /***********************************
       * Add your sensors below
       */
      
      // built-in sensors
      SensorSignal signal(node);
      
      // Attached sensors
      SensorSHT21 sht21(node);
      SensorMQ mq(node,A0);
      DisplaySSD1306 ssd1306(node);
      SensorInterrupt button(node,3);
      
      /***********************************
       * Main Sketch
       */
      
      void syncTime(Sensor* sensor) {
        // update the time with the controller
        node.syncTime();
        // update the display
        ssd1306.onLoop(ssd1306.children.get(1));
      }
      
      // before
      void before() {
        // setup the serial port baud rate
        Serial.begin(MY_BAUD_RATE);
        /*
        * Configure your sensors below
        */
      
        // temperature/humidity sensor
        sht21.setReportIntervalMinutes(5);
      
        // gas sensor
        mq.setReportIntervalMinutes(5);
        mq.setRoValue(56842);
        mq.setCurveScalingFactor(38.35);
        mq.setCurveExponent(-2.74);
        
        // display
        ssd1306.setReportIntervalSeconds(30);
      
        // button
        button.setInitialValue(HIGH);
        button.setInterruptMode(FALLING);
        button.setInterruptHook(&syncTime);
        
        /*
        * Configure your sensors above
        */
        node.before();
      }
      
      // presentation
      void presentation() {
        // call NodeManager presentation routine
        node.presentation();
      }
      
      // setup
      void setup() {
        // call NodeManager setup routine
        node.setup();
      }
      
      // loop
      void loop() {
        // call NodeManager loop routine
        node.loop();
      }
      
      #if FEATURE_RECEIVE == ON
      // receive
      void receive(const MyMessage &message) {
        // call NodeManager receive routine
        node.receive(message);
      }
      #endif
      
      #if FEATURE_TIME == ON
      // receiveTime
      void receiveTime(unsigned long ts) {
        // call NodeManager receiveTime routine
        node.receiveTime(ts);
      }
      #endif
      

      To show on the display only the information relevant for this project, I had to override DisplaySSD1306 onLoop() function in this way:

      void DisplaySSD1306::onLoop(Child* child) {
        long timestamp = now()+60*60*2;
        _oled->setCursor(0,0);
        // print the current date
        _oled->setFont(X11fixed7x14);
        _oled->print(F("    "));
        if (day(timestamp) < 10) _oled->print(F("0"));
        _oled->print(day(timestamp));
        _oled->print(F("-"));
        if (month(timestamp) < 10) _oled->print(F("0"));
        _oled->print(month(timestamp));
        _oled->print(F("-"));
        _oled->println(year(timestamp));
        // print the current time
        _oled->setFont(lcdnums12x16);
        _oled->set2X();
        if (hour(timestamp) < 10) _oled->print(F("0"));
        _oled->print(hour(timestamp));
        _oled->print(F(":"));
        if (minute(timestamp) < 10) _oled->print(F("0"));
        _oled->println(minute(timestamp));
        // print the sensors' data
        _oled->setFont(Adafruit5x7);
        _oled->set1X();
        _oled->println("");
        _oled->print(((ChildFloat*)_node->getChild(1))->getValueFloat());
        _oled->print(F("C "));
        _oled->print((int)((ChildFloat*)_node->getChild(2))->getValueFloat());
        _oled->print(F("% "));
        _oled->print(((ChildInt*)_node->getChild(3))->getValueInt());
        _oled->print(F("ppm"));
        _oled->clearToEOL();
      }
      

      Finally some pictures of the project once finalized:
      0_1529327416355_3.png

      0_1529327427911_4.png

      U Offline
      U Offline
      user2684
      Contest Winner
      wrote on last edited by
      #2

      And if you don't like a hot MQ sensor just aside your bed, or want a 3.3v sensor or even something which can run on battery (even if not recommended) , you can try using a CCS811 which is more expensive (€7) than a MQ sensor but not as expensive as many other digital sensors for detecting e.g. CO2 (https://www.aliexpress.com/item/CJMCU-811-CCS811-Carbon-Monoxide-CO-VOCs-Air-Quality-Numerical-Gas-Sensor-Module/32846769569.html).
      There's a library on Adafruit. I'd not say it is that accurate for measurements but for sure way better than the MQ.

      1 Reply Last reply
      0
      • pihomeP Offline
        pihomeP Offline
        pihome
        wrote on last edited by
        #3

        @user2684 looks very nice. Can you share wiring.

        PiHome - Smart Heating Control

        U 1 Reply Last reply
        0
        • pihomeP pihome

          @user2684 looks very nice. Can you share wiring.

          U Offline
          U Offline
          user2684
          Contest Winner
          wrote on last edited by
          #4

          @pihome sure will do!

          1 Reply Last reply
          0
          • zrom69Z Offline
            zrom69Z Offline
            zrom69
            wrote on last edited by
            #5

            hi
            I have this error
            'class SensorMQ' has no member named 'setCurveScalingFactor'

            U 1 Reply Last reply
            0
            • zrom69Z zrom69

              hi
              I have this error
              'class SensorMQ' has no member named 'setCurveScalingFactor'

              U Offline
              U Offline
              user2684
              Contest Winner
              wrote on last edited by
              #6

              @zrom69 sorry for the delay! This is because I was using the development version of NodeManager available at https://github.com/mysensors/NodeManager/tree/development where SensorMQ implementation has been completely reviewed. Sorry for not making it clear!

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


              5

              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