Для USB с интерфейсом FTDI для RS485 требуется недокументированный тайм-аут после записи? - PullRequest
1 голос
/ 14 апреля 2020

Я разрабатываю контроллер для панели назначения шины Mobite c. Предполагаемый уровень связи: SBC -> USB 2 RS485 [FTDI] -> Mobitec.

Я также впервые работаю с последовательным интерфейсом и RS485.

Хотя при разработке моя рабочая станция - ОС Ma c - если это может что-то изменить.


Как узнать, что это устройство FTDI?

$ system_profiler SPUSBDataType
USB:

    USB 3.0 Bus:

      Host Controller Driver: AppleUSBXHCIWPT
      PCI Device ID: 0x9cb1
      PCI Revision ID: 0x0003
      PCI Vendor ID: 0x8086

        FT230X Basic UART:

          Product ID: 0x6015
          Vendor ID: 0x0403  (Future Technology Devices International Limited)
          Version: 10.00
          Serial Number: DN05Q09Q
          Speed: Up to 12 Mb/s
          Manufacturer: FTDI
          Location ID: 0x14100000 / 8
          Current Available (mA): 500
          Current Required (mA): 90
          Extra Operating Current (mA): 0

Используя библиотеку node-serialport, я написал следующий код:

const SerialPort = require("serialport");

const port = new SerialPort("/dev/tty.usbserial-DN05Q09Q", {
  autoOpen: false,
  baudRate: 4800
});

port.on("open", () => {
  console.log("Opened", port.path);
});

port.open((error) => {
  if (error) {
    return void console.error(`Error opening port`, port.path, error);
  }

  port.write(/* Buffer with a length of 23 bytes (proprietary structure) */, (error) => {
    if (error) {
      return void console.error(
        "Error while writing...",
        port.path,
        error
      );
    }

    console.log(
      "Written successfully.",
      port.path
    );
  });
});
$ node script.js
Opened /dev/tty.usbserial-DN05Q09Q
Written successfully. /dev/tty.usbserial-DN05Q09Q

Но, к сожалению, хотя в журналах нет ошибок, и я вижу светодиод активности на моем USB 2 RS485 устройство, кажется, что целевое устройство не получает сообщение, поскольку оно не отвечает должным образом (дисплей не обновляет светодиоды).


Хотя, если я хочу добавить Тайм-аут после записи, например, так:

port.write(/* Buffer with a length of 33 bytes (proprietary structure) */, (error) => {
  if (error) {
    return void console.error(
      "Error while writing...",
      port.path,
      error
    );
  }

  console.log(
    "Written successfully.",
    port.path
  );

  console.log("Starting a timeout after write...");
  setTimeout(() => {
    console.log("Timeout after write expired.");
  }, 1000)
});
$ node script.js
Opened /dev/tty.usbserial-DN05Q09Q
Written successfully. /dev/tty.usbserial-DN05Q09Q
Starting a timeout after write...
Timeout after write expired.

Работает.

Очевидно, устройство будет реагировать быстрее, чем указанная секунда.
Но, учитывая, что если я измените время ожидания на 10ms, оно не будет работать. Если я изменю его на 50ms, он, кажется, будет работать постоянно, но я заметил некоторые редкие исключения 1 . 40ms, кажется, работает ~ 5% времени.

1 Исключения возникают при изменении полезных нагрузок. Как будто какое-то состояние было оставлено в последовательном порту.


Я также попытался SerialPort.drain после записи в обратном вызове записи. Также пытался drain параллельно.

Ни один не помог.


К сожалению, у меня нет производственного предназначенного SB C для тестирования с этим, так как он будет работать Linux и это может что-то изменить.

В своих усилиях по отладке я попытался watch -n .1 node script.js проверить, связано ли это с какими-то внутренними буферами устройства, но оно работает безупречно с 50ms. 10ms один не зарегистрируется ни разу. 40ms дает результат ~ 5%.


Является ли тайм-аут известной вещью в последовательном мире, и есть известные схемы, чтобы обойти это? Может быть, это проблема MacOS? Может быть, адаптер RS485 требует дополнительной обработки?

Неужели здесь нет подсказок ...

...