基于STM32的智能鱼缸控制系统的Proteus仿真

文章目录

  • 一、智能鱼缸控制系统
    • 1.题目要求
    • 2.思路
      • [2.1 主控](#2.1 主控)
      • [2.2 传感器](#2.2 传感器)
      • [2.3 按键](#2.3 按键)
      • [2.4 声光报警](#2.4 声光报警)
      • [2.5 自动换水,喂食,供氧](#2.5 自动换水,喂食,供氧)
      • [2.6 OLED显示](#2.6 OLED显示)
      • [2.7 电源部分](#2.7 电源部分)
      • [2.8 远程终端](#2.8 远程终端)
    • 3.电路仿真
      • [3.1 未仿真时](#3.1 未仿真时)
      • [3.2 开始仿真,正常显示](#3.2 开始仿真,正常显示)
      • [3.3 按下设置按键,进入阈值界面](#3.3 按下设置按键,进入阈值界面)
      • [3.4 通过阈值加减按键控制阈值大小](#3.4 通过阈值加减按键控制阈值大小)
      • [3.5 温度大于温度阈值,声光报警](#3.5 温度大于温度阈值,声光报警)
      • [3.6 远程终端设置阈值和换水时间,喂食时间](#3.6 远程终端设置阈值和换水时间,喂食时间)
    • 4.仿真程序
      • [4.1 程序说明](#4.1 程序说明)
      • [4.2 主程序](#4.2 主程序)
      • [4.3 OLED显示函数](#4.3 OLED显示函数)
      • [4.4 按键扫描函数](#4.4 按键扫描函数)
  • 二、总结


一、智能鱼缸控制系统

1.题目要求

1、检测温度、水位、PH值、浑浊度;

2、按键设定阈值,高于阈值,声光报警;

3、OLED双界面显示,第一界面正常显示温度等,第二界面显示阈值,可通过按键切换返回;

4、自动换水,自动喂食,自动供氧;

5、手机端设置各个阈值,换水时间和喂食时间。

2.思路

2.1 主控

由系统框图可知我们需要一个单片机,这里首选还是STM32。因为有好几个传感器在Proteus仿真里面是没有的,得用滑动变阻器模拟,到时候就需要用到AD外设。

2.2 传感器

温度传感器Proteus仿真里面有常用的温度传感器DS18B20和温湿度传感器DHT11,这里选择DS18B20.

剩下的水位传感器,PH传感器,浑浊度传感器用滑动变阻器去模拟。

2.3 按键

因为显示有两个界面和多个阈值,所以这边设定4个按键来切换。

按键一(设置按键):初始正常显示界面,按下进入阈值界面,阈值界面有4个阈值,再次按下选择下一个阈值,依次类推;

按键二(阈值加按键):除PH值阈值是+0.1(规定阈值范围:1.0-9.9),其他三者都是+1(规定阈值范围:10-99)

按键三(阈值减按键):除PH值阈值是-0.1(规定阈值范围:1.0-9.9),其他三者都是-1(规定阈值范围:10-99)

按键一(返回按键):按一下退出设置阈值界面,返回初始正常显示界面。

2.4 声光报警

2.5 自动换水,喂食,供氧

2.6 OLED显示

OLED显示温度、水位、PH、浊度,要显示中文,这需要用到取模软件,如下所示:

参数设置为:

2.7 电源部分

2.8 远程终端

手机端设置各个阈值,换水时间和喂食时间。

3.电路仿真

3.1 未仿真时

3.2 开始仿真,正常显示

OLED显示正常温度,水位,PH值,浊度的值,因为是鱼缸,默认是一直供氧的,喂食和进水默认时间是3s,也就是前3s进水,后3s出水,前3s喂食,后3s不喂食,换水时间和喂食时间都是可以通过远程终端去设置的。

3.3 按下设置按键,进入阈值界面

3.4 通过阈值加减按键控制阈值大小

3.5 温度大于温度阈值,声光报警

3.6 远程终端设置阈值和换水时间,喂食时间

具体协议见下面的仿真程序说明

4.仿真程序

4.1 程序说明

主控芯片:STM32F103C8

HICK:64MHZ

Systick: 1ms

水位传感器:ADC1(PA0)

PH传感器:ADC2(PA1)

浑浊度传感器:ADC2(PA1)

DS18B20温度传感器:DAT(PA4)

模拟Wifi模块(Uart1):9600(PA9:tx1,PA10:rx1)

模拟进水:Into(PA12)

模拟出水:Out(PA13)

模拟喂食:Feed(PA14)

模拟进水:Breath(PA15)

KEY按键:

KEY1(PB0)

KEY2(PB1)

KEY3(PB2)

KEY3(PB3)

时钟模块DS1302:

SCLK(PB5)

IO(PB6)

RST(PB7)

风扇:FAN(PB10)

OLED显示屏:SCL(PB12),SDA(PB13)

蜂鸣器:BUZZER(PB15)

串口协议

设置温度阈值TH1HH,HH取值范围为(10-99),如 TH150,即设置温度阈值为50.

设置水位阈值TH2HH,HH取值范围为(10-99)
设置PH阈值
TH3HH,HH取值范围为(1.0-9.9)

设置浊度阈值*TH4HH,HH取值范围为(10-99)

设置换水时间TM1HH,HH取值范围为(1-99)秒
设置喂食时间
TM2HH,HH取值范围为(1-99)秒

4.2 主程序

c 复制代码
/* Includes ------------------------------------------------------------------*/
#include "Drv_UserSystem.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
	UserSystemInit();//用户配置初始化		
	while (1)
	{			
		if (stSysTime.flg._100ms + TEN_MILLISECOND < Time_millis()) //10ms
		{
			stSysTime.flg._10ms = Time_millis();
			Key_Scan();//按键扫描						
		}
		if (stSysTime.flg._50ms + FIFTY_MILLISECOND < Time_millis()) //50ms
		{
			stSysTime.flg._50ms = Time_millis();						
			ADC_Scan();	//检测							
		}				
		if(stSysTime.flg._100ms + BEST_MILLISECOND < Time_millis()) //100ms
		{
			stSysTime.flg._100ms = Time_millis();					
			Receive_data_Handel();//数据接收判断 			
			Warning_function();//预警							
			OLED_Handel();//OLED显示								
			IWDG_ReloadCounter();//清开门狗 				
		}
		if (stSysTime.flg._1s + THOUSAND_MILLISECOND < Time_millis()) //1s
		{
			stSysTime.flg._1s = Time_millis();	
            timer_task();//时间任务			
		}
  }
}

4.3 OLED显示函数

c 复制代码
/*******************************************************************************
 * 函数名:OLED_Handel
 * 描述  :OLED显示
 * 输入  :void
 * 输出  :void
 * 调用  :初始化
 * 备注  :100ms
*******************************************************************************/
void OLED_Handel(void)
{  	
   if(ADC_Flag)
	 {
		if(Interface_switching == 0) 
		{		
				OLED_Show_Character(1,1,0,16);//温
				OLED_Show_Character(1,2,1,16);//度	
				OLED_Show_Character(1,3,2,16);//:	 			
			
				temperature = DS18B20_Get_Temp();
				temperature = (-1) * temperature;
		 
//				printf("temperature=%d\r\n",temperature);	 
			 
				Temp_High = temperature / 10;
				if(Temp_High < 10)
				{
					if(Temperature_jump == 1)
					{
							Temperature_jump = 0;
							OLED_Part_Clear(1,8,9);
					}
					OLED_ShowNum(1,10,Temp_High,1);			
				}
				else
				{
					Temperature_jump = 1;
					OLED_ShowNum(1,9,Temp_High,2);				
				}
				
		    if(Temp_High > Temp_Threshold)
				{
		        Warning1 = 1;					
				}
				else
				{
		        Warning1 = 0;							
				}				
				
				Temp_Low = temperature % 10;
				OLED_ShowNum(1,12,Temp_Low,1);
				OLED_ShowString(1, 11, ".");	
				OLED_Show_Character(1,7,3,16);	
				OLED_ShowString(1, 15, "C");		

				OLED_Show_Character(2,1,4,16);//水
				OLED_Show_Character(2,2,5,16);//位
				OLED_Show_Character(2,3,2,16);//:		

		    if(ADC1_Value > ADC1_Threshold)
				{
		        Warning2 = 1;					
				}
				else
				{
		        Warning2 = 0;							
				}

			  if(ADC1_Value < 10)
				{
						OLED_Part_Clear(2,8,9);					
				    OLED_ShowNum(2,10,ADC1_Value,1);						
				}
				else
				{					
				    OLED_ShowNum(2,9,ADC1_Value,2);	
				}	

				OLED_ShowString(3, 1, "PH");	
				OLED_Show_Character(3,2,9,16);//值
				OLED_Show_Character(3,3,2,16);//:	

		    if(ADC2_Value > ADC2_Threshold)
				{
		        Warning3 = 1;					
				}
				else
				{
		        Warning3 = 0;							
				}

				OLED_ShowNum(3,9,ADC2_High,1);						
				OLED_ShowString(3, 10, ".");		
				OLED_ShowNum(3,11,ADC2_Low,1);														

				OLED_Show_Character(4,1,6,16);//浊
				OLED_Show_Character(4,2,7,16);//度
				OLED_Show_Character(4,3,2,16);//:		

		    if(ADC3_Value > ADC3_Threshold)
				{
		        Warning4 = 1;					
				}
				else
				{
		        Warning4 = 0;							
				}

			  if(ADC3_Value < 10)
				{
						OLED_Part_Clear(4,8,9);					
				    OLED_ShowNum(4,10,ADC3_Value,1);						
				}
				else
				{					
				    OLED_ShowNum(4,9,ADC3_Value,2);	
				}				
		}
    else
		{
				if(Interface_switching == 1)
				{
					OLED_Show_Character(1,8,10,16);//←					
				}
				else if(Interface_switching == 2)
				{
					OLED_Show_Character(2,8,10,16);//←							
				}
				else if(Interface_switching == 3)
				{
					OLED_Show_Character(3,8,10,16);//←							
				}				
				else if(Interface_switching == 4)
				{
					OLED_Show_Character(4,8,10,16);//←							
				}				
			
				OLED_Show_Character(1,1,0,16);//温
				OLED_Show_Character(1,2,1,16);//度	
				OLED_Show_Character(1,3,8,16);//阈
				OLED_Show_Character(1,4,9,16);//值				
				OLED_Show_Character(1,5,2,16);//:		

				OLED_ShowNum(1,12,Temp_Threshold,2);	

				OLED_Show_Character(2,1,4,16);//水
				OLED_Show_Character(2,2,5,16);//位
				OLED_Show_Character(2,3,8,16);//阈
				OLED_Show_Character(2,4,9,16);//值				
				OLED_Show_Character(2,5,2,16);//:			

				OLED_ShowNum(2,12,ADC1_Threshold,2);	
			
				OLED_ShowString(3, 1, "PH");	
				OLED_Show_Character(3,2,8,16);//阈			
				OLED_Show_Character(3,3,9,16);//值
				OLED_Show_Character(3,4,2,16);//:	
			
				OLED_ShowNum(3,12,ADC2_ThresholdHigh,1);						
				OLED_ShowString(3, 13, ".");		
				OLED_ShowNum(3,14,ADC2_ThresholdLow,1);	

				OLED_Show_Character(4,1,6,16);//浊
				OLED_Show_Character(4,2,7,16);//度
				OLED_Show_Character(4,3,8,16);//阈
				OLED_Show_Character(4,4,9,16);//值					
				OLED_Show_Character(4,5,2,16);//:		

				OLED_ShowNum(4,12,ADC3_Threshold,2);				
		}		
	}		
}

4.4 按键扫描函数

c 复制代码
/*******************************************************************************
 * 函数名:Key_Scan
 * 描述  :按键扫描
 * 输入  :void
 * 输出  :void
 * 调用  :10ms
 * 备注  :
 *******************************************************************************/
void Key_Scan(void)
{				
		if(Key1_IN_Read() == 0)//key1
		{
			KeyState.value1 = 1;
			if(!KeyState.Press1)
			{			
				  if(Interface_switching == 0)
					{
					    OLED_Clear();							
					}
				  Interface_switching++;					
				  if(Interface_switching > 4)
					{
						Interface_switching = 1;
					}
					if(Interface_switching == 2)
					{
							OLED_Part_Clear(1,15,16);						
					}
					else if(Interface_switching == 3)
					{
							OLED_Part_Clear(2,15,16);							
					}
					else if(Interface_switching == 4)
					{
							OLED_Part_Clear(3,15,16);							
					}
					else if(Interface_switching == 1)
					{
							OLED_Part_Clear(4,15,16);							
					}					
					printf("按键1按下 \r\n");					
			}
			KeyState.Press1 = 1;					
		}		
		else
		{		
			if(KeyState.value1)
			{
					KeyState.value1= 0;
					printf("按键1松开 \r\n");									
			}
			KeyState.Press1 = 0;
		}		
		
		if(Key2_IN_Read() == 0)//key2
		{
			KeyState.value2 = 1;
			if(!KeyState.Press2)
			{						
				  if(Interface_switching == 1)
					{		
						Temp_Threshold++;
						if(Temp_Threshold > 98)
						{
							Temp_Threshold = 99;					
						}						
					}
					else if(Interface_switching == 2)
					{
						ADC1_Threshold++;
						if(ADC1_Threshold > 98)
						{
							ADC1_Threshold = 99;					
						}												
					}				
					else if(Interface_switching == 3)
					{
						ADC2_Threshold++;
						if(ADC2_Threshold > 98)
						{
							ADC2_Threshold = 99;					
						}		
						ADC2_ThresholdHigh = ADC2_Threshold/10;
						ADC2_ThresholdLow = ADC2_Threshold%10;								
					}	
					else if(Interface_switching == 4)
					{
						ADC3_Threshold++;
						if(ADC3_Threshold > 98)
						{
							ADC3_Threshold = 99;					
						}						
					}						
					printf("按键2按下 \r\n");						
			}
			KeyState.Press2 = 1;
		}		
		else
		{		
			if(KeyState.value2)
			{
					KeyState.value2= 0;
					printf("按键2松开 \r\n");								
			}					
			KeyState.Press2 = 0;
		}	

		if(Key3_IN_Read() == 0)//key3
		{
			KeyState.value3 = 1;					
			if(!KeyState.Press3)
			{					
				  if(Interface_switching == 1)
					{
						if(Temp_Threshold < 11)
						{
							Temp_Threshold = 10;					
						}
						else
						{
							Temp_Threshold--;
						}						
					}
					else if(Interface_switching == 2)
					{
						if(ADC1_Threshold < 11)
						{
							ADC1_Threshold = 10;					
						}
						else
						{
							ADC1_Threshold--;
						}							
					}				
					else if(Interface_switching == 3)
					{
						if(ADC2_Threshold < 11)
						{
							ADC2_Threshold = 10;					
						}
						else
						{
							ADC2_Threshold--;
						}	
						ADC2_ThresholdHigh = ADC2_Threshold/10;
						ADC2_ThresholdLow = ADC2_Threshold%10;							
					}	
					else if(Interface_switching == 4)
					{
						if(ADC3_Threshold < 11)
						{
							ADC3_Threshold = 10;					
						}
						else
						{
							ADC3_Threshold--;
						}							
					}							
					printf("按键3按下 \r\n");						
			}
			KeyState.Press3 = 1;
		}		
		else
		{		
			if(KeyState.value3)
			{
					KeyState.value3= 0;
					printf("按键3松开 \r\n");									
			}						
			KeyState.Press3 = 0;
		}	

		if(Key4_IN_Read() == 0)//key4
		{
			KeyState.value4 = 1;					
			if(!KeyState.Press4)
			{			
				  if(Interface_switching != 0)
					{
					    OLED_Clear();	 
  						Interface_switching = 0;							
					}						
					printf("按键4按下 \r\n");						
			}
			KeyState.Press4 = 1;
		}		
		else
		{		
			if(KeyState.value4)
			{
					KeyState.value4= 0;
					printf("按键4松开 \r\n");									
			}						
			KeyState.Press4 = 0;
		}			
}

二、总结

今天主要讲了基于STM32的智能鱼缸控制系统的Proteus仿真。

感谢你的观看!

相关推荐
DS小龙哥9 分钟前
基于STM32设计的仓库环境监测与预警系统
stm32·单片机·嵌入式硬件
0X781 小时前
HC-SR04(超声波)应急使用方案
stm32·单片机
深圳市青牛科技实业有限公司 小芋圆5 小时前
GC8872 是一款带故障报告功能的刷式直流电机驱动芯片, 适用于打印机、电器、工业设备以及其他小型机器。
人工智能·科技·stm32·单片机·嵌入式硬件·机器人
可喜~可乐7 小时前
CAN总线入门指南:从原理到实践
c++·stm32·单片机·硬件工程
冰糖雪莲IO10 小时前
【江协STM32】9-4/5 USART串口数据包、串口收发HEX数据包&串口收发文本数据包
网络·stm32·嵌入式硬件
无聊到发博客的菜鸟10 小时前
STM32中的MCO
stm32·单片机·嵌入式硬件
Echo_cy_10 小时前
STM32 I2C通信外设
stm32·单片机·嵌入式硬件
半个番茄10 小时前
STM32 : PWM 基本结构
stm32·单片机·嵌入式硬件
小猪写代码10 小时前
STM32 拓展 RTC案例1:使用闹钟唤醒待机模式 (HAL库)
stm32·嵌入式硬件·实时音视频
qq_4597300312 小时前
STM32-ADC模数转换
stm32·单片机·嵌入式硬件