STM32项目分享:植物生长环境监测系统

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.6k人参与

目录

一、引言

二、硬件设计

2.1 模块组成

2.2  原理图

2.3  PCB

三、软件设计

3.1 功能

3.2 main代码

四、系统实现与测试

4.1 B站视频介绍

五、结论与展望

5.1  小结

六、资料内容及获取


一、引言

本项目基于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主,一键三联,私信博主!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值