To make it easier to understand what's going on, I created a simple library for the Centipede Shield. It could also be used as-is to control any MCP23017 chip. Right now it makes the Centipede I/O work like the normal Arduino I/O. More specialized functions are not implemented yet.
Download zipped library here
Example code using the Centipede library:
// Example code for Centipede Library
// Works with Centipede Shield or MCP23017 on Arduino I2C port
#include <Wire.h>
#include <Centipede.h>
/* Available commands
.digitalWrite([0...63], [LOW...HIGH]) - Acts like normal digitalWrite
.digitalRead([0...63]) - Acts like normal digitalRead
.pinMode([0...63], [INPUT...OUTPUT]) - Acts like normal pinMode
.portWrite([0...3], [0...65535]) - Writes 16-bit value to one port (device)
.portRead([0...3]) - Reads 16-bit value from one port (device)
.portMode([0...3], [0...65535]) - Write I/O mask to one port (device)
.init() - Sets all register to initial values
Examples
CS.init();
CS.pinMode(0,OUTPUT);
CS.digitalWrite(0, HIGH);
int recpin = CS.digitalRead(0);
CS.portMode(0, 0b0111111001111110);
CS.portWrite(0, 0b1000000110000001);
int recport = CS.portRead(0);
*/
Centipede CS; // create Centipede object
void setup()
{
Wire.begin(); // start I2C
CS.initialize(); // set all register to default
CS.portMode(0, 0b0000000000000000); // set all pins on port 0 to output
}
void loop()
{
CS.digitalWrite(0, HIGH); // write A0 high
CS.digitalWrite(15, LOW); // write B7 low
delay(150);
CS.digitalWrite(0, LOW); // write A0 low
CS.digitalWrite(15, HIGH); // write B7 high
delay(150);
}
Centipede.h:
// Centipede Shield Library
// Controls MCP23017 16-bit digital I/O chips
#ifndef Centipede_h
#define Centipede_h
#include "WProgram.h"
extern uint8_t CSDataArray[2];
class Centipede
{
public:
Centipede();
void pinMode(int pin, int mode);
void digitalWrite(int pin, int level);
int digitalRead(int pin);
void portMode(int port, int value);
void portWrite(int port, int value);
int portRead(int port);
void initialize();
private:
void WriteRegisters(int port, int startregister, int quantity);
void ReadRegisters(int port, int startregister, int quantity);
void WriteRegisterPin(int port, int regpin, int subregister, int level);
};
#endif
Centipede.cpp:
// Centipede Shield Library
// Controls MCP23017 16-bit digital I/O chips
#include "WProgram.h"
#include "Centipede.h"
#include <Wire.h>
uint8_t CSDataArray[2] = {0};
#define CSAddress 0b0100000
Centipede::Centipede()
{
// no constructor tasks yet
}
// Set device to default values
void Centipede::initialize()
{
for (int j = 0; j < 4; j++) {
CSDataArray[0] = 255;
CSDataArray[1] = 255;
WriteRegisters(0, 0x00, 2);
CSDataArray[0] = 0;
CSDataArray[1] = 0;
for (int k = 2; k < 0x15; k+=2) {
WriteRegisters(j, k, 2);
}
}
}
void Centipede::WriteRegisters(int port, int startregister, int quantity) {
Wire.beginTransmission(CSAddress + port);
Wire.send(startregister);
for (int i = 0; i < quantity; i++) {
Wire.send(CSDataArray[i]);
}
Wire.endTransmission();
}
void Centipede::ReadRegisters(int port, int startregister, int quantity) {
Wire.beginTransmission(CSAddress + port);
Wire.send(startregister);
Wire.endTransmission();
Wire.requestFrom(CSAddress + port, quantity);
for (int i = 0; i < quantity; i++) {
CSDataArray[i] = Wire.receive();
}
}
void Centipede::WriteRegisterPin(int port, int regpin, int subregister, int level) {
ReadRegisters(port, subregister, 1);
if (level == 0) {
CSDataArray[0] &= ~(1 << regpin);
}
else {
CSDataArray[0] |= (1 << regpin);
}
WriteRegisters(port, subregister, 1);
}
void Centipede::pinMode(int pin, int mode) {
int port = pin >> 4;
int subregister = (pin & 8) >> 3;
int regpin = pin - ((port << 1) + subregister)*8;
WriteRegisterPin(port, regpin, subregister, mode ^ 1);
}
void Centipede::digitalWrite(int pin, int level) {
int port = pin >> 4;
int subregister = (pin & 8) >> 3;
int regpin = pin - ((port << 1) + subregister)*8;
WriteRegisterPin(port, regpin, 0x12 + subregister, level);
}
int Centipede::digitalRead(int pin) {
int port = pin >> 4;
int subregister = (pin & 8) >> 3;
ReadRegisters(port, 0x12 + subregister, 1);
int returnval = (CSDataArray[0] >> (pin - ((port << 1) + subregister)*8)) & 1;
return returnval;
}
void Centipede::portMode(int port, int value) {
CSDataArray[0] = value;
CSDataArray[1] = value>>8;
WriteRegisters(port, 0x00, 2);
}
void Centipede::portWrite(int port, int value) {
CSDataArray[0] = value;
CSDataArray[1] = value>>8;
WriteRegisters(port, 0x12, 2);
}
int Centipede::portRead(int port) {
ReadRegisters(port, 0x12, 2);
int receivedval = CSDataArray[0];
receivedval |= CSDataArray[1] << 8;
return receivedval;
}