logo1
logo2
Contact Us Curdridge Observatory channel on youtube google plus

Arduino PWM - Mega 2560 pins, registers and changing the frequency and range

Arduino PWM introduction

The Arduino Mega 2560 has 15 pins which can be used for PWM output. Normally you do this with the analogWrite() command, however, you can access the Atmel registers directly for finer control over the PWM on an Arduino including changing the type, range and frequency of the pulse width modulation PWM.

Which Arduino Mega pins map to which registers in the ATMEL microcontroller?

The following table gives the Arduino pin number and the corresponding register for controlling the duty cycle

Arduino Pin Register
2OCR3B
3OCR3C
4OCR4C
5OCR3A
6OCR4A
7OCR4B
8OCR4C
9OCR2B
10OCR2A
11OCR1A
12OCR1B
13OCR0A
44OCR5C
45OCR5B
46OCR5A

How can we use this information on PWM registers?

Very simply we can use the register to set the duty cycle instead of the analogWrite command. Using the register is slightly faster.


First we set the pin to output and use the analogWrite command to initialise the PWM
pinMode(2,OUTPUT);
analogWrite(2,1);

Now we can change the duty cycle using just the register
OCR3B = 128;
OCR3B = 4;

And so on

How to change the frequency and range of the Arduino PWM?

One of the most annoying aspects of the native arduino PWM commands is that the PWM frequency is set to a value which is audible. This is extremely annoying as it produces a nasty noise when operating DC or stepper motors by PWM.

We need to look at the timer counter control registers. These control the type, range and frequency of the PWM generated by the Arduino. Please see section 17.9 in the datasheet. This is demonstrated by the code below. Please note that the control registers 4, sections A & B will effect the PWM on all the OCR4n pins, see table above.


sbi(TCCR4B, CS40);
cbi(TCCR4B, CS41);
cbi(TCCR4B, CS42);

sbi(TCCR4B, WGM43);
sbi(TCCR4B, WGM42);
sbi(TCCR4A, WGM41);
cbi(TCCR4A, WGM40);

ICR4 = 400;

The 4 statements relating to the WGM bits control the mode of operation of the PWM. We have set it to mode 14, which is fast PWM with ICRn used as the maximum for the counter. The CS bits relate to the clock selection, see table 17-6 in the datasheet. We have selected no prescaling, which corresponds to the native 16Mhz frequency of the Arduino clock.

The actual frequency of the PWM is a function of these settings and the final entry, the input capture register. Setting this to 400 results in a PWM frequency on the Arduino Mega pin of 16Mhz / 400 = 47304Hz, or possibly half that! The duty cycle is then changed by setting OCR4A or B to some value between 0 and 400

Further reading of the datasheet will explain all the registers, but hopefully this will point you in the right direction

Please note, not all PWM mode are available on all clocks.