パルスの幅を計測する

パルス幅を計測する処理方法


赤外線通信、リモコン信号の解析などなど、やってくるパルス幅を計測する必要は時々あります。
3664FでもタイマーWを使えば割と簡単にパルスの幅は計測できます。


パルスの幅を計測

この項目は Tekurobo工作室 にあり、同様に3664Fでもできますが、師匠ページあり、まだ入れてなかったので追加。
まずは、
 Tekurobo工作室の パルスの幅を計測する を参照してください。

 

3664FでもタイマーWには同等の機能があるので、パルスの両エッジで割り込みを使えば同様にできます。
パルス幅の計測は時々必要になります。
テレビのリモコンなどを入力装置がわりに使うときなどに、その信号解析のモトに またはラジコンの受信機の出すパルスなどの取り込みに

 

タイマーWのインプットキャプチャ

3664Fにあるタイマー最高峰のWを使うとインプットキャプチャ機能は上記リンクで説明されている方法と同じです。

(タイマーWにはコンペアマッチAによるカウンタのレジスタ設定でクリアもあるのですが、同様のプログラムを作成したところ、うまくいきませんでした)

 

タイマーWにはコンペアマッチAによるカウンタは出来てもインプットキャプチャでは、カウンタクリアされないようです、

 

 

インプットキャプチャを設定することで、FTIOA~FTIODのポート(P81-84)の入力エッジを検出して タイマWカウンタT CNTの値をGRA~GRDに転送できます。

 

外部からのパルスをタイマーWのインプットキャプチャ入力に取り込みます。

入力は P81~P84 

P81に入力されるパルスの立ち上がり、立ち下がりの両エッジにタイマーW割り込みで、測定します。

 

入力パルスと両エッジなどについては 外部割り込みをつかう(IRQ割り込み) も参照

この機能はパルス幅や周期を測るのに適しています。

* タイマーWのカウンタTCNTは16Bit
インプットキャプチャ入力信号のパルス幅は2システムクロック(φ)以上必要です。これ以下のパルス幅では正しく動作しない

 

原理、方法

命令、タイマー各名称が違うだけで、測定原理や方法は 上記リンクと同じですが、そのままの3664へ移植では動きませんでした。

ここでは 3番目にされている方法  でやってみます。

    116-3.インプットキャプチャ機能の割り込みによるパルス幅の計測

3664FのタイマーWに移植し やってみましたが、レジスタ設定でのTCNTカウンタをハード設定でクリアさせる方法では うまくいきませんでした。

 

簡単な変更として

  • TCNTカウンタをハード設定でクリアするのをやめ
  • ソフトでTCNTをクリアする

のを加えました。

 

プログラム

タイマーW でインプットキャプチャ の設定にします。

レジスタTIORで、インプットキャプチャ の設定: 立ち上がり、立ち下がりの設定をします。

 

TIOR0で GRA、GRB、レジスタ TIOR1で GRC、GRD を設定

 

7 6 5 4 3 2 1 0
GRB GRA
 /    IOB2   IOB1   IOB0  /   IOA2   IOA1   IOA0
 /    /    1 
   
IOA2で  0 :アウトプットコンペア
1 :インプットキャプチャ     の設定
IOA2 で 1を設定し
IOA1 ,IOA0 で 立ち上がり、立ち下がりを設定
0    0   : 立ち上がり   でインプットキャプチャ
0    1   : 立ち下がり   でインプットキャプチャ
1   1   :  両エッジ 

 

タイマーWをインプットキャプチャに設定すると 、FTIOA~FTIODのポート(P81-84) が入力ピンとなります。

ここでは TIOR0 - IOA2 IOA1 IOA0 だけ設定したので FTIOAP81)だけへの入力になります。


割り込みも設定してあるので割り込み関数も起動します。

 

ポートをIO入力にも設定

 

(P81-84)はインプットキャプチャ用のポートになっていますが、
IO.PCR8=0x00; //全部入力に

として、IOポート入力設定すれば、IOポートとしてもアクセスできます。

 

両エッジの設定をしてあり、立ち上がり、立ち下がりで、インプットキャプチャで割り込みがかかりますが、
どっちが 立ち上がり だかわかりません。

そこで、IOアクセスを使って
if(IO.PDR8.BIT.B1==1){ // 入力パルス立ち上がりの場合
のように判定しています。

 

・立ち上がり で カウンタクリア
・立ち下がり で 転送されているGRAを counter に取得 

これでカウンタ値として、パルス幅を得ています。

 

 

回路図

今回は外部回路は何も必要ありません。


タイマーVのパルス出力をタイマーWのピンに取り込むだけなので。

TMOV端子 と P81 の端子を 単に線でつなぐだけです。

 

実行

実行するのには、測定すべきパルスの入力が必要です
どっかでパルスを発生させ、入力しなければ・・・・

 

ゲートICとかを使っての発信回路を作るとかでもいいんですが、メンドウなので、これもH8にやらせましょう。

つまり、自分で発生させたパルスを、自分で取り込んで計測
タイマーVで発生させます。それをタイマーWのピンに入力して測定します。

自分で発生させるので、測らなくてもパルス幅も最初から知ってるんですが測定値との違いなども比較できるでしょう。

 

タイマーVでのパルス発生

 

パルス発生


#include <3664.h>

/*
タイマーVによるPWM 出力ピン CH2-7PIN(TMOV)
*/


void main()
{
   DI;                   /* 割り込み禁止*/

  TV.TCRV0.BYTE=0x11;   //00010 001 クロックφ/8 2000kHz マッチBでカウンタクリア
  TV.TCRV1.BYTE=0x01;   //0000 0001
  
  TV.TCSRV.BYTE=0x06;   /*マッチAで1を端子に出力 マッチBで0を端子に出力*/
  TV.TCORB=250;         /* 周期 8KHz*/
  TV.TCORA=125;           /* デューティ比 0.5 初期値*/
  
   EI;              /* 割り込み許可*/
   while(1){ 
        ;
   }
  
       

 

タイマーVの設定だけです。

クロックをφ/8  周期は8KHz、デューィー比0.5 のパルスです。

これで、TMOVのポートからパルスが出ます。

 

これをタイマーWの入力P81にほり込んでみましょう。

 

両方をつなぐ

 

FQ_InpCapWV_Plus


#include<3664.h>
#include "myfunc.h"

/*************************************************************
インプットキャプチャでのパルス幅計測
p81へパルス入力をいれ
インプットキャプチャにより、割り込み関数timer_w起動

タイマーWでパルス幅の両エッジでの割り込みで パルス幅を計測
************************************************************/

short counter;


void int_timerw (void){

    TW.TIERW.BIT.IMIEA=0;           //割り込みA禁止
    TW.TSRW.BIT.IMFA = 0;       // 割り込みフラグクリア

        if(IO.PDR8.BIT.B1==1){      // 入力パルス立ち上がりの場合
            TW.TCNT=0x0000;
        }
        else{      // 入力パルス立下りの場合
            counter=TW.GRA;
        }
//    TW.TSRW.BIT.IMFA = 0;       // 割り込みフラグクリア
    TW.TIERW.BIT.IMIEA=1;           //割り込みA許可
}


void main()
{

    
  TW.TCRW.BYTE=0x30;      //0011 0000 内部クロック1/8( 2MHz )
//  TW.TCRW.BYTE=0x00;      //0000 0000 内部クロック( 16MHz )

  TW.TIERW.BYTE=0x01;     //0000 0001 割り込みA 許可
  TW.TIOR0.BYTE=0x0F;     //0000 1 111 インプットキャプチャA 両エッジ


  TV.TCRV0.BYTE=0x11;   //0001 0 001 クロックφ/8(2000kHz) マッチBでカウンタクリア
  TV.TCRV1.BYTE=0x01;   //0000 0001

  TV.TCSRV.BYTE=0x06;   /*マッチAで1を端子に出力 マッチBで0を端子に出力*/
  TV.TCORB=250;         /* 周期 8KHz*/
  TV.TCORA=125;         /*パルス幅 62.5us デューティ比 0.5 初期値*/



  IO.PCR8=0x00;  //全部入力に

  LCD_init( 16 );     //LCD初期化
    
    TW.TMRW.BIT.CTS=1;      // TCNTカウンタスタート


   EI;       
        while (1) {
         LCD_locate(1,2);
         LCD_dataout(counter);
 
        }
}

       

 

こうなります。
結果はLCD表示になっています。

 

TMOVのポートのポートからパルスがでて、それを計測するのに、P81に入れます。

上のソースに書き加え、合体させると
タイマーVでパルス発生 → タイマーWで測定   とできます。

各タイマ設定もレジスタ設定程度などで、貼り付けるだけで、 タイマーはそれぞれ独立に動くので、この方法でパルス発生、測定もできるのです。

 

実行結果

実行してみると 表示結果 115 となります。

タイマーW,V共に φ/8 の設定なので、タイマーV側で TV.TCORA=125 と作ったとおり、

本来は 125 となるべきはずですが、測定結果は 115  パルス幅にすると 57.5uS(本来62.5uS) とだいぶ違う。 8%ぐらいの誤差があるようです

測定パルス

 

オシロで測ってみました。

レジスタ設定ではパルス幅125としてあるので

φ/8で  2M
 パルスで 1/2=0.5

 0.5×125 = 62.5uS  

 オシロでは62.4uS
発生はかなり正確です。

 

 

入力するパルスは正確なので、やはり測定には誤差がでています。

タイマーWのクロックを小さく変えてみます。

 

タイマーWのパルスを最小に メインクロックのまま 分周なしで

// TW.TCRW.BYTE=0x00; //0000 0000 内部クロック( 16MHz )
にしてみました。

 

表示結果 924 (本来は1000のハズ)  パルス幅にすると57.75uS 同様に8%ぐらいの誤差

これはプログラム内の処理などの処理遅れでしょう

まとめ

この程度の差はでますが、パルスは測定できました。

 

ちょっとしたカウンタ読み取り方法で数%の誤差が出る結果になりましたが、 より正確にならこのような処理よりも、
counter=TW.GRA; と立ち上がり、立ち下がり共にGRA値を取得することがより正確です。

 

それで測定する方法は

  • スタート(立ち上がり)次点のGRA値を取得
  • エンド(立ち下がり)次点のGRA値を取得

その差を パルス幅とする方法です。

 

この場合、スタート(立ち上がり)のカウンタ値によっては エンド(立ち下がり)を検出する前に
カウンタがオーバーフローしてしまうことがあります。
それでも、また0に戻ったエンド(立ち下がり)のカウント値を修正加算して パルス幅とすることがこのハード上の機能では最良になるかと思います。

 

その方法は試しませんでしが、しかしながら、カウンタを直接クリアする方法では、ある程度の誤差がでることは確認できました。

 

パルス幅を正確に計測するのが目的でなく、信号として入力に受け取るためなら、一律にパルス幅を得られたら、正確に計測でなくてもいいので計測値が安定しない、値が振れる方が問題になることが多いでしょう。

 


 

スポンサーリンク
  • facebook
  • twtter
  • google+
  • hatena