当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]在上一篇文章中,我们提到为什么运行代码时没有彩色显示,是因为main.py是运行在微控制器上的程序。它的职责是通过以太网/UDP接收LED数据,并将这些数据写入NeoPixel矩阵。然而,微控制器本身并不会自行生成动画帧。

在上一篇文章中,我们提到为什么运行代码时没有彩色显示,是因为main.py是运行在微控制器上的程序。它的职责是通过以太网/UDP接收LED数据,并将这些数据写入NeoPixel矩阵。然而,微控制器本身并不会自行生成动画帧。

我们将创建一个名为streamer.py的新文件,它运行在计算机上,充当LED帧生成器和发送器。该程序为全部256个LED生成RGB值,将其打包成UDP数据包,并通过IP地址10.0.1.140、端口6454发送给微控制器。

因此,我们需要streamer.py,因为它提供main.py所接收并显示的动画帧。如果没有streamer.py,虽然控制器可能运行正常,但没有新的LED数据显示,LED就会保持关闭或不显示任何内容。

现在,我们直接进入正题!

streamer.py代码解析

导入模块与全局参数

•网络常量:配置目标板IP,并将流量分发到两个独立的UDP端口(6454用于外发视频,6455用于接收遥测数据)。要获取您的板IP,请先运行udp.py,然后复制命令行中显示或OLED上显示的IP地址。

•矩阵尺寸:设置目标网格大小为32x8 = 256个LED。

•共享状态字典:存储模拟变量(速度、亮度)和诊断信息(丢弃帧数)。由于Python以原子方式读取和替换字典条目,该字典在后向通道监听器与帧渲染器之间充当线程安全的桥梁。

遥测监听器:backchannel_worker()

•套接字设置:使用UDP(SOCK_DGRAM)绑定到0.0.0.0:6455,以接收来自任意接口的遥测数据包。

•数据包验证:通过recvfrom(32)最多读取32字节,并验证数据包至少包含5字节长度,且头部魔数为b'CT'。

•二进制解包:

•data[2]提取原始编码器旋钮位置(0-100)。(

•data[3] << 8) | data[4] 重建了 UDP.py 发送的带宽字节序 16 位无符号整数,用于表示帧丢失。

•参数缩放:将旋钮值(0-100)转换为动画速度(0.2x 至 3.0x)和亮度比例(0.1 至 0.8)。

视频引擎:run_streamer()

帧间隔设置:定义目标帧间隔为 1.0 / 60.0 ≈ 16.67 毫秒(60 帧/秒)。frame_id 从 0 开始。

头部生成:生成一个包含 [0xAA, 0x55] 的字节数组,后跟当前 frame_id 的高字节(frame_id >> 8)与 0xFF 的组合,以及低字节 frame_id & 0xFF。

时间累加器:根据遥测线程设定的动态速度,按比例推进相位时间 t。

等离子体算法:在坐标 x 和 y 上计算 R、G、B 的平滑正弦/余弦波,通过 b_factor 进行缩放。我请 Gemini 帮助我创建此图案。

序列化:每像素追加 3 字节到帧中(256×3=768 像素字节 + 4 个头字节 = 总共 772 字节)。

传输与循环:将帧发送至 BOARD_IP:6454,并将 frame_id 在 16 位范围内循环(& 0xFFFF,从 0 到 65535 循环)。

自适应速率限制:使用高分辨率时间测量帧渲染和套接字传输延迟。perf_counter(),仅在60帧每秒周期的剩余时间内进行睡眠。

观察

请注意,当我顺时针旋转旋钮时,动画会加快;而逆时针旋转时则会变慢。我们还可以在OLED屏幕上看到IP、FPS、闪烁次数(DROPS)以及旋钮百分比(KNOB%)。

下一步计划

下一篇文章中,我打算添加一个按钮模块,以便更方便地关闭LED矩阵。目前,我只能通过同时停止Thonny IDE和命令提示符中运行的两个程序,然后在Thonny shell中执行独立命令来关闭LED灯,这种方式非常不便。

不过,我无法直接通过GPIO按钮为LED矩阵供电!一个32×8的矩阵包含256个LED,在最大亮度下,可能需要相当大的电流。因此,LED的电源应来自合适尺寸的外部电源。这时之前我在风扇项目中使用的MOS FET开关模块就派上用场了。

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭