2019年8月3日土曜日

Arduinoでパルスを読み取る方法


背景

Arduinoでパルス波を受信したい場面に遭遇したので、備忘録を兼ねて割り込み処理を利用したパルスの読み取り方法を共有します。

後日、周波数読取り用のライブラリを公開しました。
良ければこちらもご覧ください。
Arduinoで周波数を計測する便利ライブラリHzMeter_asukiaaaを作った
asukiaaa/arduino-HzMeter

使ったもの


回路を作成

パルスを出力する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 Reference
Arduinoでus(マイクロ秒)間隔のパルスを作る方法

変更履歴

2019.11.29 platformioの設定ファイルを「platformio.ino」と間違えていたので、「platformio.ini」 に修正しました。
2021.06.10
サンプルコードのsetupにSerial.beginが抜けていたので追加しました。
2021.12.23
周波数読取り用の便利クラスの使い方解説記事のリンクを背景に追加しました。

0 件のコメント :