PIC16F887によるラジコンアンプカッコカリ
僕が大学の部活で作ったラジコンアンプカッコカリについて記します。
まず、何をするものかですが、図1を見てください。右下のターミナルが電源in、奥のアルミコンがついている側のターミナル2つへプロポ受信機をつなぎます。左がDC5[V],右が信号入力です。その入力信号を中央のPICマイコンで読み取り、手前左側のターミナルからMOSFETで増幅したPWM信号を出力するものです。
図1
回路的にはアナログ的な部分はないため非常に簡単です。問題はマイコンのプログラムでした。ここからそのプログラムについて記します。
まず、開発環境はMicrochipのMPLABX、プログラム言語はアセンブラを使用していることを最初に示しておきます。
さて、プログラムを書くにあたって、プロポの受信機からどんな信号が出てくるのか知らないと始まりませんね。これはプロポを購入して、オシロスコープにつなげば一発なのですが、そもそもプロポ高いんですよね。まぁ大体、パルスオン幅が1.0[ms]~2.0[ms]の間で出力されるようです。中点は1.5[ms]あたりです。(プロポメーカーによって変化します)まぁ、多少ずれていたとしてもプロポ本体にアジャスト機能がついていますので、まぁ、多少はね?
以上のことから、1.0[ms]~2.0[ms]をカウントし、1.5[ms]ならOFF、2.0[ms]ならPWMON時duty100%近くとなるようなプログラムにしておけば良いとわかります。
具体的なプログラムは実物を見てもらうのが(アセンブラ読める方なら)きっと一番早いと思いますので、後々アップロードしておきます。
次にプログラムの簡単な流れを記します。まず、TIMER1をプリスケーラー1/8にて使用します。PICのTIMERではメインクロックを使用しカウントアップする場合、メインクロックの1/4の周波数となりますので注意してください。今回は内部発信、4[Mhz]に設定したため、TIMER1のカウントアップ速度は4/4=1[MHz]となります。これにプリスケーラーが加わり、1/8=0.125[Mhz]となるように設定をします。
次にCCP1モードをCaptureモードで毎回のエッジ立ち上がり検出モードにセットします。これで、CCP1ピンがlow→highになった瞬間のTIMER1の値がCCPR1L、CCPR1Hレジスタにそれぞれ保存されます。なぜレジスタが2つあるのかというと、TIMER1は16bitタイマーです。しかしPICがあつかえる数は8bitしかありませんからレジスタを2つ使うことで16bitを表します。CCPR1Lが下位8bit、CCPR1Hが上位8bitとなります。そして、そのレジスタに保存されたTIMER1の時間は次の書き込み時には消えてしまいますから、検出された瞬間に別のレジスタ(任意の定数レジスタを定義しておく)に代入しなおす必要があります。
さて、ここでlow→highが読めました。次にhigh→lowを読み取ります。
そのため、まずCCP1モードをCaptureモードで毎回のエッジ立下り検出モードにセットします。そのあとの動作は立ち上がり時と同じです。
これでパルスの立ち上がり時と立下り時のTIMERの値をレジスタにコピーすることができます。ここで、
立下り時間ー立ち上がり時間=パルスオン時間
とどのくらいの長さのパルス信号が入力されているかを計算できます。具体的にレジスタで示すと、パルス立ち上がり時、
CCPR1L=cap1l
CCPR1H=cap1h
と代入しているとして、パルス立下り時、
CCPR1L=cap2l
CCPR1H=cap2h
と代入しているとします。
するとパルスオン時間の計算は、
cap2h-cap1h (上位8ビット)
cap2l=cap1l (下位8ビット)
として計算できます。ですが、今回はこのパルスオン時間をPWMオン時間に代入したいので、8bit以上は扱いたくないわけです。どうするかというと、TIMER1を8bit分でオーバーフローさせます。具体的には、TMR1Hという、TIMER1の上位8bitのレジスタに初めから2進数で表すと[11111111](2)という数を代入しておくことです。すると、TMR1Lレジスタで8bit分カウントが進み切るとTMR1Hレジスタを1あげようとしますが、すでに満員のためTMRレジスタはオーバーフローし、0に戻ります。このとき割り込みが発生します。この割り込みで再びTMR1Hレジスタに8bit満タンの数値を代入してやればオーバーフロー後も8bitTIMERとして動かすことができます。
そうかんがえると、CCPR1Hは常に[11111111](2)となるため、パルスオン幅計算時には考えなくてよくなります。つまり、
パルスオン時間=cap2l-cap1l
と求めることが可能になります。
これは8bitの値であるとわかるため、あとは求めたパルスオン時間をPWMのパルスオン幅のレジスタである、CCPR2Lへ代入してやればよいとわかります。
さて、ここまでで大体のプログラムの流れを説明しました。ここからはTIMERのプリスケールや、内臓クロックの設定条件について記します。
今回のTIMERを使う目的は入力パルスのオン時間を計算するためです。つまり、1[ms]~2[ms]という時間を計測できるような設定にしなければいけません。計算をしてみましょう。計算では簡略化のため、1(m)*2(u)=2(p)のように10^-3などを()にいれて表します。
まず、TIMER1を8bitカウンタとして使用するため、最大値は255となりますから、1カウントするときの時間を t とおき、カウント最大時間を tmax とおくと、
t * 255 = tmax
となります。今回 tmax = 2(m)となるのが理想ですから、
t * 255 = 2(m)
2(m) / 255 = t
t = 7.84(u)
となります。また、内臓クロック4[MHz]としておくと、TIMER1のプリスケーラー1の時のカウントアップ時間 t' は
t' = 4(m) / 4 / 1
t' = 1(m)
と、1[MHz]、1[us]となります。今回必要な t は7.84[us]のため、
t = t' / 7.84
であるとわかります。ここでマイコンのdataseetsを眺めるとプリスケーラーの設定は
1/1
1/2
1/4
1/8
が選択できると書いてありますから、7.84に近い、1/8(8分の1の速度にする設定)を選びます。そうすると、t の計算は、
t = 4(m) / 4 / 8 = 0.125(m)
つまり125[KHz]、8[us]となります。よって
tmax = t * 255
より
tmax = 8(u) * 255
tmax = 2.04(m)
つまり2.04[ms]までカウント可能になります。これなら tmax は想定の範囲内ですから、問題なしです。TIMER1はプリスケーラーの選択肢が少ないため、内臓クロックを上げてしまうと tmax が 2[ms]まで上げられなくなります。これの兼ね合いを考え、4[MHz]を選択しました。
大体の流れはこのような感じです。次回はPWMオン幅の変化量拡大について記します。
追記:https://onedrive.live.com/redir?resid=D2EBC92A2E5D44CE!16907&authkey=!AG21FbiQhjGKYAg&ithint=folder%2casm
プログラムのasmファイルとhexファイルです。
0コメント