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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *