Determinarea temperaturii și umidității mediului ambiant folosind senzori digitali de tip DHT11/DHT22 și o placă de dezvoltare.
DHT11 și DHT22 sunt senzori integrați de temperatură și umiditate. Conțin un termistor, un transductor capacitiv și un microcontroller (MCU) care realizează conversia analog - digitală și trimite printr-un protocol serial valoarea parametrilor măsurați. Protocolul este unul specific, dar ușor de implementat în software. Cei doi senzori sunt similari și au aceeași pini. Vom vedea în acest articol cum putem determina acești senzori să trimită date către placa de dezvoltare și cum putem prelucra aceste date.
Totuși, DHT22 (cunoscut ca și AM2302) este versiunea mai performantă. Ambele versiuni se alimentează la tensiuni cuprinse între 3,3 și 5 V, deci nu sunt probleme de conectare la plăcile de dezvoltare uzuale. Spre deosebire de DHT11, care are o acuratețe de 5% RH pentru umiditate, respectiv 2 grade Celsius pentru temperatură, AM2302 este mai performant, cu o acuratețe de 2% RH, respectiv 0,5 grade Celsius. Dezavantajul acestuia din urmă este că citirea parametrilor se poate face o dată la 2 secunde (este mai lent), pe când DHT11 poate fi citit la fiecare secundă. De asemenea, prețul lui DHT22 este mai mare.
Module cu senzor DHT11 (stânga) și AM2302/DHT22 (dreapta)
Acești senzori au 4 pini: unul pentru alimentare, unul pentru semnalul digital și 2 de masă. Pentru conectarea în mod corect a pinului de date la MCU, este necesar un rezistor de 1 kilo-ohm (la AM2302) sau 5,1 kilo-ohmi (la DHT11) conectat între acest pin și alimentare (pull-up). Chiar dacă interfațarea cu un MCU este destul de ușoară, în comerț se găsesc plăcuțe cu acești senzori. Acestea conțin rezistorul menționat, dar și un condensator de filtrare între masă și alimentare. Cele două componente se află pe fața superioară a plăcii de circuit a senzorului AM2302, după cum vezi în imaginea de mai sus. Ele sunt prezente și pe placa cu DHT11, dar pe fața inferioară.
Module cu senzori DHT11 și DHT22 (și schema lor)
Voi conecta ambele module la o placă de dezvoltare Arduino cu ajutorul căreia voi genera semnalul de solicitare date de la senzori. Transmisia de pe pinul de date va fi înregistrată cu un analizor logic. Pinii de date de la senzori pot fi conectați la orice pin digital al plăcii de dezvoltare. Starea implicită a pinului de date este intrare, logic 1 (datorită rezistorului de pull-up). Pentru a solicita valorile parametrilor măsurați, MCU-ul preia controlul liniei setând pinul ca ieșire. Apoi, timp de minimum 18 milisecunde pentru DHT11, respectiv 1 milisecunde pentru AM2302, starea pinului trebuie să fie logic 0. MCU-ul trebuie să lase apoi pinul liber (setat ca intrare). Datorită rezistorului ce trage linia spre VCC, starea pinului va trece la logic 1. De acum înainte, senzorul preia controlul liniei, și setează inițial pinul logic 0.
Solicitarea de date de la senzori (adaptare după fișele tehnice)
Deci, după generarea semnalului START, lăsăm pinul liber (intrare) astfel încât rezistorul să îl aducă la nivelul VCC, iar senzorul să îl poată controla. Dacă folosești un MCU care include rezistoare pull-up pe pini, nu activa aceste rezistoare când pinul este setat ca intrare. Senzorul are deja un rezistor pull-up, cu o valoare specifică. În Arduino IDE, pinul setat corect este INPUT
, nu INPUT_PULLUP
. Generarea semnalului START se poate face astfel:
void readSensor(byte sensorPin) { pinMode(sensorPin, OUTPUT); // Arduino preia controlul liniei digitalWrite(sensorPin, LOW); // si il seteaza logic 0 if (sensorPin == DHT11_PIN) delay(20); // daca senzorul este DHT11, asteapta 20 ms (min. 18 ms) else if (sensorPin = DHT22_PIN) delay(2); // daca senzorul este DHT22, asteapta 2 ms (min. 1 ms) pinMode(sensorPin, INPUT); // lasa pinul liber }
Am conectat senzorii la o placă de dezvoltare compatibilă cu Arduino Nano. Firele de date de la senzori vor fi de asemenea conectate la analizorul logic.
Senzorii conectați la placa de dezvoltare
Înregistrarea liniilor de semnal în PulseView demonstrează că senzorii funcționează corespunzător, începând să trimită date imediat după comanda START. După ce am lăsat pinul liber (modificat în INPUT
), DHT11 a așteptat doar 14 microsecunde înainte să tragă nivelul liniei la masă, chiar dacă în fișa tehnică se spune că răspunsul de la senzor apare după 20...40 microsecunde. AM2302 se încadrează în aceste specificații, așteptând 23 microsecunde înainte să genereze răspunsul.
Vizualizarea protocolului senzorilor în PulseView
Durata semnalului START este foarte mare în comparație cu durata întregii transmisii de date, de aceea semnalul nu poate fi prins în întregime pe graficul de mai sus. Imediat după START urmează R (răspunsul senzorului), apoi transmisia temperaturii și a umidității. Pe lângă vizualizarea semnalului, aplicația PulseView permite decodarea mai multor protocoale uzuale, printre care și acesta folosit de senzorii DHT. Deși amplasați unul lângă altul, putem observa mici diferențe între citirile efectuate.
După cum se vede și după cum spune fișa tehnică, senzorii trimit 40 de biți (5 octeți) după răspuns. Menținerea stării liniei logic 0 timp de 50 us, urmată de logic 1 timp de 26...28 us semnifică bitul 0. Dacă după 50 us de logic 0, linia rămâne logic 1 timp de 70 us, senzorul a trimis bitul 1. După terminarea transmisiei, senzorul lasă linia liberă (își setează pinul de date ca intrare) și intră în modul standby. După o perioadă de 1 secundă pentru DHT11, respectiv 2 secunde pentru AM2302, MCU-ul poate genera un nou semnal START și senzorul va răspunde trimițând temperatura și umiditatea. Fiecare parametru ocupă câte 16 biți (2 octeți). Un octet suplimentar (8 biți) este trimis la sfârșit și semnifică o sumă de control.
Să reluăm programarea plăcii de dezvoltare. După ce am setat pinul ca intrare, așteptăm ca senzorul să îl tragă spre masă timp de 80 us. Apoi, îl va ține la VCC tot 80 us. După această secvență urmează biții de date.
delayMicroseconds(50); // se asteapta suficient ca pinul sa fie logic 0 while (digitalRead(sensorPin) == LOW) ; // nu face nimic cat pinul este 0 // urmeaza setarea pinului 1 de catre senzor (parte a raspunsului) while (digitalRead(sensorPin) == HIGH) ; // asteapta terminarea raspunsului // incepe transmiterea bitilor for (byte i = 0; i < 40; i++) { while (digitalRead(sensorPin) == LOW) ; // nu intereseaza starea 0 a pinului unsigned long t = micros(); // memoreaza timpul actual while (digitalRead(sensorPin) == HIGH) ; // asteapta finalizarea trimiterii bitului if ((micros() - t) > 40) // daca pinul a stat logic 1 mai mult de 40 us dht_data[i / 5] |= (1 << (7 - (i % 8))); // bitul este 1 si este stocat }
Cam așa ar putea arăta un fragment de cod simplu care stochează cei 40 de biți într-un vector cu 5 octeți. Codul este mult simplificat și nu se recomandă utilizarea lui. În caz de erori de transmisie, nu există verificări ale duratelor impulsurilor, iar MCU-ul poate intra în bucle ale căror condiții de întrerupere nu vor fi îndeplinite (numeroasele while()
care depind de modificarea stării pinului). Desigur există și alte abordări ale acestei situații. Protocolul poate fi decodat prin înregistrarea perioadelor tranzițiilor pinului de date folosind întreruperi.
Popularitatea Arduino este foarte mare. În prezent vei găsi biblioteci C pentru aproape toate modulele, shield-urile și senzorii pe care îi poți conecta la Arduino. Pentru acest caz, putem folosi bibliotecile oferite de Adafruit: Adafruit Unified Sensor și DHT sensor library. Le poți instala din Arduino IDE, accesând Library Manager Ctrl+Shift+I. Poți obține astfel datele de la senzori în mai puțin de 40 de linii de cod:
#include "DHT.h" #define DHT11_PIN 2 #define DHT22_PIN 3 DHT senzor1(DHT11_PIN, DHT11); DHT senzor2(DHT22_PIN, DHT22); void setup() { Serial.begin(9600); Serial.println("Test senzori DHT\n"); senzor1.begin(); senzor2.begin(); delay(2000); } void loop() { float t, h; t = senzor1.readTemperature(); h = senzor1.readHumidity(); Serial.print("DHT11 : T = "); Serial.print(t, 1); Serial.print(F("°C. H = ")); Serial.print(h, 0); Serial.println("%"); t = senzor2.readTemperature(); h = senzor2.readHumidity(); Serial.print("AM2302: T = "); Serial.print(t, 1); Serial.print(F("°C. H = ")); Serial.print(h, 0); Serial.println("%\n"); delay(2000); }
Mai departe poți folosi senzorii pentru a monitoriza mediul. Știind temperatura și umiditatea, poți calcula indicele de confort termic. Poți adăuga alți senzori și construi o stație meteo.
Resurse
- DHT11 - module cu acest senzor; datasheet.
- DHT22/AM2302 - module cu acest senzor; datasheet.
Niciun comentariu :
Trimiteți un comentariu
Vă recomandăm să citiți regulamentul comentariilor înainte de a scrie un comentariu.