ArduinoのPWM周波数を変更したいので調べてみました.
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端子ですが,この3系統は内部処理や設定が異なっていることがポイントと思います.
(PWM波形生成の設定が異なっていたり, 9, 10番ピンは16ビットカウンタだったりします)
このため少し話がごちゃごちゃします.
以下それぞれの設定項目についてマニュアル[1]参照ページを記入したので, 必要に応じて参照してください. (読みが違っていたらごめんなさい, お気づきの点はご指摘ください.)
5番,6番ピンはFAST PWMモードで動いているため
f=fc/(256*r)
1,8,64,256,1024の中から選びます.
クロック周波数は16MHzですので, PWM周波数は977Hzになります.
(注) なお, Arduinoは5, 6番ピンが使用しているカウンタをもとに時間を管理しています.
従って5, 6番ピンのPWM周波数をあげるとdelay()などの挙動が変わってきます.
たんにPWM周波数を向上させたい場合は5, 6番ピンの設定を変えないほうが無難です.
9,10番ピンは Phase Correct PWMモードで動いていて
f=fc/(2*TOP*r)
rはTCCR1Bの下位3ビットを使って指定して
1,8,64,256,1024の中から選びます
クロック周波数は16MHzですので, PWM周波数は409.2Hzになります.
f=fc/(510*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
例えば
Serial.println(TCCR0B,BIN);
と現状の設定をシリアルモニタで確認すると
11と帰ってくると思います.
変更する場合のプログラム記述はsetup関数内で
setup(){
TCCR0B &= B11111000;
TCCR0B |= B00000010;// r=8の場合
}
と記述すればOKです.
TCCR1B(9,10番ピン)については[1]の137ページ 表15-5を参照
r=1 は001
r=8 は010
です.
TCCR2B(3,11番ピン)については[1]の162ページ 表17-9を参照
r=8 は010
r=32は011
r=128は101
最後に例として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とした場合 |
波形は1V程度のオーバーシュートが見えますが,
周波数は31.36kHzとほぼ想定通りの値になっています.
参考文献
[1] ATmega48PA/88PA/168PA/328Pマニュアル
キーワード
Arduino PWM 周波数 高周波化
コメント
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はメロメロ。