Brute-Force PWM:
This code is split up into two distinct parts. The function pwmAllPins() takes care of implementing PWM. The remaining code in the event loop increases and decreases a brightness variable. Calling pwmAllPins() with the increasing and decreasing brightness makes the LEDs pulse in and out. In pwmAllPins(), we have a loop over i, which takes exactly 256 steps each time. Inside the i loop, we compare a variable brightness to i and turn on the LEDs if i is smaller. This has the effect of turning on the LEDs at the beginning of each set
of 256 and then turning them off as soon as i reaches the value brightness, so for higher values of brightness the LEDs stay on for a greater percentage of the 256 steps.
Now, you can modify the per-step delay time and figure out where you just start to notice the flickering.You’ll soon find your personal flicker-fusion rate. Notice when you move your head that you’ll see the persistence-of-vision trailer effects as well. When you’re playing around with the delay, remember that you’re taking 256 steps per cycle, so if you delay 20 microseconds per step, that’s 5,120 microseconds, or
5.12 milliseconds per cycle. Because there are 1,000 milliseconds in a second, this gives a PWM frequency of 1,000 / 5.12, or around around 195 Hz. The main() portion of the code sets up a direction variable (as a signed integer) that lets us add to or subtract from the current brightness. Finally, when the brightness
hits either limit, direction reverses sign. The result is a brighter-and-dimmer pulsing fade. When you’re playing with the LED demo, you may also notice that the human eye doesn’t respond to equal changes in brightness equally. In our simple fade, it looks like the LEDs go through the dark portion of their fade-in and fade-out faster than the light part, even though we know that the duty cycle is changing by +/– 1 delay
period each step through the for loop. The human eye is much better at telling the difference between low levels of light than higher ones. That is, the human eye’s response to light is nonlinear. Many LEDs
are driven in PWM mode to exploit this fact—if you notice LED traffic lights flickering when you turn your head past them suddenly, that’s PWM. The reason that PWM-driven LEDs are so prevalent is that your eyes can’t really tell the difference between 90% and 100% duty cycles, so the city can run the traffic lights at 90% and pocket the 10% energy savings.
CODE:
/* Quick and dirty PWM Demo */
// ------- Preamble -------- //
#include <avr/io.h> /* Defines pins, ports, etc */
#include <util/delay.h> /* Functions to waste time */
#include "pinDefines.h"
#define LED_DELAY 20 /* microseconds */
void pwmAllPins(uint8_t brightness) {
uint8_t i;
LED_PORT = 0xff; /* turn on */
for (i = 0; i < 255; i++) {
if (i >= brightness) { /* once it's been on long enough */
LED_PORT = 0; /* turn off */
}
_delay_us(LED_DELAY);
}
}
int main(void) {
uint8_t brightness = 0;
int8_t direction = 1;
// -------- Inits --------- //
// Init all LEDs
LED_DDR = 0xff;
// ------ Event loop ------ //
while (1) {
// Brighten and dim
if (brightness == 0) {
direction = 1;
}
if (brightness == 255) {
direction = -1;
}
brightness += direction;
pwmAllPins(brightness);
} /* End event loop */
return (0); /* This line is never reached */
}
This code is split up into two distinct parts. The function pwmAllPins() takes care of implementing PWM. The remaining code in the event loop increases and decreases a brightness variable. Calling pwmAllPins() with the increasing and decreasing brightness makes the LEDs pulse in and out. In pwmAllPins(), we have a loop over i, which takes exactly 256 steps each time. Inside the i loop, we compare a variable brightness to i and turn on the LEDs if i is smaller. This has the effect of turning on the LEDs at the beginning of each set
of 256 and then turning them off as soon as i reaches the value brightness, so for higher values of brightness the LEDs stay on for a greater percentage of the 256 steps.
Now, you can modify the per-step delay time and figure out where you just start to notice the flickering.You’ll soon find your personal flicker-fusion rate. Notice when you move your head that you’ll see the persistence-of-vision trailer effects as well. When you’re playing around with the delay, remember that you’re taking 256 steps per cycle, so if you delay 20 microseconds per step, that’s 5,120 microseconds, or
5.12 milliseconds per cycle. Because there are 1,000 milliseconds in a second, this gives a PWM frequency of 1,000 / 5.12, or around around 195 Hz. The main() portion of the code sets up a direction variable (as a signed integer) that lets us add to or subtract from the current brightness. Finally, when the brightness
hits either limit, direction reverses sign. The result is a brighter-and-dimmer pulsing fade. When you’re playing with the LED demo, you may also notice that the human eye doesn’t respond to equal changes in brightness equally. In our simple fade, it looks like the LEDs go through the dark portion of their fade-in and fade-out faster than the light part, even though we know that the duty cycle is changing by +/– 1 delay
period each step through the for loop. The human eye is much better at telling the difference between low levels of light than higher ones. That is, the human eye’s response to light is nonlinear. Many LEDs
are driven in PWM mode to exploit this fact—if you notice LED traffic lights flickering when you turn your head past them suddenly, that’s PWM. The reason that PWM-driven LEDs are so prevalent is that your eyes can’t really tell the difference between 90% and 100% duty cycles, so the city can run the traffic lights at 90% and pocket the 10% energy savings.
CODE:
/* Quick and dirty PWM Demo */
// ------- Preamble -------- //
#include <avr/io.h> /* Defines pins, ports, etc */
#include <util/delay.h> /* Functions to waste time */
#include "pinDefines.h"
#define LED_DELAY 20 /* microseconds */
void pwmAllPins(uint8_t brightness) {
uint8_t i;
LED_PORT = 0xff; /* turn on */
for (i = 0; i < 255; i++) {
if (i >= brightness) { /* once it's been on long enough */
LED_PORT = 0; /* turn off */
}
_delay_us(LED_DELAY);
}
}
int main(void) {
uint8_t brightness = 0;
int8_t direction = 1;
// -------- Inits --------- //
// Init all LEDs
LED_DDR = 0xff;
// ------ Event loop ------ //
while (1) {
// Brighten and dim
if (brightness == 0) {
direction = 1;
}
if (brightness == 255) {
direction = -1;
}
brightness += direction;
pwmAllPins(brightness);
} /* End event loop */
return (0); /* This line is never reached */
}
No comments:
Post a Comment