LED Cube with expander PCF8574AN

Hi, I hope it's right forum.
I'm working on building 4x4x4 LED Cube. So far, I managed to build cube which works great when I connect 16 anodes (pins 0-13 and A0,A1) and 4 cathodes (pins A2-A5) to my Arduino UNO board.
But I would like to add to this some buttons for switching between 'patterns'.

I bought expander PCF8574AN where I would like to connect those 4 cathodes (I can't use both I2C and Analog A4,A5 right?). I connected addresses pins to ground (pins 1,2,3) and also Vss (pin 8) to GND on Arduino.
On pins 9-12 I connected my cables from cathodes. I left INT pin empty and connected 14 to SCL and 15 to SDA on Arduino board (above AREF pin).

I think I messed up something with my code or I am missing something but I can't figure out what is it :confused:

Here is my code for cube which doesn't work:

#include <avr/pgmspace.h>
#include <PCF8574.h>
#include <Wire.h>

PCF8574 expander;

//#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 20 // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units
// TODO this could be a lot more compact but not with binary pattern representation
const char PatternTable[] PROGMEM = {
// blink on and off

B0001,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
//and so on...
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
** Note that analog inputs 0-5 are also digital outputs 14-19!
** Pin DigitalOut0 (serial RX) and AnalogIn5 are left open for future apps
*/

int LEDPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int PlanePin[] = {4, 5, 6, 7};

// initialization
void setup()
{
  Wire.begin();
  Serial.begin(57600);
  Serial.println("PCF8575 ok");
 
  int pin; // loop counter
  // set up LED pins as output (active HIGH)
  for (pin=0; pin<PLANESIZE; pin++) {
  pinMode( LEDPin[pin], OUTPUT );
  }

  expander.begin(0x38);
  // set up plane pins as outputs (active LOW)
  for (pin=0; pin<CUBESIZE; pin++) {
  expander.pinMode( PlanePin[pin], OUTPUT );
  expander.pullUp( PlanePin[pin] );
  }
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop()
{
  // declare variables
  byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
  int PatternIdx;
  byte DisplayTime; // time*100ms to display pattern
  unsigned long EndTime;
  int plane; // loop counter for cube refresh
  int patbufidx; // indexes which byte from pattern buffer
  int ledrow; // counts LEDs in refresh loop
  int ledcol; // counts LEDs in refresh loop
  int ledpin; // counts LEDs in refresh loop
  
  // Initialize PatternIdx to beginning of pattern table
  PatternIdx = 0;
  // loop over entries in pattern table - while DisplayTime>0
  do {
  // read pattern from PROGMEM and save in array
  memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
  PatternIdx += PLANESIZE;
  // read DisplayTime from PROGMEM and increment index
  DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
  // compute EndTime from current time (ms) and DisplayTime
  EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;
  
  // loop while DisplayTime>0 and current time < EndTime
  while ( millis() < EndTime ) {
  patbufidx = 0; // reset index counter to beginning of buffer
  // loop over planes
  for (plane=0; plane<CUBESIZE; plane++) {
  // turn previous plane off
  if (plane==0) {
  expander.digitalWrite( PlanePin[CUBESIZE-1], LOW );
  } else {
  expander.digitalWrite( PlanePin[plane-1], LOW );
  }
  
  // load current plane pattern data into ports
  ledpin = 0;
  for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
  for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
  digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
  }
  patbufidx++;
  }
  
  // turn current plane on
  expander.digitalWrite( PlanePin[plane], HIGH );
  // delay PLANETIME us
  delayMicroseconds( PLANETIME );
  } // for plane
  } // while <EndTime
  } while (DisplayTime > 0); // read patterns until time=0 which signals end
}

I changed digitalWrite of PlanePin to LOW from HIGH and to HIGH from LOW becouse I read that expander gives more currency on LOW state. But still no luck.

I would be thankful for any advice on this issue :slight_smile:
Thanks in advance!
Rafał

The pins on the expander, like the pins on the Arduino, can neither source nor sink enough current for 16 leds. You need transistors.

Paul

PS. You mean "gives current". If you have found a pin that gives currency, please PM me and don't tell anyone else!

The PCF8574 can sink a maximum of 25 mA per pin and a maximum of 100 mA at any single time. The pins cannot supply more than 100 μA!

So it's not suitable as a LED-driver.

For LED-cubes, look at the TLC5940. I have built one that uses the TLC5940 and P-channel MOSFET for each layer.

// Per.

Thank guys for your responses. Sorry for no hearing from me for few days but I was busy finishing this project. I finally figured out what was going on.
The issue was stupid... I bought new prototype board and I was focused on finding problem with expander but there was something wrong with this board -.-
Now, when I changed it, everything work fine.

Topic for close :wink:

For a 43 cube, you use a MAX7219.