Go Down

Topic: Varying the pwm frequency for timer 0 or timer 2? (Read 49126 times) previous topic - next topic

festo

Feb 19, 2009, 05:22 pm Last Edit: Feb 19, 2009, 05:26 pm by airmusclekings Reason: 1
Hi,
I'm trying to use the Diecimila Arduino board to pulse solenoid valves, at a frequency of 125Hz. I can get pins 9 and 10 to work fine using the following:

TCCR1A=0x00;
TCCR1B=0x12;
ICR1=0x1F40;

However I have no idea how to change the pwm frequency at pins 3, 5, 6 and 11. I understand these don't use timer 1, but timer0 and timer 2 instead, and that these don't have the ICR1 input capture unit, which I believe the above code was using to vary the pwm frequency.
So is it possible to change the pwm frequncy of the other timers? And if so how?

Thanks in advance, and any help will be much appreciated!

Adam (& Ben)

koyaanisqatsi

I brought up this subject as a feature request a while back.  A few suggestions were made on how to do this.  Not sure if it has what you need. But it may help:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1234764073
What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

festo

Thanks for the reply -  I had actually already found that thread, and like you found the document on controlling timers far beyond my programming ability!

If someone has achieved this (low frequency pwm on a tleast 4 channels) I'd be very grateful if they could let me know how!

Cheers,

Adam


macegr

#4
Feb 23, 2009, 01:24 am Last Edit: Feb 23, 2009, 01:35 am by macegr Reason: 1
[size=16]How to adjust Arduino PWM frequencies[/size]

[size=14]Pins 5 and 6:[/size]





SettingDivisorFrequency
0x01162500
0x0287812.5
0x0364976.5625
0x04256244.140625
0x05102461.03515625


[size=14]TCCR0B = TCCR0B & 0b11111000 | <setting>;[/size]


[size=14]Pins 9 and 10:[/size]





SettingDivisorFrequency
0x01131250
0x0283906.25
0x0364488.28125
0x04256122.0703125
0x05102430.517578125


[size=14]TCCR1B = TCCR1B & 0b11111000 | <setting>;[/size]


[size=14]Pins 11 and 3:[/size]







SettingDivisorFrequency
0x01131250
0x0283906.25
0x0332976.5625
0x0464488.28125
0x05128244.140625
0x06256122.0703125
0x07102430.517578125


[size=14]TCCR2B = TCCR2B & 0b11111000 | <setting>;[/size]

All frequencies are in Hz and assume a 16000000 Hz system clock.
Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

halley

macegr, that deserves to be a sticky posting in the FAQ section, and in the reference pages under advanced topics.

macegr

#6
Feb 23, 2009, 01:36 am Last Edit: Feb 23, 2009, 01:43 am by macegr Reason: 1
It was wrong, I fixed it all. The last two sections are divided by two for the Arduino. I also left in the decimals because they might factor into someone's results.

I was figuring out how to smoothly dim/fade some neon sign segments and they needed something close to 100Hz, so I had calculated most of the data and checked it with an oscilloscope already.
Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

koyaanisqatsi

Macegr, you are THE MAN!  Thank you so much!

So some observations/questions:

The PWM range increased from 0-255 to 0-1023 in the cases I tested.  Is this true for all values?

delay() and millis() are no longer behaving as expected after changing the TCCR0B settings.  Do you know of any other side effects of changing these timers?
What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

macegr

I don't know of other side effects...the ones you mentioned were enough make me avoid changing the TCCR0B register.
Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

westfw

Quote
Pins 5 and 6:
Setting       Divisor       Frequency
0x03       64       976.5625
TCCR0B = TCCR0B & 0b11111000 | <setting>;

Pins 11 and 3:
Setting       Divisor       Frequency
0x04       64       488.28125
TCCR2B = TCCR2B & 0b11111000 | <setting>;

Does timer2 really run half the frequency of timer0 with the same prescaler?  I coudn't find anything obvious to account for such a discrepancy in the AVR datasheet, although it matches observations.  What am I missing?

festo

thanks a lot! I'll try this out today. I'm pulsing some solenoid valves to control a pair of air muscles, and they just arrived!

halley

westfw, start with the first section on page 136 of the atmega168 datasheet.  I am not able to fully make sense of it all, but it looks like timers 0 and 1 source from different clock inputs (one 8bit vs one 16bit), so even with the shared prescaler logic and settings, they have different frequency outputs; timer 2 is more independent.  I wonder what the design considerations were, but I think they were going for maximum variation between the three, while sharing a lot of logic.

mekon83

macegr: I'm afraid that the frequencies in your post for pins 3, 9, 10 and 11 are a little of. The correct formula is f = clock/(510 N), where N is the divisor (prescaler) and clock = 16,000,000. That gives f = 490.196 Hz for the default setting. But close enough. See the ATmega168 datasheet.

westfw: The reason is that Timer0 runs in the FastPWM mode to feed the millis() function. That gives a frequency f = clock / (256 N), N = 64 by default. In FastPWM, the counter is always incrementing until it reaches 256 when it overflows to 0.  The frequency f = 976.563 that is close enough to generate milliseconds.
Timers 1 and 2 run in the Phase correct PWM, which is apperently better for motors. Then the counter increments until it reaches the top 255 and then starts decrementing until it reaches 0. And then again incrementing... Thus for each cycle it has to go through 255 + 255 = 510 steps, hence the frequency clock/ (510 N), N = 64. That gives you ~~ 490Hz.

koyaanisqatsi

#13
Jun 21, 2009, 08:40 am Last Edit: Jun 21, 2009, 09:15 am by koyaanisqatsi Reason: 1
If you change TCCR0B, it affects millis() and delay().  They will count time faster or slower than normal if you change the TCCR0B settings.  Below is the adjustment factor to maintain consistent behavior of these functions:

Default: delay(1000) or 1000 millis() ~ 1 second

0x01: delay(64000) or 64000 millis() ~ 1 second
0x02: delay(8000) or 8000 millis() ~ 1 second
0x03: is the default
0x04: delay(250) or 250 millis() ~ 1 second
0x05: delay(62) or 62 millis() ~ 1 second
(Or 63 if you need to round up.  The number is actually 62.5)

Also, the default settings for the other timers are:
TCCR1B: 0x03
TCCR2B: 0x04

There may be other side effects from changing TCCR0B.  For example my project would not properly run with TCCR0B set to 0x02 or 0x01.  But it worked fine at 0x03 and higher.  YMMV
What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

Flotec

Hello,

Does anyone know which timer (TCCR**) that controls which pins on a Arduino Mega? I would like to change the pwm frequency on to of the pins.

/Flotec

Go Up