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ファイルはこの中に入っています