我正在开发一个项目,通过串行数据控制LED灯的动画,并需要与动画引擎保持同步。这种情况下,由于有一个大的串行写缓冲区(OSX(POSIX)+ FTDI芯片组USB串行设备),如果不手动限制write()调用的速度,软件可能会领先几秒钟。目前,我手动限制串行写速度为波特率(8N1 = 10个字节的串行帧每8个字节的数据,19200 bps串行 - >最大每秒1920个字节),但是我遇到了一个问题:随着时间的推移,动画与灯光之间开始脱离同步-一开始还好,但是在10分钟后,动画和灯光之间出现明显的延迟(100ms +)。以下是限制串行写速度的代码(每个动画帧调用一次,“elapsed”是当前帧的持续时间,“baudrate”是波特率(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)系统上实现此目标。
欢迎任何建议。