シンプルなArduinoストップウォッチ:ボタンで動作するクロノメーターの作り方
必要な部品と用品
| 部品 | 説明 | 数量 |
|---|---|---|
| Arduino UNO | どのArduinoでも可、場合によってはArduino以外でも可能 | 1 |
| タクトスイッチ(非ラッチング) | プルダウン抵抗(1kΩ使用)とセットで | 1 |
| 抵抗 10kΩ | 1 |
アプリとオンラインサービス
| ツール | 説明 |
|---|---|
| Arduino IDE |
プロジェクト概要
あるプロジェクトで、ボタンを押している間だけ時間を計測するArduinoクロノメーターが必要になりました。複雑なものではありませんが、このコードが他の方のプロジェクトの参考になればと思い公開します。おそらく1時間程度のコーディング時間を節約できるはずです。
EEPROM(不揮発性メモリ)
電源を切ってもデータが保持されるArduino内部のメモリです。#include <EEPROM.h>ライブラリを使用します(標準でインストール済み)。
割り込み(Interrupts)
Arduino内部で処理が進行中でも、特定のピンがHIGHになった瞬間に実行を中断し、ISR(割り込みサービスルーチン)を実行させる機能です。追加ライブラリは不要です。
プロジェクトのコード
定義とインクルード
#include <EEPROM.h>
#define interruptPin 2
#define eeAddress 0 // EEPROMのアドレス(内部不揮発性メモリ)
float starttime = 0; // 計算用変数
float endtime = 0;
float resulttime = 0, oldresulttime = 0;
EEPROMライブラリをインクルードし、ボタンをピン2に接続。EEPROMのアドレス0を使用(Arduino UnoはATmega328で1024バイトありますが、整理のためアドレス0を選択)。
setup()
void setup() { Serial.begin(9600); while (!Serial) { ; // シリアルポート接続待ち(ネイティブUSBポートの場合のみ必要) } Serial.println("Serial comms are ready sir!:.. bip bip"); attachInterrupt(digitalPinToInterrupt(interruptPin), refreshTime, CHANGE); }通常のシリアル通信初期化(9600ボーレート)に加え、
attachInterrupt(digitalPinToInterrupt(interruptPin), refreshTime, CHANGE);で割り込みを設定。
CHANGEモードなので、ピンの論理レベルが変化するたび(LOW→HIGH、HIGH→LOW両方)にトリガーされます。プルダウン抵抗により、ボタンを押していないときはLOWに固定されます。loop()
void loop() { // ここにメインの処理を書く! }メインループは空。割り込みで処理するため、ここに他の処理を入れられます。
その他の関数
void refreshTime() { if (digitalRead(interruptPin)) { starttime = millis(); Serial.print("Start time: "); Serial.println(starttime); } else if (digitalRead(interruptPin) == LOW) { endtime = millis(); resulttime = endtime - starttime; Serial.print("End time: "); Serial.println(endtime); Serial.print("Result time: "); Serial.println(resulttime); WhatsNewEeprom(); // EEPROMに保存 } }割り込み発生時に実行される関数。ピンがHIGHなら開始時刻、LOWなら終了時刻を記録し、差分を計算。最後にEEPROM保存処理を呼びます。
void WhatsNewEeprom() { Serial.println("-----------checking eeprom"); EEPROM.get(eeAddress, oldresulttime); Serial.print("oldresulttime"); Serial.println(oldresulttime); Serial.print("resulttime"); Serial.println(resulttime); if (resulttime != oldresulttime) { EEPROM.put(eeAddress, resulttime); Serial.print("-----Ding! New time recorded in eeprom: "); Serial.println(resulttime); } else { Serial.println("No new time found, eeprom was not disturbed"); } }EEPROMに保存されている値と新しい計測値を比較し、異なれば更新します。
おまけ:ボタンのチャタリング対策
![]()
人間のボタン操作はArduinoにとって非常に遅く、一度の押下で信号がハイ・ローを繰り返す「チャタリング」が発生します。対策はソフトウェア・ハードウェア両方で可能です。
- ソフトウェアでのデバウンス
- ハードウェアでのデバウンス:コンデンサを使う!
センスピンとGNDの間に220nFのコンデンサを並列接続します。コンデンサが急激な電圧変化を吸収してくれます。
コード
arduino chronometer (Arduino)
EEPROMと割り込みを使用、容易に改造可能
// coded by Javier Muñoz 23/10/2017
// questions to javimusama@gmail.com
#include <EEPROM.h>
#define interruptPin 2
#define eeAddress 0
float starttime = 0;
float endtime = 0;
float resulttime = 0, oldresulttime = 0;
void setup() {
Serial.begin(9600);
while (!Serial) { ; }
Serial.println("Serial comms are ready sir!:.. bip bip");
attachInterrupt(digitalPinToInterrupt(interruptPin), refreshTime, CHANGE);
}
void loop() {
// ここに処理を追加
// (EEPROM保存済み) 最後の計測時間(ミリ秒)"float resulttime"
}
void refreshTime() {
if (digitalRead(interruptPin)) {
starttime = millis();
Serial.print("Start time: ");
Serial.println(starttime);
} else if (digitalRead(interruptPin) == LOW) {
endtime = millis();
resulttime = endtime - starttime;
Serial.print("End time: ");
Serial.println(endtime);
Serial.print("Result time: ");
Serial.println(resulttime);
WhatsNewEeprom();
}
}
void WhatsNewEeprom() {
Serial.println("-----------checking eeprom");
EEPROM.get(eeAddress, oldresulttime);
Serial.print("oldresulttime"); Serial.println(oldresulttime);
Serial.print("resulttime"); Serial.println(resulttime);
if (resulttime != oldresulttime) {
EEPROM.put(eeAddress, resulttime);
Serial.print("-----Ding! New time recorded in eeprom: "); Serial.println(resulttime);
} else {
Serial.println("No new time found, eeprom was not disturbed");
}
}
回路図
プルダウン抵抗付きボタンのシンプルな接続
製造プロセス
- Adafruit 60 LED NeoPixelリングとArduinoで作るスタイリッシュな壁掛け時計
- DIY Arduinoワードクロック – 文字で時刻を表示する洗練されたリアルタイムクロック
- Arduino Nanoで20kHzオシロスコープを自作:Nokia 5110 LCD搭載・簡易DIYガイド
- Bluetooth操作のArduinoスパイボットを自作する
- FlickMote:ジェスチャー操作のIRリモコンでスマートホームを制御
- 自作Arduino TV-B-Gone:全テレビ対応の万能リモコン
- 12メートル先から見える大型LEDマスタークロック(アラーム機能付き)を自作しよう
- Arduinoでシンプルな障害物センサーを自作 – IR LEDとフォトダイオード入門
- ArduinoとBluetoothで作るスマート紛失防止タグ「Find Me」
- Arduinoプロジェクトのための最適化電源ソリューション
- DS1302 RTCとArduino UNOで作る信頼性の高い目覚まし時計