【过程帖】接入灯带和 TFT 显示屏:榨干 Teensy 4.0 的性能极限
在上一阶段搞定了 INMP441 麦克风的音频采集和基础 FFT 分析后,这几天我把主要精力放在了视觉呈现上。这次不仅给 Teensy 4.0 挂上了一块 240x135 分辨率的 TFT 彩屏(ST7789 驱动),还初步接入了一条 144灯/米的 WS2812B 氛围灯带。
整个过程可以说是“痛并快乐着”,踩了不少坑,但也彻底感受到了 Teensy 4.0 极其残暴的算力。和大家分享一下折腾的过程和填坑经验。
一、 屏幕 UI 的进化与“底噪”保卫战一开始,我只是想在屏幕上画几个简单的柱状图。但实际一跑,发现了几个很棘手的问题:
1. 幽灵般的底噪
当环境完全安静时,最右边的低音柱子依然会高高耸立,但放音乐时反而不敏感。
解决思路: 这是典型的环境低频风噪。我一开始简单粗暴地提高及格线(硬截断),结果底噪没了,音乐的细节也全被砍没了,画面极其生硬。
最终方案: 改用“动态底噪 + 软扣除”。把环境底噪当成一个动态的值,从音频信号里平滑地“减去”它。配合高频 EQ 补偿(越往高频放大的倍数越高),终于实现了:安静时屏幕干干净净,音乐响起时细节拉满。
2. 榨干算力的四大主题与 UI 修复
为了让这块屏幕的显示效果更加丰富,我加入了一个 DFRobot 的 Gravity 大按键(接在 Pin 5),用来一键切换四套 UI:
赛博霓虹: 带专业暗色网格和最高峰值掉落游标。
模拟示波器: 极其锐利的单线跳动,纯粹的复古感。
3D 瀑布图: 录音棚级别的热力图谱。
中心能量波: 从中间向两边炸开的对称光束。
期间遇到了严重的画面撕裂、游标残影(白点去不掉)以及按键连发的问题。经过几次代码重构,我放弃了微小的增量擦除,改用稳健的完全覆盖策略。虽然多画了几笔,但彻底消灭了残影。按键也加入了严密的锁死机制,现在按键效果比较丝滑,
3. 突破帧率天花板
在做 3D 瀑布图时,因为横向切了 80 个频段,一开始帧率掉到了可怜的 14 FPS,按键也完全失灵。
解决思路: SPI 通信被密集的“画短线”指令塞爆了。我直接利用 Teensy 4.0 庞大的 RAM,申请了一块超级显存缓冲区。在内存里把一整张 240x120 的图拼好,然后一次性打包发给屏幕(显存轰炸)。
结果: 帧率瞬间飙升!在普通的柱状图模式下,FPS 能稳定在 87 帧左右;在最吃性能的全屏瀑布图模式下,也稳稳锁定在 41 帧(这是 SPI 物理传输的极限,也是肉眼看瀑布图最舒服的速度)。
二、 驯服“电老虎”:WS2812B 灯带的安全接入
屏幕搞定后,重头戏来了——144灯/米的 WS2812B 灯带。
这玩意儿是个名副其实的“电老虎”。如果 144 颗灯全亮纯白,瞬间电流能飙到 8A 以上(将近 45W 的功耗)。如果直接把它怼在 Teensy 的 5V(也就是电脑的 USB 供电)上,绝对会把开发板和电脑主板一起“送走”。
但我实在迫不及待想看 1 米长灯带的完整联动效果,不想妥协去剪断灯带,也不想干等大功率开关电源接线。于是,我用了一个极客且硬核的“软件级封印”方案:
1. 榨干 FastLED 的电源管理魔法
在代码初始化阶段,我直接调用了 FastLED 库里极其强大的功耗限制函数:
FastLED.setMaxPowerInVoltsAndMilliamps(5, 1500);
这行代码的作用是:告诉单片机,我的电源最多只能提供 5V / 1.5A 的电流。FastLED 会在后台实时计算 144 颗灯的预估电流,一旦超过设定的安全阈值,它会自动、平滑地压低全局亮度。
2. 极简直接的物理接线
有了这道软件级“免死金牌”,我就能大胆地使用极简接线了:
灯带的 5V(红线)直接接 Teensy 的 VIN 引脚(直接借用 USB 的 5V 输出)。
灯带的 GND(黑线)接 Teensy 的 GND 引脚。
灯带的 DIN(数据线)接 Teensy 的 Pin 2。
目前的灯带效果:
得益于软件动态限流,144 颗灯全部成功点亮,且电脑 USB 端口安然无恙!我将这 144 颗灯在代码里硬分成了 16 组(每组 9 颗),完美一对一映射屏幕上的 16 根频谱柱。
从左到右红蓝渐变,低音区的灯光猛烈冲刷,高音区灵动闪烁。配合 Teensy 的高帧率,现实世界的光影和屏幕里的动态波浪实现了零延迟的神同步,视觉冲击力直接拉满!
下一步计划
目前软硬件逻辑已经非常成熟了。接下来准备把代码再重构一遍增加鲁棒性!
我要赚赏金
