Pages: [1]   Go Down
Author Topic: PWM to 50 hz  (Read 1848 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!

How do i set one of the PWM port to 50hz with a 0.5ms pulse width?

So far i got this:
Code:
 pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = TCCR2B & 0b11111000 | 0x07;
  OCR2A = 180;
  OCR2B = 50;

This code generates a 30.6hz signal with 22.8ms pulse width.

http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
http://playground.arduino.cc/Main/TimerPWMCheatsheet

Thanks in advance
« Last Edit: February 20, 2013, 01:48:24 pm by thrinker » Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 331
Posts: 16470
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bandwidth ?

You seem to be misusing that term or don't understand what the term means, do you mean duty cycle or pulse width?

Lefty
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 25
Posts: 1872
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

"Blink without delay" see examples will let you do this.

Mark
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24308
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try using the Servo library, using "writeMicroseconds (500);"
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 25
Posts: 1872
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Look in the playground - lots of ways to do this kind of thing listed there.

Mark
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I edited my post, i ment pulsewidth and not bandwidth. I dont want to use the arduino servo library. I want to write to the registers myself..
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You want to pay special attention to this section of the :
Varying the timer top limit: fast PWM on this page
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
This is probably the most confusing configuration you'll run into.  It's not very intuitive because it looks like you will be toggling OC2A (Pin 11), but you really toggle OC2B (Pin 3).  This is because you hijack the OCR2A register to set the TOP limit so it can't possibly set a duty cycle now.  The duty cycle is set by OCR2B and consequently it toggles OC2B (Pin 3).  This is all necessary because you want to use a "non standard" PWM frequency.
Code:
 pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22)| _BV(CS21)| _BV(CS20);           //
  OCR2A = 156;
  OCR2B = 4;

This should give you a 50.1 Hz update rate with a .512mS pulse width on Pin 3.  I haven't tested it, but I think it's right.

EDIT:  I tested it on the scope and it works.  Pin 11 has a 25Hz 50% duty cycle waveform on it.
« Last Edit: February 20, 2013, 05:10:12 pm by afremont » Logged

Experience, it's what you get when you were expecting something else.

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You want to pay special attention to this section of the :
Varying the timer top limit: fast PWM on this page
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
This is probably the most confusing configuration you'll run into.  It's not very intuitive because it looks like you will be toggling OC2A (Pin 11), but you really toggle OC2B (Pin 3).  This is because you hijack the OCR2A register to set the TOP limit so it can't possibly set a duty cycle now.  The duty cycle is set by OCR2B and consequently it toggles OC2B (Pin 3).  This is all necessary because you want to use a "non standard" PWM frequency.
Code:
 pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22)| _BV(CS21)| _BV(CS20);           //
  OCR2A = 156;
  OCR2B = 4;

This should give you a 50.1 Hz update rate with a .512mS pulse width on Pin 3.  I haven't tested it, but I think it's right.

EDIT:  I tested it on the scope and it works.  Pin 11 has a 25Hz 50% duty cycle waveform on it.


Thanks alot! That works great. To change the pulse width i edit the output compare register b, OCR2B = 4 gives me 510us width. When i change the OCR2B value to 20 i get a 2.560ms width. Between 10 and 11 the value is 1.280ms and 1.410ms, is it possible to get a value inbetween those two? like 1.300?

Thanks in advance!
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The problem is that with a 50Hz update rate, the possible pulse length is 20mS.  This is spread across 156 possible widths.  This only gives .13mS resolution as you already can see.  To achieve .02mS resolution as you asked, would require several more bits of resolution in the PWM unit and that's not going to happen, you're stuck at 8 bits maximum; right now you barely have 7 since the TOP count is 156.  You are asking for 10 bits of PWM resolution.  It's just not possible with the 8-bit timers.
Logged

Experience, it's what you get when you were expecting something else.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24308
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or you could use the Servo library (or look at the source, and see which bits you want to use, if you don't want to use the library itself)
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I glanced (literally five minutes) at the servo library code and it looks like it uses Timer1 initially.  This is a 16 bit counter.  It puts it in ordinary count mode and enables overflow interrupts.  With the prescaler of 8, it should overflow roughly 30.5 times per second.  This would be the update rate to the servo, not 50Hz.  This means one cycle is about 33mS long but is divided into 65536 possible parts for 500nS resolution on the duty cycle.  It's not using the PWM feature of the chip, it's simulating it with software in the ISR so that it can run a multitude of servos.  Given this method, it should work on any output pin.

EDIT:  When you hijack Timer1, it disables the ability to use analogWrite() on Pins 9 and 10 for PWM.
« Last Edit: February 23, 2013, 03:33:30 am by afremont » Logged

Experience, it's what you get when you were expecting something else.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24308
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I glanced (literally five minutes) at the servo library code and it looks like it uses Timer1 initially.  This is a 16 bit counter.  It puts it in ordinary count mode and enables overflow interrupts.  With the prescaler of 8, it should overflow roughly 30.5 times per second.  This would be the update rate to the servo, not 50Hz
I don't have the source to hand to glance at, but I do have a Servo library project and a 'scope.
50Hz, pretty much on the nose.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep, you're right.  I looked thru the code a little more and the library does go to the trouble to dink the Timer for a 20mS period (50Hz).  I commend the author for doing it right.
Logged

Experience, it's what you get when you were expecting something else.

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks alot for all the help. I will look in the servo library and try to use timer1.
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks alot for all the help. I will look in the servo library and try to use timer1.

Your welcome.  Feel free to ask, I spent some time last night getting acquainted with the servo library source code.  It's pretty well done.  I experimented with TImer1 some more and played around with Timer0 to see what kind of impact its ISR was having on other interrupts.  I didn't specifically experiment with PWM modes on Timer1, but I'm pretty sure I could help you get it set up if you want to go that way.  The library is probably the best way to sacrifice Timer1 for the most return.
Logged

Experience, it's what you get when you were expecting something else.

Pages: [1]   Go Up
Jump to: