Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

Измерване на температура и влажност чрез Arduino и DHT22

DHT22 е сензор за измерване на температура и относителна влажност. Захранва се с напрежение от 3.3 до 6V и е готов за работа една секунда след захранването му.

Комуникацията със сензора се осъществява по One Wire интерфейс и започва след подаване на начален сигнал от микроконтролер. Сензорът потвърждава получаването му и отговаря с четири байта данни за относителната влажността и температурата и един контролен байт.

Началният сигнал микроконтролерът подава като свали на LOW (ниско ниво) линията за комуникация и я задръжи така за повече от 1 милисекунда. За да получи отговор от сензора, трябва да върне линията на HIGH (високо ниво) и да изчака от 20 до 40 микросекунди. Сензорът ще отговори, като я свали на LOW за 80 микросекунди и я върне пак на HIGH за още 80 микросекунди.

След потвърждаване на началния сигнал, сензорът започва да предава данните бит по бит. Всеки бит сигнализира, като сваля линията на LOW за 50микросекинди. След изтичането им я връща на HIGH и я задържа 26-28 микросекунди за 0 или 70 микросекунди за 1.

Първите два байта са съответно за цялата и дробната част на относителната влажност, а следващите два байта са за цялата и дробната част на температурата. Последният байт е контролен и съдържа последните 8 бита от сумата на четирите байта.

Пример

Даденият по-долу код комуникира със сензора по един проводник. Получените стойности се сумират и се сравняват с контролния байт. Ако проверката покаже, че данните са получени коректно, стойностите се извеждат в Serial Monitor.

Сензорът се свързва към Arduino, като първият пин от ляво надясно е към 5V, а последният към GND. Вторият пин е за комуникацията с микроконтролер и се свързва към пин 7 на платката. (Добре е да се добави един (pull-up) резистор от 1K между вторият пин и 5V)

Кодът, който трябва да се зареди на Arduino за да комуникира със сензора е следният:

/*

 Описание:
 * Осъществява комуникация с DHT22 по една линия
 * Чете данни от сензора и проверява коректни ли са
 * Превръща данните в стойности за температура 
   и влажност и ги извежда в Serial Monitor
    ___
   /_0_\     
  |     |    
  |DHT22|     Свързване:
  |_____|     1 -> 5V
  | | | |     2 -> pin7
  | | | |     4 -> GND
  1 2 3 4    

 * Tihomir Trifonov (08-2011)
 * email:tisho@inbox.com

 * с подкрепата на Robotev.com

*/

byte dht_dpin = 7; // пин за комуникация със сензора
byte dht_dat[5];   // масив за данните от сензора

void setup(){ // начални инициализации

  InitDHT(); // инициализира сензора
  Serial.begin(9600);// стартира сериийна комуникация
  Serial.println("Humidity and temperature\n\n");
  delay(1000); // изчаква 1 секунда
}

void loop(){ // програмен цикъл

  StartDHT22(); // започва комуникация със сенозра

  for (byte i=0; i<5; i++)   // повтаря се 5 пъти
    dht_dat[i] = readByte(); // извиква фунцкията за четене на байт от сензора

   //// проверява правилно си са получени данните
   byte checksum = dht_dat[0] + dht_dat[1] + dht_dat[2 ] + dht_dat[3];	 
   if(dht_dat[4] == checksum) { // ако данните са коректни

   //// намира цялата и дробната част на относителната влажност
        int HighByte = dht_dat[0]; // първи байт
        int LowByte = dht_dat[1];  // втори байт
        int TReading = (HighByte << 8) + LowByte; // обединява байтовете
        int Whole = TReading / 10; // намира цялата част
        int Fract = TReading % 10; // намира дробната част

    //// извежда стойността в Serial Monitor
	Serial.print("humdity = ");
	Serial.print(Whole); // цяла част
	Serial.print(".");   // десетична запетая
	Serial.print(Fract); // дробна част
	Serial.print("%  "); // мерна единица  

    //// намира цялата и дробната част на температурата
        HighByte = dht_dat[2];  // трети байт
        LowByte = dht_dat[3];   // четвърти байт
        TReading = (HighByte << 8) + LowByte; // обединява байтовете
        Whole = TReading / 10;  // намира цялата част
        Fract = TReading % 10;  // намира дробната част

    //// извежда стойността в Serial Monitor
        Serial.print("temperature = ");
        int SignBit = TReading & 0x8000; // проверява знака на температурата
        if (SignBit)           // ако е отрицателна
           Serial.print("-");  // слага минус пред стойността
	Serial.print(Whole);   // цяла част
	Serial.print(".");     // десетична запетая
	Serial.print(Fract);   // дробна част
	Serial.println("C  "); // мерна единица  
   }

  delay(800); // закъснение, необходимо за да се продотврати прегряване 
}

/////////////////////// инициализира сензозра

void InitDHT(){

  pinMode(dht_dpin,OUTPUT); // пина за комуникация става изходен
  digitalWrite(dht_dpin,HIGH); // вдига линията на ниво HIGH
}

/////////////////////// започва комуникация със сензора

void StartDHT22(){

//// изпраща начален сигнал  
  pinMode(dht_dpin,OUTPUT);    // пина за комуникация става изходен
  digitalWrite(dht_dpin,LOW);  // сваля линията на ниво LOW и
  delay(1);                    // изчаква 1 милисекунда
  digitalWrite(dht_dpin,HIGH); // вдига линията на HIGH и
  delayMicroseconds(40);       // изчаква 40 микросекунди

//// изчаква отговор от сензора  
  pinMode(dht_dpin,INPUT);             // пина за комуникация става входен
  while(digitalRead(dht_dpin) == LOW); // изчаква линията да стане LOW
  while(digitalRead(dht_dpin) == HIGH);// изчаква да се върне на HIGH
}

//////////////////////// прочита един байт от сензора

byte readByte(){

  byte result = 0; // съхранява стойността на байта

  for(byte i=0; i< 8; i++){ // прочита 8 бита от линията

      while(digitalRead(dht_dpin) == LOW); // изчаква 50us от началото на бита
      delayMicroseconds(45);               // изчаква още 45us
      if (digitalRead(dht_dpin) == HIGH)   // проверява линията дали е HIGH
 	  result |= (1 << (7 - i));        // счита байта за 1 и го добавя на
                                           // съответната позиция в байта                
      while (digitalRead(dht_dpin)==HIGH); // изчаква сигнал за нов бит
    }

  return result; // връща стойността на байта
}