文章目录
一、前言
实物项目成品:

仿真项目成品:

n/direct/e9f8c5792cfa462e9b89acb77c465491.png)
哔哩哔哩开源视频链接(复制浏览器打开):
https://www.bilibili.com/video/BV1g2eu6YEeg/?vd_source=10da4d04d580bd6b34f7298120737c50
(资料分享见文末)
二、项目功能简介
【开源】STM32单片机智能插座控制系统(代码 + 原理图 + 仿真)
功能介绍:
- 使用 OLED 屏幕实时显示采集到的温度数据与插座实时功率;
- 通过 DS18B20 温度传感器采集环境温度;
- 采用 HLW8032 电能计量模块采集插座输出功率;
- 搭载语音识别模块,通过语音指令控制插座通断;
- 实时对比采集数据与设定阈值,当温度或功率超过阈值时,插座自动断电,同时蜂鸣器声光报警;
- 手机机智云 APP 可同步查看 OLED 上的温度、功率数据,并且远程控制插座的开启与断开。
三、PCB设计

四、原理图设计

五、程序设计
代码如下():
c
#include "sys.h"
#include "adc.h"
#include "delay.h"
#include "OLED.h"
#include "ds18b20.h"
#include "esp8266.h"
#include "timer.h"
#include "dht11.h"
#include "PWM.h"
#include "gpio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned int light=0;
unsigned char temperature=0;
unsigned char Humi;
unsigned char setTempValue=35;
unsigned int setHumiValue=70;
unsigned int setLightValue=900;
unsigned int LightValue=0;
bool usart_send_flag = 0;
bool mode = 0;
bool shuaxin = 0;
bool shanshuo = 0;
bool sendFlag = 1;
u8 buff[30];//参数显示缓存数组
u8 count;
uint8_t Ren; // 人
unsigned char setn=0;
void Red_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
uint8_t Red_Rdata(void)//获取有人无人的数据
{
return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);
}
void displayLight(void)
{
u16 test_adc=0;
static u16 last_light[5] = {0}; // 保存最近5次的光照值,用于滑动平均滤波
static u8 filter_index = 0; // 当前滤波数组索引
u16 sum = 0; // 用于计算平均值的总和
// 增加采样次数,从20次增加到30次
test_adc = Get_Adc_Average(ADC_Channel_0,30);
// 计算当前光照值
u16 current_light = test_adc*1000/4096;
//current_light = 99 - current_light;
// 更新滑动窗口数组
last_light[filter_index] = current_light;
filter_index = (filter_index + 1) % 5; // 循环更新索引
// 计算滑动平均值
for(u8 i = 0; i < 5; i++) {
sum += last_light[i];
}
// 如果是初始状态(前几次采样),使用当前值
if(last_light[4] == 0) {
light = current_light;
} else {
// 使用滑动平均值,但对新值赋予更高权重
// 新值占20%,历史平均值占80%
light = (current_light * 2 + (sum / 5) * 8) / 10;
}
// 确保值在合理范围内
light = light >= 1000? 1000: (light <= 0? 0: light);
if(light<=setLightValue && shanshuo)
{
// OLED_ShowString(16*6,32," ",16);
}
else
{
//OLED_ShowNum(3, 13, light, 4);
sprintf((char*)buff,"%2d Luz",light);
OLED_ShowString(3,7,(char*)buff); //显示光照
}
}
void displayTemp_Humierature(void)
{
DHT11_Read_Data(&Humi,&temperature);
if(temperature>=setTempValue && shanshuo)
{
//OLED_ShowString(16*6,16," ",16);
}
else
{
if(temperature!=0)
{
sprintf((char*)buff,"%2d C",temperature);
OLED_ShowString(1,7,(char*)buff);
}
}
if(Humi<=setHumiValue && shanshuo)
{
// OLED_ShowString(16*6,0," ",16);
}
else
{
sprintf((char*)buff,"%2d %%",Humi);
OLED_ShowString(2,7,(char*)buff); //显示温度
}
}
void displaySetValue(void)
{
if(setn == 1)
{
if(shanshuo)
{
OLED_ShowString(2,11," ");
}
else
{
sprintf((char*)buff,"%2dC",setTempValue);
OLED_ShowString(2,11,(char*)buff);
sprintf((char*)buff,"%2d%%",setHumiValue);
OLED_ShowString(3,11,(char*)buff);
sprintf((char*)buff,"%2dLux",setLightValue);
OLED_ShowString(4,11,(char*)buff);
}
}
if(setn == 2)
{
if(shanshuo)
{
OLED_ShowString(3,11," ");
}
else
{
sprintf((char*)buff,"%2dC",setTempValue);
OLED_ShowString(2,11,(char*)buff);
sprintf((char*)buff,"%2d%%",setHumiValue);
OLED_ShowString(3,11,(char*)buff);
sprintf((char*)buff,"%2dLux",setLightValue);
OLED_ShowString(4,11,(char*)buff);
}
}
if(setn == 3)
{
if(shanshuo)
{
OLED_ShowString(4,11," ");
}
else
{
sprintf((char*)buff,"%2dC",setTempValue);
OLED_ShowString(2,11,(char*)buff);
sprintf((char*)buff,"%2d%%",setHumiValue);
OLED_ShowString(3,11,(char*)buff);
sprintf((char*)buff,"%2dLux",setLightValue);
OLED_ShowString(4,11,(char*)buff);
}
}
}
void keyscan(void)
{
if(KEY1 == 0)
{
delay_ms(20);
if(RELAY2==1)delay_ms(50);
if(KEY1 == 0)
{
while(KEY1 == 0);
if(setn == 0)
{
mode = !mode;
if(mode==0)
{
OLED_ShowChinese(4,4,19);
OLED_ShowChinese(4,5,20);
}
else
{
RELAY1=0;
RELAY2=0;
RELAY3=0;
OLED_ShowChinese(4,4,21);
OLED_ShowChinese(4,5,22);
}
}
}
}
if(KEY2 == 0)
{
delay_ms(20);
if(KEY2 == 0)
{
while(KEY2 == 0);
BEEP=0;
if(mode==0)
{
setn ++;
PWM_SetCompare2(0);
RELAY2=0;
}
if(setn == 0 && mode==1)
{
PWM_SetCompare2(0);
}
if(setn == 1)
{
OLED_Clear();
}
if(mode==1)
{
RELAY3=~RELAY3;;
}
if(setn == 1||setn == 2||setn == 3)
{
OLED_ShowChinese(1,3,16);
OLED_ShowChinese(1,4,17);
OLED_ShowChinese(1, 5, 23);
OLED_ShowChinese(1, 6, 24);
//显示"温度阈值:"
OLED_ShowChinese(2, 1, 2);
OLED_ShowChinese(2, 2, 3);
OLED_ShowChinese(2, 3, 23);
OLED_ShowChinese(2, 4, 24);
OLED_ShowChar(2, 9, ':');
//显示"湿度阈值:"
OLED_ShowChinese(3, 1, 6);
OLED_ShowChinese(3, 2, 7);
OLED_ShowChinese(3, 3, 23);
OLED_ShowChinese(3, 4, 24);
OLED_ShowChar(3, 9, ':');
//显示"光照阈值:"
OLED_ShowChinese(4, 1, 10);
OLED_ShowChinese(4, 2, 11);
OLED_ShowChinese(4, 3, 23);
OLED_ShowChinese(4, 4, 24);
OLED_ShowChar(4, 9, ':');
}
displaySetValue();
if(setn >= 4)
{
OLED_Clear();
setn = 0;
//显示"温度:"
OLED_ShowChinese(1, 1, 2);
OLED_ShowChinese(1, 2, 3);
OLED_ShowChar(1, 5, ':');
//显示"湿度:"
OLED_ShowChinese(2, 1, 6);
OLED_ShowChinese(2, 2, 7);
OLED_ShowChar(2, 5, ':');
//显示"光照:"
OLED_ShowChinese(3, 1, 8);
OLED_ShowChinese(3, 2, 9);
OLED_ShowChar(3, 5, ':');
//显示"工作模式:"
OLED_ShowChinese(4,1,14);
OLED_ShowChinese(4,2,15);
OLED_ShowChar(4, 5, ':');
if(mode==0)
{
OLED_ShowChinese(4,4,19);
OLED_ShowChinese(4,5,20);
}
else
{
OLED_ShowChinese(4,4,21);
OLED_ShowChinese(4,5,22);
}
}
}
}
if(KEY3 == 0)//加
{
delay_ms(20);//
if(KEY3 == 0 )
{
while(KEY3 == 0);
if(setn == 0 && mode==1)
{
if(LightValue==0)
{
LightValue=setLightValue;
}
LightValue+=100;
if(LightValue>=1000)
LightValue=10;
PWM_SetCompare2(LightValue);
}
if(setn == 2)
{
if(setHumiValue<99)setHumiValue++;
}
if(setn == 1)
{
if(setTempValue<99)setTempValue++;
}
if(setn == 3)
{
if(setLightValue<999)setLightValue+=100;
}
displaySetValue();
}
}
if(KEY4 == 0)//减
{
delay_ms(20);//
if(RELAY2==1)delay_ms(50);
if(KEY4 == 0 )
{
while(KEY4 == 0);
if(setn == 0 && mode==1)
{
RELAY2=~RELAY2;
}
if(setn == 2)
{
if(setHumiValue>0)setHumiValue--;
}
if(setn == 1)
{
if(setTempValue>0)setTempValue--;
}
if(setn == 3)
{
if(setLightValue>0)setLightValue-=100;
}
displaySetValue();
}
}
}
int main(void)
{
delay_init();
NVIC_Configuration();
delay_ms(500);
Adc_Init(); //光照adc初始化
KEY_GPIO_Init(); //按键初始化
DHT11_Init(); //DHT11初始化
Red_Init(); //人体检测
PWM_Init(); //PWM初始化
OLED_Init(); //OLED初始化
OLED_Clear();
OLED_ShowString(2,1," Loading... ");
delay_ms(1000);
OLED_Clear();
//显示"温度:"
OLED_ShowChinese(1, 1, 2);
OLED_ShowChinese(1, 2, 3);
OLED_ShowChar(1, 5, ':');
//显示"湿度:"
OLED_ShowChinese(2, 1, 6);
OLED_ShowChinese(2, 2, 7);
OLED_ShowChar(2, 5, ':');
//显示"光照:"
OLED_ShowChinese(3, 1, 8);
OLED_ShowChinese(3, 2, 9);
OLED_ShowChar(3, 5, ':');
//显示"工作模式:"
OLED_ShowChinese(4,1,14);
OLED_ShowChinese(4,2,15);
OLED_ShowChar(4, 5, ':');
TIM3_Init(99,719);
while(1)
{
keyscan();
if(setn == 0)
{
if(shuaxin == 1)
{
shuaxin = 0;
displayLight();
displayTemp_Humierature();
Ren=Red_Rdata();
if(Ren==1)
{
OLED_ShowChinese(1,7,25);
OLED_ShowChinese(1,8,27);
}
else
{
OLED_ShowChinese(1,7,26);
OLED_ShowChinese(1,8,27);
}
if(mode==0)
{
if(Ren==1) //有人
{
if(light<=setLightValue)
PWM_SetCompare2(1000-light);
else
PWM_SetCompare2(0);
}
else //无人自动关灯
{
PWM_SetCompare2(0);
}
if(temperature>=setTempValue||Humi>=setHumiValue)RELAY2=1;else RELAY2=0;
if(temperature>=setTempValue||Humi>=setHumiValue)BEEP=1;else BEEP=0;
OLED_ShowChinese(4,4,19);
OLED_ShowChinese(4,5,20);
}
else
{
BEEP=0;
OLED_ShowChinese(4,4,21);
OLED_ShowChinese(4,5,22);
}
}
}
if(setn!=0)
{
displaySetValue();
}
delay_ms(10);
}
}
void TIM3_IRQHandler(void)
{
static u16 timeCount1 = 0;
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
timeCount1++;
if(timeCount1 >= 300) //300ms
{
timeCount1 = 0;
shanshuo = !shanshuo;
shuaxin = 1;
}
}
}
六、包含内容

七、资料分享
资料获取:请查看主页介绍搜索或观看开源视频获取