using the MCP23008 gpio expander with chip Pro and perl

I’ve mentioned the next thing co.  chip family of single board computers before.  It was billed as the world’s first $9 computer.  I first heard of it on NPR one morning and couldn’t get to a computer to pre-order one fast enough.  A full-blown debian distribution, wifi, i2c, SPI, 8-gpio pins, composite video, UART, USB and more about the size of a credit card.  It seemed too good to be true.  I guess it was, because they did not last long.  I bought 15 of them, but never received the last five before they tanked.  They also came out with the chip Pro,  an even smaller, somewhat stripped down version of the chip aimed at being a platform for mass-produced products for $16.  I really liked the optional ufl wifi antenna port.  With an external high-gain antenna, it is really great at sniffing wifi networks.   It is totally awesome, and I wish I had 100 of them.

chip pro
chip Pro

Sadly, I burned up all my gpio pins on a project.  I didn’t want to scrap my chip pro, however, and decided to use the MCP23008 gpio I/O expander to get my gpio back up and working.

I wrote my own easy to use perl based driver to interface with the MCP23008.  There are some great tools on CPAN that implement I2C for stuff like this, but I went an even simpler route.  My driver (at a mere 40 lines of code)  uses system calls (via backticks)  to read and write to registers on the gpio expander.  For example, to read the gpio register, the script will just make a system call like so:


sudo i2cget -y 1 0X20 0x09

This tells the chip Pro to talk to the i2c device on bus 1, at address 0x20, and read the value in register 0x09 (gpio register).   Here is the driver in it’s entirety:

#!/usr/bin/perl -w
use strict;

=pod
utilities for MCP23008 gpio extender
execute any scripts that use this as sudo
=cut

#global variables
my $address;
my $gpio_w = 0;

sub gpio_enable{
	#function takes the i2c address of the MCP23008
	#it also  sets the IO direction
	#register.  Must be a value from 0-255
	#1 is input, 0 is output

	$address = $_[0];
	my $ioreg_val = $_[1];

	#write io reg
	`i2cset -y 1 $address 0x00 $ioreg_val`;
}#end gpio_enable

sub gpio_read{
	#function uses i2cget to
	#read gpio register 0x09
	my $reading = `i2cget -y 1 $address 0x09`;
	return $reading;
}#end gpio_read

sub gpio_write{
	#takes int from 0-255 to write to the
	#gpio register
	$gpio_w = $_[0];
	`i2cset -y 1 $address 0x09 $gpio_w`;
}#end gpio_write

1;

So simple, I’m embarrassed, but it works great.  To test, I wrote a simple script that visually counts to 255 in binary with LED output.

perl mcp23008 driver
i2c mcp23008 binary counter with chip Pro and perl

Here is the script:

#!/usr/bin/perl
use strict;
use Time::HiRes qw(usleep);
require 'gpio_MCP23008.pl';

#init the 23008 IO register as output
gpio_enable(0x20, 0);

for(my $i=0;$i<256;$i++){
usleep(50000);
gpio_write($i);
}#end for

sleep(5);
gpio_write(0);

 

Leave a Reply

Your email address will not be published. Required fields are marked *