I've built a dual color 8x8 LED matrix with three 74HC595 shift registers and one ULN2801 transistor array for the common ground shift register. In general it's working fine, but there's a little bit of echoing in the previous rows when I light up an LED.
For example, if I light up the LED on row 1, column 2, the LED on row 0 column 2 is very dimly lit. If I light up the LED on row 0 column 3, the LED on row 7 column 3 is dimly lit. The LEDs are well isolated so no light flows from one to another, so this must be a programming issue I guess, since the technique is based on persistence of vision.
Here's the code (I'm using the Serial to receive raw bytes for controlling the matrix):
#include <SPI.h>
const int latchPin = 10;
const int numChips = 3;
byte outBytes[numChips] = { 0 };
enum matrixTags {common, green, red };
byte greenBinMatrix[8][8] = { 0 };
int stepRowIndex = 0;
int stepColIndex = 0;
int trigRowIndex = 0;
int trigColIndex = 0;
int allRowsIndex = 0;
int wholeRow = 0;
byte wholeRowVal = 0;
int channel = 0;
int displayStep = 0;
int displayTrigSteps = 0;
void setOutput(){
digitalWrite(latchPin, LOW);
for(int i = numChips - 1; i >= 0; i--)
SPI.transfer(outBytes[i]);
digitalWrite(latchPin, HIGH);
}
void setup() {
SPI.begin();
Serial.begin(115200);
pinMode(latchPin, OUTPUT);
// add a delay so that no accidental pulses arrive in the serial port
// when the Teensy that controls the breadboarduino boots up
delay(2000);
}
void loop() {
while (Serial.available()) {
byte inByte = Serial.read();
static int temp;
if (inByte < 128) {
temp = inByte;
}
else {
switch (inByte) {
case 128:
channel = temp;
temp = 0;
break;
case 129:
// these are for the triggering steps (green LEDs)
trigColIndex = temp % 8;
trigRowIndex = temp / 8;
temp = 0;
break;
case 130:
bitWrite(greenBinMatrix[channel][trigRowIndex], trigColIndex, temp);
temp = 0;
break;
case 131:
// these are for the step indicator (red LEDs)
stepColIndex = temp % 8;
stepRowIndex = temp / 8;
temp = 0;
break;
case 132:
displayStep = temp;
temp = 0;
break;
case 133:
// 133 means clear the current channel
for (int i = 0; i < 8; i++) {
greenBinMatrix[channel][i] = 0;
}
break;
case 134:
// 134 means clear all channels
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
greenBinMatrix[i][j] = 0;
}
}
break;
case 135:
// 135 and 136 is for setting a column on all rows
allRowsIndex = temp;
temp = 0;
case 136:
for (int i = 0; i < 8; i++) {
bitWrite(greenBinMatrix[channel][i], allRowsIndex, temp);
}
temp = 0;
break;
case 137:
wholeRow = temp;
temp = 0;
break;
case 138:
wholeRowVal = temp;
greenBinMatrix[channel][wholeRow] = wholeRowVal;
temp = 0;
break;
case 139:
displayTrigSteps = temp;
temp = 0;
break;
case 140:
for (int i = 0; i < 8; i++) greenBinMatrix[channel][i] = 0;
}
}
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 3; j++) {
outBytes[j] = 0;
}
bitSet(outBytes[common], i);
if (displayStep) {
if (i == stepRowIndex) {
bitSet(outBytes[red], stepColIndex);
}
}
if (displayTrigSteps) outBytes[green] = greenBinMatrix[channel][i];
else outBytes[green] = 0;
setOutput();
// add a short delay to avoid having the previous channel dimly lit
// this should probably go higher if the dimly lit issue persists, but 3ms don't seem to work properly
delay(2);
}
}
Any help greatly appreciated.