HOME >> 鉄道模型実験室 > Arduino Nano Every のPWM周波数をアップする
先回の報告「卓上レイアウトで楽しもう 自動運転 その23」(2020/3/1)で、PWM制御によって当初の狙いどうりの制御を実施することが出来ましたので、次の課題に取り組みました。 それは、PWM制御の周波数が約 1KHz と低いため、動きがぎごちなく感じられますし、ピーという音も気になりますので、このPWM周波数を20KHz近くまでアップさせることに挑戦しました。 結果はうまく行きましたが、新たな問題も出てきました。
■ PWM周波数について
ご存知のように、PWM制御はON/OFFによるスイッチング機能によって、モータなどへの給電を制御しています。 この時のスイッチング周波数が人間の可聴域にあると、ピーという音が聞こえてきます。 従って一般的にはこの可聴域を避けたシステムにする必要があります。 しかし、技術的に難しい電車等ののモータ制御は例外です。
本当に、どこまでの周波数が聞こえてくるのか調べてみましょう。 道具はスマホにダウンロードしたアプリを使用します。
このアプリを使って、自分の可聴域をチェックすると、なんと、8,000HZ を越える辺りから聞こえなくなってしまいました・・・・・・・・・(;_;) 参考画面を見ると年齢と共に低下する様子が案内されていましたが、もうすぐ80になる小生には、妥当な数字の様でした。
今年の正月に孫たちが集まった時、何故だかこの可聴域が話題となり、中学・高校の孫たちは 20KHz 近くまで聞こえており、40〜50代の大人たちは15KHz 程度までで、自分は 10KHz 以下でありました。 このため、PWM周波数のアップは、10KHz以上を目標とすることにしましょう。
■ 給電制御での周波数アップの方法は?
自動運転では、速度制御のためにPWM制御が欠かせません。 このため、20KHz 程度の高周波PWM制御を実施する方法を考えてみました。
■ Arduino Nano Every で挑戦する
ます、ネットで情報を集めましたが、なかなか見つかりませんでした。 石が異なると指示方法が異なるので、Everyに関する情報を探りました。 そして、Arduino 関係のページで Topic: Nano Every PWM frequency を見つけましたが、内容はやっぱり理解出来ませんでした。 ただ、関係するタイマーはTCA とTCB があるらしいことがわかり、
タイマーはTCAを触ると時間に関する命令が影響されるので注意せよとのことでした。
そこで、PWM制御の設定方法は、PICマイコンの場合と基本的には同じであろうと睨んで、Nano Every のチップである ATmega4809 の仕様書を睨んでいました。 内蔵するタイマーにはいくつかあるのですが、5個のPWM制御ポートにつながっているタイマーはTCA でした。 そこで、タイマーTCAを中心に探していると、下のようなページを見つけました。 タイマー/カウンタのプリスケーラ設定倍率を指定するレジスタです。
そこで、このレジスターの値を変えてやればPWM周波数も変更できるのではないかと考えましたが、さて、どうやってArduino に命令するのか、その方法に悩みました。 さる資料では、cbi( ) とか sbi( ) などの命令でビット操作が出来ると書いてあったので試してみましたが、ケッチンを食らってしまいました。 なにやらのライブラリーを読み込んでおく必要があるようですが、何を読み込むのか分かりません。 しかし、上記の参考サイトで見た記述方法をいろいろ試してみました。
TCA0.SINGLE.CTRLA = 0x2 ;
コンパイルをかけてみると、なんと通ってしまいました。 たったこの一行の命令で指定できるのだ!
.
そこで、0ビットのENABLE指定も含めた値を入力して、プリスケーラの設定倍率を指定することにしました。
TCA0.SINGLE.CTRLA = 0b0101 ;
ENABLE指定ビットは常に1に設定します。
■ 実際のPWM出力波形を観察しよう
そこで、実際のPWM出力波形を観察して、指定倍率と周波数の関係を確認することにしました。 実験装置は、右の写真に示すように、予備のNano Every を使い、出力ポートの波形をオシロで直接観察しました。
■ 観察結果
まず、追加記述の無いオリジナル状態を上記の記述を追加した状態を見てみましょう。 使用したスケッチ ⇒ Every-Test-10
追加記述なし(オリジナル状態) | TCA0.SINGLE.CTRLA = 0b0101 |
---|---|
周波数 = 983 Hz |
周波数 = 15.7 KHz |
周波数は、見事にアップしている事が分かります。 そこで数値を変えて周波数を読み取って行き、その結果を表にまとめました。
Value | Name | 指定した数値 | 周波数 | 倍率 |
---|---|---|---|---|
0x0 | DIV1 | 0b0001 | 62.9KHz | 1 |
0x1 | DIV2 | 0b0011 | 31.4KHz | 2.0 |
0x2 | DIV4 | 0b0101 | 15.7KHz | 4.0 |
0x3 | DIV8 | 0b0111 | 7.86KHz | 8.0 |
0x4 | DIV16 | 0b1001 | 3.93KHz | 16.0 |
0x5 | DIV64 | 0b1011 | 983Hz | 64.0 |
0x6 | DIV256 | 0b1101 | 246Hz | 256 |
0x7 | DIV1024 | 0b1111 | 61.4Hz | 1024 |
さすがにコンピュータは正確ですね。目標とする 20KHz にするには、他の項目をいじる必要がありますので、DIV4 の15.7KHz で良しとしましょう。
● 他のポートとの同期具合は?
この実験は、二つのポートに出力させて、波形を観察しました。 使用したスケッチ ⇒ Every-Test-11
D10とD9 | D10とD3 |
---|---|
ピッタリ一致しています。 |
ピッタリ一致しています。 |
D6やD5ポートの場合の問題無く、ピタリと一致していました。
● 遅延時間関数への影響は?
タイマーのTCA を触っていますので、時間に関する delay( ) 関数の数値を指定して、実際の時間をオシロで観察しました。 数値を指定してパルスをON/OFFさせました。 使用したスケッチ ⇒ Every-Test-12
delay(1000)を指定 | delay(100)を指定 |
---|---|
パルスの間隔は 62msec |
パルスの間隔は 6.2msec |
即ち、1000/62 ≒ 16、100/6.2 ≒ 16 であるので、delay() 関数は16倍して指定する必要がでてきました。 なお、オシロで表示された周波数は休止時間があるため、半分の周波数になったものと解釈しています。
■ 実際の卓上レイアウトで確認しましたが、新の問題が発生しました。
出来た!出来た! と喜んで実際の卓上レイアウト上のプログラムに適応してみました。 先回のスケッチにたった一行を追加しただけですが、思わに問題に突き当た手しまいました。
コアレスモータの動力車はスムースに動くのに、Bトレ電車は動かない!
えーー !?????・・・・・・・・? ダイヤルまわしてデューティ比を上げると、電車は脱兎のごとく生きよい良く飛び出していきますが・・・。
1KHz では問題無く走ったのに、16KHz では動かないのはなぜなの?
これまた、不思議な現象に出くわしました。 まだ、その原因が分からないのですが、オシロで波形を見た限り、疑問点がいくつかありました。 ネット情報で調べた限りでは、「A4953ELJの波形調査」と同じような現象が起きているのではないかと考えています。
この件に関しては、自分なりに色々実験してみることにして、とりあえず、Arduino Nano Every のPWM周波数をアップ出来た事を報告しておきます。
2020/3/3 作成