
電子工作のアプリ開発で手軽に使えるゲームパッドを作成しました。 レバー(サムスティック)とそれに内蔵されたプッシュスイッチのほか、3つのボタンを使うことができます。 マイコンのアナログ入力ピンを利用することで複数ボタンを1本の配線で済ませています。
ことの始まりは「マンデルブロ集合 改良版」で拡大・縮小・情報表示を方向キーで操作しようとしたことです。
十字キー(4つのボタン)は通常4つのGPIOを使用します。
レバーではない方のボタン(A,B,Cボタン)も個数分のGPIOを使用するので、合計7つのGPIOが必要です。
これではESP32-C3のようにGPIOの数が少ないマイコンでは対応できません。
そこで十字キーは、代わりにアナログレバー(サムスティック)を使用することにしました。
これならGPIOはX軸/Y軸入力の2つで済みます。このGPIOはアナログ入力に対応している必要があります。
一方、3個のボタンも抵抗分圧の仕組み(最適化したR-2Rラダー回路)により1つのGPIOで済ませることができます。
もちろん同時押しの組み合わせを判定することができます。このGPIOもアナログ入力に対応している必要があります。
結果、レバー+3ボタンをマイコンのアナログ入力ピン3つで読み取る仕組みとなりました。
サムスティックに内蔵のプッシュスイッチ(ここではPボタンと呼ぶ)は、敢えてデジタル入力ピンと接続しています。 ゲームパッドを縦持ちする場合、A,B,Cボタンは使わないがPボタンは使う、という使い方が考えられます。 ボタン1つなら単純にデジタル入力ピンに接続してHigh/Lowを読み取る方がよいです。
当ゲームパッドをマイコン(ESP32シリーズ)で使用するためのライブラリを作成しました。 ライブラリ内、GamePadクラスは、A,B,Cボタンを使用するコントローラー(いわゆるゲームパッド)を想定しています。 Joystickクラスは、A,B,Cボタンを使用しない(レバーとPボタンのみ使用する)、レバー操作主体のコントローラーを想定しています。
GitHub - GamePadLib
試作品でライブラリを開発したのち、専用基板化しました。 サムスティック部分は「ジョイスティックRKJXV122400R DIP化キット」(秋月電子通商[115433])を利用します。
専用基板はA,B,Cボタン、Pボタンの実装と読み取り方をある程度カスタマイズすることができます。
基板のP端子はマイコンのデジタル入力ピンへ接続、ABC端子はアナログ入力ピンへ接続する前提で、
ライブラリ側はデジタル入力ピンの値をPボタンの入力として読み、アナログ入力ピンの値をA,B,Cボタンの入力として読みます。
※ライブラリ内でデジタル/アナログ入力とボタン名の対応は固定。
この前提に合わせて基板上の配線を変更します。例えば…
Cボタンを実装せず、四角いパッドPを四角いパッドCへ配線します。 その結果、P端子からマイコンへの配線をなくすことができます(GPIOを1つ節約)。 パッド側でPボタンを押すとライブラリ側ではCボタンが押されたことになります。
抵抗を全て外し、四角いパッドAを四角いパッドPへ配線します。 その結果、ABC端子からマイコンへの配線をなくすことができます(GPIOを1つ節約)。 パッド側でAボタンを押すとライブラリ側ではPボタンが押されたことになります。
抵抗を全て外し、Aボタン下の2.2kΩの箇所をジャンパーショートします。 そしてABC端子をマイコンのデジタル入力ピンに接続し、High/Lowを読み取ります。 ※この場合、ゲームパッドライブラリでAボタンを読み取ることはできない。
プッシュスイッチ3個をアナログピン1つで読み取る実験。ESP32-C3のADCをmilliVoltモードで。上限理論値は3300mVだと思うが実測は2800mVだった。ESP32のADCはこういうもんなんだろう。同時押し含め誤判定なく動作したので実験完了。 pic.twitter.com/vTZao7SO3m
— 『昼夜逆転』工作室 (@jsdiy) April 12, 2026
縦持ち(レバーと軸のプッシュボタンのみの使用を想定)、横持ち(レバーと全ボタンの使用を想定)。ハンダ付けした部品の足が指に当たって痛いのでカバーを作成。ねじ頭が少しめり込む穴にしたとこがポイント。 pic.twitter.com/9aj9c2S18J
— 『昼夜逆転』工作室 (@jsdiy) May 21, 2026
初めはユニバーサル基板バージョンで十分だったのですが、ボタンスイッチも必要となり、GPIOが足りなくなり、 抵抗分圧方式をとることにし、動作実験が上手くいったので、専用基板で仕上げました。 でも実はライブラリを作り込んでいるときが一番面白かった気がします。