基于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仿真。

感谢你的观看!

相关推荐
小A1599 分钟前
STM32完全学习——使用标准库完成定时器中断
stm32·单片机·学习
美式小田14 分钟前
单片机学习笔记 10. 中断系统(理论)
笔记·单片机·嵌入式硬件·学习
我不是码农 嘤嘤嘤23 分钟前
单片机GPIO的8种工作模式
单片机·嵌入式硬件
相醉为友1 小时前
006 单片机嵌入式中的C语言与代码风格规范——常识
c语言·单片机·嵌入式硬件
电子绿洲3 小时前
低温存储开关机问题
嵌入式硬件·学习·硬件工程·信息与通信·智能硬件
电子绿洲3 小时前
10M和100M网口的编码及EMC影响
嵌入式硬件·学习·硬件工程·信息与通信·智能硬件
好想有猫猫4 小时前
【STM32】GPIO(超详细)
驱动开发·stm32·单片机·嵌入式硬件·51单片机
霖霖7144 小时前
MPU6050
stm32·单片机·算法
北京迅为12 小时前
【北京迅为】iTOP-4412全能版使用手册- 第五章 Linux常用命令
linux·嵌入式硬件·4412开发板