Timer2 questions: Why is OCR2A not consistant on my oscilliocope?

I’m trying to learn timers, to build a LED dimmer for my ceiling lamps. I am using timer2.

I use an interrupt function, check the “anim.onCycle2” boolean; if true, the “OCR2A=” on-value, if FALSE then “OCR2A=” off-value. I use serial commands to set “anim.PWMonValue2” and “anim.PWMoffValue2”. This is how I expect to change the width of my wave, to dim my LEDs

After I hooked my oscilloscope up to see what was going on, I can visually see the square wave change shape as I change the ON/OFF values from serial commands. As I understand, the “ISR(TIMER2_COMPA_vect)” will execute on the pre-scaler, count whatever “OCR2A” - is this correct?

I can set the on value for 128, off value for 128 and the square wave 50% duty with frequency on my screen measures “122.044Hz”. If I change on value to 10, OFF value to 10 - I see the EXACT wave, with same frequency. Same goes if I set them both, to ANY value. I was expecting, if this counter counts to 10, (2) times -vs- counts to 100 (2) times this WAVE would be wider in both on/off and give me a different frequency. Whatever this is doing I can not understand, please help me.

If I set on-Value to 10, off-value to 100 - I can shape the width of that wave is longer on the off-value. Same goes if I set on-value to 100, and off-value to 10, I see the wave shape in opposite. I can tell my interrupt compare function is processing the on/off values in to OCR2A. If I set both on & off to 10, or both to 100, or both to ANY of the same values - my scope reads the same “122.04 HZ” value. I just can not understand how the processor is interpreting these values!?!? I thought 100 pre-scale cycles took much more time to process than 10 pre-scale cycles, but my oscilloscope tells me different.

Here is my SIMPLIFIED setup function:

void setup()
{
    animInit();
}

void animInit()
{
	noInterrupts();						
	TCCR2A =	0;
	TCCR2B = 0;							

	TCCR2B = 6;                                    // CS22=1	CS21=1	CS20=0
	TCCR2B |= (1 << WGM12);              // CTC mode

	TCNT2=		0;					
	OCR2A =		255;		                     

	TIMSK2 |= (1 << OCIE2A);		// enable timer compare interrupt	

	interrupts();						

}


ISR(TIMER2_COMPA_vect)				// timer compare interrupt service routine
{
	digitalWrite(anim.LED[testLed], anim.onCycle2);	// toggle LED pin	

	OCR2A = anim.onCycle2 ? anim.PWMonValue2 : anim.PWMoffValue2;

	anim.onCycle2 = ! anim.onCycle2;

}

volatile?

TCCR2B |= (1 << WGM12);              // CTC mode

WGM12 is a bit used to set Timer1. You have either inadvertently transposed or don’t realize that the first number refers to the timer and the second to the bit.

WGM12 is probably defined as bit3 which is WGM22 when applied to register TCCR2B. and you are not getting the mode you want. In fact, WGM22:WGM20 = 100 is not a valid mode

TCCR2A |= (1 << WGM21);              // CTC mode

What do you see when you correct this?

Why are you trying to generate pwm with a ctc mode instead of a pwm mode?

Jiggy-Ninja:
volatile?

const byte LEDS = 7;
const byte LED[7] = { 14, 15, 16, 17, 18, 19, 13 }; // LED PINS, 6 designs - 1 spare

volatile bool onCycle = false;
volatile bool onCycle2 = false;

volatile unsigned int PWMonValue = 31250;
volatile unsigned int PWMoffValue = 31250;
volatile byte PWMonValue2 = 255;
volatile byte PWMoffValue2 = 255;

but now that you mention it, these are members of a STRUCT I declared:

struct animationsStr

The STRUCTURE ITSELF is NOT volatile:

animationsStr anim;

I'm not sure how that works if members of the structure are volatile and the structure itself is not....

cattledog:

TCCR2B |= (1 << WGM12);              // CTC mode

WGM12 is a bit used to set Timer1. You have either inadvertently transposed or don’t realize that the first number refers to the timer and the second to the bit.

WGM12 is probably defined as bit3 which is WGM22 when applied to register TCCR2B. and you are not getting the mode you want. In fact, WGM22:WGM20 = 100 is not a valid mode

TCCR2A |= (1 << WGM21);              // CTC mode

What do you see when you correct this?

Why are you trying to generate pwm with a ctc mode instead of a pwm mode?

I did not realize the “WGM12” bits were for timer1, please excuse me - I find it difficult and confusing to learn.

PWM instead of CTC? My hardware is wired to PORTC, pins A0-A5 (14, 15, 16, 17, 18, 19). I thought the PWM function was hard-wired to specific pins, I did not design for this layout. I found it easier for me to do my project by after studying the CTC examples I found. I am still confused by however many different PWM settings there are. The examples and tutorials appear to leave out important details that have me on a confusing and distracting scavenger hunt for information.

I changed code:

TCCR2B |= (1 << WGM22);							// CTC mode

I get the same results. I then checked on my compiler “WGM22” and “WGM21” both return “3”, that will explain why my results are the same.

I get the same results. I then checked on my compiler "WGM22" and "WGM21" both return "3", that will explain why my results are the same.

Yes, except Mode 100 is not a valid mode on Timer2.

My recommendation is that you put the timer in normal mode 000 with prescaler 256 like you have. Then the timer will cycle at 244 hz.

I would use an overflow interrupt to turn the pin on, then use a compare interrupt at OCR2A to turn the pin off. Then just adjust OCR2A for the duty cycle.

Hi, thank you for pointing that out. Can you tell me, is THIS an accurate table for timer2?

Is this mode "000" toggling a pin by hardware? I've got software serial on other pins, and can't have this crazy thing toggle signals. I'm trying to toggle my hardware pins in the interrupt function - without using the hardware timer to toggle anything else automatically.

Can you tell me, is THIS an accurate table for timer2?

Yes, that looks correct.

Is this mode "000" toggling a pin by hardware?

No, mode 0 just runs the timer from 0 to 255 over and over. With prescaler 256, that takes 4096 microseconds, for 244Hz cycle.

You can implement the pwm (different on off timing at the basic 244 Hz) with two interrupts. I am giving you the method which looks intuitive with a bigger setting of OCR2A giving a longer pulse.

Used the timer overflow interrupt to turn the desired output pin on. Use the Compare match interrupt to turn the pin off. The pin will be on for what ever percentage of 255 the OCR2A setting is. e.g. OCR2A =63 will be 25% duty cycle. The timer always starts at 0 and runs to 255 so the settting is 0 referenced.

I think I just nailed it.

TCCR2A |= (1 << WGM21);											// CTC mode
[\code]

I have to assign to TCCR2A and NOT TCCR2B.  I have no idea why it's so difficult for me to figure out what TCCR2A, TCCR1A 1B - the differences are, and how to correctly assign these registers.

I have to assign to TCCR2A and NOT TCCR2B. I have no idea why it's so difficult for me to figure out what TCCR2A, TCCR1A 1B - the differences are, and how to correctly assign these registers.

Have you read the datasheet? It's pretty clear about what bits are in which register.

If you don't want to tackle the full data sheet, Nick Gammon's timer tutorial has some handy cheat sheets on page 2 reply #14.
http://www.gammon.com.au/forum/?id=11504&reply=18#reply18

When I opened, what I thought was the data-sheet, there was a table that spanned across 4 pages. I started reading, then with the fine print, and back to the table again - all I felt was a huge headache after I discovered what I was reading was some type of summary guide for the 1,000+ other pages.

Thanks Cattledog for the Nick Gammon charts - this is more like what I can probably study and learn something from.

Which datasheet did you look at? The ATmega328P has 442 pages. Yes it's a lot, but the datasheets also have bookmarks in them that you can use to quickly navigate to whatever section you want. You don't need to read the whole thing in order like a book.

The cheat sheets in the post cattledog linked to are annotated snippets of the tables in the Register Description section of the datasheet.

It's not easy for me to explain. I'm a slow learner. I become confused when there is too much information, is overwhelming. Once the datasheets start using symbols, calculations, modes, terms I'm not familiar with - the task of reading becomes painful for me to comprehend.