Fast PWM with Arduino – Fast!

HEY! THIS POST HAS MOVED!

This post is now on my new site. All updates and comments will appear there, so I strongly suggest you click here to read at bluepichu.com. Thank you!

It’s been so long since I posted!

I recently purchased two Boarduinos from adafruit for an infrared control project I’ve been working on. However, I found it quite annoying to get the correct frequency for a square wave so that the IR detector would get the signal.

After a long day of searching, I came across a lot of sites including libraries that would (supposedly) do it for you and a lot about using the Arduino’s built-in timers and pulse-width modification (PWM). Since I needed 56 kHz, I had to combine a lot of the info I found to make it work, but in the end I got it! Here I’m going to show how you can use the Arduino’s timers to make a square wave of any frequency quickly and easily.

This page says what I’m going to talk about here and more, but for now I’m going to try to use simpler terms than that page and try to make this as painless as possible.

Prescalers

The arduino has three timers (appropriately enough named Timer 0, Timer 1, and Timer 2). Each one is connected to two pins (see the chart below). Each timer can have a prescaler that changes how often it’s triggered. Here’s a table of the timer frequencies versus prescaler values (data from here; I’ll explain what the “setting” is in a second):

Timer 0 (pins 5 and 6)

***Note the high base frequency*** Setting Divisor Frequency 0x01 1 62500 0x02 8 7812.5 0x03 64 976.5625 0x04 256 244.140625 0x05 1024 61.03515625

Timer 1 (pins 9 and 10)

Setting Divisor Frequency 0x01 1 31250 0x02 8 3906.25 0x03 64 488.28125 0x04 256 122.0703125 0x05 1024 30.517578125

Timer 2 (pins 11 and 3)

***Note the wider variety of prescaler options*** Setting Divisor Frequency 0x01 1 31250 0x02 8 3906.25 0x03 32 976.5625 0x04 64 488.28125 0x05 128 244.140625 0x06 256 122.0703125 0x07 1024 30.517578125

Now we can use this data to set the prescaler. This is done through the variable TCCR#B, where # is replaced with the number of the timer for which you want to change the prescaler, like so:

TCCR#A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR#B = _BV(CS22);
TCCR#& = TCCR#& & 0b11111000 | <setting>;
//just replace # with the timer number, & with either A or B to get the pin you want, and <setting> with the setting from above

NOTE: In the table above, A is the first listed pin while B is the second listed pin.

Varying the Timer Limit

So now you can get any of the frequencies above, but what about other frequencies, like the 56 kHz required for my project?

What you can do is vary the upper limit of the timer. How the arduino timer works is that, by default, it counts up from 0 to 255, and then resets to 0. Whenever it resets, it sets the clock signal to high; whenever the value passes a given threshold value, the clock signal goes low.

However, it is possible to change this upper limit. Instead of using the above code, use this one:

TCCR#A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR#B = _BV(WGM22) | _BV(CS22);
TCCR#& = TCCR#& & 0b11111000 | <setting>;
OCR#& = <limit>;
//just replace # with the timer number, & with either A or B to get the pin you want, <setting> with the setting from above, and <limit> with the clock's maximum value

Now all you have to do is calculate the clock’s maximum value. This is very easy:

limit = (desired value / frequency from above * 256) – 1

So for my 56 kHz example, this would be

limit = (56000 / 62500 * 256) – 1
limit = (.896 * 256) – 1
limit = 229.376 – 1
limit = 228.376 ≈ 228

That’s all! Just plug in the values and it should work just fine, and should output a square wave with your given frequency and a 50% duty cycle.

Don’t forget to subscribe if you want to receive updates about future posts.

Advertisements

, , , , , ,