✌️✌️大家好,这里是5132单片机毕设设计项目分享,今天给大家分享的是基于《基于STM32的智能植物养护系统设计》。

目录

一、系统功能

2.1、硬件清单

2.2、功能介绍

2.3、控制模式

二、演示视频和实物

三、系统设计框图

四、软件设计流程图

五、原理图

六、主程序

七、总结

八、资料内容


一、系统功能

2.1、硬件清单

STM32核心控制板 + OLED显示屏 + 光敏传感器 + 蜂鸣器 + 风扇 + 补光灯(LED) + 水泵(继电器控制) + 舵机(遮阳棚) + 温度传感器 + 土壤湿度传感器 + 二氧化碳传感器 + 蓝牙模块 + 4个按键 + 后备电池

2.2、功能介绍

(1)蓝牙模块:用于无线通信,通过手机APP连接(原文中通过“数字意识”APP),实现远程控制风扇、水泵、补光灯等设备,并在OLED显示屏上同步显示控制状态(如开关状态)。
(2)光敏传感器:检测环境光照强度,数据用于自动控制补光灯和遮阳棚(舵机)。
(3)温度传感器:检测环境温度,数据用于自动控制风扇(当温度过高时)。
(4)土壤湿度传感器:检测土壤湿度,数据用于自动控制水泵(当湿度过低时启动灌溉)。
(5)二氧化碳传感器:检测空气中二氧化碳浓度,数据用于触发蜂鸣器报警(当浓度过高时)。
(6)OLED显示屏:实时显示系统信息,包括时间、传感器数据(温度、土壤湿度、光照强度、二氧化碳浓度)及工作模式(手动、蓝牙、自动),并支持菜单导航。
(7)4个按键模块:在不同模式下提供控制功能:
第一个按键为确认键(在手动模式下控制风扇,在自动模式下用于阈值切换);
第二个按键为菜单/模式切换键(用于切换手动、蓝牙、自动模式);
第三个按键功能上下文相关(在手动模式下控制水泵,在自动模式下用于阈值加减操作);
第四个按键为返回键(退出菜单或返回上级界面)。
(8)蜂鸣器:用于声音报警,当二氧化碳浓度超过设定阈值时自动触发。
(9)风扇:在自动模式下,当温度超过阈值时启动以降温;手动或蓝牙模式下可通过按键或APP直接控制。
(10)补光灯(LED):在自动模式下,当光照强度低于设定阈值时开启以补光;手动或蓝牙模式下可通过按键或APP直接控制。
(11)水泵(继电器控制):用于植物灌溉,在自动模式下,当土壤湿度低于设定阈值时自动启动;手动或蓝牙模式下可通过按键或APP直接控制(继电器打开时绿灯亮起)。
(12)舵机(遮阳棚):控制遮阳棚(可安装纸片模拟),在自动模式下,当光照强度超过设定阈值时自动开启以遮阳;手动或蓝牙模式下可通过APP控制。
(13)STM32核心控制板(STM32F103C8T6):作为系统主控制器,处理所有传感器数据、执行控制逻辑(如阈值比较),并协调外设(如显示屏、按键、执行器)。
(14)后备电池:用于为系统时钟供电,确保上电后时间数据保持准确。

2.3、控制模式

系统支持三种工作模式,通过第二个按键(菜单/模式切换键)进行切换:
(1)蓝牙模式(远程控制):上电后可通过蓝牙模块连接手机APP(原文中APP名称为“数字意识”),实现远程控制风扇、水泵、补光灯、遮阳棚(舵机)等设备,并实时查看OLED显示屏上的传感器数据(温度、土壤湿度、光照强度、二氧化碳浓度)。
(2)手动模式:通过按键直接控制外设
第一个按键控制风扇开关;
第三个按键控制水泵开关(继电器状态在OLED显示);
第三个按键控制补光灯开关;
第四个按键用于返回上级菜单。
(操作时无需长按,原文未提及延迟处理)。
(3)自动模式:系统根据传感器检测值与设定阈值的比较自动执行动作,支持通过按键调整阈值(第一个按键切换阈值类型,第二个按键增加阈值,第三个按键减少阈值):
温度 > 阈值时启动风扇(例如,温度 > 30°C);
二氧化碳浓度 > 阈值时触发蜂鸣器报警(例如,二氧化碳 > 500 ppm,正常空气为350 ppm);
土壤湿度 < 阈值时启动水泵(例如,土壤湿度 < 39%);
光照强度 < 阈值时开启补光灯(例如,光照强度 < 59 lux);
光照强度 > 阈值时开启舵机(遮阳棚)(例如,光照强度 > 59 lux)。


二、演示视频和实物

基于STM32的植物养护系统设计(加入了菜单)

 


三、系统设计框图


四、软件设计流程图


五、原理图


六、主程序

#include "main.h"
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    delay_init();      //延时函数初始化
    LED_Init();            //初始化与LED连接的硬件接口
    Buzzer_Init();             //下面为外设初始化
    OLED_Init();
    Key_Init();
    AD_Init();
    Serial_Init();   //串口1初始化
    MyRTC_Init();
    Servo_Init();     //舵机初始化,并设置舵机初始角度
  	USART2_Config();
    while (1)
    {
        TimeRead();

        if (YiJiMenu) menu();

        if (t % 10 == 0)                                         //读取传感器信息
        {
            sensor.Guang = AD_GetValue(ADC_Channel_4);    //光敏传感器     PA4
            if (sensor.Guang > 4000)sensor.Guang = 4000;
            sensor.Guang = (u8)(100 - (sensor.Guang / 40));

            sensor.Tu_Humi = AD_GetValue(ADC_Channel_5);    //土壤传感器     PA5
            if (sensor.Tu_Humi > 4000)sensor.Tu_Humi = 4000;
            sensor.Tu_Humi = (u8)(100 - (sensor.Tu_Humi / 40));

            temperature = DS18B20_Get_Temp();
					
					 	CO2GetData(&co2);
        }
        t++;

        KeyNum = Key_GetNum();                                    //按键扫描
        if (KeyNum == 1)                       //确认键
        {
            qingping = 0;
            delay_ms(20);
            if (KeyNum == 1)
            {
                YiJiMenu = 0;
            }
        }
        if (KeyNum == 4)            //返回键
        {
            qingping = 0;
            delay_ms(20);
            if (KeyNum == 4)
            {
                YiJiMenu = 1;
            }
        }
        if (YiJiMenu == 0)
        {
            switch (state)
            {
            case 0:
            {
                if (qingping == 0)
                {
                    OLED_Clear();
                    qingping = 1;
                }
                zhidong();
                ChuanGan();
            }
            break;
            case 1:
            {
                if (qingping == 0)
                {
                    OLED_Clear();
                    qingping = 1;
                }
                shoudong();
            }
            break;
            case 2:
            {
                if (qingping == 0)
                {
                    OLED_Clear();
                    qingping = 1;
                }
                LanYa();
            }
            break;
            }
        }
    }
}



void menu()                 //菜单
{
    if (qingping == 0)
    {
        OLED_Clear();
        qingping = 1;
    }
    if (KeyNum == 2)
    {
        delay_ms(20);
        if (KeyNum == 2)
        {
            state++;
            if (state > Mode - 1)
            {
                state = 0;
            }
        }
    }
    switch (state)
    {
    case 0:
    {
        OLED_ShowString(2, 1, ">>");
        OLED_ShowString(2, 15, "<<");
        OLED_ShowString(3, 1, "  ");
        OLED_ShowString(3, 15, "  ");
        OLED_ShowString(4, 1, "  ");
        OLED_ShowString(4, 15, "  ");

        OLED_ShowChinese(2, 3, 51);
        OLED_ShowChinese(2, 4, 52);
        OLED_ShowChinese(2, 5, 8);
        OLED_ShowChinese(2, 6, 9);

        OLED_ShowChinese(3, 3, 18);
        OLED_ShowChinese(3, 4, 52);
        OLED_ShowChinese(3, 5, 8);
        OLED_ShowChinese(3, 6, 9);

        OLED_ShowChinese(4, 3, 69);
        OLED_ShowChinese(4, 4, 70);
        OLED_ShowChinese(4, 5, 8);
        OLED_ShowChinese(4, 6, 9);
    }
    break;
    case 1:
    {
        OLED_ShowString(2, 1, "  ");
        OLED_ShowString(2, 15, "  ");
        OLED_ShowString(3, 1, ">>");
        OLED_ShowString(3, 15, "<<");
        OLED_ShowString(4, 1, "  ");
        OLED_ShowString(4, 15, "  ");

        OLED_ShowChinese(2, 3, 51);
        OLED_ShowChinese(2, 4, 52);
        OLED_ShowChinese(2, 5, 8);
        OLED_ShowChinese(2, 6, 9);

        OLED_ShowChinese(3, 3, 18);
        OLED_ShowChinese(3, 4, 52);
        OLED_ShowChinese(3, 5, 8);
        OLED_ShowChinese(3, 6, 9);

        OLED_ShowChinese(4, 3, 69);
        OLED_ShowChinese(4, 4, 70);
        OLED_ShowChinese(4, 5, 8);
        OLED_ShowChinese(4, 6, 9);
    }
    break;
    case 2:
    {
        OLED_ShowString(2, 1, "  ");
        OLED_ShowString(3, 1, "  ");
        OLED_ShowString(2, 15, "  ");
        OLED_ShowString(3, 15, "  ");
        OLED_ShowString(4, 1, ">>");
        OLED_ShowString(4, 15, "<<");

        OLED_ShowChinese(2, 3, 51);
        OLED_ShowChinese(2, 4, 52);
        OLED_ShowChinese(2, 5, 8);
        OLED_ShowChinese(2, 6, 9);

        OLED_ShowChinese(3, 3, 18);
        OLED_ShowChinese(3, 4, 52);
        OLED_ShowChinese(3, 5, 8);
        OLED_ShowChinese(3, 6, 9);

        OLED_ShowChinese(4, 3, 69);
        OLED_ShowChinese(4, 4, 70);
        OLED_ShowChinese(4, 5, 8);
        OLED_ShowChinese(4, 6, 9);
    }
    break;
    case 3:
    {
        OLED_ShowString(2, 1, "  ");
        OLED_ShowString(3, 1, "  ");
        OLED_ShowString(2, 15, "  ");
        OLED_ShowString(3, 15, "  ");
        OLED_ShowString(4, 1, ">>");
        OLED_ShowString(4, 15, "<<");

        OLED_ShowChinese(2, 3, 18);
        OLED_ShowChinese(2, 4, 52);
        OLED_ShowChinese(2, 5, 8);
        OLED_ShowChinese(2, 6, 9);

        OLED_ShowChinese(3, 3, 57);
        OLED_ShowChinese(3, 4, 58);
        OLED_ShowChinese(3, 5, 8);
        OLED_ShowChinese(3, 6, 9);

        OLED_ShowChinese(4, 3, 61);
        OLED_ShowChinese(4, 4, 62);
        OLED_ShowChinese(4, 5, 8);
        OLED_ShowChinese(4, 6, 9);
    }
    break;
    }
}

void shoudong()
{
    OLED_ShowString(2, 1, "FengShan:");
    OLED_ShowString(3, 1, "Shui Ben:");
    OLED_ShowString(4, 1, "LED:");

    if (KeyNum == 1)        //按键
    {
        delay_ms(20);
        if (KeyNum == 1)
        {
            state2++;
            if (state2 > 1)
            {
                state2 = 0;
            }
        }
    }
    if (state2 == 0)
    {
        FengShan_ON();
        OLED_ShowString(2, 10, "ON ");
    }
    if (state2 == 1)
    {
        FengShan_OFF();
        OLED_ShowString(2, 10, "OFF");
    }
    if (KeyNum == 2)        //按键
    {
        delay_ms(20);
        if (KeyNum == 2)
        {
            state2_1++;
            if (state2_1 > 1)
            {
                state2_1 = 0;
            }
        }
    }
    if (state2_1 == 1)
    {
        ShuiBen_ON();
        OLED_ShowString(3, 10, "ON ");
    }
    if (state2_1 == 0)
    {
        ShuiBen_OFF();
        OLED_ShowString(3, 10, "OFF");
    }
    if (KeyNum == 3)        //按键
    {
        delay_ms(20);
        if (KeyNum == 3)
        {
            state2_2++;
            if (state2_2 > 1)
            {
                state2_2 = 0;
            }
        }
    }
    if (state2_2 == 1)
    {
        LED_ON();
        OLED_ShowString(4, 10, "ON ");
    }
    if (state2_2 == 0)
    {
        LED_OFF();
        OLED_ShowString(4, 10, "OFF");
    }


}
void zhidong()
{
    if (sensor.Tu_Humi < sensor.Tu_Humi_Yu)
    {
        ShuiBen_ON();
    }
    else
    {
        ShuiBen_OFF();
    }

    if (temperature > temperature_Yu)
    {
        FengShan_ON();
    }
    else
    {
        FengShan_OFF();
    }

    if (sensor.Guang < sensor.Guang_Yu)
    {
        LED_ON();
			  Servo_SetAngle(0);//外设操作
    }
    else
    {
        LED_OFF(); 
			   Servo_SetAngle(90);//外设操作
    }
		
		if (co2< 500)
    {
        Buzzer_OFF();
    }
    else
    {
        Buzzer_ON();
    }


    if (KeyNum == 1)                          //自动模式下PB0按键控制阈值切换
    {
        delay_ms(20);
        if (KeyNum == 1)
        {
            state3++;
            if (state3 > 2)
            {
                state3 = 0;
            }
        }
    }
    if (state3 == 1)
    {
        if (KeyNum == 2)temperature_Yu += 10;       //光照强度上限加
        if (KeyNum == 3)temperature_Yu -= 10;          //光照强度上限减
    }
    if (state3 == 2)
    {
        if (KeyNum == 2)sensor.Tu_Humi_Yu++;
        if (KeyNum == 3)sensor.Tu_Humi_Yu--;
    }
    if (state3 == 0)
    {
        if (KeyNum == 2)sensor.Guang_Yu++;
        if (KeyNum == 3)sensor.Guang_Yu--;
    }
}

void LanYa()
{
    OLED_ShowString(2, 1, "FengShan:");
    OLED_ShowString(3, 1, "Shui Ben:");
    OLED_ShowString(4, 1, "LED:");
    if (Serial_GetRxFlag() == 1)
    {
        RxData = Serial_GetRxData();     //蓝牙接收
        switch (RxData)
        {
        case 1:
            state2++;
            if (state2 > 1)
            {
                state2 = 0;
            }
            break;
        case 2:
            state2_1++;
            if (state2_1 > 1)
            {
                state2_1 = 0;
            }
            break;
        case 3:
            state2_2++;
            if (state2_2 > 1)
            {
                state2_2 = 0;
            }
            break;
        default:
            break;

        }
    }
    if (state2 == 0)
    {
        FengShan_ON();
        OLED_ShowString(2, 10, "ON ");
    }
    if (state2 == 1)
    {
        FengShan_OFF();
        OLED_ShowString(2, 10, "OFF");
    }

    if (state2_1 == 1)
    {
        ShuiBen_ON();
        OLED_ShowString(3, 10, "ON ");
    }
    if (state2_1 == 0)
    {
        ShuiBen_OFF();
        OLED_ShowString(3, 10, "OFF");
    }

    if (state2_2 == 1)
    {
        LED_ON();
        OLED_ShowString(4, 10, "ON ");
    }
    if (state2_2 == 0)
    {
        LED_OFF();
        OLED_ShowString(4, 10, "OFF");
    }
}

void ChuanGan()
{
    OLED_ShowChinese(3, 1, 63);
    OLED_ShowChinese(3, 2, 65);
    OLED_ShowString(3, 5, ":");
    OLED_ShowNum(3, 6, sensor.Tu_Humi, 2);
    OLED_ShowString(3, 8, "%");

    OLED_ShowChinese(2, 1, 26);
    OLED_ShowChinese(2, 2, 28);
    OLED_ShowString(2, 5, ":");
    if (temperature < 0)
    {
        OLED_ShowString(2, 6, "-");     //显示负号
        temperature = -temperature;                 //转为正数
    }
    else OLED_ShowString(2, 6, "+");        //去掉负号
    OLED_ShowNum(2, 7, temperature / 10, 2);
    OLED_ShowString(2, 9, ".");
    OLED_ShowNum(2, 10, temperature % 10, 1);
		
		OLED_ShowNum(2, 12, co2, 4);

    OLED_ShowChinese(3, 5, 4);
    OLED_ShowChinese(3, 6, 6);
    OLED_ShowString(3, 13, ":");

    OLED_ShowNum(3, 14, sensor.Guang, 2);

    OLED_ShowChinese(4, 1, 67);
    OLED_ShowChinese(4, 2, 68);
    OLED_ShowString(4, 5, ":");
    OLED_ShowNum(4, 6, temperature_Yu / 10, 2);
    OLED_ShowNum(4, 9, sensor.Tu_Humi_Yu, 2);
    OLED_ShowNum(4, 12, sensor.Guang_Yu, 2);
}

void TimeRead()
{
    MyRTC_ReadTime();

    OLED_ShowNum(1, 2, MyRTC_Time[1], 2);    //时
    OLED_ShowString(1, 4, "/");
    OLED_ShowNum(1, 5, MyRTC_Time[2], 2);    //分


    OLED_ShowNum(1, 8, MyRTC_Time[3], 2);    //时
    OLED_ShowString(1, 10, ":");
    OLED_ShowNum(1, 11, MyRTC_Time[4], 2);    //分
    OLED_ShowString(1, 13, ":");
    OLED_ShowNum(1, 14, MyRTC_Time[5], 2);   //秒
}


七、总结

本文设计了一款基于STM32的智能火灾报警系统,采用STM32F103C8T6作为主控芯片,集成温湿度、烟雾、火焰等传感器,实现环境监测与火灾预警功能。系统具备自动、手动、远程三种控制模式:自动模式下通过传感器数据触发喷水灭火、排风等联动操作;手动模式支持按键直接控制设备;远程模式通过ESP8266连接阿里云平台实现手机APP远程监控。系统还包含OLED显示、声光报警、后备电源等功能模块,通过模块化程序设计实现了火灾检测、报警和联动控制的完整解决方案。该设计具有实用性强、响应快速、操作灵活等特点。

八、资料内容

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐