Отметка времени поступающих последовательных данных под WinXP 32 с использованием Boost ASIO и Boost posix time?
Я пытаюсь считывать и метить данные с последовательного устройства под WinXP 32. Я использую boost::asio для моего последовательного получения, но у меня были некоторые ограничения. Если я попытаюсь прочитать и пометить меткой времени каждое 2-байтовое измерение диапазона, сказав asynch_read_some использовать 2-байтовый буфер, я получу огромную задержку при измерениях диапазона.
Чтобы обойти это, мой план состоял в том, чтобы использовать большие (5 КБ) буферы, метку времени, когда я получаю каждый буфер и выгружать буфер, метку времени и некоторые другие вещи (размер, заголовок, нижний колонтитул и т. Д.) В файл. Мне нужны эти временные метки, так как я должен синхронизировать данные датчика с данными с другого устройства на одном ПК. Процесс регистрации для этого устройства также применяет временные метки почти таким же образом, и я собираюсь подключить все это в автономном режиме после того, как я взял свои журналы.
Эта функция вызывается непосредственно из моего обратного вызова RX 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 Гц, я по-прежнему получаю некоторую разницу в метках времени между выборками, составляющую 125 миллисекунд, а некоторые - всего лишь 80 миллисекунд. Если я увеличу частоту дискретизации (датчик может возвращать показания 2-байтового диапазона на частоте до 30 кГц по каналу RS232 со скоростью 921600 бод), я обнаружу, что нестабильность становится еще хуже. Используя осциллограф на последовательных линиях, я знаю, что датчик фактически выплевывает данные с заданной скоростью, поэтому недостаток должен быть где-то на стороне программного обеспечения.
Есть ли что-то, что я делаю неправильно, серьезный недостаток в одном из моих предположений, или мне просто придется делать все это в Linux вместо того, чтобы получать точные метки времени? Я действительно предпочел бы избежать этого последнего варианта, так как, хотя мой последовательный код кроссплатформенный, код моего другого устройства будет трудно сделать переносимым.
1 ответ
Отметка времени данных, внешних по отношению к ПК, или использование ОС реального времени. Настольные ОС, которые действительно хорошо работают с Office и Firefox, совершенно безнадежны при сборе данных в режиме реального времени. Драйверы оптимизированы, чтобы сигнализировать о получении огромных буферов данных, чтобы максимизировать пропускную способность сложных веб-страниц и потокового мультимедиа. Немедленная сигнализация получения пары байтов (или даже 5 КБ) находится немного ниже их - драйверы не могут быть обеспокоены и имеют тенденцию лежать без дела целую вечность, если поступает больше данных, тогда они могут сигнализировать все это однажды:((
Все мои встроенные контроллеры, которые возвращают данные, для которых требуется отметка времени, возвращают отметку в данных и не полагаются на какую-либо мегалитическую операционную систему для настольного компьютера, чтобы вызвать поток любым быстрым способом.
Тем не менее, вы можете настроить последовательный драйвер COMMTIMEOUTS для более быстрого возврата данных. Поможет ли это сильно - это другой вопрос, потому что у вас есть другие устройства, которые могут быть подвержены тем же проблемам.
Кроме того, что такое m_logFileStream? Это еще одна асинхронная запись или запись в очередь на диск? Если нет, то должно быть.
Если вы хотите попытаться применить временные метки к данным на ПК так, как вам кажется, то в идеале все ваши данные должны проходить через тот же поток, который добавляет временные метки и ведет запись в журнал. Запись нескольких журналов и их последующая фильтрация для сортировки по меткам времени просто добавит еще больше дрожания. Такого рода вещи делают разработчики Unix, потому что их компьютеры могут выполнять только скрипты bash:))