
【密恐慎入】2020的WS2812B灯板
简介
小型的2020尺寸的WS2812B灯板,可拼接,3mm间距;同时附带一个WS2812B的时间换空间的控制方法,移植方便
简介:小型的2020尺寸的WS2812B灯板,可拼接,3mm间距;同时附带一个WS2812B的时间换空间的控制方法,移植方便开源协议
:GPL 3.0
(未经作者授权,禁止转载)描述
灯板?可拼接?方块?
一块简单的,小型的2020尺寸的WS2812B灯板
可以选择扩大底板,也可选择多小板拼接,每版64、128灯,较为密集


推荐上一遍锡后铁板烧,上锡时发现某点位不粘锡,将温度提到250以上用烙铁尖尖戳两秒即可(我这里灯珠是从另一个灯板拆下来的,烫的时间有些长所以有点发黄)
铁板烧后记得测试是否有短路,如果哪个灯光不亮,请检查前一颗灯的输出、该灯的输入、电源、地引脚,使用尖头烙铁烫一下就好,45度摆放,利用手工补救



附赠一个用时间换空间的PWM+DMA双缓冲灯光控制方法 (将基本的配置放到附件了哈~附带了简单的调用函数,请另外建立应用代码文件进行修改)
本人喜好灯光控制,此前有顺手购买合宙air001芯片,16K空间,4K的内存
但是!一般控制灯光需要的数组大小为灯光数量*24,即利用8M的SPI或PWM的CCR,
WS2812B采用的是RGB888,单线控制,根据实际高低电平的时间占比,进而转换成灯珠的逻辑0和逻辑1
这时,SPI的方法是在8M情况下分别用两个字节模拟高低电平,最后统一发送即可
灯光数量增加后,对内存空间的要求上涨十分恐怖,而小小的001内存空间不够使用
本次想控制的灯板起码256颗,使用以上方法肯定不行
幸好之前用RP2040核心板做过一个简易的逻辑分析仪,还是比较好用的(小声嘀咕:不知道为什么不能超过10M采样速率)
(PCB改版自轻灵之翼)

经采样:合宙官方的arduino例程中,逻辑分析仪发现发送的每一位都是0!!!?

不不不,实际上是使用的SPI每一字节单独发送,间隔大概19us,对于这个逻辑分析仪的协议还是按照默认的高低电平比例计算逻辑0和1的方法不适用,所以低电平时间超长,就都显示为0

图示是我后续模拟的,实际周期比显示的长,图示周期大概4.2us
但由此我们可以认为,在不超过灯珠复位的时间内,高电平时间符合规定,低电平时间可以有所延长
理论存在,开始写bug~
方案一:修改keil中SPI的函数,使字节间间隔缩短到30us内。。。。功力有限,没成功,24M的主频,不清楚arduino是怎么做到的/(ㄒoㄒ)/~~
方案二:使用PWM+DMA方案,具体原版的我不多描述,STM32的有非常多的案例教学,大家有需要自行百度哈
本方法详细描述:
PWM本身是引脚的快速高低电平变化,周期由AAR决定,高电平或低电平时间由CCR决定,DMA是为了快速给定CCR值防止周期出错
通过计算可知,在我24M主频下,大概AAR为28时,周期接近灯珠的1.2us,CCR给8或17,可以接近2812灯珠要求的350ns和750ns高电平时间(如对此不清楚可考虑问一下AI学习前置知识~)
即,使用CCR建立数组,不同的CCR值代表不同的逻辑电平,24位用24个CCR的值来替代

将TIM更新事件关联到DMA上,即TIM完成一个周期,DMA触发一次,实现快速给下一个周期值的效果
实验理想状态:
灯珠颜色暂存是必不可少的,除非纯运算实现,即灯珠数量*3的数组,加上DMA搬运CCR的数组,使用半字搬运,也就是2字节*24位
计算完第一颗灯珠后,使能DMA,开始PWM发送,此时软件计算第二颗灯珠的CCR,塞入数组,在发送完成24个CCR值时,恰好计算也追着dma的尾巴完成,由此循环
现实状态:或许是24M主频时间不够,计算跟不上发送,会导致显示混乱,原因较多
解决方法:
1、合宙的HAL库中,并未直接给禁用软件DMA的函数,需进入初始化DMA函数内部将其标志位清除


2、AAR为28时,时间略有不足,可将其提升至56、84等值,或者写90、100都可(该值代表周期,不必完全按照规定的1.25us,保证CCR低电平值符合规范就行)
3、使用双缓冲区,建立两个CCR数组待发,计算第一颗灯珠时将第一个CCR数组地址给DMA搬运寄存器,内存地址自增使能,目的地址不自增(锁定CCR可劲儿塞)
计算完成后,给DMA搬运的数量,然后使能DMA,开始计算第二颗灯珠对应的CCR数组,塞入后给DMA地址(不用管上一次是否完成,会在完成时刷新)
由于我们给了充足的AAR时间,一颗灯可能需要花3~4us计算,完成后需要等待一下上一次DMA完成,即CNDTR==0
注意:这里CNDTR是dma搬运剩余的次数,即使为0,pwm也只是刚刚开始发送,还未完成上一次灯光的最后一位的控制
我们判断搬运次数为0后,失能dma,再给一次24次搬运,然后使能,地址之前给过了,完成后自动刷新从该地址开始搬运,即PWM发送完最后一次波形触发更新,DMA给塞入第二个数组的CCR值
实验结果:第一颗灯状态不正常,偶尔出现突发性的亮度增长,第一颗灯不亮,灯珠颜色顺延
解决方法:PWM的输出比较寄存器的锅,可能会导致输出的第一个波形宽度异常或者多出来一个波形,同时由于每次发送之间时间不是恰好与PWM同步,第一个波形有概率会被恰好”吞掉“,直接刷到第二个值,导致整体向前一位,表现出来灯光亮度突增
在开始发送第一颗灯珠之前,使PWM的比较寄存器值为0,计数值为最大,同时保证一定可行,又建立了一个CCR数组元素为两个0,即先将DMA发送地址设置到这个0的数组地址,数量2,
发送灯珠前先发送该数组,发送完毕后按之前的逻辑发送第一颗灯...最后一颗灯结束后,再次发送元素为0的CCR数组,顺利结束
实验结果:所有灯光颜色正常,周期可根据需要进行缩短


搜了好多教程一直没有合适的方法,都占用太多空间了,后来写完代码后,突然搜到了20年的一篇文章利用PWM+DMA双缓冲控制灯珠的方法/(ㄒoㄒ)/~~
不过还是有些区别的,本次方法全程没用中断,各位可根据喜好使用中断控制达到自动档的效果,目前还是手动档,需要CPU控制,计算完成后的空余时间留给处理突发中断记录标志等操作
代码较好实现,使用定时器(PWM)+一个DMA通道,中断按需~
如果感觉对你有用,记得给个好评噻~
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程

评论