ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

超低频PWM调光真的护眼吗?从STM32实测看闪烁与视觉疲劳

超低频PWM调光真的护眼吗?从STM32实测看闪烁与视觉疲劳 这两年讨论手机 OLED 屏幕时“PWM 调光”几乎成了一个绕不开的词。很多消费者在选机时会盯着一个数字看PWM 调光频率是多少1440Hz、1920Hz、2160Hz数字越高好像就越护眼。但很少有人反过来问一个问题如果 PWM 频率做得非常低比如只有几十赫兹画面反而没有高频时那种“回电”的刺眼感这是不是也挺护眼的这个想法听起来有点反直觉却也很容易让人踩坑。作为一个平时写单片机、做嵌入式控制的人我第一次接触“超低频 PWM 调光”这个说法时第一反应是在嵌入式领域几十赫兹的 PWM 太常见了舵机控制、风扇调速、呼吸灯、电子蜡烛全是这种频率。但“常见”不代表“适合观看”。本文会从 PWM 的基本原理讲起用 STM32 实际生成不同频率的 PWM 波形再结合示波器、光敏 ADC 采样把“护眼”这个主观问题拆成几个可以测量的工程指标。读完你会得到一个明确判断超低频 PWM 调光并不护眼但它有它存在的工程场景。1. 这篇文章真正要解决的问题关于 PWM 调光和护眼目前讨论里最典型的误区是“把频率当成唯一指标”。一些人以为高频 PWM 调光既然能骗过人眼说明 PWM 本身就是一种“可见闪烁”的技术那么干脆把频率降低让每次亮灭都变得缓慢柔和是不是更接近传统白炽灯的“余晖”效果这个想法听起来有道理但实际操作中有一个直观反例你去看一盏调暗到 10% 的普通 LED 台灯如果它的驱动电路用了低频 PWM你很容易观察到灯光在“发抖”看久了眼睛会酸胀。那种发抖感就是低频 PWM 带来的视觉负担。所以本文要解决的不只是一个“护眼偏好”问题而是三个更具体的问题PWM 调光的频率、占空比、分辨率到底怎么理解为什么电子工程师选频率时不只看“人眼是否可见”超低频 PWM比如 50Hz 到 120Hz 区间对于长期观看场景到底是不是“更低刺激”的护眼方案嵌入式开发者怎样用 STM32、CubeMX、示波器和 ADC 采样把“是否闪烁”变成一个可以量化、可以复现的工程结果如果你正在做 LED 调光项目、屏幕背光驱动或者纯属好奇想搞清楚“PWM 调光和高频调光哪个对眼睛更友好”这篇文章适合你。文中涉及 STM32F103 的 TIM 定时器输出 PWM、PWM 触发 ADC 采样、软件 PWM 等常见嵌入式技术同时也给出从护眼角度出发的频率选择建议。2. PWM 调光的核心概念与参数2.1 什么是 PWMPWM 的全称是 Pulse Width Modulation脉冲宽度调制。本质上是让开关信号在一个固定周期内高电平持续的时间和低电平持续的时间按比例变化。这里的“持续高电平时间”叫脉冲宽度它占整个周期的比例叫占空比。对于一个 LED 来说如果 PWM 频率足够高人眼并不能直接分辨亮灭切换只会感受到平均亮度。这时候占空比越高LED 等效亮度越高占空比越低LED 等效亮度越低。这也是“PWM 调光”能够成立的原因不需要改变电流大小只需要改变导通比例。和常见的 PPM 信号做个区分PPM脉冲位置调制通常是在一个周期里用几个脉冲之间的时间间隔来编码通道信息典型应用是遥控接收机信号而 PWM 是每个通道独立一个周期和占空比直接输出给舵机、电机驱动或者 LED 驱动。PWM 关注的是“占空比”PPM 关注的是“脉冲位置”这是两者最本质的区别。2.2 PWM 调光的三个核心参数一个 PWM 波形有三个关键参数参数含义对调光的影响频率每秒 PWM 周期重复的次数单位 Hz决定闪烁是否被人眼感知也影响驱动电路的损耗占空比高电平时间占整个周期的比例单位 %决定 LED 的平均亮度分辨率占空比可调节的最小步进通常由定时器 ARR 值决定决定调光是否平滑会不会出现肉眼可见的亮度跳变对于 STM32 定时器输出 PWM频率和分辨率是一对矛盾组合。频率越高在相同定时器时钟下ARR 值越低占空比调节档位越少。比如定时器时钟是 72MHz如果 ARR7199那么 PWM 频率是 10kHz占空比最小步进是 1/7200如果 ARR719PWM 频率是 100kHz占空比分辨率就只剩 1/720。工程上要在这两者之间选一个平衡点。2.3 为什么 PWM 调光在 OLED 屏上这么常见OLED 屏幕和传统 LCD 不同它每个像素是自发光的有机发光材料。在低亮度下如果直接降低驱动电流OLED 会出现明显的色温偏移甚至导致低灰阶下颜色不均匀。为了在低亮度下尽量保持色彩稳定很多 OLED 屏会使用 PWM 调光通过控制背光或像素点在一个周期内的点亮时间来模拟较低亮度。这就带来一个工程矛盾PWM 调光本质上是一种时间上的通断切换。如果频率不够高人眼就会感知到闪烁如果频率太高对驱动 IC 和面板电路的要求又会变高。所以厂商通常会在“护眼”和“成本”之间做取舍而不是无限提高频率。这里可以得出第一个判断PWM 调光本身不是问题频率选择才是问题。超低频 PWM 恰恰是因为频率太低才容易让用户感知到明显的亮度波动主观上并不“护眼”。3. 超低频 PWM 调光的真实问题人眼会看见闪烁3.1 人眼对闪烁的感知很复杂人眼对闪烁的感知有一个概念叫临界闪烁频率CFFCritical Flicker Frequency。高于这个频率时人眼会把闪烁的光融合成连续光低于这个频率时闪烁就能被察觉。CFF 不是一个固定值它跟光的亮度、颜色、占空比、观看者的疲劳程度、视觉区域都有关系。在屏幕亮度比较低的情况下瞳孔会放大进入眼睛的光线更多对亮度波动的敏感度反而会提升。也就是说超低频 PWM 调光往往会在低亮度档位下更明显。这与很多用户的体感一致晚上把手机亮度调低如果屏幕用了低频 PWM滑动屏幕时能看到背景亮度在轻微波动甚至像“水波纹”一样。从嵌入式开发视角看这种低频 PWM 就是一个频率只有几十到几百赫兹的方波。如果把它接到 LED 上用光敏二极管配合示波器看亮度曲线你会得到一条明显起伏的波形而换成高频 PWM波形经过视觉积分后输出就平滑得多。3.2 超低频 PWM 为什么不护眼“不护眼”可以从三个层面理解第一可见闪烁直接增加视觉疲劳。当光源以几十赫兹的频率反复变化时人眼会不断调节瞳孔大小睫状肌长期处于紧张状态。这也是“低频 PWM 看着好像没那么亮但看久了眼睛很累”的原因。第二频闪效应会影响视觉信息的捕捉。如果 PWM 频率和工作环境里的其他光源频率接近比如 50Hz 工频灯或者电风扇叶片转速的整数倍屏幕上可能会出现低频闪烁叠加看起来像画面在抖动。对于阅读、写字这类高精度视觉任务这种干扰很不友好。第三超低频 PWM 并不等于“更低亮度刺激”。它只是把一个本来应该持续发光的 LED 变成了一亮一灭。瞬时峰值亮度可能并没有降低反而因为频繁的明暗切换增加了视觉噪声。3.3 低频 PWM 也有适合的场景需要特别说明的是低频 PWM 在嵌入式领域非常常用而且很适合某些场景。比如舵机控制PWM 频率通常是 50Hz 到 330Hz这是舵机硬件本身要求的不涉及视觉护眼问题。再比如 PWM 控制风扇几百赫兹到几千赫兹都可以用户更关心的是噪音和调速性能。还有 PWM 模拟电子蜡烛本来就是要模拟火焰忽明忽暗的效果低频 PWM 反而是核心设计。所以“护眼”只是 PWM 频率选择里的一个维度不是唯一维度。我们要评估的是“长期观看”场景也就是屏幕、台灯、阅读光源这些环境。这种情况下超低频 PWM 是劣势而不是优势。4. 用 STM32 产生不同频率 PWM一个最小实验为了把上面的判断落到工程实践我们用 STM32F103C8T6 做一个小实验通过 TIM1 输出不同频率的 PWM 波形并通过修改预分频器和自动重装载值真实感受“超低频 PWM”和“高频 PWM”在波形上的差异。4.1 CubeMX 配置要点在 STM32CubeMX 中新建工程选择 STM32F103C8T6然后按下面步骤配置将 PA8 设置为 TIM1_CH1 输出这是 TIM1 的通道 1 引脚。把 TIM1 的 Clock Source 设置为 Internal Clock。在 PWM Generation Channel 1 中设置 Mode 为 PWM Generation CH1。设置 Prescaler、Counter Period、Pulse 参数。生成工程编译器选择 MDK-ARM 或 STM32CubeIDE 均可。为了让频率计算更直观这里假设定时器时钟是 72MHzPWM 频率计算公式为PWM频率 定时器时钟 / ((PSC 1) * (ARR 1))比如要输出 20kHz PWM可以设置 PSC 71ARR 49那么频率 72MHz / (72 * 50) 20000Hz。要输出 100Hz PWM可以设置 PSC 719ARR 999那么频率 72MHz / (720 * 1000) 100Hz。4.2 初始化代码CubeMX 生成的代码会自动包含定时器和 PWM 的初始化。在 main.c 的 MX_TIM1_Init 函数中核心逻辑如下// 文件路径main.c 中 MX_TIM1_Init 函数 static void MX_TIM1_Init(void) { TIM_OC_InitTypeDef sConfigOC {0}; htim1.Instance TIM1; htim1.Init.Prescaler 719; // PSC 719 htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 999; // ARR 999 htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter 0; htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_PWM_Init(htim1); sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 250; // 初始占空比 25% sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim1, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); }注意这里的 Pulse 250表示 CCR 250在 ARR 999 时占空比是 250/1000 25%。如果想改成 50% 占空比把 Pulse 改成 500 即可。4.3 运行中动态修改频率和占空比在实际调光项目中经常需要动态改变亮度和频率。用 HAL 库可以这样修改// 修改占空比CCR 500 表示 50% __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, 500); // 修改 PWM 频率。先修改 ARR再修改 CCR __HAL_TIM_SET_AUTORELOAD(htim1, 1999); // ARR 1999频率减半 __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, 500); // 重新设置占空比修改 ARR 之后PWM 频率会立即改变。但要注意如果 ARR 改小了而 CCR 大于新的 ARRPWM 会变成一直输出高电平也就是 100% 占空比。所以修改频率时一定要先计算 CCR再设置 ARR 和 CCR顺序不要搞反。4.4 三种频率下的实验结果预期用示波器观察 PA8 引脚可以看到配置频率占空比示波器观察结果PSC719, ARR999, CCR500100Hz50%方波明显闪烁LED 能看出抖动PSC71, ARR999, CCR5001000Hz50%肉眼看不到闪烁但高速摄像仍可见PSC0, ARR899, CCR45080kHz50%示波器上升沿下降沿接近理想方波LED 非常平滑如果直接把 LED 串限流电阻接在 PA8 上你会发现 100Hz 时 LED 的亮度看起来并不稳定尤其当你的头左右晃动或者用手机摄像头对准 LED 时画面里会出现条纹。这就是低频 PWM 被视觉和采样设备感知到的典型表现。5. PWM 触发 ADC 采样把“护眼”变成可测量数据只看示波器上的方波还是不能完全说明“亮度是否稳定”。更好的方案是使用光敏二极管把 LED 的亮度变化转换成电压再用单片机的 ADC 采样得到一条完整的“光强-时间”曲线。5.1 为什么用 PWM 触发 ADC 采样普通 ADC 循环采样很难捕捉到 PWM 周期内的亮度变化。因为 PWM 频率可能很高单片机循环采样会错过很多细节而且采样点与 PWM 相位不同步测出来的数据会很随机。更合理的方案是用定时器的另一个通道产生触发信号在 PWM 周期的固定相位点启动 ADC 采样。这种“PWM 触发 ADC 采样”在电机控制、电源控制里很常见比如磁通观测、电流环采样都需要在 PWM 开关周期的特定时刻采集电压或电流。用在亮度测量上思路一样把采样点对齐到 PWM 周期才能真正看到亮度波形。5.2 一个简化的 ADC 采样思路如果你手头没有光敏二极管也可以用 LED 驱动端的分压电阻做一个模拟环境把 PA8 的 PWM 信号经过一个 RC 低通滤波器再用 ADC 采样滤波后的电压。这个方法可以验证 PWM 平均值和占空比的关系。更贴近“护眼”测量的做法是用光敏二极管或环境光传感器把 LED 表面亮度转换成电压信号输入到 STM32 的 ADC 引脚。配置思路如下使用 TIM1 的 TRGO 信号作为 ADC 触发源。将 ADC 采样周期设置为略小于 PWM 周期。连续采样多个点重建一个 PWM 周期内的亮度曲线。一个最小示例代码片段如下// 文件路径adc_trigger.c void ADC_Init_With_PWMTrigger(void) { ADC_ChannelConfTypeDef sConfig {0}; hadc1.Instance ADC1; hadc1.Init.ScanConvMode ADC_SCAN_DISABLE; hadc1.Init.ContinuousConvMode DISABLE; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConv ADC_EXTERNALTRIGCONV_T1_TRGO; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion 1; HAL_ADC_Init(hadc1); sConfig.Channel ADC_CHANNEL_0; // PA0 sConfig.Rank ADC_REGULAR_RANK_1; sConfig.SamplingTime ADC_SAMPLETIME_239CYCLES_5; HAL_ADC_ConfigChannel(hadc1, sConfig); }注意这里需要把 CubeMX 中 TIM1 的 Trigger Output 设置为 Update Event也就是 TRGO 选择 “Update Event”这样每个 PWM 周期更新时都会触发一次 ADC 采样。5.3 从 ADC 数据判断闪烁程度假设你采到一个 PWM 周期内的 20 个 ADC 点。如果 PWM 频率是 100Hz你能明显看到一条高低起伏的曲线高电平段光强值高低电平段光强值低。如果 PWM 频率是 20kHz由于传感器的响应速度和相机积分效应曲线会平滑得多光强值波动很小。一个简单的判断指标是“波动率”波动率 (最大亮度值 - 最小亮度值) / 平均亮度值 * 100%波动率越高说明亮度越不稳定闪烁越明显。对长期观看场景低波动率显然更友好。这就是把“护眼”从主观感受转换成工程数据的过程。6. 如何测量 PWM 波形并判断闪烁风险6.1 用示波器测量频率和占空比测量 PWM 波形最直接的工具是示波器。把探头接地夹接 GND探头尖端接 PWM 输出引脚设置合适的时基和触发电平就能看到方波。测量时要注意时基要足够小至少能显示几个完整周期否则测不出真实频率。占空比要在示波器菜单中选择自动测量直接读占空比百分比。如果是差分测量或高压环境要注意探头量程。对于超低频 PWM比如 50Hz一个周期是 20ms示波器时基设置为 2ms/div 到 5ms/div 比较合适。测量方法本身很简单判断闪烁风险则要看频率落在哪个区间。6.2 用光敏二极管加示波器直接看亮度波形“护眼”对应的物理量不是 PWM 引脚电压而是光源发出的光强。要测量光强变化可以把光敏二极管反向接在电池和示波器探头之间让 LED 的光照射到光敏二极管上。示波器显示的不是 PWM 方波而是亮度的电压波形。在低频 PWM 下你会看到类似方波的亮度曲线在高频 PWM 下亮度曲线会平滑很多。这也是判断一个屏幕调光是否“感知得到闪烁”的客观方法。6.3 常见测量误区有些开发者用万用表去测 PWM 输出发现显示“1.65V”就以为占空比是 50%。万用表测 PWM 得到的是电压平均值确实和占空比相关但并不能反映频率和实时波形。如果要用万用表估占空比可以测 PWM 高电平电压 VH 和平均值 VAVG再计算 VAVG / VH * 100%这里要有两个量高电平电压和平均值。另一个误区是只看 PWM 频率不看示波器采样率。如果示波器带宽不足或采样率太低高频 PWM 的上升沿会变得很圆滑看起来像正弦波导致误判占空比。7. 常见问题与排查方法在生成和测量 PWM 的过程中经常遇到的问题比想象中多。下面整理一个排查表。问题现象可能原因排查方式解决方案PWM 没有输出引脚一直是低电平定时器没有启动 PWM 输出检查是否调用 HAL_TIM_PWM_Start在初始化后启动 PWM 通道输出频率和计算值不一致PSC 或 ARR 算错定时器时钟不是预期值查看系统时钟树确认定时器时钟频率重新计算 PSC 和 ARR修改占空比后亮度不变CCR 值大于 ARR打印或调试查看当前 ARR 和 CCR先改 ARR再设置 CCR高频 PWM 下 LED 出现异响PWM 频率落在可听声频段用示波器看实际频率听电机/陶瓷电容啸叫把频率提高到 20kHz 以上或避开谐振点ADC 采样到的数据毛刺很大采样点与 PWM 相位不同步检查 TIM TRGO 触发配置使用 PWM 触发 ADC或者提高采样率后软件滤波示波器看不到完整方波时基过大或触发方式不对调整时基重新设置触发电平以边沿触发电平整定在 PWM 中点对于 PWM 控制电机、舵机的场景如果出现抖动通常不是“护眼”问题而是 PWM 频率不对。舵机一般接收 50Hz 左右的 PWM 信号这属于超低频率但这种 PWM 用于控制机械位置不用于照明不具备护眼意义。所以在讨论“低频 PWM 护眼”时一定要先区分用途别把舵机控制里的 50Hz 直接套到屏幕调光里。8. 工程建议与最佳实践8.1 屏幕和照明调光的频率选择从护眼角度出发弱光环境下长期使用的屏幕或阅读灯不建议使用低于 1kHz 的 PWM 调光。更稳妥的方向是高频 PWM 调光频率选在 1kHz 到 20kHz 之间视觉上平滑不会产生可听噪声。混合调光高亮度用 DC 调光低亮度再用高频 PWM。这样能兼顾高亮度下的色彩表现和低亮度下的闪烁控制。软件平滑过渡改变亮度时不要一步从 10% 跳到 90%而是按固定步进渐变避免剧烈的明暗变化。在嵌入式产品里如果硬件允许优先使用硬件 PWM而不是软件延时实现的 PWM。软件 PWM 在高亮度段和低亮度段容易抖动因为主循环被其他任务阻塞时定时不准确。8.2 硬件滤波把 PWM 变成直流如果项目不需要真正的闪烁调光而是希望 LED 亮度很平稳可以在 PWM 输出后加一个 RC 低通滤波器把 PWM 方波变成模拟直流电压。比如电阻 1kΩ、电容 10μF截止频率约 16Hz对于 100Hz 以上的 PWM 信号滤波后亮度曲线会平滑很多。但要注意这会降低调光响应速度不适合需要快速变化的场景。8.3 关于护眼比频率更重要的因素从工程角度看护眼不是 PWM 频率一个参数决定的。还有几个因素同样重要环境光亮度在暗环境中同样的 PWM 闪烁会更容易被感知。占空比区间低占空比下PWM 波形的关断时间更长闪烁更明显。屏幕蓝光强度如果屏幕上蓝光占比很高即使在同样 PWM 频率下视觉疲劳也会加剧。观看距离和时长近距离长时间使用频率和闪动的影响都会被放大。所以做产品时建议把所有因素放到一起评估先确定用户场景再选择频率最后通过硬件和软件调优。8.4 一个可复现的验证流程在项目里验证“这个调光方案是否容易引起视觉疲劳”可以按下面流程走用示波器抓取 PWM 波形记录频率和占空比。用光敏二极管加 ADC 采样计算一个周期内的亮度波动率。在暗室中用手机摄像头或高速相机拍摄屏幕观察是否有明显扫描纹。安排多人进行短时间阅读测试记录是否出现眼酸、流泪等主观反馈。如果条件允许对比同一亮度下 DC 调光和高频 PWM 调光的用户反馈。这套流程把“护眼”从主观感受转换成了可量化的工程检查项也适合写进产品测试规范。9. 总结回到最初的问题超低频 PWM 调光是不是也挺护眼的答案是不护眼。超低频 PWM 会让 LED 或屏幕出现肉眼可见的亮度波动长时间观看更容易导致视觉疲劳。它不像高频 PWM 那样能把闪烁“融合”掉也不像 DC 调光那样能提供稳定的持续亮度。把超低频 PWM 用在舵机、风扇、电子蜡烛上没有问题但用在屏幕调光或阅读灯具上体验会很差。从嵌入式开发者的角度看这个问题的价值在于它提醒我们不能只看“PWM”三个字就默认所有 PWM 调光都是一样。频率、占空比、分辨率、负载响应、人眼感知每一个环节都影响最终效果。真正稳妥的做法是把护眼需求转换成可测量的指标用示波器看波形用 ADC 量化波动再结合使用场景做选择。如果你正在做 LED 调光或屏幕背光项目建议收藏这篇文章回头按第四章和第五章的步骤跑一遍实验。先在同一块开发板上输出 100Hz 和 20kHz 两种 PWM亲眼看一下亮度波形的差异。很多时候一个简单的实验比看十篇科普文章更有说服力。
返回列表