拓冰建站拓冰建站
首页 / 资讯中心 / 正文

STM32+可控硅零点检测:白炽灯无级调光实战解析

简介一套基于STM32的白炽灯亮度调节完整工程面向嵌入式开发者和智能照明设计人员。资源以零点检测与可控硅Triac控制为核心展示如何借助定时器PWM输出、GPIO中断和软件调度实现交流负载的连续调光同时兼顾多灯控制与电气安全。工程文件共238个约6.22MB主要包含STM32标准外设库的C/H源码、编译生成的HEX固件、Keil工程文件uvprojx/uvoptx以及调试配置与链接脚本便于直接打开、编译和烧录验证。已有1104人学习下载项目结构清晰注释完整适合想掌握交流调光原理的STM32初学者进阶参考也可为智能家居调光方案提供实现蓝本。零点检测 可控硅控制用 STM32 给白炽灯做无级调光全解析一说到用 STM32 调白炽灯亮度很多人的第一反应是“这不就是 PWM 么”我当初也是这么想的直到自己画板子、写代码、焊元件、上强电实测之后才发现 PWM 和可控硅调光完全是两码事——前者是把低压直流斩波后者要在 220V 交流电上做相位控制中间隔着的是零点检测、隔离驱动、过零触发、负载冲击这些问题。整个项目做完我对可控硅这个器件、强电和弱电之间的配合方式理解比啃十篇芯片手册都深刻。这个项目适合哪些人做如果你的水平是“能跑个流水灯、能配置个定时器中断”那就可以入手了。它不需要复杂的算法也不需要高端的 DSP核心工具就是 STM32 的 GPIO 外部中断、一个定时器、一路光耦隔离的零点检测电路、一路可控硅触发电路。硬件成本按散件算不超过 30 块钱DIY 价值感却非常高做完你就能把一个普通白炽灯改成“从暗到亮、从亮到暗”平滑变化的智能调光灯。如果你正在做智能家居相关的毕业设计或者项目练习这个方案还可以顺势扩展成手机蓝牙调光、红外遥控调光甚至加个传感器做自动亮度调节。这篇文章我直接把整个项目的方案选型、电路原理、软件实现、实测踩坑全拆开讲照着走一遍你就能跑起来。1. 项目整体设计与电路方案思路1.1 为什么白炽灯调光能成为经典教学案例白炽灯和别的负载不一样它是纯阻性负载钨丝的温度直接决定亮度而钨丝的热惯性不大不小用在相位控制调光上效果非常直观。普通 LED 灯驱动电源内部的整流滤波电路对波形要求高直接上可控硅很容易出问题闪烁、啸叫或者干脆不工作电机或者变压器这类感性负载又牵扯到反电动势调试难度直接翻倍。反倒是白炽灯只要有效值电压能降下来亮度就跟着降控制模型干干净净没有任何奇怪的反馈或者补偿要做。换个角度看这个负载特性也给了我们一个很好的“避风港”你不需要在硬件上处理复杂的负载特性可以把全部精力放在可控硅相位控制的原理和实现上。很多书和教程讲电力电子都爱拿白炽灯举例子原因就在这里。所以我强烈建议第一次做可控硅控制的人一定先用白炽灯练手把电路和逻辑调通了再去碰其他负载。1.2 整体架构弱电控强电的隔离思路整个系统的结构是“强电 弱电”混合体。主控侧是 STM32工作在 3.3V 或 5V 的直流环境要控制的是 220V 交流输出的通断时刻。核心思路不是让单片机直接去推可控硅它也没这个能力而是分三层第一层是零点检测电路。它负责把交流电的过零点转变成单片机认得出来的下降沿或者上升沿信号。ST 官方和网上各种资料里最常见的做法是“整流桥 光耦”方案220V 交流经过整流桥变成 100Hz 的全波脉动直流然后通过限流电阻接到光耦的输入侧。当交流电压接近 0V 时光耦关断输出高电平当电压升到一定值光耦导通输出拉低。STM32 这边的引脚就能捕捉到这些边沿从而知道每一次市电过零的时刻。第二层是触发驱动电路。STM32 的引脚输出高电平时通过三极管或者直接驱动光耦我实际用的是 MOC3021再由光耦输出侧触发双向可控硅的门极G 极。可控硅导通后主回路电流走可控硅的 T1-T2单片机和强电之间被光耦隔开了安全性大大提升。第三层才是负载白炽灯串在交流火线和可控硅之间给可控硅一个触发脉冲灯丝就在当前半波周期的剩余时间里得电发光。这种架构最稳妥的地方在于强电与弱电之间有两级隔离——零点检测的光耦和触发的光耦。板子上电时先测弱电部分再接强电能避免很多危险和返工。提示涉强电操作时必须使用隔离变压器或者在确保断电的情况下接线。示波器测 220V 侧一定要用隔离探头普通探头接地夹一旦误接到火线位置轻则烧设备重则出安全事故。这条不是建议是底线。2. 零点检测与可控硅触发原理详解2.1 零点检测单片机是怎么“看见”市电过零的先明确一点为什么非要做零点检测因为可控硅一旦导通只要电流没有降到维持电流以下它就会一直保持导通门极的信号已经没有控制权了。要想在一个周期内控制灯的亮度唯一的办法是调整在每个半波周期里“什么时候开始导通”。如果你在电压已经很高的时候才触发那么输出电压的有效值就小灯就暗如果你在过零点附近立刻触发那么整个半波都导通灯就最亮。所以“过零点”是所有时间计量的起点。我用的零点检测电路具体参数是这样的220V 交流进 1N4007 整流桥四个二极管组成全桥输出的是 100Hz 全波波形。这个波形经过两只 100kΩ 电阻限流两只串联是为了分摊功率、提高耐压接到 PC817 光耦的 1、2 脚。光耦输出端集电极接 STM32 引脚同时接一个 10kΩ 上拉电阻到 3.3V发射极接地。这个电路在 220V 接近 0V 的小区间内光耦 LED 电流接近 0输出端是上拉高电平电压只要离开零点一小段光耦就饱和导通输出被拉低。所以 STM32 引脚上得到的是一个大约 100Hz 的方波信号方波的每个下降沿对应交流电的一个过零时刻。这里需要强调的是电路输出的是下降沿不是上升沿写中断配置的时候要选下降沿触发。我一开始用的是上升沿触发结果触发时刻偏了接近 90 度灯亮度怎么调都不对查了半天才发现是这个细节。限流电阻的取值算一下就有数了220V 交流的峰值是 311V光耦 LED 正向压降约 1.2V取电流 5mA 左右那么限流电阻就是 (311-1.2)/0.005 ≈ 62kΩ。实际我用了两只 100kΩ 串联总阻值 200kΩ电流大概 1.5mAPC817 的 CTR 在 5mA 时还有 50% 以上但在 1mA 左右比较临界。实测下来可以触发但波形边沿不够陡。后来我把两只 100kΩ 并联等效 50kΩ电流提到了 6mA 左右波形干净很多。这说明零点检测的电阻不是随便选个值就行的要兼顾功率和光耦的电流传输比。2.2 可控硅自锁特性与触发时机的关系双向可控硅Triac这东西的工作方式用一句“过零之后才能管住、导通之后管不住”来描述最形象。它内部是两个反向并联的晶闸管结构无论交流电压是正半波还是负半波只要门极有一个合适的触发电流它就能导通。但一旦导通门极就会“失效”——电流过零之前你没法再关断它。只有当主回路的电流降低到维持电流以下也就是接近过零点时它才会自动关断。这就带来一个非常重要的结论在每个 10ms 的半波周期里你只能决定“从哪个相位开始导通”而不能决定“从哪个相位关断”。所以调光本质上是在调整可控硅的导通角。导通角越大负载上得到的电压波形面积越大灯越亮导通角越小波形被切掉的部分越多灯越暗。那么触发时机怎么和亮度对应起来呢50Hz 交流电的周期是 20ms一个周期里有两个过零点一次从正到负一次从负到正所以相邻两次过零信号的间隔大约 10ms。这 10ms 对应电角度 180°。如果过零后我们延时 t 微秒再触发可控硅那触发角就是(t / 10ms) × 180°。触发角越接近 180°灯的亮度越低。当触发角超过 180° 时说明这一整个半波都没触发灯就完全熄灭。我在软件里用了一个查表思路把触发角 0° 到 170° 映射成不同的延时微秒数。0° 就是全亮170° 几乎看不到灯丝发光。表格做出来后实测调节非常顺滑比现场计算速度还快。2.3 随机相位光耦与过零光耦不能混用这是很多第一次做的人最容易忽略的坑。市面上常见的光耦可控硅驱动器有 MOC3021 和 MOC3061 两个系列外观相似但内部电路差异巨大。MOC3021 是随机相位Random Phase触发光耦它可以在交流电压的任意相位点触发输出而 MOC3061 内置了过零检测电路它只会在输出端交流电压过零附近那一小段窗口内导通。过零型光耦是专门用来控制交流负载通断的比如固态继电器如果拿它来做调光你会发现自己怎么调都只有“全亮”或者“全灭”两个状态——因为它强制把触发点锁在过零附近了。我调试的时候曾经抱着侥幸心理把过零型的光耦焊上去测试结果白炽灯要么亮度几乎不变要么一闪一闪跳变一度怀疑是可控硅坏了。后来翻了数据手册才恍然大悟。到淘宝买元件的时候一定要看清楚规格MOC3021 之类不带过零检测的型号才是做调光的正路。触发光耦输出侧一般接一个 100Ω 到 330Ω 的限流电阻再接到双向可控硅的 T1 和 G 极之间。3. STM32 侧软件实现从捕获过零到精确触发3.1 硬件连接与开发环境准备主控我用的是 STM32F103C8T6蓝色药丸板这个型号对这类项目来说性能绰绰有余而且网上资料和例程极多。开发环境我习惯用 STM32CubeMX 生成初始化代码配上 HAL 库然后迁移到 Keil5 里写业务逻辑。当然用标准库新建工程也完全可以核心差别只是库函数名不同中断逻辑和定时器逻辑是通用的。引脚分配上我把 PB0 接到零点检测输出端配置成外部中断下降沿触发。PC13板载 LED用来做状态指示。可控硅触发引脚用 PB1配置成推挽输出初始化为低电平。如果用的是带 PWM 功能的定时器通道也可以把触发引脚顺便配置成输出比较模式用比较寄存器自动产生延迟脉冲这样 CPU 可以在等待期间干其他事。但这个项目控制逻辑不重直接用 HAL_Delay 或者微秒级延时函数就够了关键是延时精度要够。注意HAL_Delay 默认单位是毫秒而触发角延时大部分时间在几十微秒到几毫秒之间直接用 HAL_Delay 精度不够。我建议用 DWTData Watchpoint and Trace或者 SysTick 写一个微秒级延时函数能做到 us 级别的时间控制。这个细节决定了你的调光曲线是否平滑。3.2 触发角和延时时间的换算表这是整个软件里最核心的一张表。以 50Hz 市电为例半波周期是 10ms对应 180°。延时时长 (目标角度 / 180) × 10000 微秒。目标触发角延时时长亮度效果0°0 us最亮全波导通30°1667 us较亮轻微可感知变暗60°3333 us中等偏亮90°5000 us亮度约一半120°6667 us较暗150°8333 us微亮灯丝发红170°9444 us几乎不可见亮度实际公式是delay_us (angle_deg / 180.0) × 10000。我在程序里预先算好一个 0 到 180 的表格按索引去取避免每次中断都做浮点运算。表格大小我做成 181 个元素每度一个延时值内存占用只有 724 字节完全可以接受。3.3 主循环与中断的配合实现平滑渐亮渐暗很多初学者容易犯的错误是在外部中断服务函数里做延时触发然后在主循环里又用延时控制亮度变化结果中断嵌套和阻塞导致系统卡死或者灯乱闪。正确思路是用“状态 定时器”的方式外部中断过零信号里只做一件事读取当前目标延时值然后调用微秒延时函数延时结束触发可控硅拉高 PB1 几微秒再拉低。这段流程在中断里执行耗时最多 10ms触发角为 180° 时期间其他中断会被挂起但这个项目里没有其他高优先级事件所以可以接受。主循环里负责缓慢改变目标延时值。比如每 20ms 把目标触发角从 170° 缩小到 0°灯就会在 3 秒内从暗变亮。下面是一段基于标准库写的核心逻辑伪代码uint16_t target_angle 170; // 初始微暗 uint16_t delay_table[181]; void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) ! RESET) { EXTI_ClearITPendingBit(EXTI_Line0); if (target_angle 180) { delay_us(delay_table[target_angle]); // 相位延迟 } // 触发可控硅 GPIO_SetBits(GPIOC, GPIO_Pin_1); delay_us(50); // 维持门极电流 GPIO_ResetBits(GPIOC, GPIO_Pin_1); } } int main(void) { // 初始化... while (1) { if (target_angle 0) target_angle--; delay_ms(10); // 这个值决定渐变速度 } }这里有个小细节可控硅触发脉冲的宽度不需要很长。双向可控硅一旦导通门极电流就可以撤掉了。50 微秒的脉冲已经足够可靠触发太长反而会在感性负载场景下增加功耗。我在实测中把脉冲维持在 50us 左右触发特别稳定没必要搞成 1ms 的长脉冲。4. 实测中的疑难杂症与排查笔记4.1 干扰导致的误触发怎么解决灯忽闪忽灭这个项目是在交流电环境里工作的而交流电本身就是一个巨大的干扰源。我第一次上强电测试的时候灯还能亮但亮度控制不稳定明明设定了一个固定亮度灯丝却在轻微闪烁。用示波器查过零信号发现波形边沿处有一串毛刺光耦输出在下拉状态中途出现反弹单片机把这些抖动当成了好几个下降沿触发了多次中断于是可控硅被错误地触发了。解决干扰问题我做了三件事。第一是硬件上在零点检测光耦输出的集电极和发射极之间并联一个 104100nF陶瓷电容把窄毛刺滤掉。第二是软件上外部中断服务函数开头加了一个防抖判断——只有在距离上一次中断 3ms 以上才响应。不过这里要特别谨慎防抖时间不能太长否则会错失真实的过零信号一般控制在 1ms 到 3ms 之间。第三是布局上把零点检测电路的地线和可控硅触发电路的地线分开走最后在单片机附近汇合避免强电侧的突变电流在地线上产生压降干扰弱电逻辑。这三个动作做完后示波器上看到的波形干净了很多灯也稳定了。4.2 最小触发时间与亮度曲线的非线性如果你把触发角从 0° 一直往后推会发现亮度变化很不均匀触发角很小的时候稍微改变一点角度亮度变化非常明显触发角接近 180° 的时候角度变了一大截亮度也没多大变化。这是因为白炽灯的亮度和有效电压之间不是线性关系有效电压和触发角之间存在余弦关系。如果直接线性调节角度人眼感受到的渐变效果就是“前半段太明显、后半段几乎没反应”。我后来在程序里加了一个补偿查表把目标亮度百分比映射成触发角映射关系是angle arccos(1 - brightness) × 180 / π。这样调整后灯的渐变从人的视角看就均匀多了。比如亮度从 10% 到 90% 的过程触发角从约 103° 平滑降到约 59°肉眼看起来一直是匀速运动。如果没有这个补偿你的“无级调光”体验会大打折扣。4.3 上电冲击与可控硅发热处理白炽灯的冷态电阻比热态电阻小很多所以在过零点附近立刻全功率触发的瞬间冲击电流比正常工作电流高出 8 到 10 倍。如果可控硅的规格余量不大这个冲击很可能让可控硅在每一次上电都硬生生挨一下长期积累下来容易损坏。我实测用的是 BTA16-600B 双向可控硅16A 的规格带一个 200W 的白炽灯余量很大发热可以忽略不计。如果用在更大功率负载上除了提高可控硅规格外还要考虑加一个散热片。另外可控硅两端最好并联一个 RC 阻容吸收典型参数是 100Ω 10nF用来限制电压上升率防止没有触发信号时因为 dV/dt 过高而误触发导通。软件方面也做了一个软启动逻辑上电以后不是立刻把触发角设为 0° 全亮而是从 170° 开始每隔 20ms 减小几度大概 2 秒后过渡到目标亮度。这个处理不但能减少冲击电流还能让每次开灯都有一个非常自然的“渐亮”仪式感实用性拉满。做一个可控硅调光项目前期对原理不熟的时候觉得离电路很神秘踩完抗干扰的坑以后回头看思路其实非常清晰零点检测是同步信号源定时器是执行器可控硅是开关而调节亮度就是在做一场精心计算的时间游戏。最后再分享一个小技巧调试阶段不要直接操作 220V 强电你可以在电源端串一个隔离变压器或者先用 36V 的交流变压器模拟把整套逻辑跑顺了再切换到市电。这样既安全又能完全覆盖所有控制流程——因为算法和硬件参数在低压下验证正确之后到高压下只是幅值变化控制时序不变。等你把这一整套流程走完理解了一些交流电的脾气再看其他调光、调速、软启动项目基本都能轻松上手了。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门