コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

卓上ロボット掃除機の改造 (4) PIC Microbridgeプログラム

PICのプログラムを書くのにMPLAB Xを使っているのですが、Windows7 64bit版環境だと、PICKit3をうまく認識できず、ずっと、古いXPを使ってプログラミングしていました。ところが、最近出たMPLAB X IDE Ver 1.00になって、正常にPICKit3を認識することが分かり、今ではWindows7 64bit版でMPLAB Xを使ってプログラミングしています。
タイトルにあるPIC Microbridgeとは、日曜エレクトロニクス(日エレ)のブログを書かれている石井さんが、MicrobridgeをPICに移植されたものです。Microbridgeとは、Androidデバッグ用に用意されているAndroid Debug Bridge(ADB)を使って、マイコンAndroidの通信を実現したすばらしいプログラムです。本家サイトはここです

PIC ADK Miniboard

今回、PIC Microbridgeを実装しているPICマイコン基板は、これも石井さんが作成されたPIC ADK Miniboardという基板です。この回路はオープンソースとなっており、回路図面はこちらに有ります。この基板には、PICとモータドライバ(TB6552)が搭載可能で、他にもデジタルサーボモータが3台まで接続可能な端子が用意されている。現状は、この基板のSJ2とSJ3を短絡させて使っています。現在はRev2が出来ており、これらの基板は、隔月で行われている日本Androidの会神戸支部主催のAndroid日本橋でんでんタウンもくもく会で配布されています。最新基板の写真はこれです。

これらの基板用に作られているのが、石井さんが公開されているPIC Microbridgeプログラムです。

PIC Microbridge Cleaner

石井さんが作られたPIC Microbridgeプログラムを、今回、製作した卓上ロボット掃除機の改造ロボット用に改造したものが、PIC Microbridge Cleanerプログラムです。プロジェクト一式は石井さんの許可を得て、githubに公開しました。
Microbridgeのプログラム部分は、元々の石井さんのプログラムとほとんど同じで、Androidにamコマンドを送信してアプリを起動する部分を関数化したり、tcp Forwardを行う部分を関数化したりしただけです。
6番ピンにLEDを付けたので、チカチカさせるようなコードも入っています。

//***********************************************
// Starting Activity
//***********************************************
int StartingActivity(const char* activityName)
{
char ac[256];
int ret = 0;
    applicationLaunched = false;
    strcpy( ac, "shell:am start -n " );
    strcat( ac, activityName );
    Connection *con = ADB_addConnection( ac, false);
    int i;
    for(i=0;i<75;i++){
        ADB_poll(con);
        if(applicationLaunched == true){
            ret = 1;
            break;
        }
        LATBbits.LATB2 = 0;
        DelayMs(50);
        LATBbits.LATB2 = 1;
        DelayMs(20);
    }
    applicationLaunched = true;
    ADB_delConnection(con);
    return ret;
}
//***********************************************
// tcp Forward
//***********************************************
Connection* tcpForward(const char* port)
{
char ac[128];
    strcpy( ac, "tcp:" );
    strcat( ac, port );
    Connection *con = ADB_addConnection( ac, false);
    AdbDataReceiveFlg = false;
    while(AdbDataReceiveFlg==false){
        ADB_poll(con);
        DelayMs(1);
    }
    return con;
}

ロボットの制御

ロボットの制御というかモータの制御は、すごく簡単なプロトコルで動きます。
命令はたった6つです。

  • 前進: F
  • 後退: B
  • 右回転: R
  • 左回転: L
  • 停止: S
  • 終了: Q

2バイトのプロトコルで、AndroidからのFx, Bx, Rx, Lx, Sx, Qx命令を待っています。xは0〜255段階のDCモータに掛かる電圧を意味します。よって、SとQ命令では、xは無視されます。
2バイトの命令を受信したら、受信した命令1バイトをackの替わりに返します。ただし、これらのコマンドで無かった場合はEが返ります。
プログラムは、下記のようなベタなプログラムになっています(^^;。ちなみに、PICのUARTは使えるようになっていて、16ピンにTXD,17ピンにRXDが割りついていて、57600bpsでログを出力しています。

    unsigned int power = 0;
    AdbDataReceiveFlg = false;
    while (1) {
        ADB_poll(AdbC);
        if (AdbDataReceiveFlg == true) {
            tprintf("receivedCommand = %Xh %Xh\r\n", RecvData[0], RecvData[1]);
            power = (unsigned int)RecvData[1];
            if( power>0x80 )    power = 0x80;
            switch(RecvData[0]){
                case 'F':
                    //Just Stop
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //Straight Gear
                    setServoAngle(0,90);
                    OC4R = power;
                    OC5R = power;
                    setMotorControl(0,MOTOR_FORWARD);
                    //LED ON
                    LATBbits.LATB2 = 1;
                    break;
                case 'B':
                    //Just Stop
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //Straight Gear
                    setServoAngle(0,90);
                    OC4R = power;
                    OC5R = power;
                    setMotorControl(0,MOTOR_BACKWARD);
                    //LED OFF
                    LATBbits.LATB2 = 0;
                    break;
                case 'S':
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //LED OFF
                    LATBbits.LATB2 = 1;
                    break;
                case 'R':
                    //Just Stop
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //Rotation Gear
                    setServoAngle(0,10);
                    OC4R = power;
                    OC5R = power;
                    setMotorControl(0,MOTOR_FORWARD);
                    //LED OFF
                    LATBbits.LATB2 = 1;
                    break;
                case 'L':
                    //Just Stop
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //Rotation Gear
                    setServoAngle(0,10);
                    OC4R = power;
                    OC5R = power;
                    setMotorControl(0,MOTOR_BACKWARD);
                    //LED OFF
                    LATBbits.LATB2 = 0;
                    break;
                case 'Q':
                    OC4R = 0;
                    OC5R = 0;
                    setMotorControl(0,MOTOR_STOP);
                    //Straight Gear
                    setServoAngle(0,160);
                    //LED OFF
                    LATBbits.LATB2 = 0;
                    ADB_delConnection(AdbC);
                    DelayMs(250);
                    while(true);
                    break;
                default:
                    RecvData[0] = 'E';
                    break;
            }
            ADB_write(AdbC, 1,RecvData);
            AdbDataReceiveFlg = false;
        }
        DelayMs(1);
    }

通信について

上記のAndroidとの通信はtcp通信を行っています。ADBの機能であるPort Forwardを用いて、60101ポートをADBのUSB側に振ってやるように指定して、Androidアプリとtcp通信を行うことにより、PIC及びロボットの制御を実現しています。
ここで、Android側の制御アプリとしてLuaridaを用いています。先月、Luaridaのtcp通信部分を新たにNDKで実装したので、そこそこ速い通信が実現できています。

次回は、Android側のLuaridaスクリプトについて書こうと思います。