前回はデジタル入出力のお話をしましたが、今回は疑似アナログ出力ともいわれるPWMの出力を紹介します。PWMと言ってもなにかわからないかもしれないので、まずは、PWMがどんなものであるかをお見せしましょう。
1
この図の波形は電圧の波形を示しています。PWMというのはこのようにONOFFを高速で繰り返して、疑似的にアナログ出力を行おうとするものです。出力電圧は以下の式で表せます。

Vin:入力電圧[V]

Vout:出力電圧[V]

T:PWM周期[s]

t:ON時間[s]

Vout=Vin×(t/T)

つまり、ONの時間とOFFの時間の割合を調整して、0Vから入力電圧の範囲でいろいろな電圧を作り出せるというわけです。そして、PWM周期とON時間の比をデューティー比と言います。

そして、モータを演奏するうえでは非常に有用なのがPWM周期です。PWM周期が短くなると高い音周波数が高い音)が出て、PWM周期が短くなると低い音周波数が低い音)なります。ちなみに、周期から周波数は以下の式で変換できます。

f:PWM周波数[Hz]

f = 1/T

この式より、PWM周期が大きいとPWM周波数が低くなり低い音が、PWM周期が小さいとPWM周波数が高くなり高い音が出ることがよくわかると思います。つまり、モータ演奏はこのPWM周波数を調整して音色を演奏するというわけです。この章では、PWMの出力方法はもちろん、PWMの周波数の変更方法も紹介していきます。

 

マイコンのタイマーの動作

マイコンのPWM出力はArudinoでいうdelay()のようなものを使って、手動でONOFFを繰り返して出力するものではありません。マイコンのPWMはマイコン内部に搭載されているタイマーと呼ばれる機能を使って、波形を生成しています。

今回使用している「atmega328P」の場合はタイマーが3つ搭載されており、内部の最大カウントが8ビット(255)の8ビットタイマーが2つ、最大カウントが16ビット(65535)16ビットタイマーが1つ搭載されています。それぞれのタイマーで出せる周波数やデューティー比の精度が大幅に変わってきます。(もちろん16ビットタイマーの方が精度を出しやすい)

話ばかりでは、分からないと思うので、実際にマイコンのタイマーがどのようなものであるかをデータシート(https://avr.jp/user/DS/PDF/mega328P.pdf )から見てみましょう。データシートの89ページからタイマーについて書かれているページがあります。

はじめにタイマー全体の概要を紹介するために例として、高速PWM動作を使ってみます。
2

マイコンのタイマーは、内部的に図の→で示したようなのこぎり波を描くカウンタがあります。時間(CPUのクロック数)に応じてこのカウンタの値が変化し、こののこぎり波と閾値を比較してPWMの波形を生成しています。CPUのクロック数に応じてPWMの波形を生成しているため、一定で正確なPWM周波数とデューティー比を出力できるというわけです。PWMは図で示したように、のこぎり波の値が閾値より小さい時ON状態になっていて、閾値より大きい時にOFF状態となってことがわかります。

マイコンでは、この上下する波形の形や、最大高さ傾き変更することができます。これらの変化させることで、生成するPWMの周波数を変更することができます。ここからは、波形の形、最大高さ、傾きによりPWM周波数が変えれることを紹介していきます。

 

波形の形

波形の形は2種類あり、先ほど示したようなカウンタが最大値となると0に戻るのこぎり波を描くタイプと、カウンタが最大値になると値が降下し始める三角波を描くタイプの2種類があります。この2種類の波形は動作種別により設定ができます。前者のタイプの波形は「高速PWM動作」を選んだ場合に生成され、後者のタイプの波形は「位相基準PWM動作」または「位相/周波数基準PWM」を選んだ場合に生成されます。

傾きと最大高さが同じ場合に、PWMの出力波形がどのようになるかを図示してみます。
3

この波形の図からもわかるように、のこぎり波を生成する「高速PWM動作」で生成されるPWM周波数は、三角波を生成する「位相基準動作」「位相/周波数基準動作」(位相/周波数基準動作はタイマー1のみ)で生成されるPWM周波数の約2倍の周波数になっていることがわかります。(約とつけたのは、完全な2倍ではないため)これによって、PWM周波数を2倍に変化させることはできますが、これだけでは音色を奏でることはできません。 そのため、ほかのテクニックを組み合わせる必要があります。

また、データシートの「位相基準動作」のページを確認すると、「位相/周波数基準動作」が使えるタイマー1の場合はTOP(波の最大高さ)を変更する場合は、「位相/周波数基準動作の使用を推奨する」と書かれています。そのため、今回使用する動作種別は「高速PWM動作」と、「位相/周波数基準動作」(タイマー1)or「位相基準動作」(タイマー0,1)をタイマーに応じて使い分け、各波形ごとに1種類の種別を使うことにします。

 

波の最大高さ

先ほどは、波の形を変えて周波数を変化させようとしましたが、今度は波の最大値(高さ)を変化させてPWM周波数を変化させる方法を紹介します。

傾きが同じ場合に最大値を変化させると生成される周波数が変化するというわけですが、言葉ではわかりにくいと思うので、どのようになるのかを図示してみます。
3

この図から、傾きが同じでも波の高さを高くすればPWM周波数は低くなり、高さを低くすればPWM周波数が高くなることがわかります。これより、PWMの周波数は波の高さに反比例することがわかると思います。

 波の最大高さの設定は、PWMの出力の設定によって可否が変わります。周波数を可変するPWMを生成する場合は、最大値が固定ではなくレジスタで設定できるものを選びます。(可変しない場合はTOP値0xFF(255)のものを選ぶ)8ビットタイマーである「タイマー0」と「タイマー2」の場合は波の最大高さはOCR0A」、「OCR2A」のレジスタで設定できます。また、16ビットタイマーである「タイマー1」の場合は波の最大高さを「ICR1」かOCR1Aで設定できますが、PWM周波数を頻繁に変える場合「ICR1」を使うと正しく動作しません。(データシートによると「ICR1」を変更する際に2重緩衝がされないため、条件によって正しく動作なると書かれており、波の高さを変更する場合は「OCR1A」の利用を推奨すると書かれています。筆者の環境で「ICR1」で周波数可変を試しましたが、正しく音が出ないときが発生しました。)そのため、波の高さを変える(周波数を変える)場合に使える波の最大値(TOP値)の設定レジスタは「OCR*Aとなります。

 次に、各タイマーで使える波の高さの最大値について紹介します。設定できる波の高さの最大値は8ビットタイマー(タイマー0,2)と16ビットタイマー(タイマー1)で大きく違うことに注意しなければなりません。 

8ビットタイマーはその名の通り、内部処理を8ビットで行っています。そのため、設定できる波の高さの最大値も8ビットで表せる数に限られます。つまり、最大値は255(2^8-1)というわけです。また、PWMを生成するにあたって波の高さが最低2は必要(最大高さ1以下だと、閾値との比較ができずPWMとして成立しない)です。そのため、原理上設定できる波の高さは2255というわけです。しかし、波の高さが低いとduty比の変更が困難になってくるので、実質的に使用できる波の高さの最低値は20~30程度として、実使用においての波の高さの範囲は30255となります。

16ビットタイマーの場合は内部処理が16ビットで行われているので波の最大高さは65,535となり、実質的に波の高さとして設定できるのは20~65,535となります。そのため、周波数の設定の自由度は圧倒的に16ビットタイマーの方が高いというわけです。

 

波の傾き

 波の形や高さを変えて周波数を変化させる方法以外にも波の傾きを変更して周波数を変更する方法を紹介しましたが、次は波の傾きを変えて周波数を変更する方法を紹介します。先ほどまでの方法に比べると直感的にもわかりやすいとは思いますが、今回も図示してみます。5

 この図から、傾きを小さくするとPWM周波数が低くなり、傾きを大きくするとPWM周波数が高くなることがわかります。これより、PWMの周波数は波の傾きからも変更できることが明らかですね。

 AVRマイコンではタイマーの波の傾きは、マイコンに接続されている水晶発振子の周波数をもとに決められています。ですが、プログラム上からは水晶発振子の周波数を変更することは基本的にできません。そのため、タイマーには分周器という水晶が一定の回数発振したら、カウントを1つ進めるという機能が搭載されています。この分周器の設定を変更することによりタイマーのカウンタの傾きを変更できるというわけです。それでは分周器を使った場合のタイマーの波形のイメージを実際に図示してみましょう。
7

分周のイメージとしては、このような感じのイメージになっています。(実際の動作とはちょっと違うかもしれないけど)つまり、分周をした分だけ傾きが小さくなります。図で示した8分周の場合は傾きが1/8になり、結果として出力される周波数も1/8となります。

分周器で設定できる分周はタイマーごとに決められており、Atmega328Pの場合設定できる分周は以下の通りです。
8

このようにいくつかの決められた分周の中から選択をすることで大まかな、周波数を決めることができます。また、外部からクロックを与えることでPWMを生成することも可能です。(ここでは紹介しません)

 

出力周波数の設計

先ほどまでは、PWMの理論と周波数を変える理論の紹介を行いましたが、次は実際に周波数を変えるためのパラメータの決定を行っていきたいと思います。設計の手順としては

波の形→波の傾き→波の高さ

で設計を行います。

初めに、波の形を決めます。のこぎり波の高速PWM動作三角波の位相基準動作(タイマー0,2)位相/周波数基準操作(タイマー1)のどちらかから選びます。特に理由がなければ三角波を選んでおけばよいでしょう。なお、ここで選ぶ波形によって使用する数式が変わるので注意が必要です。波の形を決めたら、周波数とパラメータの関係の数式からパラメータ選定を行います。データシートから出力周波数は以下の式で表せることがわかります。

9
初めに、この式に変形して以下のようにします。

10
そして、この式に、出力したいPWM周波数とシステムクロック(水晶の周波数)、そして適当な分周の値(8ビットタイマーで可聴周波数の場合は64分周程度を推奨)を代入して、TOP値を計算します。TOP値の計算結果が255(8ビットタイマーであるタイマー0,2),65535(16ビットタイマーであるタイマー1)を超えた場合分周の値を大きくします。逆にTOP値の計算結果が30を下回った場合分周の値を小さくします。分周の値を決めて、この式で計算したTOP値を波の高さとして設定すれば、出力したい周波数のPWMを出力することができます。

PS. 16ビットタイマーの場合でもTOP値が大きくなると扱いにくい場合は、必要に応じて分周の値を大きくしてください。

 

以上で任意の周波数のPWMを生成するための設定のパラメータは求まりました。次回は実際にプログラムに入力する方法を紹介します。