More…

相撲ロボット用モータドライバアンプ
電子工作 PIC 関水 正裕

仕様

  • 大きさは125mm×45mm×12mm(最厚部)
  • 耐電圧は60V、耐電流は166A、※どちらも理論値
  • PICは16F84Aを使用し、クロックは20Mを使用、電源は受信機から5Vを受け取ります。 ※受信機の側に電源必要
  • Hブリッジについては、P・N混合型となっていてPチャンネルは2SJ606を、NチャンネルはSUP85N15-21を使用しています。また、回路中にゲート電圧を作るための6V出力の三端子レギュレータを乗せています。
  • LEDによる電源投入時の信号確認や操作時の動作確認

回路紹介

回路図(1チャンネル分)

上記回路で1チャンネル分となっていいて、実際はその回路が2つ横並びになっている状態になっています。回路について言うと至って簡単で、受信機からの信号は、ポートBの7pinに入力し、ポートAからデジタル(0・1)で出力しています。  FETの上部を弓鋸で切り取ってあります。これは省スペース化などのために行いました。  大会会場でのノイズの影響もほとんど受けず、高負荷時のFETの状態も良好で発熱も抑えられています。(体感温度で約45℃前後)

プログラムについて

まず、信号受信には外部割り込みをかけています。  これはポートBへの入力されている信号が変化したとき割り込む機能で、なぜこのようにしたかと言うと、ポートの入力の変化によって割り込みが入ることによって、プロポを操作したときに割り込みが入り、遅延を作らないようにするためです。そしてなぜポートBを入力ポートとしたかというと、この外部割り込み機能がポートBでしか出来ないためである。(CCSコンパイラ参照)つまりポートAだとこの割り込み機能が使えないため、遅延が発生するか、別の割り込み方法にしないとなりません。  次にパルスの読み方として、TIMER0を使っています。  パルスの計り方は、まずwhile(input(入力ポート));でパルスが一度立ち下がるまで待ち、次に、while(!(input(入力ポート)));でパルスが立ち上がるまで待ちます。そしてパルスが立ち上がるとこのwhileから抜けるので、ここでset_timer0(0);としてタイマーをリセット+カウント開始を行う。  次にwhile(input(PIN_B7));でパルスが立ち下がるまで待ち、立ち下がったらwhileから抜け、ここでn = get_timer0();とし、カウンタ値を取得し、変数に格納します。こうすることによって、パルスの立ち上がっているときの時間を計ることが出来ます。  そして私は、最初の1回目にgetした値は遊びとし、2・3回目で初期値設定(2度設定する)を、3回目以降初期値を中心として各種条件動作ということにしています。

※具体的に以下に1チャネル分のプログラム例を示します。

#include<16f84a.h>
#fuses HS,NOPROTECT,PUT,NOWDT
#use delay (clock=20000000)

#use fast_io(B)
#byte port_a=5
#byte port_b=6

long n=0;
long h1,l1,m=0,h2,l2;
#INT_RB
void intval(){
    while(input(PIN_B7));      //パルス立ち下がりまで待つ
    while(!(input(PIN_B7)));     //パルス立ち上がりまで待つ
    set_timer0(0);          //タイマーをリセット(カウント開始)
    while(input(PIN_B7));      //パルスの立下りまで待つ
    n = get_timer0();        //nにカウンタ値を格納

    if(m < 1){
        port_a=0b1000;delay_ms(125);
        port_a=0b0010;delay_ms(125);
        port_a=0b0100;delay_ms(125);
        port_a=0b0001;delay_ms(125);
        port_a=0b0100;delay_ms(125);
        port_a=0b0010;delay_ms(125);
        port_a=0b1000;delay_ms(125);
        port_a=0;delay_ms(125);
        m++;
    }
    if((m >= 1)&&(m <= 2)){
        h1 = n+7;
        l1 = n-7;
        h2 = h1+5;
        l2 = l1-5;
        m++;
    }
    if(m > 2){
        if((n >= l1) && (n <= h1)){port_a=0b0011;}
        else if(n > h2){port_a=0b0101;}
        else if(n < l2){port_a=0b1010;}
        else if((n > h1) && (n <= h2)){port_a=0;}
        else if((n >= l2) && (n < l1)){port_a=0;}
        else{port_a=0;}
    }
}
void main(){
    set_tris_a(0);
    set_tris_b(0b11111100);
    setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64);  // 内部クロック指定、プリスケーラ64
    enable_interrupts(INT_RB);     //ポートBの外部割り込み許可
    enable_interrupts(GLOBAL);     //グローバル割り込み許可
    while(1){              //無限ループ
    }                  //while中には何も書かない
}

反省

  • PIC側の回路とHブリッジ側の回路はGndで繋がっているが、回路的にはここを切り離しても動作するだろうし、その方が安全になるだろう。これは私の設計ミスによるもので、これにより危険という訳ではないがフォトカプラの意味が半減してしまっているという状態です。
  • 外部クロック20Mを付けていますが、上記プログラム例を見てわかるように全く外部クロックを付けている意味がありません。この場合内部クロックで全て事足ります。
  • 入力PINをRB7ではなく、RB1やRB2にしてジャンパーピンにおけば良かった。それは、PIC16F648AやPIC16F88などを使ったときに、シリアル通信のポートとして使いやすいためです。別にRB7でもシリアル通信が出来ない訳ではないが、元々シリアル通信としての機能があるPINの方が良いからです。
  • 今回はPICを2つ使用しているが、これも1つにしておけばもう少し小型化が可能だった。が、プログラムが若干複雑になります。
  • 今回は片面基盤で製作したが、これを両面基盤で、さらに表面実装で製作していたら、おそらくサイズは今回の半分手度になっていたと思います。
  • 最後に、今回の製作したANPでの最大の設計ミスが左右のモータを同時に正転または逆転させた場合、左右に流れる電流値が異なり、大きく機体が右に旋回してしまいます。これは電源コネクタを取り付けている位置を修正すれば解消されると思われます。

現在は、次回に向けて上記の反省を踏まえ、現在設計中です。