3个不稳定版本

使用旧的Rust 2015

0.2.1 2017年3月6日
0.2.0 2017年3月6日
0.1.0 2017年3月6日

#21#lighting

Download history 12/week @ 2024-03-11 51/week @ 2024-03-18 26/week @ 2024-03-25 55/week @ 2024-04-01 25/week @ 2024-04-08 44/week @ 2024-04-15 32/week @ 2024-04-22 22/week @ 2024-05-06 17/week @ 2024-05-13 14/week @ 2024-05-20 13/week @ 2024-05-27 32/week @ 2024-06-03 58/week @ 2024-06-10 9/week @ 2024-06-17 18/week @ 2024-06-24

117 每月下载次数

MIT 许可证

10KB
64

DMX512支持

通过一个特质,在Rust中通过`dmx` crate支持DMX512传输,尽管目前只有通过Linux上的UART实现。

有关详细信息,请参阅文档


lib.rs:

DMX512

“数字复用”(DMX)协议用于控制大型和小型装置中的舞台灯光和效果。它基于[RS485] (https://en.wikipedia.org/wiki/RS-485),并且可以(几乎)轻松地在微控制器以及具有软实时能力的操作系统上实现。

协议

该协议本身假设为单主多从系统。主设备定期发送最多512个通道的更新。这些更新中的每一个都称为DMX 数据包,由一个起始码和从通道1开始的任意数量的通道组成。数据包可以包含少于512个通道,但必须始终从1开始,并按顺序进行。

通道是介于0到255之间的字节数值。对于大多数通道,这些是强度值,其中0表示“关闭”,255表示“全亮度”。然而,其他功能也可能连接到通道,例如选择闪烁序列或设置伺服位置。

技术细节

DMX使用串行协议在非寻常的波特率250,000 baud传输,无奇偶校验和两个停止位。

要开始传输,发送器必须首先将线路拉低以发送所谓的中断,然后将其拉高以发送标记。这个中断的持续时间相当长,标记也是如此,两者都远长于提交单个字节通常所需的时间。

在中断/中断后标记序列之后,以250,000 baud的波特率开始常规传输,发送单个字节的起始码。这个起始码几乎总是0xFF,除非使用特殊功能,这些功能是供应商特定的。

在起始码之后,可以传输任意数量的通道。

刷新率

刷新率取决于传输的通道数。对于完整的512个通道,可以达到的最大符合标准刷新率约为44帧/秒。如果在数据包内发送的通道数少于512个,则可能实现更高的刷新率。

请注意,在休息时间(以及因此 DMX 数据包)之间有一个最小时间为 1204 微秒,理论上将刷新率限制在大约每秒 830 次更新。

DMX 通常意味着需要连续发送,每秒至少更新一次。如果间隔太大,许多设备将关闭。

更多信息

DMX512-A 标准(《[DMX512-A 标准] (http://tsp.esta.org/tsp/documents/docs/E1-11_2008R2013.pdf)》)包含详细规范。

实现

目前,只有使用 Linux 串行设备的实现可用。将 UART 连接到 RS485 收发器就足够了。该实现并非完全优化 DMX:由于大多数 Linux 内核不具备实时能力,因此无法始终实现完美的帧率。然而,DMX 协议对时间的不确定性具有一定的容错能力。

UART 必须支持非标准波特率和合理的波特率切换速度。发送中断是通过切换到低速波特率,发送单个 0x00 字节,然后等待一段时间,再切换回 250,000 波特率来完成的。

示例

接口使用起来相当简单

   use dmx::{self, DmxTransmitter};
   use std::{thread, time};

   let mut dmx_port = dmx::open_serial("/dev/ttyS1").unwrap();

   // a typical 4-channel device, expecting RGBV values. this will set a
   // fairly bright yellow.
   let data = &[0xe4, 0xe4, 0x00, 0xca];

   loop {
       dmx_port.send_dmx_packet(data).unwrap();

       // repeat about every 51 ms. for more accurate frame timings,
       // consider using the ticktock crate.
       thread::sleep(time::Duration::new(0, 50_000_000));
   }

依赖关系

~195KB