Use the IO Expander and Relay Expander to control up to 65,280 relays.
Need to add a lot of relays to your project? Then you need the IO Expander with Relay Expanders. Each IO Expander can control up to 16 daisy chained Relay Expanders for a total of 256 relays. Then connecting 255 IO Expanders together you can selectively control up to 65,280 relays.
Control Relays with a Single IO Expander.- Use cheap < $15 Arduino 16 relay boards.
- Easy to use relay control commands.
- Control an individual relay or a bank at a time.
- No driver required. Save code space.
- No data space to maintain relay state.
- No extra power supply needed.
Note: In the above wiring diagram the IO Expander is being powered by the first relay board. All the Relay Expanders are powered from the relay board they are connected to.
#!/usr/bin/env python
import ioexpander
import time
ioexpander.ser.flushInput()
ioexpander.SerialCmdDone(b'eb4')
relay = 1
while 1:
cmd = b'e' + bytes(str(relay),'raw_unicode_escape') + b'f'
ioexpander.SerialCmdDone(cmd)
relay += 1
if relay > 64:
relay = 1
cmd = b'e' + bytes(str(relay),'raw_unicode_escape') + b'o'
ioexpander.SerialCmdDone(cmd)
time.sleep(0.1)
Multiple IO Expanders Controlling RelaysAnother way to control relays is to use multiple IO Expanders. This gives us the ability to distribute sensors and relays to a central, or star network, but still interconnect all the IO Expanders on a single serial bus. If you have to separate the IO Expanders up to 4000ft then use the IO Extenders as shown below with the standard blue Cat5 network wire.
Note: In the above wiring diagram all the IO Expanders are being powered by the first relay board through the serial bus. All the Relay Expanders are powered from the relay board they are connected to.
#!/usr/bin/env python
import ioexpander9bit
import time
MAX_BOARDS = 4
ioexpander9bit.ser.flushInput()
# set IO Expander to 9-bit
ioexpander9bit.ser.write(b'\0')
# switch to simulated 9-bit mode using SPACE and MARK parity
ioexpander9bit.SerialSPACEParity()
for board in range(1, MAX_BOARDS+1):
ioexpander9bit.SerialCmdDone(board, b'eb1')
board = 1
relay = 1
while 1:
cmd = b'e' + bytes(str(relay),'raw_unicode_escape') + b'f'
ioexpander9bit.SerialCmdDone(board, cmd)
relay += 1
if relay > 16:
relay = 1
board += 1
if board > MAX_BOARDS:
board = 1
cmd = b'e' + bytes(str(relay),'raw_unicode_escape') + b'o'
ioexpander9bit.SerialCmdDone(board, cmd)
time.sleep(0.1)
Raspberry Pi 9-bitThe Raspberry Pi does not support 9-bit, so we will have to use 8-bit mark and space parity. Only problem is that the Raspbian OS does not support mark and space parity either, so for the Pi4 that uses the BCM2711 (pg.186) we will have to use some undocumented code and use what is called stick parity that is selected by bit 7 (SPS) in the LCRH register.
By default the primary serial port on the header pins 14 and 15 uses UART1 (MiniUART/ttyS0) which does not support any parity bits. We will have to switch the pins to use a different UART0 (ttyAMA0) as the primary serial port instead.
To do this add the following lines to your /boot/config.txt file.
enable_uart=1
dtoverlay=disable-bt
Run the following command on your console as well, to disconnect the bluetooth from UART0.
pi@raspberrypi:~ $ sudo systemctl disable hciuart
Python code to set MARK or SPACE parity.
import serial
import termios
ser = serial.Serial(
port='/dev/serial0',
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=5
)
# extra termios flags
CMSPAR = 0x40000000 # Use "stick" (mark/space) parity
# select SPACE parity to clear the address bit
def SerialSPACEParity():
iflag,oflag,cflag,lflag,ispeed,ospeed,cc = termios.tcgetattr(ser)
cflag |= termios.PARENB | CMSPAR
cflag &= ~termios.PARODD
termios.tcsetattr(ser, termios.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
# select MARK parity to set the address bit
def SerialMARKParity():
iflag,oflag,cflag,lflag,ispeed,ospeed,cc = termios.tcgetattr(ser)
cflag |= termios.PARENB | CMSPAR | termios.PARODD
termios.tcsetattr(ser, termios.TCSANOW, [iflag,oflag,cflag,lflag,ispeed,ospeed,cc])
# select the IO Expander board by setting the 9th or address bit
def SerialWriteBoard(board):
if board is not None and board > 0:
SerialMARKParity()
ser.write(bytes(chr(board),'raw_unicode_escape'))
SerialSPACEParity()
So why do I need to control so many relays?One such application is in Aquaponics or Hydroponics. Lot's of sensors and devices need to be automated down to each grow bed or individual plant. This requires extreme IO and the IO Expander delivers.
So get your IO Expander today and build your system!
Comments