Go Down

Topic: PWM frequency (Read 726 times) previous topic - next topic


Oct 16, 2007, 02:39 am Last Edit: Oct 16, 2007, 04:40 am by frank26080115 Reason: 1
How do I change the frequency period to something over 5ms? I need to control servos without worrying about some functions which may take over 20ms to execute.

I'm pouring over the register descriptions in the atmega168 datasheet and it's not clear what I have to change.

I can't lower my clock rate. An external servo controller is also an option but I really don't like the idea.

I found this:

Thanks for your hints, Mellis.

After some hours of diggin' in datasheets and webpages i finally came up with a solution that works:
(hope it's of any interest)

/* ServoPWM
* ---------------
* Comments
* (copyright notice) 2007 by Moe
* <http://youraddress.here>
* <mailto:you@youraddress.here>

int val = 0;

void setup(void) {
 pinMode(9,OUTPUT);  // Servo Pin

 TCCR1A = 0x00;      // sets timer control bits to PWM Phase and Frequency Correct mode
 TCCR1B = 0x12;      // sets timer control bits to Prescaler N = 8
 ICR1 = 0x0FA0;      // Upper Timer Limit = 4000 (in hex) equals 4ms => 1/5 of servo frequency


void loop(void) {
 val = analogRead(0);      // read potentiometer
 val = (val * 1.76) + 600; // convert potentiometer reading to value in microseconds (my servo responds to signals in the 600us - 2400us range)
 analogWrite(9,val);       // pulse servo
 Serial.println(val);      // output servo value


what it does:

- it initializes the PWM timer so its frequency is 4ms - 1/5 of the servo's frequency of 20ms
 (as all of the servo's signals fall in between the 0.5ms - 2.5ms range).
- analogWrite now takes values from 0 to 4000 (for us = 0.001ms)


it currently only works on pins 9 and 10 as Timer1 only drives these two.

best regards,

What about timer0 and timer2? I know they are 8 bits, so do I do this?

TCCR0A = 0x00;
TCCR0B = 0x12;
TCCR2A = 0x00;
TCCR2B = 0x12;


Go Up