連射装置を作る
少しずつ基板遊びに役立つ装置を作っていくことにします。
まずはシューティングゲームなどでよく見かける連射装置です。
連射装置には以下の2つがあります。
- ボリューム連射
- シンクロ連射
⇒ ボタンのON/OFFは装置側のタイミングで行います。
ゲーム側とタイミングが合わないこともあるため連射装置につけたボリュームで調整します。
⇒ V-SYNC(垂直同期信号)に同期してボタンをON/OFFさせます。
今回はシンクロ連射装置を作ってみることにします。
V-SYNCってなんだ!?という方はまずはこちらをざっとご覧ください
速度可変のシンクロ連射装置を作る
せっかくなので連射速度は可変のタイプにしたいのです。よくバトルガレッガについているやつですね。
また柔軟に改良していけるものにしたいので、ソフト側で作りこめるものが向いていると感じました。
人気のRaspberryPIをはじめ数種類のマイコンを検討した結果、Arduinoを使用してみることにしたのでした。
- +5Vを出力できる
- OSがあるわけではないため使いやすそう
- V-SYNC(垂直同期)を扱いやすい
- オープンハードなので価格が安価
- 電子工作が苦手でも敷居を低く始められる
ボタンを入力するということは・・・
マイコンで自動化するにあたりテスターをつなげてボタンを押したり離したりしてみました。
ボタンやレバーはスイッチのようなものなのですね。入力すると電圧が+5Vに上がり電流が流れると。
連射装置やコマンドコントローラーのようにボタン・レバーの入力を自動化するには、適切なタイミングで+5V/0Vを切り替える装置があれば良さそうです。
ArduinoのGPIOは+5Vを出力できるのでとても都合がよいですね。
5枚ほど計測し直してみたのですが、ボタン離したときに+5V/ボタン押したときに0Vでした。
JAMMA基板の入力は負論理と聞いていたのでおかしいなーと思っていたのですが、、、
当エントリーの内容は参考程度と捉えていただいて、ぜひこちらもご覧ください。
V-SYNC割り込み
ちょうど接続されていたセガmodel3基板の同期信号をオシロに入力してみました。
黄色がV-SYNC(垂直同期信号)、水色がH-SYNC(水平同期信号)の波形です。
V-SYNCは垂直表示期間が上側の線(電圧が高い)、垂直帰線期間が下側の線(電圧が低い)になっています。
オシロで見たところV-SYNCは垂直帰線期間がくると電圧が下がることがわかったため、FALLING(下降するタイミング)で割り込みをかけ連射処理のサブルーチンを実行するようにします。
当初、V-SYNCはアナログRGBの1つの信号なので、A/Dコンバーター(Arduinoならアナログ入力)経由で入力させ「ある閾値を越えたらHIGH、それ以外はLOW」等と処理しなくてはならないと思っていました。
ところがどっこい拍子抜け。
int.0に入力するだけで割り込み処理させることができました。
これは便利!!
チャタリング防止
こちらのサイトの情報(ソース)をもとにチャタリング防止のコードを入れています。
このサイトのソースでは、前回の割り込み発生から20ms以上経ったときだけON/OFFの判定をするようになっていました。
シンクロ連射の場合、最短だと1F単位でボタン入力のON/OFFをしなければなりません。
1Fあたりの時間は秒間60フレームのゲームで約16.7msです。
チャタリングがその半分の時間続くことはないでしょうから、前回の割り込みから8ms以上経った時だけ連射処理するようにしています。
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 31 32 33 34 35 36 37 38 39 40 41 | int pin = 13; int button0 = 10; // 仮 volatile int ren[6] = {1,0,0,0,0,0}; volatile int ren_element = 0; // 現在の要素番号 volatile int ren_speed = 4; // 現在の連射速度(5:10発,4:12発,3:15発,2:20発,1:30発) volatile int button_now = 0; // 現在のボタン状況 volatile unsigned long time_prev = 0, time_now; unsigned long time_chat = 8; // 0.5F void setup() { pinMode(button0, OUTPUT); attachInterrupt(0, V_SYNC, FALLING); //垂直帰線期間で割り込み } void loop() { // ロータリースイッチを付けたらこの辺で連射モードを切り替える } void V_SYNC() { time_now = millis(); if ( time_now - time_prev > time_chat ) { // チャタリング対策 if ( ren_element >= ren_speed ) { // 配列をラップさせる時の判定 ren_element = 0; } else { ren_element = ren_element + 1; } if ( ren[ren_element] != button_now ) { button_now = ren[ren_element]; } if (button_now == 0) { digitalWrite(button0, LOW); } if (button_now == 1) { digitalWrite(button0, HIGH); } } time_prev = time_now; } |
動作確認
テストモードのINPUT TESTでボタン入力のON/OFFを確認しつつ、オシロスコープで波形を確認してみました。
黄色がV-SYNC(垂直同期信号)、水色がボタン入力です。
秒間30発
1Fごとにボタン入力がON/OFF切り替わっていることがわかります。
秒間20発
秒間15発
秒間12発
秒間10発
まとめ
思ったよりもあっさりできてしまいました。
Arduinoは素晴らしいですね!
あとはロータリースイッチに抵抗をつなげてArduinoと接続し、スイッチ位置ごとの電圧変化によって連射速度を切り替えるコードを書けば一段落の予定です。
想定通りに行くかはわかりませんが、今のところ順調にできているのでとても楽しみです。
これでバトルガレッガの基板を買っても大丈夫!!(あまりに高くて買う予定はないのですが・・・)