ゲームのコントローラーやラジコンなどで使われているジョイスティック。
レバーを前後左右へ倒すことで、方向や操作量を入力できるデバイスです。
電子工作向けにもジョイスティックモジュールが販売されており、ArduinoやESP32などのマイコンと接続して、
- 前後左右の方向を検出する
- レバーを倒した量を取得する
- モーターの方向や速度を操作する
- ロボットやモーターカーを操作する
といったことができます。
この記事では、ジョイスティックの内部がどのような仕組みになっているのか、そしてマイコンからどのようにX・Y方向を読み取るのかを解説します。
ジョイスティックとは?
ジョイスティックは、レバーを倒した方向と大きさを入力できるデバイスです。
一般的な電子工作用の2軸ジョイスティックでは、
X軸:左右方向
Y軸:前後方向
の2つの値を取得できます。
レバーを動かすとX軸とY軸の値が変化します。
Y+
↑
│
│
X- ←──── ● ────→ X+
│
│
↓
Y-
中央にあるときはX軸・Y軸ともにほぼ中央の値になります。
右へ倒すとX軸が変化し、前へ倒すとY軸が変化します。
斜めへ倒した場合は、X軸とY軸の両方が変化します。
ジョイスティックの中には可変抵抗が入っている
電子工作用ジョイスティックの仕組みは、それほど複雑ではありません。
一般的な2軸ジョイスティックには、**2つの可変抵抗(ポテンショメータ)**が入っています。
1つがX軸用、もう1つがY軸用です。
レバーを左右へ動かすとX軸側の可変抵抗が動き、前後へ動かすとY軸側の可変抵抗が動きます。
つまり、
レバーを動かす
↓
可変抵抗の位置が変わる
↓
出力電圧が変わる
↓
マイコンで電圧を読み取る
という仕組みです。
なぜ方向を数値として取得できるの?
ジョイスティックの可変抵抗には電源とGNDを接続します。
その中間にある端子から、レバーの位置に応じた電圧が出力されます。
たとえば3.3Vで使用する場合、レバーが中央にあれば概ね中間付近の電圧になります。
3.3V
│
[ 可変抵抗 ]
│
├── X軸出力
│
GND
レバーを一方へ倒すと出力電圧が0V側へ近づき、反対側へ倒すと3.3V側へ近づきます。
Y軸にも同じような可変抵抗があります。
そのためマイコンから、
X軸の電圧
Y軸の電圧
という2つの値を測定すれば、ジョイスティックがどちらへ倒されているのか分かります。
ジョイスティックではADCを使う
ジョイスティックから出てくるのは、HIGHまたはLOWだけではありません。
レバーの位置によって連続的に電圧が変化します。
そこで使用するのが**ADC(A/D変換)**です。
ADCは、アナログ電圧をマイコンで扱える数値へ変換する機能です。
たとえば、
ジョイスティック
↓
電圧変化
↓
ADC
↓
数値として取得
という流れになります。
デジタル入力では、
LOW / HIGH
の2状態しか読み取れません。
一方、ADCを使うことで、
500
1200
2048
3100
3900
といった途中の値も取得できます。
これによって、単に「右か左か」だけではなく、どのくらいレバーを倒しているのかまで分かります。
ジョイスティックモジュールの端子
一般的な電子工作用ジョイスティックモジュールには、次のような端子があります。
| 端子 | 内容 |
|---|---|
| VCC | 電源 |
| GND | GND |
| VRx | X軸のアナログ出力 |
| VRy | Y軸のアナログ出力 |
| SW | 押し込みスイッチ |
製品によって端子名や並び順が異なる場合があります。
接続する前に、使用するジョイスティックモジュールの仕様を確認してください。
今回は方向を取得するため、主にVRxとVRyを使用します。
ジョイスティックは押すこともできる
一般的なジョイスティックモジュールには、レバーを倒すだけでなくレバーそのものを押し込むスイッチが搭載されているものもあります。
この場合、SW端子をマイコンのデジタル入力へ接続します。
すると、
X軸 → 左右
Y軸 → 前後
SW → 押し込み
という3種類の入力を1つのジョイスティックから取得できます。
たとえばモーターカーなら、前後左右の操作に加えて、押し込みを別の機能へ割り当てることもできます。
マイコンへ接続する
ジョイスティックをマイコンへ接続する場合は、基本的に次のようになります。
ジョイスティック マイコン
VCC ───────── 3.3V
GND ───────── GND
VRx ───────── ADC対応GPIO
VRy ───────── ADC対応GPIO
SW ───────── GPIO
重要なのは、VRxとVRyをADCが利用できるGPIOへ接続することです。
使用するマイコンによってADCを利用できるGPIOが異なるため、ピン配置を確認して接続してください。
また、マイコンの入力可能な電圧を超えないように注意してください。
Arduinoでジョイスティックの値を読み取る
Arduino環境では、analogRead()を使ってアナログ入力を読み取れます。
たとえば、
const int JOYSTICK_X = 0;
const int JOYSTICK_Y = 1;
void setup() {
Serial.begin(115200);
}
void loop() {
int x = analogRead(JOYSTICK_X);
int y = analogRead(JOYSTICK_Y);
Serial.print("X: ");
Serial.print(x);
Serial.print(" Y: ");
Serial.println(y);
delay(100);
}
のようにします。
※JOYSTICK_XとJOYSTICK_Yには、実際に使用するADC対応GPIOを指定してください。
シリアルモニターを開きながらジョイスティックを動かしてみましょう。
中央の値を確認する
まずジョイスティックに触らず、中央に戻した状態の値を確認します。
たとえば12bitのADCであれば、中央付近では概ね、
X: 2048
Y: 2048
のような値になることが考えられます。
ただし、必ずぴったり2048になるわけではありません。
実際には、
X: 1990
Y: 2075
のように少しずれることがあります。
これはジョイスティックの個体差や可変抵抗の特性などによるものです。
そのため、プログラムでは中央の値を1点だけで判定するのではなく、ある程度の範囲を持たせます。
デッドゾーンを作る
たとえば中央付近を、
1700 ~ 2400
とします。
この範囲に入っている場合は、
「ジョイスティックを操作していない」
と判断します。
このような中央付近の無反応範囲をデッドゾーンと呼びます。
操作範囲
0 ────────┬────────┬──────── 4095
│ │
1700 2400
└────────┘
デッドゾーン
デッドゾーンを設けることで、ジョイスティックのわずかなズレや値の揺れによる誤動作を防げます。
前後左右を判定する
X軸とY軸の値を使えば、ジョイスティックがどちらへ倒されているのか判定できます。
たとえば、
const int LOW_THRESHOLD = 1700;
const int HIGH_THRESHOLD = 2400;
として判定します。
if (y > HIGH_THRESHOLD) {
Serial.println("前");
}
else if (y < LOW_THRESHOLD) {
Serial.println("後ろ");
}
else if (x < LOW_THRESHOLD) {
Serial.println("左");
}
else if (x > HIGH_THRESHOLD) {
Serial.println("右");
}
else {
Serial.println("中央");
}
これでジョイスティックの操作を、
前
後ろ
左
右
中央
という5つの状態へ変換できます。
実際のX・Y方向や値の増減方向はジョイスティックの取り付け方向によって変わるため、シリアルモニターで確認しながら調整してください。
斜め方向も分かる
先ほどのプログラムではelse ifを使っているため、前後左右のどれか1方向として判定されます。
しかし実際のジョイスティックでは、X軸とY軸が同時に変化します。
そのため、
X:右方向
Y:前方向
なら、
右斜め前
へ倒していることも判断できます。
たとえば、
bool forward = y > HIGH_THRESHOLD;
bool backward = y < LOW_THRESHOLD;
bool left = x < LOW_THRESHOLD;
bool right = x > HIGH_THRESHOLD;
として個別に判定すれば、
forward && right
→ 右斜め前
のような処理もできます。
「方向」だけでなく「倒した量」も使える
ジョイスティックの面白いところは、前後左右を判定できるだけではありません。
ADCで連続した値を取得しているため、レバーをどのくらい倒したかも利用できます。
たとえば、
中央
↓
少し倒す
↓
大きく倒す
↓
最大まで倒す
という変化を数値として取得できます。
この値をPWM制御と組み合わせれば、
少し倒す
↓
PWM小
↓
モーター低速
大きく倒す
↓
PWM大
↓
モーター高速
という操作ができます。
ゲームのアナログスティックのように、操作量によって動作量を変えられるわけです。
ジョイスティックで何が作れる?
ジョイスティックは、方向や操作量を入力したい電子工作で幅広く利用できます。
たとえば、
- モーターカーの操作
- ロボットの操作
- サーボモーターの角度制御
- カメラのパン・チルト操作
- メニュー画面の操作
- 無線コントローラー
- ゲーム用入力デバイス
などがあります。
特にモーター制御とは相性がよく、
ジョイスティックの方向 → モーターの回転方向
ジョイスティックを倒した量 → モーターの速度
という対応にできます。
ESP-NOWと組み合わせれば無線リモコンにもできる
ジョイスティックから取得したX・Yの値は、同じマイコンの中だけで使う必要はありません。
ESP32シリーズであれば、ESP-NOWを使って別のESP32へ送信できます。
ジョイスティック
↓
ADC
↓
KUMITATE-C3
↓
ESP-NOW
↓
KUMITATE-C3
↓
モータードライバ
↓
モーターカー
この構成にすると、ジョイスティックを使った無線モーターカー用コントローラーを作れます。
前後左右だけでなく、ジョイスティックを倒した量を送信すれば、モーターカーの速度や曲がり方まで連続的に操作できます。
KUMITATE-C3のGPIO拡張コネクターでも試せる
KUMITATE-C3にはGPIOを外部へ接続するための拡張コネクターがあります。
ADCに対応したGPIOを利用すれば、外付けのジョイスティックからX・Yのアナログ値を読み取る実験にも利用できます。
これまでボタンのようなデジタル入力を扱ってきた場合は、ジョイスティックを使うことで、
HIGH / LOWを読み取るデジタル入力
から、
連続した値を読み取るアナログ入力
へ学習を広げることができます。
まとめ
今回はジョイスティックの仕組みと、マイコンからX・Y方向を読み取る方法を紹介しました。
ジョイスティックのポイントは、
- X軸とY軸の2方向を取得できる
- 内部には可変抵抗が使われている
- レバーの位置によって出力電圧が変化する
- ADCを使ってアナログ電圧を数値として読み取る
- X・Yの値から前後左右を判定できる
- 中央付近にはデッドゾーンを設ける
- レバーを倒した量も取得できる
- PWMと組み合わせれば速度なども連続的に操作できる
というところです。
単純なボタンでは「押した・押していない」という2つの状態しかありません。
ジョイスティックでは、方向と操作量を同時に取得できるため、より直感的な操作装置を作ることができます。
次はこのジョイスティックをKUMITATE-C3へ接続し、ESP-NOWで操作情報を送信して、モーターカーを無線操作してみましょう。


