C++ 使用Boost ASIO和Boost posix time在WinXP 32下为传入的串行数据添加时间戳?

C++ 使用Boost ASIO和Boost posix time在WinXP 32下为传入的串行数据添加时间戳?,c++,timestamp,serial-port,boost-asio,C++,Timestamp,Serial Port,Boost Asio,我正在尝试从Win32下的串行设备读取数据并为其添加时间戳。我正在使用boost::asio作为串行接收器,但遇到了一些限制。如果我试图通过告诉asynch_read_some使用一个2字节缓冲区来读取每个2字节的范围测量值并给其加上时间戳,那么我的范围测量值就会有很大的延迟 为了解决这个问题,我的计划是使用5 kb的大缓冲区,给接收到每个缓冲区的时间加上时间戳,并将缓冲区、时间戳和一些其他内容大小、页眉、页脚等转储到一个文件中。我需要这些时间戳,因为我必须将传感器数据与来自同一台PC上不同设备

我正在尝试从Win32下的串行设备读取数据并为其添加时间戳。我正在使用boost::asio作为串行接收器,但遇到了一些限制。如果我试图通过告诉asynch_read_some使用一个2字节缓冲区来读取每个2字节的范围测量值并给其加上时间戳,那么我的范围测量值就会有很大的延迟

为了解决这个问题,我的计划是使用5 kb的大缓冲区,给接收到每个缓冲区的时间加上时间戳,并将缓冲区、时间戳和一些其他内容大小、页眉、页脚等转储到一个文件中。我需要这些时间戳,因为我必须将传感器数据与来自同一台PC上不同设备的数据同步。该设备的日志记录过程也以几乎相同的方式应用时间戳,我将在获取日志后将其全部脱机连接

一旦接收到数据,就直接从我的boost::asio串行接收回调调用此函数,并将指针传递到缓冲区和接收的字节数

void AR2500CallbackFunction(char * RXBuff, unsigned int bytesRcvd)
{
  boost::posix_time::ptime nowPTime( boost::posix_time::microsec_clock::local_time() );
  uint64_t pktTimestamp( nowPTime.time_of_day().total_microseconds() );

  // Log Packet Header - PacketStartSentinel                                                    
  m_logFileStream.write((char *)PacketStartSentinel, sizeof(PacketStartSentinel));
  // Log Packet ID - m_packetCounter
  m_logFileStream.write((char *)&m_packetCounter, sizeof(m_packetCounter));
  // Add number of bytes recieved - bytesRcvd
  m_logFileStream.write((char *)&bytesRcvd, sizeof(bytesRcvd));
  // Log Data - RXBuff
  m_logFileStream.write(RXBuff, bytesRcvd);
  // Add Timestamp - pktTimestamp
  m_logFileStream.write((char *)&pktTimestamp, sizeof(pktTimestamp));
  // Add End Sentinel - PacketEndSentinel
  m_logFileStream.write((char *)PacketEndSentinel, sizeof(PacketEndSentinel));
  m_packetCounter++;
}
由于我的数据是通过串行端口以恒定流的形式输入的,因此我做出了一个合理的假设。我假设我在每个数据包中记录的时间戳是可重复的,但不一定准确,在回调实际执行我接收数据包中最后一个样本的时间测量之前,会有一些近似恒定的延迟。在我的后处理阶段,我从前一个数据包中获取时间戳,即当前数据包的时间戳,然后线性插值以估计当前数据包中每个样本的时间戳

在后处理之后,我发现,即使对于极低的数据速率(每个回调只有1或2个范围读数),我也会得到极不稳定的时间戳。一些数据包被标记为具有相同的时间,一些连续的数据包被标记为具有不可能的大间隙。当我将传感器采样率设置为10 Hz时,125毫秒的采样与80毫秒的采样之间仍然存在时间戳差异。如果我提高采样率,传感器可以通过921600波特RS232链路返回高达30 KHz的2字节范围读数,我发现不稳定性变得更糟。通过在串行线路上使用示波器,我知道传感器实际上是在以命令的速率输出数据,因此缺陷一定在软件端的某个地方


是我做错了什么,我的假设中有一个严重的缺陷,还是我只是要在linux下做这些来获得准确的时间戳?我真的宁愿避免最后一种选择,因为尽管我的串行代码是跨平台的,但我的其他设备代码很难移植。

给PC外部的数据加上时间戳或使用实时操作系统。真正擅长于运行Office和Firefox的桌面操作系统在实时数据采集方面是毫无希望的。驱动程序经过优化,可以发出接收巨大数据缓冲区的信号,从而最大限度地提高复杂网页和流媒体的吞吐量。接收到几个字节,甚至5K的提示信号比它们低一点-驾驶员不会感到麻烦,并且往往会在收到更多数据的情况下长时间躺着,然后他们可以立即发出信号:

我所有返回需要时间戳的数据的嵌入式控制器都返回数据中的时间戳,并且不依赖于某些megalithic桌面操作系统以任何形式的提示方式唤醒线程

也就是说,您可以调整串行驱动程序COMMTIMEOUTS以更快地返回数据。这是否会有很大帮助是另一回事,因为您还有其他设备可能会遇到同样的问题

还有,“m_logFileStream”是什么?这是另一个异步或排队磁盘写入吗?如果不是,应该是这样


如果您想尝试以您想要的方式对PC中的数据应用时间戳,那么理想情况下,所有数据都应该通过添加时间戳并进行日志记录的同一线程。编写多个日志,然后过滤它们,将它们按时间戳顺序排序,这只会增加更多的抖动。Unix开发人员就是这么做的,因为他们的计算机只能执行bash脚本:

Cheers@Martin,这里有更多的信息:1我使用的是boost::asio::serial。就我所能找到的而言,这不会让我获得调整的通信超时。。。2不幸的是,我不能在外部为我的量程数据应用时间戳,我的设备只能输出原始量程读数。3 m_logFileStream是一个std::ofstream,我相信它会排队,稍后会处理。4我想与之同步数据的另一个设备没有异步读取功能,这是一个让ass模块头疼的问题,有一个由弱智猴子编写的API。这意味着我的串行接收必须在它自己的线程中处理。我现在已经尝试了一些其他的事情
,虽然承认这一点让我很痛苦,但我需要更聪明一点才能让这一切顺利进行。我只是无法让boost::asio返回任何大于3968字节的缓冲区。为什么3968我不知道,但这似乎是基本极限,所以我的平均误差的想法是死在水中。为朋友的建议干杯。我一点也不明白,你说你的设备可以采样2个字节,但你使用的是一个8字节的无符号整数uint64\t进行传输?如果这是您的实际代码,您可能会在强制转换方面遇到一些问题。它应该是安全的,但我不能真正理解它的意义。串行端口正在使用什么COMMTIMEOUTS值?在默认情况下,司机们不喜欢以他们能逃脱的任何速度发出信号并要求重新安排行程。几个字节不值得让一个用户线程做好准备——最好等待很长时间,以防更多数据进入,然后发出信号,有点像网络上的nagle算法。默认情况下,在linux上也不会获得非常准确的时间戳,除非串行驱动程序设计得特别糟糕:@OcularProgrammer:pktTimestamp变量的分辨率粒度是多少?我很好奇:如果你写了一个紧循环,它一直在做nowPTime…::local_time和nowPTime.time_of_day.total_微秒重复,直到它转换,然后再转换,这两个值之间的区别是什么?如果你这样做100000次,忽略一些可能由于硬件中断而产生的异常值,差异是否一致?