こんにちは。
今日の技術話も、自作のコントローラーについてです。
ついに今回は、気になる(?)あの課題の解決方法を見てみたいと思います。
制作した回路は既に試してみたと思いますが、
実は、今のままでは1回ボタンを押しただけでも、文字が数多く入力されてしまいます。
しかも、このコントローラーには更なる問題が隠れているのです。
それは・・・
ボタンを押し続ける操作に対応していない、ということ
な、何だってー (-_-;
当方も最初に気づいたときは驚きました。なんせ、これでは操作できるゲームが限定されてしまいます(汗
押すだけのゲームもありますが、どうせなら押しっぱなしの操作にも対応させたい・・・。
押すだけの入力すらまともにできないし
ですが、これらの問題はすべてArduinoのプログラムを変えるだけで解決できます!
では、どこを変えればよいのでしょうか。
(プログラムの課題)
まず、今のプログラムのどこに問題があるかを考えましょう。
今のプログラムの処理内容は、下のように簡単なものです。
ボタンを押している(ピンへの入力がLOW) → キーボードで文字を打つ
一見するとこれで正しいと思われますが、スイッチの機械的な特性を考えると好ましくありません。
スイッチにはチャタリングという現象がつきもので、これはスイッチの接点が完全に接触する前に、微細な振動を発生する現象です。要は1回押しただけでも、瞬間的に何度もに押されてしまうのです。
では、この現象をどう対処すればよいか。
一番簡単なのは、入力状態が変化した後の特定の時間は処理しない、という手法です。
Arduinoにはdelay関数という、特定の時間だけ何もしないように待機させる処理もありますが、ここではmillis関数を使います。
millis関数は、Arduinoが起動してからの経過時間をミリ秒で返す関数で、時間がかかわる処理(ボタンを数秒押すなど)で利用されます。押した直後はキー入力処理を行い、その後の何ミリ秒かは処理をしないようにプログラムを書けば、チャタリングの影響を受けずにすみます。
チャタリングを無視するだけであればdelay関数でもよいのですが、押しっぱなしの処理を実装する際にボタンを押している時間が必要があるためこの関数を利用します。
そして、押しっぱなしの処理については、ボタンが一定時間を超えて押されていれば、キー押下の状態を維持する処理を実装すればよいのです。
実は、今のプログラムにあるもうひとつの問題は、キー入力を「打つ」という処理になっていることです。
Keyboard.writeという処理はキーボードを「打つ」、つまりキーを「押して」「離す」という一連の動作がセットで行われます。キーを一度離しているため、これでは何回呼び出しても押しっぱなしにはなりませんね。
キー押下を実装するには、Keyboard.pressという処理を代わりに実装します。
これは、一度呼び出すと指定のキーを押したままの状態にする関数で、Keyboard.releaseによって解除できます(でないと、ずっと押したままの状態になる)。
以上が大まかな修正点になります。これを踏まえたプログラムのソースがこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
; title="JoyStick_mouse.ino"]#define SW1 4 void setup() { pinMode(SW1, INPUT_PULLUP); } void loop() { static boolean preState = HIGH; // 前回の入力ピンの状態を保存 static long preTime = 0; //最後に入力が変化したときの時間を保存 boolean stateButton = digitalRead(SW1); long time = millis(); // 経過時間を計測 if(stateButton != preState){ // 入力ピンの状態が変化したとき preState = stateButton; if(stateButton == LOW){ Keyboard.press('x'); // キーボードのキーを押下 } else{ Keyboard.release('x'); // キーボードのキー押下を解除 } } else if(stateButton == LOW){ // スイッチが押されているとき if(time - preTime > 500){ // 押した時間が500ミリ秒を超えた場合 Keyboard.press('x'); } } else{ preTime = time; // 現在の時刻を保存 } delay(10); } |
前回と同様、このプログラムをコピぺしてArduinoに書き込めば、問題が解決できたことが確認できます。
では、新しく出てきた関数を中心に説明していきます。
・static変数
→ 関数内で定義すると、関数の処理が終わった後も値を保持し続ける変数になる。
・millis()
→ Arduinoが起動してからの経過時間を返す関数。
・Keyboard.press(key)
→ 指定のキー(key)ボタンを押下する命令を与える。
・Keyboard.release(key)
→ 指定のキー(key)のボタン押下を解除する。
(ゲームをやってみよう)
ここで早速、実際にゲームをプレイしてみましょう。
紹介するゲームは「Nano Ninja」というもので、1ボタンで操作できるアクションゲームです。
http://www.kongregate.com/games/Rogerup/nano-ninja
いかがでしょうか。
自作のコントローラーでゲームをプレイしてみると、キーボードで操作したときとは一味違った体験ができたかと思います。
次回は、アナログスティックを使ったコントローラーでも制作してみたいと思います。
さらば(・ω・)//
コメント