Closed omelia-iliffe closed 3 months ago
A bit more digging and I have a working example
use rs485::SerialRs485;
use std::{fs::File, os::fd::AsRawFd, thread, time::Duration};
fn main() {
let port_name = "/dev/ttyS5";
// open the file. This must remain in scope until the settings have been written
let file = File::open(port_name).unwrap();
let mut port = SerialRs485::from_fd(file.as_raw_fd()).unwrap(); //read the current settings from the file
port.set_enabled(true); //enable rs485
port.set_on_fd(file.as_raw_fd()).unwrap(); //write the settings to the file
drop(file); //finished with the file now. Dropping it isn't 100% necessary
let ser = serial2::SerialPort::open(port_name, 115200).unwrap(); //open the serial port like normal
loop {
ser.write(b"test").unwrap();
thread::sleep(Duration::from_millis(500));
}
}
I'm not sure if this is worth folding into the crate. It could also be done externally I think.
Hmm, serial devices never cease to annoy me. More random ioctls! :D
But yeah, I think I want to support this. Dynamixels with RS485 were one of the main reasons for writing this library. The converters I used didn't need an IOCTL though.
I'm not 100% sure how to integrate this. The main challenge is: if we add a function called enabled_rs485()
or something, how do we know what method to use to enable it? I'm worried it will turn out that different devices have different ways to enable it.
Although I guess worst case we can just try all known method until we find one that works.
And: some converters are set to RS485 with hardware switches, or they're always RS485 anyway. Then this ioctl will probably fail, even though the converter is set to RS485. But I think this will need to be solved with documentation.
So yeah, I think it is worth adding support for this. Do you want to write a PR for it? If not, I will try to get to it soon-ish.
For your workaround, it should also work to open the serial port first, and then do the ioctl:
use rs485::SerialRs485;
use std::{fs::File, os::fd::AsRawFd, thread, time::Duration};
fn main() {
let port_name = "/dev/ttyS5";
let ser = serial2::SerialPort::open(port_name, 115200).unwrap();
let mut port = SerialRs485:
port.set_enabled(true); //enable rs485
port.set_on_fd(ser.as_raw_fd()).unwrap(); //write the settings to the file
loop {
ser.write(b"test").unwrap();
thread::sleep(Duration::from_millis(500));
}
}
Hope you're holiday's were pleasant.
They were, thanks :D
Yup, I can give it a go.
Do you think it should be part of the settings struct, a method you call after opening the port, or a separate method for serial2::SerialPort
like open_rs485
? Also would you like to use the rs485
crate as a dependency or re implement it
Although I guess worst case we can just try all known method until we find one that works.
I'd be worried that it would quietly fail and than we wouldn't know if it was working or not. Hard to test if it succeeded :/
Those IOCTLS only exist on some RS-485 devices that support using RTS for signaling send/recive on the same line
https://www.kernel.org/doc/Documentation/serial/serial-rs485.txt
Some CPUs/UARTs (e.g., Atmel AT91 or 16C950 UART) contain a built-in half-duplex mode capable of automatically controlling line direction by toggling RTS or DTR signals. That can be used to control external half-duplex hardware like an RS485 transceiver or any RS232-connected half-duplex devices like some modems.
So we should support it, but not rely on it for RS485 support. Many industrial installations for example just use two half-duplex RS486 lines for full duplex, or the main node directs the children nodes, asking for updates and waiting over the same half duplex line.
It also might make sense to use a type state pattern, and return a Serial
Lets continue discussion in this PR: https://github.com/de-vri-es/serial2-rs/pull/29
Hello again, Hope you're holiday's were pleasant.
I am using a PCIE RS485 board with some Dynamixels and would love to use this library. I have tested the board (with dynamixels) using the python pyserial library and its working correctly but not sure where to start with modifying this Serial2 crate.
The python lib uses ioctl to set bits of the TIOCSRS485
fcntl.ioctl(self.fd, TIOCSRS485, buf)
https://github.com/pyserial/pyserial/blob/7aeea35429d15f3eefed10bbb659674638903e3a/serial/serialposix.py#L195There is also this rust lib that seems to mirror what python does: https://github.com/mbr/rs485-rs/blob/master/src/lib.rs its possible that this crate can be using independently to set the correct settings and Serial2 to handle the comms.