連打速度を測りたい[Arduino UNO]
ほんの少しだけ実用(?)的な物を考えてみました。
いわゆるシュウォッチ的なやつですね。
使用した物
- Arduino UNO R3
- 適当なスイッチ
Arduino Uno R3
いつものですね。
適当なスイッチ
ON/OFFできるスイッチであれば一応なんでも良いです。
上の写真のものはPC用のリセットスイッチで、PCパーツショップで売っています。
コネクタも最初から付いているので、実験には便利ですね。
ただ、実際に連打力を計りたいのであれば、もっとしっかりとしたスイッチが必要ですね。
こういうのとかも使えます。ビー玉でこすったり金属定規で弾いたりしたい人はどうぞ。
作った回路
デジタル2番ピンと、GND端子のあいだにスイッチを繋ぐだけです。簡単ですね。
実装概要
スイッチを押すと測定を開始し、10秒間ボタンを押された回数をカウントします。
10秒はタイマーライブラリを使用します。そのため、タイマーライブラリのインストールが必要です。
タイマーライブラリのインストール方法は、 Arduino IDEのメニューの
スケッチ→ライブラリをインクルード→ライブラリを管理
から、ライブラリマネージャを開き、右上に
MSTIMER2
と入力し、ライブラリを検索します。
MSTIMER2が見つかるはずですので、インストールボタンを押して下さい。
スケッチ
連打速度測定機
#include <MsTimer2.h>
// 変数の定義
#define SW_PIN 2
int timercnt;
void setup() {
pinMode(SW_PIN, INPUT_PULLUP);
Serial.begin(9600);
}
void timerHandler() {
//タイマ満了時呼び出される
timercnt++;
}
void loop() {
int state_old;
int state;
int cnt;
char buf[128];
MsTimer2::set(10000, timerHandler);
Serial.println("Standby...");
//ボタンが押されるのを待つ
while (digitalRead(SW_PIN) == HIGH) {}
Serial.println("Ready...");
for (cnt = 3; cnt != 0; cnt--) {
sprintf(buf, "%d", cnt);
Serial.println(buf);
delay(1000);
}
Serial.println("Go!");
timercnt = 0;
MsTimer2::start();
while (timercnt == 0) {
state = digitalRead(SW_PIN);
if (state_old != state) {
if (state == LOW) {
cnt++;
sprintf(buf, "cnt=%d", cnt);
Serial.println(buf);
}
state_old = state;
delay(5);//チャタリング防止用
}
}
Serial.print("average=");
dtostrf(float(cnt) / 10, 3, 1, buf);
Serial.println(buf);
//次のStandbyに行く前に適当に待つ
delay(3000);
}
使いかた
スケッチをArduinoに書き込んだら、Arduino IDEのメニューの
ツール→シリアルモニタ
から、シリアルモニタを表示します。
シリアルモニタには、
「Standby...」
が表示されていると思います。
この状態でスイッチを押すと、
「Ready...」
からカウントダウンが始まり、
「Go!」
と表示が変わります。ここから計測開始ですので、頑張って連打してみましょう。
ボタンを押す毎にカウンタが増えていき、10秒後に平均値が表示されます。
その後、また、最初の動作に戻ります。
動作説明
電子工作的にキーになるところのみ解説します。
INPUT_PULLUP
スケッチのpinMode設定で、modeをINPUT_PULLUPに設定してあります。
これは通常のINPUTとは異なり、内蔵pull Up抵抗を有効にする設定となります。
内蔵pull Up抵抗を有効とした場合、PINと5Vの間に抵抗が接続されているのと同じ状態になります(厳密にはCPU内部で有効になります)。
そのため、SWがOFFの状態では、CPUの入力には5Vの電圧が見えることになり、「HIGH」状態となります。
また、SWがONの状態では、CPUの入力には0Vの電圧が見えることになりますので、この場合は「LOW」状態となります。
スイッチのON/OFFとLOW/HIGH状態が逆に感じますが、こういう物です。
もちろん、スイッチがONの状態ではpull Up抵抗を通して電流が流れますので、スイッチONの場合は回路全体として消費電力は多少増えることになります。
抵抗値が少なすぎると消費電力は増えますし、逆に大きすぎるとノイズに弱い設計となってしまいます。
だいたい、3.3Vや5V前後で動作する回路であれば、10kΩ~47kΩあたりを使うのが一般的です。
このように、内蔵pullUp設定を使用すると、スイッチ以外の外部部品を使用すること無くスイッチを読み取ることができるため、部品点数の削減にもなり便利ですね。
チャタリング防止
スイッチは、基本的な構造としてはスイッチを押すことで金属板2つが接触して導通する仕組みです。
この、スイッチを押した瞬間、もしくは離した瞬間にチャタリングという現象が発生します。接触不良の一種です。
これが実際にボタンを押した瞬間の波形ですが、綺麗に切り替わるのでは無く、多数のノイズが乗っているのが見えますね。
このノイズをプログラムが拾ってしまうことで、1度ボタンを押しただけなのに数回分カウントされるという現象が起きます。
この波形だと約0.4msで安定していますが、スイッチをゆっくり押したりすると安定するまでに数msかかることもあります。
なので、スイッチの状態変化を検出したあとは、ある一定期間は状態検出を行わないという対処が必要になります。これがチャタリング防止です。
安定するまでにどのくらいの期間が必要なのかはスイッチによって異なりますので、ある程度試行錯誤が必要になります。
短すぎるとチャタリングが防ぎきれず、長すぎると連打などの反応が悪くなります。
ちなみに、仮に秒間16発の連射を拾おうとすると、SW OFF→ON→OFFを1秒間に16回繰り返すため、1秒間に32回の状態変化が発生します。
1000ms÷32回≒31msとなりますので、このくらいの速度の連射を数えるのであれば、チャタリング防止は最大でも31ms程度におさめないとダメなことになります。
今回のソースでは5msとしていますので、秒間100回くらいまでは数えることができるはずです。その他処理(たとえばシリアルへの出力)もあるので、実際には100回はカウントできません。
ですが、どちらにせよ人間が連打する速度ではありませんね。じゅうぶんでしょう。
かっこよくする
さて、やりたい動作がちゃんとできていることがわかったら、かっこよくしてみましょう。
・
・
・
・
・
・
はーい、無駄にかっこよくなりましたね。
おわりに
単純に連射速度を測るのでは無く、一番速度が速かったピーク値を測定するとか、離してから押すまでの時間を測定するとか、連射速度のゆらぎを測定するとか、いろいろ測定するネタはありそうです。
ただ、その場合だと、「特定のイベント間の時間を計る」という使い方になるので、タイマーの使用方法がかわりますので、このサンプルを多少改造する程度では難しいと思います。
あと、Leafony欲しい!
投稿者の人気記事
-
lyricalmagical
さんが
2020/04/24
に
編集
をしました。
(メッセージ: 初版)
-
lyricalmagical
さんが
2021/12/29
に
編集
をしました。
ログインしてコメントを投稿する