Driving LED matrix with 74HC595 - Page 1
Forum section: electronics / projects

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 07:32:41 am
content: Hi. I stumbled into a ridiculous problem when trying to drive a 8x8 LED matrix with a 74HC595 register. Didn't think that such easy thing could go wrong.In the first version, I used 74HC595 for the anode side, through 330 ohm resistors to the matrix and a TPIC6C595 for the cathodes (Like 595, but different pins arrangement, 100 mA open drain outputs).When there was only one LED lit up on a single cathode line, it was brighter than when there were 8. So, the 74HC595 has too little current capability. This happened also when I shorted the cathode to the ground, eliminating TPIC6C595 from the equation.Therefore, I opted to use PNP transistors for the LED anodes (see schematic below). But it didn't resolve the problem completely. Now the droop is barely visible, but it's still there. It also introduced another problem, weird shadow on the matrix that manifests itself more at higher refresh rates (but still sub-1 MHz). Video:clickHow do I fix this? I don't want to resort to these constant current LED drivers (like MAX6969 / similar from TI) , or LED matrix/display drivers (like MAX7219). They're hard to get, expensive and don't help anyone who wants to recreate my circuit (It will be a Snake game on a 16x16 matrix).

author: Tandy
author_rank: Frequent Contributor
timestamp: October 15, 2014, 09:01:52 am
content: How does your software work? I'm guessing but maybe wrong that when you are scanning a row you are cycling through the outputs of the shift register quickly moving to the next output if the LED does not require illuminating and then introducing a delay on the lines you want to illuminate. The problem with that is that the more LEDs you want lit on the row the longer it will take to refresh that LED.You are effectively creating a PWM supply for the LEDs. To ensure that all LEDs are the same brightness you need to write your control software so that it continually scans each column and row and spends an equal amount of time in each position even if that LED is not to be lit.Simplified exampleIt takes one µS to switch between outputs on the shift register so it would take 8µs to cycle through the 8 outputs. You switch one of the LEDs on for 10µS it then takes 8µS for you to cycle through the outputs until you get back to your LED. So now your LED has been off for 8µS and is now on again for 10µS. It spends more time on than it does off.Now you want to switch a second LED on, so this time you cycle through your outputs delay 10µS for LED 1 and then 10µS for LED 2. Now what happens is LED 1 is now off for an extra 10µS while LED 2 is lit up. So it is now on for 10µS and off for 18µS, the LED spends more time off than it does on. The more LEDs you illuminate the less time each will spend on.Instead what you would need to do is make sure the time spent at each position is the same if the LED is off or on. So you would have a standard delay for every step through the cycle. So for example you would have 10µS of delay on every output so that it takes 88µS to cycle through the outputs every time regardless of the number of LEDs that you turn on.Now that you know your LED will only ever be on for 10µS out of every 88µS it will always spend more time off than it does on even if it is the only LED lit. Now because you know this you can reduce the size of the current limiting resistor as the LED is capable of much higher peak currents than it it can for a continuous current. This will partly compensate for the lost brightness, it still won't be as bright but the brightness will be consistent.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: October 15, 2014, 09:18:01 am
content: I did this years ago,http://seventransistorlabs.com/tmoranwms/Elec_Z80.htmlit's an 8x8 matrix which is only a little smaller, and arguably should be more sensitive to brightness differences (any given segment has a 1/8th difference, not 1/16th).The LEDs are arranged between outputs (LSTTL, no current limiting resistors) and give reasonable brightness. Think I'd still recommend a little resistance with HC CMOS, but definitely not 330 or 160 ohms, more like 47. Be sure that, whatever's driving the common node, it has a nice low resistance (in the TTL case, the strong logic-low drive probably hid that pretty well).The segments are also driven in a very particular order:1. Set row drivers low2. Advance column driver (C0 low, others high --> C1 low, others high; etc.), increment memory address3. Set row drivers to value at memory address4. Wait 256 counts5. RepeatIf you skip step 1, you get noticeable bleed, where a given pattern is lit on the next column for the few cycles before the next pattern is written. Better to waste time with no LEDs lit at all than to save nanoseconds making a crummy display.(The wait was later changed to a 0-255 "on time" count, then clearing the row drivers and waiting the remaining 255-0 counts, for a basic PWM action.)So, I don't know if your circuit matches mine. All you need is a strong driver on the common terminal.Tim

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 09:29:17 am
content: Doh. I weren't clear enough that this brightness drop and ghosting are separate problems.For this prototype, I used Tiva C Launchpad with Energia (Arduino port). I will use AVR with hardware SPI for the final project.I multiplex this in a loop, for each of the 8 lines I write (1 << row) to the TPIC6C595 and the line content to 74HC595 using shiftOut function (They are chained). So at any time, one line is active, for set time and independent of the contents.My colleague assembled the same circuit on a breadboard and subsequently tried to eliminate any single element that could be the cause. He removed the TPIC6C595 (shorting one cathode to ground), 74HC595, and finally substituted the matrix with a row of LEDs. And still there's a slight drop in LED brightness when you turn 8 LEDs on. So the problem lies in transistors. Or is the breadboard really so crappy it can't handle 100 mA or so?Code://Pin connected to ST_CP of 74HC595int latchPin = 8;//Pin connected to SH_CP of 74HC595int clockPin = 10;////Pin connected to DS of 74HC595int dataPin = 9;byte message[] = {0,0,0,0,0,0,0,0,126,128,128,128,126,0,76,146,146,146,100,0,126,128,128,128,126,0,254,4,10,17,254,0,0,0,0,0,254,16,40,68,130,0,124,130,130,130,124,0,254,4,8,16,254,0,2,2,254,2,2,0,124,130,130,130,124};void setup() {//set pins to output so you can control the shift registerpinMode(latchPin, OUTPUT);pinMode(clockPin, OUTPUT);pinMode(dataPin, OUTPUT);}int x;int frame=0;void loop() {frame++;for (int i=0; i<3000; i++) {for (int row=0; row<8; row++){digitalWrite(latchPin, LOW);shiftOut(dataPin, clockPin, MSBFIRST, 1 << row);shiftOut(dataPin, clockPin, MSBFIRST, ~message[(row+frame)%65]);digitalWrite(latchPin, HIGH);//delayMicroseconds(20);}}}

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 09:56:54 am
content: QuotePut 8 resistors on each segment, not 1 resistor for every digit (8 segments).

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 10:05:15 am
content: Quote from: dannyf on October 15, 2014, 09:56:54 amThat is exactly what I did. Every transistor for a segment (pixel in a row) has a separate resistor (160 ohms). See schematic snippet I posted. Right of it there are LED matrix anodes connected.I will post a full schematic later today.

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 10:13:03 am
content: QuoteRather than posting a "schematic snippet", you can post the schematic instead?Help others help you.

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 10:18:57 am
content: Yeah. I see. It is just that it was more of a proof-of-concept to see whether we'll need 1 or 2 layer PCB and how big the board will be. The schematic itself is horrible. It will be quicker for me to draw it by hand.Edit: Here it is, in its current form (I only use one 8x8 matrix, because I have too few wires...)

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 11:05:49 am
content: That circuit work work for common cathode leds.For common anode leds, put the resistors on the anode.Essentially, you want to the resistors on the segments, not on the common connection (cathode or anode): so that when a digit is light up, the resistors decide the current going through each leds (assuming that they sum up less than the sink capabilities of the tpic).

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 11:07:24 am
content: QuoteNot sure what it is for but that's way higher than necessary. 100Hz frames (800Hz per column or row) would be more than enough.

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 01:35:18 pm
content: Quote from: dannyf on October 15, 2014, 11:05:49 amWell, that confused the hell out of me when I was buying my LED matrices at the shop's site. How a LED matrix can be "common cathode" or "common anode"? (A single-color one, RG/RGB are a different story). Both anodes and cathodes are shared. Now, for the actual driving method, then yes. You drive 8 anodes/cathodes and 1 cathode/anode is "common" ie. multiplexed.Said dimming effect occurs whether I use the TPIC or not (just connecting LED cathode to ground).But I see that I could easily circumvent TPIC's current limit by flipping this circuit and connecting its outputs through resistors, then multiplexing one BC557 at a time. My friend who also does this circuit by himself tried that and said the image was garbage. Got to verify by myself.

author: RicoElectrico
author_rank: Contributor
timestamp: October 15, 2014, 02:56:35 pm
content: Quote from: dannyf on October 15, 2014, 11:07:24 amOops. Should have told this is pixel (well, pixel + column, because they are chained) clock.

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 03:00:57 pm
content: Each led runs about 20ma so 8 of them go for 160ma -> does that approach / exceed the limit of your TPIC? If it does, a better way might be to switch from the low-side -> HC595's can output 20ma per pin but use a transistor to sink 160ma per row/column.I would also take a look at the code to make sure that it turns off other rows / columns.

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 03:02:58 pm
content: QuoteI assume you could output all 8 bits on a row / column and then on individual column / row. Thus the 100Hz x 8 calculation.But even if you were to drive individual pixel, it is only 100Hz x 8 x 8 = 6Khz. Far less than 1Mhz.

author: macboy
author_rank: Super Contributor
timestamp: October 15, 2014, 03:18:41 pm
content: Quote from: dannyf on October 15, 2014, 03:02:58 pmMeasure voltage between a) the Vcc directly at the PNP transistor emitter, and b) the ground pin of the TPIC6C595.Do this for both cases: only that one LED on, and all eight LEDs on. If there is a difference in this voltage for those two cases, then that explains the difference in brightness. You will then need to look at reducing the V=IR voltage drops in your wiring (the breadboard doesn't help) and/or improve voltage regulation.

author: dannyf
author_rank: Super Contributor
timestamp: October 15, 2014, 03:24:27 pm
content: Code:shiftOut(dataPin, clockPin, MSBFIRST, 1 << row);I think I found the problem. That line turns on all rows other than the "row". You need to transmit its complement instead.

author: macboy
author_rank: Super Contributor
timestamp: October 15, 2014, 05:15:22 pm
content: Quote from: dannyf on October 15, 2014, 03:24:27 pmThe TPIC6C595 inverts the output due to its open-drain outputs (a '1' bit turns on the corresponding output FET, pulling output low). So that line of code should work as expected.

author: Corporate666
author_rank: Unknown
timestamp: October 15, 2014, 09:42:20 pm
content: I didn't read through the code, but are you "scanning" from top to bottom or from left to right, as shown in your hand-drawn schematic?If left to right, then I think you are overloading your lower shift register, aren't you? The ones I have used are spec'd to 100mA per pin, but if all of your LED's are on, then you are at 160mA (if they are 20mA per LED).If you are scanning left to right, then you have only one current limiting resistor regardless of how many LED's are on - in this case it will be brighter with one LED than with 8.I would put the resistors on the cathodes and I would scan left to right... you shouldn't need current limiting on the high side if you are using a constant current shift register on the low side. But if you are not using a CC shift register, put the resistors on the low side so that you will have one resistor for one LED, then scan left to right.It doesn't really matter whether you scan left to right or top to bottom, but you will always have a full row (or column) on at one time, and then the individual 'pixels' of that row or column will be controlled by a series of grounds (like through the shift register). Put the resistors on that series of grounds, not on the single supply for the whole string.

author: RicoElectrico
author_rank: Contributor
timestamp: October 26, 2014, 11:16:43 pm
content: Sorry for not responding for awhile...It turned out to be the breadboard resistance! 10 ohms for both supply sides... It's obvious that breadboards are not ideal, but I didn't expect it to be so much... Especially as mine is supposed to be nickel-plated phosphor bronze. And you know, this is stuff they put in relays...As per our driving scheme, is there something inherently wrong with it? Currently, we swapped TPIC6C595 for a HC595 + ULN2803. At one moment, 1 cathode is switched to ground and there may be 0 to 8 (or 16 in the final version) active anodes, each with itsownresistor. Driving multiple leds through 1 resistor was never a thing in our design.As we have means of ordering free 2-sided PTH PCBs, my friend designed a board and we will see what it will be like.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 26, 2014, 11:43:36 pm
content: You can actually get away with using a 595 with no resistors for a column drive - the chip's internal output resistance limits current.Many Chinese monochrome matrix signage modules do this, using a 4:1 multiplex.I've also used it to drive a small 16x64 array of 0402 white LEDs - works a treat!For the row drive, P-channel MOSFETS from a HC138, or another HC595

author: RicoElectrico
author_rank: Contributor
timestamp: October 26, 2014, 11:55:07 pm
content: Quote from: mikeselectricstuff on October 26, 2014, 11:43:36 pmWith no brightness drop depending on the number of LEDs turned on?If I were to drive within datasheet limits of HC595, the picture will not be bright and readable in the sunlight, considering 1:16 mux.So maybe my matrix, FYM-15881BUG-11 is crappy and inefficient?datasheetAll the LED matrix driver schematics that you can find in the Web use simply resistors for HC595 output.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 26, 2014, 11:58:59 pm
content: Quote from: RicoElectrico on October 26, 2014, 11:55:07 pmYes you do get a little brightness variation but not enough to be too noticeable. It's particularly good for white LEDs, which have high efficiency, but if you want to max out the LEDs & use in sunlight, use proper CC drivers.One benefit is very low current draw when not driving and near-zero current when static - most CC drivers have a few mA quiescent. Handy for small battery-powered displays.

author: dannyf
author_rank: Super Contributor
timestamp: October 27, 2014, 12:51:15 am
content: QuoteDepending on the setup.I would use one hc595 + resistors to current on one side (say columns), and then one hc595 + npn transistors to sink current on another side (row), and scan the rows.With this set up, hc595's current limitations are no concern as each hc595's output is driving just one led, and the current sink side is handled by the npn transistors for all leds on a given row.All you need to do is to make sure that only one col / row of the matrix is lit.

author: Rudolfo
author_rank: Contributor
timestamp: October 27, 2014, 09:54:24 pm
content: There is a 32 bit serial IO-port for the SPI which can drive LED matrix with up to 25mA push/pull outputs. It#s the iC-DY6818 -http://www.ichaus.de/wp8_whitepaper_en.

author: TonyStewart
author_rank: Contributor
timestamp: October 27, 2014, 11:01:07 pm
content: STPIC6C595 has Low RDS(on): 4 ? typThis looks pretty low but taking Anode values 160? With 8 in parallel =20 drops intensity 5/25=20% is not great but for this unit... OkActually ESR of LED is ~15 Ohms so load ratio on H595 is ..,Min 4+15+160=2V/If <={5V-Vf@1mA}/Ifthus If=2V/179=11mA with 88mA when all On.The ghosting is charge current from last pixel and needs pullup R's to eliminate or lower capacitance per pixel.