FC2カウンター FPGAの部屋 超音波距離センサ・インターフェースIP の番外編

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

超音波距離センサ・インターフェースIP の番外編

Zybot に超音波距離センサを搭載する3(Vivado HLSでインターフェースIPを作製)”で作製した超音波距離センサ・インターフェースIP を使うことにしたが、もっと違った方法試してみようと思う。
具体的には、トリガパルスもsensor_in から読み込んで、2つ目の距離パルスをカウントする方法を試してみたい。そのためには最初からsensor_in をモニタする必要がある。方法としては、トリガパルスを出す回路とsensor_in からパルス長を計測する回路を並列に動作させたい。そのためにその2つを関数として実装して、トップにDETAFLOW 指示子を付加することにした。

ultrasonic_sensor_inf2.cpp を示す。

// ultrasonic_sensor_inf2.cpp
// 2016/12/05 by marsee
// count_val は超音波距離センサからのパルス長を示す。単位は 10 ns とする
// 2016/12/07 : パララックス社の超音波距離センサはSIGピンがINOUTなので、自分で出力したトリガパルスを自分で受けてしまう。
//              対策としては、sensor_outのパルスを受けてから、センサのパルス長を測定する。
//
// ライセンスは二条項BSDライセンス (2-clause BSD license)とします。
//

#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <ap_utils.h>

#define COUNT_LIMIT    2000000 // clock = 100MHz, 20ms

void gen_trigger_pulse(volatile ap_uint<1> &sensor_out, volatile ap_uint<1> &sensor_out_en);
int mesure_high_width(hls::stream<ap_uint<1> >& sensor_in, int &cnt);
int mesure_high_width2(hls::stream<ap_uint<1> >& sensor_in, int &cnt);

int ultrasonic_sensor_inf(int &count_val, volatile ap_uint<1> &sensor_out,
        volatile ap_uint<1> &sensor_out_en, hls::stream<ap_uint<1> >& sensor_in){
#pragma HLS DATAFLOW
#pragma HLS INTERFACE ap_hs port=sensor_in
#pragma HLS INTERFACE ap_none register port=sensor_out_en
#pragma HLS INTERFACE ap_none register port=sensor_out
#pragma HLS INTERFACE s_axilite port=count_val
#pragma HLS INTERFACE s_axilite port=return

    int cnt;
    int return_val;

    // 5usのトリガパルスを出力
    gen_trigger_pulse(sensor_out, sensor_out_en);

    // 2回パルスを検出(sensor_out, 距離パルス)
    return_val = mesure_high_width2(sensor_in, cnt);
    count_val = cnt;

    return(return_val);
}

void gen_trigger_pulse(volatile ap_uint<1> &sensor_out, volatile ap_uint<1> &sensor_out_en){
    int cnt;

    Loop_1out5us: for(cnt=0; cnt<500; cnt++){ // 5 us のパルスを出力
#pragma HLS PIPELINE II=1
        sensor_out = 1;
        sensor_out_en = 1;
    }
    sensor_out = 1;
    sensor_out_en = 1;
    Loop_wait1us: for(cnt=0; cnt<100; cnt++){ // 1 us の間 senser_out に 0 を保持
#pragma HLS PIPELINE II=1
        sensor_out = 0;
        sensor_out_en = 1;
    }
    sensor_out = 0;
    sensor_out_en = 1;
    Loop_wait1us2: for(cnt=0; cnt<100; cnt++){ // 1 us の間 senser_out_en に 0 を保持
#pragma HLS PIPELINE II=1
        sensor_out = 0;
        sensor_out_en = 0;
    }
    sensor_out = 0;
    sensor_out_en = 0;
}

// mesure_high_widthを2回実行する
int mesure_high_width2(hls::stream<ap_uint<1> >& sensor_in, int &cnt){
    int return_val;

    // sensor_out のパルスを検出
    return_val = mesure_high_width(sensor_in, cnt);
    if(return_val)
        return(return_val);

    // 超音波距離センサのパルスを検出
    return_val = mesure_high_width(sensor_in, cnt);
    if(return_val)
        return(return_val);

    return(0);
}

// sensor_in が 1 の間のパルス幅を検出する
int mesure_high_width(hls::stream<ap_uint<1> >& sensor_in, int &cnt){
    ap_uint<1> sensor_in_node;

    Loop_wait_high: for(cnt=0; cnt<COUNT_LIMIT; cnt++){
#pragma HLS PIPELINE II=1
        sensor_in >> sensor_in_node;
        if((int)sensor_in_node)
            break;
    }
    if(cnt == COUNT_LIMIT)
        return(1); // error, overflow

    Loop_mesure_high: for(cnt=1; cnt<COUNT_LIMIT; cnt++){ // リミットは 20 ms
#pragma HLS PIPELINE II=1
#pragma HLS LOOP_TRIPCOUNT min=11500 max=1850000 avg=20000
        sensor_in >> sensor_in_node;
        if(!(int)sensor_in_node)
            break;
    }

    if (cnt == COUNT_LIMIT)
        return(2); // error, overflow
    else
        return(0); // normal end
}


ultrasonic_sensor_inf2_tb.cpp を示す。

// ultrasonic_sensor_inf_tb.cpp
// 2016/12/06 by marsee
// 2016/12/07 : パララックス社の超音波距離センサはSIGピンがINOUTなので、自分で出力したトリガパルスを自分で受けてしまう。
//              sensor_in にトリガパルスを出力してから、センサが出力するであろうパルスを出力する。
//
// ライセンスは二条項BSDライセンス (2-clause BSD license)とします。
//

#include <ap_int.h>
#include <hls_stream.h>

#define PULSE_WIDTH 20000 // (PULSE_WIDTH/100) us

int ultrasonic_sensor_inf(int &count_val, volatile ap_uint<1> &sensor_out,
        volatile ap_uint<1> &sensor_out_en, hls::stream<ap_uint<1> >& sensor_in);

int main(){
    using namespace std;

    hls::stream<ap_uint<1> > sensor_in;
    int count_val;
    ap_uint<1> sensor_out, sensor_out_en;
    int return_val;

    // パララックス社の超音波距離センサは入出力なので、自分の出力に反応しないか?を検証する
    // 756 us wait
    for(int i=0; i<22; i++){ // 220 ns wait
        sensor_in << (ap_uint<1>)0;
    }
    for(int i=0; i<500; i++){ // 5 us間 1 を入れる
        sensor_in << (ap_uint<1>)1;
    }
    for(int i=0; i<75078; i++){ // 756 us - 5 us - 220 ns
        sensor_in << (ap_uint<1>)0;
    }
    // 測定用に PULSE_WIDTH 間、1 を入れる
    for(int i=0; i<PULSE_WIDTH; i++){ // PULSE_WIDTHの間 sensor_in を 1 にする
        sensor_in << (ap_uint<1>)1;
    }
    for(int i=0; i<20000; i++){ // 1 usの間 sensor_in を 0 にする
        sensor_in << (ap_uint<1>)0;
    }

    return_val = ultrasonic_sensor_inf(count_val, sensor_out, sensor_out_en, sensor_in);

    printf("Pulse width = %f us\n", (float)count_val/100.0);

    if(return_val){
        printf("Error: return_val = %d\n");
        exit(1);
    }

    return(0);
}


C コードの合成を行った。結果を示す。
Ultrasonic_senser_inf_14_161210.png

C/RTL協調シミュレーションを行った。
Ultrasonic_senser_inf_15_161210.png

C/RTL協調シミュレーション波形を示す。
Ultrasonic_senser_inf_16_161210.png

sensor_out と sensor_out_en が「x」になってしまっている。まずい。。。

最初の波形を拡大した。
Ultrasonic_senser_inf_17_161210.png

sensor_out と sensor_out_en の for 文が終わったところで「x」になってしまっているようだ。
距離パルスが不定なので、sensor_out と sensor_out_en の for 文の長さを合わせることはできない。よってこの実装を使用することは無理そうだと思う。
  1. 2016年12月10日 09:08 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3657-017e4bd7
この記事にトラックバックする(FC2ブログユーザー)