I'm trying to port a program, which communicates over RS485 half-duplex UART, to Raspberry Pi. Since Pi's built-in UARTs don't support the RS485 standard, I'm using the USB-RS485-WE-1800-BT FTDI cable.
When connected, I can confirm that the cable's FTDI chip shows up in dmesg
, the ftdi_sio
driver is loaded, and properly exposes the /dev/ttyUSB0
serial terminal to the rest of the system. However, when I attempt to enable RS485 mode from a simple C program:
struct serial_rs485 config = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND,
.delay_rts_before_send = 0,
.delay_rts_after_send = 0
};
if (ioctl(fd, TIOCSRS485, &config) < 0) {
fprintf(stderr, "ioctl failed (%d): %s\n", errno, strerror(errno));
exit(0);
}
... I get the following error:
ioctl failed (25): Inappropriate ioctl for device
Looking into a schematic, I realized that the FTDI cable internally uses 2 components:
ftdi_sio
driver over USB and produces conventional serial output, andSo, given that FT232R doesn't technically emit RS485, I understand why its driver complains when asked to enable RS485 mode. What it doesn't know, though, is that the second chip takes care of format conversion transparently.
Having researched this topic for a bit and read answers to a similar question, I'm now curious how to proceed. Should I change the request ID in my ioctl()
call to something else than TIOCSRS485
? Should I remove the ioctl()
call entirely? And if I do that, how can RS485 flags and RTS delays be set? Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Should I change the request ID in my
ioctl()
call to something else thanTIOCSRS485
? Should I remove theioctl()
call entirely?
Removing the ioctl()
would be the appropriate thing to do in this case, as the serial converter is handling it entirely for you. As far as you are concerned, it is just a serial port that you read and write to.
And if I do that, how can RS485 flags and RTS delays be set?
You can't set any flags or delay using the FTDI cable. However, since the data that comes out of the cable is already RS485, there's no need to set anything. As long as whatever it is you're talking to is half-duplex(it does not talk at the same time as you do), this isn't an issue, and you can use it just like an RS232 cable. This depends on your specific use-case though. I have never encountered the need to have an RTS delay.
Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Sure, you can do that. There are also many different models of RS485 transcievers that you could use; Electronics.SE would the the place to ask for more information on that. You may need to enable RS485 at that point with TIOCSRS485
, but that's going to be driver-dependent. I don't know about the Pi, but at least on some Atmel chips that I have used before setting the RS485 mode sets a certain bit in the peripheral on the chip that automatically toggles the RTS pin to enable/disable the RS485 transciever; otherwise, Linux needs to toggle a GPIO in order to set the transciever into the correct state.
Specifically on the FTDI, there are GPIOs that can be set that will turn on/off at appropriate times. One of these is the TXDEN signal, which controls the transciever for you automatically. Others are used for the Tx/Rx LEDs.