👉 Table of Contents

Trong bài viết hôm nay, chúng ta sẽ khám phá về cảm biến nhiệt độ và độ ẩm DHT20 cùng với giao thức giao tiếp I2C (Inter-Integrated Circuit). DHT20 là một sản phẩm mới được nâng cấp từ phiên bản trước đó là DHT11, mang đến nhiều cải tiến đáng kể về hiệu suất và độ chính xác trong việc đo lường môi trường xung quanh. Đồng thời, giao thức I²C cũng đóng vai trò quan trọng trong việc kết nối cảm biến này với các vi điều khiển và các thiết bị thông minh.

Trong bài viết này, chúng ta sẽ tìm hiểu chi tiết về DHT20 và những tính năng đáng chú ý của nó. Chúng ta sẽ khám phá cách cảm biến này hoạt động, khả năng đo nhiệt độ và độ ẩm của nó, cũng như các ứng dụng thực tế mà nó có thể được sử dụng.

Cảm biến DHT20

Nếu bạn quan tâm đến việc sử dụng cảm biến nhiệt độ và độ ẩm trong các dự án của mình hoặc muốn khám phá thêm về giao thức giao tiếp I2C, hãy tiếp tục theo dõi blog của chúng tôi. Bây giờ, hãy cùng nhau bắt đầu khám phá thế giới của DHT20 và I2C!

Tài liệu về cảm biến: Data sheet cảm biến DHT20

Humidity and Temperature Module

• Relative humidity and temperature output

• Superior sensor performance, typical accuracy RH: ±3%, T: ±0.5℃

• Fully calibrated and processed digital output, I²C protocol

• Wide voltage support 2.2 to 5.5V DC

• Excellent long-term stability

Fast-response and anti-interference capability

ASIC (Application-Specific Integrated Circuit) là một loại vi mạch tích hợp được thiết kế và tùy chỉnh để phục vụ cho một ứng dụng cụ thể. Trong trường hợp của DHT20, ASIC sensor là một chip vi mạch tích hợp được thiết kế đặc biệt để chức năng cụ thể của cảm biến DHT20.

ASIC sensor trong DHT20 được sử dụng để thực hiện các chức năng cơ bản liên quan đến việc đo độ ẩm và nhiệt độ môi trường. Nó bao gồm các thành phần điện tử và mạch điện được tối ưu hóa để đảm bảo hiệu suất, độ chính xác và tiết kiệm năng lượng cho cảm biến DHT20.

Một số tính năng chính của ASIC sensor trong DHT20 có thể bao gồm:

  1. Xử lý tín hiệu: ASIC sensor thực hiện việc xử lý tín hiệu từ cảm biến độ ẩm và cảm biến nhiệt độ để chuyển đổi các giá trị đo lường thành dữ liệu số.
  2. Hiệu chỉnh (calibration): ASIC sensor thực hiện việc hiệu chỉnh cảm biến để đảm bảo độ chính xác của kết quả đo và khắc phục các sai số có thể xuất hiện trong quá trình đo lường.
  3. Giao tiếp: ASIC sensor cung cấp giao diện kết nối với vi điều khiển hoặc các thiết bị khác thông qua giao thức I2C, cho phép truyền dữ liệu đo lường và nhận lệnh điều khiển từ vi điều khiển.
  4. Tiết kiệm năng lượng: ASIC sensor được thiết kế để tiêu thụ ít năng lượng, giúp tối ưu hóa hiệu năng cho cảm biến DHT20, đặc biệt khi sử dụng trong các ứng dụng di động hoặc cần tiết kiệm năng lượng.

Với việc sử dụng ASIC sensor, DHT20 trở thành một cảm biến thông minh, chính xác và linh hoạt, giúp đo lường và ghi nhận độ ẩm và nhiệt độ môi trường một cách hiệu quả trong nhiều ứng dụng khác nhau.

  1. DHT20 là cảm biến đo độ ẩm và nhiệt độ:
    • Điều này cho phép nó đo lường môi trường xung quanh về hai thông số quan trọng này cùng một lúc.
  2. Giao tiếp thông qua giao thức I²C:
    • DHT20 sử dụng giao thức giao tiếp I²C để truyền dữ liệu đo lường.
    • I²C (Inter-Integrated Circuit) là một giao thức giao tiếp số hai dây được sử dụng rộng rãi trong việc kết nối các thành phần điện tử.
  3. Ứng dụng đa dạng:
    • HVAC (Heating, Ventilation, and Air Conditioning): Hệ thống điều hòa không khí.
    • Dehumidifier: Thiết bị hút ẩm.
    • Testing and Inspection Equipment: Thiết bị kiểm tra và kiểm định.
    • Consumer Products: Sản phẩm tiêu dùng.
    • Automobiles: Ô tô.
    • Automatic Control: Điều khiển tự động.
    • Data Loggers: Thiết bị ghi dữ liệu.
    • Weather Stations: Trạm thời tiết.
    • Home Appliances: Thiết bị gia dụng.
    • Humidity Control: Điều khiển độ ẩm.
    • Medical and Other Application Fields: Lĩnh vực y tế và các ứng dụng khác.

⚙️Đặc tính độ ẩm

Thông số làm việc từ 0-100%

Tuy nhiên, hoạt động chính xác tối ưu ở dãy 30% - 80%, ngoài dãy hoạt động trên cảm biến cần thời gian để tự động hiệu chỉnh lại bằng tính năng “Recovery Processing” - được nói ở Đặc tính hoạt động chung


Đặc tính độ ẩm

⚙️Đặc tính điện

Hoạt động trong dãy điện áp 2.2v đến 5.5v

Hoạt động tốt ở mức 3.3v (tối ưu tiết kiệm điện với ASIC sensor)


Đặc tính điện

⚙️Đặc tính nhiệt độ

Thông số làm việc từ -40 đến +80 độ C

Tuy nhiên, hoạt động tối ưu ít sai số ở 10 độ C đến 55 độ C


Đặc tính nhiệt độ

⚙️Đặc tính hoạt động chung

Hiệu suất của cảm biến ổn định trong điều kiện làm việc được khuyến nghị như trong hình 4.

Tiếp xúc lâu dài với điều kiện nằm ngoài phạm vi điều kiện bình thường, đặc biệt là độ ẩm trên 80%, có thể khiến tín hiệu đầu ra bị trôi tạm thời (trôi + 3% RH sau 60 giờ).

Sau khi trở lại trạng thái hoạt động bình thường, cảm biến sẽ từ từ khôi phục trạng thái hiệu chuẩn.

Recovery Processing

As mentioned above, if the sensor had been exposed to extreme working conditions or chemical vapors, the output signal will drift. It can be restored to the calibration state by the following processing.

Drying: Keep for 6 hours under 60-65℃ and <5%RH humidity conditions;

Rehydration: Keep for 6 hours under 20-30℃ and >75%RH humidity conditions7

Hoạt động lâu dài trong điều kiện bất thường sẽ đẩy nhanh quá trình lão hóa của cảm biến.


Đặc tính hoạt động chung

⚙️Cấu hình chân cắm của DHT20

DHT20 có 2 chân nguồn VCC, GND2 chân giao tiếp I2C


Cấu hình chân cắm của DHT20

⚙️Bảng đặc tính tốc độ truyền I2C

DHT20 có 2 mode lựa chọn tốc độ truyền khi giao tiếp I2C, tuy nhiên khuyến nghị chọn Standard Mode.


Bảng đặc tính tốc độ truyền I2C

Quá trình khởi động DHT20

Khởi động DHT20 đóng vai trò là SLAVE khi giao tiếp với MCU.

Cũng bao gồm các bước Start, truyền, nhận, Stop…

Untitled

⚙️Cấp nguồn

Sau khi cấp nguồn, DHT20 cần 100ms để cho quá trình chuẩn bị nhận lệnh từ MCU!

Đặc tính Start/Stop I²C theo chuẩn I2C!

⚙️Giao tiếp vơi DHT20

DHT20 có địa chỉ I²C theo datashet là 0x38.

Sau khi MCU gửi byte địa chỉ 0x38, tiếp tục gửi lệnh Write yêu cầu đo đạc số liệu cmd = 0xAC, sau khi lệnh này được gửi thì MCU phải chờ >80ms để DHT20 hoàn tất quá trình đo đạc số liệu cảm biến.

⚙️Đọc dữ liệu

Sau khi quá trình đo đạc hoàn thành, chúng ta gửi byte địa chỉ cùng với yêu cầu Read thì sẽ nhận được 7-byte dữ liệu:

  • Byte 0: chứa Status-State của việc đo đạc dữ liệu, gồm 7 bit thông tin như hình sau:
    • Bit[7]Bit[3] được sử dụng.

    Untitled

  • Byte 0 → Byte 5: chứa dữ liệu về độ ẩm và nhiệt độ
  • Byte 6: chứa byte CRC data theo chuẩn CRC-8

    Untitled

⚙️Tóm tắt quá trình cũng như bit dữ liệu như sau:

  • Trigger measurement data

Untitled

  • Read temperature and humidity data

Untitled

Lưu ý:

Cảm biến cần thời gian để thu thập.

Sau khi máy chủ gửi lệnh đo (0xAC), hãy trì hoãn hơn 80 mili giây trước khi đọc dữ liệu đã chuyển đổi và đánh giá xem bit trạng thái được trả về có bình thường hay không.

Nếu bit trạng thái [Bit7] bằng 0, điều đó có nghĩa là dữ liệu có thể được đọc bình thường.

Khi nó là 1, cảm biến đang bận và máy chủ cần đợi quá trình xử lý dữ liệu hoàn tất.

Thử nghiệm với STM32F407VET6

⚙️Tạo Project

Khởi tạo Project STM32F407VET6:

Chọn I2C1 với Standtard Mode (khuyên dùng)

Untitled

Untitled

Sau khi tạo Project (các bước hoàn thiện Project với MXCube mình sẽ không chi tiết ra nhé)

Tôi sẽ thêm thư viện LCD sử dụng I²C vào Project chung luôn:

Chi tiết về thư viện LCD I2C có thể xem ở đây: Giao tiếp I²C với màn hình LCD (bangnguyendev.github.io)

Untitled

⚙️Giới thiệu 2 function để sử dụng DHT20

Có 2 hàm còn cần giới thiệu trước khi thực hiện quá trình đọc dữ liệu cảm biến:

#define ADDRESS_SLAVE_DHT20 0X38

unsigned char  CheckCrc8(unsigned char *pDat,unsigned char Lenth)
{
	unsigned char crc = 0xff, i, j;

	for (i = 0; i < Lenth ; i++)
	{
			crc = crc ^ *pDat;
			for (j = 0; j < 8; j++)
			{
					if (crc & 0x80) crc = (crc << 1) ^ 0x31;
					else crc <<= 1;
			}
			pDat++;
	}
	return crc;
}

uint8_t read_register(uint8_t register_pointer)
{
	HAL_StatusTypeDef status = HAL_OK;
	uint8_t return_value = 0;

	status = HAL_I2C_Mem_Read(&hi2c1, ADDRESS_SLAVE_DHT20 << 1, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, &return_value, 1, 100);

	/* Check the communication status */
	if(status != HAL_OK)
	{
			
	}
	printf("return_value for %X : %X \n",register_pointer, return_value);
	return return_value;
}

Hàm unsigned char CheckCrc8(unsigned char *pDat,unsigned char Lenth) sẽ là hàm check CRC-8 và return lại giá trị CRC tính toán!

Hàm uint8_t read_register(uint8_t register_pointer) là hàm yêu cầu đọc giá trị tại địa chỉ register_pointer khi Master yêu cầu đọc.

⚙️Các bước truyền nhận dữ liệu MCU với DHT20

Theo datasheet của DHT20 thì có 5 bước để có kết quả của độ ẩm và nhiệt độ từ cảm biến:

Được sử dụng theo “7.4 Sensor Reading Process” - DataSheet DHT20

Bước 1:

Sau khi bật nguồn, đợi không ít hơn 100 mili giây.

Trước khi đọc giá trị nhiệt độ và độ ẩm, hãy lấy một byte trạng thái từ bằng cách gửi 0x71.

  • Nếu từ giá trị trạng thái đọc về AND-BIT với 0x18 không bằng 0x18 thì hãy khởi tạo thanh ghi 0x1B, 0x1C, 0x1E.
  • Nếu chúng bằng nhau, hãy chuyển sang bước tiếp theo!
//Trigger measurement data
void trigger_measurement_data_dht20 ()
{
	// Bước 1: 
	HAL_Delay(100);
	uint8_t status = read_register(0x71);
	if ((status & 0x18) == 0x18)
	{
			// Bước 2:
	}
	else //  initialize the 0x1B, 0x1C, 0x1E registers
	{
		
	}
}

image-1

Bước 2:

Đợi 10ms để gửi lệnh 0xAC (đo kích hoạt).

image-1

Tham số lệnh tiếp theo này có hai byte:

  • Byte đầu tiên byte là 0x33.
  • Byte thứ hai là 0x00.

Ta tạo mảng với độ lớn 3 phần tử để chứa dữ liệu cho 3 lệnh này: uint8_t data_t[3];

Sử dụng hàm HAL_I2C_Master_Transmit để gửi dữ liệu từ MASTER qua SLAVE

ADDRESS_SLAVE_DHT20 << 1 thuộc tính địa chỉ 7 bit dịch về trái 1 bit để bit thứ 0 là bit R/W (chi tiết xem tại bài viết Giao tiếp I²C với màn hình LCD (bangnguyendev.github.io)).

//Trigger measurement data
void trigger_measurement_data_dht20 ()
{
	HAL_Delay(100);
	uint8_t status = read_register(0x71);
	if ((status & 0x18) == 0x18)
	{
			// Bước 2: 
			HAL_Delay(10);
			uint8_t data_t[3];
			data_t[0] = 0xAC;
			data_t[1] = 0x33;
			data_t[2] = 0x00;
			HAL_I2C_Master_Transmit (&hi2c1, ADDRESS_SLAVE_DHT20 << 1,(uint8_t *) data_t, 3, 100);
	}
	else //  initialize the 0x1B, 0x1C, 0x1E registers
	{
		
	}
}

image-1

Bước 3:

Chờ 80ms để phép đo hoàn thành, nếu từ trạng thái đọc Bit [7] bằng 0, có nghĩa là phép đo đã hoàn thành, và sau đó sáu byte có thể được đọc liên tục; nếu không, tiếp tục chờ đợi.

HAL_Delay(80); chờ khoảng hơn 80ms

image-1

uint8_t buffer[7]; tạo mảng 7 phần tử để chứa 7 byte data nhận về từ DHT20. uint32_t data_read = 0; biến để lưu giá trị tính toán độ ẩm, nhiệt độ.

Sử dụng kiểu dữ liêu uint32_t bởi vì mỗi gói data nhiệt độ hoặc độ ẩm chứa 20-bit data

Độ ẩm : byte1 + byte2 + 4bit cao của byte3 (20-bit)

Nhiệt độ : 4bit thấp của byte3 + byte4 + byte5 (20-bit)

//Trigger measurement data
void trigger_measurement_data_dht20 ()
{
	HAL_Delay(100);
	uint8_t status = read_register(0x71);
	if ((status & 0x18) == 0x18)
	{
			HAL_Delay(10);
			uint8_t data_t[3];
			data_t[0] = 0xAC;
			data_t[1] = 0x33;
			data_t[2] = 0x00;
			HAL_I2C_Master_Transmit (&hi2c1, ADDRESS_SLAVE_DHT20 << 1,(uint8_t *) data_t, 3, 100);
			
			// Bước 3: 
			HAL_Delay(80);
			
			uint8_t buffer[7];
			uint32_t data_read = 0;
	
			// Gửi lệnh yêu cầu đọc dữ liệu từ MASTER tới DHT20
	    	// yêu cầu nhận 7 byte lưu vào mảng buffer (bao gồm byte CRC-8 luôn)
	    	HAL_I2C_Master_Receive(&hi2c1, ADDRESS_SLAVE_DHT20 << 1, buffer, 7, 100);
			for (int i =0; i<7;i++)
			{
				printf("bufffer %d: %X \n",i, buffer[i]);
			}
			
			// Check Bit[7] = 0 at Byte0
			if ((buffer[0] & 0x80) == 0x00)
			{
				// Bước 4: 
			}
			else
			{
				printf("Check Bit[7] at Byte0: %x \n",buffer[0]&0x80);
			}
	}
	else //  initialize the 0x1B, 0x1C, 0x1E registers
	{
		
	}
}

image-1

Bước 4:

Sau khi nhận được

  • sáu byte (Byte 0→ Byte 5): dữ liệu độ âm , nhiệt độ
  • byte tiếp theo (Byte 6): dữ liệu kiểm tra CRC.

Người dùng có thể đọc nó ra khi cần thiết. Nếu đầu nhận cần kiểm tra CRC, một ACK sẽ được gửi sau khi nhận được byte thứ sáu. Nếu không thì gửi NACK để kết thúc, giá trị ban đầu của CRC là 0XFF và đa thức kiểm tra CRC8 là:

CRC [7:0] = 1+X4+X5+X8

...
	// Check Bit[7] = 0 at Byte0
	if ((buffer[0] & 0x80) == 0x00)
	{
			// Bước 4: 
			// Check CRC buffer[0] vs buffer[6]
			if(CheckCrc8(&buffer[0],6)==buffer[6])
			{
				// Bước 5: 
				printf("CRC OK \n");
			}
			else
			{
				printf("CRC fail \n");
			}
	}
	else
	{
		printf("Check Bit[7] at Byte0: %x \n",buffer[0]&0x80);
	}
...

Bước 5:

Tính giá trị nhiệt độ và độ ẩm

Lưu ý: Kiểm tra trạng thái hiệu chỉnh ở bước đầu tiên chỉ cần kiểm tra khi bật nguồn.

...
	// Check Bit[7] = 0 at Byte0
	if ((buffer[0] & 0x80) == 0x00)
	{
			// Bước 4: 
			// Check CRC buffer[0] vs buffer[6]
			if(CheckCrc8(&buffer[0],6)==buffer[6])
			{
				// Bước 5: 
				printf("CRC OK \n");
				data_read=buffer[1]; //0x83
				data_read=data_read<<8;//0x83 <<8 = 0x8300
				data_read+=buffer[2]; //0x8300 + 0x30 => 0x8330
				data_read=data_read<<8; //0x8330  <<8 = 0x833000
				data_read+=buffer[3]; //0x833000 + 0x76 => 0x833076
				data_read=data_read>>4;	 //0x833076 => 0x83307
				
				RH = (float)data_read*100/1048576;
				printf("RH %0.1f%% \n", RH);
				
				data_read=buffer[3]&0x0F; //0x76 & 0x0F = 0x06
				data_read=data_read<<8; //0x06  <<8 = 0x0600
				data_read+=buffer[4]; //0x0600 + 0x27 = 0x0627
				data_read=data_read<<8; //0x0627  <<8 = 0x062700
				data_read+=buffer[5];	//0x062700 + 0xDD = 0x0627DD
				
				Temp = (float)data_read*200/1048576-50;
				printf("Temp %0.1f \n", Temp);
			}
			else
			{
				printf("CRC fail \n");
			}
	}
	else
	{
		printf("Check Bit[7] at Byte0: %x \n",buffer[0]&0x80);
	}
...

Debug mode để xem giá trị nhé!

image-1

Hình ảnh trên LCD

image-1

Cám ơn mọi người đã theo dõi bài viết!