文章目录
- 一、智能鱼缸控制系统
- 1.题目要求
- 2.思路
- 2.1 主控
- 2.2 传感器
- 2.3 按键
- 2.4 声光报警
- 2.5 自动换水,喂食,供氧
- 2.6 OLED显示
- 2.7 电源部分
- 2.8 远程终端
- 3.电路仿真
- 3.1 未仿真时
- 3.2 开始仿真,正常显示
- 3.3 按下设置按键,进入阈值界面
- 3.4 通过阈值加减按键控制阈值大小
- 3.5 温度大于温度阈值,声光报警
- 3.6 远程终端设置阈值和换水时间,喂食时间
- 4.仿真程序
- 4.1 程序说明
- 4.2 主程序
- 4.3 OLED显示函数
- 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 主程序
/* 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显示函数
/*******************************************************************************
* 函数名: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 按键扫描函数
/*******************************************************************************
* 函数名: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仿真。
感谢你的观看!