July 15, 2006

ラジコン受信機とマイコンの接続

室内で飛行する模型飛行機の自動制御を企んでいるわけですが、機体外から送られてきた制御情報と、機体に搭載されたセンサから得られた情報を、機体内のマイコンでミキシングすることによって全体のシステムが成立するようなことを考えています。
つまり機体外の情報を一度、機体内のマイコンにとりこむ必要があるのですが、今回は機体外の情報の通信手段としてはラジコンの無線を利用することを考えているので、ラジコンの受信機とマイコンを接続すれば達成できることになります。

ラジコンの受信機は普通、制御する対象の数(チャンネル数)だけ配線があり、そこにパルス(OFF→ON→OFFの信号)が出力されます。このパルスのON時間と制御量は比例関係にあるので、パルスのON時間をマイコンで計測できれば目的が達成されます。
しかしマイコン側でON時間を計るための機能は、残念ながらチャンネル数分ないことがほとんどであるため、なんらかの工夫をする必要があります。今回は6チャンネルの受信機をH8/3694マイコンの2つ分のパルス計測機能(正確にはタイマWのインプットキャプチャ機能、端子はFTIOAとFTIOB)で計ることにしました。

rx2cpu.png
こんな回路でできます。

工夫というのは単純な話で、ラジコン受信機からでてくるパルスは、チャンネルが違えば出力されるタイミングが異なることを利用しました。回路は図のとおりです。

あとはプログラムですが、これは続きをどうぞ。

#define SERVO_CH 6
unsigned short input_pulse[SERVO_CH];

void init_check_pulse(){
    /* タイマWの有効化
     *
     * クロックはφ/2(0.1 us)
     * A => インプットキャプチャ(割り込み)
     * B => インプットキャプチャ(割り込み)
     */
    TW.TCRW.BYTE = 0x10;
    TW.TIOR0.BYTE = 0x74; // A => 立ち上がりエッジのみ検出
    TW.TIERW.BYTE = 0x03;

    /* カウントスタート */
    TW.TMRW.BIT.CTS = 1;
}

#define BIT_IMFA 0x01
#define BIT_IMFB 0x02

inline void check_pulse(unsigned char flag){
    static unsigned char target_ch = SERVO_CH;
    static unsigned short before_count;

    if(target_ch < SERVO_CH){
        // 奇数(1, 3, ...)
        if(target_ch & 0x01){
            if(flag & BIT_IMFB){
                input_pulse[target_ch]
                     = (TW.GRB > before_count) ? (TW.GRB - before_count) : ~(before_count - TW.GRB);
                if(flag & BIT_IMFA){
                    before_count = TW.GRA;
                    target_ch++;
                    return;
                }
            }
        // 偶数(0, 2, ...)
        }else{
            if(flag & BIT_IMFA){
                input_pulse[target_ch]
                     = (TW.GRA > before_count) ? (TW.GRA - before_count) : ~(before_count - TW.GRA);
                if(flag & BIT_IMFB){
                    before_count = TW.GRB;
                    target_ch++;
                    return;
                }
            }
        }
        target_ch = SERVO_CH;
        TW.TIOR0.BYTE &= ~(0x03); // A => 立ち上がりエッジのみ検出
    }else{
        if((flag & (BIT_IMFA | BIT_IMFB)) == BIT_IMFA){
            before_count = TW.GRA;
            TW.TIOR0.BYTE |= 0x03; // A => 両エッジ検出
            target_ch = 0;
        }
    }
}

#pragma interrupt
void int_timerw(){
    unsigned char flag = TW.TSRW.BYTE;
    /* フラグクリア */
    TW.TSRW.BYTE = 0x00;

    /* IMFA, IMFB */
    if(flag & (BIT_IMFA | BIT_IMFB)){check_pulse(flag);}
}

int main(){
    init_check_pulse();
    enableIRQ(); /* 割り込み有効 */
    while(1);
    return 0;
}


これでうまく動いています。

02:24 fenrir が投稿 : 固定リンク | このエントリーを含むはてなブックマーク | この記事をLivedoorでクリップ! | この記事をdelicious.comでブックマーク | このエントリをドリコムRSSにクリップ | トラックバック
このエントリーのトラックバックURL: http://fenrir.naruoka.org/mt/mt-tb.cgi/500
コメント
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。