我正在做一个发送串行数据的项目来控制LED灯的动画,这需要与动画引擎保持同步。似乎有一个很大的串行写入缓冲区(OSX (POSIX) + FTDI芯片组usb串行设备),因此无需手动限制对write()的调用,软件就可以提前几秒钟。
目前我手动将串行写入速度限制在波特率(8N1 =每8字节数据10字节串行帧,最大19200 bps串行-> 1920字节每秒),但我遇到了动画随时间漂移与灯光不同步的问题-它开始很好,但10分钟后动画和灯光之间存在明显的(100ms+)延迟。
这是限制串行写入速度的代码(每个动画帧调用一次,'elapsed‘是当前帧的持续时间,'baudrate’是bps (19200)):
void BufferedSerial::update( float elapsed )
{
baud_timer += elapsed;
if ( bytes_written > 1024 )
{
// maintain baudrate
float time_should_have_taken = (float(bytes_written)*10)/float(baudrate);
float time_actually_took = baud_timer;
// sleep if we have > 20ms lag between serial transmit and our write calls
if ( time_should_have_taken-time_actually_took > 0.02f )
{
float sleep_time = time_should_have_taken - time_actually_took;
int sleep_time_us = sleep_time*1000.0f*1000.0f;
//printf("BufferedSerial::update sleeping %i ms\n", sleep_time_us/1000 );
delayUs( sleep_time_us );
// subtract 128 bytes
bytes_written -= 128;
// subtract the time it should have taken to write 128 bytes
baud_timer -= (float(128)*10)/float(baudrate);
}
}
} 很明显,有什么地方出了问题。
一种更好的方法是能够确定当前传输队列中的字节数,并尝试将其保持在固定阈值以下,但我不知道如何在OSX (POSIX)系统上做到这一点。
任何建议都很感谢。
发布于 2010-05-24 08:33:49
如果你想放慢你的动画速度以匹配你可以写入LED的最大速度,你可以只使用tcdrain();类似这样:
while (1)
{
write(serial_fd, led_command);
animate_frame();
tcdrain(serial_fd);
}发布于 2010-05-23 22:47:22
您可以使用硬件流控制。
我不知道串行链路的另一端有什么硬件,但展台两端可以通过RTS/CTS握手线路进行同步和节流。
毕竟,这就是他们的目的。
发布于 2010-05-24 00:20:29
必须将数据输入到串行热敏条形图记录器一次(非常类似于收据打印机),并有相同类型的问题。数据中的任何延迟都会导致打印输出中的跳转,这是不可接受的。
解决方案非常简单:如果您始终将数据保存在内核串行缓冲区中,则输出将精确到每秒(波特率/ (1 +数据位+停止位))个字符。所以只需添加足够的NUL字节填充来分隔数据即可。
我想,如果一些设备在数据中看到NUL字节,那么它们可能会做非常糟糕的事情,在这种情况下,这将不起作用。但许多人只是忽略了消息之间的额外NUL字节,这让你可以在串口内部使用非常精确的硬件计时器来控制计时。
https://stackoverflow.com/questions/2892096
复制相似问题