Files
nixie-clock/firmware/uniclock/ESP32_UniClock2/DHT_temp.ino
T
mangavalkandClaude Opus 5.5 b347f1c63f Import ESP_UniClock (upstream 1189810)
Vendored from https://github.com/gpeter62/ESP_UniClock: the sketch
source, the web UI and the libraries the ESP8266 build needs, unpacked
from the bundled zips. Adds a PlatformIO project for the ESP-12. The
source is unchanged; local changes follow as separate commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:48:04 +01:00

133 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