背景
Arduinoでパルス波を受信したい場面に遭遇したので、備忘録を兼ねて割り込み処理を利用したパルスの読み取り方法を共有します。後日、周波数読取り用のライブラリを公開しました。
良ければこちらもご覧ください。
Arduinoで周波数を計測する便利ライブラリHzMeter_asukiaaaを作った
asukiaaa/arduino-HzMeter
使ったもの
- Arudino IDEかPlatformIOを使えるようにしたPC
- ProMicro2つ
片方に今回作成するプログラムを書き込みます。
もう片方には前回(Arduinoでus(マイクロ秒)間隔のパルスを作る方法)作成したパルス出力プログラムを書き込み、テスト用のパルスの発生源にしました。 - ブレッドボード
- ジャンパワイヤ
回路を作成
パルスを出力するProMicroの信号を、今回プログラムを作成するProMicroで受信できるように回路を作成します。ProMicroに使われるatmega32u4で割り込みを設定できるピンは 0,1,2,3,7のどれかなので、UartやI2Cで使われていない7番ピンで信号を受信します。
Arduino Unoの場合は2番ピンに割り込みを設定できます。
ほかのボードをお使いの場合はArduinoのattachInterrupts関数の解説ページで紹介されているボードごとの対応ピンを確認してください。
このように接続しました。
送信側 | 受信側 |
---|---|
VCC | VCC |
5(パルス送信ピン) | 7(パルス受信ピン) |
GND | GND |
実際に接続するとこのようになりました。
HIGHからLOWに変化した回数を計測
attachIntterupt関数を割り込みを設定できるので、GPIOへの信号がLOWからHIGHに変わった時に割り込み処理を実行します。割り込み処理では変化回数を記録するための変数に1を加算します。
loopでは1秒ごとに現在の変数の値を出力します。
#define PULSE_READ_PIN 7 unsigned long pulseCounter = 0; void onRising() { ++pulseCounter; } void setup() { pinMode(PULSE_READ_PIN, INPUT); attachInterrupt(digitalPinToInterrupt(PULSE_READ_PIN), onRising, RISING);
Serial.begin(9600); } void loop() { delay(1000); Serial.println("pulseCounter: " + String(pulseCounter)); Serial.println("at " + String(millis())); }
シリアルモニタでログを出力するとこのような情報を取得できました。
pulseCounter: 17504 at 7003 pulseCounter: 20006 at 8003 pulseCounter: 22507 at 9004 pulseCounter: 25008 at 10004 pulseCounter: 27509 at 11004 pulseCounter: 30010 at 12005 pulseCounter: 32511 at 13005 pulseCounter: 35012 at 14006
1秒に約2500回のパルスの立ち上がりを検出していました。パルスを出す側のArduinoは約200us毎にHIGHとLOWを切り替えているので、HIGHの周期は約2500Hzとなることから期待する値が読み取れているようです。
Timerで周波数に換算
パルスの値が周波数になっていた方が都合が良い場合があるので、FlexiTimer2を利用して0.5秒ごとに周波数を計算するプログラムも共有します。FlexiTimer2を使う場合、Arduinoの場合はFlexiTimer2のReleaseのページからzipをダウンロードして、Arduinoのライブラリディレクトリに配置してください。
PlatformIOの場合は、platformio.iniに「lib_deps = FlexiTimer2」を記述してください。
割り込みでパルスを読み取りTimerで周波数に換算するプログラムはこちらです。
#include <FlexiTimer2.h> #define PULSE_READ_PIN 7 #define CALC_HZ_INTERVAL_MS 500 unsigned long pulseCounter = 0; float currentHz = 0; void onRising() { ++pulseCounter; } void calcHz() { currentHz = (double) pulseCounter * 1000 / CALC_HZ_INTERVAL_MS; pulseCounter = 0; } void setup() { pinMode(PULSE_READ_PIN, INPUT); attachInterrupt(digitalPinToInterrupt(PULSE_READ_PIN), onRising, RISING); FlexiTimer2::set(CALC_HZ_INTERVAL_MS, 1.0/1000, calcHz); FlexiTimer2::start(); Serial.begin(9600);
} void loop() { delay(1000); Serial.println(String(currentHz) + "Hz at " + String(millis())); }
シリアルモニタでログを見ると計算の結果2500Hzになっていることを確認できます。
2500.00Hz at 2000 2500.00Hz at 3001 2500.00Hz at 4001 2500.00Hz at 5002 2500.00Hz at 6002 2500.00Hz at 7002 2500.00Hz at 8002 2500.00Hz at 9003 2500.00Hz at 10003
まとめ
Arduinoでパルス波の読み取りと周波数への変換ができました。参考
attachInterrupt() | Arduino ReferenceArduinoでus(マイクロ秒)間隔のパルスを作る方法
変更履歴
2019.11.29 platformioの設定ファイルを「platformio.ino」と間違えていたので、「platformio.ini」 に修正しました。2021.06.10
サンプルコードのsetupにSerial.beginが抜けていたので追加しました。
2021.12.23
周波数読取り用の便利クラスの使い方解説記事のリンクを背景に追加しました。
0 件のコメント :
コメントを投稿