NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Sensors, Actuators, and Robotics » PWM Not Working

July 30, 2012
by Todd2473
Todd2473's Avatar

I am pulling my hair out on this one. I can't get the PWM functionality to work properly. I am trying to dim an LED. I was eventually going to use it to control the brightness of the included display, but didn't get that far.

Here is the counter set up that I used (I set the Data Direction in a separate io_init routine that is called prior to this timer_init routine DDRB |= (1<<PB3); // output on pin PB3 This is the PWM output):

TCCR2A = 0b11000001; //Compare Output Mode On When Up Counting and WGM for Phase Correct PWM Mode

TCCR2B = 0b00001111; //WGM for Phase Correct PWM Mode and prescalar of 1024 TCNT2=0;

OCR2A=200;

TIMSK2=0b00000010; // Enable the interrupt for future use

PRR &= ~(1<<PRTIM2); //make sure the timer is not turned off

This keeps pin PB3 Low all the time, but I thought I would get a PWM output. Oddly, if I change just TCCR2A to 0b01000001 then it does work correctly and I get a 50% duty cycle pulse.

I have measured this with both an LED and an oscilliscope. I have used different prescalars but this slow could be seen more obviously.

So, I thought I would work around this and just change the value of OCR2A to control the duty cycle by using the interrupt. I wrote simple code to change OC2RA to change at each interrupt per below (I did initialize pulse_mode earlier to 1):

ISR(TIMER2_COMPA_vect) {

if (pulse_mode==1)
{
    OCR2A=10;
    pulse_mode=0;
}
else
{
    OCR2A=100;
    pulse_mode=1;
}

}

I know the interrupt was working as a created a quick real time clock and it worked fine. Not a whole lot of precision with 256 bits, but it proved it was working. Interestingly, the output now would always be low after 1 brief cycle where it turned on. If I set OCR2A to the same value in both branches, it works. If I change it by just 1 in either direction, then I get an always low output.

I hope I am missing something simple but I have gone blind reading the ATmega data sheet and can't sort out what is going wrong. Any help would be appreciated.

July 31, 2012
by pcbolt
pcbolt's Avatar

Todd -

I think there is a mistake in the datasheet because there is a contradiction when describing the WGM registers. In your case there are two things I would try.

First, try using Phase Correct Mode 1, which would mean setting TCCR2B = 0b00000111. This should set the TOP value to MAX (255). Then you can set OCR2A to 200 (or whatever you need) and use the other settings to control if you want to go high, go low or toggle on a compare match.

Second, instead of using ISR(TIMER2_COMPA_vect), try using ISR(TIMER2_OVF_vect). The second one will trigger at the bottom of the wave and not at the compare match.

August 01, 2012
by Ralphxyz
Ralphxyz's Avatar

And let us know how everything works out.

Oh also the Nerdkit Community Library could use a simple article on PWM on the Nerdkit.

Ralph

August 01, 2012
by Todd2473
Todd2473's Avatar

I am not sure what the contradiction is, but your suggestion worked. Thank you!

I think I see my problem. I confused MAXIMUM with TOP. Not sure what value there would ever be to set TOP equal to OCR2A (which is what I was doing when I set WGM22=1), but I see how that would result in either an always high or always low value that I was getting.

I did see how I am suppose to use the overflow flag to change OCR2A. Not sure how I missed that having read that section about 10 times. This isn't necessary, though, for my simple dimmer now that the PWM is working properly.

Now on to driving a FET to drive the display as the output pin doesn't have the current capability to drive the display. I think the final project will be pretty slick where the intensity will be set by the time of day.

Thanks again for your help!!

August 01, 2012
by pcbolt
pcbolt's Avatar

Todd -

Excellent. Glad to help. The contradiction was in these two lines...

  • "The phase correct PWM mode (WGM22:0 = 1 or 5) provides..."

and

  • "TOP is defined as 0xFF when WGM2:0 = 3, and OCR2A when MGM2:0 = 7...(sic)"

I can't understand how both can be true and still be in "phase correct" mode. I wish it had the extra WGM registers so you could have easy control of duty cycle and frequency. But like you said...if it works, it works.

Cool concept of changing intensity by a clock. You could throw in a photo-diode on the ADC and really dial it in. Let us know how it turns out...seeing a finished product on here is a highlight of the forums.

Post a Reply

Please log in to post a reply.

Did you know that talking to the microcontroller over the USB/Serial link is easy under Windows, Linux, and OS X? Learn more...