132 lines
7.2 KiB
Arduino
132 lines
7.2 KiB
Arduino
// =================================================================================================
|
|||
|
|
// DHT_temp.ino - DHT11 / DHT22 (AM2302/AM2321) / DHT21 combined temperature+humidity sensor driver
|
||
|
|
// -------------------------------------------------------------------------------------------------
|
||
|
|
// Single-wire (not 1-Wire protocol, just one signal wire) sensor read via the Adafruit DHT sensor
|
||
|
|
// library (libraries/DHT_sensor_library.zip), on pin TEMP_DHT_PIN with sensor type DHTTYPE.
|
||
|
|
// Enabled per-clock via USE_DHT_TEMP in clocks.h (pin: TEMP_DHT_PIN, type: DHTTYPE, default DHT22).
|
||
|
|
// Used (as of this writing) by CLOCK_18, CLOCK_21, CLOCK_22, CLOCK_23A, CLOCK_23B, CLOCK_32, CLOCK_50
|
||
|
|
// and CLOCK_99 - see clocks.h for the exact list. Unlike dallas_temp.ino, this driver only ever
|
||
|
|
// supports a single physical sensor (one temperature + one humidity reading).
|
||
|
|
//
|
||
|
|
// DHT sensors are slow and must not be polled too often (Adafruit recommends >=2s between reads,
|
||
|
|
// otherwise you get stale or garbage data back) - getDHTemp() below enforces its own minimum gap
|
||
|
|
// between reads independent of the DHT library (which does not enforce this itself).
|
||
|
|
// =================================================================================================
|
||
|
|
#ifdef USE_DHT_TEMP
|
||
|
|
|
||
|
|
// REQUIRES the following Arduino libraries:
|
||
|
|
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
|
||
|
|
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor
|
||
|
|
|
||
|
|
#include "DHT.h"
|
||
|
|
// TEMP_DHT_PIN is used to connect the sensor
|
||
|
|
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
|
||
|
|
// Pin 15 can work but DHT must be disconnected during program upload.
|
||
|
|
|
||
|
|
// Uncomment whatever type you're using!
|
||
|
|
//#define DHTTYPE DHT11 // DHT 11
|
||
|
|
#ifndef DHTTYPE
|
||
|
|
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //default DHT type
|
||
|
|
#endif
|
||
|
|
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
|
||
|
|
|
||
|
|
// Connect pin 1 (on the left) of the sensor to +5V
|
||
|
|
// NOTE: If using a board with 3.3V logic like ESP8266 or ESP32 connect pin 1
|
||
|
|
// to 3.3V instead of 5V!
|
||
|
|
// Connect pin 2 of the sensor to whatever your DHTPIN is
|
||
|
|
// Connect pin 4 (on the right) of the sensor to GROUND
|
||
|
|
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
|
||
|
|
|
||
|
|
|
||
|
|
DHT dht(TEMP_DHT_PIN, DHTTYPE);
|
||
|
|
int DHTtempPtr = -1; // index into the shared temperature[] array reserved for this sensor; -1 = "no sensor found / not set up"
|
||
|
|
int DHThumidPtr = -1; // index into the shared humid[] array reserved for this sensor; -1 = "no sensor found / not set up"
|
||
|
|
|
||
|
|
// Probes for a DHT sensor at boot. Up to 5 attempts, 1 second apart (DHT sensors need time between
|
||
|
|
// reads to settle - see getDHTemp() below for the steady-state rate limit), stopping as soon as one
|
||
|
|
// attempt returns a valid (non-NaN) temperature. Only DHTtempPtr/DHThumidPtr are left at -1 (their
|
||
|
|
// initialized value) if no sensor ever responds, which is how getDHTemp() knows to do nothing later.
|
||
|
|
void setupDHTemp() {
|
||
|
|
float tempTMP, humidTMP;
|
||
|
|
regPin(TEMP_DHT_PIN,"TEMP_DHT_PIN");
|
||
|
|
dht.begin();
|
||
|
|
int i= 0;
|
||
|
|
while (i<5) {
|
||
|
|
humidTMP = dht.readHumidity();
|
||
|
|
tempTMP = dht.readTemperature();
|
||
|
|
DPRINT("DHT Test:"); DPRINT(tempTMP); DPRINT("/"); DPRINTLN(humidTMP);
|
||
|
|
i++;
|
||
|
|
if (!isnan(tempTMP)) // note: only the temperature reading is checked here, humidity's NaN state is not verified
|
||
|
|
break;
|
||
|
|
delay(1000);
|
||
|
|
}
|
||
|
|
if (isnan(tempTMP)) {
|
||
|
|
DPRINT("No DHTxx sensor found on GPIO"); DPRINTLN(TEMP_DHT_PIN);
|
||
|
|
return; // DHTtempPtr/DHThumidPtr stay -1 and useTemp/useHumid are not incremented - sensor is effectively disabled
|
||
|
|
}
|
||
|
|
DHTtempPtr = useTemp; //remember my ID-s
|
||
|
|
DHThumidPtr = useHumid;
|
||
|
|
useTemp++; //increase the number of sensors
|
||
|
|
useHumid++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Called every ~200ms from timeProgram(), AND once directly from setup() right after pin init (see
|
||
|
|
// ESP32_UniClock2.ino) to get an initial reading before the first display refresh.
|
||
|
|
// Unlike the DS18B20 driver, the DHT library's readTemperature()/readHumidity() calls themselves
|
||
|
|
// block for ~250ms (bit-banged single-wire protocol, no async/non-blocking mode available) - there is
|
||
|
|
// no separate request/poll split here, it's a straightforward "gate how often we call it" scheme instead.
|
||
|
|
void getDHTemp() {
|
||
|
|
static unsigned long lastRun = 0;
|
||
|
|
float tempTMP, humidTMP;
|
||
|
|
|
||
|
|
if (EEPROMsaving) return;
|
||
|
|
if (DHTtempPtr<0) return; //no sensor
|
||
|
|
// Rate limiting: DHT11/DHT22 sensors must not be read faster than roughly once every 2 seconds, or
|
||
|
|
// they return stale/garbage data - readings are gated to once per minute, at the exact second
|
||
|
|
// prm.tempStart (the same "start of temperature display window" second used to schedule the Dallas
|
||
|
|
// driver's request), which is always >=2.5s apart in practice for any sane tempStart. The 2500ms
|
||
|
|
// millis()-based check below is really just a safety net (e.g. against `second()` briefly matching
|
||
|
|
// more than once, or the caller re-entering the same second) - the schedule itself already respects
|
||
|
|
// the sensor's minimum read interval.
|
||
|
|
//if (((millis()-lastRun)<2500) || (second()!=prm.tempStart)) return;
|
||
|
|
// `&& (lastRun !=0)` makes the very first call (from setup(), before lastRun has ever been set)
|
||
|
|
// bypass both the 2.5s and the second()==tempStart gating, so a reading is taken immediately at boot
|
||
|
|
// instead of waiting for the clock to reach prm.tempStart.
|
||
|
|
if ((((millis()-lastRun)<2500) || (second()!=prm.tempStart)) && (lastRun !=0)) return;
|
||
|
|
lastRun = millis();
|
||
|
|
|
||
|
|
// Reading temperature or humidity takes about 250 milliseconds!
|
||
|
|
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
|
||
|
|
humidTMP = round1(dht.readHumidity());
|
||
|
|
// Range check doubles as the NaN/error guard: a NaN humidity fails both comparisons (NaN vs any value
|
||
|
|
// is always false in C/C++), so a failed read simply leaves humid[DHThumidPtr] holding its previous value.
|
||
|
|
if ((humidTMP>0) && (humidTMP<=100)) humid[DHThumidPtr] = humidTMP;
|
||
|
|
tempTMP = round1(dht.readTemperature()); // Read temperature as Celsius (the default)
|
||
|
|
// Same implicit-NaN-guard trick as above: NaN<99 is false, so a failed read is silently skipped and
|
||
|
|
// temperature[DHTtempPtr] keeps its last good value rather than being overwritten with garbage.
|
||
|
|
if (tempTMP<99) temperature[DHTtempPtr] = tempTMP;
|
||
|
|
|
||
|
|
// Read temperature as Fahrenheit (isFahrenheit = true)
|
||
|
|
//float f = dht.readTemperature(true); Compute heat index in Fahrenheit (the default)
|
||
|
|
//float hif = dht.computeHeatIndex(f, h);
|
||
|
|
|
||
|
|
//float hic = dht.computeHeatIndex(t, h, false); // Compute heat index in Celsius (isFahreheit = false)
|
||
|
|
|
||
|
|
// NOTE: this isnan() check runs AFTER the assignments above have already decided (via the range
|
||
|
|
// checks) whether to update temperature[]/humid[] - by this point the display has already been
|
||
|
|
// re-enabled too. So this block is purely diagnostic logging on the raw (pre-round1) values, it does
|
||
|
|
// not itself prevent a bad reading from being used (that already happened, or didn't, above).
|
||
|
|
if (isnan(humidTMP) || isnan(tempTMP)) { // Check if any reads failed and exit early (to try again).
|
||
|
|
DPRINTLN("DHT sensor reading error!");
|
||
|
|
//temperature[DHTtempPtr] = 99.9f;
|
||
|
|
//humid[DHThumidPtr] = 0;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
DPRINT("DHTxx Temperature:"); DPRINT(temperature[DHTtempPtr]); DPRINT("C Humidity:"); DPRINT(humid[DHThumidPtr]); DPRINTLN(" %");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
void setupDHTemp() {}
|
||
|
|
void getDHTemp() {}
|
||
|
|
#endif
|