基于STM32的智能鱼缸监控投喂系统设计与实现
基于STM32的智能鱼缸监控投喂系统设计与实现
这是一篇关于STM32智能鱼缸监控投喂系统的毕业设计项目分享。项目通过STM32单片机实现鱼缸的智能化管理,包括自动加水、放水、投食等功能,并通过WiFi模块实现远程监控和控制。文章详细介绍了项目的硬件设计、软件实现以及系统功能,具有较高的实用性和参考价值。
0 前言
近年来,毕业设计和毕业答辩的要求不断提高,传统的毕设题目往往缺乏创新和亮点,难以达到毕业答辩的要求。为了帮助同学们顺利完成毕业设计,本文分享一个基于STM32的智能鱼缸监控投喂系统项目。
学长对本项目进行综合评分如下(每项满分5分):
- 难度系数:3分
- 工作量:3分
- 创新点:4分
项目包含内容:
- 完整源代码
- 硬件设计图纸
- 详细设计论文
1 主要功能
本设计旨在实现鱼缸换水、投食、远程监控、实时数据显示和远程操控的一体化和智能化。具体功能包括:
- 自动加水:当水位过低时自动启动水泵,向鱼缸内自动加水
- 自动放水:当水位过高时启动放水阀(用继电器模拟),当水位达到标准时停止放水
- 换水启动:当监测到水质过于浑浊,自动开始放水,并触发自动加水逻辑
- 自动投食:每日固定时间投食(用继电器模拟)
- 状态显示:传感器数据实时显示于OLED屏上
- 远程交互:传感器数据通过WiFi模块远程上传到上位机客户端上
- 远程控制:上位机可通过WiFi模块,向单片机发送远程指令,控制其换水、投食
2 硬件设计(原理图)
3 核心软件设计
为了实现智能鱼缸的理想功能,需要对温度采集模块、OLED显示模块、继电器控制模块、按键控制模块、WiFi模块等进行模块化编程。主程序控制流程如下:
上位机部分设计:
上位机界面通过Python程序语言进行开发,通过无线传输数据的方式即可实现无线监控。当用户输入正确的IP地址以及指定端口登录后,后台系统开始运行。应用界面设计主要由Python应用程序完成,以连接STM32和ESP8266模块,使用适合的GUI框架,例如Tkinter,PyQt等。再设计主窗口的大小、标题、背景颜色等基本属性,并使用Tkinter提供的组件,诸如Frame、Label、Entry、Button等组件来构建界面,同时为相应的组件设置属性。在这个应用程序中,Label组件可以用于添加提示语句,Entry组件可以接受用户输入的串口号、波特率等参数,Button组件在设计时应该能够实现连接和断开操作等。在代码中,需要使用pySerial模块实现串口通信,来连接STM32和ESP8266模块。首先,需要导入pySerial模块,并通过串口的设定创建Serial对象,设置好相关参数,然后使用open()方法打开串口。构建和设置基本属性,通过pySerial模块实现串口通信的过程,连接STM32和ESP8266模块,并保证良好的用户交互和异常处理机制。连接通讯流程图如图
关键代码
#include"stm32.h"
uchar PageNum=0; //0显示温湿度 1显示温度和报警数值2显示湿度和报警数值
float Temp_Data=0;
uchar AlarmTemp[]={32,20}; //高低温度
unsigned char FeedTime[3]={0}; //喂食时间
unsigned char O2Time[3]={0}; //充氧气时间
unsigned char LoopTime[3]={0}; //水循环时间
sbit RELAY1 = P2^2; //加水继电器
sbit RELAY2 = P2^1; //加热继电器
sbit RELAY3 = P2^0; //放水继电器
sbit ENA=P3^2;
sbit ENB=P3^3;
void TimerInit(void);
void GetTemp(void);
void PageInit(void);
void PageDisplay(void);
void DataLoad(void); //数据加载
void TempInit(void); //
void HeatControl(void); //加热自动控制
void Timer1_Init(void); //50毫秒@11.0592MHz
void IncO2Control(void);
void FeedControl(void);
void LoopControl(void);
unsigned char FeedSecond=0;
unsigned char O2Second=0;
unsigned int LoopSecond=0;
unsigned char CountTime[3]={0}; //水循环时间计时
void main(void)
{
Delay_1ms(100);
LCD_Init();
TimerInit();
PageInit();
DataLoad();
TempInit();
Timer1_Init();
while(1)
{
GetTemp();
DS1302_Read();
FeedControl();
HeatControl();
IncO2Control();
PageDisplay();
LoopControl();
Delay_1ms(50);
}
}
void Timer0_Serve(void) interrupt 1
{
TH0 = (65535-20000)/256; //20MS定时
TL0 = (65535-20000)%256;
LCD_Refresh(); //LCD刷新
KEY_Scan();
}
void Timer1_Serve(void) interrupt 3 //50ms定时
{
static unsigned char T50MS=0;
TL1 = 0x00; //设置定时初值
TH1 = 0x4C; //设置定时初值
T50MS++;
if(T50MS>=20)
{
T50MS=0;
CountTime[2]++;
if(CountTime[2]>=60)
{
CountTime[2]=0;
CountTime[1]++;
if(CountTime[1]>=60)
{
CountTime[1]=0;
CountTime[0]++;
if(CountTime[0]>23)
CountTime[0]=0;
}
}
if(FeedSecond>0)
FeedSecond--;
if(O2Second>0)
O2Second--;
if(LoopSecond>0)
{
LoopSecond--;
}
}
}
void HeatControl(void) //加热控制
{
/*------------------低于下限开始加热---------------------*/
if(Temp_Data<AlarmTemp[1])
{
RELAY1=0;
}
/*------------------高于上限停止加热---------------------*/
if(Temp_Data>AlarmTemp[0])
{
RELAY1=1;
}
}
void TimerInit(void)
{
TMOD &= 0xF0;
TMOD |= 0X01; //T1工作在定时模式, T0 工作在8位自动重载计数
TL0 = (65535-20000) % 256; //T0工作在定时模式 50ms定时
TH0 = (65535-20000) / 256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
void PageDisplay(void)
{
/*---------------------------------------------------------*/
if(KeyVal=='E')
{
KeyVal=0;
PageNum++;
if(PageNum>4)
{
PageNum=0;
}
PageInit();
}
/*-------------------------------------------------------*/
switch(PageNum)
{
/*-------------------------------------------------------*/
case 0: //显示和设置实时时间
{
LCD_DisplayDate(0,Date);
LCD_DisplayTime(16,Time);
if(KeyVal=='S')
{
KeyVal = 0;
SetRTC();
}
}break;
/*-------------------------------------------------------*/
case 1: //显示实时温度和上下限值
{
TempDisplay(5,Temp_Data);
DisplayU8(18,AlarmTemp[0]); //
DisplayU8(26,AlarmTemp[1]); //
if(KeyVal=='S')
{
KeyVal=0;
SetTempHigLow(AlarmTemp);
WrToROM(AlarmTemp,5,2); //温度存储地址0
}
}break;
/*-------------------------------------------------------*/
case 2:
{
LCD_DisplayTime(16,FeedTime);
if(KeyVal=='S')
{
KeyVal=0;
SetClockTime(FeedTime);
WrToROM(FeedTime,20,3);
}
}break;
/*-------------------------------------------------------*/
case 3:
{
LCD_DisplayTime(16,O2Time);
if(KeyVal=='S')
{
KeyVal=0;
SetClockTime(O2Time);
WrToROM(O2Time,25,3);
}
}break;
/*-------------------------------------------------------*/
case 4:
{
LCD_DisplayTime(16,LoopTime);
if(KeyVal=='S')
{
KeyVal=0;
SetClockTime(LoopTime);
WrToROM(LoopTime,30,3);
}
}break;
default: { PageNum=0; PageInit(); }break;
}
/*-------------------------------------------------------*/
}
void IncO2Control(void)
{
if(1==CompareClock(O2Time,Time))
{
O2Second=60;
}
if(O2Second>0)
RELAY2=0;
else
RELAY2=1;
}
void FeedControl(void)
{
if(1==CompareClock(FeedTime,Time))
{
FeedSecond=10;
}
if(FeedSecond>0)
{
ENA=0;
ENB=1;
}
else
{
ENA=1;
ENB=1;
}
}
void LoopControl(void)
{
if(1==CompareClock(LoopTime,CountTime))
{
CountTime[0]=CountTime[1]=CountTime[2]=0;
LoopSecond=60;
}
if(LoopSecond>0)
{
RELAY3=0;
}
else
{
RELAY3=1;
}
}
4 实现效果
下位机实现效果
上位机实现效果
实物演示效果
5 最后
本项目包含完整的源代码、硬件设计图纸和详细的设计论文,适合用于毕业设计或嵌入式系统学习。通过本项目,读者可以深入了解STM32单片机的开发、传感器应用、WiFi通信以及远程监控系统的实现方法。