基于STM32物联网智能鱼缸智能家居系统设计与实现
摘要:本文设计并实现了一种基于STM32F103C8T6单片机和ESP8266 01S WIFI模块的物联网智能鱼缸智能家居系统。该系统具备温度测量显示、浊度测量报警、温度自动控制、自动定时补氧控制、自动定时喂食控制以及手机远程控制等功能。通过集成多种传感器和执行器,系统能够实时监测和调控鱼缸环境,为鱼类提供一个舒适、健康的生活环境。同时,手机APP的远程监控和控制功能提高了用户的使用便利性。
关键词:STM32F103C8T6;ESP8266 01S WIFI模块;物联网智能鱼缸;温度控制;浊度测量;手机远程控制
一、引言
随着科技的不断进步和人们生活水平的提高,智能家居设备逐渐渗透到我们生活的方方面面。智能鱼缸作为一种新兴的家居设备,正受到越来越多养鱼爱好者的青睐。传统的鱼缸管理方式存在喂食不及时、水质监测不准确、换水不便捷等问题,难以满足现代家庭对智能化、便捷化的需求。因此,设计一种基于STM32单片机的物联网智能鱼缸智能家居系统具有重要意义。
本系统以STM32F103C8T6单片机为核心控制器,结合ESP8266 01S WIFI模块实现物联网手机通信,集成了温度测量显示、浊度测量报警、温度自动控制、自动定时补氧控制、自动定时喂食控制以及手机远程控制等功能,旨在为鱼类提供一个更加舒适、健康的生活环境,同时提高用户的使用便利性。
二、系统总体设计
(一)系统架构
本系统主要由STM32F103C8T6单片机、ESP8266 01S WIFI模块、传感器(如温度传感器、浊度传感器)、执行器(如加热棒、增氧泵、喂食器)、电源模块、显示模块(如OLED显示屏)以及手机APP等部分组成。系统架构图如图1所示。
<img src="https://example.com/system_architecture.png" />
(二)功能需求
- 温度测量显示:系统能够实时测量鱼缸内的水温,并通过显示模块显示出来。
- 浊度测量报警:系统能够实时测量鱼缸内的水质浊度,当浊度超过预设阀值时,发出报警信号提醒主人更换水。
- 温度自动控制:系统能够根据预设的温度范围,自动调节加热棒的工作状态,使鱼缸内的水温保持在适宜范围内。
- 自动定时补氧控制:系统能够按照预设的时间间隔,自动启动增氧泵为鱼缸补氧。
- 自动定时喂食控制:系统能够按照预设的时间间隔,自动启动喂食器为鱼类喂食。
- 手机远程控制:用户能够通过手机APP远程监控鱼缸内的情况,包括温度、浊度等参数,并能够远程修改自动喂食、供氧时间等设置。
三、硬件设计
(一)核心控制器——STM32F103C8T6单片机
STM32F103C8T6单片机是STMicroelectronics(意法半导体)公司生产的一种基于ARMCortex-M3内核的32位微控制器。它具有高性能、低功耗、丰富的外设和灵活的功耗管理等特点,非常适合用于智能控制系统的设计。在本系统中,STM32F103C8T6单片机作为核心控制器,负责接收传感器数据、处理控制逻辑以及输出控制信号。
(二)WIFI模块——ESP8266 01S
ESP8266 01S WIFI模块是一款基于乐鑫ESP8266EX的低功耗UART-WIFI芯片模组。它集成了Tensilica L106超低功耗32位微型MCU,支持RTOS,内置TCP/IP协议栈,可以方便地进行二次开发。该模块支持STA(Station)模式、AP(Access Point)模式和STA+AP混合模式,能够满足不同场景下的通信需求。在本系统中,ESP8266 01S WIFI模块用于实现物联网手机通信,将鱼缸内的数据上传到云端服务器,并接收手机APP的控制指令。
(三)传感器
- 温度传感器:本系统选用DS18B20数字温度传感器。DS18B20具有防水、耐高温、精度高等特点,适合在水中测量温度。它通过单总线协议与STM32单片机进行通信,将测量到的温度数据传输给单片机。
- 浊度传感器:本系统选用一种基于光散射原理的水质浊度传感器。它能够测量水体中悬浮物的含量,从而反映水质的浊度。浊度传感器通过模拟信号输出与STM32单片机进行通信,将测量到的浊度数据转换为数字信号后传输给单片机。
(四)执行器
- 加热棒:加热棒用于调节鱼缸内的水温。当水温低于预设的下限值时,STM32单片机控制加热棒启动加热;当水温达到预设的上限值时,加热棒停止工作。
- 增氧泵:增氧泵用于为鱼缸补氧。系统按照预设的时间间隔自动启动增氧泵工作一段时间,以确保鱼缸内的溶解氧含量充足。
- 喂食器:喂食器用于为鱼类喂食。系统按照预设的时间间隔自动启动喂食器投放鱼食。
(五)电源模块
电源模块负责为系统各部分提供稳定的电源。本系统采用开关电源模块将交流电转换为直流电,再通过稳压模块为各部分提供稳定的5V或3.3V直流电源。
(六)显示模块
显示模块用于显示鱼缸内的温度、浊度等参数。本系统选用OLED显示屏作为显示模块。OLED显示屏具有自发光、对比度高、视角广、响应速度快等优点,能够清晰地显示各种信息。
四、软件设计
(一)开发环境
本系统采用Keil uVision作为开发环境。Keil uVision是一款功能强大的单片机开发软件,它支持多种编程语言(如C语言),提供了丰富的库函数和开发工具,方便开发者进行程序编写和调试。
(二)软件架构
本系统的软件架构主要包括初始化模块、数据采集模块、数据处理模块、控制逻辑模块、通信模块以及显示模块等部分。
- 初始化模块:负责初始化STM32单片机的各个外设(如GPIO、ADC、UART等)以及ESP8266 01S WIFI模块。
- 数据采集模块:负责采集温度传感器和浊度传感器的数据,并将采集到的数据转换为数字信号后存储到单片机的内存中。
- 数据处理模块:负责对采集到的数据进行处理和分析,如计算平均值、判断数据是否超出预设范围等。
- 控制逻辑模块:根据数据处理模块的结果,执行相应的控制逻辑,如控制加热棒、增氧泵、喂食器的工作状态等。
- 通信模块:负责ESP8266 01S WIFI模块与云端服务器之间的通信,包括数据上传和指令接收等。
- 显示模块:负责将鱼缸内的温度、浊度等参数显示到OLED显示屏上。
(三)关键程序实现
-
温度测量与显示
温度测量的关键程序如下:
c复制代码
uint16_t ReadTemperature(void) {
ADC_InitTypeDef ADC_InitStruct;
// 初始化ADC
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStruct);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
uint16_t temperature = ADC_GetConversionValue(ADC1);
ADC_Cmd(ADC1, DISABLE);
return temperature;
}
温度显示的关键程序如下:
c复制代码
void DisplayTemperature(uint16_t temperature) {
OLED_Clear(); // 清屏
OLED_ShowString(0, 0, "Temperature:", 12);
char tempStr[10];
sprintf(tempStr, "%d.%02dC", temperature / 100, (temperature % 100) / 10);
OLED_ShowString(0, 16, tempStr, 12);
OLED_Refresh_Gram(); // 刷新显示
}
-
浊度测量与报警
浊度测量的关键程序如下:
c复制代码
uint16_t ReadTurbidity(void) {
ADC_InitTypeDef ADC_InitStruct;
// 初始化ADC(与温度测量类似,但通道不同)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC2, &ADC_InitStruct);
ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
ADC_Cmd(ADC2, ENABLE);
ADC_ResetCalibration(ADC2);
while(ADC_GetResetCalibrationStatus(ADC2));
ADC_StartCalibration(ADC2);
while(ADC_GetCalibrationStatus(ADC2));
ADC_SoftwareStartConvCmd(ADC2, ENABLE);
while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC));
uint16_t turbidity = ADC_GetConversionValue(ADC2);
ADC_Cmd(ADC2, DISABLE);
return turbidity;
}
浊度报警的关键程序如下:
c复制代码
void CheckTurbidity(uint16_t turbidity) {
if (turbidity > TURBIDITY_THRESHOLD) {
// 浊度超过阀值,发出报警信号
Buzzer_On(); // 启动蜂鸣器
OLED_Clear();
OLED_ShowString(0, 0, "Turbidity High!", 12);
OLED_Refresh_Gram();
} else {
Buzzer_Off(); // 关闭蜂鸣器
}
}
-
温度自动控制
温度自动控制的关键程序如下:
c复制代码
void ControlHeater(uint16_t temperature) {
if (temperature < TEMPERATURE_LOWER_LIMIT) {
// 温度低于下限值,启动加热棒
Heater_On();
} else if (temperature > TEMPERATURE_UPPER_LIMIT) {
// 温度高于上限值,关闭加热棒
Heater_Off();
}
}
-
自动定时补氧控制
自动定时补氧控制的关键程序如下:
c复制代码
void OxygenateTimer(void) {
static uint32_t lastOxygenateTime = 0;
uint32_t currentTime = HAL_GetTick();
if (currentTime - lastOxygenateTime >= OXYGENATE_INTERVAL) {
// 达到补氧时间间隔,启动增氧泵
OxygenPump_On();
HAL_Delay(OXYGENATE_DURATION); // 补氧持续时间
OxygenPump_Off();
lastOxygenateTime = currentTime; // 更新上次补氧时间
}
}
-
自动定时喂食控制
自动定时喂食控制的关键程序如下:
c复制代码
void FeedTimer(void) {
static uint32_t lastFeedTime = 0;
uint32_t currentTime = HAL_GetTick();
if (currentTime - lastFeedTime >= FEED_INTERVAL) {
// 达到喂食时间间隔,启动喂食器
Feeder_On();
HAL_Delay(FEED_DURATION); // 喂食持续时间
Feeder_Off();
lastFeedTime = currentTime; // 更新上次喂食时间
}
}
-
WIFI通信与手机远程控制
WIFI通信与手机远程控制的关键程序主要涉及到ESP8266 01S WIFI模块的配置和数据传输。以下是一个简单的WIFI通信初始化程序:
c复制代码
void WIFI_Init(void) {
USART_InitTypeDef USART_InitStruct;
// 初始化USART(用于与ESP8266通信)
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
// 配置ESP8266为STA模式并连接到WIFI热点
USART_SendString(USART1, "AT+CWMODE=1\r\n"); // 设置模块为STA模式
HAL_Delay(1000);
USART_SendString(USART1, "AT+RST\r\n"); // 重启模块
HAL_Delay(2000);
USART_SendString(USART1, "AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"); // 连接WIFI热点
HAL_Delay(5000);
}
手机远程控制功能需要配合云端服务器和手机APP实现。云端服务器负责接收ESP8266 01S WIFI模块上传的数据,并将数据转发给手机APP;同时,云端服务器还负责接收手机APP的控制指令,并将指令转发给ESP8266 01S WIFI模块。手机APP则负责显示鱼缸内的参数信息,并允许用户修改自动喂食、供氧时间等设置。
五、系统测试与优化
(一)系统测试
系统测试的主要目的是为了验证智能鱼缸控制系统的设计是否满足预期的功能需求和性能指标。测试内容包括硬件测试和软件测试两个方面。
-
硬件测试
- STM32单片机测试:测试STM32单片机的运行稳定性,包括GPIO引脚的输入输出功能、ADC模块的采样精度等。
- 传感器测试:测试温度传感器和浊度传感器的测量精度和响应速度。
- 执行器测试:测试加热棒、增氧泵、喂食器的工作状态和控制效果。
- WIFI模块测试:测试ESP8266 01S WIFI模块的通信稳定性和数据传输速度。
-
软件测试
- 功能测试:测试系统的各项功能是否正常工作,如温度测量显示、浊度测量报警、温度自动控制、自动定时补氧控制、自动定时喂食控制以及手机远程控制等。
- 性能测试:测试系统的响应时间、稳定性、可靠性等性能指标。
(二)系统优化
在测试过程中,可能会发现系统的某些部分存在性能瓶颈或不足。针对这些问题,可以对系统进行优化和改进。例如:
- 优化算法:对温度控制算法、浊度测量算法等进行优化,提高系统的控制精度和响应速度。
- 改进用户界面:对手机APP的用户界面进行优化,提高用户体验。
- 增加传感器:可以考虑增加更多的传感器,如溶解氧传感器、光照传感器等,以实现对鱼缸环境的更全面监测。
六、结论与展望
(一)结论
本文详细阐述了一种基于STM32F103C8T6单片机和ESP8266 01S WIFI模块的物联网智能鱼缸智能家居系统的设计与实现。该系统集成了温度测量显示、浊度测量报警、温度自动控制、自动定时补氧控制、自动定时喂食控制以及手机远程控制等功能,能够实时监测和调控鱼缸环境,为鱼类提供一个舒适、健康的生活环境。通过系统测试和优化,验证了系统的可行性和稳定性。
(二)展望
随着物联网技术的不断发展,智能鱼缸智能家居系统有望与家庭物联网系统进行更深入的集成,实现与其他家电的互联互通。未来可以考虑增加更多的智能化功能,如语音识别控制、图像识别监测等,进一步提高系统的智能化水平和用户体验。同时,还可以对系统的硬件和软件进行优化和升级,降低系统成本,提高系统的可靠性和稳定性,使其更加适用于家庭、办公室等场所。
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "timer.h"
#include "usart.h"
#include "usart3.h"
#include "OLED_I2C.h"
#include "math.h"
#include "ds1302.h"
#include "dht11.h"
#include "bjdj.h"
#include "adc.h"
#include "stdio.h"
#define Num_i 256 //电机步数
u16 Flag_adc=0;
u8 Num_wendu1,Num_wendu2,Num_shidu1,Num_shidu2;
extern u8 Flag_caidan;
extern u8 Flag_dakai,dakai,Flag_bankai,bankai,Flag_zhanting;
extern u8 st[50];
int MQ_res = 0;
int main(void)
{
u16 ii=0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(9600); //语音模块串口初始化
usart3_init(9600); //蓝牙使用
DHT11_Init();
Adc_Init();
Moto_Init();
ds1302_gpio_init();
//ds1032_init(); //时间设置
ds1032_read_realTime(); //读取实时数据
KEY_Init();
MQ_Init();
LED_Init();
OLED_Init(); //屏幕初始化
TIM3_Int_Init(719,7199);
printf("AF:30");//声音调到31档 最大
delay_ms(100);
delay_ms(1000);
printf("A7:00003");//欢迎使用
delay_ms(1000);
OLED_CLS();
while(1)
{
if(Flag_caidan==1)//自动模式
{
delay_ms(500);
Flag_adc=Get_Adc_Average(0,10);
delay_ms(500);
if(Flag_adc>1000&&Flag_dakai==0)
{
printf("A7:00001");//打开
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorcw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=1;
dakai=1;
}
if(Flag_adc<1000&&Flag_dakai==1)
{
printf("A7:00002");//关闭
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorccw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=0;
dakai=0;
}
// MQ_res = MQ_Scan();
if(MQ==0)
{
LED0 = !LED0;
delay_ms(100);
LED0 = !LED0;
delay_ms(100);
}
}
if(Flag_caidan==2)//手动模式
{
if(dakai==1&&Flag_dakai==0)
{
printf("A7:00006");//打开
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorcw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=1;
}
if(dakai==0&&Flag_dakai==1)
{
printf("A7:00007");//关闭
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorccw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=0;
}
}
if(Flag_caidan==3)//定时模式
{
if(TimeRAM.kai==1&&Flag_dakai==0)
{
if(TimeRAM.hour_kai==TimeData.hour&&TimeRAM.minute_kai==TimeData.minute)
{
printf("A7:00006");//打开
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorcw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=1;
}
}
if(TimeRAM.guan==1&&Flag_dakai==1)
{
if(TimeRAM.hour_guan==TimeData.hour&&TimeRAM.minute_guan==TimeData.minute)
{
printf("A7:00007");//关闭
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorccw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=0;
}
}
}
if(Flag_caidan==4)//遥控模式
{
if(dakai==1&&Flag_dakai==0)
{
printf("A7:00006");//打开
TIM_Cmd(TIM3,DISABLE);
ii=0;
for(ii=0;ii<Num_i;ii++)
{
Motorcw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=1;
}
if(dakai==0&&Flag_dakai==1)
{
printf("A7:00007");//关闭
TIM_Cmd(TIM3,DISABLE);
for(ii=0;ii<Num_i;ii++)
{
Motorccw_angle(1,3);
MotorStop();
}
TIM_Cmd(TIM3, ENABLE);
Flag_dakai=0;
}
}
}
}