Подключение датчика температуры и влажности DHT11 к микроконтроллеру Atmega8.

В данном уроке мы подключим датчик DHT11 к микроконтроллеру Atmega8 и выведем его данные на экран.

Датчик DHT11 имеет следующий вид:

Краткий алгоритм работы датчика:

  1. Микроконтроллер подаёт стартовый сигнал — прижимает шину к земле на 18-20 мс;
  2. После чего микроконтроллер отпускает линию и смотрит за уровнем на ней, около 20-40 мкс;
  3. Датчик, увидев сигнал ждет  пока уровень снова станет высоким, и сам прижимает шину к земле на 80 мкс, за это время датчик  измеряет и преобразует значение результатов;
  4. После датчик отпускает линию на 80 мкс, говоря микроконтроллеру, что он готов отправить данные;
  5. После он отправляет 40 бит данных. Перед отправкой каждого бита, датчик прижимает шину к земле на 50 мкс, далее он отпускает шину на 26-28 мкс для «0» или 70 мкс для «1»;
  6. По завершении связи к линии подключается  подтягивающий резистор и датчик переходит в состояние ожидания.

Формат данных:

Данные от датчика передаются в виде посылки, состоящих из 40 бит данных: 

первые два байта влажность, следующие два температура и байт четности.

5 байт из которых первых два влажность, следующие 2 температура и байт четности:

  • 1-й байт: относительная влажность — целая часть в %;
  • 2-й байт: десятая часть относительной влажности в % (в датчике DHT11 записаны 0);
  • 3-й байт: целая часть температуры в °C;
  • 4-й байт: десятая часть температуры в °C (в датчике DHT11 записаны 0);
  • 5-й байт: контрольная сумма (последние 8 бит {1-й байт + 2-й байт + 3-й байт + 4-й байт})

Подключать его вывод DATA будем на порт С вывод 3.

Выводить данные будем на экран WH1604 через I2C шину.

Программный код:

#define F_CPU 4000000UL

#define DHT_PORT PORTC
#define DHT_DDR DDRC
#define DHT_PIN PINC

#define DHT_PIN_nomer 3

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include
#include

#endif /* MAIN_H_ */

рабочий файл:

#include "main.h"
typedef struct temphumi { // структура данных для DHT11
uint8_t temp;
uint8_t humi;
} temphumi_t;

int DHT_read(uint8_t _PIN, temphumi_t* _DATA);// читаем данные с датчика

void setup() {
// настраиваем порты
DDRB = 0x00;
PORTB = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRD = 0x00;
PORTD = 0x00;
// включаем I2C шину и экран
I2C_init();
LCD_ini();

}

int main(void) {
char buff[3]; // переменная для хранения данных которые выводим на экран
temphumi_t DHT_DATA = {0 ,0}; //переменная для хранения данных которые считываем с датчика

setup();

setpos(0, 0);
str_lcd("TEMP");
setpos(0, 2);
str_lcd("HUMI");

while (1) {

if (DHT_read(DHT_PIN_nomer, &DHT_DATA) == 1) {// если данные пришли

sprintf(buff, "%d", DHT_DATA.temp);
setpos(5, 0);
str_lcd(buff);// выводим температуру

sprintf(buff, "%d", DHT_DATA.humi);
setpos(5, 2);
str_lcd(buff);// выводим влажность

}

else {// если ответа от датчика нет

setpos(5, 0);
str_lcd("----");

setpos(5, 2);
str_lcd("----");

}

_delay_ms(5000);

}

}

int DHT_read(uint8_t _PIN, temphumi_t* _DATA) {

// обнуляем переменную
uint8_t DHT_RESPONSE[5] = {0, 0, 0, 0, 0};

// формируем задержки для старта датчика

DHT_DDR |= (1 << _PIN);
DHT_PORT &= ~(1 << _PIN);

_delay_ms(18);

DHT_PORT |= (1 << _PIN);
DHT_DDR &= ~(1 << _PIN);

_delay_us(40);

//смотрим, что пришло через 54us и 80us

if(DHT_PIN & (1 << _PIN)) {
return 0;
}

_delay_us(54);

if(!DHT_PIN & (1 << _PIN)) {
return 0;
}

_delay_us(80);

//если датчик готов с нами работать - читаем 5 байт

uint8_t _bit, _byte;

while (DHT_PIN & (1 << _PIN));

for (_byte = 0; _byte < 5; _byte++) {

DHT_RESPONSE[_byte] = 0;

for (_bit = 0; _bit < 8; _bit++) {

while (!(DHT_PIN & (1 << _PIN))); // ждем ....

_delay_us(30);

if (DHT_PIN & (1 << _PIN)) { // если пришла 1, записываем ее в нужное место
DHT_RESPONSE[_byte] |= 1 << (7 - _bit);
}

while (DHT_PIN & (1 << _PIN)); // ждем окончания сигнала
}
}

// если пришли все  0 - ошибка приема данных
if (DHT_RESPONSE[0] + DHT_RESPONSE[1] + DHT_RESPONSE[2] + DHT_RESPONSE[3] == 0) { return 0; }

// проверяем данные на ликвидность
if (DHT_RESPONSE[0] + DHT_RESPONSE[1] + DHT_RESPONSE[2] + DHT_RESPONSE[3] != DHT_RESPONSE[4]) { return 0; }

// если проверка на ликвидность прошла - читаем данные.
_DATA -> humi = DHT_RESPONSE[0]; // влажность
_DATA -> temp = DHT_RESPONSE[2];// температура

return 1;

}