Logicool CORDLESS COMPACT CONTROLLER LPGC-60000 をつないでみる
(2006年 1月 2日 (C) 岡田 紀雄)
ロボットを動かす際、細かなコントロールをしてみたくなりものです。 そこで、プレステ用コントローラを使って動かしてみようと思い、諸先輩方の資料を基に作ったので、日記を切り出しまとめをしておきます。 試行錯誤して作ったので、どこかに誤りがあるかもしれません。 見つけられた方、メール等でお知らせ頂けると、幸いです。
ゲーム機のコントローラを衝動買いしてしまいました。 4k円也。
|
|
PSコントローラの仕様については、下記が代表的なサイトのようですね。
実際に、ロボットへの搭載というのは、のんさやさんのサイトのココが良いです。
![]() |
![]() |
|
(★特記★)
DAT 信号のプルアップ抵抗は忘れずに。 受信機からの信号は、Lo か Hi-Z だからです。 プルアップ抵抗が入っていないと、常に
Lo(0) になってしまいます。
(★特記2★)
74LCXシリーズは、全ての端子に 5V トレラントがついてます。 これにより、DSC2
側は 3.3V デバイスであっても、5V CPU でデータの送受信ができます。
(★特記3★)
Xilinx の CPLD には、Vccio の電位にあわせて I/O の出力電圧を決めることができるんですね。 逆に、入力は Vcc +0.5V なので、安心。 ずっと、I/O共にVcc と同じと思い込んで使ってました。 また、内部 3.3V(=Vcc) 版には、5Vトレラントがあって入力が5Vでも大丈夫な仕様になってるし。 つまり、5V系と3.3V系のデータ転送を CPLD を通せば、簡単にできちゃう、ということになります。 以下、XC9572 の電気特性仕様の関係しそうなところだけをメモとして残しておきます(参考まで)。
Symbol | Parameter | Value |
Vin | DC input voltage relative to GND | -0.5V to Vcc+0.5V |
Vccio | Supply voltage for output driver for 5.0V operation | 4.75V to 5.25V |
Supply voltage for output driver for 3.3V operation | 3.0V to 3.6V | |
Vih | High-level input voltage | 0V to Vcc+0.5V |
Vo | Output voltage | 0V to Vccio |
(★特記4★)
もし、DATに対してもLCX125を介して接続したら、下図のような波形になってしまいました。
![]() |
![]() |
黄色の線がDAT信号。 入力パルスが鈍るのと、H電位が低くなりすぎます(約1.8V程度)。 これだと、CPUで H に切り替わったことが認識できません。
(★事故記録★) 以下、SH2/7145F に対して DSC2 を繋いで実験した時の記録です。
最初、CPU も受信機も 3.3V デバイスだからという理由だけで信号線を直結して通信させてみました。(プルアップ抵抗は全ピンに入れます)
いろいろと試しているうちに、CPU 側の CLK 出力端子が壊れてしまったみたい。 最悪。。。
気を取り直して、別ピンでトライ。 どうせ、壊れた CPU だし。。。(って、結構高いんですけど、BTC080
)。 オシロで見て、ちゃんと CLK が出ているのを確認。 よし。 ちゃんと通信できたかな? ボタンを押しても、帰ってくるデータが同じ。 おかしい。 リセット。 あれれ? 全部ビットが1に。 あ、また、壊れた。。。
CLK端子って、結構電流を必要としてるのかな? 直結はやめたほうがよさそう(って、今頃。。。)。
74HC08を通してみた。 安定している。 が! コントローラの MODE スイッチを押して、アナログモード、もう1回押して・・・ あれ? 入力がHi状態が続く。。。 また、お亡くなりになってしまった。。。 CPU
の方が駄目になってる。 何が悪いんだ?
(★プリント基板で自作ボード作成のメモ★)
何回か基板作りをしているうちに、感覚的なところがわかってきました。 その感覚を言葉で表現して残して起きます。
(★動作確認★)
動作確認できている CPU は以下の通り。
R8C/11-21114FP 20MHz ・・・ 各端子にプルアップ抵抗が内蔵されているので、SH2/7145F
駄目だった直結&3.3V 動作でできちゃいます。
SH2/7047F 50MHz ・・・ 74LCX125 を介して動作してます。
(★特記&各自変更希望部分★)
9行目の DSC2_LOOP ですが、小さすぎても、大きすぎても駄目です。 コントローラ受信機からの信号がうまく帰ってきません。 デジタルモードの場合は比較的範囲が広いですが、アナログモードにした場合は狭いので、微調整をしてください。 ここの数字だけで駄目な場合は、DSC2_pause()
を読み出しているところで nop() を 1,2 個足して安定性を確保してみてください。
1: unsigned char CONFIG_MODE_ENTER[] = { 0x01,0x43,0x00,0x01,0x00,0x00,0x00,0x00,0x00 }; 2: unsigned char QUERY_MODEL_AND_MODE[] = { 0x01,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 3: unsigned char SET_MODE_AND_LOCK[] = { 0x01,0x44,0x00,0x01,0x03,0x00,0x00,0x00,0x00 }; 4: unsigned char CONFIG_MODE_EXIT[] = { 0x01,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 5: unsigned char VIBRATION_ENABLE[] = { 0x01,0x4D,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF }; 6: unsigned char READ_DATA[] = { 0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 7: unsigned char ReciveData[ 8 ] = { 0 }; 8: 9: #define DSC2_LOOP (10) // ここを CPU 毎に変える (4=[R8C/11 20MHz], 10=[SH2 50MHz]) 10: 11: inline void DSC2_pause( void ) 12: { 13: unsigned char d; 14: 15: for( d = 0; d < DSC2_LOOP; d++ ) nop(); 16: } 17: unsigned char DSC2_rw( 18: unsigned char cmd 19: ) { 20: int i; 21: unsigned char data = 0, clk_cnt = 0; 22: 23: for( i = 0; i < 8; i++ ) { 24: unsigned char d; 25: 26: _port_dsc2_cmd = ( cmd & 0x01 ); 27: cmd >>= 1; 28: _port_dsc2_clk = 0; 29: DSC2_pause(); 30: _port_dsc2_clk = 1; 31: DSC2_pause(); 32: d = _port_dsc2_dat; 33: data |= ( d << clk_cnt ); 34: clk_cnt++; 35: DSC2_pause(); 36: } 37: return data; 38: } 39: unsigned char *DSC2_send_command( 40: unsigned char *src 41: ) 42: { 43: _port_dsc2_clk = 1; 44: _port_dsc2_cmd = ( src[ 0 ] & 0x01 ); 45: _port_dsc2_sel = 0; 46: ReciveData[ 0 ] = DSC2_rw( src[ 0 ] ); // 読み込みデータは捨てる 47: ReciveData[ 0 ] = DSC2_rw( src[ 1 ] ); 48: ReciveData[ 1 ] = DSC2_rw( src[ 2 ] ); 49: ReciveData[ 2 ] = DSC2_rw( src[ 3 ] ); 50: ReciveData[ 3 ] = DSC2_rw( src[ 4 ] ); 51: ReciveData[ 4 ] = DSC2_rw( src[ 5 ] ); 52: ReciveData[ 5 ] = DSC2_rw( src[ 6 ] ); 53: ReciveData[ 6 ] = DSC2_rw( src[ 7 ] ); 54: ReciveData[ 7 ] = DSC2_rw( src[ 8 ] ); 55: _port_dsc2_sel = 1; 56: _port_dsc2_cmd = 1; 57: _port_dsc2_clk = 1; 58: } 59: void INIT_DSC2( void ) 60: { 61: DSC2_send_command( CONFIG_MODE_ENTER ); 62: DSC2_send_command( QUERY_MODEL_AND_MODE ); 63: DSC2_send_command( SET_MODE_AND_LOCK ); 64: DSC2_send_command( CONFIG_MODE_EXIT ); 65: } |
INIT_DSC2() を初期化として呼び出した後、必要に応じて、DSC2_send_command( READ_DATA ); とすれば、ReciveData にデータが格納されて帰ってきます。 INIT_DSC2() でアナログモードに切り替えを入れておけば、アナログスティックもちゃんと使えます。 もちろん、コントローラの MODE スイッチで切り替えも可能です。 たくさんボタンがあるし、従来のRCプロポ同様、アナログコントロールもできるので、かなり遊べそうです。
(★追記★) CPUを3664Fの場合はどうしたら良いのですか?という問い合わせが多いので、挙げておきます。 が、動作チェックをしてませんので、間違えていたらごめんなさい(指摘いれていただけると助かります)。 ハード構成は、のんさやさんの紹介頂いているものとします。
1: #define _port_dsc2_cmd IO.PDR5.BIT.B1 2: #define _port_dsc2_clk IO.PDR5.BIT.B3 3: #define _port_dsc2_dat IO.PDR5.BIT.B0 4: #define _port_dsc2_sel IO.PDR5.BIT.B2 5: 6: void INIT_PORT( void ) 7: { 8: IO.PMR5.BIT.BIT.0 = 0; // P50 汎用ポートとして定義 9: IO.PMR5.BIT.BIT.1 = 0; // P51 汎用ポートとして定義 10: IO.PMR5.BIT.BIT.2 = 0; // P52 汎用ポートとして定義 11: IO.PMR5.BIT.BIT.3 = 0; // P53 汎用ポートとして定義 12: 13: IO.PCR5.BIT.BIT.0 = 0; // P50 (DAT) を入力ポートとして使用 14: IO.PCR5.BIT.BIT.1 = 1; // P51 (CMD) を出力ポートとして使用 15: IO.PCR5.BIT.BIT.2 = 1; // P52 (SEL) を出力ポートとして使用 16: IO.PCR5.BIT.BIT.3 = 1; // P53 (CLK) を出力ポートとして使用 17: } |
これを付け加えて頂いて、プログラム最初の初期化の時に、INIT_PORT() 部分を呼び出してもらえればよいと思います。