Note that there are some explanatory texts on larger screens.

plurals
  1. POTimestamping incoming serial data under WinXP 32 using Boost ASIO and Boost posix time?
    primarykey
    data
    text
    <p>I'm trying to read in and timestamp data from a serial device under WinXP 32. I'm using boost::asio for my serial recieve, but have been running into some limitations. If I try to read and timestamp each 2-byte range measurement by telling asynch_read_some to use a 2-byte buffer, I get massive latency on my range measurements.</p> <p>To get around this my plan has been to use large (5 kb) buffers, timestamp the time when I receive each buffer and dump the buffer, a timestamp, and some other stuff (size, header, footer, etc) into a file. I need these timestamps, as I have to synchronise the sensor data with data from a different device on the same PC. The logging process for that device is also applying timestamps in much the same way, and I am going to hook it all up offline after I have taken my logs.</p> <p>This function is called directly from my boost::asio serial RX callback as soon as data is recieved, and passed the pointer to the buffer and the number of bytes recieved.</p> <pre><code>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 *)&amp;m_packetCounter, sizeof(m_packetCounter)); // Add number of bytes recieved - bytesRcvd m_logFileStream.write((char *)&amp;bytesRcvd, sizeof(bytesRcvd)); // Log Data - RXBuff m_logFileStream.write(RXBuff, bytesRcvd); // Add Timestamp - pktTimestamp m_logFileStream.write((char *)&amp;pktTimestamp, sizeof(pktTimestamp)); // Add End Sentinel - PacketEndSentinel m_logFileStream.write((char *)PacketEndSentinel, sizeof(PacketEndSentinel)); m_packetCounter++; } </code></pre> <p>Since my data is coming in as a constant stream over the serial port, I then make what seems to be a reasonable assumption. I assume that the timestamp I record with each packet is a repeatable (but not necessarily accurate, there will be some approximately constant lag before the callback actually executes) measurement of the time at which I received the last sample in the packet. In my post processing stage, I then take the timestamp from the the previous packet, the timestamp of the current packet, and linearly interpolate to estimate the timestamp of each of the samples within the current packet.</p> <p>What I am finding after post-processing is that, even for extremely low data-rates where there is only 1 or 2 range readings per callback, I am getting extremely unstable timestamping. Some packets are stamped as having the same time, some consecutive packets are being stamped as having impossibly large gaps. When I set the sensor sampling rate as low as 10 Hz, I still get some timestamp differences between samples of 125 milliseconds, and some as low as 80 milliseconds. If I turn the sampling rate up (the sensor can return 2-byte range readings at up to 30 KHz over a 921600 baud RS232 link) I find that the instability becomes even worse. I know by using an oscilloscope on the serial lines that the sensor is actually spitting the data out at the commanded rate, so the flaw must be somewhere in the software-side.</p> <p>Is there something that I am doing wrong, a serious flaw in one of my assumptions, or am I simply going to have to do this all under linux instead to get accurate timestamps? I'd really rather avoid this last option, since although my serial code is cross-platform, my other device code would be hard to make portable.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COWhat COMMTIMEOUTS values are being used by the serial port? Drivers don't, by default, like to generate a signal and ask for a reschedule any faster than they an can get away with. A couple of bytes is not worth making a user thread ready for - better to wait for ages in case more data comes in, and then signal, (a bit like the nagle algorithm on the network). By default, you won't get very accurate timestamps on linux either, unless the serial driver is particularly badly designed :)
      singulars
    2. CO@OcularProgrammer: What is the resolution (granularity) of your pktTimestamp variable? I'm very curious: If you write a tight loop that just keeps doing the `nowPTime(...::local_time())` and `nowPTime.time_of_day().total_microseconds()` repeatedly until it transitions, then again until it transitions again, what is the difference between those two values? And if you do that 100,000 times, is the difference consistent (disregarding a few potential outliers due to hardware interrupts, perhaps)?
      singulars
    3. COCan't understand a thing, you say that your device can sample 2 bytes but you are using a unsigned integer with 8 bytes (uint64_t) for transmission? If this is your actual code you may have some problems with casts. It should be safe but i can't really get the point of it.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload