Arduino内部タイマーをマスターして精密なタイミング制御を実現する
必要な部品と材料
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino UNO | 1 | |
| LED(汎用) | 1 | |
| 抵抗 220Ω | 1 |
プロジェクト概要
概要
正確な時間計測が必要な場合、タイマーを使用しますが、Arduinoの内部タイマーは扱いが難しいとされています。本チュートリアルでは、できるだけ分かりやすく解説します。
delay()関数ではその間何もできませんが、タイマー割り込みを使えば、指定時刻に割り込みが発生し、メインループをブロックせずに処理を実行できます。
ここでは最も扱いやすいTimer0を使用します(他のタイマーは今後解説予定)。
仕組み
ATmega328Pのデータシートを参照します。カウンターブロック図を見ると、クロックサイクルからプリスケーラーを経て制御ロジックへパルスが入り、TCNTnレジスタがインクリメントされます。
TCNTnの値を特定値(OCRnレジスタ)と比較し、一致したら割り込みを発生させる「CTCモード(Clear Timer on Compare)」を使用します。
プリスケーラーでクロックを分周できます。16MHzをそのまま使うと速すぎるため、TCCR0Bレジスタで分周比を設定します。
目標時間に対するOCRnの値は以下の式で求めます:
OCRn = (クロック周波数 / プリスケーラー) × 目標時間 - 1
例:1ms割り込み(16MHz、プリスケーラー64)
TCCR0A |= (1 << WGM01); // CTCモード設定
OCR0A = 0xF9; // 249 = 1ms @ 16MHz/64
TIMSK0 |= (1 << OCIE0A); // 比較一致割り込み許可
sei(); // グローバル割り込み許可
TCCR0B |= (1 << CS01) | (1 << CS00); // プリスケーラー64(カウント開始)
※プリスケーラー設定は最後に行うこと(設定時点でカウント開始するため)。停止するにはTCCR0Bをクリアします。
サンプルコード:1秒ごとにLED点滅
int timer = 0;
bool state = 0;
void setup() {
pinMode(13, OUTPUT);
TCCR0A = (1 << WGM01); // CTCモード
OCR0A = 0xF9; // 1ms
TIMSK0 |= (1 << OCIE0A); // 割り込み許可
sei(); // グローバル割り込み許可
TCCR0B |= (1 << CS01) | (1 << CS00); // プリスケーラー64
}
void loop() {
if (timer >= 1000) { // 1000ms = 1秒
state = !state;
timer = 0;
}
digitalWrite(13, state);
}
ISR(TIMER0_COMPA_vect) {
timer++; // 1msごとにインクリメント
}
回路図

製造プロセス
- Bluetooth操作のArduinoスパイボットを自作する
- FlickMote:ジェスチャー操作のIRリモコンでスマートホームを制御
- 自作Arduino TV-B-Gone:全テレビ対応の万能リモコン
- 12メートル先から見える大型LEDマスタークロック(アラーム機能付き)を自作しよう
- ArduinoとBluetoothで作るスマート紛失防止タグ「Find Me」
- Arduinoプロジェクトのための最適化電源ソリューション
- Arduino三目並べ:MAX7219 LEDマトリクスと段ボールケースで自作
- スマートArduino四足歩行ロボットの製作:ステップバイステップガイド
- ゲーム用カスタムArduinoジョイスティックハンドルの製作
- Arduino Nano R3で本格的なCNCマシンを自作する
- Earth Analyzer: 農業支援のための高度IoT環境監視ローバー