Skip to content
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
Expand All @@ -21,38 +22,49 @@
* REVISION HISTORY
* Version 1.0: Henrik EKblad
* Version 1.1 - 2016-07-20: Converted to MySensors v2.0 and added various improvements - Torben Woltjen (mozzbozz)
* Version 2.0 - 2018-09-25: Converted to DHTU Adafruit library
* Version 2.1 - 2018-10-06: Clearer code and... if something changed... every sensor data are sent to gateway
* Version 2.2 - 2018-12-27: Heat Index calculation included in sketch (based on Adafruit official library)
*
* DESCRIPTION
* This sketch provides an example of how to implement a humidity/temperature
* sensor using a DHT11/DHT-22.
* This sketch provides an example of how to implement a humidity/temperature sensor using a DHT11/DHT21/DHT22.
* It inlcudes Heat Index *sensor*
*
* For more information, please visit:
* http://www.mysensors.org/build/humidity
* http://www.mysensors.org/build/TemperatureAndHumidity
*
*/
#define SN "TemperatureAndHumidity"
#define SV "2.2"



// Enable debug prints
#define MY_DEBUG
//#define MY_DEBUG

// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
//#define MY_RS485

#include <SPI.h>
#include <MySensors.h>
#include <DHT.h>

// Set this to the pin you connected the DHT's data pin to
#define DHT_DATA_PIN 3
//Uncomment (and update) if you want to force Node Id
//#define MY_NODE_ID 1

#define MY_BAUD_RATE 38400

// Set this offset if the sensor has a permanent small offset to the real temperatures.
// In Celsius degrees (as measured by the device)
#define SENSOR_TEMP_OFFSET 0
// Uncomment the type of sensor in use:
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)

// Sleep time between sensor updates (in milliseconds)
// Must be >1000ms for DHT22 and >2000ms for DHT11
static const uint64_t UPDATE_INTERVAL = 60000;

// Set this to the pin you connected the DHT's data and power pins to; connect wires in coherent pins
#define DHTDATAPIN 3
#define DHTPOWERPIN 8


// Sleep time between sensor updates (in milliseconds) to add to sensor delay (read from sensor data; tipically: 1s)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: typically

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to correct it.
thank you

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
Expand All @@ -62,95 +74,218 @@ static const uint8_t FORCE_UPDATE_N_READS = 10;

#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
#define CHILD_ID_TEMP_HI 2

// Set this offset if the sensors have permanent small offsets to the real temperatures/humidity.
// In Celsius degrees or moisture percent
#define SENSOR_HUM_OFFSET 0 // used for temperature data and heat index computation
#define SENSOR_TEMP_OFFSET 0 // used for humidity data
#define SENSOR_TEMP_HI_OFFSET 0 // used for heat index data



#include <MySensors.h>
#include <Adafruit_Sensor.h>
#include <DHT_U.h>

DHT_Unified dhtu(DHTDATAPIN, DHTTYPE);
// See guide for details on Adafruit sensor wiring and usage:
// https://learn.adafruit.com/dht/overview

uint32_t delayMS;
float lastTemp;
float lastHum;
uint8_t nNoUpdatesTemp;
uint8_t nNoUpdatesHum;
uint8_t nNoUpdates = FORCE_UPDATE_N_READS; // send data on start-up
bool metric = true;
float temperature;
float humidity;
float temperatureHI;



MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
DHT dht;
MyMessage msgTempHI(CHILD_ID_TEMP_HI, V_TEMP);
Copy link

@mvdw mvdw Jan 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a better name would be "msgHeatIndex", CHILD_ID_HEATINDEX, SENSOR_HEATINDEX_OFFSET

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate your suggestion.
I'm going to change it




float computeHeatIndex(float temperature, float percentHumidity) {
// Based on Adafruit DHT official library (https://github.com/adafruit/DHT-sensor-library/blob/master/DHT.cpp)
// Using both Rothfusz and Steadman's equations
// http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml

float hi;

temperature = temperature + SENSOR_TEMP_OFFSET; //include TEMP_OFFSET in HeatIndex computation too
temperature = 1.8*temperature+32; //convertion to *F

hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094));

if (hi > 79) {
hi = -42.379 +
2.04901523 * temperature +
10.14333127 * percentHumidity +
-0.22475541 * temperature*percentHumidity +
-0.00683783 * pow(temperature, 2) +
-0.05481717 * pow(percentHumidity, 2) +
0.00122874 * pow(temperature, 2) * percentHumidity +
0.00085282 * temperature*pow(percentHumidity, 2) +
-0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);

if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0))
hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);

else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0))
hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
}

hi = (hi-32)/1.8;
return hi; //return Heat Index, in *C
}






void presentation()
{
// Send the sketch version information to the gateway
sendSketchInfo("TemperatureAndHumidity", "1.1");

sendSketchInfo(SN, SV);
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_TEMP, S_TEMP);

present(CHILD_ID_HUM, S_HUM, "Umidity");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "Humidity"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same answer than before:
I'm going to correct it.
thank you

wait(100); //to check: is it needed
present(CHILD_ID_TEMP, S_TEMP, "Temperature");
wait(100); //to check: is it needed
present(CHILD_ID_TEMP_HI, S_TEMP, "Heat Index");
metric = getControllerConfig().isMetric;
}


void setup()
{
dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
}
// Sleep for the time of the minimum sampling period to give the sensor time to power up
// (otherwise, timeout errors might occure for the first reading)
sleep(dht.getMinimumSamplingPeriod());
pinMode(DHTPOWERPIN, OUTPUT);
digitalWrite(DHTPOWERPIN, HIGH);
//Serial.begin(9600);
// Initialize device.
dhtu.begin();


Serial.println("DHTxx Unified Sensor Example");
// Print temperature sensor details.
sensor_t sensor;
dhtu.temperature().getSensor(&sensor);
Serial.println("------------------------------------");
Serial.println("Temperature");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" *C");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" *C");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" *C");
Serial.print ("Min Delay: "); Serial.print(sensor.min_delay/1000); Serial.println(" ms");
Serial.println("------------------------------------");

// Print humidity sensor details.
dhtu.humidity().getSensor(&sensor);
Serial.println("------------------------------------");
Serial.println("Humidity");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println("%");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println("%");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println("%");
Serial.print ("Min Delay: "); Serial.print(sensor.min_delay/1000); Serial.println(" ms");
Serial.println("------------------------------------");
// Set delay between sensor readings based on sensor details.
delayMS = sensor.min_delay / 1000;
}


void loop()
{
// Force reading sensor, so it works also after sleep()
dht.readSensor(true);

// Get temperature from DHT library
float temperature = dht.getTemperature();
if (isnan(temperature)) {
Serial.println("Failed reading temperature from DHT!");
} else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
// Only send temperature if it changed since the last measurement or if we didn't send an update for n times
lastTemp = temperature;

// apply the offset before converting to something different than Celsius degrees
temperature += SENSOR_TEMP_OFFSET;

if (!metric) {
temperature = dht.toFahrenheit(temperature);
}
// Reset no updates counter
nNoUpdatesTemp = 0;
send(msgTemp.set(temperature, 1));




void loop()
{
digitalWrite(DHTPOWERPIN, HIGH);
delay(delayMS);
sensors_event_t event;
// Get temperature event and use its value.
dhtu.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println("Error reading temperature!");
}
else {
temperature = event.temperature;
#ifdef MY_DEBUG
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" *C");
#endif
}

// Get humidity event and use its value.
dhtu.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println("Error reading humidity!");
}
else {
humidity = event.relative_humidity;
#ifdef MY_DEBUG
Serial.print("T: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println("%");
#endif
} else {
// Increase no update counter if the temperature stayed the same
nNoUpdatesTemp++;
}

// Get humidity from DHT library
float humidity = dht.getHumidity();
if (isnan(humidity)) {
Serial.println("Failed reading humidity from DHT");
} else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
// Only send humidity if it changed since the last measurement or if we didn't send an update for n times
if (fabs(humidity - lastHum)>=0.05 || fabs(temperature - lastTemp)>=0.05 || nNoUpdates >= FORCE_UPDATE_N_READS) {
lastTemp = temperature;
lastHum = humidity;
// Reset no updates counter
nNoUpdatesHum = 0;
send(msgHum.set(humidity, 1));
temperatureHI = computeHeatIndex(temperature,humidity); //computes Heat Index, in *C
nNoUpdates = 0; // Reset no updates counter
#ifdef MY_DEBUG
Serial.print("Heat Index: ");
Serial.print(temperatureHI);
Serial.println(" *C");
#endif

if (!metric) {
temperature = 1.8*temperature+32; //convertion to *F
temperatureHI = 1.8*temperatureHI+32; //convertion to *F
}

#ifdef MY_DEBUG
Serial.print("H: ");
Serial.println(humidity);
#endif
} else {
// Increase no update counter if the humidity stayed the same
nNoUpdatesHum++;
wait(100);
Serial.print("Sending temperature: ");
Serial.print(temperature);
#endif
send(msgTemp.set(temperature + SENSOR_TEMP_OFFSET, 2));

#ifdef MY_DEBUG
wait(100);
Serial.print("Sending humidity: ");
Serial.print(humidity);
#endif
send(msgHum.set(humidity + SENSOR_HUM_OFFSET, 2));

#ifdef MY_DEBUG
wait(100);
Serial.print("Sending HeatIndex: ");
Serial.print(temperatureHI);
#endif
send(msgTempHI.set(temperatureHI + SENSOR_TEMP_HI_OFFSET, 2));

}

nNoUpdates++;

// Sleep for a while to save energy
digitalWrite(DHTPOWERPIN, LOW);
wait(300); // waiting for potential presentation requests
sleep(UPDATE_INTERVAL);

}