概要
ロボットでArduinoを使うときに一番多いシチュエーションはPWM信号を出すことです。多くのハードウェアを制御するためには多くのPWMが必要になります。Arduinoで出せるPWMの限界について考えてみます。
PWMとは
PWMとはLow(0)とHigh(1)が交互に変化するいわゆるデジタルな波形です。PWM波形の要素として周波数とデューティー比があります。
PWMの使用方法としてロボットでは主に2つがあり、周期が大きく異なります。
- モーターの制御
モーターに送る電力をPWMで調整します。周波数1k~(周期が~1ms)のPWMを通常は使います。 - サーボモーターへの信号
RCサーボモーター(ホビー界隈でサーボと呼ばれるもの)への信号です。周期が20msで規格化されています。
arduino megaの場合
上記のモーター用とサーボ用の2つのPWMについてどれだけ出せるか検討します。
モーター用のPWMについて
Arduinoについてまとめたページではmegaは15本のPWMが出せると書いてあります。実際Arduinno megaの回路図を見るとP2~13,44~46の15本がPWMのピンに割り当てられています。
しかしこれらすべてがフルに使えるわけではありません。下記のようにタイマーに2、3個のチャンネルがぶら下がって合計15本のPWMになっています。
timer | ch | pin |
---|---|---|
timer0 | A | 13 |
B | 4 | |
timer1 | A | 11 |
B | 12 | |
timer2 | A | 10 |
B | 9 | |
timer3 | A | 5 |
B | 2 | |
C | 3 | |
timer4 | A | 6 |
B | 7 | |
C | 8 | |
timer5 | A | 46 |
B | 45 | |
C | 44 |
一部のtimerはほかの部分で使用されています。
- timer0はシステムが使用していて、これをいじってしまうとdelay()関数の待つ時間がずれます。
- またtimer0,2は8bit timerで残りの1,3,4,5は16bit timerです。8bit timerでは精度が低くて、しっかりしたモーター用のPWMを出すには適しません。
- timer5は後述するservoライブラリを使うと使用されてしまうために使えなくなります。
よってまともに使えるPWMはtimer1,3,4の8本のPWMになります。これらは自由にDuty比を変更することがありますが、周期を変更する場合は注意が必要です。
モーター用PWMの周期について
モーター用PWMの周期はtimerで共有されます。timer1,3,4は全て同じ構成でデフォルトでは490Hzに設定されています。以下のコードでtimer1の速度を変更できます。
#include <avr/io.h>
void change_freq1(int divide){
TCCR1B = (TCCR1B & 0b11111000) | divide;
}
これで以下のようになります。timer3の時はTCCR1BをTCCR3Bに書き直してください。
divide | 周波数 |
---|---|
1 | 31.37 kHz |
2 | 3.921 kHz |
3 | 490.2 Hz |
4 | 122.5 Hz |
5 | 30.64 Hz |
他 | 禁止 |
サーボ用のPWMについて
サーボ用の周期が20msのPWMはservo.hライブラリを使うとPWMのハードウェア機能を直接に使わずにソフトウェア機能で生成することができます。出力するピンはデジタル出力ができるピンならどこでも構いませんが、数に制限があります。PWM出力をする数によってtimerを占有する数が変わります。
PWM出力の数 | 占有するタイマー |
---|---|
0 | 無し |
1~12 | timer5 |
13~24 | timer4,5 |
25~36 | timer3,4,5 |
37~48 | timer1,3,4,5 |
なおArduino Unoだと最大は12個でtimer1を占有します。
またこれらのサーボ用のPWMでは周期を変更することは基本的にできません。また、Duty比の設定の精度が悪く、サーボモーターの出力で言うと1deg相当での分解能しかありません。
参考
Arduinoについてまとめたページ
Arduino megaのPWMのチャンネル
Arduinoにつながるservoの限界について