Skip to content
  • 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. OpenHardware.io
  3. 💬 Insulated Whole House Fan
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store

💬 Insulated Whole House Fan

Scheduled Pinned Locked Moved OpenHardware.io
mysensorswhole house fan
72 Posts 11 Posters 13.2k Views 11 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.
  • openhardware.ioO Offline
    openhardware.ioO Offline
    openhardware.io
    wrote on last edited by hek
    #1

    https://www.mysensors.org/view/127/Insulated-Whole-House-Fan

    rechin304R 1 Reply Last reply
    4
    • scalzS Offline
      scalzS Offline
      scalz
      Hardware Contributor
      wrote on last edited by
      #2

      @petewill Wow, amazing work :thumbsup:

      1 Reply Last reply
      0
      • openhardware.ioO openhardware.io

        https://www.mysensors.org/view/127/Insulated-Whole-House-Fan

        rechin304R Offline
        rechin304R Offline
        rechin304
        wrote on last edited by
        #3

        @petewill Great work. Did you by any chance make it work with Mysensors V2 ?

        petewillP 1 Reply Last reply
        0
        • rechin304R rechin304

          @petewill Great work. Did you by any chance make it work with Mysensors V2 ?

          petewillP Offline
          petewillP Offline
          petewill
          Admin
          wrote on last edited by
          #4

          @rechin304 No not yet. It's on the list but it will be winter here for a while so it's not at the top. When were you planning to build yours?

          My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

          rechin304R 1 Reply Last reply
          0
          • petewillP petewill

            @rechin304 No not yet. It's on the list but it will be winter here for a while so it's not at the top. When were you planning to build yours?

            rechin304R Offline
            rechin304R Offline
            rechin304
            wrote on last edited by
            #5

            @petewill I already build the wooden box, and i have all electronic parts. I do wait for threaded rod, threaded Insert, Ball Bearing to arrive from china. I just finish today the shield that will hold arduino, testing lcd screen (i have a different version then you have, less pin's and no need for resistors). I will try to convert your schetch latter to V2 (still need to make an gateway for V2). If successful i will post the code.

            petewillP 1 Reply Last reply
            2
            • rechin304R rechin304

              @petewill I already build the wooden box, and i have all electronic parts. I do wait for threaded rod, threaded Insert, Ball Bearing to arrive from china. I just finish today the shield that will hold arduino, testing lcd screen (i have a different version then you have, less pin's and no need for resistors). I will try to convert your schetch latter to V2 (still need to make an gateway for V2). If successful i will post the code.

              petewillP Offline
              petewillP Offline
              petewill
              Admin
              wrote on last edited by
              #6

              @rechin304 Ok, sounds good. Let me know if you get stuck and I'll do my best to help.

              My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

              1 Reply Last reply
              0
              • rechin304R Offline
                rechin304R Offline
                rechin304
                wrote on last edited by rechin304
                #7

                This is hat i made until now. I have two issues:

                1. DHT11 is not working (no temp or hum is shown)
                2. I use Domoticz as controller and i do not see the node connecting to it, even the clock is sync with gateway. Gateway is version 2. So please if you have some time to look at the code your help be highly appreciated. Thanks.
                /**
                   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.
                
                   Power monitoring code adapted from: http://henrysbench.capnfatz.com/henrys-bench/arduino-current-measurements/acs712-arduino-ac-current-tutorial/
                 *******************************
                
                   REVISION HISTORY
                   Version 1.0 - Initial code
                   Version 2.0 - Changed for Mysensors v2
                   
                   DESCRIPTION
                   The code below will run a MySensors whole house fan with wall mounted lcd control panel.  The fan is installed in the attic and an insulated cover will 
                   open/close to conserve energy.  The project cost a little over $300 US.  A comparable commercial product costs around $1200.
                   
                   FEATURES
                   - Physical button switch to control on/off in case there are ever issues with radio communications.  
                   - DHT22 sensor for temp/humidity monitoring in the attic
                   - LCD screen displays status, temp/humidity, errors & date/time
                   - If an error occurs a message is sent to the gateway
                   - When the unit looses power it will make sure the cover is closed and the fan is off after power is restored.
                   - Safety Features
                	- The cover will wait to close until power has been shut off to the fan
                	- Customizable over current protection on the cover motor (automatically shut off if the cover gets stuck)
                	- Customizable cover close time limit (if it slips out off the coupling the motor won't run indefinitely)
                
                   NOTE
                   This program is too large to run with all debugging and the display enabled.
                   To upload either comment out "#define DEBUG_ON" in the code below or comment out
                   "#define DEBUG" in MyConfig.h in the MySensors library.
                   For troubleshooting "#ifdef TFT_DISPLAY_ON" can be commented out so all debugging
                   messages can be output to the serial monitor
                
                */
                // Enable debug prints to serial monitor
                #define MY_DEBUG
                // Enable and select radio type attached
                #define MY_RADIO_NRF24
                #define MY_RF24_PA_LEVEL RF24_PA_MAX
                
                #include <MySensors.h>
                #include <SPI.h>
                #include <Bounce2.h>
                #include <DHT.h>
                #include <Adafruit_GFX.h>    // Core graphics library
                #include <Adafruit_ST7735.h> // Hardware-specific library
                #include <Time.h>
                #include <TimeLib.h>
                
                //#define NODE_ID AUTO //or set to AUTO to have the gateway assign an ID
                
                //#define NODE_REPEAT false //change to true to set to a repeating/relaying node
                
                
                #define MY_NODE_ID AUTO  //set to AUTO to have the gateway assign an ID
                #define SKETCH_NAME "House Fan Mysensors v2"
                #define SKETCH_VERSION "2.1"
                
                #define FAN_ID 0   	// ID of the fan sensor child
                #define ERROR_ID 1 	// ID of the alert child 
                #define	HUM_ID 2 	//ID of the humidity child
                #define TEMP_ID 3 	//ID of the temp child
                
                #define BUTTON_PIN 2  				//Pin for the on/off button 
                // Set this to the pin you connected the DHT's data pin to
                #define DHT_DATA_PIN A0
                // Set this offset if the sensor has a permanent small offset to the real temperatures
                #define SENSOR_TEMP_OFFSET 0
                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 FAN_RELAY_PIN  A1  			//Pin number for relay that will control the fan
                #define COVER_CLOSE_LIMIT_PIN A2 	//Pin number for the "cover closed" limit switch
                #define COVER_OPEN_LIMIT_PIN A3 	//Pin number for the "cover open" limit switch
                #define COVER_CLOSE_PIN A4 			//Pin number for the "cover close" L298N motor control board
                #define COVER_OPEN_PIN A5			//Pin number for the "cover open" L298N motor control board
                #define FAN_POWER_PIN A6			//Pin number for the ACS712 monitoring the fan
                #define COVER_POWER_PIN A7			//Pin number for the ACS712 monitoring the cover motor
                
                #define TFT_DISPLAY_ON //Use to turn on/off display functionality (need to turn off for debugging because code is too large).
                
                #ifdef TFT_DISPLAY_ON
                // TFT display and SD card pins.  They will share the software SPI interface.
                #define SPI_SCK 8  //Also can be labeled CLK on display
                #define SPI_DI  4 //Labeled MISO on display
                #define SPI_DO  7  //Labeled MOSI on display
                //#define SD_CS   5  // Chip select line for SD card (not currently used)
                #define TFT_CS  3
                #define TFT_DC  6 //Labeled RS
                #define TFT_RST 0  // you can also connect this to the Arduino reset
                Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, SPI_DO, SPI_SCK, TFT_RST);
                #endif
                
                #define DEBUG_ON   // comment out to supress serial monitor output
                
                #ifdef DEBUG_ON
                #define DEBUG_PRINT(x)   Serial.print(x)
                #define DEBUG_PRINTLN(x) Serial.println(x)
                #define SERIAL_START(x)  Serial.begin(x)
                #else
                #define DEBUG_PRINT(x)
                #define DEBUG_PRINTLN(x)
                #define SERIAL_START(x)
                #endif
                
                #define RELAY_ON 1 //Switch to 0 if fan relay is off when it should be on
                #define RELAY_OFF 0 //Switch to 1 if fan relay is on when it should be off
                #define DWELL_TIME 50 //Time to wait between radio messages sent (helps prevent missed messages)
                #define closingStall 465 //The value of the ACS712 when the cover motor is stopped while closing. This value should be less than the normal operating power draw.
                #define openingStall 580 //The value of the ACS712 when the cover motor is stopped while opening.  This value should be greater than the normal operating power draw.
                #define coverLimitTime 37000 //Slightly over the time it takes for the cover to fully open/close in milliseconds.  This will prevent the cover motor from running indefinitely.
                
                //Fan power reading variables. You may need to adjust these depending on your ACS712 model and house voltage
                uint8_t mVperAmp = 69; //had to adjust for my sensor you may need to adjust yours a well // use 185 for 5A Module, 100 for 20A Module and 66 for 30A Module
                uint8_t houseVoltage = 220; //Voltage of your house wiring (110 or 220) 
                
                Bounce debouncerOnOff = Bounce();
                Bounce debouncerClosedState = Bounce();
                Bounce debouncerOpenState = Bounce();
                uint8_t fanButtonPrev = 0;
                uint8_t fanState = 0;
                uint8_t fanStatePrevious = 1;
                uint8_t fanRelayState;
                uint8_t coverMoving = 0;
                uint8_t	coverClosedState = LOW;
                uint8_t	coverOpenState = LOW;
                uint8_t errorState = 0; //Used to keep track of errors.  Can be reset by manually pushing button
                uint8_t fanPowerReading = 0;
                int coverPowerReading = 0;
                unsigned long currentMillis; //used for timers
                unsigned long powerReadMillis; //Used read power every second
                unsigned long powerUpdateMillis; //Used to update power usage on LCD and gateway
                unsigned long coverMillis;
                unsigned long dhtMillisPrev;
                unsigned long dhtDelay = 305000;	//5 minutes 5 seconds.  Offset is in case of power failure I don't want all my nodes reporting at the same time.
                unsigned long lastGetTime; //Used for getting time from gateway
                
                uint8_t lastSecond;
                uint8_t lastMinute;
                uint8_t lastHour;
                
                DHT dht;
                float lastTemp = 0;
                float lastHum = 0;
                uint8_t nNoUpdatesTemp;
                uint8_t nNoUpdatesHum;
                boolean metric = true; //Set to true if you use the metric system
                
                //Fan power reading variables.
                double Voltage = 0; //Voltage read from analog pin (used to calc power)
                double VRMS = 0;
                double AmpsRMS = 0;
                uint16_t wattTotal = 0; //Used to calculate the watts used for the last minute
                int wattAvg = 0;
                int wattAvgPrev = 0;
                uint8_t wattCount = 0; //Will be used to divide watts
                uint16_t pMaxValue = 0; // store max value here
                uint16_t pMinValue = 1024; // store min value here
                
                
                //MySensor gw;
                MyMessage msgFan(FAN_ID, V_STATUS);
                MyMessage msgFanPwr(FAN_ID, V_WATT);
                MyMessage msgError(ERROR_ID, V_TRIPPED);
                MyMessage msgHum(HUM_ID, V_HUM);
                MyMessage msgTemp(TEMP_ID, V_TEMP);
                
                void presentation()  
                { 
                  sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
                  present(FAN_ID, S_BINARY);
                  wait(DWELL_TIME);
                  present(ERROR_ID, S_MOTION);
                  wait(DWELL_TIME);
                  present(HUM_ID, S_HUM);
                  wait(DWELL_TIME);
                  present(TEMP_ID, S_TEMP);
                  wait(DWELL_TIME);
                  metric = getConfig().isMetric;
                }
                
                void setup()
                {
                  delay(2000); //Allow time for sensors to power up
                  
                requestTime();
                  // Send the sketch version information to the gateway and Controller
                
                
                  dht.setup(DHT_DATA_PIN);
                    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());
                
                  // Make sure relays are off when starting up
                  digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                  digitalWrite(COVER_OPEN_PIN, LOW);
                  digitalWrite(COVER_CLOSE_PIN, LOW);
                
                  // Set the pin mode
                  pinMode(FAN_RELAY_PIN, OUTPUT);
                  pinMode(COVER_OPEN_PIN, OUTPUT);
                  pinMode(COVER_CLOSE_PIN, OUTPUT);
                  pinMode(COVER_OPEN_LIMIT_PIN, INPUT_PULLUP);
                  pinMode(COVER_CLOSE_LIMIT_PIN, INPUT_PULLUP);
                  pinMode(BUTTON_PIN, INPUT_PULLUP); // Setup the on/off button and activate internal pull-up
                
                  // After setting up the pin modes, setup debouncers
                  debouncerOnOff.attach(BUTTON_PIN);
                  debouncerOnOff.interval(50);
                  debouncerOpenState.attach(COVER_OPEN_LIMIT_PIN);
                  debouncerOpenState.interval(50);
                  debouncerClosedState.attach(COVER_CLOSE_LIMIT_PIN);
                  debouncerClosedState.interval(50);
                
                  // Register all sensors to gw (they will be created as child devices)
                
                
                  send(msgError.set(0)); // Reset Alert state
                
                  //Check the cover slide limit switch values
                  debouncerOpenState.update();
                  coverOpenState = debouncerOpenState.read();
                
                  debouncerClosedState.update();
                  coverClosedState = debouncerClosedState.read();
                
                  metric = getConfig().isMetric;
                
                unsigned long functionTimeout = millis();
                  while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
                  {
                    requestTime(); 
                    DEBUG_PRINTLN(F("Getting Time"));
                    wait(1000); // call once per second
                    DEBUG_PRINTLN(F("."));
                  }
                
                #ifdef TFT_DISPLAY_ON
                  //**Note: I had a red tab LCD but the black tab setting worked the best for me
                  // If your TFT's plastic wrap has a Black Tab, use the following:
                  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
                  // If your TFT's plastic wrap has a Red Tab, use the following:
                  //tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
                  // If your TFT's plastic wrap has a Green Tab, use the following:
                  //tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab
                
                  //Initial Setup - Set state to Idle
                  tft.drawLine(0, 7, 160, 7, tft.Color565(123, 123, 123)); //Setup
                  tft.fillRect(0, 8, 160, 21, tft.Color565(80, 80, 80)); //Setup
                  tft.drawLine(0, 29, 160, 29, tft.Color565(34, 34, 34)); //Setup
                  tft.drawLine(0, 110, 160, 110, ST7735_WHITE); //Setup
                  tft.fillRect(0, 111, 160, 43, tft.Color565(230, 230, 230)); //Setup
                  tft.drawLine(0, 153, 160, 153, tft.Color565(170, 170, 170)); //Setup
                
                  updateTime();
                  updateTemp();
                  updateHum();
                
                #endif
                
                  currentMillis = millis();
                  coverMillis = currentMillis;
                
                  //Make sure the fan is off and the cover is closed when first powered on
                  fanOff();
                }
                
                
                void loop()
                {
                  // Force reading sensor, so it works also after sleep()
                  dht.readSensor(true);
                  
                  currentMillis = millis(); //Set the current millis (used for timers)
                
                  //Check the cover slide limit switch values
                  debouncerOpenState.update();
                  coverOpenState = debouncerOpenState.read();
                
                  debouncerClosedState.update();
                  coverClosedState = debouncerClosedState.read();
                  //  DEBUG_PRINT(F("coverClosedState = "));
                  //  DEBUG_PRINTLN(coverClosedState);
                
                  //There is a spike in current when the motor is first turned on.  We need to stop reading for a short period so the motor doesn't immedately turn off
                  if (currentMillis - coverMillis > 1500)
                  {
                    coverPowerReading = analogRead(COVER_POWER_PIN); //change back when sensor is attached
                    //DEBUG_PRINT(F("coverPowerReading = "));
                    //DEBUG_PRINTLN(coverPowerReading);
                    if (coverPowerReading > closingStall && coverPowerReading < openingStall)
                    {
                      //Cover motor power draw is within limits
                      coverPowerReading = 0;
                    }
                    else
                    {
                      //Cover motor power draw is over the limit.  Motor has stalled.
                      coverPowerReading = 1;
                    }
                  }
                
                  debouncerOnOff.update();
                  uint8_t fanButton = debouncerOnOff.read(); // Get the update value
                  //DEBUG_PRINTLN(fanButton);
                  if (fanButton != fanButtonPrev && fanButton == 0) {
                    if (coverMoving == 1)
                    {
                      //If the cover is already moving, change directions.
                      fanStatePrevious = fanState;
                      coverMoving = 0;
                    }
                    fanState = fanState ? 0 : 1;
                    DEBUG_PRINT(F("fanState value changed to: "));
                    DEBUG_PRINTLN(fanState);
                    send(msgFan.set(fanState), true); // Send new state and request ack back
                    errorState = 0;
                    wait(DWELL_TIME);
                    send(msgError.set(0)); // Reset Alert state
                    coverMillis = currentMillis; //Set the millis (used to keep track of cover close/open times)
                  }
                  fanButtonPrev = fanButton;
                
                  if (fanState != fanStatePrevious && fanState == 0 && errorState == 0)
                  {
                    fanOff();
                  }
                  if (fanState != fanStatePrevious && fanState == 1 && errorState == 0)
                  {
                    fanOn();
                  }
                
                  if (currentMillis - dhtMillisPrev > dhtDelay)
                  {
                    float temperature = dht.getTemperature();
                
                    if (isnan(temperature))
                    {
                      DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
                    }
                    else
                    {
                      if (!metric)
                      {
                        temperature = dht.toFahrenheit(temperature);
                      }
                      if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS)
                      {
                        lastTemp = temperature;
                        send(msgTemp.set(temperature, 1));
                        wait(DWELL_TIME);
                #ifdef TFT_DISPLAY_ON
                        updateTemp();
                #endif
                        DEBUG_PRINT(F("Temperature is: "));
                        DEBUG_PRINTLN(temperature);
                      }
                    }
                    float humidity = dht.getHumidity();;
                    if (isnan(humidity))
                    {
                      DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
                    } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS)
                    {
                      lastHum = humidity;
                      nNoUpdatesHum = 0;
                      send(msgHum.set(humidity, 1));
                      wait(DWELL_TIME);
                #ifdef TFT_DISPLAY_ON
                      updateHum();
                #endif
                
                      DEBUG_PRINT(F("Humidity is: "));
                      DEBUG_PRINTLN(humidity);
                    } else {
                    // Increase no update counter if the humidity stayed the same
                    nNoUpdatesHum++;
                  }
                    dhtMillisPrev = currentMillis;
                  }
                
                  /*
                    Check power usage here
                    I want to check it every second then send it every minute (when changed) to the gateway and LCD
                    In the "every second" check it should get a running average so it would divide by the number of seconds
                  */
                
                  if (currentMillis - powerReadMillis < 1000)
                  {
                    //Read power every second
                    uint16_t readValue = analogRead(FAN_POWER_PIN);
                    //DEBUG_PRINT(F("readValue: "));
                    //DEBUG_PRINTLN(readValue);
                
                    // see if you have a new pMaxValue
                    if (readValue > pMaxValue)
                    {
                      /*record the maximum sensor value*/
                      pMaxValue = readValue;
                    }
                    if (readValue < pMinValue)
                    {
                      /*record the maximum sensor value*/
                      pMinValue = readValue;
                    }
                  }
                  else
                  {
                    //Calulate power usage and update gateway if necessary
                    // Subtract min from max
                    Voltage = ((pMaxValue - pMinValue) * 5.0) / 1024.0;
                    VRMS = (Voltage / 2.0) * 0.707;
                    AmpsRMS = (VRMS * 1000) / mVperAmp;
                
                    if (AmpsRMS < .15) //filter out low readings when fan is off
                    {
                      AmpsRMS = 0;
                    }
                    DEBUG_PRINT(F("Amps RMS: "));
                    DEBUG_PRINT(AmpsRMS);
                
                    wattTotal += houseVoltage * AmpsRMS;
                    DEBUG_PRINT(F(".  Watt Total: "));
                    DEBUG_PRINT(wattTotal);
                    wattCount ++;
                    DEBUG_PRINT(F(".  Watt Count: "));
                    DEBUG_PRINTLN(wattCount);
                    powerReadMillis = currentMillis;
                    //Reset max and min values
                    pMaxValue = 0;
                    pMinValue = 1024;
                
                    //Update fanPowerReading to make sure the fan is off before closing the cover
                    fanPowerReading = AmpsRMS > 1 ? 1 : 0;
                    DEBUG_PRINT(F("fanPowerReading: "));
                    DEBUG_PRINTLN(fanPowerReading);
                
                    //Update Gateway and LCD every minute if necessary
                    if (currentMillis - powerUpdateMillis > 60000)
                    {
                      //We don't want to flood the gateway with updates so if the last reading was close to the current one we don't need to send the new reading
                      wattAvg = wattTotal / wattCount;
                      DEBUG_PRINT(F("Watt Average: "));
                      DEBUG_PRINTLN(wattAvg);
                
                      //Only update if last usage was different by 2 watts
                      if (wattAvgPrev - wattAvg > 2 || wattAvg - wattAvgPrev > 2)
                      {
                        //Send to gateway
                        send(msgFanPwr.set(wattAvg));
                
                #ifdef TFT_DISPLAY_ON
                        if (fanPowerReading == 1)
                        {
                          //Update LCD if running
                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                          tft.setFont();
                          tft.setTextSize(1);
                          tft.setCursor(5, 95);
                          tft.print("Watts: "); //First line of text 20 characters max
                          tft.print(wattAvg);
                          tft.print("  ");
                          DEBUG_PRINT(F("Watts update display: "));
                          DEBUG_PRINTLN(wattAvg);
                        }
                
                
                #endif
                
                      }
                      wattAvgPrev = wattAvg;
                
                      //Reset watt trackers
                      wattTotal = 0;
                      wattCount = 0;
                
                      powerUpdateMillis = currentMillis;
                
                      //Using this if statement to update the time every minute
                #ifdef TFT_DISPLAY_ON
                      //Update Time on Display every minute
                      updateTime();
                #endif
                    }
                  }
                
                  if (currentMillis - lastGetTime >= 3600000UL) // updates clock time and gets zone times from gateway once every hour
                  {
                    DEBUG_PRINTLN(F("Requesting time and valve data from Gateway..."));
                
                    lastGetTime = millis();
                  }
                }
                
                void fanOff() {
                  /*
                     1. Turn off the fan
                     2. Make sure it's off before we start closing the cover
                     3. Close cover
                        a. Start a timer for how long the closing should take
                        b. Stop the motor when the limit switch is hit
                     4. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message (via motion sensor).
                     5. Send "off" message to gateway/controller
                  */
                
                  //DEBUG_PRINTLN(F("In the fanOff function"));
                  if (fanRelayState == RELAY_ON)
                  {
                    DEBUG_PRINTLN(F("Turning off fan"));
                    //Turn off fan and set fan relay state to 0
                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                    fanRelayState = RELAY_OFF;
                
                  }
                  if (currentMillis - coverMillis < coverLimitTime)
                  {
                    if (coverPowerReading == 0)
                    {
                      //Make sure the fan is off before closing the cover to prevent damage to the cover and fan
                      if (fanPowerReading == 0)
                      {
                        //Start closing the cover
                        //Set the close pin on the L298N board to high
                
                        if (coverMoving == 0)
                        {
                          DEBUG_PRINTLN(F("Closing Cover"));
                          digitalWrite(COVER_CLOSE_PIN, HIGH);
                          //Set COVER_OPEN_PIN to low just to be safe
                          digitalWrite(COVER_OPEN_PIN, LOW);
                
                          //Update the LCD with "Closing" status message
                #ifdef TFT_DISPLAY_ON
                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                          tft.setFont();
                          tft.setTextSize(1);
                          tft.setCursor(5, 95);
                          tft.print("CLOSING COVER     "); //First line of text 20 characters max
                #endif
                          coverMoving = 1;
                        }
                
                        if (coverClosedState == LOW)
                        {
                          //The cover is closed.  Stop motor and send status to gateway.
                          digitalWrite(COVER_CLOSE_PIN, LOW);
                          fanStatePrevious = fanState;
                          send(msgFan.set(fanState), true); // Send new state with Ack
                          coverMoving = 0;
                
                #ifdef TFT_DISPLAY_ON
                          //Update LCD
                          wait(200); //Wait for radio SPI to stop (otherwise display is garbled)
                          updateTFTStatus(0); //Set status to idle state
                #endif
                        }
                      }
                    }
                    else
                    {
                      //Cover motor is using too much power.  Stop everything to avoid damage.
                      DEBUG_PRINTLN(F("The slide motor is using too much power!"));
                      digitalWrite(COVER_CLOSE_PIN, LOW);
                      digitalWrite(COVER_OPEN_PIN, LOW);
                      errorState = 1; //Set the error state so it doesn't keep trying to close
                      send(msgError.set(1)); // Send alert state to gateway
                #ifdef TFT_DISPLAY_ON
                      //Update LCD
                      updateTFTStatus(2); //Set status to error state
                      errorOvercurrent(); //More detailed error message
                #endif
                    }
                  }
                  else
                  {
                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                      Possible errors could be:
                      Fan did not shut off.
                      Cover did not fully close in time (slide jam, motor slip etc.)
                      Over current in cover motor (jammed?)
                    */
                    //Send commands to stop everything to avoid damage.
                    DEBUG_PRINTLN(F("Cover time exceeded"));
                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                    digitalWrite(COVER_CLOSE_PIN, LOW);
                    digitalWrite(COVER_OPEN_PIN, LOW);
                    errorState = 1; //Set the error state so it doesn't keep trying to close
                    send(msgError.set(1)); // Send alert state to gateway
                
                #ifdef TFT_DISPLAY_ON
                    //Update LCD
                    updateTFTStatus(2); //Set status to error state
                    errorTime(); //Write more detailed error to LCD
                #endif
                  }
                }
                
                void fanOn() {
                
                  /*
                    1. Open the cover
                      a. Start a timer to keep track of how long the cover has been opening 
                      b. Stop the motor when the limit switch is hit
                    2. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message.
                    3. Start the fan
                    4. Send "on" message to gateway/controller
                  */
                
                  if (currentMillis - coverMillis < coverLimitTime)
                  {
                    if (coverPowerReading == 0)
                    {
                      //Start opening the cover
                      if (coverMoving == 0)
                      {
                        DEBUG_PRINTLN(F("Opening Cover"));
                
                        //Set COVER_CLOSE_PIN to low just to be safe
                        digitalWrite(COVER_CLOSE_PIN, LOW);
                        digitalWrite(COVER_OPEN_PIN, HIGH);
                        coverMoving = 1;
                
                #ifdef TFT_DISPLAY_ON
                        wait(200); //Wait for radio communication to stop (otherwise display is garbled because of SPI conflicts)
                        //Update LCD
                        updateTFTStatus(1); //Set status to idle state
                #endif
                
                      }
                
                      if (coverOpenState == LOW)
                      {
                        //The cover is open.  Stop motor and send status to gateway.
                        digitalWrite(COVER_OPEN_PIN, LOW);
                        fanStatePrevious = fanState;
                        //Turn on Fan
                        digitalWrite(FAN_RELAY_PIN, RELAY_ON);
                        fanRelayState = RELAY_ON;
                        coverMoving = 0;
                      }
                    }
                    else
                    {
                      //Cover motor is using too much power.  Stop everything to avoid damage.
                      DEBUG_PRINTLN(F("The cover motor is using too much power!"));
                      digitalWrite(COVER_CLOSE_PIN, LOW);
                      digitalWrite(COVER_OPEN_PIN, LOW);
                      errorState = 1; //Set the error state so it doesn't keep trying to close
                      send(msgError.set(1)); // Send alert state to gateway
                #ifdef TFT_DISPLAY_ON
                      //Update LCD
                      updateTFTStatus(2); //Set status to error state
                      errorOvercurrent(); //More detailed error message
                #endif
                    }
                  }
                  else
                  {
                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                      Possible errors could be:
                      Cover did not fully open in time (slide jam, motor slip etc.)
                      Overcurrent in cover motor (jammed?)
                    */
                    //Send commands to stop everything to avoid damage.
                    DEBUG_PRINTLN(F("Cover time exceeded"));
                    digitalWrite(COVER_CLOSE_PIN, LOW);
                    digitalWrite(COVER_OPEN_PIN, LOW);
                    errorState = 1; //Set the error state so it doesn't keep trying to close
                
                #ifdef TFT_DISPLAY_ON
                    //Update LCD
                    updateTFTStatus(2); //Set status to error state
                    tft.setCursor(5, 90);
                    //More detailed error message
                    errorTime();
                #endif
                  }
                
                }
                
                
                void receive(const MyMessage & message) {
                  // We only expect one type of message from controller. But we better check anyway.
                  if (message.isAck()) {
                    DEBUG_PRINTLN(F("This is an ack from gateway"));
                  }
                
                  if (message.type == V_LIGHT && !message.isAck()) {
                    // Change relay state
                    fanState = message.getBool();
                    if (coverMoving == 1)
                    {
                      //If the cover is already moving, check to see if we need to change directions
                      DEBUG_PRINT(F("Cover is moving"));
                      if (fanState == fanStatePrevious)
                      {
                        //We need to change directions
                        fanStatePrevious = fanState ? 0 : 1;
                        coverMoving = 0;
                      }
                    }
                    coverMillis = millis(); //Set the millis (used to keep track of cover close/open times)
                
                    // Write some debug info
                    DEBUG_PRINT(F("Incoming change for sensor:"));
                    DEBUG_PRINT(message.sensor);
                    DEBUG_PRINT(F(", New status: "));
                    DEBUG_PRINTLN(fanState);
                  }
                }
                
                // This is called when a new time value was received
                void receiveTime(unsigned long time) {
                  // Ok, set incoming time 
                  setTime(time);
                }
                
                #ifdef TFT_DISPLAY_ON
                void updateTFTStatus(uint8_t bgStat)
                {
                  //bgStat: 0 = "Idle", 1 = "Running", 2 = "Error"
                  //Idle Color = 37, 125, 20
                  //Running Color = 53, 47, 125
                  //Error Color = 155, 26, 26
                
                  uint8_t r, g, b;
                  const char *displayStatus[] = {
                    "Idle", "Running", "Error"
                  };
                  if (bgStat == 0)
                  {
                    //Idle
                    r = 37;
                    g = 125;
                    b = 20;
                  }
                  else if (bgStat == 1)
                  {
                    //Running
                    r = 53;
                    g = 47;
                    b = 125;
                  }
                  else
                  {
                    //Error
                    r = 155;
                    g = 26;
                    b = 26;
                  }
                
                  tft.fillRect(0, 0, 160, 7, tft.Color565(r, g, b));
                  tft.fillRect(0, 30, 160, 80, tft.Color565(r, g, b));
                  tft.fillRect(0, 154, 160, 6, tft.Color565(r, g, b));
                
                  tft.setCursor(5, 40);
                  tft.setTextColor(ST7735_WHITE);
                  tft.setTextSize(1);
                  tft.println("Status");
                
                  tft.setCursor(5, 65);
                  tft.setTextColor(ST7735_WHITE);
                  tft.setFont();
                  //tft.setTextSize(3);
                  tft.setTextSize(bgStat == 1 ? 2 : 3); //The word "Running" doesn't fit with text size 3.
                  tft.println(displayStatus[bgStat]);
                
                }
                void errorOvercurrent()
                {
                  tft.setCursor(5, 90);
                  tft.setTextColor(ST7735_WHITE);
                  tft.setFont();
                  tft.setTextSize(1);
                  tft.println("Motor overcurrent"); //First line of text 20 characters max
                  tft.setCursor(5, 101);
                  tft.println("Check cover slide"); //Second line of text 20 characters max
                }
                void errorTime()
                {
                  tft.setCursor(5, 90);
                  tft.setTextColor(ST7735_WHITE);
                  tft.setFont();
                  tft.setTextSize(1);
                  tft.println("Time exceeded"); //First line of text 20 characters max
                  tft.setCursor(5, 100);
                  tft.println("Check cover slide"); //Second line of text 20 characters max
                }
                void updateTime()
                {
                  //Update Time
                  tft.setCursor(5, 17);
                  tft.setTextColor(ST7735_WHITE, tft.Color565(80, 80, 80));
                  tft.setTextSize(1);
                  tft.print(hourFormat12());
                  tft.print(minute() < 10 ? F(":0") : F(":"));
                  tft.print(minute());
                  tft.print(isAM() ? F("am") : F("pm"));
                  tft.print(month() < 10 ? F(" 0") : F(" "));
                  tft.print(month());
                  tft.print(day() < 10 ? F("/0") : F("/"));
                  tft.print(day());
                  tft.print(F("/"));
                  tft.print(year() % 100);
                  tft.print(F(" "));
                }
                void updateTemp()
                {
                  //Update Temperature
                  tft.setCursor(5, 120);
                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                  tft.setTextSize(1);
                  tft.print("Temp: ");
                  tft.print(lastTemp, 1);
                  tft.print((char)247);
                  tft.print(" ");
                }
                void updateHum()
                {
                  //Update Humidity
                  tft.setCursor(5, 140);
                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                  tft.setTextSize(1);
                  tft.print("Humidity: ");
                  tft.print(lastHum, 1);
                  tft.print("% ");
                }
                #endif
                
                rechin304R 1 Reply Last reply
                0
                • rechin304R Offline
                  rechin304R Offline
                  rechin304
                  wrote on last edited by
                  #8

                  Small progress. It can be seen now in Domoticz, however DHT11 not working.

                  petewillP 1 Reply Last reply
                  0
                  • NuubiN Offline
                    NuubiN Offline
                    Nuubi
                    wrote on last edited by
                    #9

                    Excellent project. However, have you considered any possibility of condensation of humid air in the attic? At least where I live, that would become a problem.

                    petewillP 1 Reply Last reply
                    0
                    • rechin304R Offline
                      rechin304R Offline
                      rechin304
                      wrote on last edited by
                      #10

                      In my case the air will go outside attic (i have a shaft for ventilation).

                      1 Reply Last reply
                      0
                      • NuubiN Nuubi

                        Excellent project. However, have you considered any possibility of condensation of humid air in the attic? At least where I live, that would become a problem.

                        petewillP Offline
                        petewillP Offline
                        petewill
                        Admin
                        wrote on last edited by
                        #11

                        @Nuubi You need to have proper venting in your attic to use a fan like this. If you have the venting the humidity should not be a problem because it will pull fresh air from the outside through your house and out the attic vents. I don't live in a high humidity area so maybe the venting in attics is different there though.

                        My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

                        1 Reply Last reply
                        0
                        • rechin304R rechin304

                          Small progress. It can be seen now in Domoticz, however DHT11 not working.

                          petewillP Offline
                          petewillP Offline
                          petewill
                          Admin
                          wrote on last edited by
                          #12

                          @rechin304 said:

                          Small progress. It can be seen now in Domoticz, however DHT11 not working.

                          Are you sure you have the wiring correct? Does it show in the serial monitor but not Domoticz or neither place?

                          My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

                          1 Reply Last reply
                          0
                          • rechin304R Offline
                            rechin304R Offline
                            rechin304
                            wrote on last edited by rechin304
                            #13

                            Hi @petewill , i do not see anything on serial monitor related to temp or hum, and yes is connected correctly on A0, everything now works ok, except temp and hum. I do not have yet an DHT22 to test.

                            petewillP 1 Reply Last reply
                            0
                            • rechin304R rechin304

                              Hi @petewill , i do not see anything on serial monitor related to temp or hum, and yes is connected correctly on A0, everything now works ok, except temp and hum. I do not have yet an DHT22 to test.

                              petewillP Offline
                              petewillP Offline
                              petewill
                              Admin
                              wrote on last edited by
                              #14

                              @rechin304 Strange. Did you enable debugging in the code (uncomment this line "//#define DEBUG_ON")? Without that line enabled you won't see anything in the serial monitor.

                              My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

                              1 Reply Last reply
                              0
                              • rechin304R rechin304

                                This is hat i made until now. I have two issues:

                                1. DHT11 is not working (no temp or hum is shown)
                                2. I use Domoticz as controller and i do not see the node connecting to it, even the clock is sync with gateway. Gateway is version 2. So please if you have some time to look at the code your help be highly appreciated. Thanks.
                                /**
                                   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.
                                
                                   Power monitoring code adapted from: http://henrysbench.capnfatz.com/henrys-bench/arduino-current-measurements/acs712-arduino-ac-current-tutorial/
                                 *******************************
                                
                                   REVISION HISTORY
                                   Version 1.0 - Initial code
                                   Version 2.0 - Changed for Mysensors v2
                                   
                                   DESCRIPTION
                                   The code below will run a MySensors whole house fan with wall mounted lcd control panel.  The fan is installed in the attic and an insulated cover will 
                                   open/close to conserve energy.  The project cost a little over $300 US.  A comparable commercial product costs around $1200.
                                   
                                   FEATURES
                                   - Physical button switch to control on/off in case there are ever issues with radio communications.  
                                   - DHT22 sensor for temp/humidity monitoring in the attic
                                   - LCD screen displays status, temp/humidity, errors & date/time
                                   - If an error occurs a message is sent to the gateway
                                   - When the unit looses power it will make sure the cover is closed and the fan is off after power is restored.
                                   - Safety Features
                                	- The cover will wait to close until power has been shut off to the fan
                                	- Customizable over current protection on the cover motor (automatically shut off if the cover gets stuck)
                                	- Customizable cover close time limit (if it slips out off the coupling the motor won't run indefinitely)
                                
                                   NOTE
                                   This program is too large to run with all debugging and the display enabled.
                                   To upload either comment out "#define DEBUG_ON" in the code below or comment out
                                   "#define DEBUG" in MyConfig.h in the MySensors library.
                                   For troubleshooting "#ifdef TFT_DISPLAY_ON" can be commented out so all debugging
                                   messages can be output to the serial monitor
                                
                                */
                                // Enable debug prints to serial monitor
                                #define MY_DEBUG
                                // Enable and select radio type attached
                                #define MY_RADIO_NRF24
                                #define MY_RF24_PA_LEVEL RF24_PA_MAX
                                
                                #include <MySensors.h>
                                #include <SPI.h>
                                #include <Bounce2.h>
                                #include <DHT.h>
                                #include <Adafruit_GFX.h>    // Core graphics library
                                #include <Adafruit_ST7735.h> // Hardware-specific library
                                #include <Time.h>
                                #include <TimeLib.h>
                                
                                //#define NODE_ID AUTO //or set to AUTO to have the gateway assign an ID
                                
                                //#define NODE_REPEAT false //change to true to set to a repeating/relaying node
                                
                                
                                #define MY_NODE_ID AUTO  //set to AUTO to have the gateway assign an ID
                                #define SKETCH_NAME "House Fan Mysensors v2"
                                #define SKETCH_VERSION "2.1"
                                
                                #define FAN_ID 0   	// ID of the fan sensor child
                                #define ERROR_ID 1 	// ID of the alert child 
                                #define	HUM_ID 2 	//ID of the humidity child
                                #define TEMP_ID 3 	//ID of the temp child
                                
                                #define BUTTON_PIN 2  				//Pin for the on/off button 
                                // Set this to the pin you connected the DHT's data pin to
                                #define DHT_DATA_PIN A0
                                // Set this offset if the sensor has a permanent small offset to the real temperatures
                                #define SENSOR_TEMP_OFFSET 0
                                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 FAN_RELAY_PIN  A1  			//Pin number for relay that will control the fan
                                #define COVER_CLOSE_LIMIT_PIN A2 	//Pin number for the "cover closed" limit switch
                                #define COVER_OPEN_LIMIT_PIN A3 	//Pin number for the "cover open" limit switch
                                #define COVER_CLOSE_PIN A4 			//Pin number for the "cover close" L298N motor control board
                                #define COVER_OPEN_PIN A5			//Pin number for the "cover open" L298N motor control board
                                #define FAN_POWER_PIN A6			//Pin number for the ACS712 monitoring the fan
                                #define COVER_POWER_PIN A7			//Pin number for the ACS712 monitoring the cover motor
                                
                                #define TFT_DISPLAY_ON //Use to turn on/off display functionality (need to turn off for debugging because code is too large).
                                
                                #ifdef TFT_DISPLAY_ON
                                // TFT display and SD card pins.  They will share the software SPI interface.
                                #define SPI_SCK 8  //Also can be labeled CLK on display
                                #define SPI_DI  4 //Labeled MISO on display
                                #define SPI_DO  7  //Labeled MOSI on display
                                //#define SD_CS   5  // Chip select line for SD card (not currently used)
                                #define TFT_CS  3
                                #define TFT_DC  6 //Labeled RS
                                #define TFT_RST 0  // you can also connect this to the Arduino reset
                                Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, SPI_DO, SPI_SCK, TFT_RST);
                                #endif
                                
                                #define DEBUG_ON   // comment out to supress serial monitor output
                                
                                #ifdef DEBUG_ON
                                #define DEBUG_PRINT(x)   Serial.print(x)
                                #define DEBUG_PRINTLN(x) Serial.println(x)
                                #define SERIAL_START(x)  Serial.begin(x)
                                #else
                                #define DEBUG_PRINT(x)
                                #define DEBUG_PRINTLN(x)
                                #define SERIAL_START(x)
                                #endif
                                
                                #define RELAY_ON 1 //Switch to 0 if fan relay is off when it should be on
                                #define RELAY_OFF 0 //Switch to 1 if fan relay is on when it should be off
                                #define DWELL_TIME 50 //Time to wait between radio messages sent (helps prevent missed messages)
                                #define closingStall 465 //The value of the ACS712 when the cover motor is stopped while closing. This value should be less than the normal operating power draw.
                                #define openingStall 580 //The value of the ACS712 when the cover motor is stopped while opening.  This value should be greater than the normal operating power draw.
                                #define coverLimitTime 37000 //Slightly over the time it takes for the cover to fully open/close in milliseconds.  This will prevent the cover motor from running indefinitely.
                                
                                //Fan power reading variables. You may need to adjust these depending on your ACS712 model and house voltage
                                uint8_t mVperAmp = 69; //had to adjust for my sensor you may need to adjust yours a well // use 185 for 5A Module, 100 for 20A Module and 66 for 30A Module
                                uint8_t houseVoltage = 220; //Voltage of your house wiring (110 or 220) 
                                
                                Bounce debouncerOnOff = Bounce();
                                Bounce debouncerClosedState = Bounce();
                                Bounce debouncerOpenState = Bounce();
                                uint8_t fanButtonPrev = 0;
                                uint8_t fanState = 0;
                                uint8_t fanStatePrevious = 1;
                                uint8_t fanRelayState;
                                uint8_t coverMoving = 0;
                                uint8_t	coverClosedState = LOW;
                                uint8_t	coverOpenState = LOW;
                                uint8_t errorState = 0; //Used to keep track of errors.  Can be reset by manually pushing button
                                uint8_t fanPowerReading = 0;
                                int coverPowerReading = 0;
                                unsigned long currentMillis; //used for timers
                                unsigned long powerReadMillis; //Used read power every second
                                unsigned long powerUpdateMillis; //Used to update power usage on LCD and gateway
                                unsigned long coverMillis;
                                unsigned long dhtMillisPrev;
                                unsigned long dhtDelay = 305000;	//5 minutes 5 seconds.  Offset is in case of power failure I don't want all my nodes reporting at the same time.
                                unsigned long lastGetTime; //Used for getting time from gateway
                                
                                uint8_t lastSecond;
                                uint8_t lastMinute;
                                uint8_t lastHour;
                                
                                DHT dht;
                                float lastTemp = 0;
                                float lastHum = 0;
                                uint8_t nNoUpdatesTemp;
                                uint8_t nNoUpdatesHum;
                                boolean metric = true; //Set to true if you use the metric system
                                
                                //Fan power reading variables.
                                double Voltage = 0; //Voltage read from analog pin (used to calc power)
                                double VRMS = 0;
                                double AmpsRMS = 0;
                                uint16_t wattTotal = 0; //Used to calculate the watts used for the last minute
                                int wattAvg = 0;
                                int wattAvgPrev = 0;
                                uint8_t wattCount = 0; //Will be used to divide watts
                                uint16_t pMaxValue = 0; // store max value here
                                uint16_t pMinValue = 1024; // store min value here
                                
                                
                                //MySensor gw;
                                MyMessage msgFan(FAN_ID, V_STATUS);
                                MyMessage msgFanPwr(FAN_ID, V_WATT);
                                MyMessage msgError(ERROR_ID, V_TRIPPED);
                                MyMessage msgHum(HUM_ID, V_HUM);
                                MyMessage msgTemp(TEMP_ID, V_TEMP);
                                
                                void presentation()  
                                { 
                                  sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
                                  present(FAN_ID, S_BINARY);
                                  wait(DWELL_TIME);
                                  present(ERROR_ID, S_MOTION);
                                  wait(DWELL_TIME);
                                  present(HUM_ID, S_HUM);
                                  wait(DWELL_TIME);
                                  present(TEMP_ID, S_TEMP);
                                  wait(DWELL_TIME);
                                  metric = getConfig().isMetric;
                                }
                                
                                void setup()
                                {
                                  delay(2000); //Allow time for sensors to power up
                                  
                                requestTime();
                                  // Send the sketch version information to the gateway and Controller
                                
                                
                                  dht.setup(DHT_DATA_PIN);
                                    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());
                                
                                  // Make sure relays are off when starting up
                                  digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                  digitalWrite(COVER_OPEN_PIN, LOW);
                                  digitalWrite(COVER_CLOSE_PIN, LOW);
                                
                                  // Set the pin mode
                                  pinMode(FAN_RELAY_PIN, OUTPUT);
                                  pinMode(COVER_OPEN_PIN, OUTPUT);
                                  pinMode(COVER_CLOSE_PIN, OUTPUT);
                                  pinMode(COVER_OPEN_LIMIT_PIN, INPUT_PULLUP);
                                  pinMode(COVER_CLOSE_LIMIT_PIN, INPUT_PULLUP);
                                  pinMode(BUTTON_PIN, INPUT_PULLUP); // Setup the on/off button and activate internal pull-up
                                
                                  // After setting up the pin modes, setup debouncers
                                  debouncerOnOff.attach(BUTTON_PIN);
                                  debouncerOnOff.interval(50);
                                  debouncerOpenState.attach(COVER_OPEN_LIMIT_PIN);
                                  debouncerOpenState.interval(50);
                                  debouncerClosedState.attach(COVER_CLOSE_LIMIT_PIN);
                                  debouncerClosedState.interval(50);
                                
                                  // Register all sensors to gw (they will be created as child devices)
                                
                                
                                  send(msgError.set(0)); // Reset Alert state
                                
                                  //Check the cover slide limit switch values
                                  debouncerOpenState.update();
                                  coverOpenState = debouncerOpenState.read();
                                
                                  debouncerClosedState.update();
                                  coverClosedState = debouncerClosedState.read();
                                
                                  metric = getConfig().isMetric;
                                
                                unsigned long functionTimeout = millis();
                                  while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
                                  {
                                    requestTime(); 
                                    DEBUG_PRINTLN(F("Getting Time"));
                                    wait(1000); // call once per second
                                    DEBUG_PRINTLN(F("."));
                                  }
                                
                                #ifdef TFT_DISPLAY_ON
                                  //**Note: I had a red tab LCD but the black tab setting worked the best for me
                                  // If your TFT's plastic wrap has a Black Tab, use the following:
                                  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
                                  // If your TFT's plastic wrap has a Red Tab, use the following:
                                  //tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
                                  // If your TFT's plastic wrap has a Green Tab, use the following:
                                  //tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab
                                
                                  //Initial Setup - Set state to Idle
                                  tft.drawLine(0, 7, 160, 7, tft.Color565(123, 123, 123)); //Setup
                                  tft.fillRect(0, 8, 160, 21, tft.Color565(80, 80, 80)); //Setup
                                  tft.drawLine(0, 29, 160, 29, tft.Color565(34, 34, 34)); //Setup
                                  tft.drawLine(0, 110, 160, 110, ST7735_WHITE); //Setup
                                  tft.fillRect(0, 111, 160, 43, tft.Color565(230, 230, 230)); //Setup
                                  tft.drawLine(0, 153, 160, 153, tft.Color565(170, 170, 170)); //Setup
                                
                                  updateTime();
                                  updateTemp();
                                  updateHum();
                                
                                #endif
                                
                                  currentMillis = millis();
                                  coverMillis = currentMillis;
                                
                                  //Make sure the fan is off and the cover is closed when first powered on
                                  fanOff();
                                }
                                
                                
                                void loop()
                                {
                                  // Force reading sensor, so it works also after sleep()
                                  dht.readSensor(true);
                                  
                                  currentMillis = millis(); //Set the current millis (used for timers)
                                
                                  //Check the cover slide limit switch values
                                  debouncerOpenState.update();
                                  coverOpenState = debouncerOpenState.read();
                                
                                  debouncerClosedState.update();
                                  coverClosedState = debouncerClosedState.read();
                                  //  DEBUG_PRINT(F("coverClosedState = "));
                                  //  DEBUG_PRINTLN(coverClosedState);
                                
                                  //There is a spike in current when the motor is first turned on.  We need to stop reading for a short period so the motor doesn't immedately turn off
                                  if (currentMillis - coverMillis > 1500)
                                  {
                                    coverPowerReading = analogRead(COVER_POWER_PIN); //change back when sensor is attached
                                    //DEBUG_PRINT(F("coverPowerReading = "));
                                    //DEBUG_PRINTLN(coverPowerReading);
                                    if (coverPowerReading > closingStall && coverPowerReading < openingStall)
                                    {
                                      //Cover motor power draw is within limits
                                      coverPowerReading = 0;
                                    }
                                    else
                                    {
                                      //Cover motor power draw is over the limit.  Motor has stalled.
                                      coverPowerReading = 1;
                                    }
                                  }
                                
                                  debouncerOnOff.update();
                                  uint8_t fanButton = debouncerOnOff.read(); // Get the update value
                                  //DEBUG_PRINTLN(fanButton);
                                  if (fanButton != fanButtonPrev && fanButton == 0) {
                                    if (coverMoving == 1)
                                    {
                                      //If the cover is already moving, change directions.
                                      fanStatePrevious = fanState;
                                      coverMoving = 0;
                                    }
                                    fanState = fanState ? 0 : 1;
                                    DEBUG_PRINT(F("fanState value changed to: "));
                                    DEBUG_PRINTLN(fanState);
                                    send(msgFan.set(fanState), true); // Send new state and request ack back
                                    errorState = 0;
                                    wait(DWELL_TIME);
                                    send(msgError.set(0)); // Reset Alert state
                                    coverMillis = currentMillis; //Set the millis (used to keep track of cover close/open times)
                                  }
                                  fanButtonPrev = fanButton;
                                
                                  if (fanState != fanStatePrevious && fanState == 0 && errorState == 0)
                                  {
                                    fanOff();
                                  }
                                  if (fanState != fanStatePrevious && fanState == 1 && errorState == 0)
                                  {
                                    fanOn();
                                  }
                                
                                  if (currentMillis - dhtMillisPrev > dhtDelay)
                                  {
                                    float temperature = dht.getTemperature();
                                
                                    if (isnan(temperature))
                                    {
                                      DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
                                    }
                                    else
                                    {
                                      if (!metric)
                                      {
                                        temperature = dht.toFahrenheit(temperature);
                                      }
                                      if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS)
                                      {
                                        lastTemp = temperature;
                                        send(msgTemp.set(temperature, 1));
                                        wait(DWELL_TIME);
                                #ifdef TFT_DISPLAY_ON
                                        updateTemp();
                                #endif
                                        DEBUG_PRINT(F("Temperature is: "));
                                        DEBUG_PRINTLN(temperature);
                                      }
                                    }
                                    float humidity = dht.getHumidity();;
                                    if (isnan(humidity))
                                    {
                                      DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
                                    } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS)
                                    {
                                      lastHum = humidity;
                                      nNoUpdatesHum = 0;
                                      send(msgHum.set(humidity, 1));
                                      wait(DWELL_TIME);
                                #ifdef TFT_DISPLAY_ON
                                      updateHum();
                                #endif
                                
                                      DEBUG_PRINT(F("Humidity is: "));
                                      DEBUG_PRINTLN(humidity);
                                    } else {
                                    // Increase no update counter if the humidity stayed the same
                                    nNoUpdatesHum++;
                                  }
                                    dhtMillisPrev = currentMillis;
                                  }
                                
                                  /*
                                    Check power usage here
                                    I want to check it every second then send it every minute (when changed) to the gateway and LCD
                                    In the "every second" check it should get a running average so it would divide by the number of seconds
                                  */
                                
                                  if (currentMillis - powerReadMillis < 1000)
                                  {
                                    //Read power every second
                                    uint16_t readValue = analogRead(FAN_POWER_PIN);
                                    //DEBUG_PRINT(F("readValue: "));
                                    //DEBUG_PRINTLN(readValue);
                                
                                    // see if you have a new pMaxValue
                                    if (readValue > pMaxValue)
                                    {
                                      /*record the maximum sensor value*/
                                      pMaxValue = readValue;
                                    }
                                    if (readValue < pMinValue)
                                    {
                                      /*record the maximum sensor value*/
                                      pMinValue = readValue;
                                    }
                                  }
                                  else
                                  {
                                    //Calulate power usage and update gateway if necessary
                                    // Subtract min from max
                                    Voltage = ((pMaxValue - pMinValue) * 5.0) / 1024.0;
                                    VRMS = (Voltage / 2.0) * 0.707;
                                    AmpsRMS = (VRMS * 1000) / mVperAmp;
                                
                                    if (AmpsRMS < .15) //filter out low readings when fan is off
                                    {
                                      AmpsRMS = 0;
                                    }
                                    DEBUG_PRINT(F("Amps RMS: "));
                                    DEBUG_PRINT(AmpsRMS);
                                
                                    wattTotal += houseVoltage * AmpsRMS;
                                    DEBUG_PRINT(F(".  Watt Total: "));
                                    DEBUG_PRINT(wattTotal);
                                    wattCount ++;
                                    DEBUG_PRINT(F(".  Watt Count: "));
                                    DEBUG_PRINTLN(wattCount);
                                    powerReadMillis = currentMillis;
                                    //Reset max and min values
                                    pMaxValue = 0;
                                    pMinValue = 1024;
                                
                                    //Update fanPowerReading to make sure the fan is off before closing the cover
                                    fanPowerReading = AmpsRMS > 1 ? 1 : 0;
                                    DEBUG_PRINT(F("fanPowerReading: "));
                                    DEBUG_PRINTLN(fanPowerReading);
                                
                                    //Update Gateway and LCD every minute if necessary
                                    if (currentMillis - powerUpdateMillis > 60000)
                                    {
                                      //We don't want to flood the gateway with updates so if the last reading was close to the current one we don't need to send the new reading
                                      wattAvg = wattTotal / wattCount;
                                      DEBUG_PRINT(F("Watt Average: "));
                                      DEBUG_PRINTLN(wattAvg);
                                
                                      //Only update if last usage was different by 2 watts
                                      if (wattAvgPrev - wattAvg > 2 || wattAvg - wattAvgPrev > 2)
                                      {
                                        //Send to gateway
                                        send(msgFanPwr.set(wattAvg));
                                
                                #ifdef TFT_DISPLAY_ON
                                        if (fanPowerReading == 1)
                                        {
                                          //Update LCD if running
                                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                                          tft.setFont();
                                          tft.setTextSize(1);
                                          tft.setCursor(5, 95);
                                          tft.print("Watts: "); //First line of text 20 characters max
                                          tft.print(wattAvg);
                                          tft.print("  ");
                                          DEBUG_PRINT(F("Watts update display: "));
                                          DEBUG_PRINTLN(wattAvg);
                                        }
                                
                                
                                #endif
                                
                                      }
                                      wattAvgPrev = wattAvg;
                                
                                      //Reset watt trackers
                                      wattTotal = 0;
                                      wattCount = 0;
                                
                                      powerUpdateMillis = currentMillis;
                                
                                      //Using this if statement to update the time every minute
                                #ifdef TFT_DISPLAY_ON
                                      //Update Time on Display every minute
                                      updateTime();
                                #endif
                                    }
                                  }
                                
                                  if (currentMillis - lastGetTime >= 3600000UL) // updates clock time and gets zone times from gateway once every hour
                                  {
                                    DEBUG_PRINTLN(F("Requesting time and valve data from Gateway..."));
                                
                                    lastGetTime = millis();
                                  }
                                }
                                
                                void fanOff() {
                                  /*
                                     1. Turn off the fan
                                     2. Make sure it's off before we start closing the cover
                                     3. Close cover
                                        a. Start a timer for how long the closing should take
                                        b. Stop the motor when the limit switch is hit
                                     4. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message (via motion sensor).
                                     5. Send "off" message to gateway/controller
                                  */
                                
                                  //DEBUG_PRINTLN(F("In the fanOff function"));
                                  if (fanRelayState == RELAY_ON)
                                  {
                                    DEBUG_PRINTLN(F("Turning off fan"));
                                    //Turn off fan and set fan relay state to 0
                                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                    fanRelayState = RELAY_OFF;
                                
                                  }
                                  if (currentMillis - coverMillis < coverLimitTime)
                                  {
                                    if (coverPowerReading == 0)
                                    {
                                      //Make sure the fan is off before closing the cover to prevent damage to the cover and fan
                                      if (fanPowerReading == 0)
                                      {
                                        //Start closing the cover
                                        //Set the close pin on the L298N board to high
                                
                                        if (coverMoving == 0)
                                        {
                                          DEBUG_PRINTLN(F("Closing Cover"));
                                          digitalWrite(COVER_CLOSE_PIN, HIGH);
                                          //Set COVER_OPEN_PIN to low just to be safe
                                          digitalWrite(COVER_OPEN_PIN, LOW);
                                
                                          //Update the LCD with "Closing" status message
                                #ifdef TFT_DISPLAY_ON
                                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                                          tft.setFont();
                                          tft.setTextSize(1);
                                          tft.setCursor(5, 95);
                                          tft.print("CLOSING COVER     "); //First line of text 20 characters max
                                #endif
                                          coverMoving = 1;
                                        }
                                
                                        if (coverClosedState == LOW)
                                        {
                                          //The cover is closed.  Stop motor and send status to gateway.
                                          digitalWrite(COVER_CLOSE_PIN, LOW);
                                          fanStatePrevious = fanState;
                                          send(msgFan.set(fanState), true); // Send new state with Ack
                                          coverMoving = 0;
                                
                                #ifdef TFT_DISPLAY_ON
                                          //Update LCD
                                          wait(200); //Wait for radio SPI to stop (otherwise display is garbled)
                                          updateTFTStatus(0); //Set status to idle state
                                #endif
                                        }
                                      }
                                    }
                                    else
                                    {
                                      //Cover motor is using too much power.  Stop everything to avoid damage.
                                      DEBUG_PRINTLN(F("The slide motor is using too much power!"));
                                      digitalWrite(COVER_CLOSE_PIN, LOW);
                                      digitalWrite(COVER_OPEN_PIN, LOW);
                                      errorState = 1; //Set the error state so it doesn't keep trying to close
                                      send(msgError.set(1)); // Send alert state to gateway
                                #ifdef TFT_DISPLAY_ON
                                      //Update LCD
                                      updateTFTStatus(2); //Set status to error state
                                      errorOvercurrent(); //More detailed error message
                                #endif
                                    }
                                  }
                                  else
                                  {
                                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                                      Possible errors could be:
                                      Fan did not shut off.
                                      Cover did not fully close in time (slide jam, motor slip etc.)
                                      Over current in cover motor (jammed?)
                                    */
                                    //Send commands to stop everything to avoid damage.
                                    DEBUG_PRINTLN(F("Cover time exceeded"));
                                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                    digitalWrite(COVER_CLOSE_PIN, LOW);
                                    digitalWrite(COVER_OPEN_PIN, LOW);
                                    errorState = 1; //Set the error state so it doesn't keep trying to close
                                    send(msgError.set(1)); // Send alert state to gateway
                                
                                #ifdef TFT_DISPLAY_ON
                                    //Update LCD
                                    updateTFTStatus(2); //Set status to error state
                                    errorTime(); //Write more detailed error to LCD
                                #endif
                                  }
                                }
                                
                                void fanOn() {
                                
                                  /*
                                    1. Open the cover
                                      a. Start a timer to keep track of how long the cover has been opening 
                                      b. Stop the motor when the limit switch is hit
                                    2. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message.
                                    3. Start the fan
                                    4. Send "on" message to gateway/controller
                                  */
                                
                                  if (currentMillis - coverMillis < coverLimitTime)
                                  {
                                    if (coverPowerReading == 0)
                                    {
                                      //Start opening the cover
                                      if (coverMoving == 0)
                                      {
                                        DEBUG_PRINTLN(F("Opening Cover"));
                                
                                        //Set COVER_CLOSE_PIN to low just to be safe
                                        digitalWrite(COVER_CLOSE_PIN, LOW);
                                        digitalWrite(COVER_OPEN_PIN, HIGH);
                                        coverMoving = 1;
                                
                                #ifdef TFT_DISPLAY_ON
                                        wait(200); //Wait for radio communication to stop (otherwise display is garbled because of SPI conflicts)
                                        //Update LCD
                                        updateTFTStatus(1); //Set status to idle state
                                #endif
                                
                                      }
                                
                                      if (coverOpenState == LOW)
                                      {
                                        //The cover is open.  Stop motor and send status to gateway.
                                        digitalWrite(COVER_OPEN_PIN, LOW);
                                        fanStatePrevious = fanState;
                                        //Turn on Fan
                                        digitalWrite(FAN_RELAY_PIN, RELAY_ON);
                                        fanRelayState = RELAY_ON;
                                        coverMoving = 0;
                                      }
                                    }
                                    else
                                    {
                                      //Cover motor is using too much power.  Stop everything to avoid damage.
                                      DEBUG_PRINTLN(F("The cover motor is using too much power!"));
                                      digitalWrite(COVER_CLOSE_PIN, LOW);
                                      digitalWrite(COVER_OPEN_PIN, LOW);
                                      errorState = 1; //Set the error state so it doesn't keep trying to close
                                      send(msgError.set(1)); // Send alert state to gateway
                                #ifdef TFT_DISPLAY_ON
                                      //Update LCD
                                      updateTFTStatus(2); //Set status to error state
                                      errorOvercurrent(); //More detailed error message
                                #endif
                                    }
                                  }
                                  else
                                  {
                                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                                      Possible errors could be:
                                      Cover did not fully open in time (slide jam, motor slip etc.)
                                      Overcurrent in cover motor (jammed?)
                                    */
                                    //Send commands to stop everything to avoid damage.
                                    DEBUG_PRINTLN(F("Cover time exceeded"));
                                    digitalWrite(COVER_CLOSE_PIN, LOW);
                                    digitalWrite(COVER_OPEN_PIN, LOW);
                                    errorState = 1; //Set the error state so it doesn't keep trying to close
                                
                                #ifdef TFT_DISPLAY_ON
                                    //Update LCD
                                    updateTFTStatus(2); //Set status to error state
                                    tft.setCursor(5, 90);
                                    //More detailed error message
                                    errorTime();
                                #endif
                                  }
                                
                                }
                                
                                
                                void receive(const MyMessage & message) {
                                  // We only expect one type of message from controller. But we better check anyway.
                                  if (message.isAck()) {
                                    DEBUG_PRINTLN(F("This is an ack from gateway"));
                                  }
                                
                                  if (message.type == V_LIGHT && !message.isAck()) {
                                    // Change relay state
                                    fanState = message.getBool();
                                    if (coverMoving == 1)
                                    {
                                      //If the cover is already moving, check to see if we need to change directions
                                      DEBUG_PRINT(F("Cover is moving"));
                                      if (fanState == fanStatePrevious)
                                      {
                                        //We need to change directions
                                        fanStatePrevious = fanState ? 0 : 1;
                                        coverMoving = 0;
                                      }
                                    }
                                    coverMillis = millis(); //Set the millis (used to keep track of cover close/open times)
                                
                                    // Write some debug info
                                    DEBUG_PRINT(F("Incoming change for sensor:"));
                                    DEBUG_PRINT(message.sensor);
                                    DEBUG_PRINT(F(", New status: "));
                                    DEBUG_PRINTLN(fanState);
                                  }
                                }
                                
                                // This is called when a new time value was received
                                void receiveTime(unsigned long time) {
                                  // Ok, set incoming time 
                                  setTime(time);
                                }
                                
                                #ifdef TFT_DISPLAY_ON
                                void updateTFTStatus(uint8_t bgStat)
                                {
                                  //bgStat: 0 = "Idle", 1 = "Running", 2 = "Error"
                                  //Idle Color = 37, 125, 20
                                  //Running Color = 53, 47, 125
                                  //Error Color = 155, 26, 26
                                
                                  uint8_t r, g, b;
                                  const char *displayStatus[] = {
                                    "Idle", "Running", "Error"
                                  };
                                  if (bgStat == 0)
                                  {
                                    //Idle
                                    r = 37;
                                    g = 125;
                                    b = 20;
                                  }
                                  else if (bgStat == 1)
                                  {
                                    //Running
                                    r = 53;
                                    g = 47;
                                    b = 125;
                                  }
                                  else
                                  {
                                    //Error
                                    r = 155;
                                    g = 26;
                                    b = 26;
                                  }
                                
                                  tft.fillRect(0, 0, 160, 7, tft.Color565(r, g, b));
                                  tft.fillRect(0, 30, 160, 80, tft.Color565(r, g, b));
                                  tft.fillRect(0, 154, 160, 6, tft.Color565(r, g, b));
                                
                                  tft.setCursor(5, 40);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setTextSize(1);
                                  tft.println("Status");
                                
                                  tft.setCursor(5, 65);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  //tft.setTextSize(3);
                                  tft.setTextSize(bgStat == 1 ? 2 : 3); //The word "Running" doesn't fit with text size 3.
                                  tft.println(displayStatus[bgStat]);
                                
                                }
                                void errorOvercurrent()
                                {
                                  tft.setCursor(5, 90);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  tft.setTextSize(1);
                                  tft.println("Motor overcurrent"); //First line of text 20 characters max
                                  tft.setCursor(5, 101);
                                  tft.println("Check cover slide"); //Second line of text 20 characters max
                                }
                                void errorTime()
                                {
                                  tft.setCursor(5, 90);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  tft.setTextSize(1);
                                  tft.println("Time exceeded"); //First line of text 20 characters max
                                  tft.setCursor(5, 100);
                                  tft.println("Check cover slide"); //Second line of text 20 characters max
                                }
                                void updateTime()
                                {
                                  //Update Time
                                  tft.setCursor(5, 17);
                                  tft.setTextColor(ST7735_WHITE, tft.Color565(80, 80, 80));
                                  tft.setTextSize(1);
                                  tft.print(hourFormat12());
                                  tft.print(minute() < 10 ? F(":0") : F(":"));
                                  tft.print(minute());
                                  tft.print(isAM() ? F("am") : F("pm"));
                                  tft.print(month() < 10 ? F(" 0") : F(" "));
                                  tft.print(month());
                                  tft.print(day() < 10 ? F("/0") : F("/"));
                                  tft.print(day());
                                  tft.print(F("/"));
                                  tft.print(year() % 100);
                                  tft.print(F(" "));
                                }
                                void updateTemp()
                                {
                                  //Update Temperature
                                  tft.setCursor(5, 120);
                                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                                  tft.setTextSize(1);
                                  tft.print("Temp: ");
                                  tft.print(lastTemp, 1);
                                  tft.print((char)247);
                                  tft.print(" ");
                                }
                                void updateHum()
                                {
                                  //Update Humidity
                                  tft.setCursor(5, 140);
                                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                                  tft.setTextSize(1);
                                  tft.print("Humidity: ");
                                  tft.print(lastHum, 1);
                                  tft.print("% ");
                                }
                                #endif
                                
                                rechin304R Offline
                                rechin304R Offline
                                rechin304
                                wrote on last edited by
                                #15

                                Yes, debug is enabled, see the code adapted for v2, below. I have build separate node for testing only temp and hum and no data is coming too (several DHT11 used).. i used example that come from library. (example used is this https://github.com/mysensors/MySensorsArduinoExamples/blob/master/examples/DhtTemperatureAndHumiditySensor/DhtTemperatureAndHumiditySensor.ino )

                                @rechin304 said:

                                This is hat i made until now. I have two issues:

                                1. DHT11 is not working (no temp or hum is shown)
                                2. I use Domoticz as controller and i do not see the node connecting to it, even the clock is sync with gateway. Gateway is version 2. So please if you have some time to look at the code your help be highly appreciated. Thanks.
                                /**
                                   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.
                                
                                   Power monitoring code adapted from: http://henrysbench.capnfatz.com/henrys-bench/arduino-current-measurements/acs712-arduino-ac-current-tutorial/
                                 *******************************
                                
                                   REVISION HISTORY
                                   Version 1.0 - Initial code
                                   Version 2.0 - Changed for Mysensors v2
                                   
                                   DESCRIPTION
                                   The code below will run a MySensors whole house fan with wall mounted lcd control panel.  The fan is installed in the attic and an insulated cover will 
                                   open/close to conserve energy.  The project cost a little over $300 US.  A comparable commercial product costs around $1200.
                                   
                                   FEATURES
                                   - Physical button switch to control on/off in case there are ever issues with radio communications.  
                                   - DHT22 sensor for temp/humidity monitoring in the attic
                                   - LCD screen displays status, temp/humidity, errors & date/time
                                   - If an error occurs a message is sent to the gateway
                                   - When the unit looses power it will make sure the cover is closed and the fan is off after power is restored.
                                   - Safety Features
                                	- The cover will wait to close until power has been shut off to the fan
                                	- Customizable over current protection on the cover motor (automatically shut off if the cover gets stuck)
                                	- Customizable cover close time limit (if it slips out off the coupling the motor won't run indefinitely)
                                
                                   NOTE
                                   This program is too large to run with all debugging and the display enabled.
                                   To upload either comment out "#define DEBUG_ON" in the code below or comment out
                                   "#define DEBUG" in MyConfig.h in the MySensors library.
                                   For troubleshooting "#ifdef TFT_DISPLAY_ON" can be commented out so all debugging
                                   messages can be output to the serial monitor
                                
                                */
                                // Enable debug prints to serial monitor
                                #define MY_DEBUG
                                // Enable and select radio type attached
                                #define MY_RADIO_NRF24
                                #define MY_RF24_PA_LEVEL RF24_PA_MAX
                                
                                #include <MySensors.h>
                                #include <SPI.h>
                                #include <Bounce2.h>
                                #include <DHT.h>
                                #include <Adafruit_GFX.h>    // Core graphics library
                                #include <Adafruit_ST7735.h> // Hardware-specific library
                                #include <Time.h>
                                #include <TimeLib.h>
                                
                                //#define NODE_ID AUTO //or set to AUTO to have the gateway assign an ID
                                
                                //#define NODE_REPEAT false //change to true to set to a repeating/relaying node
                                
                                
                                #define MY_NODE_ID AUTO  //set to AUTO to have the gateway assign an ID
                                #define SKETCH_NAME "House Fan Mysensors v2"
                                #define SKETCH_VERSION "2.1"
                                
                                #define FAN_ID 0   	// ID of the fan sensor child
                                #define ERROR_ID 1 	// ID of the alert child 
                                #define	HUM_ID 2 	//ID of the humidity child
                                #define TEMP_ID 3 	//ID of the temp child
                                
                                #define BUTTON_PIN 2  				//Pin for the on/off button 
                                // Set this to the pin you connected the DHT's data pin to
                                #define DHT_DATA_PIN A0
                                // Set this offset if the sensor has a permanent small offset to the real temperatures
                                #define SENSOR_TEMP_OFFSET 0
                                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 FAN_RELAY_PIN  A1  			//Pin number for relay that will control the fan
                                #define COVER_CLOSE_LIMIT_PIN A2 	//Pin number for the "cover closed" limit switch
                                #define COVER_OPEN_LIMIT_PIN A3 	//Pin number for the "cover open" limit switch
                                #define COVER_CLOSE_PIN A4 			//Pin number for the "cover close" L298N motor control board
                                #define COVER_OPEN_PIN A5			//Pin number for the "cover open" L298N motor control board
                                #define FAN_POWER_PIN A6			//Pin number for the ACS712 monitoring the fan
                                #define COVER_POWER_PIN A7			//Pin number for the ACS712 monitoring the cover motor
                                
                                #define TFT_DISPLAY_ON //Use to turn on/off display functionality (need to turn off for debugging because code is too large).
                                
                                #ifdef TFT_DISPLAY_ON
                                // TFT display and SD card pins.  They will share the software SPI interface.
                                #define SPI_SCK 8  //Also can be labeled CLK on display
                                #define SPI_DI  4 //Labeled MISO on display
                                #define SPI_DO  7  //Labeled MOSI on display
                                //#define SD_CS   5  // Chip select line for SD card (not currently used)
                                #define TFT_CS  3
                                #define TFT_DC  6 //Labeled RS
                                #define TFT_RST 0  // you can also connect this to the Arduino reset
                                Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, SPI_DO, SPI_SCK, TFT_RST);
                                #endif
                                
                                #define DEBUG_ON   // comment out to supress serial monitor output
                                
                                #ifdef DEBUG_ON
                                #define DEBUG_PRINT(x)   Serial.print(x)
                                #define DEBUG_PRINTLN(x) Serial.println(x)
                                #define SERIAL_START(x)  Serial.begin(x)
                                #else
                                #define DEBUG_PRINT(x)
                                #define DEBUG_PRINTLN(x)
                                #define SERIAL_START(x)
                                #endif
                                
                                #define RELAY_ON 1 //Switch to 0 if fan relay is off when it should be on
                                #define RELAY_OFF 0 //Switch to 1 if fan relay is on when it should be off
                                #define DWELL_TIME 50 //Time to wait between radio messages sent (helps prevent missed messages)
                                #define closingStall 465 //The value of the ACS712 when the cover motor is stopped while closing. This value should be less than the normal operating power draw.
                                #define openingStall 580 //The value of the ACS712 when the cover motor is stopped while opening.  This value should be greater than the normal operating power draw.
                                #define coverLimitTime 37000 //Slightly over the time it takes for the cover to fully open/close in milliseconds.  This will prevent the cover motor from running indefinitely.
                                
                                //Fan power reading variables. You may need to adjust these depending on your ACS712 model and house voltage
                                uint8_t mVperAmp = 69; //had to adjust for my sensor you may need to adjust yours a well // use 185 for 5A Module, 100 for 20A Module and 66 for 30A Module
                                uint8_t houseVoltage = 220; //Voltage of your house wiring (110 or 220) 
                                
                                Bounce debouncerOnOff = Bounce();
                                Bounce debouncerClosedState = Bounce();
                                Bounce debouncerOpenState = Bounce();
                                uint8_t fanButtonPrev = 0;
                                uint8_t fanState = 0;
                                uint8_t fanStatePrevious = 1;
                                uint8_t fanRelayState;
                                uint8_t coverMoving = 0;
                                uint8_t	coverClosedState = LOW;
                                uint8_t	coverOpenState = LOW;
                                uint8_t errorState = 0; //Used to keep track of errors.  Can be reset by manually pushing button
                                uint8_t fanPowerReading = 0;
                                int coverPowerReading = 0;
                                unsigned long currentMillis; //used for timers
                                unsigned long powerReadMillis; //Used read power every second
                                unsigned long powerUpdateMillis; //Used to update power usage on LCD and gateway
                                unsigned long coverMillis;
                                unsigned long dhtMillisPrev;
                                unsigned long dhtDelay = 305000;	//5 minutes 5 seconds.  Offset is in case of power failure I don't want all my nodes reporting at the same time.
                                unsigned long lastGetTime; //Used for getting time from gateway
                                
                                uint8_t lastSecond;
                                uint8_t lastMinute;
                                uint8_t lastHour;
                                
                                DHT dht;
                                float lastTemp = 0;
                                float lastHum = 0;
                                uint8_t nNoUpdatesTemp;
                                uint8_t nNoUpdatesHum;
                                boolean metric = true; //Set to true if you use the metric system
                                
                                //Fan power reading variables.
                                double Voltage = 0; //Voltage read from analog pin (used to calc power)
                                double VRMS = 0;
                                double AmpsRMS = 0;
                                uint16_t wattTotal = 0; //Used to calculate the watts used for the last minute
                                int wattAvg = 0;
                                int wattAvgPrev = 0;
                                uint8_t wattCount = 0; //Will be used to divide watts
                                uint16_t pMaxValue = 0; // store max value here
                                uint16_t pMinValue = 1024; // store min value here
                                
                                
                                //MySensor gw;
                                MyMessage msgFan(FAN_ID, V_STATUS);
                                MyMessage msgFanPwr(FAN_ID, V_WATT);
                                MyMessage msgError(ERROR_ID, V_TRIPPED);
                                MyMessage msgHum(HUM_ID, V_HUM);
                                MyMessage msgTemp(TEMP_ID, V_TEMP);
                                
                                void presentation()  
                                { 
                                  sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
                                  present(FAN_ID, S_BINARY);
                                  wait(DWELL_TIME);
                                  present(ERROR_ID, S_MOTION);
                                  wait(DWELL_TIME);
                                  present(HUM_ID, S_HUM);
                                  wait(DWELL_TIME);
                                  present(TEMP_ID, S_TEMP);
                                  wait(DWELL_TIME);
                                  metric = getConfig().isMetric;
                                }
                                
                                void setup()
                                {
                                  delay(2000); //Allow time for sensors to power up
                                  
                                requestTime();
                                  // Send the sketch version information to the gateway and Controller
                                
                                
                                  dht.setup(DHT_DATA_PIN);
                                    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());
                                
                                  // Make sure relays are off when starting up
                                  digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                  digitalWrite(COVER_OPEN_PIN, LOW);
                                  digitalWrite(COVER_CLOSE_PIN, LOW);
                                
                                  // Set the pin mode
                                  pinMode(FAN_RELAY_PIN, OUTPUT);
                                  pinMode(COVER_OPEN_PIN, OUTPUT);
                                  pinMode(COVER_CLOSE_PIN, OUTPUT);
                                  pinMode(COVER_OPEN_LIMIT_PIN, INPUT_PULLUP);
                                  pinMode(COVER_CLOSE_LIMIT_PIN, INPUT_PULLUP);
                                  pinMode(BUTTON_PIN, INPUT_PULLUP); // Setup the on/off button and activate internal pull-up
                                
                                  // After setting up the pin modes, setup debouncers
                                  debouncerOnOff.attach(BUTTON_PIN);
                                  debouncerOnOff.interval(50);
                                  debouncerOpenState.attach(COVER_OPEN_LIMIT_PIN);
                                  debouncerOpenState.interval(50);
                                  debouncerClosedState.attach(COVER_CLOSE_LIMIT_PIN);
                                  debouncerClosedState.interval(50);
                                
                                  // Register all sensors to gw (they will be created as child devices)
                                
                                
                                  send(msgError.set(0)); // Reset Alert state
                                
                                  //Check the cover slide limit switch values
                                  debouncerOpenState.update();
                                  coverOpenState = debouncerOpenState.read();
                                
                                  debouncerClosedState.update();
                                  coverClosedState = debouncerClosedState.read();
                                
                                  metric = getConfig().isMetric;
                                
                                unsigned long functionTimeout = millis();
                                  while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
                                  {
                                    requestTime(); 
                                    DEBUG_PRINTLN(F("Getting Time"));
                                    wait(1000); // call once per second
                                    DEBUG_PRINTLN(F("."));
                                  }
                                
                                #ifdef TFT_DISPLAY_ON
                                  //**Note: I had a red tab LCD but the black tab setting worked the best for me
                                  // If your TFT's plastic wrap has a Black Tab, use the following:
                                  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
                                  // If your TFT's plastic wrap has a Red Tab, use the following:
                                  //tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
                                  // If your TFT's plastic wrap has a Green Tab, use the following:
                                  //tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab
                                
                                  //Initial Setup - Set state to Idle
                                  tft.drawLine(0, 7, 160, 7, tft.Color565(123, 123, 123)); //Setup
                                  tft.fillRect(0, 8, 160, 21, tft.Color565(80, 80, 80)); //Setup
                                  tft.drawLine(0, 29, 160, 29, tft.Color565(34, 34, 34)); //Setup
                                  tft.drawLine(0, 110, 160, 110, ST7735_WHITE); //Setup
                                  tft.fillRect(0, 111, 160, 43, tft.Color565(230, 230, 230)); //Setup
                                  tft.drawLine(0, 153, 160, 153, tft.Color565(170, 170, 170)); //Setup
                                
                                  updateTime();
                                  updateTemp();
                                  updateHum();
                                
                                #endif
                                
                                  currentMillis = millis();
                                  coverMillis = currentMillis;
                                
                                  //Make sure the fan is off and the cover is closed when first powered on
                                  fanOff();
                                }
                                
                                
                                void loop()
                                {
                                  // Force reading sensor, so it works also after sleep()
                                  dht.readSensor(true);
                                  
                                  currentMillis = millis(); //Set the current millis (used for timers)
                                
                                  //Check the cover slide limit switch values
                                  debouncerOpenState.update();
                                  coverOpenState = debouncerOpenState.read();
                                
                                  debouncerClosedState.update();
                                  coverClosedState = debouncerClosedState.read();
                                  //  DEBUG_PRINT(F("coverClosedState = "));
                                  //  DEBUG_PRINTLN(coverClosedState);
                                
                                  //There is a spike in current when the motor is first turned on.  We need to stop reading for a short period so the motor doesn't immedately turn off
                                  if (currentMillis - coverMillis > 1500)
                                  {
                                    coverPowerReading = analogRead(COVER_POWER_PIN); //change back when sensor is attached
                                    //DEBUG_PRINT(F("coverPowerReading = "));
                                    //DEBUG_PRINTLN(coverPowerReading);
                                    if (coverPowerReading > closingStall && coverPowerReading < openingStall)
                                    {
                                      //Cover motor power draw is within limits
                                      coverPowerReading = 0;
                                    }
                                    else
                                    {
                                      //Cover motor power draw is over the limit.  Motor has stalled.
                                      coverPowerReading = 1;
                                    }
                                  }
                                
                                  debouncerOnOff.update();
                                  uint8_t fanButton = debouncerOnOff.read(); // Get the update value
                                  //DEBUG_PRINTLN(fanButton);
                                  if (fanButton != fanButtonPrev && fanButton == 0) {
                                    if (coverMoving == 1)
                                    {
                                      //If the cover is already moving, change directions.
                                      fanStatePrevious = fanState;
                                      coverMoving = 0;
                                    }
                                    fanState = fanState ? 0 : 1;
                                    DEBUG_PRINT(F("fanState value changed to: "));
                                    DEBUG_PRINTLN(fanState);
                                    send(msgFan.set(fanState), true); // Send new state and request ack back
                                    errorState = 0;
                                    wait(DWELL_TIME);
                                    send(msgError.set(0)); // Reset Alert state
                                    coverMillis = currentMillis; //Set the millis (used to keep track of cover close/open times)
                                  }
                                  fanButtonPrev = fanButton;
                                
                                  if (fanState != fanStatePrevious && fanState == 0 && errorState == 0)
                                  {
                                    fanOff();
                                  }
                                  if (fanState != fanStatePrevious && fanState == 1 && errorState == 0)
                                  {
                                    fanOn();
                                  }
                                
                                  if (currentMillis - dhtMillisPrev > dhtDelay)
                                  {
                                    float temperature = dht.getTemperature();
                                
                                    if (isnan(temperature))
                                    {
                                      DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
                                    }
                                    else
                                    {
                                      if (!metric)
                                      {
                                        temperature = dht.toFahrenheit(temperature);
                                      }
                                      if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS)
                                      {
                                        lastTemp = temperature;
                                        send(msgTemp.set(temperature, 1));
                                        wait(DWELL_TIME);
                                #ifdef TFT_DISPLAY_ON
                                        updateTemp();
                                #endif
                                        DEBUG_PRINT(F("Temperature is: "));
                                        DEBUG_PRINTLN(temperature);
                                      }
                                    }
                                    float humidity = dht.getHumidity();;
                                    if (isnan(humidity))
                                    {
                                      DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
                                    } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS)
                                    {
                                      lastHum = humidity;
                                      nNoUpdatesHum = 0;
                                      send(msgHum.set(humidity, 1));
                                      wait(DWELL_TIME);
                                #ifdef TFT_DISPLAY_ON
                                      updateHum();
                                #endif
                                
                                      DEBUG_PRINT(F("Humidity is: "));
                                      DEBUG_PRINTLN(humidity);
                                    } else {
                                    // Increase no update counter if the humidity stayed the same
                                    nNoUpdatesHum++;
                                  }
                                    dhtMillisPrev = currentMillis;
                                  }
                                
                                  /*
                                    Check power usage here
                                    I want to check it every second then send it every minute (when changed) to the gateway and LCD
                                    In the "every second" check it should get a running average so it would divide by the number of seconds
                                  */
                                
                                  if (currentMillis - powerReadMillis < 1000)
                                  {
                                    //Read power every second
                                    uint16_t readValue = analogRead(FAN_POWER_PIN);
                                    //DEBUG_PRINT(F("readValue: "));
                                    //DEBUG_PRINTLN(readValue);
                                
                                    // see if you have a new pMaxValue
                                    if (readValue > pMaxValue)
                                    {
                                      /*record the maximum sensor value*/
                                      pMaxValue = readValue;
                                    }
                                    if (readValue < pMinValue)
                                    {
                                      /*record the maximum sensor value*/
                                      pMinValue = readValue;
                                    }
                                  }
                                  else
                                  {
                                    //Calulate power usage and update gateway if necessary
                                    // Subtract min from max
                                    Voltage = ((pMaxValue - pMinValue) * 5.0) / 1024.0;
                                    VRMS = (Voltage / 2.0) * 0.707;
                                    AmpsRMS = (VRMS * 1000) / mVperAmp;
                                
                                    if (AmpsRMS < .15) //filter out low readings when fan is off
                                    {
                                      AmpsRMS = 0;
                                    }
                                    DEBUG_PRINT(F("Amps RMS: "));
                                    DEBUG_PRINT(AmpsRMS);
                                
                                    wattTotal += houseVoltage * AmpsRMS;
                                    DEBUG_PRINT(F(".  Watt Total: "));
                                    DEBUG_PRINT(wattTotal);
                                    wattCount ++;
                                    DEBUG_PRINT(F(".  Watt Count: "));
                                    DEBUG_PRINTLN(wattCount);
                                    powerReadMillis = currentMillis;
                                    //Reset max and min values
                                    pMaxValue = 0;
                                    pMinValue = 1024;
                                
                                    //Update fanPowerReading to make sure the fan is off before closing the cover
                                    fanPowerReading = AmpsRMS > 1 ? 1 : 0;
                                    DEBUG_PRINT(F("fanPowerReading: "));
                                    DEBUG_PRINTLN(fanPowerReading);
                                
                                    //Update Gateway and LCD every minute if necessary
                                    if (currentMillis - powerUpdateMillis > 60000)
                                    {
                                      //We don't want to flood the gateway with updates so if the last reading was close to the current one we don't need to send the new reading
                                      wattAvg = wattTotal / wattCount;
                                      DEBUG_PRINT(F("Watt Average: "));
                                      DEBUG_PRINTLN(wattAvg);
                                
                                      //Only update if last usage was different by 2 watts
                                      if (wattAvgPrev - wattAvg > 2 || wattAvg - wattAvgPrev > 2)
                                      {
                                        //Send to gateway
                                        send(msgFanPwr.set(wattAvg));
                                
                                #ifdef TFT_DISPLAY_ON
                                        if (fanPowerReading == 1)
                                        {
                                          //Update LCD if running
                                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                                          tft.setFont();
                                          tft.setTextSize(1);
                                          tft.setCursor(5, 95);
                                          tft.print("Watts: "); //First line of text 20 characters max
                                          tft.print(wattAvg);
                                          tft.print("  ");
                                          DEBUG_PRINT(F("Watts update display: "));
                                          DEBUG_PRINTLN(wattAvg);
                                        }
                                
                                
                                #endif
                                
                                      }
                                      wattAvgPrev = wattAvg;
                                
                                      //Reset watt trackers
                                      wattTotal = 0;
                                      wattCount = 0;
                                
                                      powerUpdateMillis = currentMillis;
                                
                                      //Using this if statement to update the time every minute
                                #ifdef TFT_DISPLAY_ON
                                      //Update Time on Display every minute
                                      updateTime();
                                #endif
                                    }
                                  }
                                
                                  if (currentMillis - lastGetTime >= 3600000UL) // updates clock time and gets zone times from gateway once every hour
                                  {
                                    DEBUG_PRINTLN(F("Requesting time and valve data from Gateway..."));
                                
                                    lastGetTime = millis();
                                  }
                                }
                                
                                void fanOff() {
                                  /*
                                     1. Turn off the fan
                                     2. Make sure it's off before we start closing the cover
                                     3. Close cover
                                        a. Start a timer for how long the closing should take
                                        b. Stop the motor when the limit switch is hit
                                     4. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message (via motion sensor).
                                     5. Send "off" message to gateway/controller
                                  */
                                
                                  //DEBUG_PRINTLN(F("In the fanOff function"));
                                  if (fanRelayState == RELAY_ON)
                                  {
                                    DEBUG_PRINTLN(F("Turning off fan"));
                                    //Turn off fan and set fan relay state to 0
                                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                    fanRelayState = RELAY_OFF;
                                
                                  }
                                  if (currentMillis - coverMillis < coverLimitTime)
                                  {
                                    if (coverPowerReading == 0)
                                    {
                                      //Make sure the fan is off before closing the cover to prevent damage to the cover and fan
                                      if (fanPowerReading == 0)
                                      {
                                        //Start closing the cover
                                        //Set the close pin on the L298N board to high
                                
                                        if (coverMoving == 0)
                                        {
                                          DEBUG_PRINTLN(F("Closing Cover"));
                                          digitalWrite(COVER_CLOSE_PIN, HIGH);
                                          //Set COVER_OPEN_PIN to low just to be safe
                                          digitalWrite(COVER_OPEN_PIN, LOW);
                                
                                          //Update the LCD with "Closing" status message
                                #ifdef TFT_DISPLAY_ON
                                          tft.setTextColor(ST7735_WHITE, tft.Color565(53, 47, 125));
                                          tft.setFont();
                                          tft.setTextSize(1);
                                          tft.setCursor(5, 95);
                                          tft.print("CLOSING COVER     "); //First line of text 20 characters max
                                #endif
                                          coverMoving = 1;
                                        }
                                
                                        if (coverClosedState == LOW)
                                        {
                                          //The cover is closed.  Stop motor and send status to gateway.
                                          digitalWrite(COVER_CLOSE_PIN, LOW);
                                          fanStatePrevious = fanState;
                                          send(msgFan.set(fanState), true); // Send new state with Ack
                                          coverMoving = 0;
                                
                                #ifdef TFT_DISPLAY_ON
                                          //Update LCD
                                          wait(200); //Wait for radio SPI to stop (otherwise display is garbled)
                                          updateTFTStatus(0); //Set status to idle state
                                #endif
                                        }
                                      }
                                    }
                                    else
                                    {
                                      //Cover motor is using too much power.  Stop everything to avoid damage.
                                      DEBUG_PRINTLN(F("The slide motor is using too much power!"));
                                      digitalWrite(COVER_CLOSE_PIN, LOW);
                                      digitalWrite(COVER_OPEN_PIN, LOW);
                                      errorState = 1; //Set the error state so it doesn't keep trying to close
                                      send(msgError.set(1)); // Send alert state to gateway
                                #ifdef TFT_DISPLAY_ON
                                      //Update LCD
                                      updateTFTStatus(2); //Set status to error state
                                      errorOvercurrent(); //More detailed error message
                                #endif
                                    }
                                  }
                                  else
                                  {
                                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                                      Possible errors could be:
                                      Fan did not shut off.
                                      Cover did not fully close in time (slide jam, motor slip etc.)
                                      Over current in cover motor (jammed?)
                                    */
                                    //Send commands to stop everything to avoid damage.
                                    DEBUG_PRINTLN(F("Cover time exceeded"));
                                    digitalWrite(FAN_RELAY_PIN, RELAY_OFF);
                                    digitalWrite(COVER_CLOSE_PIN, LOW);
                                    digitalWrite(COVER_OPEN_PIN, LOW);
                                    errorState = 1; //Set the error state so it doesn't keep trying to close
                                    send(msgError.set(1)); // Send alert state to gateway
                                
                                #ifdef TFT_DISPLAY_ON
                                    //Update LCD
                                    updateTFTStatus(2); //Set status to error state
                                    errorTime(); //Write more detailed error to LCD
                                #endif
                                  }
                                }
                                
                                void fanOn() {
                                
                                  /*
                                    1. Open the cover
                                      a. Start a timer to keep track of how long the cover has been opening 
                                      b. Stop the motor when the limit switch is hit
                                    2. Ensure the limit switch has been pressed and the timer didn't run out.  If it did send an error message.
                                    3. Start the fan
                                    4. Send "on" message to gateway/controller
                                  */
                                
                                  if (currentMillis - coverMillis < coverLimitTime)
                                  {
                                    if (coverPowerReading == 0)
                                    {
                                      //Start opening the cover
                                      if (coverMoving == 0)
                                      {
                                        DEBUG_PRINTLN(F("Opening Cover"));
                                
                                        //Set COVER_CLOSE_PIN to low just to be safe
                                        digitalWrite(COVER_CLOSE_PIN, LOW);
                                        digitalWrite(COVER_OPEN_PIN, HIGH);
                                        coverMoving = 1;
                                
                                #ifdef TFT_DISPLAY_ON
                                        wait(200); //Wait for radio communication to stop (otherwise display is garbled because of SPI conflicts)
                                        //Update LCD
                                        updateTFTStatus(1); //Set status to idle state
                                #endif
                                
                                      }
                                
                                      if (coverOpenState == LOW)
                                      {
                                        //The cover is open.  Stop motor and send status to gateway.
                                        digitalWrite(COVER_OPEN_PIN, LOW);
                                        fanStatePrevious = fanState;
                                        //Turn on Fan
                                        digitalWrite(FAN_RELAY_PIN, RELAY_ON);
                                        fanRelayState = RELAY_ON;
                                        coverMoving = 0;
                                      }
                                    }
                                    else
                                    {
                                      //Cover motor is using too much power.  Stop everything to avoid damage.
                                      DEBUG_PRINTLN(F("The cover motor is using too much power!"));
                                      digitalWrite(COVER_CLOSE_PIN, LOW);
                                      digitalWrite(COVER_OPEN_PIN, LOW);
                                      errorState = 1; //Set the error state so it doesn't keep trying to close
                                      send(msgError.set(1)); // Send alert state to gateway
                                #ifdef TFT_DISPLAY_ON
                                      //Update LCD
                                      updateTFTStatus(2); //Set status to error state
                                      errorOvercurrent(); //More detailed error message
                                #endif
                                    }
                                  }
                                  else
                                  {
                                    /*Things have taken too long there must be an error.  Print it out to the LCD and send trigger to gateway
                                      Possible errors could be:
                                      Cover did not fully open in time (slide jam, motor slip etc.)
                                      Overcurrent in cover motor (jammed?)
                                    */
                                    //Send commands to stop everything to avoid damage.
                                    DEBUG_PRINTLN(F("Cover time exceeded"));
                                    digitalWrite(COVER_CLOSE_PIN, LOW);
                                    digitalWrite(COVER_OPEN_PIN, LOW);
                                    errorState = 1; //Set the error state so it doesn't keep trying to close
                                
                                #ifdef TFT_DISPLAY_ON
                                    //Update LCD
                                    updateTFTStatus(2); //Set status to error state
                                    tft.setCursor(5, 90);
                                    //More detailed error message
                                    errorTime();
                                #endif
                                  }
                                
                                }
                                
                                
                                void receive(const MyMessage & message) {
                                  // We only expect one type of message from controller. But we better check anyway.
                                  if (message.isAck()) {
                                    DEBUG_PRINTLN(F("This is an ack from gateway"));
                                  }
                                
                                  if (message.type == V_LIGHT && !message.isAck()) {
                                    // Change relay state
                                    fanState = message.getBool();
                                    if (coverMoving == 1)
                                    {
                                      //If the cover is already moving, check to see if we need to change directions
                                      DEBUG_PRINT(F("Cover is moving"));
                                      if (fanState == fanStatePrevious)
                                      {
                                        //We need to change directions
                                        fanStatePrevious = fanState ? 0 : 1;
                                        coverMoving = 0;
                                      }
                                    }
                                    coverMillis = millis(); //Set the millis (used to keep track of cover close/open times)
                                
                                    // Write some debug info
                                    DEBUG_PRINT(F("Incoming change for sensor:"));
                                    DEBUG_PRINT(message.sensor);
                                    DEBUG_PRINT(F(", New status: "));
                                    DEBUG_PRINTLN(fanState);
                                  }
                                }
                                
                                // This is called when a new time value was received
                                void receiveTime(unsigned long time) {
                                  // Ok, set incoming time 
                                  setTime(time);
                                }
                                
                                #ifdef TFT_DISPLAY_ON
                                void updateTFTStatus(uint8_t bgStat)
                                {
                                  //bgStat: 0 = "Idle", 1 = "Running", 2 = "Error"
                                  //Idle Color = 37, 125, 20
                                  //Running Color = 53, 47, 125
                                  //Error Color = 155, 26, 26
                                
                                  uint8_t r, g, b;
                                  const char *displayStatus[] = {
                                    "Idle", "Running", "Error"
                                  };
                                  if (bgStat == 0)
                                  {
                                    //Idle
                                    r = 37;
                                    g = 125;
                                    b = 20;
                                  }
                                  else if (bgStat == 1)
                                  {
                                    //Running
                                    r = 53;
                                    g = 47;
                                    b = 125;
                                  }
                                  else
                                  {
                                    //Error
                                    r = 155;
                                    g = 26;
                                    b = 26;
                                  }
                                
                                  tft.fillRect(0, 0, 160, 7, tft.Color565(r, g, b));
                                  tft.fillRect(0, 30, 160, 80, tft.Color565(r, g, b));
                                  tft.fillRect(0, 154, 160, 6, tft.Color565(r, g, b));
                                
                                  tft.setCursor(5, 40);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setTextSize(1);
                                  tft.println("Status");
                                
                                  tft.setCursor(5, 65);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  //tft.setTextSize(3);
                                  tft.setTextSize(bgStat == 1 ? 2 : 3); //The word "Running" doesn't fit with text size 3.
                                  tft.println(displayStatus[bgStat]);
                                
                                }
                                void errorOvercurrent()
                                {
                                  tft.setCursor(5, 90);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  tft.setTextSize(1);
                                  tft.println("Motor overcurrent"); //First line of text 20 characters max
                                  tft.setCursor(5, 101);
                                  tft.println("Check cover slide"); //Second line of text 20 characters max
                                }
                                void errorTime()
                                {
                                  tft.setCursor(5, 90);
                                  tft.setTextColor(ST7735_WHITE);
                                  tft.setFont();
                                  tft.setTextSize(1);
                                  tft.println("Time exceeded"); //First line of text 20 characters max
                                  tft.setCursor(5, 100);
                                  tft.println("Check cover slide"); //Second line of text 20 characters max
                                }
                                void updateTime()
                                {
                                  //Update Time
                                  tft.setCursor(5, 17);
                                  tft.setTextColor(ST7735_WHITE, tft.Color565(80, 80, 80));
                                  tft.setTextSize(1);
                                  tft.print(hourFormat12());
                                  tft.print(minute() < 10 ? F(":0") : F(":"));
                                  tft.print(minute());
                                  tft.print(isAM() ? F("am") : F("pm"));
                                  tft.print(month() < 10 ? F(" 0") : F(" "));
                                  tft.print(month());
                                  tft.print(day() < 10 ? F("/0") : F("/"));
                                  tft.print(day());
                                  tft.print(F("/"));
                                  tft.print(year() % 100);
                                  tft.print(F(" "));
                                }
                                void updateTemp()
                                {
                                  //Update Temperature
                                  tft.setCursor(5, 120);
                                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                                  tft.setTextSize(1);
                                  tft.print("Temp: ");
                                  tft.print(lastTemp, 1);
                                  tft.print((char)247);
                                  tft.print(" ");
                                }
                                void updateHum()
                                {
                                  //Update Humidity
                                  tft.setCursor(5, 140);
                                  tft.setTextColor(tft.Color565(80, 80, 80), tft.Color565(230, 230, 230));
                                  tft.setTextSize(1);
                                  tft.print("Humidity: ");
                                  tft.print(lastHum, 1);
                                  tft.print("% ");
                                }
                                #endif
                                
                                1 Reply Last reply
                                0
                                • rechin304R Offline
                                  rechin304R Offline
                                  rechin304
                                  wrote on last edited by rechin304
                                  #16

                                  This is the output that i get. Maybe you can understand why. And this is a clean example. Anyone have make temp DHT11 to work in version2 ?

                                  Starting sensor (RNNNA-, 2.0.0)
                                  TSM:INIT
                                  TSM:RADIO:OK
                                  TSP:ASSIGNID:OK (ID=27)
                                  TSM:FPAR
                                  TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                  TSM:FPAR
                                  TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                  TSP:MSG:READ 25-25-27 s=255,c=3,t=8,pt=1,l=1,sg=0:1
                                  TSP:MSG:FPAR RES (ID=25, dist=1)
                                  TSP:MSG:PAR OK (ID=25, dist=2)
                                  TSP:MSG:READ 0-0-27 s=255,c=3,t=8,pt=1,l=1,sg=0:0
                                  TSP:MSG:FPAR RES (ID=0, dist=0)
                                  TSP:MSG:PAR OK (ID=0, dist=1)
                                  TSM:FPAR:OK
                                  TSM:ID
                                  TSM:CHKID:OK (ID=27)
                                  TSM:UPL
                                  TSP:PING:SEND (dest=0)
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=ok:1
                                  TSP:MSG:READ 0-0-27 s=255,c=3,t=25,pt=1,l=1,sg=0:1
                                  TSP:MSG:PONG RECV (hops=1)
                                  TSP:CHKUPL:OK
                                  TSM:UPL:OK
                                  TSM:READY
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=ok:0100
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=ok:2.0.0
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=ok:0
                                  TSP:MSG:READ 0-0-27 s=255,c=3,t=15,pt=6,l=2,sg=0:0100
                                  TSP:MSG:READ 0-0-27 s=255,c=3,t=6,pt=0,l=1,sg=0:M
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=11,pt=0,l=22,sg=0,ft=0,st=ok:TemperatureAndHumidity
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=ok:1.1
                                  TSP:MSG:SEND 27-27-0-0 s=0,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=ok:
                                  TSP:MSG:SEND 27-27-0-0 s=1,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=ok:
                                  Request registration...
                                  TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=ok:2
                                  TSP:MSG:READ 0-0-27 s=255,c=3,t=27,pt=1,l=1,sg=0:1
                                  Node registration=1
                                  Init complete, id=27, parent=0, distance=1, registration=1```
                                  

                                  If i get the sensor out i get this

                                  Init complete, id=27, parent=0, distance=1, registration=1
                                  Failed reading temperature from DHT!
                                  Failed reading humidity from DHT
                                  
                                  petewillP flyswiftlyF 2 Replies Last reply
                                  0
                                  • rechin304R rechin304

                                    This is the output that i get. Maybe you can understand why. And this is a clean example. Anyone have make temp DHT11 to work in version2 ?

                                    Starting sensor (RNNNA-, 2.0.0)
                                    TSM:INIT
                                    TSM:RADIO:OK
                                    TSP:ASSIGNID:OK (ID=27)
                                    TSM:FPAR
                                    TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                    TSM:FPAR
                                    TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                    TSP:MSG:READ 25-25-27 s=255,c=3,t=8,pt=1,l=1,sg=0:1
                                    TSP:MSG:FPAR RES (ID=25, dist=1)
                                    TSP:MSG:PAR OK (ID=25, dist=2)
                                    TSP:MSG:READ 0-0-27 s=255,c=3,t=8,pt=1,l=1,sg=0:0
                                    TSP:MSG:FPAR RES (ID=0, dist=0)
                                    TSP:MSG:PAR OK (ID=0, dist=1)
                                    TSM:FPAR:OK
                                    TSM:ID
                                    TSM:CHKID:OK (ID=27)
                                    TSM:UPL
                                    TSP:PING:SEND (dest=0)
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=ok:1
                                    TSP:MSG:READ 0-0-27 s=255,c=3,t=25,pt=1,l=1,sg=0:1
                                    TSP:MSG:PONG RECV (hops=1)
                                    TSP:CHKUPL:OK
                                    TSM:UPL:OK
                                    TSM:READY
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=ok:0100
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=ok:2.0.0
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=ok:0
                                    TSP:MSG:READ 0-0-27 s=255,c=3,t=15,pt=6,l=2,sg=0:0100
                                    TSP:MSG:READ 0-0-27 s=255,c=3,t=6,pt=0,l=1,sg=0:M
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=11,pt=0,l=22,sg=0,ft=0,st=ok:TemperatureAndHumidity
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=ok:1.1
                                    TSP:MSG:SEND 27-27-0-0 s=0,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=ok:
                                    TSP:MSG:SEND 27-27-0-0 s=1,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=ok:
                                    Request registration...
                                    TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=ok:2
                                    TSP:MSG:READ 0-0-27 s=255,c=3,t=27,pt=1,l=1,sg=0:1
                                    Node registration=1
                                    Init complete, id=27, parent=0, distance=1, registration=1```
                                    

                                    If i get the sensor out i get this

                                    Init complete, id=27, parent=0, distance=1, registration=1
                                    Failed reading temperature from DHT!
                                    Failed reading humidity from DHT
                                    
                                    petewillP Offline
                                    petewillP Offline
                                    petewill
                                    Admin
                                    wrote on last edited by
                                    #17

                                    @rechin304 Something is most likely wrong with your wiring or the sensor. I am using a DHT22 without any issues in my rain gauge which is on 2.0 (I'm using the most recent beta release). Try connecting a 4.7k resistor between the data pin and power on the DHT like this.
                                    0_1478303148400_upload-1d245d6b-aad9-4841-8307-485c9caf5056

                                    My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

                                    1 Reply Last reply
                                    0
                                    • enloE Offline
                                      enloE Offline
                                      enlo
                                      wrote on last edited by
                                      #18

                                      @petewill wow, your screen case looks amazing! Is that acryl glass? Did you build that yourself too?

                                      petewillP 1 Reply Last reply
                                      0
                                      • enloE enlo

                                        @petewill wow, your screen case looks amazing! Is that acryl glass? Did you build that yourself too?

                                        petewillP Offline
                                        petewillP Offline
                                        petewill
                                        Admin
                                        wrote on last edited by
                                        #19

                                        @enlo Thanks. Yeah, it's acrylic glass (Plexiglas). It was a pain to use though as I couldn't clean off the paint very well. My next project I'm working on I'm going to try to use regular glass.

                                        My "How To" home automation video channel: https://www.youtube.com/channel/UCq_Evyh5PQALx4m4CQuxqkA

                                        1 Reply Last reply
                                        0
                                        • rechin304R rechin304

                                          This is the output that i get. Maybe you can understand why. And this is a clean example. Anyone have make temp DHT11 to work in version2 ?

                                          Starting sensor (RNNNA-, 2.0.0)
                                          TSM:INIT
                                          TSM:RADIO:OK
                                          TSP:ASSIGNID:OK (ID=27)
                                          TSM:FPAR
                                          TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                          TSM:FPAR
                                          TSP:MSG:SEND 27-27-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc:
                                          TSP:MSG:READ 25-25-27 s=255,c=3,t=8,pt=1,l=1,sg=0:1
                                          TSP:MSG:FPAR RES (ID=25, dist=1)
                                          TSP:MSG:PAR OK (ID=25, dist=2)
                                          TSP:MSG:READ 0-0-27 s=255,c=3,t=8,pt=1,l=1,sg=0:0
                                          TSP:MSG:FPAR RES (ID=0, dist=0)
                                          TSP:MSG:PAR OK (ID=0, dist=1)
                                          TSM:FPAR:OK
                                          TSM:ID
                                          TSM:CHKID:OK (ID=27)
                                          TSM:UPL
                                          TSP:PING:SEND (dest=0)
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=ok:1
                                          TSP:MSG:READ 0-0-27 s=255,c=3,t=25,pt=1,l=1,sg=0:1
                                          TSP:MSG:PONG RECV (hops=1)
                                          TSP:CHKUPL:OK
                                          TSM:UPL:OK
                                          TSM:READY
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=ok:0100
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=ok:2.0.0
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=ok:0
                                          TSP:MSG:READ 0-0-27 s=255,c=3,t=15,pt=6,l=2,sg=0:0100
                                          TSP:MSG:READ 0-0-27 s=255,c=3,t=6,pt=0,l=1,sg=0:M
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=11,pt=0,l=22,sg=0,ft=0,st=ok:TemperatureAndHumidity
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=ok:1.1
                                          TSP:MSG:SEND 27-27-0-0 s=0,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=ok:
                                          TSP:MSG:SEND 27-27-0-0 s=1,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=ok:
                                          Request registration...
                                          TSP:MSG:SEND 27-27-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=ok:2
                                          TSP:MSG:READ 0-0-27 s=255,c=3,t=27,pt=1,l=1,sg=0:1
                                          Node registration=1
                                          Init complete, id=27, parent=0, distance=1, registration=1```
                                          

                                          If i get the sensor out i get this

                                          Init complete, id=27, parent=0, distance=1, registration=1
                                          Failed reading temperature from DHT!
                                          Failed reading humidity from DHT
                                          
                                          flyswiftlyF Offline
                                          flyswiftlyF Offline
                                          flyswiftly
                                          wrote on last edited by
                                          #20

                                          @rechin304 said:

                                          dht.setup(DHT_DATA_PIN);
                                          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());

                                          For what it's worth, I just went through a very long debug session trying to get a simple dht11 based sensor built and working. For reasons I don't even pretend to understand, the one thing I changed that allows it to work is changing the 'sleep' command in this section of the setup function to a 'wait' command.

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


                                          3

                                          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
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular