您的位置:首页 > 文旅 > 旅游 > 预警器件控制思考

预警器件控制思考

2024/12/23 8:56:46 来源:https://blog.csdn.net/qq_57484399/article/details/140879950  浏览:    关键词:预警器件控制思考

预警器件控制思考

最小示例思想

当读取到环境信息与环境阈值的时候, 我们预警系统就要根据这些信息做出判断,是否要启动器件。

image-20240801174851481

最简单的就是, 举温度temp的例子, temp(温度)与temp_th(阈值), 通过判断, 得出是否要启动器件.

image-20240802061601931

如果在一段时间内, 一直是环境异常, 我们那只需要启动一次器件就可以了, 按照上面的方法, 就会一直重复启动器件. 所以我们在启动器件前, 需要判断一下, 器件的状态, 如果要切换状态的话, 那么我们就操作硬件.

image-20240801173412942

(1)当temp > temp_th 时, 当环境刚异常, 并且器件没有启动的时候, 此时我们判断出此状态, 那么我们就启动硬件.

那下一次判断的时候, 环境仍然异常, 但是器件刚才已经启动了, 那么通过判断, 我们就不用启动了.

(2)当temp < temp_th 时, 当环境刚恢复正常时, 并且器件启动的时候, 此时我们判断出此状态, 那么我们就可以关闭硬件了.

那下一次判断的时候, 环境仍然正常, 但是器件刚才已经关闭了, 那么通过判断, 我们就不用重复关闭了.

(3) 所以, 当我们要切换器件状态的时候, 我们首先判断器件当前的状态是否和我们所需一致, 如果一致, 那么我们就不进行切换即可.

(4)最小例程的代码, 是用 red_led 和 blue_led 来存储温湿度应急器件的状态的, 并且这个标志位是和器件io口绑定状态, 我们在操作io口后,我们都要更新这个状态。只是为了避免频繁操作器件,我们在判断预警操作器件的时候,都需要判断当前器件状态,是否已经符合, 如果符合,那么就不操作。我们这里功能不是太复杂,所以就用这种方法来实现。

后续如果加入操作系统的思想的话,尤其是硬件的操作,需要多级容错判断,来保证绝对的安全,这里只做简单分析。

image-20240801175047736

器件状态绑定

我们通过观察发现 ,red_led和 PBout(3)深度绑定, 所以直接新建一个文件, 然后新建一个结构体, 来保存器件的状态, 操作器件开关.

我们先观察下面示例, 然后分析学习, 构建我们的工程:

image-20240801180144618

(1)观察, 这个函数,是操作器件的, 然后每次操作的时候, 都会传入一个status, 就是我们所需的状态,

​ 但是 传入状态并不代表着我们就要频繁操作io口, 因为在一段时间内环境一直异常,我们100ms钟检测一次,当我们检测到异常, 我们就启动器件, 因为要保证预警系统的实时性, 所以下一个100ms检测的时候, 器件已经运行了,我们就无需重复启动了. 所以当我们传入状态后, 想开器件, 就判断一下器件是否已经启动, 如果启动, 就说明在上一个100ms的时候, 就已经启动了,我们这次进入只是为了保证实时性, 从而重复确认.

​ 同理, 关闭器件也一样, 如果我们检测到 环境 从 异常->正常后,

我们就关闭器件,操作io口前, 也同样判断一下, 器件是否已经处于关闭状态, 如果关闭,则无需操作. (注意我们上图运用的是结构体变量, 其函数状态和io口状态深度绑定, 所以通过判断变量,就可以判断出我们所处的状态,从而操作io口)

image-20240801173412942

代码实操:

在加dht11和oled最小例程的基础上,手把手改写代码, 加思路导向

改前的工程:

https://ww0.lanzoul.com/i1jH22680p3a

修改完预警的工程:

https://ww0.lanzoul.com/ihhjp26avqub

失效联系qq:2958360390 回复关键词 最小例程系统预警系统构建

(1) 我们解压打开改之前的工程

image-20240802071443939

(2)然后去锁定预警处理部分的代码

会发现, 我们这里是直接在main函数里面访问temp和humi的, 直接做出预警判断

image-20240802071703229

(3)并且, 和上述说的一样, red_led和 PBout(3) 并没有深度绑定, 所以我们先去 构建一下, 操作器件的函数, 我们构建两个文件一个是temp预警器件, 一个是 humi预警器件。

​ 首先,还和之前一样, 在品字哪里, 新建一个alarm的文件夹, 来存放预警器件的文件, 然后再去add, 逐个创建文件, 我们起名, temp_led.c 和 temp_led.h , humi_led.c和 humi_led.h吧。

详细步骤:(为了避免篇幅过长)

https://blog.csdn.net/qq_57484399/article/details/140862473

(4)如下图,我们先做temp_led.c的预警,

这里我们不谈c语言格式, 只谈随心写代码, 甚至我们可以用中文来代替, 至于格式问题, 是编译器和al的事情, 我们只谈逻辑.

image-20240802081906579

(5)先看之前原始的预警的时候, 操作器件的时候, 是怎么操作的

image-20240802082109921

我们是先判断状态, 让着当状态切换的时候, 我们才操作器件.

但是这些好像和我们用户没什么关系, 我们用户, 只是想, 在报警的时候, 你操作器件就行了, 至于启动不启动器件, 是我们底层控制启动器件的代码通过判断, 才做的事情, 所以, 我们此处进行替换.

image-20240802082426300

(6)至于启动不启动器件, 是函数内部通过判断器件是否处于运行状态, 才操作io口的.我们这里复制 temp_led_Set, 然后直接跳转temp_led.c函数

image-20240802082630432

(7)看到这个是传入的状态, 所以我们还得给led_red绑定一个结构体状态, 通过调用判断这个状态, 再确定是否需要操作io口,

我们去temp_led.h去定义状态结构体

image-20240802124853840
#define red_led_ON	1#define red_led_OFF	0typedef struct
{_Bool red_led_Status;} TEMP_ALARM_INFO;

(8)定义完, 之后, 去temp_led.c里面去创建一个temp_alarm_info的变量, 然后 再去构造函数. 相当于定一个了一个状态了

image-20240802125209534

TEMP_ALARM_INFO temp_info = {0};

(9) 然后我们接着构造控制函数

传入的状态, 我们修改为 _Bool status

void temp_led_Set(_Bool status)
{}

(10)还是根据流程图所示, 我们传入的状态, 就是我们想要的状态, 目前如果 机器是此状态, 我们就跳过不操作io口, 相当于我们切换状态的时候, 我们才操作io口

image-20240802130517065

(11)直接上代码, 如果需要开预警设备, 并且当前状态不是开,则操作io口

如果需要关应急设备, 并且当前状态不是关,则操作io口.

(为什么要判断切换状态呢? 因为我们并不能确保这是 第一次从正常->应急, 或者从应急->预警, 第一次操作,当然可以直接操作io口, 因为在一段时间内, 我们只需要操作一次io口,就行了, 但是为了保证实时性, 我们会一直操作判断器件状态, 从而达到实时性, 后续我们采用操作系统思想解决, 我们这里比较简单粗暴.)

image-20240802190849869

下面我把完善的代码奉上, 请直接复制黏贴即可

temp_led.c
//单片机头文件
#include "stm32f10x.h"#include "temp_led.h"
#include "sys.h"TEMP_ALARM_INFO temp_info = {0};void temp_led_Init(void)
{//初始化小灯, PB3(温度) PB4(湿度) PB5(烟雾浓度)GPIO_InitTypeDef GPIO_InitStructure;//开启硬件时钟	PB5/* GPIOD Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//禁用JTAGD端口GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	//配置 pB 3 4 5 GPIO工作模式(推挽输出)/* Configure PD0 and PD2 in output pushpull mode */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);	//配置端口//控制端口寄存器GPIO输出电平PBout(3) = 0;//temp_led	}	void temp_led_Set(_Bool status)
{if(status == red_led_ON && temp_info.red_led_Status != red_led_ON)	{//操作小灯开PBout(3) = 1;//temp_led//状态设置为开temp_info.red_led_Status = status;}elseif(status == red_led_OFF && temp_info.red_led_Status != red_led_OFF){//操作小灯关PBout(3) = 0;//temp_led//状态设置为关temp_info.red_led_Status = status;}
}
temp_led.h
#ifndef _TEMP_LED_H_
#define _TEMP_LED_H_#define red_led_ON	1#define red_led_OFF	0typedef struct
{_Bool red_led_Status;} TEMP_ALARM_INFO;extern TEMP_ALARM_INFO temp_info;void temp_led_Init(void);
void temp_led_Set(_Bool status);#endif
humi_led.c
//单片机头文件
#include "stm32f10x.h"#include "humi_led.h"
#include "sys.h"HUMI_ALARM_INFO humi_info = {0};void humi_led_Init(void)
{//初始化小灯, PB3(温度) PB4(湿度) PB5(烟雾浓度)GPIO_InitTypeDef GPIO_InitStructure;//开启硬件时钟	PB5/* GPIOD Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//禁用JTAGD端口GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	//配置 pB 3 4 5 GPIO工作模式(推挽输出)/* Configure PD0 and PD2 in output pushpull mode */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);	//配置端口//控制端口寄存器GPIO输出电平PBout(4) = 0;//humi_led	}	void humi_led_Set(_Bool status)
{if(status == blue_led_ON && humi_info.blue_led_Status != blue_led_ON)	{//操作小灯开PBout(4) = 1;//blue_led//状态设置为开humi_info.blue_led_Status = status;}elseif(status == blue_led_OFF && humi_info.blue_led_Status != blue_led_OFF){//操作小灯关PBout(4) = 0;//blue_led//状态设置为关humi_info.blue_led_Status = status;}
}
humi_led.h
#ifndef _HUMI_LED_H_
#define _HUMI_LED_H_#define blue_led_ON	  1#define blue_led_OFF  0typedef struct
{_Bool blue_led_Status;} HUMI_ALARM_INFO;extern HUMI_ALARM_INFO humi_info;void humi_led_Init(void);
void humi_led_Set(_Bool status);#endif
main.c
#include "stm32f10x.h"                  // Device header
#include "sys.h"
#include "delay.h"
#include "dht11.h"
#include "OLED.h"#include "humi_led.h"
#include "temp_led.h"uint8_t temp;	//读取的环境温度
uint8_t humi;	//读取的环境湿度uint8_t temp_th;	//设置的温度阈值
uint8_t humi_th;	//设置的湿度阈值_Bool red_led;	//(温度指示灯)_Bool blue_led;	//(湿度指示灯)_Bool set_limit;	//管理员是否设置阈值led小灯初始化
//void led_init(void);int main()
{unsigned short timeCount = 0;	//发送间隔变量//手动设置环境温度(模拟上帝)temp = 66;	//温度是28度humi = 60;	//湿度是60%	//手动设置阈值(代替远程)temp_th = 30;	//温度阈值是30度humi_th = 60;		//湿度阈值是60%//小灯状态初始化red_led = 0;blue_led = 0;   //测试变量: 管理设置阈值符号位set_limit = 1;
//	//小灯初始化
//	led_init();//滴答定时器Delay_Init();//dht11初始化DHT11_Init();
//	while(DHT11_Init())
//	{
		printf("DHT11 Error \r\n");
//		OLED_ShowString(0,48, "DHT11 Error", 8);
//		OLED_Update();	
//		DelayMs(2000);
//	}//oled初始化OLED_Init();humi_led_Init();temp_led_Init();while(1){//(1)设置环境信息阈值(手动输入代替远程控制)if(set_limit == 1){temp_th = 29;humi_th = 88;//设置完阈值就清零,下次不设置了, 直到set_limit被管理员置1//然后再次进入此功能函数里,进行设置阈值set_limit = 0;}//(2)读取环境信息 (手动输入代替器件读取)//if(过了100毫秒) 每隔100毫秒,读取一次, 保证实时性,减轻负担if(++timeCount >= 10){DHT11_Read_Data(&temp,&humi);
//			temp = 99;	//人手输入,代替器件,忽略底层,重视逻辑
//			humi = 99;	OLED_Clear();OLED_ShowChinese(0, 0, "温度");OLED_ShowChinese(0, 24, "湿度:");OLED_Printf(48,0,OLED_8X16,"%2d",temp);OLED_Printf(48,24,OLED_8X16,"%2d",humi);	OLED_ShowChinese(80,0 , "℃");OLED_ShowChinese(80,24 , "%");		OLED_Update();timeCount = 0; 	//从新计时`		}DelayXms(10);	//10*10 = 100ms//后面跟 1ms的延时, 我们一切从简,先留着//(3)每时每刻判断环境信息是否异常if(temp >= temp_th){//启动器件temp_led_Set(red_led_ON);}else	//同理,环境正常时候{     temp_led_Set(red_led_OFF);}      //判断湿度是否报警//每时每刻判断环境信息是否异常if(humi >= humi_th){humi_led_Set(blue_led_ON);//			if(blue_led == 0)	//如果是关闭状态则启动,开启则无操作
//			{
//				blue_led = 1; 
//				PBout(4) = 1;
//			}}else	//同理,环境正常时候{humi_led_Set(blue_led_OFF);
//			if(blue_led == 1)	//如果是开启状态则启动,关闭则无操作
//			{
//				blue_led = 0;
//				PBout(4) = 0;
//			}        }       }	}///**************************************************
//函数名: led_init
//功  能: 温湿度,烟雾浓度小灯初始化
//参  数: 无
//配置参数: PB3(温度) PB4(湿度) PB5(烟雾浓度)
//		  推挽输出
//		 小灯正极接io口, 负极接地
//返回值: 无
//**************************************************/
//void led_init(void)
//{
//	//初始化小灯 , PB3(温度) PB4(湿度) PB5(烟雾浓度)
//	GPIO_InitTypeDef GPIO_InitStructure;
//	//开启硬件时钟	PB5
//	/* GPIOD Periph clock enable */
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//	//开启AFIO时钟
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	//禁用JTAGD端口
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	
//   //配置 pB 3 4 5 GPIO工作模式(推挽输出)
//	/* Configure PD0 and PD2 in output pushpull mode */
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//	GPIO_Init(GPIOB, &GPIO_InitStructure);	//配置端口//	//控制端口寄存器GPIO输出电平
//	PBout(3) = 0;//temp_led
//	PBout(4) = 0;	//humi_led
	PBout(5) = 0;	//mq2_led	
//	
//}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com