Google Ad

Donate to IanJohnston.com using PayPal here, or pledge a donation via Patreon here.
I like creating electronics related YouTube videos. I mostly buy faulty gear from Ebay and make a repair video of it, but it's expensive and so with your help maybe I can continue to do so. Your support would be greatly appreciated.


Project #016 - Arduino I2C 32ch Digital I/O Extender Board

This is my first Arduino shield. The "IanJ I2C 32ch Digital I/O Extender Board".

Specifications/Info:-
- 32 digital I/O channels, each configurable as input or output.
- Configured as inputs, you can assume internal pull up resistors on each channel.
- I2C addresses configurable via DIP switches.
- +5vdc supply from Arduino main board (see note 1).
- Interrupt line available to tie back to main Arduino

Note 1:-
Each output is capable of 25mA sink, however, with 32 possible outputs this is 800mA (0.8A)
and so an external 5vdc supply must be used.
See the board I/O diagram below (coming soon) for info on selecting this mode.
With a relatively low current consumption expectation, such as when using a lot of inputs, you can use the Arduino +5vdc supply to power the board.

References:
For more information on usage of the interrupt line, how to independently assign each pin as input or output, driving high current loads, or learn about the I2C commands, refer to:
http://www.nxp.com/documents/data_sheet/PCA8574_PCA8574A.pdf
http://www.arduino.cc/en/Reference/Wire

Here's a partial 3D rendered interpretation of the board (missing the pushbutton & the screw terminals).

And here's a photo of the 1st prototype, minus the switches:-

Demo sketch:-

There are many ways to pass data via I2C and to manipulate bits/bytes of data. This sketch offers a minimal demo (showing how easy it is!) on how to control the board.

{codecitation}

/*

  Demo program for "IanJ I2C 32ch Digital I/O Extender Board"
  V1.0 - By Ian Johnston, Feb 2010.

  The Pcb has 4off IC's, designated U1, U2, U3 & U4.
  In this demo sketch:-
  U1 = All 8 channels set for digital output
  U2 = All 8 channels set for digital input
  U3 = All 8 channels set for digital output
  U4 = All 8 channels set for digital input

*/

#include <Wire.h>  // The I2C library

// Setup I2C addresses for the 4off IC's. These are 7-bit addresses.
// 4off bits internal to IC, last 3 bits via switches on pcb, i.e. 0100 [A1] [A2] [A3]
// Note: An 8th bit sets direction, however Wire.h takes care of this automatically.
byte U1_ADDR = 33; // B0100001 = Pcb Switch setting = 001
byte U2_ADDR = 34; // B0100010 = Pcb Switch setting = 010
byte U3_ADDR = 35; // B0100011 = Pcb Switch setting = 011
byte U4_ADDR = 36; // B0100100 = Pcb Switch setting = 100

// Setup variables
byte I2C_dataTx;   // Data to outputs IC's
byte I2C_dataRx;   // Data from input IC's
int I2C_TxAddr;    // IC Address holder for output
int I2C_RxAddr;    // IC Address holder for input
int i=0;           // Demo variable only
int delaytime=100; // Demo variable only


void setup() {

  Wire.begin();

}


void loop() {

  // DIGITAL OUTPUT - A few examples on how to drive outputs

      // Demo turn all outputs on in one go, on U1
      I2C_dataTx = B11111111; // Make up byte to be sent from binary data of port P7,P6,P5,P4,P3,P2,P1,P0
      I2C_TxAddr = U1_ADDR; // Set 7-bit I2C address to send to
      I2C_Send(); // Run subroutine and send data to I2C bus
      delay(delaytime);

      // Demo turn all outputs off in one go, on U1
      I2C_dataTx = B00000000; // Make up byte to be sent from binary data of port P7,P6,P5,P4,P3,P2,P1,P0
      I2C_TxAddr = U1_ADDR; // Set I2C address to send to
      I2C_Send(); // Run subroutine and send data to I2C bus
      delay(delaytime);
           
      // Demo rotate round all 8off bits on U1 turning them on one by one
      I2C_TxAddr = U1_ADDR; // Set I2C address to send to
      for(i = 0; i < 7; i++) {
         bitSet(I2C_dataTx, i);
         I2C_Send(); // Run subroutine and send data to I2C bus
         delay(delaytime);
      }
     
      // Demo rotate round all 8off bits on U1 turning them off one by one
      I2C_TxAddr = U1_ADDR; // Set I2C address to send to
      for(i = 0; i < 7; i++) {
         bitClear(I2C_dataTx, i);
         I2C_Send(); // Run subroutine and send data to I2C bus
         delay(delaytime);
      }
 

  // DIGITAL INPUT - A few examples on how to read inputs

      //  Demo receive data from U2
      I2C_RxAddr = U2_ADDR; // set I2C address
      I2C_Receive(); // Run subroutine and receive data from I2C bus, data appears in var I2C_dataRx

      // Now do something with one of the bits, let's speed up the whole main loop a bit. Note: inputs are normally high so test for 0
      if (bitRead(I2C_dataRx, 0) == 0) { // Check bit 0
         delaytime=50;
      }

      // And one of the other bits, let's speed up the whole main loop a lot
      if (bitRead(I2C_dataRx, 1) == 0) { // Check bit 1
         delaytime=25;
      }
     
      // And one of the other bits, reset the speed back to default
      if (bitRead(I2C_dataRx, 2) == 0) { // Check bit 2
         delaytime=100;
      }

}


void I2C_Send() {
  // I2C send routine
  Wire.beginTransmission(I2C_TxAddr); // setup I2C address to send to
  Wire.send(I2C_dataTx);              // send byte to that address
  Wire.endTransmission();             // end send
}


void I2C_Receive() {
  // I2C receive routine
  Wire.requestFrom(I2C_RxAddr, 1);    // request 1 byte from I2C address
  if (Wire.available()) I2C_dataRx = Wire.receive();
}

{/codecitation}