I’m new to AVR’s and messing with them is quite fun!
right now I’m doing a fade in fade out RGB LED thing as an excersize in learning AVRs and learning about PWM
I’m using a atmega168 and playing with 8bit timer 0 using both channel A and B
currently I’m having a little issue getting the LEDs to turn off completely when I set OCR0A to 0 they’re dim but not off
here’s my code:
//shorthand type def
typedef unsigned char u8;
#include <avr/io.h>
#include <avr/interrupt.h>
int main(){
u8 direction_R = 1; //set fade direction 0=bottom_peak_hold, 1=fadein, 2=top_peak_hold, 3=fadeout
u8 direction_G = 3;
u8 hold_length = 50; //hold length
u8 hold_R = 0;
u8 hold_G = 0;
//OCR0A = 255; //set initial width 0=off 255=on
//OCR0B = 0;
TCCR0B |= (1 << CS01) | (1 << CS00); //use internal clock with prescaler of 64
DDRD |= (1 << DDD6) | (1 << DDD5); //set PORTD pin 6 and 5 or OC0A and OC0B for output
TCCR0A |= (1 << COM0A1) | (1 << COM0B1); //set TCCR0A pin for non-inverted PWM clear on compare match, on at BOTTOM
TCCR0A |= (1 << WGM00) | (1 << WGM01); //set waveform generator for fast PWM with TOP = 0xFF
while(1){
if(TIFR0 & (1 << TOV0)){
if(direction_R == 0 && hold_R > 0){
hold_R--; //hold
}else if(direction_R == 0 && hold_R == 0){
direction_R++; //start fadein
}else if(direction_R == 1 && OCR0A < 255){
OCR0A++; //fadein
}else if(direction_R == 1 && OCR0A == 255){
direction_R++; //start top peak hold
hold_R = hold_length;
}else if(direction_R == 2 && hold_R > 0){
hold_R--; //hold
}else if(direction_R == 2 && hold_R == 0){
direction_R++; //start fadeout
}else if(direction_R == 3 && OCR0A > 0){
OCR0A--; //fadeout
}else if(direction_R == 3 && OCR0A == 0){
direction_R = 0; //start bottom peak hold
hold_R = hold_length;
}
if(direction_G == 0 && hold_G > 0){
hold_G--; //hold
}else if(direction_G == 0 && hold_G == 0){
direction_G++; //start fadein
}else if(direction_G == 1 && OCR0B < 255){
OCR0B++; //fadein
}else if(direction_G == 1 && OCR0B == 255){
direction_G++; //start top peak hold
hold_G = hold_length;
}else if(direction_G == 2 && hold_G > 0){
hold_G--; //hold
}else if(direction_G == 2 && hold_G == 0){
direction_G++; //start fadeout
}else if(direction_G == 3 && OCR0B > 0){
OCR0B--; //fadeout
}else if(direction_G == 3 && OCR0B == 0){
direction_G = 0; //start bottom peak hold
hold_G = hold_length;
}
TIFR0 = (1 << TOV0); //reset TOV0
}
}
return 0;
}
Messy and redundant, I know how to program properly in C++, but for some reason when I created other functions they never worked properly… was like execution skipped over them completely… (in the AVR studio simulation they did get skipped completely during execution…) however, that’s another issue for another day.
Even if I comment out my fading code block and just set OCR0A & OCR0B to 0 you can see really well that the LEDs are still being turned on dimly.
I’m guessing because when the timer resets it automatically turns on the pin for a tick before it’s turned off by the OCR0A / B compare
note that I’m probably going to add a blue and maybe a couple others to this using the other available timers so I need to keep them all synced. I’m thinking I’ll have to create a for loop and work with arrays for each of the colors so I can fade from red to orange to yellow to green to etc… and back to red.
Am I going about this the wrong way?
Thanks!