基于MATLAB GUI的环境温湿度检测界面设计

6 篇文章 0 订阅
2 篇文章 1 订阅

一、题目要求

  温度,湿度,CO2作为农业生产中中非常重要的参数,需要准确的采样。该系统完成对于上述参数的精确采样,通过LCD显示在面板上,并将测量值发送到上位机进行显示。

(1)测量对应的温度、湿度、CO2的值。
(2)用OLED显示实际的温度值和湿度值
(3)实现对温度,湿度,CO2的实时采集。
(4)如果温湿度低于或者高于设定值,采取对应措施升降温和升降湿度值。
(5)在上位机上设计监测界面,实时显示各个测量值。


源码
链接:https://pan.baidu.com/s/1PWT5x9oD2lo6c3Wlz6RVfg
提取码:6666

二、系统总体设计

1、用到的器件和软件

控制器:stm32f407vet6核心板
显示屏:0.96寸OLED (SPI接口)
温湿度传感器:DHT11
CO2浓度传感器:SGP30 (I2C接口)

stm32编程软件:CUBEMX,keil5
上位机软件设计工具:MATLAB APP Designer

2、整体思路

  通过DHT11采集温湿度和SGP30采集二氧化碳并通过OLED实时显示,1s刷新一次,通过串口将采集到的数据上传到用MATLAB做的界面中。



三、效果图

在这里插入图片描述
在这里插入图片描述

四、嵌入式硬件部分

1.原理图

请添加图片描述
请添加图片描述

五、嵌入式软件部分

1.主函数

//包含显示、初始化、和传感器读数程序
int main(void)
{
uint32_t CO2Data,TVOCData;//定义CO2浓度变量与TVOC浓度变量
  uint16_t temperature;
  uint16_t humidity;
unsigned long sgp30_dat;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_TIM6_Init();
  MX_SPI2_Init();
HAL_UART_Receive_DMA(&huart1,aRxBuffer,1);  //串口DMA初始化
OLED_Init();    //OLED初始化
Show_Str(0, 2,"Initializing...", 16, 0);  //显示初始化中...

//DHT11初始化
  while(DHT11_Init()){
	HAL_Delay(500);
  }

  //初始化SGP30
  SGP30_Init();  
HAL_Delay(100);
SGP30_Write(0x20,0x08);
sgp30_dat = SGP30_Read();//读取SGP30的值
CO2Data = (sgp30_dat & 0xffff0000) >> 16;
TVOCData = sgp30_dat & 0x0000ffff;	
//SGP30模块开机需要一定时间初始化,在初始化阶段读取的CO2浓度为400ppm,TVOC为0ppd且恒定不变,因此上电后每隔500ms读取一次
//SGP30模块的值,如果CO2浓度为400ppm,TVOC为0ppd,则屏幕闪烁显示“正在检测中...”,直到SGP30模块初始化完成。
while(CO2Data == 400 && TVOCData == 0)
{
	 SGP30_Write(0x20,0x08);
	 sgp30_dat = SGP30_Read();//读取SGP30的值
	 CO2Data = (sgp30_dat & 0xffff0000) >> 16;//取出CO2浓度值
	 TVOCData = sgp30_dat & 0x0000ffff;			 //取出TVOC值
	 HAL_Delay(500);
}
OLED_Clear();    //清屏
  while (1)
  {
	DHT11_Read_Data(&temperature,&humidity);   //读取温度湿度值
     SGP30_Write(0x20,0x08);
	sgp30_dat = SGP30_Read();//读取SGP30的值
	CO2Data = (sgp30_dat & 0xffff0000) >> 16;//取出CO2浓度值
	printf("%02d%1d",temperature>>8,temperature&0xff);
	printf("%02d%1d",humidity>>8,humidity&0xff);
	printf("%03d",CO2Data);
	HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_6);
	
//OLED显示
//温度显示
	Show_Str(4, 1,"temp:", 16, 0);
	OLED_ShowNum(40,1,temperature>>8,3,16);
	Show_Str(64, 1,".", 16, 0);
	OLED_ShowNum(72,1,temperature&0xff,1,16);
	Show_Str(84,1,"℃", 16, 0);
		
    //湿度显示
	Show_Str(4, 3,"humi:", 16, 0);
	OLED_ShowNum(40,3,humidity>>8,3,16);
Show_Str(64, 3,".", 16, 0);
	OLED_ShowNum(72,3,humidity&0xff,1,16);
	Show_Str(84, 3,"%RH", 16, 0);
	 
    //CO2浓度显示	
	Show_Str(4, 5,"CO2:", 16, 0);
	OLED_ShowNum(40,5,CO2Data,3,16);
	Show_Str(70, 5,"PPM", 16, 0);
		
    HAL_Delay(1000);		//延时1s
  }
}

2.DHT11初始化程序

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在     	 
uint8_t DHT11_Init(void)
{ 
  DHT11_Rst();
	return DHT11_Check();
}

//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//设置为输出
	DHT11_DQ_OUT_LOW; 	//拉低DQ
	HAL_Delay(20);    	//拉低至少18ms
	DHT11_DQ_OUT_HIGH; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void) 	   
{   
	uint8_t retry=0;
	DHT11_IO_IN();      //设置为输出	 
	while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
	while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}

3.DHT11测量程序

//从DHT11读取一次数据
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi)    
{        
 	uint8_t buf[5];
	uint8_t i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=(buf[0]<<8) + buf[1];
			*temp=(buf[2]<<8) + buf[3];
		}
	}else return 1;
	return 0;	    
}

4.SGP30模块初始化

//初始化IIC接口
void SGP30_Init(void)
{
   SGP30_Write(0x20, 0x03);
}

5.SGP30模块测量CO2
uint32_t SGP30_Read(void)
{
  uint32_t dat;
  uint8_t crc;
  SGP30_IIC_Start();
  SGP30_IIC_Send_Byte(SGP30_read); //发送器件地址+读指令
  SGP30_IIC_Wait_Ack();
  dat = SGP30_IIC_Read_Byte(1);
  dat <<= 8;
  dat += SGP30_IIC_Read_Byte(1);
  crc = SGP30_IIC_Read_Byte(1); //crc数据,舍去
  crc = crc;  //为了不让出现编译警告
  dat <<= 8;
  dat += SGP30_IIC_Read_Byte(1);
  dat <<= 8;
  dat += SGP30_IIC_Read_Byte(0);
  SGP30_IIC_Stop();
  return(dat);
}

六、MATLAB GUI部分

1、界面设计

App 设计工具并不要求软件开发专业背景。您只需拖放可视化组件即可实现图形用户界面 (GUI) 设计布局,还可以使用集成的编辑器快速为其行为编程。
App 设计工具集成了 App 构建的两大任务:图形用户界面 (GUI) 可视化组件布局,以及 App 行为编程。要在 MATLAB 中构建 App,App 设计工具是十分理想的环境。

在matlab命令行中输入appdesigner
>> appdesigner
在这里插入图片描述
将可视化组件拖放到设计画布,然后根据对齐提示实现精确布局。App 设计工具自动生成面向对象的代码,用于指定 App 的布局和设计。
在这里插入图片描述
其会自动生成代码。使用集成的 MATLAB 编辑器来定义 App 的行为。App 设计工具可以使用代码分析器自动检查代码问题。您可以在编写代码时查看关于代码的警告和错误消息,并根据这些消息修改您的 App。您还可以使用 Stateflow® 图对 App 行为建模。在这里插入图片描述
生成自己的APP,双击.exe文件即可运行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、程序

①.串口接收及显示

  properties (Access = public)
        COM;    % 端口号
        s  ;    %端口设置句柄
        RX_num; %接收统计
        TX_num; %发送统计
        RX_once;%一次接收的数据
        RX_Date;%接收的所以数据
        is_open;%是否打开串口标志位
    end
    
    methods (Access = public)
        function  EveBytesAvailableFcn(app, src, event)
            global i;
            n = src.BytesAvailable;%获取接收到的字符个数
            if n>0%n>0才继续执行,因为00也会触发中断
                app.RX_num=app.RX_num+n;
                %app.Label_RX.Text=num2str(app.RX_num);%将数字转化为字符串输出
                app.RX_once=fread(src,n,'uchar');%读取函数,读取后矩阵为一列
                app.RX_Date =strcat(app.RX_Date, app.RX_once');%字符串拼接,需要转置化为一行
                %app.ReceiveView.Value= app.RX_Date;%textarea的设置格式为cell,或单行字符串
                
                %温度显示
                temp=floor(str2double(app.RX_Date)/1000000)*0.1;
                app.Temp.Value=temp;
                app.Gauge_Temp.Value=temp;
                %温度最低最高值判断
                if temp>=str2double(app.TextArea_Temp.Value)
                    app.Lamp_Temp.Color="1.00,0.00,0.00";
                else
                    app.Lamp_Temp.Color="0.00,1.00,0.00";
                end
                if temp<=str2double(app.TextArea_Temp_2.Value)
                    app.Lamp_Temp_2.Color="1.00,0.00,0.00";
                else
                    app.Lamp_Temp_2.Color="0.00,1.00,0.00";
                end
                
                %湿度显示
                humi=mod((floor(str2double(app.RX_Date)/1000)),1000)*0.1;
                app.Humi.Value=humi;
                app.Gauge_Humi.Value=humi;

                %波形显示
                plot(app.UIAxes,i,temp,'r.');
                plot(app.UIAxes_2,i,humi,'b.');
                if i==20
                    i=0;
                    cla(app.UIAxes);
                    cla(app.UIAxes_2);
                else
                    hold(app.UIAxes,'on');   % 这样就可以hold住了
                    hold(app.UIAxes_2,'on');   % 这样就可以hold住了
                    i=i+1;
                End
                 %湿度最低最高值判断
                if humi>=str2double(app.TextArea_Humi.Value)
                    app.Lamp_Humi.Color="1.00,0.00,0.00";
                else
                    app.Lamp_Humi.Color="0.00,1.00,0.00";
                end
                if humi<=str2double(app.TextArea_Humi_2.Value)
                    app.Lamp_Humi_2.Color="1.00,0.00,0.00";
                else
                    app.Lamp_Humi_2.Color="0.00,1.00,0.00";
                end
                
                %CO2显示
                co2=mod(str2double(app.RX_Date),1000);
                app.CO2.Value=co2;
                app.Gauge_CO2.Value=co2;
                if co2>=str2double(app.TextArea_CO2.Value)
                    app.Lamp_CO2.Color="1.00,0.00,0.00";
                else
                    app.Lamp_CO2.Color="0.00,1.00,0.00";
                end
                
                app.RX_Date ='';
                %app.ReceiveView.Value= app.RX_Date;
                %app.TX_num=0;
                %app.RX_num=0;
                %app.Label_TX.Text=num2str(app.TX_num);
                %app.Label_RX.Text=num2str(app.RX_num);
            end
        end
    end

②.串口接收

function Button_SendPushed(app, event)
%val=app.transmitView.Value;
val=strcat(strcat(app.TextArea_Temp.Value,app.TextArea_Humi.Value),app.TextArea_CO2.Value);
%val=num2str(app.EditField_Temp.Value);
if ~isempty(val{1})%textarea控件是cell格式,获取需要用{1}
app.TX_num=app.TX_num+length(val{1});
%app.Label_TX.Text=num2str(app.TX_num);
fwrite(app.s, char(val), 'uint8', 'async');%需要将val转化为char
End

③.串口设置

 function pbOpenSerialValueChanged2(app, event)
      app.COM=get(app.ppCOM,'Value');
      if strcmp(get(app.pbOpenSerial,'Text'),'打开串口')
           try
                app.s=serial(app.COM);
                app.s.BaudRate=str2num(app.Baud.Value);%设置波特率                  app.s.DataBits=8;%设置数据长度
                app.s.StopBits=1;%设置停止位长度
                app.s.InputBufferSize=1024000;%设置输入缓冲区大小为1M
                app.s.BytesAvailableFcnMode='byte';  %串口事件回调设置
                app.s.BytesAvailableFcnCount=1; %输入缓冲区存在10个字节触发回调函数
                app.s.BytesAvailableFcn={@app.EveBytesAvailableFcn};%回调函数的指定
                fopen(app.s);%打开串口
                app.is_open=1;
                app.pbOpenSerial.Text='关闭串口';
                app.Lamp.Color=[0 1 0];
             catch err
                msgbox('打开失败');
             end
        else
             try
                fclose(app.s);
                app.pbOpenSerial.Text='打开串口';
                app.Lamp.Color=[0.15 0.15 0.15];
              catch err
                msgbox('关闭失败');
              end
              delete(app.s);
              app.is_open=0;
         end
      end


七、源代码及原理图压缩包

https://download.csdn.net/download/qq_44181970/74730641

BUG解决记录

1.串口DMA用不了

解决方法: 先初始化DMA,再初始化串口

2.DHT11读取数值错误,且一直为一个固定数

us延时配置问题,应将168-1更改为84-1。

  • 4
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
教程使用MATLAB搭建一个家庭监控系统视频温湿度报警-视频及源码下载地址.txt 系统背景:监控家里是否有陌生人闯入,家里的设备是否工作正常(北方的会员可能知道,如果家里的暖气是自供的话,冬天千万不能关暖气,否则水管容易爆裂)。所以打算自己DIY一个家庭监控系统,全部使用MATLAB自带的函数功能。使用MATLAB GUIDE设计一个操作界面,使用MATLAB图像采集/处理/机器人视觉工具箱来检测物体。 需要的硬件: 1:家里有网络(一般使用无线摄像头、无线摄像头一般有网线接口); 2:一台运行windows的电脑(能连上家里的网络即可,我用的是05年买的一个台式机,现在看来已经很落后了); 3:一个无线IP Camera(会员@梦之缘工作坊给我推荐EasyN IPCam的F系列和H3系列,因为他们提供SDK。 我现在使用的是从淘宝上购买的凯聪1018,但是他们不提供SDK,摄像头的很多功能都不方便调用。所以打算放弃凯聪,选购EasyN的IP摄像头。如果大家有好的推荐,也欢迎跟帖。硬件必须要选对); 4:一个USB温度计、湿度计(我也是在taobao上购买的,还在邮寄中,一般可以把环境温度录入Excel文件)。 希望实现的功能: (1)        无线摄像头能够检测到移动物体,系统能自动给我发邮件,并且附上当前的照片。 (2)        USB温度计检测室内温度,当温度低于15°时候,能够发邮件给我,提醒我是否忘记开暖气。当温度高于40°时候,也能够提醒我,很可能着火了。 (3)        USB湿度计检测室内湿度,如果发现湿度很大,是否表示水龙头没有关好,或者提醒我打开空调的除湿功能。 你是否有这个疑问? 一般IP Camera厂商都提供完善的物体检测、发邮件报警等功能,那有必要还要自己开发么? 我的经验是这样的,自己开发是可以实现一些自定义的功能,比如说加上一些特定的图像算法、扩展应用(邮件报警只是一个使用,是否可以实现与其他硬件的协作)等。 我计划把我的实现过程记录下来,而不是只是呈现一个最终的系统界面给大家。我每天添加一些类容,公布一些进展,并且上传不同阶段的程序。这样做的好处是可以把整个系统分散开来,不同会员可以根据自己的需要摘取系统里的一些功能。跟我以前给的教程类似,我一般只是给一个大体的可以工作的框架,希望感兴趣的会员能完善整个系统的功能。 所有开发都基于MATLAB R2012a, 需要用到的MATLAB工具箱(不断添加中): MATLAB MATLAB图像处理工具箱 MATLAB图像采集工具箱 ======================== 2012年7月22日 ======================== 实现功能: 1:搭建一个基础的GUI框架; 2:实现MATLAB读取IP摄像头: 修改了urlwrite函数,改成urlwrite_basicauth。原因是一般IP camera需要用户名和密码,而现有的imread不能提供用户名和密码。修改了MATLAB图像工具箱里自带的imread函数,改成imread_auth,使之调用urlwrite_basicauth。使用MATLAB的timer功能,不间断读取图像,用户可以在GUI上修改帧率。 常见问题: 用户名和密码怎么修改? 答:在urlwrite_basicauth.m,搜索urlConnection.setRequestProperty;复制代码其中的aWxvdmVtYXRsYWI6MTIzNDU2是加密后的用户名和密码。 压缩包里,有一个get_code.php文件,其中“ilovematlab:123456”对应的是用户名ilovematlab和密码123456. 根据你自己的需要,修改成自己的用户名和密码。然后运行此php文件,返回值就是加密的用户名和密码。 程序打包下载: Home Security System 12-07-22.zip 使用MATLAB搭建一个家庭监控系统(视频 温湿度 报警) MATLAB 视频监控系统.png 使用MATLAB搭建一个家庭监控系统(视频 温湿度 报警) MATLAB读取IP Camera.png ======================== 2012年8月05日 ======================== 更新: 用户可以自定义采集图像的URL地址,用户可以根据自己自定义的IP地址,输入到imrea

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值