\ Amazon 冬支度セール 11/4(月)~11/12/(火) /

Arduino 入門 番外編 21 【pulseIn関数 まとめ】

arduino-extra-edition-21-00 Arduino番外編
記事に広告(アフィリエイト広告)が含まれています。
スポンサーリンク

Arduino 入門
番外編 21
【pulseIn関数 まとめ】

こんにちは管理人のomoroyaです。

arduino 入門 番外編はarduinoの基本的なことを解説している記事です。

 

本記事は、Arduinoで使用するpulseIn関数についてです。

入門編、番外編では、超音波センサの距離測定に使用した関数。

まあ、まあ使う関数かなということで備忘録のためまとめます。

 

pulseIn関数はパルス幅を測定する関数です。

pinに入力されるパルス幅を測定できます。

パルスはHighでもLowでもどちらでも測定可能

HighとLowのパルス幅を測定できることから、それほど速くない周波数なら周期の測定もこの関数で可能。

Arduinoの公式HPでは「経験上、10マイクロ秒から3分」との記述があります。

あるサイトで精度を検証されていましたが、1%程度は誤差がある。

パルス幅に関しては、100us以上であれば精度よく測定可能ということでした。
※100us以下は急激に測定精度が悪化

周波数で考えると~5KHz程度が限界(duty:50%)と考えておくのがよいようです。

 

ファンクションジェネレータが手元にあれば精度検証ができるのですが、手元になく。。。

当然、Arduinoよりも精度の高いパルスジェネレータでないと意味がありません。

用意ができたら、精度の検証を管理人もやってみたいと思います。

 

どんなときに使うのか?

入門編では超音波センサで使用しました。

使い道としては、一番わかりやすい使い道となります。

 

管理人はプログラマーの専門家というわけではありません。

気が向いたときにテキストを開き、ネットを調べ自己学習。

管理人にとってはブログ記事が自己学習のノートです。

書くことによって頭の中が整理できる。

何よりも、忘れたときに見返せるってのが良い。

 

arduino自身のこと、スケッチ(コード、プログラム)を少しづつ理解して行きましょう。

いやいや、arduinoを早速始めたいんだ!というかたは下記の入門編からお読みください。

 

Arduino入門編の解説にて使用しているArduinoは互換品です。

互換品とは言え、Arduinoはオープンソースであり複製して販売するのもライセンス的に問題なし。

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

正規品(Arduino UNO R3)の本体単品がほしい方はこちらとなります。

 

Arduino入門編2では「Arduino UNO R4 Minima」「Arduino UNO R4 WIFI」にて遊ぶため今のところは正規品を使用。(まだ互換品が・・・ほぼない)

 

 

スポンサーリンク

pulseIn関数 基本解説

まずは基本的なことを復習。

繰り返しになりますが、「パルス幅を測定する」ための関数です。

 

余談ですが・・・

pulseIn関数の時間測定は「micros()」で測定しています。

16MHz動作のArduinoボードでの、micros()関数の分解能は4us

公式に記載のあるpulseIn関数の「経験上、10マイクロ秒から3分」との記載。

これで納得できるわけです。

 

公式リファレンスはこちら
https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/

コマンド 説明
pulseIn(pin, value, timeout) pinに入力されたパルス幅の読み取り
pin: パルスを入力するピンの番号
value: 測定するパルスの種類(HIGH / LOW)
timeout: タイムアウトまでの時間
・省略可
・単位:マイクロ秒
・デフォルト:1秒 (unsigned long)

パルスがHighになっている期間を取得する。
pulseIn(pin,HIGH);

 

pulseIn関数 サンプルスケッチ

シリアルモニタに測定したパルス幅を表示するスケッチとなります。

analogWrite関数を利用すれば、簡単にパルスを生成できますのでこちらを利用。

 

スケッチに通信用の関数を使いますので念のため説明をのせておきます。

関数 説明
Serial.begin(speed) シリアル通信のデータ転送レートをbpsを指定します。
bpsはビット/秒。
speed:転送レート
転送レートは下記が指定可能です。
300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200
戻り値:なし
Serial.available() シリアルポートにデータがあるかどうかの確認をする。
戻り値:シリアルバッファにあるデータのバイト数
Serial.read() 受信データの読み込み。
戻り値:
読み込み可能なデータの最初の1バイトを返す。
-1の場合はデータなし。
Serial.print(data,format) ASCIIテキストでシリアルポートにデータを出力する。
data:出力する値
format:基数または有効桁数(BIN,DEC・・・など)
戻り値:送信したバイト数
Serial.println(data,format) データの末尾に改行を入れて送信。
Serial.print()と同じフォーマットが使えます。

 

流れとしては以下。

  • analogWrite関数でPWMを出力
  • pulseIn関数でパルス幅を測定
  • 値は、シリアルモニタで確認

Dutyは数値で入力し、途中で簡単に変えられるようにしておきました。

//番外編 21 pulseIn関数
//pulseIn関数をシリアルモニタで理解するサンプルスケッチ
//https://omoroya.com/

const int pin_pwm =  3; //PWM出力ピン
const int pin_pul = 11; //パルス幅測定ピン
int val_duty = 50;      //初期値のDuty設定
int val_pwm;            //duty計算用の変数
int val_hpul, val_lpul; //H,Lパルス幅格納変数
float val_frq;          //周波数格納変数

void setup() 
{
  pinMode(pin_pwm, OUTPUT);         //PMW設定ピンをOUTPUT指定
  pinMode(pin_pul, INPUT);          //パルス幅測定ピンをINPUT指定
  Serial.begin(9600);               //シリアル通信のデータ転送レート設定しポート開放
  Serial.println("set Duty = 50%"); //デフォルト表示
}

void loop() 
{
  if (Serial.available() > 0 )    //受信したデータが存在した場合以下を実行
  {
    val_duty = Serial.parseInt(); //文字列データを数値に変換
    Serial.print("set Duty = ");  //表示
    Serial.print(val_duty , DEC); //セットしたdutyを表示
    Serial.println("%");          //表示
  }
  
  val_pwm = 255*val_duty/100;    //dutyからPWM値計算
  analogWrite(pin_pwm, val_pwm); //PWM出力
  
  val_hpul = pulseIn(pin_pul, HIGH);             //Hパルス幅測定
  val_lpul = pulseIn(pin_pul, LOW);              //Lパルス幅測定
  val_frq = 1 / (val_hpul*1e-6 + val_lpul*1e-6); //周波数計算
  
  Serial.print(val_hpul); //Hパルス表示
  Serial.print("us / ");  //単位表示
  Serial.print(val_lpul); //Lパルス表示
  Serial.print("us / ");  //単位表示
  Serial.print(val_frq);  //周波数表示
  Serial.println("Hz");   //単位表示
  delay(1000);            //表示時間調整
}

 

pulseIn関数 サンプルスケッチ 実行結果

まずは、Aruduinoへスケッチを書き込んでください。

注意(pinとpinを直接つなぐため)
念のためスケッチ書き込み後に3番ピンと11番ピンをつなぎます。

書き込み後、3番ピンと11番ピンを接続。

「ツール」 ⇒ 「シリアルモニタ」 を開きます。

Dutyのデフォルトは50%にしてあります。

あとは、「1 ~ 99」で好きな数値を入力して変化を確認してください。

 

下図がシリアルモニタの実行結果。

シリアルモニタは「改行なし」を選択してください。

改行なしを選択しないと改行も入力値として認識してしまいます。

 

50% → 25% → 75% → 1% → 99%と変えた結果。

3番ピンを使用した場合のPWM周波数は「490Hz」。

測定結果も約490Hzとなっており、周波数が測定できていることがわかります。

また、入力したDutyに応じて、H、Lのパルス幅も変わっていることが確認できます。

補足(Duty50%でH,Lのパルス幅がずれている理由)
Arduinoの実際の電圧は5Vではありません。
精度をあげたい場合、キャリブレーションが必要となります。

arduino-extra-edition-21-01

 

シリアルモニタの結果からpulseIn関数でパルス幅を測定できていることがわかります。

 

まとめ

Arduino 入門 番外編 21 【pulseIn関数 まとめ】

 

何気なしに使っている関数。

あらためて、Arduinoを使って関数を一つ一つ理解するのも学習にはもってこい。

まずは、基本を理解して応用してみましょう。

 

次回の「番外編 22」は【IOピン ポート・レジスタ まとめ】です。

Arduino 入門 番外編 22 【IOピン ポート・レジスタ まとめ】
本記事は、IOピンを高速かつ簡単に設定できるポート・レジスタについてです。ArduinoのPIN状態を設定するコマンドは「pinMode()」「digitalWrite()」「digitalRead()」。ある程度スケッチ(コード)を描くの…

最後に

疑問点、質問などありましたら気軽にコメントください。

この電子部品の解説をしてほしい!などなどなんでもOKです。

リンク切れ、間違いなどあればコメントいただけると助かります。

 

Arduino入門編、番外編、お役立ち情報などなどサイトマップで記事一覧をぜひご確認ください。

 

Arduino入門編Arduino入門編2で使用しているUNOはAmazonにて購入可能です。

Arduino入門編では互換品を使用。

Arduinoはオープンソース。

複製して販売するのもライセンス的に問題なし。

 

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

 

学習用、遊び用、お試し用には安価な互換品がおすすめです。

 

上記のものでも十分に多数の部品が入っていますが、最初からもっと多数の部品が入っているこちらもお勧めです。

 

Arduino入門編2では「Arduino UNO R4 Minima」「Arduino UNO R4 WIFI」にて遊ぶため今のところは正規品を使用。(まだ互換品が・・・ほぼない)

 

Amazonでお得に買う方法

Amazonでお得に購入するならAmazon MastercardAmazonギフト券がおすすめです。

時期により異なりますが、様々なキャンペーンを実施しています。

\Amazonギフト券/
Amazonギフトカード キャンペーン

Amazon Mastercard お申込み
Amazon Mastercard 申し込み 

 

いずれの場合もプライム会員である方がお得!!

\Amazon Prime 30日間の無料会員を試す/
無料会員登録 

 

 

コメント

  1. klose より:

    digitalWriteとdelay関数の組み合わせと、analogWriteではpulseInが働くタイミングが変わってくるんですね。delay関数について理解が足りておりませんでした。
    この手の情報はネットで探してもあまり見つからなかったので困っておりましたが、おかげさまで理解できました。ありがとうございました。

    • omoroya omoroya より:

      コメントありがとうございます。
      お役に立てたのであれば、うれしいです。
      また、何かありましたらコメントよろしくお願いいたします。

  2. klose より:

    初めまして、現在、超音波を使用して距離センサーを自作しております。
    Arduinoを使ってパルスを発生させることについて質問がございましてコメントさせていただきました。
    前に、pulseInのコードの動作を確認するために、digitalWriteとdelayでパルスを作成し、これを別のピンに入力、pulseInでパルス幅を計測しようとしておりました。しかし、シリアルモニターにはゼロしか出力されませんでした。
    お聞きしたいのは、ゼロしか出力されない理由です。もし、この原因についてご存知でしたら、ご教授いただけないでしょうか?
    void loop内のコードは下記の通りです。

    digitalWrite(13, HIGH); //13ピンが出力
    delayMicroseconds(50);
    digitalWrite(13, LOW);

    durationTime = pulseIn(12, HIGH); //12ピンが入力
    Serial.println(durationTime);

    原因がわからず、ネットで調べていたところこちらの記事にたどり着きました。記事に記載されている通り、digitalWriteではなく、analogWriteを使用して、パルスを発生させたところ、pulseInでパルス幅を計測することができました。digitalWriteで作ったパルスと、analogWriteで作ったパルスとでは何かが異なるのでしょうか?

    以上、よろしくお願い申し上げます。

    • omoroya omoroya より:

      コメントありがとうございます。
      delayMicroseconds関数はプログラムを指定した時間だけ一時停止する関数となっています。
      delay関数を使用している間はArduinoは何もすることができません。
      ※Arduinoは逐次処理です。

      記載のスケッチでは
      13番ピンをHにする → 50us秒停止 → 13番ピンをLにする → パルス幅測定
      となり、パルス幅測定時は13番ピンはLでありpulseIn関数が遷移を認識できず測定することはできません。
      digitalWriteとdelay関数の組み合わせでは、LからH、HからLへの切り替わりをpulseIn関数が認識できないということです。

タイトルとURLをコピーしました