Monday, 19 February 2018

Interface DHT22 with STM32

In my last post, I mentioned the use of microseconds delay, check HERE, and this post is the application of that. Today I am going to interface DHT22 with STM32 microcontroller, which utilizes delay in microseconds.
The DHT-22  is a digital-output relative humidity and temperature sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, and sends out a digital signal on the data pin. You can download the datasheet here.
I am not going to waste more time by going into more details, I am sure you already know what this is and that’s why you are here. So let’s jump to the point. If you look at the datasheet, you will find the signal pattern to initialize the sensor as shown in the picture below

INITIALIZATION



Here the black line is the signal from the microcontroller and the white line is the signal from the DHT22. As you can see in order to initialize the sensor, we have to pull the data line LOW for around 500 us (microseconds) and pull it HIGH for around 20-40 us. After this DHT22 will pull the line low for 80us and than high for 80us. Once this is done, the sensor will be initialized and start transmitting.
NOTE:- You need to connect pull-up resistance to the data line or else DHT22 will not be able to pull it HIGH.
So to initialize the sensor, steps are as follows:-
1.)  Set the pin (data) as output.
2.) Pull the pin low and wait for 500us.
3.) Pull the pin high and wait for 30us.
4.) set the pin as input for receiving the data.
DHT22 will now send the response as you can see in the figure above. To check the response, steps are as follows:-
1.) wait for 40us
2.) check if the pin is low, than wait for 80us. This will totally be a delay of 120us and the pin should be high now.
3.) Check if the pin is high. If it is, than the response is ok.
4.) Now wait for the pin to go low as you can see below that the pin is low for 50us before transmitting any bit.

DATA Transmission

Now DHT22 will send 40 bits of data.  Each bit’s transmission begins with low-voltage-level that last 50us, the following high-voltage-level signal’s length decides whether the bit is “1” or “0”.


So if the length of high-voltage-level is around 26-28us, the bit is “0”.



And if the length is around 70us, than the bit is “1”.
The 40 bits sent by DHT22 are as follows DATA = 8 bit integral RH data + 8 bit decimal RH data + 8 bit integral T data+8 bit decimal T data + 8 bit checksum
If the data transmission is right, check-sum should be the last 8 bit of “8 bit integral RH data+8 bit decimal RH data+8 bit integral T data+8 bit decimal T data”
Reading data is also very simple. Steps are as follows:-
1.) Wait for the pin to go high.
2.) Wait for 40us. This is because the length of “0” bit is 26-28us  and if the pin is high after 40us, it indicates that the bit is “1”.
3.) write the respective values to the variable.

Some Insight into the CODE

INITIALIZATION

void DHT22_start (void)
{
set_gpio_output ();  // set the pin as output
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 0);   // pull the pin low
DWT_Delay_us (500);   // wait for 500us
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 1);   // pull the pin high
DWT_Delay_us (30);   // wait for 30us
set_gpio_input ();   // set as input
}

RESPONSE

void check_response (void)
{
DWT_Delay_us (40);  // wait for 40us
if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1))) // if the pin is low
{
DWT_Delay_us (80);   // wait for 80us
if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1))) check = 1;  // if the pin is high, response is ok
}
while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)));   // wait for the pin to go low
}

READ DATA

uint8_t read_data (void)
{
uint8_t i,j;
for (j=0;j<8;j++)
{
while (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)));   // wait for the pin to go high
DWT_Delay_us (40);   // wait for 40 us
if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)) == 0)   // 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 (GPIOA, GPIO_PIN_1)));  // wait for the pin to go low
}
return i;
}

CODE

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_I2C1_Init();

  /* USER CODE BEGIN 2 */
DWT_Delay_Init ();
lcd_init ();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
DHT22_start ();
check_response ();
Rh_byte1 = read_data ();
Rh_byte2 = read_data ();
Temp_byte1 = read_data ();
Temp_byte2 = read_data ();
sum = read_data();
//if (sum == (Rh_byte1+Rh_byte2+Temp_byte1+Temp_byte2))
{
TEMP = ((Temp_byte1<<8)|Temp_byte2);
RH = ((Rh_byte1<<8)|Rh_byte2);
}

lcd_send_cmd (0x80);
lcd_send_string ("TEMP: ");
lcd_send_data ((TEMP/100)+48);
lcd_send_data (((TEMP%100)/10)+48);
lcd_send_data ('.');
lcd_send_data ((TEMP%10)+48);
                lcd_send_data ('C');

lcd_send_cmd (0xC0);
lcd_send_string ("RH: ");
lcd_send_data ((RH/100)+48);
lcd_send_data (((RH%100)/10)+48);
lcd_send_data ('.');
lcd_send_data ((RH%10)+48);
lcd_send_data ('%');

HAL_Delay (1000);
  }
  /* USER CODE END 3 */

}

RESULT



Servo motor with STM32

I have already covered a tutorial about Pulse Width Modulation in STM32  HERE  and in this tutorial i am going to cover one of its applicat...