ICSE014A USB relay (PL2303) on Linux: protocol, script and udev rule
The ICSE014A eight-channel relay module connects to a PC over USB (there is a PL2303 inside) and is driven by a single byte over a serial port. How to control it from Linux without any extra software: the commands, how to build the byte for the relays you want, a ready-made script that switches one relay without touching the others, and a udev rule for automatic setup.
The module
ICSE014A is 8 relays, micro-USB and a 5 V auxiliary power socket. Only the 8-channel model has that socket: eight relays can draw more than USB supplies. The smaller models of the series are the ICSE012A with 4 relays and the ICSE013A with 2. The protocol is the same for all.
| Parameter | ICSE014A |
|---|---|
| relays | 8 |
| supply | 5 V, up to 700 mA |
| interface | USB (PL2303) or TTL UART |
| baud rate | 9600 bit/s |
The vendor provides a Windows tool (Relay Board Manager). We needed Linux, where no tool is needed: sending a few bytes to the port is enough.
On Linux
The PL2303 driver is in the kernel. After plugging in, the log (dmesg) shows:
usb 4-2: New USB device found, idVendor=067b, idProduct=2303
usb 4-2: Product: USB-Serial Controller
usb 4-2: Manufacturer: Prolific Technology Inc.
pl2303 4-2:1.0: pl2303 converter detected
usb 4-2: pl2303 converter now attached to ttyUSB0
So the module is the port /dev/ttyUSB0.
The adapter can be released and attached again without pulling the cable. That helps when the port hangs. The relays keep their state, because their power is not removed.
echo -n "4-2:1.0" > /sys/bus/usb/drivers/pl2303/unbind
echo -n "4-2:1.0" > /sys/bus/usb/drivers/pl2303/bind
4-2:1.0 is the device address from the log above. Yours will be different.
The protocol in three steps
stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb raw -echo
printf '\x50' > /dev/ttyUSB0 # "hello": the ICSE014A answers with AC
printf '\x51' > /dev/ttyUSB0 # from now on the module takes bytes as commands
printf '\x00' > /dev/ttyUSB0 # all 8 relays energised
printf '\xFF' > /dev/ttyUSB0 # all released (the power-on state)
What matters:
- One byte drives all eight relays at once. One bit per relay, and 0 means “relay energised”.
- There is no separate “switch relay 3 on” command. To change one relay you send the whole byte, so you must remember the state of the others.
- The module does not report its relay state. You have to keep the state yourself.
Building the byte
With the board held USB connector up, the relays sit like this:
| Left column | Right column |
|---|---|
| 8 (next to USB) | 4 (next to USB) |
| 7 | 3 |
| 6 | 2 |
| 5 | 1 |
On our board relay 1 is the most significant bit: write the states of relays 1…8 from left to right as a binary number.
| What we want | Bits (relay 1→8) | Byte |
|---|---|---|
| nothing on | 11111111 | FF |
| relay 1 only | 01111111 | 7F |
| relays 1, 2, 4 and 8 | 00101110 | 2E |
| all | 00000000 | 00 |
We checked this on the module: 7F switches on relay 1 only, and 2E switches on relays 1, 2, 4 and 8.
⚠ The vendor says “bit 0 — K1”. So either the K1…K8 markings on the board run opposite to our positional numbering, or boards differ. Check yours with 7F before connecting a load.
A ready-made script
The script keeps the state in a file and changes only the bit you need:
relay8 init # command mode + restore the saved state
relay8 on 3 # energise relay 3, the others stay as they are
relay8 off 3
relay8 all-off
relay8 status
relay8.sh.txt · 1909 B: save it as /usr/local/bin/relay8 and make it executable (chmod +x). If the bits on your board run the other way, there is one line in the script to change, with an explanation next to it.
Automatic setup: a udev rule
After every plug-in the module has to be put into command mode again (50, 51). A udev rule does that by itself and gives the port a stable name, /dev/relay8, so you do not have to guess between ttyUSB0 and ttyUSB1:
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="relay8", MODE="0660", GROUP="dialout", RUN+="/usr/local/bin/relay8 init"
99-relay8.rules.txt · 795 B: put it in /etc/udev/rules.d/99-relay8.rules, then run udevadm control --reload.
⚠ 067b:2303 is any PL2303 adapter. If another one is plugged in, add a serial number or a USB port number to the rule (udevadm info -a -n /dev/ttyUSB0).
⚠ Old guides use SYSFS{idVendor}. Modern udev does not know that key, and the rule silently does nothing. You need ATTRS{…}.
Article changelog
| Date | What changed |
|---|---|
| 2026-11-07 | Article rewritten: the protocol in short, a byte table, our own script that keeps the state, a modern udev rule. |
| 2017-09-29 | First version on the old site. |