目录
摘要
基于stm32开发的环境检测系统可实时检测周围环境的温湿度参数,设有自动预警装置,可人为调控温湿度阈值,拥有记录功能,可自动记录温度湿度最大值和最小值并自动刷新,温湿度数据通过OLED屏幕显示,并支持无线传输功能可以在手机、电脑等上位设备显示实时温度湿度,远距离监视周围环境温湿度的变化。
一、系统方案
(一)系统功能
(二)系统结构
通过12v锂电池加稳压模块进行供电,由stm32负责控制,dht11温湿度传感器负责检测温湿度,使用jdy31蓝牙模块实现无线传输,用LED灯实现预警功能,通过按键实现人机交互,用OLED显示屏完成显示功能。
(三)元件选择
1. 主控处理器选择
STM32F103C8T6
STM32F103C8T6因其高性能、低成本和良好的开发支持,在嵌入式系统开发中得到了广泛应用。完备的固件库使得其操作起来方便简单。该微控制器集成了多种外设,如ADC、DAC、UART、SPI、I2C等,可以轻松连接多种传感器和外围设备,适用于多种应用场景。由于STM32系列微控制器应用广泛,网络上有大量的技术资料和社区支持,遇到问题时可以容易地找到解决方案。
2. 温湿度检测模块的选择
DHT11温湿度传感器
DHT11价格低廉,采用单总线通信方式,与微控制器的接口简单,只需要一个数字输入/输出引脚即可读取温湿度数据。DHT11输出的是数字信号,不需要额外的模拟前端电路,减少了电路复杂性和误差来源。DHT11将湿度传感器和温度传感器集成在一个封装内,节省了空间,简化了电路设计。DHT11与许多微控制器兼容,如Arduino、STM32、ESP8266等,社区支持和资料丰富。DHT11在测量过程中功耗低,适合电池供电的设备。DHT11能够测量相对湿度范围从5%到95%,温度范围从0°C到50°C,满足大多数室内应用的需求。
尽管DHT11具有上述优点,但它也有一些局限性,如精度相对较低,对于需要高精度测量的应用可能不够用;温度测量范围有限,不适用于极端温度环境等。因此,在选择传感器时,需要根据具体的应用需求来决定是否使用DHT11。
3. 无线传输模块的选择
jdy31或HC05蓝牙模块
JDY-31是一款低功耗蓝牙模块,通常基于蓝牙4.2低能耗(BLE)技术。JDY-31模块的最大特点是低功耗,这使得它非常适合电池供电的设备,因为它可以显著延长电池寿命。JDY-31提供了简单的接口,可以快速与微控制器或其他设备集成,通过AT指令集进行配置和控制。JDY-31与大多数蓝牙4.2及更高版本的设备兼容,包括智能手机和平板电脑。虽然BLE主要用于低数据速率应用,但JDY-31仍然可以提供足够的传输速度,适用于许多物联网(IoT)和远程监控应用。与其他蓝牙模块相比,JDY-31具有较好的成本效益,适合预算有限的项目。
4. 显示模块的选择
0.96寸OLED
是stm32最常用的显示模块,通常支持SPI、I2C等接口,易于与微控制器和其他电子设备连接。具有显示内容多,显示范围广,程序简单,使用方便,功耗低等多个优点。
5. 预警模块选择
LED或蜂鸣器
主要通过程序实现,将检测值与设置阈值的实时比较,通过LED灯或蜂鸣器模拟执行预警功能。
6. 供电模块选择
12V锂电池
在电动工具、便携式电子设备、电动车和储能系统中广泛应用。具有寿命长、容量大、抗冲击性好、自放电率低和良好的低温放电性能,强大的充电接受能力和快速充电能力。
降压模块
通过降压模块降到3.3V,给各模块供电。可选LM2596等型号降压模块。
二、理论计算与分析
通过温湿度传感器检测的数据计算温湿度的显示数据,DHT11温湿度传感器返回
数据格式:
8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据 + 8bit校验和
数据传送正确时,校验和数据等于:
8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据”所得结果的末8位
温度计算:
temperature = temp1 + temp2 / 10.0;
湿度计算:
humidity = humi1 + humi2 / 10.0;
数据校验:
buf[0] + buf[1] + buf[2] + buf[3] == buf[4];
另外,经实测发现,该传感器湿度只能精确到整数,因此湿度数据可以直接取用整数部分。且采样周期较长,短时间内连续读取没有意义,可设置一定采样周期,增大读取数据的时间间隔,这样可降低功耗,采到更多有效数据。
三、电路与程序设计
(一)电路设计
注:按键和LED均为低电平有效,VCC和GND省略
(二)实物连接图
(三)程序设计
1.温湿度读取
uint8_t DHT11_Read_Data(uint8_t *humi1, uint8_t *humi2,uint8_t*temp1, uint8_t*temp2)
{
uint8_t buf[5];
uint8_t i;
DHT11_RST(); //DHT11端口复位,发出起始信号
if(DHT11_Check() == 0) //等待DHT11回应,0为成功回应
{
for(i = 0; i < 5; i++) //读取40位数据
{
buf[i] = DHT11_Read_Byte(); //读出数据
}
if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) //数据校验
{
*humi1 = buf[0]; //将湿度值放入指针
*humi2 = buf[1];
*temp1 = buf[2]; //将温度值放入指针
*temp2 = buf[3];
}
}
else return 1;
return 0;
}
2.OLED显示
void display_task()
{
switch(display_state)
{
case 0:
OLED_ShowCC_F16x16(1, 1, 2); // 温
OLED_ShowCC_F16x16(1, 3, 4); // 度
OLED_ShowChar(1, 5, ':');
OLED_ShowFNum(1, 6, temperature, 3, 1);
OLED_ShowCC_F16x16(1, 11, 0); // ℃
OLED_ShowCC_F16x16(3, 1, 3); // 湿
OLED_ShowCC_F16x16(3, 3, 4); // 度
OLED_ShowChar(3, 5, ':');
OLED_ShowFNum(3, 6, humidity, 3, 1);
OLED_ShowCC_F16x16(3, 11, 1); // %
break;
case 1:
OLED_ShowCC_F16x16(1, 1, 7); // 最
OLED_ShowCC_F16x16(1, 3, 9); // 低
OLED_ShowCC_F16x16(1, 5, 2); // 温
OLED_ShowCC_F16x16(1, 7, 4); // 度
OLED_ShowChar(1, 9, ':');
OLED_ShowFNum(1, 10, temp_min, 3, 1);
OLED_ShowCC_F16x16(1, 15, 0); // ℃
OLED_ShowCC_F16x16(2, 1, 7); // 最
OLED_ShowCC_F16x16(2, 3, 8); // 高
OLED_ShowCC_F16x16(2, 5, 2); // 温
OLED_ShowCC_F16x16(2, 7, 4); // 度
OLED_ShowChar(2, 9, ':');
OLED_ShowFNum(2, 10, temp_max, 3, 1);
OLED_ShowCC_F16x16(2, 15, 0); // ℃
OLED_ShowCC_F16x16(3, 1, 7); // 最
OLED_ShowCC_F16x16(3, 3, 9); // 低
OLED_ShowCC_F16x16(3, 5, 3); // 湿
OLED_ShowCC_F16x16(3, 7, 4); // 度
OLED_ShowChar(3, 9, ':');
OLED_ShowFNum(3, 10, humi_min, 3, 1);
OLED_ShowCC_F16x16(3, 15, 1); // %
OLED_ShowCC_F16x16(4, 1, 7); // 最
OLED_ShowCC_F16x16(4, 3, 8); // 高
OLED_ShowCC_F16x16(4, 5, 3); // 湿
OLED_ShowCC_F16x16(4, 7, 4); // 度
OLED_ShowChar(4, 9, ':');
OLED_ShowFNum(4, 10, humi_max, 3, 1);
OLED_ShowCC_F16x16(4, 15, 1); // %
break;
case 2:
OLED_ShowCC_F16x16(1, 1, 2); // 温
OLED_ShowCC_F16x16(1, 3, 4); // 度
OLED_ShowCC_F16x16(1, 5, 11); // 下
OLED_ShowCC_F16x16(1, 7, 12); // 限
OLED_ShowChar(1, 9, ':');
OLED_ShowNum(1, 10, temp_low, 2);
OLED_ShowCC_F16x16(1, 12, 0); // ℃
OLED_ShowCC_F16x16(3, 1, 2); // 温
OLED_ShowCC_F16x16(3, 3, 4); // 度
OLED_ShowCC_F16x16(3, 5, 10); // 上
OLED_ShowCC_F16x16(3, 7, 12); // 限
OLED_ShowChar(3, 9, ':');
OLED_ShowNum(3, 10, temp_up, 2);
OLED_ShowCC_F16x16(3, 12, 0); // ℃
break;
case 3:
OLED_ShowCC_F16x16(1, 1, 3); // 湿
OLED_ShowCC_F16x16(1, 3, 4); // 度
OLED_ShowCC_F16x16(1, 5, 11); // 下
OLED_ShowCC_F16x16(1, 7, 12); // 限
OLED_ShowChar(1, 9, ':');
OLED_ShowNum(1, 10, humi_low, 2);
OLED_ShowCC_F16x16(1, 12, 0); // ℃
OLED_ShowCC_F16x16(3, 1, 3); // 湿
OLED_ShowCC_F16x16(3, 3, 4); // 度
OLED_ShowCC_F16x16(3, 5, 10); // 上
OLED_ShowCC_F16x16(3, 7, 12); // 限
OLED_ShowChar(3, 9, ':');
OLED_ShowNum(3, 10, humi_up, 2);
OLED_ShowCC_F16x16(3, 12, 0); // ℃
break;
}
}
3.数据采集与处理
void collect_task()
{
if(collect_flag == 0)return;
collect_flag = 0;
//判断是否是正常读取
if(DHT11_Read_Data(&humi1,&humi2,&temp1,&temp2)==0)
{
//读取温湿度
temperature = temp1 + temp2 / 10.0;
humidity = humi1 + humi2 / 10.0;
//判断报警
if((temp1 <= temp_low) || (temp1 >= temp_up) )
{
LED1_ON();
}
else
{
LED1_OFF();
}
if((humi1 <= humi_low) || (humi1 >= humi_up))
{
LED2_ON();
}
else
{
LED2_OFF();
}
if(reset_flag == 0)
{
//更新最大、小值
if((temp1 > temp_max1) || ((temp1 == temp_max1) && (temp2 > temp_max2)))
{
temp_max1 = temp1;
temp_max2 = temp2;
temp_max = temperature;
}
if((temp1 < temp_min1) || ((temp1 == temp_min1) && (temp2 < temp_min2)))
{
temp_min1 = temp1;
temp_min2 = temp2;
temp_min = temperature;
}
if(humi1 > humi_max1)
{
humi_max1 = humi1;
humi_max = humidity;
}
if(humi1 < humi_min1)
{
humi_min1 = humi1;
humi_min = humidity;
}
}
else
{
temp_max1 = temp1;
temp_max2 = temp2;
temp_max = temperature;
temp_min1 = temp1;
temp_min2 = temp2;
temp_min = temperature;
humi_max1 = humi1;
humi_max = humidity;
humi_min1 = humi1;
humi_min = humidity;
reset_flag = 0;
}
//蓝牙发送数据
Serial_SendPacket();
}
}
4.按键操作
void Key_task()
{
uint8_t KeyNum;
KeyNum = Key_GetNum();
switch(KeyNum)
{
case 2:
display_state = (display_state + 1)%4;
OLED_Clear();
break;
case 3:
if(display_state == 2)
{
temp_up++;
}
if(display_state == 3)
{
humi_up++;
}
break;
case 4:
if(display_state == 2)
{
temp_up--;
}
if(display_state == 3)
{
humi_up--;
}
break;
case 5:
if(display_state == 2)
{
temp_low++;
}
if(display_state == 3)
{
humi_low++;
}
break;
case 6:
if(display_state == 2)
{
temp_low--;
}
if(display_state == 3)
{
humi_low--;
}
break;
case 7:
if(display_state == 1)
{
temp_max1 = 0;
temp_max = 0;
temp_min1 = 0;
temp_min = 0;
humi_max1 = 0;
humi_max = 0;
humi_min1 = 0;
humi_min = 0;
reset_flag = 1;
}
break;
}
}
5.main函数
int main(void)
{
OLED_Init();
LED_Init();
Key_Init();
Serial_Init();
DHT11_Init();
display_task();
Delay_s(2);//跳过不稳定状态
DHT11_First();
Timer_Init();
while (1)
{
collect_task();
display_task();
Key_task();
}
}
四、测试结果
(一)温湿度实时显示测试
(二)温湿度阈值报警测试
(三)温湿度最值记录测试
(四)无线传输测试
五、完整代码
链接:https://pan.baidu.com/s/1CsJjXv9tYufPHD0WrmRGhg?pwd=85jq
提取码:85jq
六、参考文章
1、玩转传感器——DHT11温湿度传感器(STM32版)_温湿度传感器接线图-CSDN博客
2、STM32江科大的oled驱动代码添加显示浮点数_oled显示浮点数-CSDN博客
3、【STM32F103】JDY-31蓝牙模块(USART)_jdy31蓝牙模块-CSDN博客
4、GitHub - XieLazyDog/ValuePack: BlueTooth Controller for MCU
5、b站视频: https://www.bilibili.com/video/BV1Pb411o7v6/?share_source=copy_web&vd_source=d912cf4b424f2f4f9f337ac63872359a
6、b站up江协科技:STM32入门教程视频