Skip to main content
2 of 3
added 120 characters in body

Here is my code for using a single 595 to drive the columns, and hooking up the rows to the Arduino pins themselves. Here I demonstrate a clear delay in each row update, as well as another delay before the image changes. I hope this clears up your confusion, and I apologize for not have a 2 595 setup handy (though I have 2 595s so if this doesn't help you, I'd be more than happy to set it up...), but it should be easy to adapt for a second 595. This supports a variable amount of width and height.

// Pin connected to ST_CP of 74HC595
const int latchPin = 8;
// Pin connected to SH_CP of 74HC595
const int clockPin = 12;
// Pin connected to DS of 74HC595
const int dataPin = 11;
// The pin of the first row of your display
const int row1Pin = 2; // WARNING: All future rows are assumed to be row1Pin + n
// The amount of rows your display has
const int HEIGHT = 3;
// The amount of columns your display has
const int WIDTH = 2;
// The reset pin of 74HC595 (not required as it isn't used, but this pin is pulled low)
const int resetPin = 9;
// Variable used to keep track of currently lit up row
int currentRow = 0;
// Array of rows
int rows[] = {0b11,
              0b01,
              0b11};
unsigned long lastChange = 0;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(resetPin, OUTPUT);
  digitalWrite(resetPin, LOW);
}

/* I don't think this works, but it might with a much higher delay.
void reset() {
  pinMode(resetPin, INPUT);
  delayMicroseconds(1);
  pinMode(resetPin, OUTPUT);
  digitalWrite(resetPin, LOW);
}
*/

// enableRow changes the currently enabled row for future calls, it also changes
// the pinMode on the previous row to "INPUT", disabling all lights on that row.
void enableRow(int row) {
  if (currentRow != 0) {
    pinMode(currentRow, INPUT);
  }
  currentRow = row;
}

// This is a quick function to test one single LED or row on your dotmatrix display (I should have documented this one better but pass an incremeneting number to it and you'll see what it does...).
void lightOne(int pos) {
  enableRow(row1Pin + int(pos / (WIDTH+1)));
  shiftOut(dataPin, clockPin, MSBFIRST, 1 + pos % (WIDTH+1));
}

// This function draws the display stored in "rows".
void displayRows() {
  for (int i = 0; i < HEIGHT; i++) {
    digitalWrite(latchPin, LOW);
    enableRow(row1Pin+i);
    // shift out the bits:
    shiftOut(dataPin, clockPin, MSBFIRST, rows[HEIGHT-i-1]);
    digitalWrite(latchPin, HIGH);
    pinMode(currentRow, OUTPUT);   // set the current row's pin as OUTPUT
    digitalWrite(currentRow, LOW); // output LOW on currentRow to complete light's circuit and display
    delay(3); // time in ms to hold each row lit
  }
}

void loop() {
  displayRows();
  if (lastChange+1000 /* 1000ms between changes */ < millis()) {
    for (int i = 0; i < HEIGHT; i++) {
      rows[i] = random(4);
    }
    lastChange = millis();
  }
}