Dimming Leds with ULN2803

Thread Starter

MCrowe

Joined May 29, 2011
69
Hey there,
Wondered if any one could shed some light on a quite annoying problem I can seem to solve.

Im using a ULN2803 to drive 8 LED's. One per pin...
And I have it all working so I can choose which Leds are on and which are off using a PIC16f877a.

The problem I am having is a need to Dim the whole bank of LED's. Because the ULN2803 is a low side drive I figured I would just use a brushed motor ESC (electronic speed controller) to change the voltage on the high side of the entire bank. Unfortunately this doesn't work, and I have spent days trying to figure out why, and how to fix it.

When I reduce the voltage from the ESC, instead of dimming the LED's that are currently lit and meant to be lit. It starts to brighten the non-lit LED's. And if I turn it all the way down the non-lit LED's come on and increas in brightness until they are the same brightness as the meant to be lit LED's. Make sense?

Does any one know why this is and how I could fix it? Is it possible to do something like this with the ULN2803? Maybe its just using the ESC that the problem. Any help / pointers would be greatly appreciated. Thanks.
 

MrChips

Joined Oct 2, 2009
30,712
It is difficult to control the brightness of an LED by varying the source voltage. You would be better to use a PWM output using the PIC.
 

ErnieM

Joined Apr 24, 2011
8,377
What MrC said. If they all dim together you could put a PWM switch on the common. If they all have different intensities you need to PWM each control line.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Yeah but what do you PWM. Lol. Ok. I cant just have them running straigh form a Pic pin as the current will be too high. And even if its not in this case, I want to be able to use higher power LEDs and stuff later. Sooo, I cant run them straight from a pin. So what do I use? Just a Transistor of some sort? Im not big on transistors. As in I dont really know how to choose and use them. I've always gone for nice little packaged parts that say put 12v in this pin, put 5v control in this pin and conects your motors and LED's to these pins.

And ErnieM, yeah I do just want to dim all the LED's together. Or, more correctly, I want to dim all the LED's that are on. I want the ones that are off to STAY OFF. But they dont want to. The one that are off brighten instead of the ones that are on Dimming. Ahh/
 

ErnieM

Joined Apr 24, 2011
8,377
Im using a ULN2803 to drive 8 LED's. One per pin...
And I have it all working so I can choose which Leds are on and which are off using a PIC16f877a.
As you describe it you have each LED controlled off a PIC I/O pin. least hardware method is to PWM all the ON pins to make the intensity change, but that takes a bit of tricky software; worth it for a production unit but mayhaps not for something one-off.

If you post your schematic I could make a suggestion for one common point to PWM everything off one I/O pin (which should be the PWM module output if your chip has one).
 

MrChips

Joined Oct 2, 2009
30,712
Drive 8 LEDs from a single 8-bit port. Use a variable to store the 8-bit value before sending out to the port. Now modulate the 8-bit value using a delay routine to send out a PWM signal on all activated bits.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Ok, you asked for it.
Attached is my schematic / circuit diagram draw in paint shop.

As you can see the Micro controller is controlling which LEDs are ON or OFF. I also want to be able to DIM the entire bank of leds. Now obviously I only want the LEDs that are turned on to change. (dim). But when I set it up using a RC ESC (speed controller), instead of dimming the LED that were turned on, it started brightening the LEDs that were meant to be turned OFF.!!

I still haven't sorted this problem out, so any help would be appreciated. Even just a suggestion for the best lead to follow.

I was thinking I of using PWM to control brightness but what do I use to 'buffer' / drive the LEDs? As in, I dont want to drive them straight from the micro because I will eventually end up drawing too much current.

Thanks all. Hope the circuit diagram makes it clearer as to what I want to do.
 

Attachments

ErnieM

Joined Apr 24, 2011
8,377
The ULN2804 is fine for a buffer to control each LED. The place you marked "possible control line" is the correct place to insert a PNP (E to 12V, C to LEDs, B thru a resistor to PIC) (E to B resistor too), but you'll need another NPN to turn on it's base as you're in 12 land up there. 3 resistors and 2 transistors additional.

MrChips idea is probably better to turn the PIC pins on and off to PWM. If you need help there try looking for some "software PWM" code to start from, but eventually instead of turning on and off a single pin you'll be doing the whole port.

Ring back if you need more hints.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Mmm, Some interesting ideas. I can imaging PWM on the whole port would be slightly difficult although it does seem to be the most sensible approach. I already have an entire port running 8 individual 50hz PWM for controlling servos and such. (although im only using 4 of them. But is 50 hz fast enough for LED control? That and I cant see an easy way to integrate it with the other control system that selects which LED's are on. I guess I could maybe take the subroutine that selects which LED's are on and AND that with the PWM pulse routine...

Ok, Ill follow that line of attack for now and see where it gets me. Thanks heaps for all your help guys. I only started playing with PICs 3 months ago when I joined up here, and with all the help you guys have given me I think I've got sub-routines for almost ever function the 16f877a offers. Built in PWM, Interrupt driven PWM, ADC, Serial com, buttons, lights and motors going everywhere, and almost a complete working robot. Cheers.
 

MrChips

Joined Oct 2, 2009
30,712
Here is the first solution that comes to mind.
Create a 1ms time-base, i.e. a timer interrupt that occurs every 1ms (doesn't have to be exact, any period of that order will do.)

Assume the PORT output to the LED driver is active-HI, if not you can reverse the logic sent to the PORT.

Start off with a software counter = 0

In the timer interrupt routine,
Increment the counter at every interrupt.
If the counter exceeds a predetermined value, say 10 for example, send ZEROS to the port.
If the counter exceeds a limit value, say 25 for example, reset the counter to zero,
and send the LED_value to the PORT.

The ratio of the first number to the second number will determine the brightness.
To go from dim to bright just alter the first number.
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
50Hz is just fine, persistence of vision kicks in at under 30Hz.

That's true as long as the LEDs stay put! I don't know if I am hypersensitive but I can see auto LED lights a mile off since when my eyes pass over them I pick up the flashes.

I'm actually entering production with a blinkie LED product to replace a regular light bulb (it dims with the same intensity). I'm driving that at 200Hz and I can't see the blinking.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Still having a lot of trouble with this. The main problem being I already have so many things running on the PIC its getting confusing. Think I need to try building this part seperately and then integrating it into the main program.

I tried the idea MrChips suggested but had some issues. Looking at it again, if i set up a 1ms time base, and turn turn the light off on on using a count of 25. Thats 25ms... Isn't that way too slow? Any way, there are obviously other issues in my program because the best I can come up with at the moment is a strobe light. The interrupt running in my program is actually use most of the proccess time I think as even when I put the code into the Main program it still ran too slow. So I need to set up a whole new timer interrupt. Im just worried that the interrupts are going to interrupt each other.. Does that happen?

Considering I alread have a 50hz PWM running on 8 pins and am only using 4 of them. Could I maybe run all the LED control lines (8 in total) into seperate AND gates, with the other lead of each AND gate being the dimming control line.? It would take an extra Pin on the micro but would probably be much easier to do and save on processor run time.
 

ErnieM

Joined Apr 24, 2011
8,377
Using an AND gate works, you would need 2x quad NAND gate ICs.

You could also gate the supply voltage to the LEDs like so:



Both transistors are either full off or on saturated so they shouldn't dissipate much power.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Ahhhhh, Definately going insane.. I've tried everything, (I can think of) to get this PWM thing working with interrupts. I tried adding the PWM routine into my existing 50hz generator routine. That doesn't work because for some reason it messes up the 50hz routine. It still runs, but my servos jitter even though the pulse is still 50hz.

I tried running a seperate interrupt routine, basically on a lower priority than my 50hz routine. So if the 50hz is in the middle of executing it disables the Led PWM. I kind of got that to work although I had to slow the LED pwm down with pre-scale otherwise it still interfered for some reason. Despite the fact they were completely independant, weren't passing any values into the subroutines in W or Status, and the LED PWM was a resonably small interrupt routine. BUT, although I could get ALMOST all the the jitters out of the servos, every now and then all my LED would flash. Instead of just the ones that were meant to be on. And the Micro wasn't resetting incase you think that could be the cause. I have a check in for that. And the subroutine that tells the LEDs what position to turn on is in a single instruction. MOVWF. So it can't be interrupting in an odd place and giving the wrong value.

AND, despite all that, even if I could get it all working together, the camera the light are on for, picks up the PWM pulses. Lol. Nothing works proper. No matter what I changed the PWM pulse to, the camera picks it up and you end up with either fast or slow pulses of light at full brightness...

So, next option?? Any one? I think I need to varie the voltage, or current to the LEDs positive side. What would be the simplest way to do this? If its something that works at 50hz that would make it much easier. Do motor drivers vary the voltage when you PWM them? or just pass on the PWM? Seriously im so stuck on what seemed like the simplest part of my project. Any suggestions would be greatly appreciated. Cheers.
 
So, next option?? Any one? I think I need to varie the voltage, or current to the LEDs positive side. What would be the simplest way to do this? If its something that works at 50hz that would make it much easier. Do motor drivers vary the voltage when you PWM them? or just pass on the PWM? Seriously im so stuck on what seemed like the simplest part of my project. Any suggestions would be greatly appreciated. Cheers.
The standard PWM (CCPX) pins are being used for something else? And why isn't one controlling the common high side, by a pfet (mentioned much earlier), for a global brightness?
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Maybe i got carried away with PWMing the entire 8 bits. Kind of forgot about the PWM (CCP2) pin that im not using. But I did sort of have plans for not using it as I was planning on using them to drive motors for a different but quite similiar project.
I might look into that. Mainly it because I never really learnt that much about transistors. I don't know what ones to use, how to connect them correctly and what to connect with them. I love playing with digital logic, (especially things packed in ICs that say pin 1 in, pin 4 out, no external component required). But my lack of understand is definately making my life difficult at the moment.

For the moment I may have found a solution. I'm using the 50hz (from a spare pin for servo driving) and running that into an AND gate along with one of the 8 bit leds controllers. It seems to work alright, except that I can't get to 100% duty cycle as the servo driver is set up to never need to go that high. (And cant be changed). I can lower the resistor value so i still achieve full brightness but Im given to understand thats not normally the most sensibly solution. The servo driver works by taking the 50hz, and divinding it my however many servos you have connectedg.

So if I had all 8 servos connected, the max duty cycles I could get would be 12.5%?? for the LEDs. In reality, slightly less. Which is perfect for servos as you never go over about 8%.


As for the resources im using for the servo driver.. Most of the processing power I think. Im really only using Timer 1 / CCP1 in special event trigger mode, and all 8bits of any port but there doesn't seem to be much spare processing time left. I am only running 4mhz. Mmm, on second thoughts that shouldn't be doing too much damage. Im also recieveing serial data the wrong way. Polling, instead of using the interrupts. But that still shouldn't have made it so difficult to instigate another interrupt.

What would cause two seperate interrupts to interact with each other?
 

MMcLaren

Joined Feb 14, 2010
861
Have you considering using an 8-bit serial-to-parallel sinking driver IC like a (TI) TPIC6C595 or a (Micrel) MIC5821, instead of the ULN2803 sinking driver? These serial-to-parallel ICs have three inputs; <data>, <clock>, and <latch>, though different manufacturers may use slightly different names for those inputs.

Feeding these drivers is a matter setting the <data> pin to a '0' or a '1', then pulsing the <clock> pin high and low, and repeating the process to clock all eight data bits into the driver IC shift register. After sending eight data bits to the driver IC you pulse the <latch> pin high and low to copy the data in the driver shift register onto the driver output pins. A simple driver might look something like this;

Rich (BB code):
;
;  update the MIC5821 driver with the 8 bit data in WREG
;
update
        movwf   work            ; save data
        movlw   8               ;
        movwf   bitctr          ; bitctr = 8
loop
        rlf     work,F          ; put bit 7 into Carry
        bcf     clk             ; <clk> = 0
        bcf     dat             ; <dat> = 0
        skpnc                   ; C = 0? yes, skip, else
        bsf     dat             ; <dat> = 1
        bsf     clk             ; pulse the <clk> pin
        bcf     clk             ;
        decfsz  bitctr,F        ; all 8 bits sent?
        goto    loop            ; no, branch, else
        bsf     lat             ; pulse the <lat> pin to
        bcf     lat             ; copy data onto outputs
        return                  ;
The reason I'm telling you about these serial-to-parallel sinking driver ICs is that they have an /OE (active low output enable) pin. If you drive this pin from the PWM output on the PIC you can get complete fade-to-black PWM brightness control with the PWM module running as a "no overhead" background task (won't interfere with your servo driver). Your main program simply changes the value in the CCPR1L "duty cycle" register to change the brightness level.

These driver ICs also free up valuable I/O pins. For example, please check out the multiplexed display drawing below.

Food for thought. Regards, Mike
 

Attachments

Last edited:

MMcLaren

Joined Feb 14, 2010
861
Just noticed Ernie's two transistor solution in post #14 and I think that's the best/simplest way to go since, again, you can setup the PWM module to run in the background with "no overhead" and no effect to your servo driver.
 
Top