ATMELのマニュアルは大変参考になります
日本語ではgarretlabさんのanalogWrite()の項目が体系的にまとめられています.
基本的にはそちらを見ていただいた方がいいと思います.
以下は自分のための覚え書きです.
とにかく一度動かしたい方はこちら
前置き
ArduinoはPWM出力を持っていますが, この周波数は5番, 6番Pinは977Hz, 9番,10番PINは490Hz, 3番,11番PINも490Hzです.
Arduinoの内部で3つの独立したタイマからPWM生成の設定をしており,それぞれ
5番と6番, 9番と10番, 3番と11番ピンに対応しています.
例えば
analogWrite(NPIN,100);
でNPIN=5とした時の波形を図1, NPIN=9とした時の波形を図2に示します.
オシロが周波数を表示してくれてますが, 確かに976Hzと490Hzになっていることがわかります.
図1 5番PINから出力したPWM波形 |
図2 13番PINから出力したPWM波形 |
(PWM波形生成の設定が異なっていたり, 9, 10番ピンは16ビットカウンタだったりします)
このため少し話がごちゃごちゃします.
以下それぞれの設定項目についてマニュアル[1]参照ページを記入したので, 必要に応じて参照してください. (読みが違っていたらごめんなさい, お気づきの点はご指摘ください.)
5番,6番ピンはFAST PWMモードで動いているため
周波数f(Hz)はクロック周波数fc(Hz), 分周比rを使って
f=fc/(256*r)
9,10番ピンは Phase Correct PWMモードで動いていて
f=fc/(256*r)
とかけます[1: p. 102].
rはTCCR0Bの下位3ビットを使って指定して
1,8,64,256,1024の中から選びます.
1,8,64,256,1024の中から選びます.
イニシャルは64が設定されています.
クロック周波数は16MHzですので, PWM周波数は977Hzになります.
(注) なお, Arduinoは5, 6番ピンが使用しているカウンタをもとに時間を管理しています.
従って5, 6番ピンのPWM周波数をあげるとdelay()などの挙動が変わってきます.
たんにPWM周波数を向上させたい場合は5, 6番ピンの設定を変えないほうが無難です.
クロック周波数は16MHzですので, PWM周波数は977Hzになります.
(注) なお, Arduinoは5, 6番ピンが使用しているカウンタをもとに時間を管理しています.
従って5, 6番ピンのPWM周波数をあげるとdelay()などの挙動が変わってきます.
たんにPWM周波数を向上させたい場合は5, 6番ピンの設定を変えないほうが無難です.
9,10番ピンは Phase Correct PWMモードで動いていて
周波数f(Hz)はクロック周波数fc(Hz), 分周比r, カウントビットTOPを使って
f=fc/(2*TOP*r)
f=fc/(2*TOP*r)
とかけます[1: p. 130].
TOPはイニシャルで255です.
rはTCCR1Bの下位3ビットを使って指定して
1,8,64,256,1024の中から選びます
rはTCCR1Bの下位3ビットを使って指定して
1,8,64,256,1024の中から選びます
イニシャルは64が設定されています.
クロック周波数は16MHzですので, PWM周波数は409.2Hzになります.
クロック周波数は16MHzですので, PWM周波数は409.2Hzになります.
3, 13番ピンは
周波数f(Hz)はクロック周波数fc(Hz), カウンタのビット数nと分周比rを使って
とかけます[1: p. 153].
rはTCCR2Bの下位3ビットを使って指定して
1,8,32, 64,128,256,1024の中から選びます. イニシャルは64が設定されています.
クロック周波数は16MHzですので, PWM周波数は409.2Hzになります.
具体的な方法
やっと本題ですが, PWM周波数を高周波化したい時は, 分周比rを変更しますこの変更はTCCR*B(*は5番, 6番ピンは0, 9番, 10番ピンは1, 3番, 13番ピンは2です)
の下位3ビットで行います.
それぞれにはCS*2, CS*1, CS*0と名前がついています(*は0~2で前述と同じ).
TCCR0B(5,6番ピン) については[1]の110ページ 表14-9を参照
r=1 は001
r=8 は010
r=64 は 011
r=256は 100
r=1024は 101
です.
例えば
Serial.println(TCCR0B,BIN);
と現状の設定をシリアルモニタで確認すると
11と帰ってくると思います.
変更する場合のプログラム記述はsetup関数内で
setup(){例えば
Serial.println(TCCR0B,BIN);
と現状の設定をシリアルモニタで確認すると
11と帰ってくると思います.
変更する場合のプログラム記述はsetup関数内で
TCCR0B &= B11111000;
TCCR0B |= B00000010;// r=8の場合
}
と記述すればOKです.
TCCR1B(9,10番ピン)については[1]の137ページ 表15-5を参照
r=1 は001
r=8 は010
r=64 は 011
r=256は 100
r=1024は 101
です.
です.
TCCR2B(3,11番ピン)については[1]の162ページ 表17-9を参照
r=1 は001
r=8 は010
r=32は011
r=8 は010
r=32は011
r=64 は 100
r=128は101
r=128は101
r=256は 110
r=1024は 111
です.
前出の2つと割当が違うので注意が必要です.
最後に例として9ピンの周波数をかえてみます.
rを1として, 前述の式
f=fc/(2*TOP*r)
より31.37kHとなるはずです.
void setup(){ TCCR1B &= B11111000; TCCR1B |= B00000001;//rを1に設定 fc/(2*255*1)Hzになる pinMode(9, OUTPUT); } void loop(){ analogWrite(9,100); }と簡単なプログラムの結果を図3にのせます
図3 9番ピンで分周比を1とした場合 |
周波数は31.36kHzとほぼ想定通りの値になっています.
[1] ATmega48PA/88PA/168PA/328Pマニュアル
キーワード
Arduino PWM 周波数 高周波化
1 件のコメント:
T1の設定を変えるとT2のPWM Freq.も変わるので注意が必要。
例
// T0 is used for mills timer in Arduino all time, Can not touch Timer0.
// T1 is used for Propo_Pulse_Width_Counting.
TIMSK1 = 0; // T1, no overflow interrupt
TCCR1A = 0; // T1, normal operation simple count-up timer mode
TCCR1B = 2; // T1 runs 1/8 clock(2MHz)
これでT2はメロメロ。
コメントを投稿