Arduino Forum

Forum 2005-2010 (read only) => Hardware => Interfacing => Topic started by: airmusclekings on Feb 19, 2009, 05:22 pm

Title: Varying the pwm frequency for timer 0 or timer 2?
Post by: airmusclekings on Feb 19, 2009, 05:22 pm
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)
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: koyaanisqatsi on Feb 19, 2009, 08:26 pm
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
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: airmusclekings on Feb 20, 2009, 10:42 am
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
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: airmusclekings on Feb 22, 2009, 04:54 pm
bump...
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: macegr on Feb 23, 2009, 01:24 am
[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.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: halley on Feb 23, 2009, 01:33 am
macegr, that deserves to be a sticky posting in the FAQ section, and in the reference pages under advanced topics.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: macegr on Feb 23, 2009, 01:36 am
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.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: koyaanisqatsi on Feb 23, 2009, 03:36 am
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?
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: macegr on Feb 23, 2009, 03:47 am
I don't know of other side effects...the ones you mentioned were enough make me avoid changing the TCCR0B register.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: westfw on Feb 23, 2009, 08:19 am
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?
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: airmusclekings on Feb 23, 2009, 11:52 am
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!
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: halley on Feb 23, 2009, 04:36 pm
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.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mekon83 on Feb 28, 2009, 08:12 pm
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.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: koyaanisqatsi on Jun 21, 2009, 08:40 am
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
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: Flotec on Jul 17, 2009, 11:24 am
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
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mem on Jul 17, 2009, 11:30 am
I posted a spreadsheet here that has that information: http://spreadsheets.google.com/pub?key=rtHw_R6eVL140KS9_G8GPkA&gid=0
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 14, 2009, 04:54 pm
Very helpful document mem.

Do you know why timer2 on mega board has no OC2C output aka PWM T2C since all 16bit-timers on mega have three registers: OCRnA, OCRnB and OCRnC ?

Do you know when timer5 will be supported by IDE ?
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mem on Oct 15, 2009, 04:57 am
Hi, selfonlypath, I am not aware of how the Arduino designers chose which resources to expose.

But looking at the source code, I think PWM A and B on Timer5 may actually work. Try doing an analogWrite on pins 45 and 46. Let me know if it works and I will update the spreadsheet.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 15, 2009, 07:35 am
hello mem,

Just done the test with mega board and version 15 running on my Macintosh.

I confirm timer5 works perfect, here is my code where I generate 799,92Hz freq, PWM of 75% on OC5B and PWM of 1% on OC5C with clock system, phase & freq correct PWM

Code: [Select]
int outputPsuB = 45;  // Timer5-B
int outputPsuC = 44;  // Timer5-C

void setup()
{
// PSU outputs via timer5
 pinMode(outputPsuB, OUTPUT);  // select Pin as ch-B
 pinMode(outputPsuC, OUTPUT);  // select Pin as ch-C
 
 TCCR5A = B00101001; // Phase and frequency correct PWM change at OCRA
 TCCR5B = B10001;  // System clock
 OCR5A = 10000; // 799,92Hz
 OCR5B = 7500; // 75%
 OCR5C = 100; // 1%
 }


i've tried pre-scaling to diminish frequency and works perfect.

For me it looks 16-bits timer3, timer4 & timer5 are fully compatible with version 15 on Macintosh.

I'll look later on timer1 issue you've raised on your doc :-/
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 15, 2009, 07:37 pm
hello again mem,

Ok just made some test on timer1 which as you wisely mention on your doc can only have 2 pins outputs (11 and 12).

Well, it is a bit more tricky when reading atmega1280 spec because pin13 is SHARED by timer0 and timer1 so it can either be related to OCOA or OC1C.

If one make sure to only use timer1 and NOT use timer0, then timer1 becomes a full 16bit timer as timer3, timer4 and timer5 with three PW outputs.

Don't know what is best on how to describe this on your doc but with the above restriction, pin13 can be either TOA (as you have it now) and T1C :P
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 17, 2009, 06:05 am
There is more info on atemag1280 datasheet (chapter 19. Ouput Modulator (OCM1COA) giving details how pin 13 on mega board is shared by timer0 and timer1.

As stated before & this can be seen on the schematic, if one fully disable timer0 then timer1 recovers full potential of OC1A, OC1B & OC1C and three pins outputs. If you need to use timer0, then only OC1A & OC1B outputs hence only two pins are controlled by timer1.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mem on Oct 17, 2009, 09:23 am
Timer0 is used by millis and delay so it can't be disabled without disturbing these core functions.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 17, 2009, 10:32 am
OK the idea here is to have full potentiality of timer1 in mega board hence have control of OC1A, OC1B & OC1C. I could be wrong be feel then to preventing timer0 from writing to OC0A which is shared by OC1C (same pin 13 on mega) will leave intact millis() and delays(). For example, this code will block COM0A1 & COMA0 so partially disable timer0:
Code: [Select]
TCCR0A = TCCR0A & 0x3F;
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mem on Oct 17, 2009, 11:34 am
Looks promising, have you tried it and does the PWM work on timer1 without disturbing millis timing?
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 17, 2009, 11:58 am
There is no need to try because millis() does not use OC0A which happens to be connected to pin 13. Any project can use pin13 without corrupting millis() having in mind that pin13 happens to be the unique pin with a led inside mega board. My code just disable any output on pin13 coming from OC0A of timer0 so pin13 will be only modulated by OC1C of timer1.
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mem on Oct 17, 2009, 12:28 pm
Quote
There is no need to try because ...

It's been my experience that what one expects to happen based on interpreting a datasheet and what actually happens is not always as expected.  ;)
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 17, 2009, 07:42 pm
Ok, just done the test with this code and for me it works fine
Code: [Select]
#include <util/delay_basic.h>

int outputPsuB = 12;  // Timer1-B
int outputPsuC = 13;  // Timer1-C

unsigned long time;

void setup()
{
 Serial.begin(9600);
 
// PSU outputs via timer1
 pinMode(outputPsuB, OUTPUT);  // select Pin as ch-B
 pinMode(outputPsuC, OUTPUT);  // select Pin as ch-C

 TCCR1A = B00101001; // Phase and frequency correct PWM change at OCRA
 TCCR1B = B10101;  // System clock / 1024 from prescaler
 OCR1A = 10000; // 0.78125 Hz
 OCR1B = 7500; // 75% PWM
 OCR1C = 500; // 5% PWM
 
 TCCR0A = TCCR0A & 0x3F; // disable OC0A from timer0
}

void loop()
{
 Serial.print("Time: ");
 time = millis();
 //prints time since program started
 Serial.println(time);
 // wait a second so as not to send massive amounts of data
 delay(1000);
}


The terminal gives these values and I have correct PWM on pin 12 & 13:
Code: [Select]
Time: 4
Time: 1012
Time: 2023
Time: 3034
Time: 4045
Time: 5056
Time: 6067
Time: 7078
Time: 8090
Time: 9101
Time: 10113
Time: 11125
Time: 12137


Now if I remove the timer1 & timer0 specific initialization in setup(), I get same Time code log computed by millis() except there will be no PWM modulating pin 12 & pin 13.

Let me know if this fits what you wanted to test !
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Oct 23, 2009, 06:43 am
On second thought about OC1C output of timer1 on mega, it works fine but there might be a little problem because the shared pin13 is wired with a LED on the board. This will somehow alter or degrade the bandwith of fast PW as well as when using OC0A of timer0 so the problem i snot only with timer1. Worthwhile noting the presence of this led will also degrade the inner Atmega1280 Output Compare Modulator (see section 19)  :-/

It would have been best arduino designer connect the mega board LED to pin not connected to any timer as it is done with duamilanove.
Title: Here are the TCCRXB For MEGA
Post by: mark.sadgrove on Nov 04, 2009, 10:35 am
Hi,

Sorry if this is a dupe, but I can't seem to find this info anywhere else. Here are the PWM pin <-> TCCR register values to change PWM freuquencies on the Arduino Mega. These values were measured for each pin by going through the different TCCRXB values (from X=0 to 5) and measuring the pin output on an oscilloscope.

As above, the code used to set the prescaler in each case was

TCCRXB = TCCRXB & 0b11111000 | <setting>


e.g. to set the PWM freq on pin 5 to 31.25 kHz:
TCCR3B = TCCR3B 0b11111000 | 0x01

Frequencies are truncated at the decimal point. I have to admit, I didn't check every single setting, but just checked the pattern and then filled in the blanks from previous pwm divisor data. However, at least two setting values were checked for each pin, so this data should be reliable, barring a strange deviation from the divisors used in previous arduinos.
--

PIN     TIMER     Freq. at setting = 0x01   0x02   0x03   0x04  

2       TCCR3B                       31250  3906   488    122
3       TCCR3B                       31250  3906   488    122
4       TCCR0B                       62500  7812   976    244
5       TCCR3B                       31250  3906   488    122
6       TCCR4B                       31250  3906   488    122
7       TCCR4B                       31250  3906   488    122
8       TCCR4B                       31250  3906   488    122
9       TCCR2B                       31250  3906   976    488
10      TCCR2B                       31250  3906   976    488    
11      TCCR1B                       31250  3906   488    122
12      TCCR1B                       31250  3906   488    122
13      TCCR0B                       62500  7812   976    244
45      TCCR5B                       31250  3906   488    122  
46      TCCR5B                       31250  3906   488    122


--

Hope this is useful.

-- Mark
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: mark.sadgrove on Nov 05, 2009, 01:13 am
Gah, I see this information has indeed already been posted! My apologies. Believe it or not, I didn't notice that this thread had two pages so I missed mem's post above. It would have saved me an hour of checking if I had seen it. Hopefully the redundancy means that there is more chance of people finding the answer.

- Mark
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: jdumbaugh on Nov 08, 2009, 12:30 am
I'm slightly confused.  In the code:

Code: [Select]
int outputPsuB = 45;  // Timer5-B

void setup()
{
// PSU outputs via timer5
 pinMode(outputPsuB, OUTPUT);  // select Pin as ch-B
 
 TCCR5A = B00100010; // Phase correct PWM change at OCR5A
 TCCR5B = B10010;  // prescaling by 8 the system clock
 OCR5A = 14970; // 66,8002672Hz
 OCR5B = 1497; // 10% PWM
 }  


We set pin 45 as output.  How would this actually run?  If I do analogWrite(outputPsuB, 25) it gives me a distorted sine wave.  I don't understand this and nobody can seem to explain this stuff to me... :(
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: selfonlypath on Nov 09, 2009, 05:26 am
please read my answer on
Quote
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1252073278/15#15
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: jd33333333 on Jan 23, 2010, 07:08 pm
I would also like to know how to change the frequencies on the Arduino Mega....

I have changed them on my regular Arduino with good success, but the Mega has more timers and I am having trouble linking how MaceGR came up with the commands to change the frequencies from the Atmega168 datasheet.

Has anyone done this yet?
Title: Re: Varying the pwm frequency for timer 0 or timer 2?
Post by: modom on Mar 15, 2010, 06:37 am
So I am trying to create PWM using Timer4 on the Arduino Mega. I know that Timer4 uses pins 6, 7, and 8 on the Mega, and I'm trying to use output pin 7.
I want to use Fast PWM mode with a frequency of 62.5 kHz. (Ideally I would like 80kHz, but it seemed easier to get 62.5kHz by setting the clock prescale value to 1.)
Here is my code:
Code: [Select]

void setup()

{
 pinMode(7, OUTPUT);
//Within the TCCR4A register:
//COM4A1:0 = 10 for non-inverted output
 //WGM41:0 = 11 for the LSBs of WGM setting to fast PWM mode
 TCCR4A = _BV(COM4A1) | _BV(WGM41) | _BV(WGM40);
//Within the TCCR4B register:
//CS42:0 = 001 for clock prescale of 1, which should make a frequency of 62.5 kHz
//WGM43:2 = 01 for the MSBs of WGM setting to fast PWM mode
 TCCR4B = _BV(CS40) | _BV(WGM42);
 OCR4A = 14970;          // change the frequency by some (arbitrary) amount
 OCR4B = 819;              // set 80% duty cycle on channel 4B (this is supposed to show up on output pin 7!)
}

void loop()
{
}


I don't completely understand how to use the OCR registers, but from what I've seen it seems like you use OCR4A to set the timer compare value to determine the frequency you want. Then, you use the OCR4B and OCR4C registers to set the values for the duty cycles of your respective output channels.

BUT, this code just gives me a noisy sine wave on output pin 7.  What am I doing wrong?