基于STM32的楼道声光控系统设计
一、系统概述与核心功能
1. 系统定位
基于STM32的楼道声光控系统以“环境感知-智能判断-节能控制”为核心,通过光线传感器与声音传感器融合检测,实现楼道照明的“人来灯亮、人走灯灭、光控优先”功能,替代传统声控/光控开关,解决白天误亮、夜间长明灯等问题,适用于居民楼、办公楼、地下车库等场景,显著降低能耗。
2. 核心功能模块
| 模块 | 功能描述 |
|---|---|
| 环境感知 | 光敏电阻(或BH1750)检测环境亮度(区分白天/黑夜),声音传感器(如LM393)检测脚步声/说话声 |
| 智能判断 | 光控优先:白天(光线充足)不响应声音;夜间(光线不足)检测到声音后触发亮灯 |
| 延时控制 | 亮灯后延时30秒(可调)自动熄灭,期间再次检测到声音则重置延时(避免频繁开关) |
| 执行控制 | 继电器(或可控硅)驱动220V交流灯,支持过零检测(可选,减少继电器损耗) |
| 低功耗设计 | 待机时STM32进入STOP模式,传感器中断唤醒,续航≥1年(市电供电,无电池依赖) |
| 状态指示 | LED指示灯(红:待机,绿:亮灯),蜂鸣器提示(可选,操作反馈) |
二、硬件设计方案
1. 核心硬件选型
| 模块 | 型号 | 关键参数 | 接口方式 |
|---|---|---|---|
| 主控MCU | STM32F103C8T6 | 72MHz Cortex-M3,64KB Flash,20KB RAM,12位ADC,2个定时器,支持低功耗模式 | 核心控制器 |
| 光线传感器 | 光敏电阻GL5528 | 亮电阻5-10kΩ(光照),暗电阻1-2MΩ(黑暗),模拟输出,响应时间<1s | ADC1_IN0(PA0,分压电路) |
| 声音传感器 | LM393声音检测模块 | 数字输出(高电平触发),检测范围30-80dB,可调电位器调节灵敏度,带指示灯 | GPIO(PA1,外部中断) |
| 执行模块 | 5V继电器模块(带光耦) | 触点容量10A/250V AC,光耦隔离,低电平触发(STM32 GPIO控制) | GPIO(PA2,三极管驱动) |
| 显示模块 | 双色LED(红/绿) | 共阳/共阴,指示待机/亮灯状态 | GPIO(PB0=红,PB1=绿) |
| 电源模块 | 220V转5V开关电源模块 | 输入220V AC,输出5V/2A,给STM32、传感器、继电器供电(继电器需独立5V) | 市电输入,5V输出 |
| 辅助模块 | 有源蜂鸣器(可选) | 5V驱动,85dB,操作提示音 | GPIO(PB2) |
2. 硬件电路设计要点
2.1 核心电路连接
- STM32最小系统:8MHz外部晶振+32.768kHz RTC晶振(可选,用于低功耗计时),SWD调试接口(PA13/PA14),复位电路(10kΩ上拉+0.1μF电容)。
- 光线检测电路:光敏电阻与10kΩ固定电阻串联分压(VCC=5V),中点接PA0(ADC1_IN0),光照越强,ADC值越大(亮电阻小,分压大)。
- 声音检测电路:LM393模块OUT引脚接PA1(外部中断,下降沿触发),VCC=5V,GND共地,电位器调节灵敏度(阈值)。
- 继电器驱动电路:PA2接S8050三极管基极(串联1kΩ限流电阻),三极管集电极接继电器线圈(5V),发射极接地,线圈两端并联1N4007续流二极管(防反峰)。
- LED指示电路:PB0(红灯)和PB1(绿灯)通过220Ω限流电阻接5V,低电平点亮(或高电平,根据LED类型调整)。
2.2 抗干扰与安全设计
- 光耦隔离:继电器模块内置光耦,隔离STM32(3.3V)与220V交流电路,避免高压干扰。
- 电源滤波:5V电源输入端并联1000μF电解电容+0.1μF瓷片电容,滤除市电纹波。
- 防误触设计:声音传感器加RC滤波(1kΩ+0.1μF),避免瞬间噪音误触发;光控阈值通过实验校准(如白天ADC值>3000,黑夜<1000)。
三、软件设计与核心代码
1. 系统架构(前后台系统+中断)
采用前后台系统,以主循环轮询为主,中断处理声音触发事件,核心流程:
-
初始化:配置时钟、ADC(光线检测)、GPIO(声音/继电器/LED)、定时器(延时关灯)。
-
主循环:
- 读取光敏电阻ADC值,判断环境亮度(光控判断)。
- 若光线不足(黑夜),使能声音传感器中断;若光线充足(白天),关闭声音检测。
- 处理延时关灯逻辑(定时器倒计时,超时后关灯)。
-
中断服务:声音传感器触发外部中断,记录触发时间,启动/重置延时定时器。
2. 核心代码实现(基于标准库)
2.1 光线检测与光控判断
#include "stm32f10x.h"
#include "adc.h"
#define LIGHT_THRESHOLD 2000 // 光控阈值(ADC值,>2000=白天,<2000=黑夜)
// 初始化ADC1(PA0,光敏电阻)
void ADC1_Init(void) {
ADC_InitTypeDef ADC_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置PA0为模拟输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// ADC配置(12位,单次转换,软件触发)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStruct);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
}
// 读取光敏电阻ADC值(0-4095)
uint16_t Read_Light_ADC(void) {
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
// 光控判断(返回1=黑夜,0=白天)
uint8_t Is_Dark(void) {
uint16_t adc_val = Read_Light_ADC();
return (adc_val < LIGHT_THRESHOLD) ? 1 : 0; // ADC值小=光线暗
}
2.2 声音检测与中断处理
// 全局变量
uint8_t sound_triggered = 0; // 声音触发标志
uint32_t last_sound_time = 0; // 上次声音触发时间(ms)
// 外部中断配置(PA1,声音传感器OUT)
void EXTI1_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
// PA1配置为输入(上拉)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 外部中断线1配置(PA1)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
EXTI_InitStruct.EXTI_Line = EXTI_Line1;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发(声音触发时OUT从高变低)
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
// NVIC配置(优先级分组1,抢占优先级0,子优先级0)
NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
// 外部中断1服务函数(声音触发)
void EXTI1_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_Line1) != RESET) {
if (Is_Dark()) { // 仅在黑夜响应声音
sound_triggered = 1;
last_sound_time = HAL_GetTick(); // 记录触发时间(需实现HAL_GetTick,或用SysTick)
}
EXTI_ClearITPendingBit(EXTI_Line1); // 清除中断标志
}
}
2.3 延时关灯与继电器控制
// 全局变量
#define LIGHT_ON_TIME 30000 // 亮灯时间(30秒=30000ms)
uint8_t light_state = 0; // 灯状态(0=关,1=开)
// 继电器控制(PA2,高电平触发)
void Relay_Control(uint8_t state) {
GPIO_WriteBit(GPIOA, GPIO_Pin_2, state ? Bit_SET : Bit_RESET);
light_state = state;
// LED指示:绿灯亮=开,红灯亮=关
GPIO_WriteBit(GPIOB, GPIO_Pin_0, state ? Bit_RESET : Bit_SET); // 红灯
GPIO_WriteBit(GPIOB, GPIO_Pin_1, state ? Bit_SET : Bit_RESET); // 绿灯
}
// 主循环中的延时处理逻辑
void Main_Loop_Process(void) {
static uint32_t timer_count = 0;
if (sound_triggered) {
sound_triggered = 0;
if (!light_state) { // 灯未亮时,启动亮灯
Relay_Control(1); // 开灯
timer_count = HAL_GetTick(); // 启动定时器
} else { // 灯已亮时,重置延时
timer_count = HAL_GetTick();
}
}
// 灯亮状态下,检查延时是否超时
if (light_state) {
if (HAL_GetTick() - timer_count > LIGHT_ON_TIME) {
Relay_Control(0); // 关灯
}
}
// 白天自动关灯(双重保障)
if (!Is_Dark() && light_state) {
Relay_Control(0);
}
}
2.4 主程序框架
#include "stm32f10x.h"
#include "adc.h"
#include "exti.h"
#include "relay.h"
int main(void) {
HAL_Init(); // 初始化HAL库(若用标准库,可替换为SystemInit)
SystemClock_Config(); // 配置系统时钟72MHz
ADC1_Init(); // 初始化ADC(光线检测)
EXTI1_Init(); // 初始化外部中断(声音检测)
Relay_Init(); // 初始化继电器/LED(GPIO配置)
while (1) {
Main_Loop_Process(); // 主循环处理(延时关灯、光控判断)
HAL_Delay(100); // 100ms轮询一次(降低CPU占用)
}
}
参考代码 基于STM32的楼道声光控设计 www.youwenfan.com/contentcst/133690.html
四、关键技术与优化
1. 抗干扰与误触发抑制
- 声音滤波:软件层面增加“声音持续时间判断”(如检测到低电平持续>200ms才认为有效触发),避免瞬间噪音(如关门声)误触发。
- 光控校准:通过实验调整
LIGHT_THRESHOLD(如白天遮挡光敏电阻,记录ADC值作为阈值),确保在黄昏/黎明时准确切换。
2. 低功耗设计
- STOP模式:无操作时(白天或灯灭后),STM32进入STOP模式(关闭ADC、定时器时钟),通过声音传感器中断(PA1)唤醒。
- 传感器休眠:白天光线充足时,关闭声音传感器电源(通过GPIO控制其VCC),进一步降低功耗。
3. 延时精度优化
- 定时器替代延时:用STM32定时器(如TIM2)替代
HAL_GetTick()软件延时,实现毫秒级精准计时(配置TIM2为1ms中断,更新全局时间戳)。
五、系统调试与扩展
1. 调试步骤
| 阶段 | 操作 | 工具 |
|---|---|---|
| 硬件调试 | 测量光敏电阻分压(光照/黑暗时ADC值)、继电器线圈电压(吸合时5V) | 万用表、示波器 |
| 传感器测试 | 遮挡光敏电阻(模拟黑夜),拍手触发声音传感器,观察继电器是否吸合 | 肉眼观察LED状态 |
| 延时测试 | 亮灯后计时30秒,检查是否自动熄灭;再次发声,检查是否重置延时 | 秒表、逻辑分析仪(GPIO波形) |
| 功耗测试 | 白天待机时测量STM32电流(应<10mA),STOP模式下<1mA | 万用表(电流档) |
2. 扩展功能
- 人体红外融合:添加HC-SR501人体红外传感器(PIR),与声音传感器“或逻辑”触发(检测到人或声音均亮灯),提升检测可靠性。
- 远程控制:添加ESP8266 Wi-Fi模块,通过手机APP手动开关灯、调整延时时间(需修改软件支持TCP/UDP通信)。
- 电量监测:若用电池供电(如太阳能场景),添加电流传感器(ACS712)监测电池电压,低电量时LED闪烁报警。