今回はPICマイコンのPWM機能を使ってLEDの明るさを調整します。PWM機能?前回はLEDをPWM制御して明るさを調整しました。PWM制御ってプログラムで簡単に実現できることがわかりましたよね。ところで、PIC12F1822には「PWM制御」機能が搭載されています。言われても、前回、プログラムを作ってPWM制御した身からすると、何をいってるんだろう、って感じですよね。実は、PICマイコンの「PWM制御」は、ハードウエアで実現するPWM制御のことなんです。プログラムで簡単にPWM制御できるのに、わざわざマイコン側でハードウエア機能として用意するのって、意味がよくわからないですよね。そこで、PWM制御についてもう少し考えてみます。前回作成したPWM制御プログラムの動作は、LEDを点灯して、ちょっと待って、LEDを消灯して、ちょっと待って、、、という処理を繰り返すことによりPWM制御を実現しました。このような方法でソフトウエアによりPWM制御する場合、状況によっては面倒なことが発生します。前回の記事のプログラムで、PWM制御中に何か他の処理をしたい時はどうすればいいでしょうか。PWM制御中に何か他の処理をする、ということは、以下のプログラムのwhileループ内のどこかに処理を追加することになります。}このwhileループ内に、例えば処理に数msかかるようなプログラムを追加したい場合、どこに入れても周期やデューティーサイクルが変わってしまいますよね。変えないようにするには、追加する処理の時間分、__delay_us()関数の待ち時間を変えれば良さそうですが、追加したプログラムが状況に応じて処理時間が変わる場合は解決が難しそうです。この問題をソフトウエアで解決するのは無理がありますので、PWM制御をハードウエアで実現してしまう方がよさそうです。ハードウエアでPWM制御を行うと、ソフトウエアではPWMのパラメータ(周期やデューティーサイクルなど)を設定するだけで、あとはハードウエアが勝手にPWM信号を生成してくれます。このハードウエアで実現するPWM制御が、PIC12F1822によるPWM制御になります。今回の記事では、PIC12F1822のPWM制御機能を使って、LEDの明るさを変えてみます。PiなどのワンボードPCなどでもハードウエアPWM制御機能が実装されています。PICマイコンのPWM機能の概要ところで、PICマイコンのPWM制御機能を使うのは、かなり大変です。理解してしまえば大したことはないのですが、初めて使うときは、嫌がらせではないか、と思われるほどいろいろな用語や設定が出てきます。そこで、詳しい説明をする前に、PICマイコンのPWM制御手順の概要を説明し、その手順と対応づける形で完成したプログラムを見てみます。制御手順の概要と完成したプログラムを確認した後、各項目を細かく説明し、補足が必要な場合は寄り道して補足する、という方法で説明を進めたいと思います。長い説明になると思いますので、自分がどこにいるのか見失わないように読み進めてください。このセクションでは、PICマイコンのPWM制御手順の概要を説明します。ハードウエアによるPWM制御は、PICマイコンのどのピンでも使える、というわけではありません。PWMをハードウエアで実現するためにはPWM制御モジュールを用意する必要がありますが、全てのピンにPWM制御モジュールを実装するのはコストがかかります。そのため、ハードウエアによるPWM制御は、PICマイコンごとにPWM制御モジュール数と割り当てピンに制限があります。PIC12F1822では、PWM制御モジュールの数は1個、また、割り当て可能ピンはRA2ピンかRA5ピンのどちらかになります。RA0ピンとRA1ピンの両方を独立したPWM制御ピンとして使う、ということはできません。PWM機能の割り当てピンは、特定のレジスタを設定することにより行います。0b01011010;」と書きました。このような感じで、特定のレジスタに設定値を代入することによりPWM機能をRA2ピンに割り当てるか、RA5ピンに割り当てるかの設定を行います。PWM機能のピン割り当てを行なったら、次に、PWM信号の周期とデューティサイクルを指定します。この指定は、クロック周波数を元にして、「周期はクロック何個分」「デューティサイクルはクロック何個分」という形で行います。これで、PWM機能のピン割り当てとPWM信号のパラメータを設定しましたので、あとはPWM制御をスタートさせると、PWM機能を割り当てたピンにPWM信号が出力されます。PWM制御スタート後でも、周期とデューティサイクルは変更可能です。まとめておきましょう。最初にPWM機能を割り当てるピンを指定して周期とデューティサイクルの長さを設定してPWM制御をスタートさせるという手順で進めます。なんだこれだけの設定でPWM信号が生成できるのか、と思ってしまいそうですが、おそらく解説を読み進めるとげんなりしてきます。したら休憩を取るなど対策をしてください。それでは次に、この手順に対応づける形で、完成したプログラムを確認します。PWM制御プログラムPWM制御プログラムがどのようになるか確認しておきましょう。以下は、PWM機能をRA5ピンに割り当て、クロック周波数が1MHz、周期が1ms、デューティーサイクルが0.5msの場合のPWM制御部分のプログラムです。先ほどの(1)〜(3)の手順に対応する形でコメントを入れてあります。1;このプログラムを実行すると、ハードウエアのPWM制御モジュールがPWM信号の発生を始めます。このあとは、プログラムで何をしても、その処理とは関係なくPWM信号を発生し続けます。手順としては理解できるけど、実際のプログラムはさっぱり、、、って感じですよね。今回の記事は、このプログラムを理解して、他のPICマイコンでも応用できるようにするのがゴールです。それではこれから、(1)〜(3)まで、各項目の設定方法を詳しく説明します。途中で補足知識も説明しますので、どの部分の説明を読んでいるか常に確認しながら読み進めてください。PWM機能のピン割り当て指定ハードウエアのPWM制御モジュールは数が限られていて、割り当てることのできるピンも限られていることは先ほど説明しました。最初にデータシートから、PWM制御モジュール数と割り当て可能なピンを読み取って見ましょう。ここではPIC12F1822のデータシートを確認しますが、他のPICマイコンのデータシートの読み方も同じです。今後のためにも実際にデータシートを確認しながら進めてみてください。データシートを確認する前に注意点があります。これからPWM機能を設定しますが、データシートには「PWM」という言葉はあまり登場しません。この点がPWM機能設定の理解を難しくしています。他のPICマイコンでPWM制御する場合でも避けられませんので、一通り説明します。最初にPWM制御モジュール数の確認です。Technology社「PIC12F1822データシート」より引用)この表は、PIC12F1822データシートのp.2にある機能リストです。この表には、GPIOピンは何ピンあるのか、メモリはどのぐらいあるのか、などの情報がまとめられています。PWM機能はピンク色の枠で囲んでいる「CCP」または「ECCP」の欄になります。CCP」を意味しています。このように、PWM機能は、Capture機能、Compare機能とセットになっています。PWM機能は、「CCP」または「ECCP」の一つの機能として扱われています。Capture機能、Compare機能についてはこの応用編では説明しませんが、これら3つは同じハードウエアで実現する機能のためにセットになっている、という程度で理解いただければ問題ありません。上の図のピンク色枠の記述を見ると、「ECCP(Full-bridge)」「ECCP(Half-bridge)」「CCP」がそれぞれいくつあるか、という表現になっています。このシリーズて使用しているPIC12F1822は一番上の行で、「0/1/0」と書かれています。これは、「ECCP(Full-bridge)」が0、「ECCP(Half-bridge)」が1個、「CCP」が0という意味です。いうことで、PWMのことを知りたいのに、抱き合わせ商法のような感じで、Capture機能、Compare機能が出てきて、さらにCCP、ECCPが出てきた上に、さらにさらにECCPは2種類、ECCP(Half-bridge)とECCP(Full-bridge)、というように色々な種類が出てきてしまいました。道に迷いそうですが、PWM機能を使う場合、PWMを意味する「P」は「ECCP(Full-bridge)」「ECCP(Half-bridge)」「CCP」いずれにもありますので、どれかが1以上であればPWMは使えることになります。PIC12F1822は「ECCP(Half-bridge)」が1個、ということは、PWM制御モジュールが1個ある、と理解してOKです。これで、PIC12F1822のPWM制御モジュール数が1個であることがわかりました。次に、PWM機能がどのピンに割り当て可能か、です。この仕様はデータシートの次のペーシに書かれています。以下の表はPIC12F1822データシートのp.3に書かれているものです。Technology社「PIC12F1822データシート」より引用)一番左の列がピン名称の列です。ピンク色の枠で囲んだ部分がECCP機能の割り当て列になります。次にこの表を読み解く必要があります。結論としては「CCP1」と書かれているピンがPWM機能割り当て可能ピンになります。「CCP1」と書かれているピンは、RA2ピンとRA5ピンであることがわかりますので、PWM機能割り当て可能ピンは、RA2ピンとRA5ピン、ということがわかります。それでは、この表の読み方を説明します。ECCP欄には、「CCP1」「P1A」「P1B」という文字列があります(「FLT0」はCCPの付随機能のため説明は省略します)。「CCP1」ですが、これは「Capture機能/Compare機能/PWM機能」の意味で、数字は、PWM制御モジュールが複数ある場合には「CCP2」、「CCP3」と数字が増えていきます。PIC12F1822はPWM制御モジュールが1個ですので、CCP1しかありません。この表では「CCP1」はRA2とRA5のところにあるので、PWM機能はRA2かRA5に割り当て可能、ということがわかります。次に「P1A」と「P1B」ですが、これは特定用途に使用されるPWM機能名です。モーターを制御する場合、正転/逆転制御したいケースがあります。この場合、以下のような回路で、モーターを制御します。Technology社「PIC12F1822データシート」より引用)この回路に深入りするとちょっと大変ですので、この回路のポイントのみを説明します。モーターを正転/反転制御する場合は、2つのPWM制御ピンが必要です(4つ必要な場合もあります)。この回路では、PICマイコン側のP1A、P1Bという2つのPWM機能ピンでモーターを制御します。この回路において、P1AでPWM制御する場合とP1BでPWM制御する場合とでは、モーターの回転は逆になります。P1AとP1Bは同時に制御してはいけません(同時にONにすると回路がショートします)。PWM制御モジュールは1個しか使わないけど、モーター制御のように、状況に応じて2つのピンのどちらかをPWM機能として使用したいケースがあります。このようなケースのために、PWM制御をP1A、P1Bの2ピンで使用できるモードも用意されています。ハードウエアのPWM制御モジュールは1個で、それを2ピンのどちらかで排他的に使用する、ということです。P1A、P1Bの2ピンあるから、2つのPWM制御モジュールがある、というわけではありません。上の回路は「ハーフブリッジ(Half-bridge)回路」と呼ばれていて、PWM制御ピンは2ピン必要になります。他に「フルブリッジ(Full-bridge)回路」というものもあり、こちらはPWM制御ピンは4ピン必要になります(PIC12F1822のデータシートp.203に回路図がありますので、ご興味があれば確認してみてください。この後のPWM設定のレジスタで、これらの用語が出てきますが、「CCP1」と「P1A」は同じ意味で解釈して問題ありません。通常のPWM制御として使用する場合は「CCP1」ですが、上のようにHalf-bridge回路で使用する場合は2ピン必要で、そのときの名称は、「CCP1」を「P1A」と呼び、もう1つのピンを「P1B」と呼んでいます。このように「CCP1」と「P1A」は同じ意味になります。それでは、これからPWM機能ピンのプログラムでの指定方法を説明します。PWM機能ピンを指定するには、使用するピンを出力ピンにしておく必要があります。作成している回路では、RA5ピンにLEDを接続して、このピンを出力に設定してありますので(TRISAレジスタ設定)、特にプログラムの変更は必要ありません。PWM機能のピンとして使用するには、以下の設定が必要になります。APFCONレジスタのCCP1SELビットでPWM機能を割り当てるピンを指定CCP1CONレジスタで、CCP1のPWM機能を有効にしてPWM信号タイプを設定それでは最初に「APFCON」レジスタです。以下はPIC12F1822データシートのAPFCONレジスタのページの抜粋です。Technology社「PIC12F1822データシート」p.114より引用・加工)このページの説明にあるように、APFCONレジスタのCCP1SELビットを0にするとRA2ピンが、1にするとRA5ピンがCCP1/P1Aピンになる、と書かれています。PWM制御ですので、このビットでRA2かRA5どちらをPWM制御ピンとして使用するのか指定することになります。今回はRA5ピンをPWM制御ピンにしますので、このCCP1SELビットを1に設定します。0bなんとか;とか書いてしまうと、CCP1SELビット以外のビットを書き換えてしまう可能性があります。そこで、レジスタの特定ビットを設定する方法がありますので、その方法を説明します。この方法はAPFCONレジスタだけではなく、他のすべてのレジスタにも有効な方法です。今後も頻出しますので、是非覚えておきましょう。レジスタの特定ビットを指定したい場合、レジスタ名に「bits.」をつけます(bitsの最後のピリオドを忘れないようにしてください)。「APFCON」レジスタであれば、「APFCONbits.」です。実際にMPLABXのエディタ上で基礎編で作成したmain.cを開いて、適当な場所で「APFCONbits.」と入力してみてください。最後のピリオドを入力すると、以下のようにそのあとの指定可能なビットが表示されたと思います。今回指定するのは、APFCONのCCP1SELビットですので、一番上の「CCP1SEL」を選択した状態でリターンキーを押すと「APFCONbits.CCP1SEL」となります。これは、APFCONレジスタのCCP1SELビット、という意味になります(APFCONレジスタはAPFCONbitsという構造体が定義されていて、この構造体の中に各ビットが定義されています)。基礎編のmain.cは変更しませんので、保存せずに閉じてください。いうことで、RA5ピンをPWM制御ピンとして使用するために、まず、以下のように設定します。Control)で設定します。以下は、データシートのCCP1CONレジスタのページ(p.213)です。Technology社「PIC12F1822データシート」p.213より引用・加工)CCP1CONレジスタは、第7ビット〜第6ビットの「P1M」(図中青色枠)、第5ビット〜第4ビットの「DC1B」、第3ビット〜第0ビットの「CCP1M」(図中ピンク色枠)から構成されています。PWM設定に関わるのは「P1M」と「CCP1M」です。「DC1B」はデューティーサイクル設定で使用しますので、この後のセクションで説明します。PWMタイプは、ピンク色枠の第3ビット〜第0ビット「CCP1M」で設定します。このビットのデフォルトは0b0000で、この値にすると、Capture/Compare/PWM機能はすべてOFFになります。PWMとして使用するには、0b1100〜0b1111のいずれかを設定します。active-high」と書かれています。これは、「PWMモード、P1A、P1B、P1C、P1DピンはすべてアクティブハイのPWM制御」という意味になります。PIC12F1822はP1AとP1Bしかありませんので、P1C、P1Dは無視してOKです。設定内容を一通り確認すると、「active-high」「active-low」の設定があることがわかります。これは、PWM制御でONの期間、「active-high」であれば5Vに、「active-low」であれば0Vにする、という意味です。なんだかややこしいですが、電子回路によってはactive-low制御が必要な場合もあります。今回のLEDの制御は、ONの時に5VにしてLEDを点灯させますので、「active-high」設定になります。P1Aをactive-highにするには、0b1100か0b1101のどちらでもOKです。0b1100を設定することにします。CCP1CONのCCP1Mビットを0b1100に設定しますので、先ほどと同じように、「CCP1CONbits.」と入力します。最後のピリオドを入力すると、設定可能なビットが表示されますので、「CCP1M」を選択してリターンを押します。「CCP1CONbits.CCP1M」と表示されますので、その後に以下のように設定値を書きます。PWM機能を有効にして、PWM信号をactive-highに設定これで、CCP1CONレジスタのCCP1M設定ができました。次に、CCP1CONレジスタのP1Mビットを設定します。P1Mビットは以下のような設定内容になっています。P1AがPWM信号出力。Full-Bridge(反転)ということで、CCP1CONレジスタのP1Mビットは、赤色文字の設定にすればいいことがわかります。P1A、RA2がP1Bになりますので、結局この設定の意味は、「RA5ピンがPWM機能、RA2ピンがGPIO機能」ということになります。RA2ピンはGPIOに設定というプログラムになります。これで、PWM制御モジュールの設定が終わりました。休憩が必要だと思いますので、コーヒーでも飲んで一息入れましょう。次は周期とデューティーサイクルの設定です。次に周期とデューティーサイクルの設定です。これらの設定はPWM信号発生中でも変更することができますので、LEDの明るさやモーターの回転速度を可変制御できます。この記事の最初の方で、周期とデューティーサイクルの設定は「クロック何個分」という設定をする、と説明しましたが、実は素直に何個分、と設定できるわけではありません。今回のプログラムは1MHzで動作させますので、1クロックは1μsです。周期は1msにしたいので、クロックは1000個分になりますが、素直に「1000」という指定ではありません。周期とデューティサイクルの設定も、コーヒーでも飲みながらゆっくり理解を進めることをおすすめします。周期の設定は、「PR2」レジスタで行います。「PR2」レジスタは8ビット、つまり0〜255までの設定になります。このPR2の値を元に、周期は以下の式で決定されます。今回のプログラムは基礎編のmain.cを流用します。基礎編ではクロック周波数は1MHzに設定しました。1秒間に1,000,000個のクロックを発生しています。プリスケーラ値となります。あとは「プリスケーラ値」が何か?ということがわかれば周期が決まります。最初に、上の計算式で「プリスケーラ値」がない場合を考えてみます。1024μsということで、プリスケーラ値がない場合は、周期として設定できる値は、4μs〜1024μs(=約1ms)です。前回、ソフトウエアでPWM制御した場合は、周期を5msにしました。いうことは、上の式では周期を5msにすることができません。このように、1クロック分の時間に比べてある程度長い周期を設定したい場合のために「プリスケーラ値」があります。約5msということで、5msに近い値にすることができます。この場合は、PR2を77、プリスケーラ値は16に設定します。いうことで、周期を設定する場合、PR2の他にプリスケーラ値の設定も必要になります。PR2は単に8ビットのレジスタですので、0〜255の値を代入すればOKです。プリスケーラ値は「T2CON」レジスタのT2CKPSビットで設定します。以下はPIC12F1822データシートのT2CONレジスタのページです。Technology社「PIC12F1822データシート」p.178より引用・加工)T2CONレジスタのT2CKPSビットの設定値は以下の意味になります。64今回は、周期は1msにします。最初に計算したように、プリスケーラが1の場合、設定できる範囲は4μs〜1024μsで1msの設定ができますので、プリスケーラ値は1に設定します。プリスケーラを1:1に設定ということになります。1μsとなるようなPR2を求めると(1次方程式を解けばOKですね)、PR2は249になります。1msということになります。これで周期の設定が終わりました。次はデューティーサイクルです。デューティーサイクルは10ビットで設定します。デューティーサイクルは以下の式になります。あとは10ビットの値をどこに設定すればよいか、ですが、通常のレジスタは8ビットです。そこで、この10ビットの値を上位8ビットと下位2ビットに分けて、それぞれ別のレジスタに設定します。代入するレジスタは以下になります。CCP1CONレジスタのDC1Bビットデューティー比は50%にしますので、デューティーサイクルは0.5ms、つまり500μsです。1μsということで、10ビットの値は500になります。いうことで、500の上位8ビットをCCPR1Lに、下位2ビットをCCP1CONレジスタのDC1Bビット設定することになります。500は2進数ビットでは0b0111110100ですので、以下のようにレジスタに設定することになります。500をわざわざ2進数に変換して、その上位8ビットや下位2ビットを求めるのは面倒ですので、楽な方法でプログラムを書くことにしましょう。上位8ビットの求め方です。2進数表現では、2で割ると1桁右に移動します。右の桁は無くなります。2で割ればもう1桁右に移動します。いうことは、500を4で割れば上位8ビットを取り出すことができます。500/4;と書けばよいことになります。次に、CCP1CONレジスタのDC1Bビットに下位2ビットを設定します。CCP1CONbits.DC1Bに500の下位2ビットを代入すればOKです。500;と書いてしまいましょう。左辺は2ビットですので、右辺が3ビット以上の数字でも、下位2ビットだけが使用されますので、手抜きでこのように書きました。ビルド時の警告が気持ち悪いようでしたら、以下のように下位2ビット以外をマスクすればOKです。0b11;これで周期とデューティーサイクルの設定は終わりました。PWM制御スタートこれで、PWMの設定ができましたので、あとはPWMをスタートさせるだけです。今まで、周期を設定するだけでもかなり大変だったので、PWMをスタートさせるのも大変では、と余計な心配をしてしまいますが、今回は簡単です。PWMをスタートさせるには、T2CONレジスタのTMR2ONを1にするだけです。1;とすればOKです。これでPWM信号が生成され始めます。実際のプログラムそれでは、今までの内容をまとめて、周期1ms、デューティー比50%でLEDをPWM制御してみましょう。前回は、「PWMControl」というプロジェクト名で新規プロジェクトを作成しましたので、今回は「PWMFunction」というプロジェクトで新規プロジェクトを作成しましょう。作成したら、以下のプログラムをコピペしてビルド、書き込み、実行しましょう。return;}PWM制御のまとめPWM制御の設定はかなり複雑ですので、何を設定すればよいかまとめておきます。クロック周波数の設定など、基本的な設定は省略しています。前回は、PWM制御のプログラムを自分で作りましたが、今回はPWM制御モジュールのパラメータを設定して、あとはPWM信号生成をPICマイコンにお任せした、という状態ですので、本当に周期が1ms、デューティーサイクルが0.5msかよくわかりませんよね。LEDの明るさを見ても果たしてデューティー比が50%なのか、自信がないでよすね。そこで、基礎編で作成したブレッドボードと上のプログラムを使用して、RA5ピンの波形を確認しました。以下の図はRA5ピンの電圧をオシロスコープ(電圧の波形の計測器)で観測した結果です。横軸が時間で1目盛1ms、縦軸が電圧で1目盛2Vです。1ms周期の約5Vの信号が生成されているのがわかると思います。デューティー比は50%っぽいです。このオシロスコープは自動的に時間幅を測ってくれる機能があるので測ってみました。1.000kHz」とありますので指定通りです。デューティサイクル(Width)も「500us」とありますのでこちらも指定通りです。PWM制御スタート、という手順でOKですが、かなり大変ですよね。他のPICマイコンも同様の指定方法ですので、PIC12F1822がマスターできれば他のPICマイコンでも問題なく使えるようになると思います。他のマイコンも同じような感じの設定になりますので、是非PWM制御に慣れてみてください。