还在用DHT11嘛?用这款温湿度传感器让HR不再说你项目"烂大街"!

上期我们介绍了一个STM32毕设的器件选型,其中有温湿度传感器,我推荐了SHT30。

在CSDN上一搜温度传感器,冒出来的就是DHT11,大部分朋友在选型时也会选DHT11,是一个实打实的已经“烂大街”的传感器。听一些HR说看到简历上写着DHT11,就知道是什么水准了。
DHT11采用单总线通讯协议即one-wire,数据以位为单位传输,每个数据位持续 50 微秒。高电平持续 26-28 微秒表示一个逻辑 "1",高电平持续 70 微秒表示一个逻辑 "0"。在学习51单片机的时候使用的非常多。
而SHT30采用的是标准I2C通讯协议,是多数低速传感器都会采用的通讯协议,相较于DHT11有着更复杂的技术栈和在STM32等更为简单的实现,具有更高的精度和稳定性。
本期我们介绍如何分别利用STM32和ESP32实现SHT30。
关于SHT30,其实操作起来比较简单,它的器件地址是0x44,我们只需要对其写入命令,读取数据,查阅数据手册后将相关的命令使用宏定义实现。
// SHT30 I2C地址 (ADDR引脚接GND时为0x44) #define SHT30_ADDR 0x44 // 7位地址:0x44 (ADDR引脚接GND时) // SHT30命令列表 #define SHT30_SOFT_RESET 0x30A2 // 软复位 #define SHT30_HIGH_ENABLED 0x2C06 // 周期测量,高重复性 #define SHT30_READ_STATUS 0xF32D // 读状态寄存器 #define SHT30_CLEAR_STATUS 0x3041 // 清除状态寄存器 #define SHT30_STOP_MEASURE 0x3093 // 停止周期测量 #define SHT30_SINGLE_HIGH 0x2400 // 单次测量,高重复性
之后利用硬件I2C实现命令发送。
static uint8_t SHT30_Send_Cmd(uint16_t cmd)
{
uint8_t cmd_buffer[2];
cmd_buffer[0] = cmd >> 8; // 高字节
cmd_buffer[1] = cmd & 0xFF; // 低字节
return HAL_I2C_Master_Transmit(&hi2c1, (SHT30_ADDR << 1), cmd_buffer, 2, 0xFF);
}
它的读取函数也很简单,我们在读取前需要发送单次测量命令,之后直接读取寄存器的值。
// 读取温湿度数据
uint8_t SHT30_Read_Temp_Hum(float *temperature, float *humidity)
{
uint8_t buffer[6];
uint16_t temp_raw, hum_raw;
// 发送单次测量命令
if(SHT30_Send_Cmd(SHT30_SINGLE_HIGH) != HAL_OK)
return HAL_ERROR;
// 等待测量完成
HAL_Delay(15);
// 读取6个字节数据,注意这里要用读地址(末位为1)
if(HAL_I2C_Master_Receive(&hi2c1, (SHT30_ADDR << 1) | 0x01, buffer, 6, 0xFF) != HAL_OK)
return HAL_ERROR;
// 温度数据转换
temp_raw = ((uint16_t)buffer[0] << 8) | buffer[1];
*temperature = -45 + 175 * ((float)temp_raw / 65535);
// 湿度数据转换
hum_raw = ((uint16_t)buffer[3] << 8) | buffer[4];
*humidity = 100 * ((float)hum_raw / 65535);
return HAL_OK;
}
第1,2个字节表示温度数据,第3,4个字节表示湿度数据。
利用公式:温度 = -45 + (175 * (温度数据 / 65536))
湿度同样如此,我们就可以获取温湿度数据了。
在此基础上,利用结构体深度封装一下。
typedef struct {
float temperature; // 温度值
float humidity; // 湿度值
} SHT30_Data_t;
// SHT30设备结构体
typedef struct {
I2C_HandleTypeDef* hi2c; // I2C句柄
uint8_t dev_addr; // 设备地址
SHT30_Data_t data; // 测量数据
uint8_t init_flag; // 初始化标志
} SHT30_HandleTypeDef;
之后就可以在我们的主函数使用了。
if(SHT30_Init(&hsht30, &hi2c1) != HAL_OK)
{
Error_Handler();
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(SHT30_ReadData(&hsht30) == HAL_OK)
{
float temp = SHT30_GetTemperature(&hsht30);
float humi = SHT30_GetHumidity(&hsht30);
}
HAL_Delay(1000);
}
关于SHT30,其实操作起来比较简单,它的器件地址是0x44,我们只需要对其写入命令,读取数据,查阅数据手册后将相关的命令使用宏定义实现。
// SHT30 I2C地址 (ADDR引脚接GND时为0x44) #define SHT30_ADDR 0x44 // 7位地址:0x44 (ADDR引脚接GND时) // SHT30命令列表 #define SHT30_SOFT_RESET 0x30A2 // 软复位 #define SHT30_HIGH_ENABLED 0x2C06 // 周期测量,高重复性 #define SHT30_READ_STATUS 0xF32D // 读状态寄存器 #define SHT30_CLEAR_STATUS 0x3041 // 清除状态寄存器 #define SHT30_STOP_MEASURE 0x3093 // 停止周期测量 #define SHT30_SINGLE_HIGH 0x2400 // 单次测量,高重复性
之后利用硬件I2C实现命令发送。
static uint8_t SHT30_Send_Cmd(uint16_t cmd)
{
uint8_t cmd_buffer[2];
cmd_buffer[0] = cmd >> 8; // 高字节
cmd_buffer[1] = cmd & 0xFF; // 低字节
return HAL_I2C_Master_Transmit(&hi2c1, (SHT30_ADDR << 1), cmd_buffer, 2, 0xFF);
}
它的读取函数也很简单,我们在读取前需要发送单次测量命令,之后直接读取寄存器的值。
// 读取温湿度数据
uint8_t SHT30_Read_Temp_Hum(float *temperature, float *humidity)
{
uint8_t buffer[6];
uint16_t temp_raw, hum_raw;
// 发送单次测量命令
if(SHT30_Send_Cmd(SHT30_SINGLE_HIGH) != HAL_OK)
return HAL_ERROR;
// 等待测量完成
HAL_Delay(15);
// 读取6个字节数据,注意这里要用读地址(末位为1)
if(HAL_I2C_Master_Receive(&hi2c1, (SHT30_ADDR << 1) | 0x01, buffer, 6, 0xFF) != HAL_OK)
return HAL_ERROR;
// 温度数据转换
temp_raw = ((uint16_t)buffer[0] << 8) | buffer[1];
*temperature = -45 + 175 * ((float)temp_raw / 65535);
// 湿度数据转换
hum_raw = ((uint16_t)buffer[3] << 8) | buffer[4];
*humidity = 100 * ((float)hum_raw / 65535);
return HAL_OK;
}
第1,2个字节表示温度数据,第3,4个字节表示湿度数据。
利用公式:温度 = -45 + (175 * (温度数据 / 65536))
湿度同样如此,我们就可以获取温湿度数据了。
在此基础上,利用结构体深度封装一下。
typedef struct {
float temperature; // 温度值
float humidity; // 湿度值
} SHT30_Data_t;
// SHT30设备结构体
typedef struct {
I2C_HandleTypeDef* hi2c; // I2C句柄
uint8_t dev_addr; // 设备地址
SHT30_Data_t data; // 测量数据
uint8_t init_flag; // 初始化标志
} SHT30_HandleTypeDef;
之后就可以在我们的主函数使用了。
if(SHT30_Init(&hsht30, &hi2c1) != HAL_OK)
{
Error_Handler();
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(SHT30_ReadData(&hsht30) == HAL_OK)
{
float temp = SHT30_GetTemperature(&hsht30);
float humi = SHT30_GetHumidity(&hsht30);
}
HAL_Delay(1000);
}

ESP32上开发相对简单,在Arduino中下载相对应的库。

// 初始化I2C通信,指定ESP32的SDA和SCL引脚
Wire.begin(SDA_PIN, SCL_PIN);
// 初始化SHT31D传感器,默认地址0x44
sht31d.begin(0x44);
SHT31D result = sht31d.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50);
// 打印温度数据
Serial.print("温度 (°C): ");
Serial.println(result.t);
Serial.println("");
// 打印湿度数据
Serial.print("湿度 (%RH): ");
Serial.println(result.rh);
之后依据库API打印数据即可。

之后我们可以测试一下,利用ESP32将温湿度数据每隔半小时上传到MQTT服务器,在云服务器部署相应网页。



登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!