Raspberry Pi GPIO’s
There are 40 GPIO’s brought out on a header on all current Pi models (earlier ones had only 26), however most of these GPIO’s are dual purpose and so somewhat less than 40 are available for custom use. To control the GPIO inputs I’ll be using some cheap quadrature rotary encoders – the type that are commonly used for volume controls where you can rotate the dial continuously in either direction. These devices contain 2 (sometimes 3 if you want a push button too) micro switches that for the rotary part are sequenced 90° out of phase –
So not only can you count the number of switch transitions but by detecting which switch is leading you can deduce the direction of rotation.
All good but how can I scale this up to say control lights in my entire house? – I’ve assumed 2 lights per downstairs room and 3 for each bedroom on the basis that you might want to control bedside lighting as well as overhead stuff, I calculate I’ll need 24 switches which would require 72 GPIO’s and possibly more if one includes outdoor lighting etc…
One way to achieve this would be to use these GPIO expanders that sit on the Serial Peripheral Interface (the Pi has 2 of these). SPI on the Pi is implemented as a 4-wire bus-
MISO – Master In Slave Out
MOSI – Master Out Slave In
SCK – Serial Clock
CS/CE – Chip Select/Enable
With the SPIdev kernel module loaded 2 pins of the Pi are used as chip selects, however the MCP23S17 chips can be programmed to use hardware addressing and thus only use 1 CE pin for up to 8 devices – basicaly at device initialisation a command is sent to turn on Hardware Addressing, and since all the devices are on the same CS line then all will be set to that mode and then are addressable via the status of their 3 address lines A0-A2
So this allows expansion of the usable GPIO’s at the cost of one Pi GPIO per chip + the 4 used by the SPI bus. To put this into perspective using only 1 SPI bus we can create 128 GPIO’s at the cost of only 12 on the Pi 🙂
So to use this we need to write some code that registers an interrupt on the Pi and a callback routine to read the appropriate chip registers to see which GPIO triggered the interrupt. The act of reading the chip registers causes the chip to reset the interrupt pin, so the device is then ready to register any further changes.
Sounds good in theory, lets put this into practice by first hooking one of these chips up to a Pi and seeing what we can read/write….
1st pass using 1 MCP23S17 and hooking it up to one rotary encoder, with the rotary switch pins wired to GPA0 and GPA1.
From a bare install of the latest Raspbian image –
If you are trying this from a new Raspbian installation you will also need to do a bit of housekeeping –
In a terminal window – I run my Pi’s headless so log on via SSH using an X-windows terminal, however a terminal session in the gui will work fine-
So we are now ready to test accessing the GPIO chips using the RPiMCP23S17 library which abstracts the configuring of the spi bus and the initialisation of the device and also provides a more friendly way to access the various functions.
By default the library initialises the devices with Hardware Addressing enabled, GPIO’s as inputs and optional internal pull-up’s enabled (100KΩ to VDD), lets see if we can read the 16 pins – they should all be high so would expect both banks to return 1111111111111111….
Read on to see why the results weren’t quite what I expected!