led fading

Hello everyone!

i just tried to analogWrite an led for fading using a for loop. i get to experience something really unuua there.
when i put down the code like this-

for(i=0;i<1023;i++)
{
analogWrite(led,i);
}

for(i=1023;i>0;i--)
{
analogWrite(led,i);
}

the led reaches full brightness at i=512 and as soon as 513 is read, led starts from 0 again for the next half.
i would really feel thankful for being rectified!

thanks

From the reference:

Syntax

analogWrite(pin, value)

Parameters

pin: the pin to write to.

value: the duty cycle: between 0 (always off) and 255 (always on).

That is assuming that you are using a pwm pin?

Try a software pwm on a digital pin

As dannable says, the range is from 0 - 255.
But I noticed your script did not have any delays in it. With no delays, I think you would not be able to see any level shifting. You probably just did not include that part of the code?

255 levels for the LED should be more than most humans could detect. A computer may be able to detect more levels tho.

If you need 0-1023 you can try this:
Instead of analogWrite use Timer1.pwm as seen below.

#include <TimerOne.h>

void setup() 
{
  pinMode(9, OUTPUT);   
  pinMode(10, OUTPUT);   
  Timer1.initialize(1000);
  Timer1.pwm(9, 512);   //50%
  Timer1.pwm(10, 255); //25%
}
 
void loop()
{
}

.

[quote author=jack wp link=msg=2317525 date=1436979020]
255 levels for the LED should be more than most humans could detect.[/quote]

Not true! Have you even tried it?

Ok, you can't tell the difference between 254 and 255. But the difference between 0 and 1, or 1 and 2 is very obvious.

Paul

Maybe if you are concerned about the low end, put a 200 ohm resistor in series, and a 2mf cap across the LED.

Maybe add a diode if we can't use open collector.

You misunderstand the matter. It has nothing to do with the PWM frequency being visible.

The eye is sensitive to proportional changes in intensity. It may not perceive a 5% change, but the difference between 6 and 5 is 20% and easily observed. If you want to display colours at low intensity, you need to provide a second-level PWM which "kicks in" at about 50 (out of 255) and counts finer fractions.

Which we cannot.

You misunderstand the matter. It has nothing to do with the PWM frequency being visible.

I think the PWM frequency does not change. Seems like it stays about 500khz.

It is the ratio of high to low. If you have a resistor and cap on the line. The low to high ratio will be buffered by the RC network, reducing the LED at narrower pulses (the cap absorbing most of the amps). Do I misunderstand this?

Which arduino are you using?

If you have the Due, it can send DAC at 4095 resolution, rather than just 255.

I think the PWM frequency does not change. Seems like it stays about 500khz.

kHz ?

Thanks Larry for correcting my capitalization. But a bit off topic maybe.
Larry, did you get time to try the RC network to fix the low level concerns ?

500Khz should be:
~500hz (490hz)

did you get time to try the RC network to fix the low level concerns ?

Not sure which thread you are referring?

Yes Larry, you are right, 490Hz to 980Hz depending on which arduino you are using. Thanks for the correction.

Sorry, the RC question should have gone to PaulRB.

Fading an LED on an Arduino if done at a first step into programming can be a rewarding experience as it provides immediate visual feedback.

However, if looked at it closer in many other posts folks have been dissatisfied with exactly that visual feedback mostly for two reasons:

  • Visible "steps" at lower intensities.
  • LED fades to relatively brightness fast say from 0-80 and then from 80-255 there is not much happening.

Both of these effects can be attributed to the fact that the response of the human eye to changes in luminance is non linear and roughly follows a logarithmic curve. Simply the human eye is more sensitive to changes in brightness at lower light levels.

Certainly some things can be done using discrete electronics - whether a simple RC element is going to work is tested easily enough - but an option that provides more control is to use PWM with 10 or 12 bits of resolution.
There are ways to increase PWM resolution although only for a single pin on most 8-bit, non ARM Arduino's such as the UNO or Leonardo. It's been posted on this forum a good number of times. The due as already mentioned in another post provides hither PWM resolution. My favorite Arduino compatible Teensy 3.x and Teensy LC boards provide up to 16 bit resolution with easily configurable PWM frequency.

But even when using a higher PWM resolution the fading effect can still be dissatisfactory if the non-linearity is not properly taken care of. On micro controllers this is done mostly with a look-up table that contains the linearized PWM values.

That lookup table need only have 256 entries but the PWM values the table is populated with can be 10 or 12 PWM values.

One solution is to use a mapping between the value that represents the brightness and the value that you apply to the PWM. You don't need a lookup table if you can work out the math required to calculate the mapping. A quadratic function seems to work quite well for me, so I use a function to set the brightness and wrap the mapping inside that - I also take the opportunity to deal with LEDs that contain multiple units that may be common anode or common cathode:

const boolean commonCathode = false;

...

void setBrightness(int led, int val) {
 // linear mapping function val -> brightness:
 // int brightness = val;
 // quadratic mapping function val -> brightness:
 int brightness = (val * val / 255.0);

 if (commonCathode) {
   analogWrite(led, brightness);
 } else {
   analogWrite(led, 255 - brightness);
 }
}

void loop() {

...

// set the brightness of the red LED:
setBrightness(ledR, valR);

...

}

I've tried other functions like cos:

brightness = 255 * (1 - cos(val / 162.34))

but the quadratic is simple and is a sufficient improvement over the linear for a fader program that I don't see much point in looking for greater complexity.

Looks like the OP has no more questions. So, we are just talking among ourselves now. So, in that context, I still think a hardware fix would be good. RC with a diode to simulate open collector.
That would smooth the low levels out a good bit, but not hurt the higher levels much.

Since the OP is no longer around, maybe we should ease up on this thread.