Initial support for...
Clear all

Initial support for 8- and 16-channel relay driver boards using MCP23008 or MCP23017 and the ULN2803a Darlington array

Trusted Member
Joined: 9 months ago
Posts: 80
Topic starter  

Hi everyone, I've been working on adding more cheap and plentiful relay outputs to my Mycodo installation, and I've got some linux shell scripts that can control these relay systems effectively that I'm happy to share with anyone that can find them useful. They're working for me in production, but there will inevitably be refinements coming down the line, and hopefully I'll get around to making them into cleaner python modules soon.



This assumes you already have enabled I2C on your Pi and are familiar connecting I2C devices to it. If not, there are plenty of good instructions on how to do that first available elsewhere.

Get a cheap MCP23017 (16 channel) or MCP23008 (8-channel) I2C expander chip -- they're about $4 on Amazon I believe, and you can get them in DIP form if you don't like surface mount soldering. Adafruit has the MCP23008 for $2

Don't get the MCP23S17 or you'll have to deal with SPI instead of I2C.

Then get a either two ULN2803a Darlington transistor arrays for 16 channels or a single chip to match the number of channels you want, and then a bank of relays such as the Sainsmart 8-channel board if you want an inexpensive set of mechanical relays, or even a handful of Fotek/Crydom/etc standalone solid state relays (and appropriate heatsinks) if you want to switch higher amperage loads. Though the Fotek SSRs claim that they'll trigger with anything between 3-32VDC I've found that some of mine (perhaps because they're counterfeit knockoffs) won't fully enable without 5V and sometimes as much as 20 or 30mA drive current.

Get an additional DC power supply  with an appropriate voltage and amperage rating to drive your selection of relays. The ULN2803a transistor arrays will switch up to 50VDC outputs, but I've only tested this configuration with +12V and +5V relays so far. This chip includes internal freewheeling diodes to snub the EMF from switching off relay coils, but if you're trying to drive a monster coil with it you might consider getting an additional diode to parallel with the output for safety. 1N4001 seems to work fine for me.

Wire it up!

on your MCP23017 or MCP23008 connect its SCL and SDA pins to your Pi's I2C bus, connect VDD and RESET pins to the Pi's +3.3V supply.

Connect the MCP's VSS pin to the Pi's ground, and to your external power supply's ground, and to the ground pin of your ULN2803a chip.

The MCP chips can support up to 8 I2C address (from 0x20 to 0x27) so you can have quite a few relay boards on the same I2C bus before having to add an additional I2C bus or use a multiplexer. Pins A0,A1,A2 can be connected to either ground or +3.3V to set the addresses as desired, but if left disconnected it defaults to 0x20.

Connect the 8 IO pins of the MCP23008 to the 1B-8B input pins of the ULN2803a. If you have an MCP23017 you'll need to repeat this step for your second bank of IO pins and your second ULN2803a chip.

Connect the +5V or +12V of your external power supply to your ULN2803a common pin (10)  as well as to all of the positive control terminals for the relays or relay boards you wish to drive with this setup. Then connect the negative control terminal for each of your relays if they're individual relays to the 1C-8C output pins of the ULN2803a chip. If you're using a Sainsmart 8-channel board these would be the IN1 .. IN8 pins on its header.

DO NOT connect that +5V or +12V to your RPi's +3.3V supply that is powering the MCP23017/008, or bad things happen.

Because the ULN2803a is an NPN transistor array, when an input pin is activated by the MCP23008/017 chip, the output pin is effectively grounded and thus allows power to flow through the relay control terminals or relay coil if it's a mechanical relay.

SSH into your Pi, and verify that you can see the MCP23008/017 device on your i2c bus:

Example: i2cdetect -y 1

If it appears, make a note of the I2C address (0x20 or whatever) and the bus number that you're using. Download that bash shell script that I linked to at the beginning of this post, copy it to /home/pi on your Pi, mark it executable:

chmod +x /home/pi/

Then edit the file with your preferred text editor (vi, nano etc) and scroll down until you see the variables for ADDR, BUS, LOCKFILE, IODIR, OLAT, and read the directions in the comments there, and change the values to match your system configuration choices.

After saving it, you should be able to run

/home/pi/ init on

(or init off, if you want to initialize it with all relays off)

/home/pi/mcp23017_relay_v1 5 off

(to turn off relay #5).

You'll want to add the line

/home/pi/ init off

(or on) to your Pi's /etc/rc.local file so that it sets the appropriate initial state as soon as the Pi is finished booting, and make sure that /etc/rc.local is executable by running

sudo chmod +x /etc/rc.local

Then you can set up an "on/off shell script" output in Mycodo for each of the relays, and enter the path to the command with the relay number and the parameter "on" or "off" as necessary. If you run the shell script yourself with no parameters in an SSH session you'll see example syntax.

Note: As it stands currently, you'll have to have a separate copy of this script for *each* bank of 8 relay pins you wish to control, so if you have an MCP23017 you'll need to copy it to another name and configure both copies of the script with the appropriate ADDR/BUS/IODIR/OLAT variables as described in the script. I personally use naming like,,, etc.

Enjoy! You now have a $10-15 8 or 16 channel relay driver board for without having to fuss with individual transistors,resistors, diodes, and you can control higher-voltage relays or even just 5V relays without having to use 3.3V-to-5V logic level converters or the like, and keep your I2C bus entirely on 3.3V and not tax your Pi's power supply pins. :)

New Member
Joined: 1 month ago
Posts: 1

Hello..Would i be able to interface straightforwardly I2C from Arduino to SX1509 or MCP23017 and afterward to those two transfers?

I've associated single transfer sheets previously however never 16 of them.

16 Channel Relay Board has outer force supply, would it be advisable for me to associate outside force supply for those transfers? How could I compute current? Would i be able to tally 100mA for single hand-off? So for 16 transfers I'll require 1.6A 5V?