1. 项目概述
这个台灯控制系统设计项目源于我大学期间的毕业设计课题。作为一名电子工程专业的学生,我希望能将课堂所学理论知识转化为实际可用的产品。选择台灯作为载体,是因为它既贴近日常生活,又能充分体现嵌入式系统设计的核心要素。
传统台灯只能简单开关,而现代人对灯光环境的需求越来越精细化。无论是阅读、工作还是休息,不同场景下对亮度的需求差异很大。市面上的智能台灯动辄上千元,而我们的目标是用最基础的电子元件,实现一个低成本但功能完善的可调光系统。
整套系统硬件部分采用STM32F103C8T6作为主控芯片,搭配PWM调光电路和光敏传感器;软件层面则通过PID算法实现亮度闭环控制。最终成品不仅支持手动无级调光,还能根据环境光线自动调节亮度,实测功耗低于5W,材料成本不到80元。
2. 核心硬件设计
2.1 主控芯片选型
在对比了Arduino、51单片机和STM32三个方案后,最终选择了STM32F103C8T6(俗称"蓝莓派")。这款Cortex-M3内核的芯片具有以下优势:
- 72MHz主频满足实时控制需求
- 多达15个PWM通道可供选择
- 内置12位ADC便于光敏采样
- 价格仅10元左右性价比突出
注意:STM32有LQFP48和LQFP64两种封装,购买时务必确认开发板对应的封装型号。我曾因买错封装导致需要飞线焊接。
2.2 PWM调光电路设计
LED调光本质是通过改变导通时间来调节亮度。我们采用MOSFET IRF540N作为开关器件,其关键参数:
- 最大漏极电流33A(远超过LED需求)
- 导通电阻44mΩ
- 栅极阈值电压2-4V
电路设计要点:
- 在MOSFET栅极串联100Ω电阻防止振荡
- 漏极与LED间需加续流二极管(1N4007)
- LED需串联限流电阻,计算公式:
R = (Vcc - Vf) / If
以5V电源、3.3V LED、20mA电流为例:
R = (5-3.3)/0.02 = 85Ω 取标准值100Ω
2.3 环境光检测模块
采用BH1750数字光照传感器,相比传统光敏电阻有以下优势:
- 直接输出数字信号(I2C接口)
- 测量范围1-65535 lux
- 无需额外设计分压电路
- 内置16bit ADC分辨率
接线示意图:
code复制BH1750 STM32
VCC --- 3.3V
GND --- GND
SCL --- PB6
SDA --- PB7
3. 软件系统实现
3.1 开发环境搭建
使用Keil MDK作为IDE,需要安装以下组件:
- STM32F1xx_DFP设备支持包
- CMSIS核心库(5.7.0版本)
- HAL库或标准外设库(本项目使用HAL)
实测发现:Keil v5.37与STM32CubeMX生成的代码存在兼容性问题,建议使用v5.36版本。
3.2 PWM配置关键代码
c复制// PWM初始化
TIM_HandleTypeDef htim3;
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 71; // 72MHz/(71+1)=1MHz
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 999; // 1MHz/1000=1kHz PWM频率
HAL_TIM_PWM_Init(&htim3);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 初始占空比50%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
3.3 亮度控制算法
采用增量式PID算法实现平滑调光:
c复制typedef struct {
float Kp, Ki, Kd;
float error, lastError;
float integral, output;
} PID_Controller;
void PID_Update(PID_Controller* pid, float setpoint, float actual) {
pid->error = setpoint - actual;
pid->integral += pid->error;
float derivative = pid->error - pid->lastError;
pid->output = pid->Kp * pid->error
+ pid->Ki * pid->integral
+ pid->Kd * derivative;
pid->lastError = pid->error;
// 输出限幅
if(pid->output > 1000) pid->output = 1000;
if(pid->output < 0) pid->output = 0;
}
参数整定经验:
- 先调Kp直到出现小幅振荡
- 然后加入Ki消除静差
- Kd一般取0除非响应速度要求极高
- 最终参数:Kp=0.8, Ki=0.05, Kd=0
4. 系统集成与测试
4.1 硬件组装要点
-
焊接顺序建议:
- 先焊接最小系统(主控+晶振+复位)
- 然后电源电路(AMS1117稳压)
- 最后接外围模块(PWM、传感器)
-
布局技巧:
- 大电流走线(如LED回路)尽量短粗
- 数字与模拟地单点连接
- PWM信号线远离模拟输入
4.2 功能测试方案
设计四组测试场景:
| 测试项 | 预期结果 | 实测数据 |
|---|---|---|
| 手动调光范围 | 5%-100% | 3%-98% |
| 自动调光响应时间 | <1s | 0.8s |
| 待机功耗 | <0.5W | 0.3W |
| 最大亮度功耗 | <5W | 4.7W |
4.3 常见问题排查
-
LED闪烁不稳定:
- 检查PWM频率是否过低(建议1kHz以上)
- 确认电源容量足够(至少1A输出)
- 测量MOSFET栅极驱动电压
-
自动模式不灵敏:
- BH1750是否被遮挡
- I2C上拉电阻是否安装(4.7kΩ)
- 采样周期是否合理(建议200ms)
-
主控发热严重:
- 检查3.3V对地电阻
- 降低系统时钟频率测试
- 确认没有引脚短路
5. 项目优化方向
在实际使用三个月后,发现几个可以改进的点:
-
增加WiFi模块(ESP-01S)实现手机控制
- 需注意STM32的串口资源分配
- 建议使用AT指令简化开发
-
加入定时功能
- 利用RTC实现自动开关
- 需要备份电池(CR2032)
-
改进外壳设计
- 3D打印可调角度灯罩
- 增加触摸按键替代旋钮
这个项目最让我意外的是PID参数对用户体验的影响。最初使用开环控制时,亮度变化生硬;引入PID后,过渡变得非常自然。一个小技巧是:当检测到用户手动调节时,可以临时增大Kp值,使响应更迅速。