文章目录
- 一、热带鱼缸控制系统
- 1.题目要求
- 2.思路
- 3.电路仿真
- 3.1 未仿真
- 3.2 开始仿真,显示屏显示水温、浑浊度、光照强度等值
- 3.3 当水温低于阈值,开启加热并声光报警
- 3.4 当浑浊度高于阈值,开启自动换水并声光报警
- 3.5 当光照低于阈值,开启补光并声光报警
- 3.6 手动开启增氧和喂食
- 3.7 远程监控水温等数据,远程控制增氧喂食以及修改温度阈值等
- 4.仿真程序
- 4.1 程序说明
- 4.2 主程序
- 4.3 OLED显示程序
- 4.4 串口指令程序
- 二、总结
一、热带鱼缸控制系统
1.题目要求
部件:
主控:STM32
显示:OLED
温度:防水型DS18B20
浑浊度:TSW-30
光照:光敏电阻
无线通信:蓝牙
继电器5(换水、加热、增氧、喂食、补光)
声光报警:蜂鸣器+LED
按键5
主要功能需求:
1、实时监测水温、水体浑浊度、光照强度,并显示在OLED屏幕上。
2、通过蓝牙模块将监测到的各项数据传输到手机APP,实现远程监控,同时可以通过手机进行远程控制。
3、水温、光照低于阈值或浑浊度高于阈值开启声光报警。当浑浊度超过阈值,自动开启换水;光照低于阈值,开启补光;水温低于阈值,开启加热。
4、通过按键可以开启增氧、喂食,以及修改温度、浑浊度和光照强度的阈值。
2.思路
主控是STM32,这里我们选择常用的STM32F103C8T6单片机
显示:OLED
显示的内容比较多1个界面可能不够显示,所以用多个界面,界面切换选择按键切换
温度:防水型DS18B20
浑浊度:TSW-30(proteus仿真没有该传感器,所以采用滑动变阻器模拟)
光照:光敏电阻
无线通信:蓝牙
继电器*5(换水、加热、增氧、喂食、补光)和 声光报警:蜂鸣器+LED
按键*5
通过按键手动开启/关闭增氧,手动开启/关闭喂食,这里两个按键
要修改温度,浑浊度,光照强度的阈值,一共3个阈值,选择用1个按键来切换选择的阈值,另外2个按键增大/减小阈值,这里三个按键。
3.电路仿真
3.1 未仿真
3.2 开始仿真,显示屏显示水温、浑浊度、光照强度等值
3.3 当水温低于阈值,开启加热并声光报警
3.4 当浑浊度高于阈值,开启自动换水并声光报警
3.5 当光照低于阈值,开启补光并声光报警
3.6 手动开启增氧和喂食
3.7 远程监控水温等数据,远程控制增氧喂食以及修改温度阈值等
远程监控水温,浑浊度,光照强度等数据
远程控制打开增氧,关闭增氧
远程控制打开喂食,关闭喂食
按下切换按键,切换为设置温度阈值界面,更改温度阈值为50
按下切换按键,切换为设置浑浊度阈值界面,更改温度阈值为66
按下切换按键,切换为设置光照阈值界面,更改温度阈值为80
4.仿真程序
4.1 程序说明
主控芯片:STM32F103C8
HSI:64MHZ
Systick: 1ms
浑浊度传感器:ADC(PA0)
光照传感器:LDR(PA2)
DS18B20温度传感器:DAT(PA4)
模拟蓝牙模块(Uart1):9600(PA9:tx1,PA10:rx1)
声光报警:BUZZER(PA15)
按键:
KEY1(PB0)
KEY2(PB1)
KEY3(PB2)
KEY2(PB3)
KEY5(PB4)
换水:RELAY1(PB6)
加热:RELAY2(PB7)
增氧:RELAY3(PB8)
喂食:RELAY4(PB9)
补光:RELAY5(PB10)
OLED显示屏:SCL(PB14),SDA(PB15)
串口协议
举例如发送*Temp50,即设置温度阈值位50度
*TempXX 设置温度阈值 XX取值为0-99
*MuddXX 设置浑浊度阈值 XX取值为0-99
*IlluXX 设置光照阈值 XX取值为0-99
*oxygX 开启/关闭增氧 X取值为0-1
*feedX 开启/关闭喂食 X取值为0-1
*Read 远程监控水温、水体浑浊度、光照强度等数据,
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._10ms + 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();
DS18B20_Collect_data();//DS18B20采集温度数据
OLED_Handel();//OLED显示
Forewarning_Handel();//预警函数
Receive_data_Handel();//数据接收判断
IWDG_ReloadCounter();//清开门狗
}
}
}
4.3 OLED显示程序
/*******************************************************************************
* 函数名:OLED_Handel
* 描述 :OLED显示
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :100ms
*******************************************************************************/
void OLED_Handel(void)
{
if(ADC_Flag)
{
if(Threshold_switching == 0)
{
OLED_Show_Character(1,1,0,16);//水
OLED_Show_Character(1,2,1,16);//温
OLED_Show_Character(1,3,2,16);//:
OLED_ShowNum(1,7,Temp_High,2);
OLED_ShowString(1, 9, ".");
OLED_ShowNum(1,10,Temp_Low,1);
OLED_Show_Character(1,6,3,16);//°
OLED_ShowString(1, 13, "C");
OLED_Show_Character(2,1,4,16);//浑
OLED_Show_Character(2,2,5,16);//度
OLED_Show_Character(2,3,6,16);//度
OLED_Show_Character(2,4,2,16);//:
OLED_ShowNum(2,9,ADC1_Value,2);
OLED_ShowString(2, 11, "%");
OLED_Show_Character(3,1,7,16);//光
OLED_Show_Character(3,2,8,16);//照
OLED_Show_Character(3,3,9,16);//强
OLED_Show_Character(3,4,10,16);//度
OLED_Show_Character(3,5,2,16);//:
OLED_ShowNum(3,11,ADC2_Value,2);
OLED_ShowString(3, 13, "%");
}
else if(Threshold_switching == 1)
{
OLED_Show_Character(1,1,0,16);//水
OLED_Show_Character(1,2,1,16);//温
OLED_Show_Character(1,3,11,16);//阈
OLED_Show_Character(1,4,12,16);//值
OLED_Show_Character(1,5,2,16);//:
OLED_ShowNum(1,11,Temp_Threshold,2);
OLED_Show_Character(1,7,3,16);//°
OLED_ShowString(1, 15, "C");
}
else if(Threshold_switching == 2)
{
OLED_Show_Character(1,1,4,16);//浑
OLED_Show_Character(1,2,5,16);//度
OLED_Show_Character(1,3,6,16);//度
OLED_Show_Character(1,4,11,16);//阈
OLED_Show_Character(1,5,12,16);//值
OLED_Show_Character(1,6,2,16);//:
OLED_ShowNum(1,13,ADC1_Threshold,2);
OLED_ShowString(1, 15, "%");
}
else if(Threshold_switching == 3)
{
OLED_Show_Character(1,1,7,16);//光
OLED_Show_Character(1,2,8,16);//照
OLED_Show_Character(1,3,11,16);//阈
OLED_Show_Character(1,4,12,16);//值
OLED_Show_Character(1,5,2,16);//:
OLED_ShowNum(1,13,ADC2_Threshold,2);
OLED_ShowString(1, 15, "%");
}
}
}
4.4 串口指令程序
/*******************************************************************************
* 函数名:Send_Cmd1
* 描述 :设置温度阈值
* 输入 :void
* 输出 :void
* 调用 :需要时调用
* 备注 :举例如发送*Temp50,即设置温度阈值位50度
*******************************************************************************/
void Send_Cmd1(void)
{
uint8_t i = 0;
variable1 = (AsciiToHex(uart1_rx_buf[i+5])*10+AsciiToHex(uart1_rx_buf[i+6]));
if(variable1 < 99)
{
Temp_Threshold = variable1;
printf("手机设置的温度阈值 = %d\r\n",Temp_Threshold);
}
else
{
printf("手机设置的温度阈值超出设置范围 \r\n");
}
}
/*******************************************************************************
* 函数名:Send_Cmd2
* 描述 :设置水体浑浊度阈值
* 输入 :void
* 输出 :void
* 调用 :需要时调用
* 备注 :
*******************************************************************************/
void Send_Cmd2(void)
{
uint8_t i = 0;
variable2 = (AsciiToHex(uart1_rx_buf[i+5])*10+AsciiToHex(uart1_rx_buf[i+6]));
if(variable2 < 99)
{
ADC1_Threshold = variable2;
printf("手机设置的水体浑浊度阈值 = %d\r\n",ADC1_Threshold);
}
else
{
printf("手机设置的水体浑浊度阈值超出设置范围 \r\n");
}
}
/*******************************************************************************
* 函数名:Send_Cmd3
* 描述 :设置光照阈值
* 输入 :void
* 输出 :void
* 调用 :需要时调用
* 备注 :
*******************************************************************************/
void Send_Cmd3(void)
{
uint8_t i = 0;
variable3 = (AsciiToHex(uart1_rx_buf[i+5])*10+AsciiToHex(uart1_rx_buf[i+6]));
if(variable3 < 99)
{
ADC2_Threshold = variable3;
printf("手机设置的光照阈值 = %d\r\n",ADC2_Threshold);
}
else
{
printf("手机设置的光照阈值超出设置范围 \r\n");
}
}
/*******************************************************************************
* 函数名:Send_Cmd4
* 描述 :开启/关闭增氧
* 输入 :void
* 输出 :void
* 调用 :需要时调用
* 备注 :
*******************************************************************************/
void Send_Cmd4(void)
{
uint8_t i = 0;
variable4 = AsciiToHex(uart1_rx_buf[i+5]);
if(variable4 == 0)
{
Relay3_Off();
printf("关闭增氧\r\n");
}
else if (variable4 == 1)
{
Relay3_On();
printf("打开增氧 \r\n");
}
else
{
printf("手机设置的供氧模式超出设置范围 \r\n");
}
}
/*******************************************************************************
* 函数名:Send_Cmd5
* 描述 :开启/关闭喂食
* 输入 :void
* 输出 :void
* 调用 :需要时调用
* 备注 :
*******************************************************************************/
void Send_Cmd5(void)
{
uint8_t i = 0;
variable5 = AsciiToHex(uart1_rx_buf[i+5]);
if(variable5 == 0)
{
Relay4_Off();
printf("关闭喂食\r\n");
}
else if (variable5 == 1)
{
Relay4_On();
printf("打开喂食 \r\n");
}
else
{
printf("手机设置的喂食模式超出设置范围 \r\n");
}
}
/*******************************************************************************
* Function : Receive_data_Handel
* Description : 数据接收判断
* Input : 无
* Return : 无
* Call : 100ms
* Others :
*******************************************************************************/
void Receive_data_Handel(void)
{
uint8_t i = 0;
if(uart1_rx_finsh)
{
for(i = 0;i< 20; i++)
{
if(uart1_rx_buf[i] == '*')
{
switch(uart1_rx_buf[i+1])
{
case 'T':Send_Cmd1();break;//*TempXX
case 'M':Send_Cmd2();break;//*MuddXX
case 'I':Send_Cmd3();break;//*IlluXX
case 'o':Send_Cmd4();break;//*oxygX
case 'f':Send_Cmd5();break;//*feedX
case 'R':Printf_Task();break;//*Read
default:break;
}
}
}
uart1_rx_finsh = 0;
uart1_rx_count = 0;
memset(uart1_rx_buf,0,RX_MAX_NUM);
}
}
/*******************************************************************************
* Function : Printf_Task
* Description : 打印数据任务
* Input : 无
* Return : 无
* Call : 1s
* Others :
*******************************************************************************/
void Printf_Task(void)
{
if(ADC_Flag)
{
printf("水温=%d.%d 水体浑浊度=%d 光照强度=%d\r\n",Temp_High,Temp_Low,ADC1_Value,ADC2_Value);
}
}
二、总结
今天主要讲了基于STM32的热带鱼缸控制系统的设计。
感谢你的观看!