Что может вызвать задержку при использовании последовательного порта между Arduino IDE и внешними клиентами?

Несколько дней я работаю над проблемой, которую не могу решить.

Я использую Teensy3.6 с Arduino IDE для создания монитора шины CAN для автомобиля. Для тех, кто знаком, я пытаюсь сохранить данные в формате can-utils, чтобы их можно было легко воспроизвести на машинах Linux. Плата использует библиотеку FlexCAN для облегчения связи.

Все хорошо работает с последовательным монитором Arduino. Однако я хочу сохранить вывод на хост-компьютер. К сожалению, мне не удалось заставить работать другие последовательные программы. Я пробовал PuTTY & Python через PySerial. Выход, кажется, прерывается & неправильно печатает новую строку.

Пример вывода последовательного монитора Arduino:

(1302.864746) can0 1C5#2C032C032E01
(1302.864868) can0 1F4#000000000000
(1302.865356) can0 287#0000
(1302.865601) can0 F1#340000400000
(1302.865845) can0 96#BFF00A120000
(1302.866455) can0 97#35800A1518300A0A
(1302.866821) can0 98#00000A0080000A13
(1302.867065) can0 1E5#4400335000000103
(1302.867554) can0 C7#00000000
(1302.867798) can0 1E9#FF8300EFFC0000
(1302.868042) can0 232#0000000000000000
(1302.868652) can0 1E1#00000000001CC0
(1302.868896) can0 2F9#83000000000007
(1302.869019) can0 222#001607AD0C00
(1302.869629) can0 BC#A11E005C00000000
(1302.869751) can0 D3#2C02
(1302.869995) can0 186#44005D0000017C
(1302.870483) can0 224#CBC8C8
(1302.870605) can0 228#005B5F5B
(1302.870850) can0 1F3#80BC00
(1302.871460) can0 B9#000A800002000000

Вывод из PuTTY/PySerial:

(1443.927002) can0 C1#10026B0210037D86
(1443.927246) can0 C5#10026B0310026B02
(1443.927490) can0 D1#40007FFF00FF00
(1443.927856) can0 1EB#0241(1444.011230) can0 AA#2C032C030253FC00
(1444.011597) can0 C9#8000002000101800
(1444.012085) can0 1E7#019000000000316D
(1444.012329) can0 1ED#019000000000316D
(1444.012451) can0 34A#000000001B
(1444.012939) can0 1EF#00000000

Мое наивное мнение, что данные по CAN приходят быстрее, чем пишет серийник. Однако странно, что он отлично работает в Arduino IDE. Это происходит примерно 1 раз в секунду, чего вполне достаточно, чтобы вызвать головную боль.

Кто-нибудь знает, почему это может произойти, кроме SD-карт или локальной записи? Или как я могу сохранить эти данные на хост-компьютер? В худшем случае я могу скопировать/вставить вывод последовательного монитора Arduino, но это не очень элегантно.

Спасибо!

Редактировать: вот соответствующий код из моей Arduino IDE. Я изменил пример объектно-ориентированной банки из flexcan для печати в нужном мне формате.

#include <FlexCAN.h>
static CAN_message_t msg;
elapsedMicros sinceStart;

class CANHandler : public CANListener{
  void printFrame(CAN_message_t &frame);
  void gotFrame(CAN_message_t &frame, int mailbox); //переопределяет родительскую версию, чтобы мы действительно могли что-то сделать
};

void CANHandler::printFrame(CAN_message_t &frame){
   Serial.print("("); Serial.print(sinceStart / 1000.0 / 1000.0, 6); 
   Serial.print(") "); // приводим к 6 десятичным знакам для совместимости с can-utils
   Serial.print("can0 "); // для определения канала CAN для can-utils
   Serial.print(frame.id, HEX);
   Serial.print("#");
   for ( uint8_t i = 0; i < frame.len; i++ ) {
     if(frame.buf[i] < 15){
        Serial.print("0"); Serial.print(frame.buf[i], HEX);
     } else {
        Serial.print(frame.buf[i], HEX);
     }
 } 
 Serial.println();
}

void CANHandler::gotFrame(CAN_message_t &frame, int mailbox){
printFrame(frame);
}

CANHandler canHandler;

void setup() {
    Serial.begin(115200);
    Can0.begin(500000);
    Can0.attachObj(&canHandler);
    CanHandler.attachGeneralHandler();
}

void loop() {
//работаем до выхода
}

, 👍0

Обсуждение

Итак, одна вещь в подпрограммах, управляемых прерываниями (я предполагаю, что CANHandler является одной из таких), заключается в том, что они действительно могут запускаться в любое время, в том числе во время, когда обработчик уже запущен. Есть несколько стратегий борьбы с этим. Один из них заключается в том, чтобы обработчик возвращался как можно скорее, а затем обрабатывал медленную задачу (в данном случае последовательный вывод) в основном цикле программы. Но в этом случае вам придется найти способ спрятать CAN-фрейм для последующей обработки., @Chris Combs

IDE буферизует то, что отправляет на экран. Как указывает Крис, ваша проблема, скорее всего, связана с процедурой, управляемой прерываниями. Я использую ramdrive для хранения данных в таких случаях., @Wendall

@ChrisCombs Можно ли запустить обработчик снова, если он уже запущен? Если функция-обработчик вызывается из процедуры обработки прерывания, она не будет прервана другим прерыванием, пока вы не повторно разрешите прерывания внутри нее (и зачем вам это делать в таком случае). Если во время выполнения ISR срабатывает другое прерывание, оно будет выполнено после выхода из текущего ISR. Это, по крайней мере, как я это понимаю., @chrisl

Насколько я понимаю, вам нужно явно отключить прерывания внутри вашего ISR, если вы хотите такого поведения. Но я точно могу ошибаться!, @Chris Combs


1 ответ


Лучший ответ:

0

Если ваша скорость ввода данных выше или даже близка к скорости последовательного вывода (скорость передачи/10 символов/с), ваша система не сможет за ней угнаться.

В системе, управляемой прерываниями, убедитесь, что ваша функция прерывания выполняется и возвращается как можно быстрее, т. е. делает как можно меньше, чтобы не потерять данные. Пусть фоновый процесс (основной код скетча) обрабатывает поступающие данные по мере их появления. Убедитесь, что оба процесса достаточно короткие, чтобы справиться с наихудшими всплесками входных данных без их потери. Для фонового процесса используйте настолько высокую скорость передачи данных, на которую он способен, и на которую способен его нисходящий сосед (устройство хранения данных? другой MCU или ПК?), чтобы не отставать.

,