aboutsummaryrefslogtreecommitdiff
path: root/serial/rs485.py
diff options
context:
space:
mode:
Diffstat (limited to 'serial/rs485.py')
-rw-r--r--serial/rs485.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/serial/rs485.py b/serial/rs485.py
new file mode 100644
index 0000000..d7aff6f
--- /dev/null
+++ b/serial/rs485.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+
+# RS485 support
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""\
+The settings for RS485 are stored in a dedicated object that can be applied to
+serial ports (where supported).
+NOTE: Some implementations may only support a subset of the settings.
+"""
+
+from __future__ import absolute_import
+
+import time
+import serial
+
+
+class RS485Settings(object):
+ def __init__(
+ self,
+ rts_level_for_tx=True,
+ rts_level_for_rx=False,
+ loopback=False,
+ delay_before_tx=None,
+ delay_before_rx=None):
+ self.rts_level_for_tx = rts_level_for_tx
+ self.rts_level_for_rx = rts_level_for_rx
+ self.loopback = loopback
+ self.delay_before_tx = delay_before_tx
+ self.delay_before_rx = delay_before_rx
+
+
+class RS485(serial.Serial):
+ """\
+ A subclass that replaces the write method with one that toggles RTS
+ according to the RS485 settings.
+
+ NOTE: This may work unreliably on some serial ports (control signals not
+ synchronized or delayed compared to data). Using delays may be
+ unreliable (varying times, larger than expected) as the OS may not
+ support very fine grained delays (no smaller than in the order of
+ tens of milliseconds).
+
+ NOTE: Some implementations support this natively. Better performance
+ can be expected when the native version is used.
+
+ NOTE: The loopback property is ignored by this implementation. The actual
+ behavior depends on the used hardware.
+
+ Usage:
+
+ ser = RS485(...)
+ ser.rs485_mode = RS485Settings(...)
+ ser.write(b'hello')
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(RS485, self).__init__(*args, **kwargs)
+ self._alternate_rs485_settings = None
+
+ def write(self, b):
+ """Write to port, controlling RTS before and after transmitting."""
+ if self._alternate_rs485_settings is not None:
+ # apply level for TX and optional delay
+ self.setRTS(self._alternate_rs485_settings.rts_level_for_tx)
+ if self._alternate_rs485_settings.delay_before_tx is not None:
+ time.sleep(self._alternate_rs485_settings.delay_before_tx)
+ # write and wait for data to be written
+ super(RS485, self).write(b)
+ super(RS485, self).flush()
+ # optional delay and apply level for RX
+ if self._alternate_rs485_settings.delay_before_rx is not None:
+ time.sleep(self._alternate_rs485_settings.delay_before_rx)
+ self.setRTS(self._alternate_rs485_settings.rts_level_for_rx)
+ else:
+ super(RS485, self).write(b)
+
+ # redirect where the property stores the settings so that underlying Serial
+ # instance does not see them
+ @property
+ def rs485_mode(self):
+ """\
+ Enable RS485 mode and apply new settings, set to None to disable.
+ See serial.rs485.RS485Settings for more info about the value.
+ """
+ return self._alternate_rs485_settings
+
+ @rs485_mode.setter
+ def rs485_mode(self, rs485_settings):
+ self._alternate_rs485_settings = rs485_settings