ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

泰凌BLE Mesh灯控渐变优化:从20ms粗插值到1ms细插值,彻底消除阶梯感

泰凌BLE Mesh灯控渐变优化:从20ms粗插值到1ms细插值,彻底消除阶梯感 一、背景:泰凌原生SDK的渐变为什么有阶梯感?泰凌Mesh SDK原生的渐变逻辑是粗粒度插值:当你设置20ms渐变时间(transition time=20ms)时,SDK只会在渐变开始时记录start值,20ms后直接将present设为target值,中间没有任何插值;部分版本SDK最多会在中间插1次值,也就是20ms内只更新1次PWM,等效于20ms单步跳变;人眼的临界融合频率约为50Hz(即20ms内的变化如果更新次数≥20次,人眼会认为是连续变化),原生20ms仅1次更新(等效5Hz),低亮度区(亮度1000)的跳变幅度可达~300(65535满量程),肉眼感知非常明显。我们本次改造的核心目标非常明确:保持20ms总渐变时长(符合Mesh规范的最小渐变要求),将插值周期从20ms压缩到1ms,20ms内输出20个连续PWM值,彻底消除人眼可感知的跳变。二、核心设计思路:1ms插值的四个关键规则改造后的代码完全接管了SDK的插值逻辑,核心规则如下:规则1:总渐变时长固定20ms,插值周期1mstotal_ms固定为20ms(符合Mesh规范,也匹配人眼感知的平滑阈值);每1ms执行一次插值计算,20ms内共输出20个有效变化值,等效更新频率50Hz,刚好达到人眼临界融合频率。规则2:时间比例插值,无累积误差插值公式严格按时间比例计算:当前值 = start + delta * (elapsed_ms / total_ms),而非“每次加固定step”:即使某次中断延迟了几个us,只要elapsed_ms按1ms累加,最终20ms后elapsed_ms=20,刚好等于total_ms,直接赋end值,无累积误差;避免了原生SDK“固定step累加导致的终点偏移”问题。规则3:硬件实际值作为唯一锚点所有渐变的起点start_xxx永远取上次实际写入PWM的值my_last_xxx,而非SDK的present值:连续Mesh命令打断时,新渐变直接从当前灯的实际状态起步,无缝衔接,无任何跳变;符合“单点更新”原则:my_last_xxx仅在PWM写入成功后更新,其他任何地方不修改,状态唯一。三、代码拆解:从调度到插值的核心逻辑#defineLIGHT_ADJUST_INTERVAL(20)// 总渐变时长:20ms(符合Mesh规范)#defineCLOCK_SYS_CLOCK_1MS(CLOCK_SYS_CLOCK_HZ/1000)typedefstruct{/* 亮度 L */uint16_tstart_l,end_l;uint32_ttemp_l;// 插值中间结果,32位防减法下溢uint16_tdelta_l;// |end - start|的绝对值uint8_tdir_l;// 0=递增,1=递减uint8_tactive_l;// 亮度轴渐变激活标志/* CTL 色温 */uint16_tstart_ct,end_ct;uint32_ttemp_ct;uint16_tdelta_ct;uint8_tdir_ct;uint8_tactive_ct;uint16_ttotal_ms;// 总渐变时长:固定20msuint16_telapsed_ms;// 已过时间:每1ms加1,20ms后等于total_ms}my_fade_t;light_dim_refresh:渐变配置器(仅Mesh命令触发时调用)这个函数只做三件事:取锚点、算参数、启渐变,无耗时操作:voidlight_dim_refresh(intidx){st_transition_t*p_trans_l=P_ST_TRANS(idx,ST_TRANS_LIGHTNESS);my_fade_t*f=g_fade[idx];uint16_tcurr_l=s16_to_u16(p_trans_l-present);/* 1. 取硬件实际值作为起点,无缝衔接命令打断 */f-start_l=my_last_l[idx];f-end_l=curr_l;f-total_ms=LIGHT_ADJUST_INTERVAL;// 固定20ms总渐变时长/* 2. 计算绝对值delta和方向位,无符号运算避免溢出 */f-delta_l=(f-end_lf
返回列表