基于51单片机控制恒压供水系统设计


前言

💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗
👇🏻 精彩专栏 推荐订阅👇🏻
单片机设计精品实战案例
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人

资料获取

文章底部名片,详细资料联系我。

设计介绍

恒压供水系统是指用户端不管用水量大小,总保持管网中水压基本恒定。这样,既可满足各部位的用户对用水量的需求。又不会产生电动机空转,造成电能的浪费。为实现上述目标,需要变频器根据给定压力信号和反馈压力信号,调节水泵转速,从而达到控制管网中水压恒定的目的。一般的恒压供水系统是由单片机、变频器、压力传感器等器件组成的压力闭环控制系统。其原理是将压力变成模拟信号,经过一系列的转换最终调解水泵的转速,按实际用水量供水并使压力恒定。随着社会的发展,水在人们生活中越来越重要,随之便是科技的成果——恒压供水系统。现在很多地方面临水资源短缺,水污染严重的威胁,且不同时段对供水压力要求不一,单靠水厂人员根据往常经验进行手动调节很难处理供水问题。但现在国内的一些恒压供水系统存在很多缺点如下:
(1)耗能大,浪费水电资源;
(2)水压不稳,容易发生事故;
(3)供水质量差,影响人体健康;
(4)运行效率低,很难满足供水需求;
(5)自动化程度低,操作麻烦;
因此研究设计恒压供水系统显得非常重要。

功能介绍

了解基于单片机的恒压供水系统的运作,优缺点;对其发展趋势进行认识,为研发生产新型供水系统作好准备。毕业设计的具体内容:
(1)设计通过压力传感器、控制器和变频器组成闭环回路自动调节电机的转速,从而调节水泵 的供水量,确保供水压力恒定。
(2)设计以单片机为主控制器,系统通过压力传感器对压力进行采集,经过A/D转换送入主控制器,变频器控制电机水泵机组。
(3)系统能够实时显示水管的压力值、变频器的频率和各水泵工作的时间及控制参数。
(4)设计键盘模块要求能输入任意设定值。结合上述课题研究的主要内容,预期通过压力传感器,控制器和变频器组成闭环回来路来控制电机水泵组来实现恒压供水,并用显示管显示水管的一些数据。

设计通过控制变频器的输出频率从而自动调节水泵电机的转速,实现管网水压的闭环调节, 使供水系统自动恒压值稳于设定的压力值。

用户可以自行设定水管中的水压,低功耗低噪音高性能高寿命的特点使得本设计在同类产品中脱颖而出。

设计程序

#include <reg52.h>
/*---------------宏定义-----------------*/
#define uint unsigned int 
#define uchar unsigned char
#define PWM_CYC		50		//PWM周期
#define AUTO_SPEED   2000   //数字越大越慢
#define delay(x) {uint i,j;for(i = x;i>0;i--)for(j=50;j>0;j--);}
#define THC0  ((65536 - 10000)/256)			//10ms定时器定时值   
#define TLC0  ((65536 - 10000)%256)
/*--------------引脚定义-----------------*/
/* AD0809引脚 */
sbit OE  = P3^7;
sbit EOC = P3^6;
sbit ST  = P3^5;
sbit CLK = P3^4;
sbit ALE = P3^3;
#define ADCV    P1
/* lcd016 引脚 */
sbit RS = P2^0;
sbit RW = P2^1;
sbit E  = P2^2;
#define LCDData  P0
/* 按键 */
sbit BTN_UP = P2^3;
sbit BTN_DN = P2^4;
sbit BTN_AUTO = P2^5;
/* 电机PWM脚 */
sbit PWM    = P2^7;
/* LED */
sbit LED   = P2^6;
/*---------------全局变量----------------*/
const uchar display1[] = "set pressure    ";
const uchar display2[] = "cur pressure    ";
uchar water_vol=0;		//水压
uchar set_vol = 150;		//设置压力
uchar motor_speed = 6; //电机速度
uchar auto_flag = 0;
/*---------------全局函数----------------*/
void LCD_init();												//LCD初使化
void Display(uchar setv,uchar waterv);  //显示程序
uchar Get_WaterV(void);									//水压获取
void Moter_Drive(void);									//电机驱动
void SetVol_UP(void);										//设定压力加
void SetVol_DN(void);										//设定压力减
void SetMotorSpeed(void);								//电机速度设置
void Key_Scan(void);										//按键扫描
void AutoSpeed(void);										//自动模式
void SetVol_AUTO(void);									//手动 自动 切换
/*---------------------------------
* 函数:SysTemInit 初使化
*----------------------------------*/
void SysTemInit(void)
{
	TMOD = 0x02;		//定时器0 采用16位定时器
	TH0 = THC0;			//设定定时值
	TL0 = TLC0;
	ET0 = 1;				//定时器T0 溢出中断允许
	TR0 = 1;				//启动定时器0
	EA = 1;					//中断总开关开
	LED = 0;
}
/*---------------------------------
* 函数:main 程序主入口
*----------------------------------*/
void main(void)
{
	static char showcount=0;
	PWM = 0;
	SysTemInit();
	LCD_init();
	for(;;)
	{
		Moter_Drive();				//PWM驱动电机		
		if(auto_flag==0)water_vol = Get_WaterV();    //手动模式时获取水压
		else AutoSpeed();				
		showcount++;
		Key_Scan();							//扫描按键、
		if(showcount == 100)			
		{				
			Display(set_vol,water_vol);	 //显示				
			SetMotorSpeed();						 //调整速度
			showcount = 0;
		}
	}
}

/*---------------------------------
* 函数:time0 10ms定时器0中断入口  用于ADC时钟
*----------------------------------*/
void time0() interrupt 1
{
	CLK = ~CLK;
}
/*---------------------------------
* 函数:SetMotorSpeed 设置电机速度
*----------------------------------*/
void SetMotorSpeed(void)
{
	if(water_vol > set_vol)			//如果测到的水压大于设置压力
	{
		if(motor_speed > 4)motor_speed--;			//控制占空比增大 电机减速
	}
	else if(water_vol < set_vol)
	{
		if(motor_speed < 40) motor_speed ++; //控制占空比减小 电机增速
	}
}
/*---------------------------------
* 函数:AutoSpeed 自动速度
*----------------------------------*/
void AutoSpeed(void)
{
	static uint auto_speed = 0;    //自动的速度控制
	auto_speed ++;
	if(auto_speed == AUTO_SPEED)
	{
		if(water_vol > set_vol)			//如果测到的水压大于设置压力
		{
			water_vol--;			//控制占空比增大 电机减速
		}
		else if(water_vol < set_vol)
		{
			water_vol++; //控制占空比减小 电机增速
		}
		auto_speed = 0;
	}	
}
/*---------------------------------
* 函数:Key_Scan 按键扫描
*----------------------------------*/
void Key_Scan(void)
{
	static uchar keyupstate = 0;
	static uchar keydnstate = 0;
	static uchar keyupcount = 0;
	static uchar keydncount = 0;
	static uchar keyautostate = 0;
	static uchar keyautocount = 0;
		switch(keyupstate)					//按键加状态
	{
		case 0:
			if(BTN_UP == 0)      		//如果加键按下
			{
				keyupcount++;			 		//记录
				if(keyupcount>1)	 
				{
					keyupstate = 1;			//记录超过3次跳转到按下状态
					keyupcount = 0;
				}
			}
			else keyupcount = 0;				
			break;
		case 1:
			SetVol_UP();						//确认按键已按下运行一次
			keyupstate = 2;
			break;
		case 2:
			if(BTN_UP)				    	//按键松开恢复状态
			{
				keyupstate = 0;
				keyupcount = 0;				
			}
			break;
	}
	switch(keydnstate)					//按键减状态
	{
		case 0:
			if(BTN_DN == 0)      		//如果加键按下
			{
				keydncount++;			 		//记录
				if(keydncount>1)	 
				{
					keydnstate = 1;			//记录超过3次跳转到按下状态
					keydncount = 0;
				}
			}
			else keydncount = 0;				
			break;
		case 1:
			SetVol_DN();						//确认按键已按下运行一次
			keydnstate = 2;
			break;
		case 2:
			if(BTN_DN)				    	//按键松开恢复状态
			{
				keydnstate = 0;
				keydncount = 0;				
			}
			break;
	}
	
	switch(keyautostate)					//按键自动控制状态
	{
		case 0:
			if(BTN_AUTO == 0)      		//如果加键按下
			{
				keyautocount++;			 		//记录
				if(keyautocount>1)	 
				{
					keyautostate = 1;			//记录超过3次跳转到按下状态
					keyautocount = 0;
				}
			}
			else keyautocount = 0;				
			break;
		case 1:
			SetVol_AUTO();						//确认按键已按下运行一次
			keyautostate = 2;
			break;
		case 2:
			if(BTN_AUTO)				    	//按键松开恢复状态
			{
				keyautostate = 0;
				keyautocount = 0;				
			}
			break;
	}
}
/*---------------------------------
* 函数:SetVol_AUTO 自动手动切换
*----------------------------------*/
void SetVol_AUTO(void)
{
	if(auto_flag == 0) 
	{
		auto_flag = 1;
		LED = 1;
	}
	else
	{
		auto_flag = 0;
		LED = 0;
	}
}
/*---------------------------------
* 函数:SetVol_UP 压力加
*----------------------------------*/
void SetVol_UP(void)
{
	if(set_vol<255)		set_vol+=5;         //设置压力步进5	
}
/*---------------------------------
* 函数:SetVol_Dn 压力减
*----------------------------------*/
void SetVol_Dn(void)
{
	if(set_vol>0) set_vol-=5;							//设置压力步进5
}
/*---------------------------------
* 函数:Moter_Drive 电机驱动
* 参数:cmd  指令
*----------------------------------*/
void Moter_Drive(void)
{
	static uchar cnt = 0;	
	cnt++;
	if(cnt < motor_speed) PWM = 1;  //通过执行空语句来实现空占比
	else PWM = 0;
	if(cnt > PWM_CYC) cnt = 0;
}
/*---------------------------------
* 函数:Get_WaterV 获取水压
* 返回:滑动变阻器电压值 0-255 对应0-5V
*----------------------------------*/
uchar Get_WaterV(void)
{
	uchar vol = 0;  //定义一个变量来存储获取到的数值
	ST = OE = 0;   //关闭STE、OE通道
	ALE = 1;       //开放ALE通道
	ST = 1;		//启动START
	ALE = 0;	//关闭ALE通道
	ST = 0;		//关闭START
	while(EOC == 0);  //读取数值直到停止信号
	OE = 1;      //数据允许通道打开
	vol = ADCV;  //将获取到的数值赋值给全局变量ADCV
	return vol;
}
/*---------------------------------
* 函数:Write_cmd LCD写指令
* 参数:cmd  指令
*----------------------------------*/
void Write_cmd(uchar cmd)
{
	RS=0;
	RW=0;
	LCDData=cmd;
	delay(1);
	E=1;
	delay(1);
	E=0;
}
/*---------------------------------
* 函数:Write_data LCD写数据
* 参数:date  数据
*----------------------------------*/
void Write_data(uchar date)//
{
	RS=1;
	RW=0;
	LCDData=date;
	delay(1);	
	E=1;
	delay(1);
	E=0;
}
/*---------------------------------
* 函数:LCD_init LCD初使化
*----------------------------------*/
void LCD_init()
{
	E=0;
	Write_cmd(0x38); //16*2,5*7,8 位数据
	Write_cmd(0x0c); // 显示开,光标不显示,不闪烁
	Write_cmd(0x06); // 地址加1,光标加1,整屏不移动
	Write_cmd(0x80); // 地址初始
}
/*---------------------------------
* 函数:Display LCD显示
* 参数:setv  设置压力
*       waterv  当前水压
*----------------------------------*/
void Display(uchar setv,uchar waterv)
{
	uchar i;
	//Write_cmd(0x01); // 清屏
	for(i = 0;i < 17;i++)	 //显示第一行
	{
		Write_data(display1[i]);
	}
	Write_cmd(0x80+0x40);		 //显示第二行
	for(i = 0;i < 17;i++)
	{
		Write_data(display2[i]);
	}
	Write_cmd(0x80 + 13);						//第一行第13位开始显示设置压力
	Write_data(0x30 + setv/100);
	Write_data(0x30 + setv%100/10);
	Write_data(0x30 + setv%10);				
	Write_cmd(0x80 + 0x40 + 13);		//第二行第13位开始显示当前压力
	Write_data(0x30 + waterv/100);
	Write_data(0x30 + waterv%100/10);
	Write_data(0x30 + waterv%10);
	}


具体实现截图

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
在这里插入图片描述

文档目录

目录
1引 言 4
1.1 课题研究背景及意义 4
1.2 国内外研究现状 4
1.3 本课题主要研究内容 5
1.4 设计目标 5
2系统总体方案设计 6
2.1 硬件设计方案 6
2.2 软件设计方案 7
3恒压供水系统硬件设计 9
3.1 时钟模块设计 9
3.2 复位电路的设计 10
3.3 按键接口模块设计 11
3.4 转换模块(A/D)选型 11
3.5 显示模块设计及选型 16
3.6 电机控制设计及选型 17
3.7 稳压电源模块 17
4恒压供水系统软件设计 19
4.1 软件设计原理及设计所用工具 19
4.2 主程序流程图 19
4.3 按键扫描程序 20
4.4 获取水压程序 24
4.5 驱动电机程序 24
4.6 动态显示压力程序 26
4.7 系统测试仿真 29
结论 32
谢辞 33
参考文献 34
附 1 系统的原理电路图 35
附 2 系统的相关程序 36

设计获取

文章下方名片联系我即可~

精彩专栏推荐订阅:在下方专栏👇🏻

毕业设计精品实战案例

收藏关注不迷路!!

🌟文末获取设计🌟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值