目录
一、引言
本项目基于STM32主控,集成多路传感器与ESP8266通信模块,构建了一个集环境数据采集、本地智能决策于一体的自动化系统。通过实时监测温湿度、土壤水分及光照,并联动控制风扇、水泵、LED等设备,为植物创造一个精准可控的最佳生长环境。
实物:

二、硬件设计
2.1 模块组成
-
STM32F103C8T6主控
传感/执行模块
-
温湿度传感器
-
土壤湿度传感器
-
光照传感器
-
DRV8833驱动模块
-
5V风扇
-
5V水泵
人机交互模块
-
OLED显示屏
-
按键输入
通信模块
-
ESP826601SWiFi通信
2.2 原理图

2.3 PCB

三、软件设计
3.1 功能
-
环境参数实时监测:通过DHT11传感器采集空气温湿度,土壤湿度传感器检测土壤水分,光照传感器测量光照强度,全面监控植物生长环境
-
双模式智能控制:支持自动和手动两种工作模式,自动模式下系统根据预设阈值自动调节风扇、水泵、LED补光灯等设备,手动模式下允许用户直接控制
-
多界面人机交互:提供4个OLED显示界面,分别用于数据显示、设备控制、温湿度阈值设置、土壤光照阈值设置,通过按键进行切换和参数调节
-
物联网远程监控:集成ESP8266 WiFi模块,定时向巴法云平台上传环境数据,并接收APP下发的控制指令和阈值设置命令
-
智能报警功能:当任何环境参数超出阈值范围时,系统会通过蜂鸣器发出报警提示,并在云平台标记异常状态
-
数据持久化存储:利用STM32内部Flash存储所有阈值参数,确保系统重启后设置不丢失,提高系统可靠性
3.2 main代码
#include "delay.h"
#include "sys.h"
#include "led.h" //控制器
#include "oled.h"
#include "esp8266.h"
#include "Timer.h"
#include "Key.h"
#include "stmflash.h"
// 传感/执行模块
#include "dht11.h"
#include "Soil.h" // 土壤湿度传感器
#include "Light.h" // 光照强度传感器
//C库
#include <string.h>
#include "stdio.h"
#include "math.h"
#include "stdbool.h"
/*********************************** 变量声明**********************************/
extern unsigned char esp8266_buf[buf_len];
typedef enum {
auto_mode,
manual_mode,
}control_mode;
//控制模式变量
control_mode MODE= manual_mode;//开机为手动模式
//阈值结构体
struct Set_data
{
u16 temp_H; //温度上限
u16 temp_L; //温度下限
u16 humi_H; //湿度上限
u16 humi_L; //湿度下限
u16 soil_H; //土壤湿度上限
u16 soil_L; //土壤湿度下限
u16 light_H; //光照强度上限
u16 light_L; //光照强度下限
};
struct Set_data Out_data={30,20,80,40,70,30,80,20};//初始化阈值
//数据获取
u16 temp_value=0;
u16 humi_value=0;
u16 soil_value=0;
u16 light_value=0;
DHT11_Data_TypeDef DHT11_Data;//dht11添加变量
////按键相关的变量
u8 key_num=0,Page_flag=1;
char TIMER_IT=0,WiFiInit_time,Flagout=1;
//oled相关变量
u8 oled_Fill_flag=1;//OLED清屏标志
char oled_str[100];//OLED显示缓存
char date[200];//esp8266发送缓存
bool beep_flag=false;//蜂鸣器标志位
u8 alarm_fiag=0;//环境异常报警标志位
/********************************函数声明**********************************/
// 在main函数前添加函数声明
void Page_data(void); // 数据显示界面
void Page_control(void); //控制外设
void Page_setting1(void); // 设置界面
void Page_setting2(void); // 设置界面
void APP_Control(void); //APP数据下发
void BI_BI(void); //哔哔提醒数据下发
int main(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
DHT11_Init();//初始化DHT11
Soil_Init();//初始化土壤湿度传感器
Light_Init();//初始化光照强度传感器
LED_Init();
FAN=OFF;//风扇关闭
PUMP=OFF;//水泵关闭
LED=OFF;//LED关闭
BEEP=OFF;//蜂鸣器关闭
Key_Init();//按键初始化
OLED_Init();//OLED初始化
OLED_Clear(0);
do
{
OLED_ShowText(0, 0,(u8*) "是否需要联网?", 0);
OLED_ShowText(8, 4,(u8*) "1.是 2.否", 0);
key_num=KEY_Scan(0);//按键扫描
if(key_num==1)//需要联网
{
OLED_Clear(0);
Timer_Init();
ESP8266_Init(115200);
break;
}
}while(key_num!=2);
OLED_Clear(0);
/*读出内存数据*/
STMFLASH_Read(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+4, &Out_data.humi_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+6, &Out_data.humi_L,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+8, &Out_data.soil_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+10, &Out_data.soil_L,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+12, &Out_data.light_H,1);
delay_ms(100);
STMFLASH_Read(FLASH_SAVE_ADDR+14, &Out_data.light_L,1);
delay_ms(100);
while(1)
{
/*********************************数据处理区*********************************/
//获取温湿度
Read_DHT11(&DHT11_Data);
temp_value= DHT11_Data.temp_int; //获取温度
humi_value= DHT11_Data.humi_int; //获取湿度
//获取土壤湿度
soil_value = (u16)Soil_Value_Conversion(); //获取土壤湿度
//获取光照强度
light_value = (u16)Light_Value_Conversion(); //获取光照强度
/*******************向巴法云发送数据***************************************/
if(TIMER_IT)
{
TIMER_IT=0;
sprintf(date,"cmd=2&uid=%s&topic=data&msg=#%d#%d#%d#%d#%d#%d#sensordata#\r\n",\
BEMFA_ID,
MODE,(int)temp_value,(int)humi_value,(int)soil_value,(int)light_value,(int)alarm_fiag);
ESP8266_SendData((unsigned char *)date);//ESP8266发送数据
}
/*********************************人机交互区**************************************************/
key_num=KEY_Scan(0);//按键扫描
if(key_num==1)//界面切换键
{
Page_flag++;
Page_flag=Page_flag%4; // 修改为4个界面
OLED_Clear(0);//清屏
}
//界面切换功能
switch(Page_flag)
{
case 1:
Page_data(); // 第一界面 - 数据显示
break;
case 2:
Page_control(); // 第二界面 - 控制界面
break;
case 3:
Page_setting1(); // 第三界面 - 设置界面1(温度和湿度)
break;
case 0:
Page_setting2(); // 第四界面 - 设置界面2(土壤湿度和光照强度)
break;
}
/*********************************模式控制区*********************************/
/******************APP指令下发********************************/
APP_Control();//阈值下发 模式转换
/********************自动模式******************************/
if(MODE==auto_mode){
// 温度控制逻辑
if(temp_value > Out_data.temp_H)
{
FAN = ON; // 温度过高,开启风扇降温
}
else if(temp_value < Out_data.temp_L)
{
FAN = OFF; // 温度过低,关闭风扇
}
// 湿度控制逻辑
if(humi_value < Out_data.humi_L)
{
PUMP = ON; // 湿度过低,开启水泵加湿
}
else if(humi_value > Out_data.humi_H)
{
PUMP = OFF; // 湿度过高,关闭水泵
}
// 土壤湿度控制逻辑
if(soil_value < Out_data.soil_L)
{
PUMP = ON; // 土壤湿度过低,开启水泵浇水
}
else if(soil_value > Out_data.soil_H)
{
PUMP = OFF; // 土壤湿度过高,关闭水泵
}
// 光照强度控制逻辑
if(light_value < Out_data.light_L)
{
LED = ON; // 光照不足,开启LED补光
}
else if(light_value > Out_data.light_H)
{
LED = OFF; // 光照充足,关闭LED
}
// 统一蜂鸣器控制逻辑:任何参数超出阈值范围时开启报警
if(temp_value > Out_data.temp_H || temp_value < Out_data.temp_L ||
humi_value < Out_data.humi_L || humi_value > Out_data.humi_H ||
soil_value < Out_data.soil_L || soil_value > Out_data.soil_H ||
light_value < Out_data.light_L || light_value > Out_data.light_H)
{
beep_flag = true; // 有参数异常,开启报警
alarm_fiag=1;//环境异常
}
else
{
beep_flag = false; // 所有参数正常,关闭报警
alarm_fiag=0;//环境正常
}
}//自动模式
/********************手动模式*****************************/
if(MODE==manual_mode)//手动模式
{
/****************APP控制***************************/
//LED控制
if(strstr((const char *)esp8266_buf,"LED_ON")!=0)
{
LED=ON;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if(strstr((const char *)esp8266_buf,"LED_OFF")!=0)
{
LED=OFF;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
//风扇控制
if(strstr((const char *)esp8266_buf,"FAN_ON")!=0)
{
FAN=ON;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if(strstr((const char *)esp8266_buf,"FAN_OFF")!=0)
{
FAN=OFF;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
//水泵控制
if(strstr((const char *)esp8266_buf,"PUMP_ON")!=0)
{
PUMP=ON;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if(strstr((const char *)esp8266_buf,"PUMP_OFF")!=0)
{
PUMP=OFF;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
}//手动模式
}//while
}//main
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
TIMER_IT=1;
if(beep_flag)
{
BEEP=!BEEP;
}
else
{
BEEP=0;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void APP_Control(void)
{
//模式切换
if( strstr((const char *)esp8266_buf,"ZD")!=0 )
{
MODE=auto_mode;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
else if( strstr((const char *)esp8266_buf,"SD")!=0 )
{
MODE=manual_mode;
beep_flag=false;
BEEP=OFF;
PUMP=OFF;
FAN=OFF;
LED=OFF;
alarm_fiag=0;
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
}
// 温度阈值设置
char *th_ptr = strstr((char *)esp8266_buf, "TH");
if (th_ptr != NULL && sscanf(th_ptr + 2, "=%hu", &Out_data.temp_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H, 1);
}
char *tl_ptr = strstr((char *)esp8266_buf, "TL");
if (tl_ptr != NULL && sscanf(tl_ptr + 2, "=%hu", &Out_data.temp_L) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L, 1);
}
// 湿度阈值设置
char *hh_ptr = strstr((char *)esp8266_buf, "HH");
if (hh_ptr != NULL && sscanf(hh_ptr + 2, "=%hu", &Out_data.humi_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.humi_H, 1);
}
char *hl_ptr = strstr((char *)esp8266_buf, "HL");
if (hl_ptr != NULL && sscanf(hl_ptr + 2, "=%hu", &Out_data.humi_L) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.humi_L, 1);
}
// 土壤湿度阈值设置
char *sh_ptr = strstr((char *)esp8266_buf, "SH");
if (sh_ptr != NULL && sscanf(sh_ptr + 2, "=%hu", &Out_data.soil_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+8, &Out_data.soil_H, 1);
}
char *sl_ptr = strstr((char *)esp8266_buf, "SL");
if (sl_ptr != NULL && sscanf(sl_ptr + 2, "=%hu", &Out_data.soil_L) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+10, &Out_data.soil_L, 1);
}
// 光照强度阈值设置
char *lh_ptr = strstr((char *)esp8266_buf, "LH");
if (lh_ptr != NULL && sscanf(lh_ptr + 2, "=%hu", &Out_data.light_H) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+12, &Out_data.light_H, 1);
}
char *ll_ptr = strstr((char *)esp8266_buf, "LL");
if (ll_ptr != NULL && sscanf(ll_ptr + 2, "=%hu", &Out_data.light_L) == 1)
{
BI_BI();//哔哔提醒
ESP8266_Clear();//清除缓存
STMFLASH_Write(FLASH_SAVE_ADDR+14, &Out_data.light_L, 1);
}
}
// 数据显示界面
void Page_data(void)
{
// 添加按键2的模式切换功能
if(key_num==2)//模式切换键
{
MODE++;
if(MODE > manual_mode) MODE = auto_mode; // 循环切换:自动->手动->自动
// 切换到手动模式时关闭报警和设备
if(MODE == manual_mode)
{
beep_flag=false;
BEEP=OFF;
PUMP=OFF;
FAN=OFF;
LED=OFF;
alarm_fiag=0;
}
}
//温度显示
sprintf(oled_str,"温度:%2d℃",temp_value);
OLED_ShowText(0,0,(u8*)oled_str,0);
//湿度显示
sprintf(oled_str,"湿度:%2d%%",humi_value);
OLED_ShowText(0,2,(u8*)oled_str,0);
//土壤湿度显示
sprintf(oled_str,"土壤湿度:%3d%%",soil_value);
OLED_ShowText(0,4,(u8*)oled_str,0);
//光照强度显示
sprintf(oled_str,"光照强度:%3d%%",light_value);
OLED_ShowText(0,6,(u8*)oled_str,0);
//模式状态
sprintf(oled_str,"%s",MODE?"手动":"自动");
OLED_ShowText(95,0,(u8*)oled_str,0);
}
//控制界面
void Page_control(void)
{
static u8 Index_flag=1;
sprintf(oled_str,"LED:%s",LED?"ON ":"OFF");
OLED_ShowText(16,0,(u8 *)oled_str,0);
sprintf(oled_str,"风扇:%s",FAN?"ON ":"OFF");
OLED_ShowText(16,2,(u8 *)oled_str,0);
sprintf(oled_str,"水泵:%s",PUMP?"ON ":"OFF");
OLED_ShowText(16,4,(u8 *)oled_str,0);
// 处理按键和箭头选择逻辑
if(key_num==2)
{
Index_flag++;
Index_flag=Index_flag%3; // 修改为3个选项
}
// 箭头显示和控制逻辑
switch(Index_flag)
{
case 1:
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
break;
case 2:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)">",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
break;
case 0:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)">",16) ;
break;
}
if(MODE==manual_mode)//手动模式下
{
if(Index_flag==1&&key_num==3) LED=ON;
if(Index_flag==1&&key_num==4) LED=OFF;
if(Index_flag==2&&key_num==3) FAN=ON;
if(Index_flag==2&&key_num==4) FAN=OFF;
if(Index_flag==0&&key_num==3) PUMP=ON;
if(Index_flag==0&&key_num==4) PUMP=OFF;
}
}
// 设置界面1 - 温度和湿度阈值设置
void Page_setting1(void)
{
static u8 Index_flag=1;
// 显示设置参数
sprintf(oled_str,"温度上限:%d ",Out_data.temp_H);
OLED_ShowText(16,0,(u8 *)oled_str,0);
sprintf(oled_str,"温度下限:%d ",Out_data.temp_L);
OLED_ShowText(16,2,(u8 *)oled_str,0);
sprintf(oled_str,"湿度上限:%d ",Out_data.humi_H);
OLED_ShowText(16,4,(u8 *)oled_str,0);
sprintf(oled_str,"湿度下限:%d ",Out_data.humi_L);
OLED_ShowText(16,6,(u8 *)oled_str,0);
// 处理参数调节逻辑
if(key_num==2)
{
Index_flag++;
Index_flag=Index_flag%4; // 修改为4个选项
}
// 箭头显示和参数调节逻辑
switch(Index_flag)
{
case 1:
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 2:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)">",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 3:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)">",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 0:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)">",16) ;
break;
}
// 处理参数调节
//温度上限
if(Index_flag==1&&key_num==3)
{
Out_data.temp_H < 100 ? Out_data.temp_H++ : 100;//温度上限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
}
if(Index_flag==1&&key_num==4)
{
Out_data.temp_H > 0 ? Out_data.temp_H-- : 0; //温度上限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR, &Out_data.temp_H,1);
}
//温度下限
if(Index_flag==2&&key_num==3)
{
Out_data.temp_L < 100 ? Out_data.temp_L++ : 100;//温度下限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
}
if(Index_flag==2&&key_num==4)
{
Out_data.temp_L > 0 ? Out_data.temp_L-- : 0; //温度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+2, &Out_data.temp_L,1);
}
//湿度上限
if(Index_flag==3&&key_num==3)
{
Out_data.humi_H < 100 ? Out_data.humi_H++ : 100;//湿度上限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.humi_H,1);
}
if(Index_flag==3&&key_num==4)
{
Out_data.humi_H > 0 ? Out_data.humi_H-- : 0; //湿度上限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+4, &Out_data.humi_H,1);
}
//湿度下限
if(Index_flag==0&&key_num==3)
{
Out_data.humi_L < 100 ? Out_data.humi_L++ : 100;//湿度下限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.humi_L,1);
}
if(Index_flag==0&&key_num==4)
{
Out_data.humi_L > 0 ? Out_data.humi_L-- : 0; //湿度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+6, &Out_data.humi_L,1);
}
}
// 设置界面2 - 土壤湿度和光照强度阈值设置
void Page_setting2(void)
{
static u8 Index_flag=1;
// 显示设置参数
sprintf(oled_str,"土壤上限:%d ",Out_data.soil_H);
OLED_ShowText(16,0,(u8 *)oled_str,0);
sprintf(oled_str,"土壤下限:%d ",Out_data.soil_L);
OLED_ShowText(16,2,(u8 *)oled_str,0);
sprintf(oled_str,"光照上限:%d ",Out_data.light_H);
OLED_ShowText(16,4,(u8 *)oled_str,0);
sprintf(oled_str,"光照下限:%d ",Out_data.light_L);
OLED_ShowText(16,6,(u8 *)oled_str,0);
// 处理参数调节逻辑
if(key_num==2)
{
Index_flag++;
Index_flag=Index_flag%4; // 修改为4个选项
}
// 箭头显示和参数调节逻辑
switch(Index_flag)
{
case 1:
OLED_ShowString(0,0,(u8 *)">",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 2:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)">",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 3:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)">",16) ;
OLED_ShowString(0,6,(u8 *)" ",16) ;
break;
case 0:
OLED_ShowString(0,0,(u8 *)" ",16) ;
OLED_ShowString(0,2,(u8 *)" ",16) ;
OLED_ShowString(0,4,(u8 *)" ",16) ;
OLED_ShowString(0,6,(u8 *)">",16) ;
break;
}
// 处理参数调节
//土壤湿度上限
if(Index_flag==1&&key_num==3)
{
Out_data.soil_H < 100 ? Out_data.soil_H++ : 100;//土壤湿度上限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+8, &Out_data.soil_H,1);
}
if(Index_flag==1&&key_num==4)
{
Out_data.soil_H > 0 ? Out_data.soil_H-- : 0; //土壤湿度上限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+8, &Out_data.soil_H,1);
}
//土壤湿度下限
if(Index_flag==2&&key_num==3)
{
Out_data.soil_L < 100 ? Out_data.soil_L++ : 100;//土壤湿度下限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+10, &Out_data.soil_L,1);
}
if(Index_flag==2&&key_num==4)
{
Out_data.soil_L > 0 ? Out_data.soil_L-- : 0; //土壤湿度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+10, &Out_data.soil_L,1);
}
//光照强度上限
if(Index_flag==3&&key_num==3)
{
Out_data.light_H < 100 ? Out_data.light_H++ : 100;//光照强度上限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+12, &Out_data.light_H,1);
}
if(Index_flag==3&&key_num==4)
{
Out_data.light_H > 0 ? Out_data.light_H-- : 0; //光照强度上限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+12, &Out_data.light_H,1);
}
//光照强度下限
if(Index_flag==0&&key_num==3)
{
Out_data.light_L < 100 ? Out_data.light_L++ : 100;//光照强度下限不能超过100
STMFLASH_Write(FLASH_SAVE_ADDR+14, &Out_data.light_L,1);
}
if(Index_flag==0&&key_num==4)
{
Out_data.light_L > 0 ? Out_data.light_L-- : 0; //光照强度下限不能低于0
STMFLASH_Write(FLASH_SAVE_ADDR+14, &Out_data.light_L,1);
}
}
void BI_BI(void){
BEEP=ON;
delay_ms(150);
BEEP=OFF;
}
四、系统实现与测试
可在B站关注博主,获取资料哦!!!
4.1 B站视频介绍
植物生长环境监测系统
五、结论与展望
5.1 小结
可以拓展语音控制功能;执行器添加加湿器、步进电机控制遮阳、保温类地毯;监测类模块,添加PH值模块。
六、资料内容及获取
B站关注UP主,一键三联,私信博主!!!
2万+

被折叠的 条评论
为什么被折叠?



