In this guide, we will learn how to interface the DHT11 sensor and an LCD (Liquid Crystal Display) with the STM32-F103RB Nucleo Board. By combining these components, we can monitor and display real-time temperature and humidity data on the LCD screen. The DHT11 is a popular temperature and humidity sensor that provides accurate measurements in various environments.
The objective of this project is to interface the DHT11 sensor and an LCD with the STM32-F103RB Nucleo Board. By doing so, we can acquire temperature and humidity data from the sensor and display it on the LCD screen in a readable format.
Follow the circuit diagram below to properly connect the DHT11 and LCD module to the STM32-F103RB :
Nucleo-F103RB board
DHT11 Sensor
16 x 2 LCD
Potentiometer (10K Ohms)
Jumper wires
Breadboard
Follow the circuit diagram below to connect the DHT11 and LCD to the Nucleo board:
Connect the RS (Register Select) pin of the LCD to PB0 Pin of the board.
Connect the RW (Read/Write) pin of the LCD to PB1 Pin of the board.
Connect the EN (Enable) pin of the LCD to PB2 Pin of the board.
Connect the D4 pin of the LCD to PB4 Pin of the board.
The D5 pin of the LCD to PB5 Pin of the board.
Connect the D6 pin of the LCD to PB6 Pin of the board.
And the D7 pin of the LCD to PB7 Pin of the board.
Now connect the Output pin from the DHT11 to the PA0/A0 on the Nucleo board, and connect the power pins of the sensor to the board as well.
Follow these steps to configure the .IOC file and set up GPIOs and Clock :
Open the STM32 Cube IDE and start by creating a new STM32 project. Click on the board selector tab in the target selection window.
Enter "NUCLEO-F103RB" as the commercial part number and click on "Next" after selecting the board.
3. Enter the Project Name "dht11" and click on "Finish". After that, click on "Yes" to initialize all the peripherals in default mode.
Pinout & Configuration: In the Pinout & Configuration menu, select "TIM1" from the Timers section. This will configure Timer 1 for generating delay in micro seconds.
Clock Source: Choose "Internal Clock" as the Clock Source to utilize the internal clock of the STM32-F103RB Nucleo Board.
Timer Configuration: In the Configuration part of the Timers section, set the prescaler value as "72-1". The prescaler determines the frequency of the timer clock. Here, we divide the timer clock frequency by 72.
Next, specify the Counter Period as "65535". The counter period defines the overall period of the timer, this will be useful in writing a delay function in LCD.
8. To configure the GPIO pins for output, click on the GPIO pin in the Pinout & Configuration tab. Select the "GPIO_Output" option from the available options. To add a user label, right-click on the GPIO pin and select the "User Label" option and enter the desired name for the label.
9. Configure the GPIO pins highlighted in the 4th and 5th boxes in the image above as output, and rename them as shown below. These labels are predefined in the provided library
10. Don't forget to configure the PA0 Pin as GPIO_Input and name it as "DHT11".
11. After finishing the Pinout Configuration, go to the Clock Configuration menu. In the HCLK field, enter "72 MHz" as the desired frequency for the HCLK (system clock). The Integrated Development Environment (IDE) will automatically search for the necessary clock sources and prescalers based on this configuration.
12. Next, locate the gear-like icon on the toolbar and click on it. This will add the configuration settings we did in the GUI to the code.
Now, let's proceed to understand and write the C code to interface the DHT11 and LCD. Follow the steps below:
Open the main.c file, which is automatically opened by the Device Configuration Tool.
Include the necessary header file for the LCD module. Include the source file for the LCD module.
Download the "lcd_1602.c" and "lcd_1602.h" file from this link and add it to your project. Ensure that the project structure includes the added header and source files. And your project structure should look as below:
4. Now replace the below code into your main.c file before the SystemClock_Config function.
Note: You can download the full project code from this link.
#include "main.h"
#include "lcd_1602.h"
#include <stdio.h>
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim1;
UART_HandleTypeDef huart2;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM1_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t SUM, RH, TEMP;
char msg[10], T_msg[20], H_msg[20];
void Display_Temp(float Temp)
{
char str[20] = {0};
lcd_put_cur(0, 0);
sprintf(str, "TEMP:- %.2f ", Temp);
lcd_send_string(str);
lcd_send_data('C');
}
void Display_Rh(float Rh)
{
char str[20] = {0};
lcd_put_cur(1, 0);
sprintf(str, "HUMI:- %.2f ", Rh);
lcd_send_string(str);
lcd_send_data('%');
}
float Temperature = 0;
float Humidity = 0;
uint8_t Presence = 0;
void Set_Pin_Output(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
void Set_Pin_Input(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
#define DHT11_PORT GPIOA
#define DHT11_PIN DHT11_Pin
void DHT11_Start(void)
{
Set_Pin_Output(DHT11_PORT, DHT11_PIN); // set the pin as output
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, 0); // pull the pin low
delay(18000); // wait for 18ms
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, 1); // pull the pin high
delay(20); // wait for 20us
Set_Pin_Input(DHT11_PORT, DHT11_PIN); // set as input
}
uint8_t DHT11_Check_Response(void)
{
uint8_t Response = 0;
delay(40);
if (!(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)))
{
delay(80);
if ((HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)))
Response = 1;
else
Response = -1; // 255
}
while ((HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)))
; // wait for the pin to go low
return Response;
}
uint8_t DHT11_Read(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
while (!(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)))
; // wait for the pin to go high
delay(40); // wait for 40 us
if (!(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN))) // if the pin is low
{
i &= ~(1 << (7 - j)); // write 0
}
else
i |= (1 << (7 - j)); // if the pin is high, write 1
while ((HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)))
; // wait for the pin to go low
}
return i;
}
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim1);
lcd_init();
lcd_send_string("INITIALISING>>>>");
HAL_Delay(2000);
lcd_clear();
/* USER CODE END 2 */
while (1)
{
/* USER CODE BEGIN 3 */
DHT11_Start();
Presence = DHT11_Check_Response();
Rh_byte1 = DHT11_Read();
Rh_byte2 = DHT11_Read();
Temp_byte1 = DHT11_Read();
Temp_byte2 = DHT11_Read();
SUM = DHT11_Read();
TEMP = Temp_byte1;
RH = Rh_byte1;
Temperature = (float)TEMP;
Humidity = (float)RH;
Display_Rh(Humidity);
Display_Temp(Temperature);
// Convert to string and print
sprintf(T_msg, "Temperature: %.2f C \n", Temperature);
HAL_UART_Transmit(&huart2, (uint8_t *)T_msg, strlen(T_msg),
HAL_MAX_DELAY);
sprintf(H_msg, "Humidity: %.2f %%\n", Humidity);
HAL_UART_Transmit(&huart2, (uint8_t *)H_msg, strlen(H_msg),
HAL_MAX_DELAY);
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
5. After pasting the above code, ensure that you have connected your STM32-F103RB Nucleo Board to your PC/Laptop using a USB cable.
6. Next, click on the "Run and Debug" icon in the toolbar menu of the IDE (Refer to image below ). This will initiate the build process for your project. The IDE will compile the code. Once the build process is successful, the IDE will start flashing the compiled project to the STM32-F103RB Nucleo Board.
Upon successful execution of the project, the DHT11 sensor will continuously measure the temperature and humidity. The STM32-F103RB Nucleo Board will process this data and display it on the connected LCD screen in a readable format. Users will be able to monitor real-time temperature and humidity readings conveniently.
In this guide, you have learned interfacing the DHT11 sensor and LCD with the STM32-F103RB Nucleo Board allowing to monitor temperature and humidity levels in real-time. This opens up possibilities for various applications, such as weather monitoring systems, environmental control systems, and more.