Site icon Renzo Mischianti

DHT12: un sensore i2c di umidità e temperatura veramente economico

Spread the love

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 AliExpress

Molto 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.


Arduino connessione a un filo
Arduino connessione con protocollo i2c
esp8266 connessione con protocollo i2c
esp32 connessione con protocollo i2c

Link utili


Spread the love
Exit mobile version