M5Stackのジョイスティック制御
ジョイスティックを使って、M5Stackのディスプレイ上に表示したカーソルの制御を行います。AD変換やディスプレイの表示方法などM5Stackの基礎的な部分は以下を参考にしました。
使用するジョイスティックの説明
ジョイスティック
使用するジョイスティックを以下の図に示します。M5Stackの下部にIMU基板を接続していますが、今回は使用しないので無視してください。
ジョイスティックの可動域とM5StackのanalogReadの取得値の関係を調べた結果、これらの関係は以下の図のようになっていました。
図において、オレンジで示した範囲がジョイスティックの可動域を、青で示
した領域がanalogReadで取得する値が変化する範囲を示します。また、青で示した領域の左上で取得される値と右下で取得される値(x,y)を図に示しました。
オレンジで示される領域では、値は最大値または最小値が取得されます。
図のように、実際の可動域に対して、analogReadの値が変化する範囲は小さく設定されていることが分かります。
M5Stackとジョイスティックの接続
M5Stackとジョイスティックのピンを以下のように接続します。
GND ⇔ GND
VRx ⇔ 35ピン
VRy ⇔ 36ピン
SW ⇔ 2ピン
Vin ⇔ 3.3V
今回は、M5Stackの内部プルアップを使用するため、SWとM5Stackの2ピンは直接接続します。内部プルアップを使用する場合、ピンのセットアップを以下のように行います。
pinMode(STICK_BUTTON, INPUT_PULLUP); // ジョイスティックボタン入力ピンの設定(内部プルアップ)
ジョイスティックのVRx,VRyは連続値を出力とするため、M5StackのAD変換用ピンである35,36ピンと接続します。AD変換に使用できるピンは限られているので注意してください。
カーソルの制御手法の説明
M5Stackの画面にカーソルを表示します。今回、ジョイスティックから取得した位置(VRx,VRy)をそのまま画面上の座標に変換することで、カーソル位置の指定を行います。
値の変換にはmap関数を使用します。map関数は以下のように使用します。
map(変換する入力値, 入力値の最小値, 入力値の最大値, 変換後の最小値, 変換後の出力値)
値の変換に使用するコードは以下のようになります。
map(X, 0, 4095, 0, M5.Lcd.width())
ここで、M5.Lcd.width()はM5Stackのディスプレイの横幅の最大値を取得します。
ソースコード
ソースコードの全体を以下に示します。カーソルはdrawEllipseによって丸を表示しています。
#include <M5Stack.h>
TFT_eSprite sprite = TFT_eSprite(&M5.Lcd);
#define STICK_X 35
#define STICK_Y 36
#define STICK_BUTTON 2
void setup() {
M5.begin();
M5.Speaker.begin();
M5.Speaker.mute();
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(2);
sprite.setColorDepth(8);
sprite.setTextSize(2);
sprite.createSprite(M5.Lcd.width(), M5.Lcd.height());
pinMode(STICK_X, INPUT); //スティックのX位置
pinMode(STICK_Y, INPUT); //スティックのY位置
pinMode(STICK_BUTTON, INPUT_PULLUP); // ジョイスティックボタン入力ピンの設定(内部プルアップ)
}
void loop() {
sprite.fillScreen(BLACK);
sprite.setCursor(0, 0);
int X = analogRead(STICK_X);
int Y = analogRead(STICK_Y);
sprite.printf("stick X :%d\n",X);
sprite.printf("stick Y :%d\n",Y);
sprite.printf("stick distance :%f\n",sqrt(pow(X, 2) + pow(Y, 2))); //原点からの距離
sprite.printf("stick button state :%d\n",digitalRead(2));
sprite.drawEllipse(map(X, 0, 4095, 0, M5.Lcd.width()), map(Y, 0, 4095, 0, M5.Lcd.height()), 10, 10, WHITE); //スティックの位置をLcdの位置に変換
sprite.pushSprite(0, 0);
delay(1);
}
画面更新時のディスプレイのちらつきを防ぐため、spriteを使って描画しています。spriteの使用方法は以下のサイトを参考にさせていただきました。
制御の様子
制御の動画を以下に示します。
まとめ
ジョイスティックを使って、カーソル位置の制御を行いました。今回使用した方法は実装は簡単でしたが、以下の問題点が挙げられました。
スティックを離すとカーソルが画面中央に戻ってしまう。
細かい位置操作が難しい
スティックを操作していない状態でも、誤差によってカーソルが微動する
この記事が気に入ったらサポートをしてみませんか?