User avatar
RABIS50
Posts: 8
Joined: Tue May 15, 2012 6:56 am

MCP23S17 as I/O expander?

Wed May 16, 2012 2:04 pm

Hi,
I' m interested to connect a MCP23S17 to the R-pi for using with scratch. Has someone helpful information?

Thanks
RABIS50

User avatar
TonyD
Posts: 451
Joined: Thu Sep 08, 2011 10:58 am
Location: Newcastle, UK
Contact: Website

Re: MCP23S17 as I/O expander?

Fri May 18, 2012 12:38 pm

I've plans to use the SPI version MCP23017 on a simple UserPort board I've designed.
Tony

progetti-hw-sw
Posts: 1
Joined: Fri May 18, 2012 5:12 pm

Re: MCP23S17 as I/O expander?

Fri May 18, 2012 5:16 pm

hello, we develop a board with 8Relay and 8input with din enclosure and drive the relay and the input using the I2C bus, visit
www.progetti-hw-sw.it/raspberry.htm
we also made an Arduino to Raspberry shield
Best Regards

selsinork
Posts: 151
Joined: Mon Apr 16, 2012 8:31 am

Re: MCP23S17 as I/O expander?

Fri May 18, 2012 7:22 pm

there are kernel drivers for the spi and i2c versions of these chips under drivers/gpio, you'll have to recompile the kernel to add them though.

I have some of both the i2c and spi versions here and I'll be trying them out sometime soon.

Not looked at how to setup the spi one yet, but for the i2c version you need something like this at runtime:

Code: Select all

modprobe gpio-mcp23s08
echo mcp23017 0x4f > /sys/bus/i2c/devices/i2c-0/new_device
where you replace 0x4f with the i2c address.

It should also be possible to add them as a platform device somewhere in bcm2708.c to have them setup automatically on boot.

User avatar
csoutreach
Posts: 32
Joined: Mon Nov 28, 2011 1:06 pm
Contact: Website

Re: MCP23S17 as I/O expander?

Sat May 19, 2012 8:25 am

RABIS50 wrote:Hi,
I' m interested to connect a MCP23S17 to the R-pi for using with scratch. Has someone helpful information?
Thanks
RABIS50
A good idea! -- Let us know if you design your own board. -- This is our version with Scratch
http://piface.openlx.org.uk/scratch-con ... -raspberry
http://www.youtube.com/embed/-3JDeqXIqeg
http://piface.openlx.org.uk/ Raspberry Pi IO Interface Board

User avatar
nsc
Posts: 2
Joined: Sat May 12, 2012 6:11 pm
Location: Warrington, UK
Contact: Website

Re: MCP23S17 as I/O expander?

Sun May 20, 2012 10:38 am

I had a play with the MCP23017 yesterday (I2C version of the MCP23S17), very easy to get it working although have only tried it with i2c-tools so far: http://zorg.org/8tg

selsinork
Posts: 151
Joined: Mon Apr 16, 2012 8:31 am

Re: MCP23S17 as I/O expander?

Tue May 22, 2012 10:24 pm

nsc wrote:I had a play with the MCP23017 yesterday (I2C version of the MCP23S17), very easy to get it working although have only tried it with i2c-tools so far: http://zorg.org/8tg
I've just got a mcp23008 working with the in-kernel driver, see https://github.com/selsinork/raspberry- ... pi-drivers

Zoop57
Posts: 8
Joined: Tue May 15, 2012 8:26 pm

Re: MCP23S17 as I/O expander?

Wed May 23, 2012 12:06 pm

Could anyone point me to instructions on how to get i2c working on my pi?

User avatar
nsc
Posts: 2
Joined: Sat May 12, 2012 6:11 pm
Location: Warrington, UK
Contact: Website

Re: MCP23S17 as I/O expander?

Sat Jun 02, 2012 11:06 pm

I knocked up an MCP23017 expansion board this afternoon using the Slice of Pi from Ciseco (very handy little board), details here with a step by step to getting I2C working along with links for a kernel & modules I've compiled with I2C support: http://nathan.chantrell.net/20120602/ra ... der-board/

Also describes how to use some basic Python tools that I'm working on, only working with outputs so far but plan is to add support for inputs and then turn it into a library.

Fede
Posts: 14
Joined: Sun May 13, 2012 5:39 pm
Location: Italy

Re: MCP23S17 as I/O expander?

Wed Jun 06, 2012 11:17 am

Great job nsc, a very cheap way to use an expansion board!
Could the MCP23017 support also analog inputs?

selsinork
Posts: 151
Joined: Mon Apr 16, 2012 8:31 am

Re: MCP23S17 as I/O expander?

Wed Jun 06, 2012 2:20 pm

Fede wrote:Could the MCP23017 support also analog inputs?
As long as they're only 0v or 3.3v yes :P

You probably want something like the MCP3008 or MCP3903 for proper analogue inputs. We may well be off into roll-your-own-driver territory here too.

superpat999
Posts: 15
Joined: Fri May 25, 2012 12:46 pm

Re: MCP23S17 as I/O expander?

Sat Jun 09, 2012 10:09 am

by progetti-hw-sw » Fri May 18, 2012 6:16 pm
hello, we develop a board with 8Relay and 8input with din enclosure and drive the relay and the input using the I2C bus, visit
http://www.progetti-hw-sw.it/raspberry.htm
we also made an Arduino to Raspberry shield
Best Regards

Posts: 1
Joined: Fri May 18, 2012 6:12 pm

I have had no replies to my inquiry emails re this board, has anyone any more details please?

thanks

Patrick

Galoula
Posts: 1
Joined: Mon Dec 31, 2012 9:05 pm

Re: MCP23S17 as I/O expander?

Mon Dec 31, 2012 9:14 pm

Hi !

I have on my RPi, an MCP23008 and an MCP23017 working.

Actualy, I use i2ctools to get it works :

Code: Select all

root@raspberrypi:~# i2cset -y 0 0x20 0x00 0x00 # 0 for output
root@raspberrypi:~# i2cset -y 0 0x20 0x09 32
root@raspberrypi:~# i2cget -y 0 0x20 0x09
0x20
root@raspberrypi:~# i2cset -y 0 0x20 0x09 255
root@raspberrypi:~# i2cget -y 0 0x20 0x09
0xff
My relays change states well.

Now I want to use, the native driver to get GPIO in userspace :

Code: Select all

echo mcp23008 0x20 > /sys/bus/i2c/devices/i2c-0/new_device
But this doesn't works :

Code: Select all

Dec 31 19:27:07 raspberrypi kernel: [  859.853094] mcp230xx: probe of 0-0020 failed with error -22
Dec 31 19:27:07 raspberrypi kernel: [  859.853137] i2c i2c-0: new_device: Instantiated device mcp23008 at 0x20
And, of course, I don't have any new devices into /sys/class/gpio

What's happend ?

Regards,

Gaël

User avatar
Richard-TX
Posts: 1549
Joined: Tue May 28, 2013 3:24 pm
Location: North Texas

Re: MCP23S17 as I/O expander?

Mon Jul 08, 2013 2:31 pm

RABIS50 wrote:Hi,
I' m interested to connect a MCP23S17 to the R-pi for using with scratch. Has someone helpful information?

Thanks
RABIS50
Here is a simple program to get you going,. No special libraries needed. :)


Save it as spi-test.c then do a "make spi-test" You can invoke it as simply "spi-test" or "spi-test /dev/spidev0.0"

/****************************************
* basic program for mcp23s17 with addressing
* and interrupts enabled.
*****************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
/* change CMD_WRITE and CMD_READ addrs to match MCP23S17 address */
#define CMD_WRITE 0x40
#define CMD_READ 0x41
/* if MCP23S17 addr == 1 then cmd_write = 0x42 and cmd_read = 0x43 */
static char *spiDevice = "/dev/spidev0.0" ;
static uint8_t spiMode = 0 ;
static uint8_t spiBPW = 8 ;
static uint32_t spiSpeed = 5000000 ; /* */
static uint16_t spiDelay = 0;

/* all of the MCP23S17 Registers */
#define IOCON 0x0A
#define IODIRA 0x00
#define IPOLA 0x02
#define GPINTENA 0x04
#define DEFVALA 0x06
#define INTCONA 0x08
#define GPPUA 0x0C
#define INTFA 0x0E
#define INTCAPA 0x10
#define GPIOA 0x12
#define OLATA 0x14
#define IODIRB 0x01
#define IPOLB 0x03
#define GPINTENB 0x05
#define DEFVALB 0x07
#define INTCONB 0x09
#define GPPUB 0x0D
#define INTFB 0x0F
#define INTCAPB 0x11
#define GPIOB 0x13
#define OLATB 0x15
/*
* Interrupt pin can be configured for Open drain or push-pull
* Set bit 2 of IOCON high for ODR. ODR enables int pins to be tied together and wired to GPIO23 for example
* thus eliminating the need for polling.
*/
int spi_fd;
static uint8_t readByte (uint8_t reg)
{
uint8_t tx [4] ;
uint8_t rx [4] ;
struct spi_ioc_transfer spi ;
tx [0] = CMD_READ ;
tx [1] = reg ;
tx [2] = 0 ;
spi.tx_buf = (unsigned long)tx ;
spi.rx_buf = (unsigned long)rx ;
spi.len = 3 ;
spi.delay_usecs = spiDelay ;
spi.speed_hz = spiSpeed ;
spi.bits_per_word = spiBPW ;
ioctl (spi_fd, SPI_IOC_MESSAGE(1), &spi) ;
return rx [2] ;
}
static void writeByte (uint8_t reg, uint8_t data)
{
uint8_t spiBufTx [3] ;
uint8_t spiBufRx [3] ;
struct spi_ioc_transfer spi ;
spiBufTx [0] = CMD_WRITE ;
spiBufTx [1] = reg ;
spiBufTx [2] = data ;
spi.tx_buf = (unsigned long)spiBufTx ;
spi.rx_buf = (unsigned long)spiBufRx ;
spi.len = 3 ;
spi.delay_usecs = spiDelay ;
spi.speed_hz = spiSpeed ;
spi.bits_per_word = spiBPW ;
ioctl (spi_fd, SPI_IOC_MESSAGE(1), &spi) ;
}
/*spi_open
* - Open the given SPI channel and configures it.
* - there are normally two SPI devices on your PI:
* /dev/spidev0.0: activates the CS0 pin during transfer
* /dev/spidev0.1: activates the CS1 pin during transfer
*
*/
int spi_open(char* dev)
{
if((spi_fd = open(dev, O_RDWR)) < 0){
printf("error opening %s\n",dev);
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
unsigned char data = 0xAF;
if(argc <= 1){
argv[1]=spiDevice;
}
// open and configure SPI channel. (/dev/spidev0.0 for example)
if(spi_open(argv[1]) < 0){
printf("spi_open failed\n");
return -1;
}

writeByte (IODIRA, 0x00) ; // Set Port A -> Outputs
/* writeByte (IOCON, 0x08) ; // enable MCP23S17 addresses
/* writeByte (IOCON, 0x12); /* set HW address+ set interrupt pin to ODR
/* set HW address+ set interrupt pin to ODR + mirror int pins */
/* writeByte (IOCON, 0x52); /* 0101 0010 */
writeByte (IOCON, 0x0c) ; /* 0000 1100 - enable HW addresses + ODR */
writeByte (GPIOA, 0xFF) ; /* turn PORT A outputs "on" */
sleep (1); /* */
writeByte (GPIOA, 0x00) ; /* turn outputs "off" */


//writeByte (IPOLB, 0x01) ; // invert lsb
writeByte (GPINTENB, 0xFF) ; /* enable int on change . */
/* writeByte (INTCONB, 0xFF) ; /* int on change comp to defval. */
/* writeByte (DEFVALB, 0xff) ; /* set Default value for interrupt . */
writeByte (IODIRB, 0xFF) ; /* Port B -> Inputs */
writeByte (GPPUB, 0xFF) ; /* enable pullups on Port B */
/*writeByte (GPPUB, 0x00) ; /* disable pullups on Port B */
data = readByte (GPIOB) ; /* */
printf("RECEIVED: %.2X\n",data);
printf ("sleep 1 before read of INTCAPB\n"); /* */
/* sleep (1); /* */
data = readByte (INTCAPB) ;
printf("INTCAPB: %.2X\n",data);
data = readByte (GPIOB) ;
printf("GPIOB: %.2X\n",data);
data = readByte (INTFB) ;
printf("INTFB: %.2X\n",data);
close(spi_fd);
return 0;
}
Richard
Doing Unix since 1985.
The 9-25-2013 image of Wheezy can be found at:
http://downloads.raspberrypi.org/raspbian/images/raspbian-2013-09-27/2013-09-25-wheezy-raspbian.zip

User avatar
Richard-TX
Posts: 1549
Joined: Tue May 28, 2013 3:24 pm
Location: North Texas

Re: MCP23S17 as I/O expander?

Mon Jul 08, 2013 3:17 pm

As FYI, the SPI bus can address sixteen MCP23S17 chips. That means that he number of SPI based I/O ports available is a whopping 256.

The I2C buses can address an additional sixteen MCP23017 chips.

That means that the RPI can have a total of 512 I/O ports based on the mcp23x17.

If that isn't enough then the PCA9685 LED/Servo controller can be used as a output port. With the 6 address pins there can be 64 chips per I2C bus or 1024 output ports per i2c bus. Since there are two buses, a total of 2048 outputs can be realized.
Richard
Doing Unix since 1985.
The 9-25-2013 image of Wheezy can be found at:
http://downloads.raspberrypi.org/raspbian/images/raspbian-2013-09-27/2013-09-25-wheezy-raspbian.zip

MozisII
Posts: 11
Joined: Wed Jan 30, 2013 10:11 pm
Contact: Website

Re: MCP23S17 as I/O expander?

Sun Oct 06, 2013 3:30 pm

Hello,

Does somebody can explain me how to make equivalent procedure of the

Code: Select all

 modprobe gpio-mcp23s08
for the SPI version and then SPI bus.
I can't find the way do attach the driver to the spi bus.
Thanks
selsinork wrote:there are kernel drivers for the spi and i2c versions of these chips under drivers/gpio, you'll have to recompile the kernel to add them though.

I have some of both the i2c and spi versions here and I'll be trying them out sometime soon.

Not looked at how to setup the spi one yet, but for the i2c version you need something like this at runtime:

Code: Select all

modprobe gpio-mcp23s08
echo mcp23017 0x4f > /sys/bus/i2c/devices/i2c-0/new_device
where you replace 0x4f with the i2c address.

It should also be possible to add them as a platform device somewhere in bcm2708.c to have them setup automatically on boot.

wavelet
Posts: 17
Joined: Mon Mar 21, 2016 7:15 pm

Re: MCP23S17 as I/O expander?

Wed Mar 23, 2016 8:10 pm

MozisII wrote:Hello,

Does somebody can explain me how to make equivalent procedure of the

Code: Select all

 modprobe gpio-mcp23s08
for the SPI version and then SPI bus.
I can't find the way do attach the driver to the spi bus.
Thanks
I've finally figured out how to do this for the SPI variants. I'm using Pidora 20 which has kernel 3.12.26-1 so we're in the pre-DeviceTree era. You need to redefine the devices on the SPI bus from SPIDEV to MCP23S17 by patching arch/arm/mach-bcm2708/bcm2708.c in the kernel source tree and re-building the kernel.

Here's a patch file to make the necessary changes to bcm2708.c. The comments in the patch relate to a PiFace-Relay-Plus board which has a single MCP23S17 connected to bus0/cs0 and a IRQ connected to GPIO-25 (which the driver doesn't support):

Code: Select all

diff -ur linux-rpi/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-spi/arch/arm/mach-bcm2708/bcm2708.c
--- linux-rpi/arch/arm/mach-bcm2708/bcm2708.c
+++ linux-rpi-spi/arch/arm/mach-bcm2708/bcm2708.c
@@ -32,6 +32,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/mcp23s08.h>
 #include <linux/w1-gpio.h>
 
 #include <linux/version.h>
@@ -548,6 +549,16 @@
 		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
 };
 
+#ifdef CONFIG_GPIO_MCP23S08
+/* Platform data for MCP23S17 SPI->GPIO bridge on PiFace-Relay-Plus board */
+/* Map the chip's 16 GPIOs to GPIOs 64-79 */
+static struct mcp23s08_platform_data pifaceplus_gpio_info = {
+	.chip[0].is_present = true,
+	.chip[0].pullups = false,
+	.base = 64,
+};
+#endif
+
 #ifdef CONFIG_BCM2708_SPIDEV
 static struct spi_board_info bcm2708_spi_devices[] = {
 #ifdef CONFIG_SPI_SPIDEV
@@ -566,6 +577,21 @@
 	}
 #endif
 };
+#elif defined(CONFIG_GPIO_MCP23S08)
+/* Replace the SPIDEV devices with the MCP23S17 SPI->GPIO bridge
+ * on PiFace-Relay-Plus board */
+static struct spi_board_info bcm2708_spi_devices[] = {
+	{
+		.modalias = "mcp23s17",
+		.platform_data = &pifaceplus_gpio_info,
+		.controller_data = NULL,
+		.max_speed_hz = 500000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.mode = SPI_MODE_0,
+		.irq = -1, /* disable - IRQ connected to GPIO 25 but driver doesn't support irq */
+	}
+};
 #endif
 
 static struct resource bcm2708_bsc0_resources[] = {
@@ -870,7 +896,7 @@
 	system_rev = boardrev;
 	system_serial_low = serial;
 
-#ifdef CONFIG_BCM2708_SPIDEV
+#if defined(CONFIG_BCM2708_SPIDEV) || defined(CONFIG_GPIO_MCP23S08)
 	spi_register_board_info(bcm2708_spi_devices,
 			ARRAY_SIZE(bcm2708_spi_devices));
 #endif
After patching the file, re-build the kernel with the following config changes:

Code: Select all

# CONFIG_BCM2708_SPIDEV is not set
CONFIG_GPIO_MCP23S08=y
After installing your newly built kernel and rebooting, if all has gone well, you should see the new GPIOs as follows:

Code: Select all

ls /sys/class/gpio
export  gpiochip0  gpiochip64  unexport
You can then access the new GPIOs using the standard commands (as root). For example, to make GPIO-64 output logic 1:

Code: Select all

echo 64 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio64/direction
echo 1 > /sys/class/gpio/gpio64/value

ahmedawad
Posts: 42
Joined: Mon Apr 18, 2016 11:44 am
Location: Bremen, DE

Re: MCP23S17 as I/O expander?

Fri Nov 25, 2016 2:28 pm

Hi,
please I am trying to use the mcp23s17 with my RPI-3, but looks like I am doing some thing wrong.
I used the code from "Richard-TX". I have read the data sheet as well for the port expander. Can some one please confirm whether this code works or not, because I always read 00 on my screen.

Thanks in advance

wavelet
Posts: 17
Joined: Mon Mar 21, 2016 7:15 pm

Re: MCP23S17 as I/O expander?

Sun Dec 04, 2016 3:17 pm

For RPI-3 you need to use a DeviceTree overlay rather than the method in this thread. Check out this thread here: viewtopic.php?f=29&t=104638. Basically, you need to edit /boot/config.txt and add a line like

Code: Select all

dtoverlay=mcp23s17:s17-spi0-0-present=1
This is for a single MCP23S17 on SPI0 using CS0 and with its address lines tied to 0.

wavelet

ahmedawad
Posts: 42
Joined: Mon Apr 18, 2016 11:44 am
Location: Bremen, DE

Re: MCP23S17 as I/O expander?

Wed Jan 11, 2017 1:59 pm

Thanks for your reply. I wanted actually to use a totally different pin on the RPI as chip select. The problem was that the MCP23s17 is bugged. If you look on the Errata from microchip, you will find a hardware (Sillicon bug). That was it.

Return to “Automation, sensing and robotics”