Logicool CORDLESS COMPACT CONTROLLER LPGC-60000 をつないでみる

(2006年 1月 2日 (C) 岡田 紀雄)

ロボットを動かす際、細かなコントロールをしてみたくなりものです。 そこで、プレステ用コントローラを使って動かしてみようと思い、諸先輩方の資料を基に作ったので、日記を切り出しまとめをしておきます。 試行錯誤して作ったので、どこかに誤りがあるかもしれません。 見つけられた方、メール等でお知らせ頂けると、幸いです。


ゲーム機のコントローラを衝動買いしてしまいました。 4k円也。

  • ちっちゃなコントローラに、小さな受信機。
  • 受信機の端子が PS用なので結線しづらい
    → 溝をみつけカッターでグリグリやってみる
  • あらら。 簡単に解体できました。
    → ケーブルは直付けといきましょうかね。
     (良い子は真似しないように)

PSコントローラの仕様については、下記が代表的なサイトのようですね。

実際に、ロボットへの搭載というのは、のんさやさんのサイトのココが良いです。

  • 3.3Vレギュレータは 500mA タイプを使用。
    ・・・ 受信機の消費電力がわからないため。
  • 下の特記事項など参考にしてください。
  • 抵抗はプルアップ用で 10kΩを使用(*4個)。
  • コンデンサは 0.1μF を使用(*3個)

(★特記★)
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() 部分を呼び出してもらえればよいと思います。


 ロボット製作のページへ

 トップページへ