STM32 + DHT11

в 23:27, , рубрики: DHT11, diy или сделай сам, stm32, метки: ,

Попал мне в руки датчик температуры и влажности DHT11. Измеряет влажность в пределах 20-90% и температуру от 0 до 50°С. Погрешность измерения влажности 5%, температуры 2°С. Время захвата 1 сек. Интерфейс связи single wire (datashit). Столь скромные параметры ограничивают область применения датчика только бытовыми даже комнатными условиями.
image
Я хотел сравнить показания устройства на HCH1000+DS18B20 с DHT11.

Ошибочно я заключил что DHT11 и DS18B20 уживутся на одной шине. Оказалось протоколы у них совсем разные. После неудачного опыта, наспех собрал устройство для установления истины.
image
Готовой библиотеки DHT11 для STM32 не нашел. Для Ardino здесь. Протокол связи single wire не имеет ничего общего с 1-wire. Разница между 0 и 1 получается из разницы длительности импульса.
image
Сперва удерживаем порядка 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

Источник

Поделиться

* - обязательные к заполнению поля