I am developing a controller for Mobitec Bus destination panel. The intended communication layer is SBC
-> USB 2 RS485 [FTDI]
-> Mobitec
.
This is also the first time for me working with serial and RS485.
While developing, though, my workstation is a Mac OS - if that may change anything.
How do I know it's a FTDI device?
$ 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
Using node-serialport
library, I have written the following code:
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
But sadly, while the logs have no errors and I see the activity LED blinking on my USB 2 RS485
device, it appears that the target device does not receive the message as it does not respond as expected (display isn't updating the LEDs).
Though, if I am to add a timeout after the write, like so:
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.
It works.
Obviously, the device will respond faster than the specified second.
But given that, if I change the timeout to 10ms
, it won't work. If I change it to 50ms
, it seems to be working at all times, but I have noticed some rare exceptions1. 40ms
seems to work ~5% of the time.
1 The exceptions occur when changing the payloads. As if some state has been left in the serial port.
I also attempted to SerialPort.drain
after the write in the write callback. Also tried to drain
in parallel.
Neither did help.
Sadly, I do not have the production intended SBC to test with that, as it will run Linux and that may change something.
In my debugging efforts, I have tried to watch -n .1 node script.js
to see if it's related to some internal buffers of the device, but it works flawlessly with the 50ms
. The 10ms
one won't register a single time. 40ms
produces the ~5% result.
Is the timeout a known thing in serial world and there are known patterns to work around that? Maybe this is a MacOS issue? Maybe the RS485 adapter requires extra treatment?
Really out of clues here...