Arduino Mega Timer/Counter 3 Fast PWM mode 15 Duty Cycle

Hello all,

I am attempting to program a MEGA2560 to get a PWM of 50Kz to 250Kz. I was finally able to get the code right to generate the frequency but I am having difficulties with the duty cycle. I would like to be able to vary duty cycle from 20 to 80% as well.
I am using the Timer/Counter 3 in mode 15 with no prescaler. Can someone point me in the right direction to get this going?

Thank you all for the help. Most appreciated!

Chris


void setup() {
//Enable Timer/Counter 3
PRR1 = (0 << PRTIM3);
pinMode(5, OUTPUT);
Serial.begin (9600);
TCCR3A = 0; //Reset the Timer/Counter Control Registers
TCCR3B = 0; //Reset the Timer/Counter Control Registers
TCCR3C = 0; //Reset the Timer/Counter Control Registers

//Set to mode 15 with no prescaler,
TCCR3A = (0<<COM3A1) + (1<<COM3A0) + (0<<COM3B1) + (1<<COM3B0) + (0<<COM3C1) + (1<<COM3C0) + (1<<WGM31) + (1<<WGM30); 
TCCR3B = (0<<ICNC3) + (0<<ICES3) + (1<<WGM33) + (1<<WGM32) + (0<<CS32) + (0<<CS31) + (1<<CS30); 
TCCR3C = (0<<FOC3A) + (0<<FOC3B) + (0<<FOC3B);
TIMSK3 = (1<<ICIE3) + (1<<OCIE3C) + (1<<OCIE3B) + (1<<OCIE3A) + (1<<TOIE3);  // enable timer compare interrupt

OCR3A = 31;  //TOP Value 159 = 50 Kz 31 = 249Kz
OCR3B = 8;            
interrupts();             // enable all interrupts
}

void loop() {
 
}

This will output 80% duty cycle at 50 kHz on these two pins (using TIM3)

void setup_timer3(void)
{
	/***********************************
	set up timers 3
	Fast PWM with TOP at OCR3A
	***********************************/
	
	/*************
	TIMER3
	*************/
	TCCR3A = 1<<COM3B1 | 0<<COM3B0 | 1<<COM3C1 | 0<<COM3C0 | 1<<WGM31 | 1<<WGM30;
	TCCR3B = 1<<WGM33 | 1<<WGM32;

	// 50 kHz at 16Mhz
	OCR3A = 320;

	// 80% duty cycle
	OCR3B = 256;
	OCR3C = 256;

	TCNT3 = 0;

	// start TIM3 at 16MHz (DIV1)
	TCCR3B = 1<<WGM33 | 1<<WGM32 | 0<<CS32 | 0<<CS31 | 1<<CS30;
}

Make sure you configure the pins as digital output for the PWM to work.

Also, try not to use any of the timer interrupts if you are running them at 50/250 kHz. You'll run out of CPU cycle for anything else. And there are some errors on your code. With a 16 MHz clock and a TOP of 32 generates 500 kHz (not 250 kHz). Also, you have it "TOGGLE" instead of true PWM...

The duty cycle is expressed as fraction of the TOP value. If you use OCR3A (or ICR3) for the PWM frequency then this register holds the TOP value. Use TOP for 100% duty cycle.

Three values determine the PWM frequency:

  1. Clock Frequency
  2. Prescale Factor
  3. TOP value (divisor - 1)

To get 250 kHz Fast PWM from 16 MHz you need a divisor of 16000000 / 250000 = 64

To get 50 kHz Fast PWM from 16 MHz you need a divisor of 16000000 / 50000 = 320

Use the lowest prescale that will get the divisor within the capability of the timer. For an 8-bit timer (divisor = 1 to 256) you don't need a prescale for 250 kHz (64 is less than 256) but you would need a prescale for 50 kHz (320 is not less than 256).

Pick a Fast PWM mode where you can set the TOP value. WARNING: If the mode uses one of the Output Compare Registers (typically OCRnA) to store TOP, you can't use that PWM channel for PWM.

Set the TOP register to divisor - 1.

Set the OCR registers to TOP * dutycycle.

For 250 kHz (TOP == 63) you would use 12 (19%) or 13 (20.6%) for your low end and 50 (79.3%) or 51 (80.9%) for the high end.

For 50 kHz (TOP == 319) you would use 63 (19.7%) or 64 (20.0%) for your low end and 255 (79.9%) or 256 (80.3%) for the high end.

Ah!

Thank you guys! I see where I went wrong!!! I did not fully understand the impact of setting the COMnA3 values.

Thank you so much!

Chris

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.