WROOM-02とジョイスティックの接続

ちょっと前に、2つのWROOM-02をそれぞれサーバー/クライアントとして構成して相互接続しようとしたら、なかなかうまくいかなかった、という話を書いた。回避策が見つからない間の気晴らしとして、サーボ雲台の操作用に、WROOM-02にA/Dコンバータを介してジョイスティックを接続してみた。

構成

回路図を以下にしめす。WROOM02-JOYSTICK1

A/Dコンバータとジョイスティック以外はSTA-ESPという名前でWIFIステーション用として構成中のブレッドボードを使い、追加した2つの部品を別のブレッドボードに載せた。ADC + ジョイスティックおもな構成品は以下のとおり (Arduino ADKは、+5Vの供給用にのみ使用)。

  • AE-ESP-WROOM-02
    秋月電子のWROOM-02 DIP化キット。
  • MCP3002
    Microchip Technology社の、2チャネル10bit 逐次比較型A/Dコンバータ。SPI方式のシリアルI/F付。
    秋月電子の通販で180円だった。回路作りやプログラミングには、秋月の通販ページにリンクされているデータシートを参考にした。
  • TA48033S
    東芝の3.3V三端子レギュレータ。Arduino ADKの5V出力を接続し、WROOM-02、MCP3002、ジョイスティックに3.3Vを供給する。
  • PARALLAX 2-axis Joystick
    秋月電子の通販で購入した2軸アナログジョイスティック。センターリターン用のスプリング入りで手を離すと勝手に中央に復帰する。780円だったが、AE-ESP-WROOM-02が650円なので高く感じてしまう。
    PARALLAX ジョイスティック説明書きや仕様はパッケージの紙の裏側に書いてある。PARALLAX ジョイスティック重要なポイントは、各軸には10KΩのボリューム抵抗が入っており3.3~5Vで動きますよ、ということだろう。PARALLAX ジョイスティック親指で操作するのにちょうどよい程度の大きさだが、リターンスプリングがちょっと強め。
ジョイスティックの値の読み取り

アナログ式のジョイスティックでは、スティックの倒し加減に応じて可変抵抗による電源(+3.3V)の分圧のされ方が変わるので、LEFT/RIGHT方向およびUP/DOWN方向の各出力には、それぞれおよそ0~3.3Vの電圧が現れる。
今回の構成では、A/Dコンバータでそれぞれの電圧を読み取り、デジタル値に変換して利用する。mcp3002が10bit出力なので、倒し具合に応じて0~1023の範囲のデジタル値が現れる。回路図にあるように、ジョイスティックの2つの出力(L/RおよびU/D)は、A/Dコンバータのch0とch1に接続している。

mcp3002は、SPI方式のシリアルI/Fを備えているので、WROOM-02との接続線は4本で済む。そのうち2本が(mcp3002から見て)データ入力用(Din)および出力用(Dout)で、残りが変換動作の許可用(CS)と、データ入出力時の同期信号(CLK)になる。WROOM-02にはあまりGPIOポートに余裕がないので、4本で済むのはとても助かる。今回は以下のように接続した (左側がWROOM-02で右側がMP3002)。

  • IO2 — CS/SHDN
  • IO4 — Din
  • IO5 — Dout
  • IO16 — CLK

※ 今回の接続では、WROOM-02の備えるSPI機能は利用しておらず、GPIOポートのHIGH/LOWの読出し/書込みによってI/Fを実装した。

A/D変換シーケンス

WROOM-02側から見たA/D変換の実施指示と値の取得は以下のような手順で行う。

  • CS(Chip Select)をアクティブ化
    IO2をLOWとする。初期化時や変換終了後はHIGHにしておく。
  • 変換対象のチャネルを指定
    ch0ならば1101B 、ch1ならば1111Bの4ビットを、最上位ビットから順に書き込む。書込みが終わるころにはADC内部のS/Hコンデンサに電荷がたまり逐次比較が開始する。
  • 変換結果の読出し
    スタートビット(0)を含めて11ビットを読み出す。A/Dコンバータはスタートビットの後、MSBから順にデータを送り出してくる。
  • CSを非アクティブ化
    IO2をHIGHとする。これによって、mcp3002はスタンバイ状態に戻る。

対象チャネルの書込み、結果データの読出し共によく似た操作になっていて、

  • 書込み時には、DinをHIGHまたはLOWに設定して、CLKの立ち上がりエッジを与え、規定時間待った後に下げる。
  • 読出し時には、CLKの立ち上がりエッジを与え、規定時間待った後にDoutがHIGHかLOWかを読み取ってCLKを立ち下げる。
  • 以下に載せたスケッチでは、CLKの上げ下げやポートとのやり取りを分かりやすく書いたので、「規定時間の待ち」を delayMicroseconds(1); で表現した。しかしながら、データシートに書かれているタイミングチャートから分かるように、チップ自体はもっと高速に変換動作を行える。より高速なデータ収集が必要なら別の書き方になる。
 スケッチ

いろいろなテストや検証の意味で、ジョイスティックのUP/DOWN方向の倒し具合により、LEDの点滅速度が変わるスケッチを作ってみた。また、UP/DOWN、LEFT/RIGHTそれぞれが直前の読み取り値と10以上変化した値を返した場合、シリアルモニタに読み取り値を送信する。
ESP8266 CommuinityのTickerライブラリを使用していて、各チャネルの値の読出しは10msec単位に行っている。

シリアルモニタの様子を見てみると、UP/DOWN、LEFT/RIGHTともに、中央に自動リターンしたときは、500~510の範囲の値を示し、両端を含めて操作すると0~1023の値が出てくる。使い始めたばかりだからかもしれないが、中立時にも値がふらついたりはしなかった。

変換速度について

adc_read() という関数で指定チャネルの変換と読出しを行っている。いかにも遅そうなので、loop()を以下のようにして時間を測ってみた。なお計測時には、ticker.attach_ms() はコメントにしておいた。

シリアルモニタには、10000回のループに要する時間がミリ秒単位で表示され、常に877という結果だった。素直に受け取ると、adc_read()の呼び出し一回につき87.7μ秒となる。10ksps程度の変換レートまでなら、こんな具合ののんびりしたコードでよさそうである。

操作例

ジョイスティックを操作しているところを動画にしてみた。撮影しやすいようにLEDを手前のブレッドボードに持ってきている。

きょうのまとめ

クロックを15回上げ下げすることでチャネル指定とデータ読み出しができた。SPI用のライブラリ関数は使わなかったのだけど、ジョイスティックが相手ならこんなもんでいいだろうし、例えばサーボの駆動を含んだ ticker_func()に追加しても、さしたる影響はないだろう。ということは、サーボを駆動する側の回路にジョイスティック周りを載せて、wifiではなく有線でコントロールというのもアリかもしれない。

サクラの季節も近づいてきたので、ちょっと頑丈な自撮棒の先にサーボ雲台を載せ、ふだんとは違う視点でAIR A01を使ってみるのも面白いかも、とか思い始めているところ。