Workshop: repairs and experiments

ICSE014A USB relay (PL2303) on Linux: protocol, script and udev rule

Published 29.09.2017 · Updated 07.11.2026

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.

ParameterICSE014A
relays8
supply5 V, up to 700 mA
interfaceUSB (PL2303) or TTL UART
baud rate9600 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 columnRight column
8 (next to USB)4 (next to USB)
73
62
51

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 wantBits (relay 1→8)Byte
nothing on11111111FF
relay 1 only011111117F
relays 1, 2, 4 and 8001011102E
all0000000000

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

DateWhat changed
2026-11-07Article rewritten: the protocol in short, a byte table, our own script that keeps the state, a modern udev rule.
2017-09-29First version on the old site.