DHT12: un sensore i2c di umidità e temperatura veramente economico
Mi piacciono i sensori che possono essere usati con 2 fili (protocollo i2c), ma adoro quello economici.
Questa è una libreria Arduino ed esp8266 per la serie dei sensori di temperatura/umidità DHT12 a bassissimo costo (meno di 1 $) che funzionano con connessione i2c o unidirezionale.
Qui trovi il dispositivo DHT12 AliExpressMolto utile se si desidera utilizzare un esp01 (se si utilizza la seriale si hanno solo 2 pin) per leggere umidità e temperatura e visualizzarlo il tutto su un LCD i2c.
Ho letto in alcuni articoli che a volte è necessario calibrare il sensore, ma dai miei test ottengo un valore molto simile ai DHT22. Se incontri questo problema, apri una issue su github e provvederò all’implementazione.
Come funziona il protocollo I2c
Il protocollo I2C funziona con due fili, l’SDA (dati) e SCL (clock).
Questi pin sono open-drain, e sono in pull-up con delle resistenze.
Di solito c’è un master e uno o più slave sulla linea, anche se possono esserci più master, ma ne parleremo in altra occasione.
Entrambi i master e gli slave possono trasmettere o ricevere dati, pertanto un dispositivo può trovarsi in uno di questi quattro stati: trasmissione master, ricezione master, trasmissione slave, ricezione slave.
Libreria
Scrivo una libreria perché non riesco a trovare una libreria che supporti correttamente one-wire e i2c. Puoi trovare la mia libreria qui .
Download
Fai clic sul pulsante DOWNLOADS nell’angolo in alto a destra, rinomina la cartella non compressa in DHT12.
Verificare che la cartella DHT contenga DHT12.cpp e DHT12.h.
Inserisci la cartella della libreria DHT tua cartella delle librerie.
Potrebbe essere necessario creare la sottocartella librerie se è la tua prima libreria.
Riavvia l’IDE.
Comportamento
Questo libray tenta di emulare il comportamento della più famosa libreria DHT standard (da cui ho copiato anche del codice) e aggiungo il codice per gestire i2c con lo stesso proposito.
I metodi sono gli stessi della libreria DHT, con alcune aggiunte come la funzione dew point (punto di rugiada).
Uso I2c
Per utilizzare con protoccollo i2c (indirizzo standard e pin SDA SDL standard) il costruttore è:
DHT12 dht12;
(È possibile ridefinire con il contructor specificato per esp8266, necessario per ESP-01). o
DHT12 dht12(uint8_t addressOrPin)
addressOrPin -> address
per cambiare indirizzo.
Usare con un secondo canale i2c [update 28/04/2019]
Per poterlo utilizzare con un secondo canale i2c, come per gli esp32 ho aggiunto delle variazioni ai costruttori che si attivano nel caso di un environment esp32.
TwoWire I2Ctwo = TwoWire(1);
DHT12 dht12(&I2Ctwo);
//DHT12 dht12(&I2Ctwo, 21,22);
//DHT12 dht12(&I2Ctwo, 0x5C);
//DHT12 dht12(&I2Ctwo, 21,22,0x5C);
Come si può vedere si possono ritrovare tutti i parametri standard, ma in aggiunta trovate il parametro che permette di passare l’istanza del Wire specifica.
Utilizzo ad un filo
Per usare il sensore con un filo:
DHT12 dht12(uint8_t addressOrPin, true)
addressOrPin -> pin
il valore booleano è la selezione della modalità oneWire o i2c.
Lettura implicita
Puoi usarlo con il modo “implicito”, “simple read” o “fullread”:
implicito, la prima read fa una vera lettura del sensore, le altre read hanno un tempo di debuonce di 2 secondi perciò si limiteranno a mostrare i valori della prima lettura
// Reading temperature or humidity takes about 250 milliseconds!
// Read temperature as Celsius (the default)
float t12 = dht12.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f12 = dht12.readTemperature(true);
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h12 = dht12.readHumidity();
bool dht12Read = true;
// Check if any reads failed and exit early (to try again).
if (isnan(h12) || isnan(t12) || isnan(f12)) {
Serial.println("Failed to read from DHT12 sensor!");
dht12Read = false;
}
if (dht12Read){
// Compute heat index in Fahrenheit (the default)
float hif12 = dht12.computeHeatIndex(f12, h12);
// Compute heat index in Celsius (isFahreheit = false)
float hic12 = dht12.computeHeatIndex(t12, h12, false);
// Compute dew point in Fahrenheit (the default)
float dpf12 = dht12.dewPoint(f12, h12);
// Compute dew point in Celsius (isFahreheit = false)
float dpc12 = dht12.dewPoint(t12, h12, false);
Serial.print("DHT12=> Humidity: ");
Serial.print(h12);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t12);
Serial.print(" *C ");
Serial.print(f12);
Serial.print(" *F\t");
Serial.print(" Heat index: ");
Serial.print(hic12);
Serial.print(" *C ");
Serial.print(hif12);
Serial.print(" *F");
Serial.print(" Dew point: ");
Serial.print(dpc12);
Serial.print(" *C ");
Serial.print(dpf12);
Serial.println(" *F");
}
Simple read
Fa una semplice lettura che ritorna un booleano con l’esito della lettura verso il sensore.
// The read of sensor have 2secs of elapsed time, unless you pass force parameter
bool chk = dht12.read(); // true read is ok, false read problem
// Read temperature as Celsius (the default)
float t12 = dht12.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f12 = dht12.readTemperature(true);
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h12 = dht12.readHumidity();
// Compute heat index in Fahrenheit (the default)
float hif12 = dht12.computeHeatIndex(f12, h12);
// Compute heat index in Celsius (isFahreheit = false)
float hic12 = dht12.computeHeatIndex(t12, h12, false);
// Compute dew point in Fahrenheit (the default)
float dpf12 = dht12.dewPoint(f12, h12);
// Compute dew point in Celsius (isFahreheit = false)
float dpc12 = dht12.dewPoint(t12, h12, false);
Full Read
Fa una lettura più complessa così da ottenere uno stato specificato su cui poter lavorare nel caso di errore.
// The read of sensor have 2secs of elapsed time, unless you pass force parameter
DHT12::ReadStatus chk = dht12.readStatus();
Serial.print(F("\nRead sensor: "));
switch (chk) {
case DHT12::OK:
Serial.println(F("OK"));
break;
case DHT12::ERROR_CHECKSUM:
Serial.println(F("Checksum error"));
break;
case DHT12::ERROR_TIMEOUT:
Serial.println(F("Timeout error"));
break;
case DHT12::ERROR_TIMEOUT_LOW:
Serial.println(F("Timeout error on low signal, try put high pullup resistance"));
break;
case DHT12::ERROR_TIMEOUT_HIGH:
Serial.println(F("Timeout error on low signal, try put low pullup resistance"));
break;
case DHT12::ERROR_CONNECT:
Serial.println(F("Connect error"));
break;
case DHT12::ERROR_ACK_L:
Serial.println(F("AckL error"));
break;
case DHT12::ERROR_ACK_H:
Serial.println(F("AckH error"));
break;
case DHT12::ERROR_UNKNOWN:
Serial.println(F("Unknown error DETECTED"));
break;
case DHT12::NONE:
Serial.println(F("No result"));
break;
default:
Serial.println(F("Unknown error"));
break;
}
// Read temperature as Celsius (the default)
float t12 = dht12.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f12 = dht12.readTemperature(true);
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h12 = dht12.readHumidity();
bool dht12Read = true;
// Check if any reads failed and exit early (to try again).
if (isnan(h12) || isnan(t12) || isnan(f12)) {
Serial.println("Failed to read from DHT12 sensor!");
dht12Read = false;
}
if (dht12Read){
// Compute heat index in Fahrenheit (the default)
float hif12 = dht12.computeHeatIndex(f12, h12);
// Compute heat index in Celsius (isFahreheit = false)
float hic12 = dht12.computeHeatIndex(t12, h12, false);
// Compute dew point in Fahrenheit (the default)
float dpf12 = dht12.dewPoint(f12, h12);
// Compute dew point in Celsius (isFahreheit = false)
float dpc12 = dht12.dewPoint(t12, h12, false);
Serial.print("DHT12=> Humidity: ");
Serial.print(h12);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t12);
Serial.print(" *C ");
Serial.print(f12);
Serial.print(" *F\t");
Serial.print(" Heat index: ");
Serial.print(hic12);
Serial.print(" *C ");
Serial.print(hif12);
Serial.print(" *F");
Serial.print(" Dew point: ");
Serial.print(dpc12);
Serial.print(" *C ");
Serial.print(dpf12);
Serial.println(" *F");
}
Schema di collegamento
Ho disegnato i vari schemi di connessione, è importante usare il corretto valore della resistenza di pull-up per evitare problemi di vario genere.
Grazie a Bobadas, dplasa e adafruit, per aver condiviso il codice in github.