Hi All,
I have an Arduino Pro Mini 5V driving 4 series 74HC595 which in turn drives a 12 x 12 common cathode LED matrix using the SPI interface. I am wasting 4 bits of 2 shift registers but at the moment I don't have a 16 x 16 matrix. The last 12 bits of the last 16 bits are column selectors and drive BC337 transistors through 4k7 resistors to the base. The common cathodes of each column connect to the collectors of each of these transistors. The rows are driven from the last 12 of the first 16 bits. Current limiting resistors are 470R. I have based the design on the information which can be found here: Gammon Forum : Electronics : Microprocessors : Using a 74HC595 output shift register as a port-expander. (thanks Nick - yet another great post)
The clock rate of the SPI interface is maxed out at SPI_CLOCK_DIV2 however it turns out this does not affect my problem. Any clock rate same effect.
The circuit is bypassed reasonably well with the use of 4x1uF electros + 4x 0u1F ceramics as close as possible to being across the 74HC959 power pins as is achievable on a breadboard. I hate breadboards as they are as noisy as you can get. I don't think this is a noise problem though. They don't go away. I accept this circuit is running fast and the power will be bouncing about but why should it cure itself?
The code I am running simply cycles a lit up column left to right at 100mS intervals. On startup the display cycles as expected BUT there are a few flickery LEDS in a couple of columns ( column 4 and 5 actually which are driven from the last bit of the third 74C595 in the chain and the first bit of the fourth 74HC595 in the chain) which should be solidly out except for when the column is on. The flickery LEDS seem to be in rows 4 and 5 (need to verify this) which would also correspond to the boundary of the first and second 74HC595 - maybe there is a theme here.
After about 30 seconds of operation the circuit goes rock solid and the problem goes away until the next start up. The circuit has to be off for at least 5 minutes or so before the problem re-exhibits. Power off and immediately on all works well.
Nothing here is working hard. The Arduino is running from a 1 Amp power supply hard connected to its 5 volt input. It can't be heat surely??? Problems usually get worse with heat anyway. In any case nothing feels hot. Over sensitive transistors in a couple of the columns?? Not satisfactory really.
I hate things that go bump in the night. Any ideas why the circuit misbehaves in the first 30 seconds?
Here is code, please excuse the quantity of commented out sections.
#include <TimerOne.h>
#include <SPI.h>
byte column_counter;
byte r1[12], r2[12];
int test_row;
const byte LATCH = 9;
void setup ()
{
pinMode(LATCH,OUTPUT);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setBitOrder(LSBFIRST);
Timer1.initialize(100);
Timer1.attachInterrupt(transfer_data,100);
test_row = 0;
column_counter = 0;
for ( int i = 0; i <= 11; i++)
{
r1[i] = r2[i] = 0; // bottom row = row 0
}
// alternating patter not used
/*
r1[0] = 0x5; r2[0] = 0x55; // bottom row = row 0
r1[1] = 0xa; r2[1] = 0xaa; // row 1
r1[2] = 0x5; r2[2] = 0x55; // row 2
r1[3] = 0xa; r2[3] = 0xaa; // row 3
r1[4] = 0x5; r2[4] = 0x55; // row 4
r1[5] = 0xa; r2[5] = 0xaa; // row 5
r1[6] = 0x5; r2[6] = 0x55; // row 6
r1[7] = 0xa; r2[7] = 0xaa; // row 7
r1[8] = 0x5; r2[8] = 0x55; // row 8
r1[9] = 0xa; r2[9] = 0xaa; // row 9
r1[10] = 0x5; r2[10] = 0x55; // row 10
r1[11] = 0xa; r2[11] = 0xaa; // row 11 top row
*/
} // end of setup
void transfer_data()
{
byte c1,c2;
switch (column_counter)
{
case 0:
c1 = 0x8; c2 = 0x00;
break;
case 1:
c1 = 0x4; c2 = 0x00;
break;
case 2:
c1 = 0x2; c2 = 0x00;
break;
case 3:
c1 = 0x1; c2 = 0x00;
break;
case 4:
c1 = 0x0; c2 = 0x80;
break;
case 5:
c1 = 0x0; c2 = 0x40;
break;
case 6:
c1 = 0x0; c2 = 0x20;
break;
case 7:
c1 = 0x0; c2 = 0x10;
break;
case 8:
c1 = 0x0; c2 = 0x08;
break;
case 9:
c1 = 0x0; c2 = 0x04;
break;
case 10:
c1 = 0x0; c2 = 0x02;
break;
case 11:
c1 = 0x0; c2 = 0x01;
break;
}
// this reduces inter LED interference probably due to slow transistors switching off
digitalWrite (LATCH, LOW);
SPI.transfer (0);
SPI.transfer (0);
SPI.transfer (0);
SPI.transfer (0);
digitalWrite (LATCH, HIGH);
// the actual write
digitalWrite (LATCH, LOW);
SPI.transfer (c2);
SPI.transfer (c1);
SPI.transfer (r2[column_counter]);
SPI.transfer (r1[column_counter]);
digitalWrite (LATCH, HIGH);
column_counter++;
if (column_counter > 11)
column_counter = 0;
}
void loop ()
{
for ( int i = 0; i <= 11; i++)
{
r1[i] = r2[i] = 0; // bottom row = row 0
}
r1[test_row] = 0xf;
r2[test_row] = 0xff;
test_row++;
if (test_row > 11)
test_row = 0;
delay(100);