FF9 FMSアダプター 作成:2007-01-11〜2007-01-27

しばらく飛ばしていなかったときはフライトシミュレータでリハビリしてから飛ばさないとダメみたいです。そこで無料のラジコンフライトシミュレータFMSのアダプターを作ることにしました。普通のフライトシミュレータはジョイステックで飛行機を操縦しますが、ラジコン用はプロポとパソコンをアダプターで接続して、プロポのスティックで飛行機を操縦します。


FMSの見た目はこんな物です


これは以前作ったプリンターポートに接続するための物。OSをWindowsXPにしたので使えなくなってしまいました。Windows95まではプリンターポートに直接読み書きできたようですがWinXPになってからNGになったので、使えなくなったわけです。黒いケーブルはプロポの背面にあるトレーナーコネクターに差し込みます。たしかラジコンショップで¥1000ほどで販売されていたと思います。双葉純正品なのかフライトシミュレータ用なのか不明です。この黒ケーブルは、GND、電源、信号線、の3線です。プロポのトレーナーコネクターは6線ですが、そのうち3本だけしか繋がっていません。GND、信号線の2本しか繋がっていません。


中身はトランジスターと抵抗2本だけです。


プロポ側のコネクターはこれ。フライトシミュレータを使うときは電波を出すのは無駄なので高周波モジュールは外します。この方が電池も長持ちします。


FF9は9チャンネルなので信号パルスが9回連続して出ています。9個のパルスの固まりが22.4ms間隔で繰り返し出力されます。スティックを操作するとパルスの幅が変わります。百聞は一見にしかず、下のMOVIEを見てください。エクスポーネンシャル等はかかった状態で信号が出力されます。


信号の変化 <− MOVIE(前半と後半では動かしているスティックが異なります)

FMSはWindowsXP用にRS−232Cポート(=シリアルポート)経由で接続するインターフェースも公開しています。FMSをインストールすると仕様が確認できます。
仕様は...
  ・通信速度19200bps
  ・8ビット
  ・パリティー:無し
  ・ストップビット:1ビット
  ・4軸の移動量を送る前にヘッダーとして0xFFを送信する(補足:0xは16進数の意味です)
  ・ヘッダーに続けて4方向の移動量を各1バイトで送る
  ・移動量は0x80をスティックの中央として0x00〜0xFEをフルストロークとする


こんな仕様なので、プロポのトレーナーコネクターに出ている信号のパルス幅を計測してそれを0x00〜0xFEに換算して送信するのがアダプターの役割になります。この操作はPICを使用すれば造作もなく、実際FMSの\interfaceフォルダーにはPICに書き込むHEXファイルや回路図までもが公開されています。しかし、ちょっと問題もあります。
 1.FF9用の結線が明示されていない
 2.FF9にPIC側のソフトが対応できているのかよくわからない
 3.ソースコードがアセンブラーなので解りずらい
 4.PIC12C508は秋月電子では売っていない(但し、これについてはPIC16F84用の回路図が公開されているので問題ではない)
PICの232C接続機能のUSARTを使えばソフトがシンプルになりますが、小型化には適していません。8ピンの小型PICにはUSARTが付いていないからです。とりあえずソフトがシンプルになる方を優先して作ってみることにします。開発言語はmikroBASICです。


黒いケーブルはGNDと信号線の2本しか繋がっていませんでした。従ってこのケーブルをそのまま使う限りプロポ側からは給電出来ません。PICを20MHzで動作させると消費電力もそれなりに大きかったはずで、232Cから給電出来るか不明です。とりあえず回路をゼロから作るのは面倒だったのでFF9げのむに回路を追加して実験装置を作りました。ハードが違ってもPICのUSARTを使う限りソフトは全く変わりません。
後で解りましたがFF9の信号は5Vなのでこの回路不要だということが解りました。FF9側の信号電圧がFF9げのむ側の電源電圧より高い時(FF9と直結したらPICが壊れるかも?)やFF9以外でも使えるようとりあえず、このトランジスターは付けておくことにします。


FF9げのむと同居するので切り替え用のジャンパーを仮付けしました。


上の方で9チャンネル出力されていると書きましたが、パルスとパルスの間隔が変わるので8チャネルでした。FMSも8チャネルの分受け取ることが出来ます。5,6,7チャネルはプロポの額の所にある3つの黒いつまみに割り当てられているようです。8チャネル目は何に割り当てられているのか解りませんでした。プロポから出ている信号とFMSのチャネルの対応は一部ちょっとずれています。何ででしょ?
 プロポ側     FMS側
 1CH   −> 1CH
 2CH   −> 2CH
 3CH   −> 3CH
 4CH   −> 4CH
 5CH   −> 6CH
 6CH   −> 7CH
 7CH   −> 8CH
 8CH   −> 5CH


設定して動かしてみました。


実験プログラムで8CHのパルス幅を表示 <−MOVIE(16進数です。単位は1/5000000秒)

実際動かしてみて感じた問題
 1.サーボの動きの遅れのシミュレーションは無いようです(気が付かないだけ?)
 2.こだわるならプロポの個体差によるパルス幅の校正機能があった方がよい(校正ボタンをつけるかハイパーターミナルからRS232C経由で校正のコマンドを送るか、どちらかが必要でしょう)


コネクターのピン割り当てを調べてみました。6ピンありますが、2本ある電源ピンの右はスイッチを入れなくても10V、左はスイッチと連動しています。


コネクターのピッチは2mmなので2mmのヘッダーピンを入手できれば自作も出来ます。2mmピッチのヘッダーピンは千石電商で入手できます。テクニカル電子株式会社のマイクロコネクターのようです。E6−192というのが型番です。


FMSのインターフェスマニュアルに掲載されている物よりも複雑そうに見えますが、電気工作入門者がシリアルインターフェースを使った設計をするとこんなデザインになると思います。安全確実小細工無しの正攻法の設計です。基板サイズは50×32mmですが、シリアルポートコネクターが基板からかなり飛び出しています。少量ですがキットも配布します。たぶん価格は実費で¥2000〜¥2500になると思います。
仕様は...
 ・電源はプロポから供給する
 ・コネクターは自作してみる
 ・プロポ毎の個体差の校正機能を設ける
  (プロポは水晶で周波数を決めていると思うので、実際はこのインターフェースの個体差の校正機能といえるかもしれない)
 ・書き込み機を持っている人のためのプログラム書き換え端子を付ける(...というよりむしろ自分のために)


PICはパーツケースの中に1個だけあった16F648Aを使うことにします。半導体パーツケースの中は購入したものの設計途中で没になったものや、予備で購入しておいたものでいっぱいです。ほとんどが不良在庫です。たぶん3万円分くらい。感光基板が在庫切れなので、とりあえずブレッドボード上に回路を組みました。


これがほぼ最終形の基板レイアウト。少し大きくなりました、ついでにLEDも1個追加。


プロポをPCMモードにしても信号は出ているのですが規則性が解りません。もちろんこのアダプターはPPMモードでなければ動きません。PCMモードにした状態で使用するとゴミデータを送信し続けます。


ブレッドボードでの動作確認は終了。次は基板を作ります。今回は基板メーカーに発注することにします。両面基板を発注したことはあるのですが片面基板はまだ無いので試してみたいのです。


OLIMEX規格サイズの160×100mm基板からは8個取れますが、2個自分用として、残り6個を配布します。部品の価格かなりテキトーですが配布予定価格は約¥2600。もちろん組み立てキットです。

FF9 FMS アダプター 部品表
部品番号     QTY @ Price 購入先 備考
IC2 PIC PIC16F648A 1 \200 \200 秋月電子  
- IC SOCKET 18ピン 1 \50 \50 秋月電子  
IC1 232CインターフェースIC ADM3203AN 1 \200 \200 秋月電子 ソケット付き
U1 発振子 セラロック20MHz 1 \40 \40 秋月電子  
LED1 LED1 φ3mm赤 1 \42 \42 千石電商  
LED2 LED2 φ3mm緑 1 \42 \42 千石電商  
- プリント基板 OLIMEX 1 \100 \100 生基板使用  
C1-C4 積層セラミックコンデンサ 0.1uF 4 \0 \0 秋月電子 232CインタフェースICに付属
R1,R4,R5 抵抗 4.7k 1/6W 2
\5 \10 千石電商  
R2,R3 抵抗 1k 1/6W 2 \5 \10 千石電商  
T1 トランジスター 2SC1815 1 \10 \10 千石電商  
X1 RS−232Cコネクター 9ピン メス 1 \60 \60 秋月電子  
C5,C6 積層セラミックコンデンサ 0.1uF 2 \5 \10 千石電商  
IC3 電源レギュレターIC 78L05 1 \20 \20 秋月電子  
- 2mmピッチヘッダー 3ピン×2 1 \30 \30 千石電商  
JP1,JP2 2.54ピッチヘッダー 5ピン + 3ピン 1 \30 \30 秋月電子  
- 232Cケーブル 232Cケーブル 1 \300 \300 秋月電子  
- ケーブル プロポ<−>FMSアダプター 1 \150 \150 オヤイデ電気  
- 送料+代引き手数料など 部品屋ー>当方 1 \300 \300  
- 送料 当方ー>配布先 1 \200 \200 郵便局  
total \1,180  


回路図


FF9げのむ」とほぼ同じ部品構成のため価格差が小さいので、配布企画はボツにしてしました。配布企画はFF9げのむに吸収合併させます。代わりに上の四角で囲った不要な部品を無くしてシンプル版を作ることにしました。上の部品表で、濃いグレーの部分が不要になりました。

Press−n−Peelで基板作成です。右は転写後の抜け殻シート。


転写後の状態


室温が低いのでエッチング液を暖めて使います。


ドブ漬けしてトナーを落としました。ラッカーシンナーで落ちます。これならホームセンターで安く入手できます。


シンプル版回路図


EAGLEの回路図&基板レイアウト図 <−zipです
基板パターンビットマップ <−これもzipで圧縮してあります

基板出来ましたが.....


裏焼きでした。


作り直しました。この状態でハンダ付け。曲がってますが、そもそもFF9側のコネクターが曲がっているためです。


組み立てました....が、電源電圧が8V近くあります。5Vになるはずなのですが??? データシート見たら電源ICの向きが逆でした。


向きを変えてプログラムを書き込んだPICを挿して完成。FMSアダプターは安価な市販品があるようです、ほとんど儲けゼロのボランティア価格の物もあるようです。


プログラムはこんなです。言語はmikroBASICです。mikroBASICは入門書が出版されていないこともあり、あまり普及していませんが良いソフトです。プログラムサイズは無料版の制約内に収まる2kワード以下なのでプログラムが書ける人はいじってみてください。プログラム一式とHEXファイルはこのリストの一番下に貼り付いています。

'-------------------------------------------------------------- 2007-01-26 -----
' FMS adapter   PIC16F648A Clock 20MHz
'-------------------------------------------------------------------------------
program FMSadapter

'---- symbol definisions ----------------------------
symbol PORT_OUTPUT    = 0
symbol PORT_INPUT     = 1

symbol WAIT           = 0
symbol READY          = 1

symbol STICK_CTR      = 0x1DD8
symbol STICK_INC      = 0x001E

symbol FF9SIG_TRIS    = TRISB
symbol FF9SIG_PORT    = PORTB
symbol FF9SIG_BIT     = 0

'---- variable definitions ---------------------------
dim word_val   as word absolute $20
dim byte_low   as byte absolute $20
dim byte_high  as byte absolute $21

dim stick1_time as word
dim stick2_time as word
dim stick3_time as word
dim stick4_time as word
dim stick5_time as word
dim stick6_time as word
dim stick7_time as word
dim stick8_time as word

dim stick1      as byte
dim stick2      as byte
dim stick3      as byte
dim stick4      as byte
dim stick5      as byte
dim stick6      as byte
dim stick7      as byte
dim stick8      as byte

dim channel     as byte
dim sendf       as byte

'===============================================================================
' calculate full storoke TMR1 -> 0x00 to oxFE
'===============================================================================
sub function calc_stroke( dim stick_tmr1 as word) as byte
    dim offset as word

    if STICK_CTR < stick_tmr1 then
        offset = (stick_tmr1 - STICK_CTR) div STICK_INC
        if offset > 0x007E then
            result = 0xFE
        else
            word_val = 0x0080 + offset
            result = byte_low
        end if
    else
        offset = (STICK_CTR - stick_tmr1) div STICK_INC
        if offset > 0x0080 then
            result = 0x00
        else
            word_val = 0x0080 - offset
            result = byte_low
        end if
    end if
end sub

'===============================================================================
' Interrupt from FF9
'===============================================================================
sub procedure interrupt
    '---- RB0 interrupt   FF9 signal rising edge
    if INTCON.INTF = 1 then
        byte_low   = TMR1L
        byte_high  = TMR1H
        TMR1H      = 0
        TMR1L      = 0
        ' if TMR1 > (25000 = 5msec)  or  TMR1 is overflow
        if (word_val > 25000) or (PIR1.TMR1IF = 1) then
            channel = 0
        else
            channel = channel + 1
            select case channel
                case 1 stick1_time = word_val
                case 2 stick2_time = word_val
                case 3 stick3_time = word_val
                case 4 stick4_time = word_val
                case 5 stick5_time = word_val
                case 6 stick6_time = word_val
                case 7 stick7_time = word_val
                case 8 stick8_time = word_val
                       sendf = READY
            end select
        end if
        PIR1.TMR1IF = 0
        INTCON.INTF = 0
    end if
end sub

'*******************************************************************************
' Program main
'*******************************************************************************
main:
    '---- port A digital INPUT-OUTPUT (comparetor off)--------
    CMCON.CM2 = 1
    CMCON.CM1 = 1
    CMCON.CM0 = 1

    '---- disable port B pull-up -------------
    OPTION_REG.NOT_RBPU = 1

    '---- FMS adapter PORT -------------------
    FF9SIG_TRIS.FF9SIG_BIT = PORT_INPUT

    '---- Initialize -------------------------
    Usart_Init(19200)   ' Initialize USART module
    Delay_ms(1000)

    '---- RB0 interrupt ----------------------
    INTCON.INTE       = 1 ' enable RB0 interrupt
    OPTION_REG.INTEDG = 1 ' interrupt on rising edge

    '---- TMR1 initialize --------------------
    INTCON.PEIE   = 1    ' Enable Peripheral interrupt
    PIE1.TMR1IE   = 1    ' Enable TMR1 interrupt
    PIR1.TMR1IF   = 0    ' Clear interrupt flag
    T1CON.T1CKPS1 = 0    ' set prescaler 1
    T1CON.T1CKPS0 = 0    ' set prescaler 1
    T1CON.TMR1CS  = 0    ' use internal clock
    T1CON.TMR1ON  = 1    ' Enable TMR1

    '---- Enable All interrupts --------------
    INTCON.GIE = 1

    sendf = WAIT
    while( TRUE )
        if sendf = READY then
            stick1 = calc_stroke( stick1_time )
            stick2 = calc_stroke( stick2_time )
            stick3 = calc_stroke( stick3_time )
            stick4 = calc_stroke( stick4_time )
            stick5 = calc_stroke( stick5_time )
            stick6 = calc_stroke( stick6_time )
            stick7 = calc_stroke( stick7_time )
            stick8 = calc_stroke( stick8_time )

            Usart_Write( 0xFF )
            Usart_Write( stick1 )
            Usart_Write( stick2 )
            Usart_Write( stick3 )
            Usart_Write( stick4 )
            Usart_Write( stick5 )
            Usart_Write( stick6 )
            Usart_Write( stick7 )
            Usart_Write( stick8 )

            sendf = WAIT
        end if
    wend
end.

'----- E N D   O F   P R O G R A M ---------------------------------------------


プログラム一式 <−HEXファイルはこの中に入っています


inserted by FC2 system