Using DHT11 with ChibiOS/RT

A cheap sensor for humidity and temperature

The DHT11 is a basic, low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, and spits out a digital signal on the data pin (no analog input pins needed).

The communication on data pin occurs according to a non-standard protocol known as One-Wire protocol.

Getting started with DHT11

In this article we want to provide a demonstration for DHT11 compatible with ChibiOS/HAL 3.0, but also explain concepts inside that demo. Following that purpose we need for the DHT11 datasheet.

DHT11 Datasheet

Features and connections

DHT11 mechanical draft
DHT11 mechanical draft.

Typical connections

Typical circuit requires a pull-up resistor on data pin. In our case Data out is connected directly to Port A, pad 8 of a ST Nucleo F4 using a simple short wire, and it works perfectly. Anyway in a definitive circuit is suggested to connect a pull-up resistor of 4,7 kΩ as shown at page 4 of datasheet.

Pin Description

  1. the VDD power supply 3.5~5.5V DC
  2. DATA serial data, a single bus
  3. NC, empty pin
  4. GND ground, the negative power

Data format

When the DHT11 is queried , it replies using a 40bit length data packet. Data is organized as:

  • 8bit humidity integer data + 8bit humidity decimal data
  • 8bit temperature integer data + 8bit temperature decimal data
  • 8bit parity bit

Humidity rate data is provided as percentage with resolution 1%. Temperature is provided as Celsius with resolution of 1°C. That means on DHT11 data packet, decimal data is always zero. This is quite different for DHT22 that provides same data packet but with higher resolution and in this case decimal data is non-zero.

Data timing

DHT11 timing diagram
A timing diagram for the DHT11 one wire protocol communication.

According to data sheet DHT11 must be queried from host(our MCU) pulling down data pin for at least 18ms, than sensor lowers data pin for 80us as the response signal, followed by an high logical state output of 80 micro-seconds as notification of starting to send the data packet: so sensor replies with data. DHT11 actually sends out square waves and bit could be recognized measuring the time during which signal stays high: if that time is 26-28us it is a 0-bit, if it is 70 us is a 1-bit.

DHT11 bits
Differences between ‘0’ and ‘1’ bit format.

Summering getting data from DHT11 requires:

  1. Set a pin as output and pull down that output to start communication.
  2. Set the same pin as input to capture the square wave measuring high and low logical state period.
  3. Eventually control if communication succeeds using check sum.

Using DHT11 with ChibiOS/HAL 3.0

Rereading above, the question is: what we need for to use DHT11 with ChibiOS? Basically one-wire protocol requires a pin that could be used as output push-pull as well as capture input. HAL has a driver that can capture an input (typically a square wave) and measure time period as well as time during which signal is in logical high state or logical low state. This driver is Input Capture Unit (ICU) ad is associated to a TIM like PWM.

Basically every pin could be used as digital output, but only some pin are connected to a TIM. We have to choose a pin internally connected to a timer channel. Reading Alternate Function table on data-sheet we could see that PA8 could be used as TIM1 Channel 1 thought AF 1 (If you are not familiar with PAL driver checkout the tutorial Hello ChibiOS). Reading ST Nucleo user manual we could learn that PA8 is connected to D7 pin of Arduino Connector.
Let outlining our program flow:

  1. Set PA8 mode as output push-pull and request data to DHT11 lowering Data out for at least 18ms.
  2. Set PA8 as AF1 and start ICU with a clock of at least 1MHz (This way we have a resolution of 1us).
  3. Start capturing data with ICU. Using ICU width callback acquire 41 widths.
  4. For each acquisition we need to write some variable according to widths.
  5. Eventually stop the ICU and restore PA8 mode to default configuration (input pull-up)

Note that first acquisition that should be 80 ticks (80us since our resolution is 1us) and others should be 26-28 ticks for a 0-bit or 70 ticks for 1-bit.

Creating this application from scratch

First step as always is duplicate a working project (If you don’t know how to do that checkout the tutorial Quickview of Chibistudio paying particular attention to video. Once we have created a new project, we have to enable ICU in halconf.h.

Since we want to use PA8 and so TIM1 CH1 we need to enable ICUD1 in mcuconf.h

If we want to use chprintf() to print data on a serial we have to edit makefile adding memstreams.c and chprintf.c to CSRC and including related folder modifying INCDIR

Now we are ready to write main.c. First of all we have to include chprintf.h declare a base sequential stream to use with chprintf(). Furthermore we could define some constants.

Now we can write an ICU configuration according to ChibiOS documentation. Since we need to measure time during high logical states we need to set ICU input as Active High. That means ICU width will measure time between signal rising edge and signal falling edge. Measure could have an uncertainly of ± 1 tick (In this case 1us). Other configuration are width, period and overflow callbacks, channels selected and value of DIE Register of TIM. We choose only width callback and enable channel 1.

ICU width callback must be declared before ICU configuration. According to our configuration (ICU_INPUT_ACTIVE_HIGH), width callback is called on falling edge. Here we can get a width measure from driver ICU, and make some elaboration. Lets take a look to the code.

This code gets the latest width, checking if it is related to a start bit (80us) or to one of the forty bits sent from DHT11. If current bit is the start one the counter bit_counter is reset. During the forty callback occurencies related to data bits, width is stored into a buffer (just for debug purposes).

bit_counter counts data related callback occurencies and data is “built” bit by bit and stored into the static variables (HR, TEMP, CHECK_SUM). To do this bit masks are used (Take a look at Registers and bit-masks). The tmp variable is used as temporary variable to build 8-bit lenght words during the sequence of callbacks. So when bit_counter reaches the value 7, tmp contains the integer part of the humidity rate, on 15 the decimal part of the humidity rate, on 23 the integer part of the temperature and so on…

Main initialize serial driver (We will use it with chprintf), set pin properly to make request, reset pin for ICU launching this driver, waits time needed by communication and prints out data.

How to port this application on other MCUs

Most likely we have just to change ICU configuration and pin used by data. Note that every driver configuration in ChibiOS has a part common to every MCU. For ICU the timer frequency, capture mode, and callback are independent from platform. We should expect to modify last part of configuration like DIER. A good idea to understand how is structured configuration, is copying it from a platform demo in chibios3/testhal (same MCU same configuration, so, as example F401RE and F407 have same configurations).

Project download

The attached demo has been tested under ChibiOS 17.6.x. Note that you can find more recent version of this project int the Download Page. Note also that starting from the version 20 all the demos from PLAY Embedded will be distributed together with ChibiStudio.

RT-STM32F401RE-NUCLEO-DHT11-176

Replies to Using DHT11 with ChibiOS/RT

  • Hi, starting from your example, I’m trying to use the ICU driver on a F401RE to acquire the signal from the PWM generated on PWMD1 (using TIM1 on PB4) on PB6 setting it as ALTERNATE(1) and using TIM4. However, once I’ve started the ICU driver and i’ve electrically connected PB6 to PB4, it seems that the ICU callbacks are never triggered. Do I miss to configure something? ANy hint?

    • Hi,
      looking at STM323F401RE datasheet it seems that on PB4 there is TIM3CH1 mapped on AF2 and on PB6 there is TIM4CH1 mapped on AF2. BTW I don’t have figured out which demo are you talking about. FYI next time you need help we have also a forum (). Thanks for reading us and for your comment.

  • Thanks! I followed your instructions for my AM2303 sensor, thinking it was the same as a DHT-11. After getting the system running on my STM32F401RE Nucleo board connected to the sensor, I realized I was getting what looked like bad data from the sensor, along with checksums that were failing.

    Looking at the data on an oscilloscope however, the checksums were correct.

    It turns out that the AM2303 is actually compatible with the DHT-22 sensor, not the DHT-11. The pinout and one wire protocol is exactly the same, but the data is sent in a slightly different format. The low bytes for temperature and humidity are not zeros, so must be captured and included in the checksum.

    The data display format should also be handled slightly differently, since it has higher resolution than the DHT-11 data. (0.1 degree C and 0.1 % humidity instead of 1 degree and 1%).

    Once I realized the difference it was easy to update your code to work with the DHT-22 sensors. I’d be happy to send you the changes I made if you’re interested.

    • Thanks for this reply and for these kind words.
      First time I wrote the code it was for a DHT22 (AM2303). I edited it before to publish it on this website since DHT11 is cheaper than DHT22 and hence more popular. Feel free to share with us your code. Since the biggest problem is the maintenance of these articles and of the code, maybe the best way for me will be to add a preprocessor switch in the demo which allows to choose between DHT11 and DHT22. Some textual notes in the article will be also added.

      Thanks,
      RM

  • Hi everyone. I am working with the DHT22 and dont understand all your code for the changes. Please, if u like explain a little more the problem or send the code for the DHT22. Thanks

    • Hello Daniel.
      Right now is quite complicated to edit this code to make it compliant with DHT22 but I have a solution in mind. Maybe tomorrow I will update it. Keep in touch.

  • Hi Rocco.
    I changed the code and now i’m reading the DHT22 in a STM32F100. With your code I understood several things about Chibi and I was able to do what I needed.. Thanks 🙂

    • Dear,
      your comment is completely out of topic. Please take care next time. Anyway, I never used ds1307 RTC as most of STM32 MCUs already have embedded RTC. I would suggest you to migrate to STM32F3. In this case ChibiOS already has RTC driver.

Leave a Reply