基于51单片机的管道压力检测及泄露检测无线WiFi传输系统proteus仿真原理图PCB

该系统采用STC89C52单片机,结合LCD1602液晶实时显示压力信息,具备启动/停止检测、压力阈值设置功能。当压力超过预设阈值或检测到泄漏时,会触发声光报警,并显示泄漏位置。系统每2秒通过WIFI发送检测数据,使用DC002电源接口供电。
摘要由CSDN通过智能技术生成

功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示当前始端和末端压力,压力阈值
2.按键启动/停止管道压力和泄漏检测
3.按键可更改压力阈值
4.管道压力超过报警阈值时将声光报警,并在液晶上显示OVER
5.管道发生泄漏时将声光报警,并在液晶上显示距离上游多少米
6.每隔2秒向WIFI串口发送当前检测信息
7.采用DC002作为电源接口可直接输入5V给整个系统供电

原理图:
在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#include <reg52.h>
#include "main.h"

#define LENGTH 100 //管道长度m
#define RATE 100 //负压波传播速度m/s
#define FLUCTUATE 10 //0.01pa

unsigned char isNew;
unsigned int alarmWeight = 2000; //单位g
long initialWeight[2] = 0; //单位g
float objectWeight[2] = 0; //单位g //最大5
float lastObjectWeight[2] = 0; //单位g //最大5
float location = 0; //定位泄漏点位置
unsigned char timeCnt = 0; //10msj计数
bit dispFlag = 0; //液晶刷新标志
bit checkFlag = 0; //开启检测标志
bit sendDataFlag = 0; //无线发送数据标志
bit atFlag = 0; //命令/数据标志

enum {IDLE, WAITING, UPFIRST, DOWNFIRST}timeFlag; //空闲,等待,上游开始,下游开始
enum {NONE, LEAK, OVER}errorFlag; //无,泄漏,过压

//函数声明
void Timer0_Init(void); //定时器0初始化
void Timer1_Init(void); //定时器1初始化
void SendData(void); //串口发送数据
void Display(void); //显示函数
void KeyProcess(void); //按键处理
void RfreshData(void); //刷新数据
void Check(void); //检测管道泄漏
void Alarm(void); //报警
void UART_Init(void); //串口初始化
void UART_SendByte(unsigned char dat); //串口发送单字节数据
void UART_SendStr(unsigned char *s, unsigned char length); //发送定长度字符串

void main()
{
    // 初始化
    DelayS(1);
    DelayMs(20);
    //EEPROM52_Init();

    // 定时器初始化
    Timer0_Init();
    Timer1_Init();
    UART_Init();

    #ifndef _SIMULATION_ //仿真时无需发送命令
    UART_SendStr("AT+CIPMUX=1\r\n", 13); //打开多连接
	DelayS(1);
	UART_SendStr("AT+CIPSERVER=1,8080\r\n", 21); //建立服务 端口号为8080
	DelayS(1);
    #endif
    // 开机显示
    LCD_Init();
    LCD_DispStr(0, 0, "    Welcome!    ");

    initialWeight[0] = HX711_GetInitialWeight();
    initialWeight[1] = HX711_1_GetInitialWeight();
    LCD_Clear();

    while(1)
    {        
        RfreshData(); //刷新数据
        if (sendDataFlag == 1)
        {
            sendDataFlag = 0;
            SendData(); //发送数据
        }
        if (checkFlag == 1)
        {
            Check(); //检测
        }
        if (dispFlag == 1)
        {
            Display(); //显示

        }   
        KeyProcess(); //按键处理
    }
}

void RfreshData(void)
{
    EA = 0;
    objectWeight[0] = HX711_Read();
    objectWeight[1] = HX711_1_Read();
    EA = 1;
    objectWeight[0] = objectWeight[0] - initialWeight[0];
    objectWeight[1] = objectWeight[1] - initialWeight[1];

    objectWeight[0] = (objectWeight[0] * 10 / GAPVALUE); //计算真实值
    objectWeight[1] = (objectWeight[1] * 10 / GAPVALUE_1); //计算真实值
    
}

void Check(void)
{
    if (objectWeight[0] > alarmWeight || objectWeight[1] > alarmWeight) //检测到压力过高
    {
        errorFlag = OVER;
        Alarm();
    }

    if (timeFlag == WAITING) 
    {
        if (objectWeight[0] > (lastObjectWeight[0] + FLUCTUATE) || objectWeight[0] < (lastObjectWeight[0] - FLUCTUATE)) //检测到上游压力波动大于FLUCTUATE
        {
            timeFlag = UPFIRST;
            timeCnt = 0;
            TH1 = 0xDC; //10ms
            TL1 = 0x00;
            TR1 = 1; //开启计时
        }
        
        if (objectWeight[1] > (lastObjectWeight[1] + FLUCTUATE) || objectWeight[1] < (lastObjectWeight[1] - FLUCTUATE)) //检测到下游压力波动大于FLUCTUATE
        {
            timeFlag = DOWNFIRST;
            timeCnt = 0;
            TH1 = 0xDC; //10ms
            TL1 = 0x00;
            TR1 = 1; //开启计时
        }
    }
    
    if (timeFlag == UPFIRST) //上游已检测到压力波动
    {
        if (objectWeight[1] > (lastObjectWeight[1] + FLUCTUATE) || objectWeight[1] < (lastObjectWeight[1] - FLUCTUATE)) //检测到下游压力波动大于FLUCTUATE
        {
            timeFlag = IDLE;
            TR1 = 0; //停止计时
            if (timeCnt >= 100) //大于100ms则为误判
            {
                timeFlag = 0;
                timeCnt = 0;
            }
            else
            {
                errorFlag = LEAK;
                location = LENGTH / 2 - (RATE * (timeCnt * 10 + ((unsigned int)(TH1 - 0xDC) << 8 + TL1) / 1000) / 1000) / 2;
                Alarm();
            }
        }
    }
    
    if (timeFlag == DOWNFIRST) //下游已检测到压力波动
    {
        if (objectWeight[0] > (lastObjectWeight[0] + FLUCTUATE) || objectWeight[0] < (lastObjectWeight[0] - FLUCTUATE)) //检测到上游压力波动大于FLUCTUATE
        {
            timeFlag = IDLE;
            TR1 = 0; //停止计时
            if (timeCnt >= 100) //大于100ms则为误判
            {
                timeFlag = WAITING;
                timeCnt = 0;
            }
            else
            {
                errorFlag = LEAK;
                location = LENGTH / 2 + (RATE * (timeCnt * 10 + ((unsigned int)(TH1 - 0xDC) << 8 + TL1) / 1000) / 1000) / 2;
                Alarm();
            }
        }
    }
    lastObjectWeight[0] = objectWeight[0]; //保留前一次测试值
    lastObjectWeight[1] = objectWeight[1]; //保留前一次测试值
}

void Display(void)
{
    unsigned char dispRow[16];

    sprintf(dispRow, "A:%5.2f B:%5.2f", objectWeight[0] / 1000, objectWeight[1] / 1000);
    LCD_DispStr(0, 0, dispRow);

    sprintf(dispRow, "S:%5.2fPa", (float)alarmWeight / 1000);
    LCD_DispStr(0, 1, dispRow);

    if (errorFlag == OVER)
    {
        LCD_DispStr(10, 1, " OVER!");
    }
    else if (errorFlag == LEAK)
    {
        sprintf(dispRow, "%5.2fm", (float)location);
        LCD_DispStr(10, 1, dispRow);
    }
    else
    {
        if (checkFlag == 1)
        {
            LCD_DispStr(10, 1, "Check!");
        }
        else
        {
            LCD_DispStr(10, 1, " IDLE ");
        }
    }

}

void SendData(void)
{
    unsigned char dispRow[16];
    
    if (atFlag == 1)
    {
        #ifndef _SIMULATION_ //仿真时无需发送命令
        UART_SendStr("AT+CIPSEND=0,36\r\n", 18); //命令
        #endif
        atFlag = 0;
    }
    else
    {
        sprintf(dispRow, "A:%5.2f B:%5.2f", objectWeight[0] / 1000, objectWeight[1] / 1000);
        UART_SendStr(dispRow, 16); //发送内容
        UART_SendStr("\r\n", 2);
        if (errorFlag == OVER)
        {
            sprintf(dispRow, "S:%5.2fPa  OVER!", (float)alarmWeight / 1000);
            UART_SendStr(dispRow, 16); //发送内容
        }
        else if (errorFlag == LEAK)
        {
            sprintf(dispRow, "S:%5.2fPa %5.2fm", (float)alarmWeight / 1000, (float)location);
            UART_SendStr(dispRow, 16); //发送内容
        }
        else
        {
            if (checkFlag == 0)
            {
                sprintf(dispRow, "S:%5.2fPa  IDLE ", (float)alarmWeight / 1000);
            }
            else
            {
                sprintf(dispRow, "S:%5.2fPa Check!", (float)alarmWeight / 1000);
            }
            UART_SendStr(dispRow, 16); //发送内容
        }
        UART_SendStr("\r\n", 2);
        atFlag = 1;
    }
}

void Alarm(void)
{
    checkFlag = 0;
    timeFlag = IDLE;
    LED_GREEN = 1;
    LED_RED = 0;
    BUZZER = 0;
}

void KeyProcess(void)
{
    if (!KEY_RIGHT) //开启检查
    {
        DelayMs(100);
        if (!KEY_RIGHT)
        {
            checkFlag = ~checkFlag;
            if (checkFlag == 1)
            {
                timeFlag = WAITING;
                errorFlag = NONE;
                lastObjectWeight[0] = objectWeight[0]; //保留前一次测试值
                lastObjectWeight[1] = objectWeight[1]; //保留前一次测试值
                TH1 = 0xDC;                            //10ms
                TL1 = 0x00;
                timeCnt = 0;
                location = 0;
                LED_GREEN = 0;
                LED_RED = 1;
                BUZZER = 1; //关闭报警
            }
            else
            {
                timeFlag = IDLE;
                errorFlag = NONE;
                BUZZER = 1; //关闭报警
                LED_RED = 1;
                LED_GREEN = 1;
            }
        }
        while(!KEY_RIGHT);
    }

    if (!KEY_UP) //按键加
    {
        DelayMs(160);
        if (!KEY_UP)
        {
            alarmWeight = alarmWeight + 10;
            if (alarmWeight > 5000)
            {
                alarmWeight = 5000;
            }
            // EEPROM52_Write();
        }
    }

    if (!KEY_DOWN) //按键减
    {
        DelayMs(160);
        if (!KEY_DOWN)
        {
            alarmWeight = alarmWeight - 10;
            if (alarmWeight <= 0)
            {
                alarmWeight = 0;
            }
            // EEPROM52_Write();
        }
    }
    
}

void Timer0_Init(void)
{
    TMOD &= 0xF0; //Timer0 16位装载
    TMOD |= 0x01;
    TH0 = RH_10MS(5); //50ms
    TL0 = RL_10MS(5);
    TR0 = 1; //启动T0计时
    ET0 = 1; //打开T0中断
    EA = 1;  //打开总中断
}

void Timer0_Intterupt(void) interrupt 1
{
    static unsigned int cnt=0;

    TH0 = RH_10MS(5); //50ms
    TL0 = RL_10MS(5);

    cnt++;
    if (cnt % 2 == 0) //100ms
    {
        dispFlag = ~dispFlag; //每100ms刷新一次屏幕
    }

    if (cnt >= 20)
    {
        sendDataFlag = 1; //每1s发送一次数据
        cnt = 0;
    }
}

void Timer1_Init(void)
{
    TMOD &= 0x0F; //Timer1 16位装载
    TMOD |= 0x10;
    TH1 = 0xDC; //10ms
    TL1 = 0x00;
    TR1 = 0; //停止T1计时
    ET1 = 1; //打开T1中断
    EA = 1;  //打开总中断
}

void Timer1_Intterupt(void) interrupt 3
{

    TH1 = 0xDC; //10ms
    TL1 = 0x00;

    if (timeCnt<100)
    {
        timeCnt++;
    }
}


void UART_Init(void)
{
    SCON = 0x50;
    TH2 = 0xFF;
    TL2 = 0xFD;
    RCAP2H = 0xFF; //(65536-(FOSC/32/BAUD))   BAUD = 115200 FOSC = 11059200
    RCAP2L = 0xFD;

    /*****************/
    TCLK = 1;
    RCLK = 1;
    C_T2 = 0;
    EXEN2 = 0;

    /*****************/
    TR2 = 1;
    ES = 1; //打开串口中断
    EA = 1; //打开总中断
}

void UART_SendByte(unsigned char dat) //串口发送单字节数据
{
	unsigned char time_out;
	time_out = 0x00;
	SBUF = dat;						  //将数据放入SBUF中
	while ((!TI) && (time_out < 100)) //检测是否发送出去
	{
		time_out++;
		DelayUs10x(2);
	}		//未发送出去 进行短暂延时
	TI = 0; //清除ti标志
}

void UART_SendStr(unsigned char *s, unsigned char length) //发送定长度字符串
{
	unsigned char num;
	num = 0x00;
	while (num < length) //发送长度对比
	{
		UART_SendByte(*s); //放松单字节数据
		s++;			  //指针++
		num++;			  //下一个++
	}
}

void UART_Interrupt(void) interrupt 4 //串行中断服务程序
{
	if (RI) //判断是接收中断产生
	{
		RI = 0; //标志位清零
	}
}

仿真演示视频:
https://www.bilibili.com/video/BV1SP4y1F7Lc/

实物演示视频:
https://www.bilibili.com/video/BV1MG4y1p7k6/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值