#  UART RS-485 development board

[205-1014 - UART RS-485 development board](https://app.bom.com/items/detail-spec?item_id=1417869556)

Development board to interface between UART, RS-485 and USB. The board support interfacing between the physical layer UART, USB & RS-485 with ftdi driver supporting DMX.


![Board, rev A](uart-to-dmx-board.png)


## Interfaces

Use jumpers to either connect the USB or UART, USB to RS-485 or UART to RS-485.


### USB

USB-C to FT231XS provides a UART.

When building the board - use the `ftdi-eeprom.conf` to configure the IC correctly by connecting the board and running `make configure-ftdi`.


### UART

UART interface with RS485 RE and DE signals.

```
+---+---+
| 1 | 2 |  TX          RS485_RE
| 3 | 4 |  RS485_DE    RX
| 5 | 6 |  NC          GND
+---+---+
```


### DMX

Pin connector to a XLR board with termination. I.e. [200-2205 - Luna/Aurora In/Out XLR board with termination](https://app.bom.com/items/detail-spec?item_id=1308054936)


# DMX Configuration for Serial over USB

So when you open your UART port (connected via the RS485↔UART converter), set 250000-8N2

|  Setting  | Value  |
|-----------|--------|
| Baud rate | 250000 |
| Data bits | 8      |
| Parity    | None   |
| Stop bits | 2      |

DMX also uses a **BREAK** (line held low) and **Mark-After-Break** timing to frame packets.


## Receiving DMX over Serial USB

The [receive-dmx.py](tests/receive-dmx.py) is an example on how to receive DMX over the USB Serial interface.


## Sending DMX over Serial USB

The [send-dmx.py](tests/send-dmx.py) is an example of how to send >40Hz DMX over the USB Serial interface.

Note that due to USB overhead the DMX protocol **Break** and **Mark-After-Break** will not be the minimal values and therefore it is not possible to get the full 44Hz @ 250 000 Baud. A rock-solid 44 Hz is not doable, because each DMX frame needs a **BREAK** and that **BREAK** on USB-serial is a USB control transaction (plus scheduler jitter). That overhead is in the ballpark of ~3 Hz. You can shave ~40us by raising priority `sudo chrt -f 80 tests/send-dmx.py`.


## Modbus HIL utilities

The repository also bundles a lightweight Modbus RTU helper library under `src/lr_modbus`. It targets the FT231XS + MAX1487CSA+ stack on this board and exposes both a programmable API and a CLI entry-point for quick experiments.

### Installing the module locally

```bash
python -m pip install -e .[dev]
```

The editable install keeps the package in sync with your working tree and also installs the pytest tooling used by the automated tests.

### Using the CLI

```bash
lr-modbus --port /dev/ttyUSB0 server --holding 0=0x2A,1=0x1337 &

lr-modbus --port /dev/ttyUSB1 client --action read-holding --address 0 --count 2

lr-modbus --port /dev/ttyUSB1 client --action write-single --address 0 --value 67

lr-modbus --port /dev/ttyUSB1 client --action read-holding --address 0

```

By default the CLI speaks 115200-8N1 and gives each Modbus transaction a 2 s deadline while the transport itself enforces the Modbus RTU t3.5 framing gaps. This lets two boards on the same host verify their RS-485 link without extra flags, while `--timeout` lets you shorten or extend the overall operation window.

```bash
lr-modbus --port /dev/ttyUSB0 --baudrate 19200 --stopbits 1 --timeout 2 client ...
```

Use `lr-modbus --help` for the complete list of options, including how to seed holding registers or stop the server after a given number of requests for HIL-style scripting.

### Running tests & coverage

```bash
make test
```

The target wires up `pytest` with coverage reporting against the `lr_modbus` sources.

### Publishing to PyPI

```bash
python -m pip install build twine
python -m build
python -m twine upload dist/*
```

The package metadata lives in `pyproject.toml`, so no extra setup file is required.
