Calculating LED Voltage/Brightness and PWM

Started by soggybag, August 19, 2010, 02:00:45 AM

Previous topic - Next topic

soggybag

I'm using an AVR to set the brightness of an LED/LDR. The AVR is putting out a PWM which I'm assuming is in the range of 0 to 5V. The AVR is running on 5V.

I want to calculate a resistor that will get a full range of brightness from my LED. What should I look for in the data sheet?

As a related question. I'm guessing that I can think of the PWM as a voltage for this purpose. The pulse width has a range of 0 to 255, which, I'm guessing, translates as 0 to 5V. Since it takes about 1.6V to get the LED to conduct, only the range from 1.6V to 5V is useful, anything below 1.6V and the LED is off.

What would be a good approach. Program the AVR to output a PWM range with a minimum value of 1.6V, or wire an offset voltage to the LED? Or maybe use a transistor buffer?

composition4

Nah...

5V PWM only has two voltages involved - zero and five volts.  Hence the forward voltage of LED can be ignored whilst driving it.  The LED is either ON or OFF - just too fast for your eye to see.  So you're using an average current to drive the LED.

0 to 255 doesn't really translate to 0 - 5v... well, I guess it depends what you are measuring it with.  All the LED (or a motor, etc) cares about is the average current (set by the PWM and the current limiting resistor) that it receives.  So if you set the PWM pin to 5% of 255, the LED will see 5% of the current that your limiting resistor allows.  Just size the current limiting resistor as normal for full brightness (20ma for a lot of 5mm LEDs) and it will be fine.

And yes, I would use a transistor to drive the LED.  Again, same deal - the transistor will always be fully on or fully off, so you don't need to do anything special in your calculations for the base resistor.

Hope that makes sense? Let me know if it doesn't, I'm pretty jetlagged so probably not explaining things very well

Jonathan

soggybag

Thanks for the reply. I'm guessing I can use an emitter follower to drive my LED.

.Mike

#3
Quote from: soggybag on August 19, 2010, 10:25:15 AM
Thanks for the reply. I'm guessing I can use an emitter follower to drive my LED.

I was still very green when I put together my VCLFO Tremolo, so I had an EE friend of mine draw a simple transistor driver on a napkin for me. Taylor used it in his Tap Tempo Tremolo with great results.

My main concern was exceeding the PIC's 20mA max PWM current output when running an LED and a photocell off the same output. Check either of those schematics for a working example. :)

Mike
If you're not doing it for yourself, it's not DIY. ;)

My effects site: Just one more build... | My website: America's Debate.

soggybag

Thanks Mike. I took a look at your tremolo, looks very cool. The transistor driver looks very straight forward.

composition4

#5
Oh and one other thing to keep in mind about your design is that an LED's output brightness is very non linear.  For example, at half-current it appears much more than half-bright.  You can compensate for that in your code.  If you want to let me know how your LED is controlled (is it fading in/out? or is it just set to various brightnesses every now and then? or something else?) then I'm happy to try to figure out some code to make the LED respond in a linear way.

Jonathan

soggybag

Thanks for the offer Jonathan. I'm trying to make a Sample and Hold type effect. I have been using the Colorsound Wah. With an LDR for the wah resistance. Using the AVR to generate a random control voltage. Everything is working, it's just not working as well as it could be.

I'm getting a good random PWM out. But I'm not getting a good range of control. I'm having a hard time wrapping my head around PWM driving the LED and LED controlling the LDR to get a range of control for the effect. The wah would normally use a 100K pot to ground. I had been using VTL5C9. I was thinking to go through all of the LDRs in my parts bin and test them all. I might find one with a more suitable range.

As an alternative to using the LDR I thought a JFET or BPT might also work. I chose the LDR because it's easier to understand conceptually.

The timing mechanism is fairly crude. I have been using a counter and a loop to delay between changes in the PWM value, using a pot to control the count value. This is my next problem to tackle. As it is this works, but the control doesn't feel linear. I'm sure there's a better way to approach this. I have been reading up on interrupts...

The chip I'm using is the ATTiny13. It's an 8 Pin DIP. Which makes it easy to fit in a lot of projects. I figured I didn't need a lot of features, just one output and one input. I could probably wire up another out and another input using the same chip, which would probably be more than enough features for what I have in mind.

Here's the code I've been using. The last two lines of the main loop generate a random int from 0 to 255 and set this as the PWM out to pin 5.
/*
* Sample and Hold Demo. Flashes an LED at a random brightness at a rate set by a pot
* LED anode connected to pin 5, cathode to ground through a 470 ohm resistor
* B10K Pot center lug to pin 3, outer lugs to +5v and ground
* LED PB0 connected to pin 5
* Pot AD2 (PB4) connected to pin 3
*
*/

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

#define LED PB0 // Define led ext output pin on PB0 pin 5

int main( void ) {
int i;      // 8 bits integer - should be set in main?
uint8_t brightness = 0x00; // Holds the random value applied to OCR0A

// ******************************************************************
// *** Set up PWM ***
TCCR0A |= (1<<COM0A1) | (1<<WGM00); // PWM Phase correct mode 1
TCCR0B |= (1<<CS00);// --no prescale
TCNT0  = 0x00; // Timer/Counter Register
OCR0A  = 0x12; // Output Compare Register A

DDRB   |= (1<<PORTB0); // Set PB0 (Pin 5) as output
// ******************************************************************

    // *******************************************************************
    // *** Set up ADC ***
    DDRB   |= ( 1 << LED );           // Set output direction on LED
    ADCSRA |= ( 1 << ADEN  ) |        // Analog-Digital enable bit
( 1 << ADPS1 ) |          // set prescaler to 8 ( clock / 8 )
( 1 << ADPS0 );           // set prescaler to 8 ( clock / 8 )

    ADMUX |=  ( 1 << ADLAR ) |        // AD result store in ( more significant bit in ADCH )
( 1 << MUX1  );           // Choose AD input AD2 ( PB4 ) pin 3
    // *******************************************************************

    while ( 1 ) { // Main program

    ADCSRA |= ( 1 << ADEN );          // Analog-Digital enable bit
    ADCSRA |= ( 1 << ADSC );          // Discard first conversion

        while ( ADCSRA & ( 1 << ADSC ) ); // wait until conversion is done

    ADCSRA |= ( 1 << ADSC );          // start single conversion

        while ( ADCSRA & ( 1 << ADSC ) )  // wait until conversion is done

    ADCSRA &= ~( 1 << ADEN );         // shut down the ADC

//----------Set rate of blinking based on ADCH byte---------
for ( i = 0 ; i < ADCH ; i++ ) { // Loop x time until i reach ADCH value
    _delay_ms( 10 );                   // Loop delay
}
brightness = (uint8_t) rand(); // Need a random number from 0 - 255
OCR0A = brightness;
}
return 0;
}

jonfoote

hey, would a digital resistor help straighten things up?

soggybag

Maybe, I'm not familiar with these. Can you give me some part numbers or point me to a data sheet or a tutorial would be great.

PRR

I doubt an MOS CPU really delivers 5V at 20mA load. But pretend it did.   

Set PWM for 100%. Pick 20mA max LED current. (5V-1.6V)/0.020A= 170 ohms. This is not critical, use 220 ohm. 15.4mA.

Now we have 15mA at 100%PWM and the LED is very bright.

Program PWM for one cycle per second. Change PWM duty to 50%. The LED will be 15mA for 0.5 seconds, 0mA for 0.5 seconds. To the eye, it "blinks". To a slow camera with a many-second exposure, it is half as bright as an LED at 15mA 100%.

Change the PWM rate to many times a second (over 50, preferably over 100; less than a MHz; the default is probably fine). Now your eye will average-out 50% 15mA 50% 0mA to "about 7.5mA".

Very small very bright lights confuse the eye. On a dark floor, 15mA just dazzles the eye, exact brightness doesn't register well. 7.5mA average probably won't look like "half bright". No big deal. Experiment 1%-100% and make notes. I suspect that, unless it is midnight in the coal mine, 1% or 0.15mA average, is really darn dim and perhaps not useful. 5% 10% 25% 50% 100% may be the useful steps. You can try to plot a function for the CPU to compute, or just a value-list. If user wants more than 10%, give them 25%. Maybe 8 10 12 15 18 22 26%... steps look smoother.
  • SUPPORTER

ElectricDruid

Just a note to say that driving an LED with PWM helps sort out the non-linear response a good deal. Although it's true that an LED doesn't respond linearly if you plot driving current vs light output, that isn't really a consideration here, since you're only using two points on the graph - fully off and fully on.
As someone said previously, the *apparent* dimming is caused by your eye/brain averaging out the amount of light you see over a short period, say 10mS. So the nonlinearity you need to worry about is your eye/brain combination, not the LED!
That said, the technique described above will compensate for your brain just as well as it'll compensate for the LED - just remember what it is that you're compensating for! In truth, I never bother. PWM is such an improvement over trying to drive an LED from a voltage-output LFO that I can live with any remaining irregularities - that's just "character"!

T.

MoltenVoltage

Quote from: PRR on August 29, 2010, 08:43:46 PM
I doubt an MOS CPU really delivers 5V at 20mA load.   

I've found that although the datasheet will say something like "5mA max. current", you can't actually expect 5mA from a given uC pin when driving an LED.  If you measure the current with a 1000 ohm series resistor, you won't see 5mA or anything close to it.  By trial and error I usually end up with around 100 ohms to get about 4mA current if I'm driving an LED directly off a pin.
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

slotbot

Quote from: MoltenVoltage on November 01, 2010, 11:02:57 AM
Quote from: PRR on August 29, 2010, 08:43:46 PM
I doubt an MOS CPU really delivers 5V at 20mA load.   

I've found that although the datasheet will say something like "5mA max. current", you can't actually expect 5mA from a given uC pin when driving an LED.  If you measure the current with a 1000 ohm series resistor, you won't see 5mA or anything close to it.  By trial and error I usually end up with around 100 ohms to get about 4mA current if I'm driving an LED directly off a pin.

Yes its more likely a 5v mcu will output only maybe 4.2 volts or so. This spec is usually listed as Voh min (VOltage Output High Min, the lowest voltage it will output for a logic high). One way to assist this is to run ACTIVE LOW leds so the anode of the LED is connected to VCC (true 5 volts) and the cathode to a resistor then MCU. USUALLY Mcus LOW is closer to 0V then its HIGH is to VCC. So you can use this technique to get greater voltage drop. In this case the LED is on when the pin is LOW. And now you dont have to worry about how much current the mcu can source (but how much it  can sink ;).

Quote from: ElectricDruid on November 01, 2010, 08:00:03 AMAlthough it's true that an LED doesn't respond linearly if you plot driving current vs light output

I think this is a misconception. Led output in (in lumens or whatever have you) is linear to current (once the forward voltage is overcome)  however the receptors in your eyes do not respond linearly to light intensity. Different colors will seem brighter at the same intensity too IIRC green will look the brightest ~500 nm. Its similar too hearing where we have to increase volume logarithmically to PERCEIVE a linear increase.