Попал мне в руки датчик температуры и влажности DHT11. Измеряет влажность в пределах 20-90% и температуру от 0 до 50°С. Погрешность измерения влажности 5%, температуры 2°С. Время захвата 1 сек. Интерфейс связи single wire (datashit). Столь скромные параметры ограничивают область применения датчика только бытовыми даже комнатными условиями.
Я хотел сравнить показания устройства на HCH1000+DS18B20 с DHT11.
Ошибочно я заключил что DHT11 и DS18B20 уживутся на одной шине. Оказалось протоколы у них совсем разные. После неудачного опыта, наспех собрал устройство для установления истины.
Готовой библиотеки DHT11 для STM32 не нашел. Для Ardino здесь. Протокол связи single wire не имеет ничего общего с 1-wire. Разница между 0 и 1 получается из разницы длительности импульса.
Сперва удерживаем порядка 20 мс низкий уровень шины, потом отпускаем ее, через 20 мс датчик зажимает ее в 0 сам и держит 80 мкс потом отпускает на 80 мкс (формирует сигнал присутствия) за ним следует 40 бит данных, с одинаковым стартом — зажатием шины на 50 мкс и битом. бит 0 где-то 28 мкс, бит 1 — 70 мкс. Ну и на прощание датчик зажимает и отпускает шину. 40 бит данных это 5 байт из которых первых два влажность, следующие 2 температура и байт четности. Байт четности равен сумме предыдущих байт. 1-й байт и 3-й байты передают значения, 2 и 4 я так понял зарезервированы под десятые доли.
Самый простой способ считать длительность импульсов и записывать их в массив. Потом этот массив трансформировать в массив байт.Так родилась библиотека dht11.c.
uint16_t read_cycle(uint16_t cur_tics, uint8_t neg_tic){
uint16_t cnt_tics;
if (cur_tics < MAX_TICS) cnt_tics = 0;
if (neg_tic) {
while (!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)&&(cnt_tics<MAX_TICS)){
cnt_tics++;
}
} else {
while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)&&(cnt_tics<MAX_TICS)){
cnt_tics++;
}
}
return cnt_tics;
}
uint8_t read_DHT11(uint8_t *buf){
uint16_t dt[42];
uint16_t cnt;
uint8_t i, check_sum;
//reset DHT11
Delay(500);
GPIO_LOW(GPIOA,GPIO_Pin_2);
Delay(20);
GPIO_HIGH(GPIOA,GPIO_Pin_2);
//start reading
cnt = 0;
for(i=0;i<83 && cnt<MAX_TICS;i++){
if (i & 1){
cnt = read_cycle(cnt, 1);
} else {
cnt = read_cycle(cnt, 0);
dt[i/2]= cnt;
}
}
//release line
GPIO_HIGH(GPIOA,GPIO_Pin_2);
if (cnt>=MAX_TICS) return DHT11_NO_CONN;
//convert data
for(i=2;i<42;i++){
(*buf) <<= 1;
if (dt[i]>20) (*buf)++;
if (!((i-1)%8) && (i>2)) buf++;
}
//calculate checksum
buf -= 5;
check_sum = 0;
for(i=0;i<4;i++){
check_sum += *buf;
buf++;
}
if (*buf != check_sum) return DHT11_CS_ERROR;
return DHT11_OK;
}
Проект содержащий библиотеку dht11.c здесь.
Автор: tarasii