I am trying to drive 8 LEDs connected to a
74HC595 shift register with PWM. I want to be able to set each LED to a different brightness. The PWM signal is connected to the
Enable Output pin of the shift register (it is low active so the PWM signal must be inverted). By selecting each LED (only one LED at a time) and setting the PWM frequency I thought it would have been done. So currently I have following approach:
- set PWM frequency
- "activate" desired LED by writing according value to shift register (for example first LED would be
- write shift register value to shift register outputs by setting the
1and clear it back to
- start over again with new PWM frequency and next LED
This is resulting in following fault: When I set the first LED to full brightness and the next LED to no brightness (off) I notice that for a short time the full brightness of the first LED is showing up on the next LED. This behavior gives the second LED a little brightness which is bad because I want no brightness (turn it off). I know I could just jump over the LED to leave it off but I would like to only control LEDs brightness by setting the PWM frequency. Also I have this effect when setting for example first LED to full brightness and next LED to half brightness. There is always the brightness of the preceding LED on the next LED for a short time.
I think it is because I can't control the PWM output like I can control the shift register output by its latch. The PWM frequency is applied as soon as I set it in my code. This causes the short blink with preceding LED's brightness. I also tried to change the order of steps in my approach.
Do you have any idea how to solve this problem?
Some lines of my real code (if the pseudo code is not enough):
OCR0A = 0; // set PWM to full brightness SPDR = 0b00000001; // select first LED while(!(SPSR & (1<<SPIF))); // write to shift register PORTB = 0; // latch outputs PORTB = 1; _delay_ms(1); OCR0A = 255; // set PWM to no brightness (off) SPDR = 0b00000010; // select second LED while(!(SPSR & (1<<SPIF))); PORTB = 0; PORTB = 1; _delay_ms(1);
My target hardware is an
ATmega168 clocked at 20 MHz. I am using