串口:write()限制?

dam*_*ian 6 c c++ synchronization posix serial-port

我正在开发一个项目,发送串行数据来控制LED灯的动画,这需要与动画引擎保持同步.似乎有一个大的串行写缓冲区(OSX(POSIX)+ FTDI芯片组usb串行设备),因此无需手动限制对write()的调用,软件可以提前几秒钟点亮.

目前我手动将串行写入速度限制为波特率(8N1 =每8字节数据10字节串行帧,19200 bps串行 - >每秒最多1920字节),但我遇到动画漂移不同步的问题随着时间的推移 - 它开始很好,但10分钟后动画和灯光之间有一个明显的(100毫秒+)滞后.

这是限制串行写入速度的代码(每个动画帧调用一次,'过去'是当前帧的持续时间,'波特率'是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);
        }
    }
}   
Run Code Online (Sandbox Code Playgroud)

显然,某处出现了问题.

一个更好的方法是能够确定当前在传输队列中的字节数,并尝试将其保持在固定阈值以下,但我无法弄清楚如何在OSX(POSIX)系统上执行此操作.

任何建议表示赞赏

caf*_*caf 3

如果您想放慢动画速度以匹配写入 LED 的最大速度,您可以使用tcdrain(); 像这样的东西:

while (1)
{
    write(serial_fd, led_command);
    animate_frame();
    tcdrain(serial_fd);
}
Run Code Online (Sandbox Code Playgroud)