1.はじめに
以前に製作しましたサーボテスターですが、サーボモーターの動作確認には結構便利に使えたのですが、ボリュームを使っていたので正確なパルス幅を設定することや出力しているパルス幅の値を確認することが出来ませんでした。 またパルス周期も標準の20msec固定です。最近のサーボモータはデジタル式のものも増えておりパルス周期は20msecでなくても問題なく動くようです。 そこで、パルス幅やパルス周期を正確に可変出来るとともに現在の設定値をディスプレーに表示するテスター(改良版)を製作しました。 パルス幅やパルス周期の設定には、ボリュームではなくロータリーエンコーダーを採用しました。設定値の表示には有機ELディスプレーを使いました。マイコンは、PIC32MX12F032Bです。 主なパーツは以下の通りです。
![]() 右の写真のようにDCジャックに+5VのACアダプタを接続し基板上のSVGの出力ピンにテストしたいサーボモーターを接続します。この状態で基板上のロータリーエンコーダを左右に廻すとそれに応じてサーボモータが回転します。 電源を入れた直後は、パルス幅は1500μsec、パルス周期は20msecとなっています。エンコーダーのつまみを押し込む毎に、パルス幅とパルス周期の設定を切り替えることが出来ます。 パルス幅を設定している時は、青色のLEDが点灯するとともにディスプレーのパルス幅の表示が大きくなります。パルス周期の設定中は、LEDが消灯しディスプレーのパルス周期の表示が大きくなります。
エンコーダーをゆっくり回転させるとパルス幅は2μsec単位で増減します。早く回転させると回転に応じて大きく増減します。パルス周期の場合には1msec単位で増減します。 3.回 路 マイコンにPIC32MXを採用しましたのでサーボモーター用の電源+5Vから3.3Vを作成する電源レギュレータ回路を設けました。 ロータリーエンコーダーの出力ピンには、2KΩのプルアップ抵抗と1μFのセラミックコンデンサを接続しています。コンデンサはエンコーダ内部のスィッチのチャタリングを除去するためのものです。 有機ELディスプレーはマイコンとはI2Cでの接続になります。SDAやSCLラインの外付けプルアップ抵抗は、ディスプレーモジュール内でプルアップされているので不要です。 今回はデバッグ用のシリアル入出力ピンは設けていません。 パルス幅やパルス周期を正確に出力するために、マイコンのクロック発振には、20MHzのセラミック発振子を使いました。
マイコンのファームウェアは、MPLAB IDE にて xc32 コンパイラにて作成しました。主なソースコードは oled.c, main.c です。 4.ファームウエア補足説明 サーボモータの制御信号は、下図のようになります。 制御信号はPICに内蔵のタイマー2(Timer2)と出力比較モジュール1(OutputCompare1)を使って生成しています。出力比較モジュールはPWMモードに設定します。 制御信号のパルス幅は、ロータリーエンコーダのカウント増減によるパルス幅の設定値(μsec)からOC1Rのクロックカウント値を求めて、OC1RSレジスタに設定します。設定は任意のタイミングで行うことが出来ます。 制御信号のパルス周期は、ロータリーエンコーダのカウント増減によるパルス周期の設定値(msec)からタイマー2のクロックカウント値を求めてPR2レジスタに設定しています。設定はタイマー2の割込み直後に行います。 タイマー2のクロック周波数は、40MHz/16=2.5MHz(周期 0.4μsec)に設定しています。クロックカウントが1000なら 400μsec、3750なら 1500μsec、 50000なら 20msec となります。 4−1 ロータリーエンコーダーの回転検出 ロータリーエンコーダの回転検出について説明しておきます。今回使ったエンコーダの出力信号は、図のようになっています。CH-Aの出力はPICの汎用ポートRB15に、CH-Bの出力はRB14に接続しています。 エンコーダの右回転を検出した時には回転数をカウントアップし、左回転を検出した時には回転数をカウントダウンします。右図のようにCH-AとCH-Bの出力信号には位相差があります。これに着目します。 CH-Aのパルス信号の立上がりを検出できたとします。この時、CH-Bのパルス信号を読み取って、その値が0なら右回転、1なら左回転しているということです。 CH-Aの立上がりではなく立下がりを検出できた場合には、CH-Bの値が0なら左回転、1なら右回転となります。 今回、CH-Aの立上がりや立下りの検出は、ポーリングではなくポートRB15のCN(Change Notification)割込みを使いました。 main.c の中のRB15の割込み処理のコードの主要部分です。 if(PORTBbits.RB15){ // CH-Aのパルス立上がり if(PORTBbits.RB14 == 0){ // CH-Bが0なので右回転 encorder_count++; // カウントアップ }else{ encorder_count--; // CH-Bが1なので左回転、カウントダウン } }else{ // CH-Aのパルス立下がり if(PORTBbits.RB14 == 0){ // CH-Bが0なので左回転 encorder_count--; // カウントダウン }else{ encorder_count++; // CH-Bが1なので右回転、カウントアップ } } RB15の入力の立上がり立下りのいずれの場合にも割込みが発生します。そこで割込み処理では、まず最初に割込み直後のRB15の状態を読んで立上がりによる割込みか立下りによる割込みか判定しています。 続いてRB14(CH-Bの信号)の値を読んで右回転ならカウントアップ、左回転ならカウントダウンします。 4−2 OLEDの表示処理 OLEDの文字表示処理について面白いことに気付きましたので紹介しておきます。
今回使ったOLEDは、128x64ドットのグラフィックディスプレーです。8x8ドットのフォントですと、横16文字、縦8行を表示することが出来ますが、このためには、OLEDのイニシャライズ処理において、
COM Pins Hardware Configuration(0xDA)コマンドのパラメータを 0x12 に設定します。 // 0xAE Display Off // 0xA8 0x3F Set MULTIPLEX (64line) 64dot // 0xC0 COM output scan direction 0 to 63 // 0xDA 0x12 Set COM Pins Hardware Configuration // 0x8D 0x14 Set charge pump enable // 0x81 0xFF Set Contrast Control/ max contrast // 0xAF Display ON // other default value oled_write_cmd("\xAE\xA8\x3F\xC0\xDA\x12\x8D\x14\x81\xFF\xAF", 11);この設定で、上から4行分文字を表示したのが、Photo1 です。更に1行空けて2行追加表示したのが Photo2 です。
縦8行表示は随分と文字が小さくて見づらいです。次に、COM Pins Hardware Configuration(0xDA)コマンドのパラメータを0x02に設定し、同様に4行を表示してみたのが Photo3 です。 // 0xAE Display Off // 0xA8 0x3F Set MULTIPLEX (64line) 64dot // 0xC0 COM output scan direction 0 to 63 // 0xDA 0x02 Set COM Pins Hardware Configuration // 0x8D 0x14 Set charge pump enable // 0x81 0xFF Set Contrast Control/ max contrast // 0xAF Display ON // other default value oled_write_cmd("\xAE\xA8\x3F\xC0\xDA\x02\x8D\x14\x81\xFF\xAF", 11);
Photo1とPhoto3を見比べてみると、Photo3では、フォントの縦表示がPhoto1の2倍になっています。ところが良く見るとフォントの上下方向で1ドット分の隙間が出来ています。 ここで、Photo2と同じように2行追加表示したものがPhoto4です。Photo3の2行目と3行目の上下方向のドットの隙間にうまく埋め込まれています。CRTのインターレース表示のような表示です。 縦8行表示の上半分の4行と下半分の4行が1ドット分ずれて重ねて表示されます。 サーボテスターの製作では、このインタレースのような表示方式を使っています。 |