目录
一、前言
项目成品图片:
哔哩哔哩视频链接:
STM32智能大棚(蓝牙版)
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的智能大棚(蓝牙版)
功能如下:
- STM32F103C8T6单片机作为主控制器
- 防水式DS18B20检测土壤温度,当温度大于设置最大值,进行声光报警,并同时开启风扇进行降温;当温度小于设置最小值,进行声光报警,并同时开启加热片进行升温
- 土壤湿度模块检测土壤湿度,当湿度小于设置最小值,进行声光报警,并同时开启水泵进行加水,直到湿度大于设置最大值;
- 光敏电阻检测光照值,当光照值低于设置最小值进行补光
- 通过按键设置各阈值
- OLED显示屏显示测量值
- 蓝牙模块将测量数据发送到手机端
2.主要器件
- STM32F103C8T6单片机
- OLED 屏幕
- DS18B20温度传感器
- 光敏传感器
- 土壤湿度传感器
- BT04A蓝牙模块
- 继电器
- 有源蜂鸣器
- 加热片
- 水泵
- 风扇模块
- LED照明灯模块
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "ds18b20.h"
#include "adc.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组
Delay_Init(); //延时初始化
Gpio_Init(); //IO初始化
Key_Init(); //按键初始化
Oled_Init(); //OLED初始化
Oled_Clear_All(); //清屏
Usart1_Init(9600); //串口1初始化
DS18B20_Init(); //DS18B20初始化
Adc_Init(); //ADC初始化
Delay_ms(1000);
Delay_ms(1000);
while(1)
{
key_num = Chiclet_Keyboard_Scan(0); //按键扫描
if(key_num != 0) //有按键按下
{
switch(key_num)
{
case 1: //按键1,切换设置界面
flag_display++;
if(flag_display >= 6)
flag_display = 0;
Oled_Clear_All(); //清屏
break;
case 2: //按键2
switch(flag_display)
{
case 1: //界面1:温度最大值+1
if(temp_max < 99)
temp_max++;
break;
case 2: //界面2:温度最小值+1
if(temp_min < temp_max-1)
temp_min++;
break;
case 3: //界面3:湿度最大值+1
if(soil_max < 99)
soil_max++;
break;
case 4: //界面4:湿度最小值+1
if(soil_min < soil_max-1)
soil_min++;
break;
case 5: //界面5:光照最小值
if(light_min < 99)
light_min++;
break;
default:
break;
}
break;
case 3: //按键3
switch(flag_display)
{
case 1: //界面1:温度最大值-1
if(temp_max > temp_min+1)
temp_max--;
break;
case 2: //界面2:温度最小值-1
if(temp_min > 0)
temp_min--;
break;
case 3: //界面3:湿度最大值-1
if(soil_max > soil_min+1)
soil_max--;
break;
case 4: //界面4:湿度最小值-1
if(soil_min > 0)
soil_min--;
break;
case 5: //界面5:光照最小值-1
if(light_min > 0)
light_min--;
break;
default:
break;
}
break;
default:
break;
}
}
if(flag_display == 0) //测量界面
{
if(time_num % 5 == 0) //获取数据
{
temp_value = DS18B20_Get_Temp();
light_value = 99-30*(Get_Adc_Average(0,3)*3.3/4096.0);
soil_value = 99-30*(Get_Adc_Average(1,3)*3.3/4096.0);
}
if(time_num % 30 == 0) //发送数据
{
UsartPrintf(USART1,"温度:%d.%dC\r\n",temp_value/10,temp_value%10);
UsartPrintf(USART1,"湿度:%d%%\r\n",soil_value);
UsartPrintf(USART1,"光照:%dLux\r\n",light_value);
}
}
switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
{
case 0: //界面0:显示温度,湿度,光照的数值
Oled_ShowCHinese(1,1,"土壤环境监测");
Oled_ShowCHinese(2,0,"温度:");
sprintf(display_buf,"%d.%dC ",temp_value/10,temp_value%10);
Oled_ShowString(2,6,display_buf);
Oled_ShowCHinese(3,0,"湿度:");
sprintf(display_buf,"%d%% ",soil_value);
Oled_ShowString(3,6,display_buf);
Oled_ShowCHinese(4,0,"光照:");
sprintf(display_buf,"%dLux ",light_value);
Oled_ShowString(4,6,display_buf);
break;
case 1: //界面1:设置温度最大值
Oled_ShowCHinese(1,0,"设置温度最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 2: //界面2:设置温度最小值
Oled_ShowCHinese(1,0,"设置温度最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",temp_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 3: //界面3:设置湿度最大值
Oled_ShowCHinese(1,0,"设置湿度最大值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",soil_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 4: //界面4:设置湿度最小值
Oled_ShowCHinese(1,0,"设置湿度最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",soil_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
case 5: //界面5:设置光照最小值
Oled_ShowCHinese(1,0,"设置光照最小值");
if(time_num % 5 == 0)
{
sprintf(display_buf,"%d ",light_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0)
{
Oled_ShowString(2, 7, " ");
}
break;
default:
break;
}
if(flag_display == 0) //测量界面
{
if(temp_value < temp_min*10) //温度小于最小值,开启加热,和声光报警
{
flag_temp_min = 1;
flag_temp_max = 0;
FS = 0;
JR = 1;
}
else if(temp_value > temp_max*10) //温度大于最大值,开启风扇,和声光报警
{
flag_temp_min = 0;
flag_temp_max = 1;
FS = 1;
JR = 0;
}
else //温度在两者之间关闭风扇和加热和声光报警
{
flag_temp_min = 0;
flag_temp_max = 0;
FS = 0;
JR = 0;
}
if(soil_value < soil_min) //湿度小于最小值开启水泵和声光报警
{
flag_soil_min = 1;
JS = 1;
}
else if(soil_value > soil_max) //湿度大于最大值关闭水泵和声光报警
{
flag_soil_min = 0;
JS = 0;
}
else //湿度在两者之间关闭声光报警
{
flag_soil_min = 0;
}
if(light_value < light_min) //光照小于最小值开启补光
BG = 1;
else //光照大于最小值关闭补光
BG = 0;
if(flag_temp_min == 1 || flag_temp_max == 1 || flag_soil_min == 1)
{
if(time_num % 3 == 0) //开启声光报警
{
LED = ~LED;
BEEP = ~BEEP;
}
}
else //关闭声光报警
{
LED = 1;
BEEP = 0;
}
}
else //设置界面
{
LED = 1;
BEEP = 0;
FS = 0;
JS = 0;
JR = 0;
BG = 0;
}
time_num++; //计时变量+1
Delay_ms(10);
if(time_num %10 == 0)
LED_SYS = ~LED_SYS;
if(time_num >= 5000)
{
time_num = 0;
}
}
}
六、实验效果
七、资料内容