目次

Ultrasonic sensor interface

 最近の超音波センサー基板には、マイコンを実装し
 トリガーを与えると、計測後、距離相当のパルス幅
 を返すものがあります。



 タイミングチャートでは、次のようになります。



 超音波センサーは、音波を壁にあてたとして
 170m/sという音速を考えます。

 壁まで400mm程度あるとして、検出処理を
 VHDLコードにしてみます。



 利用するCPLDを、Cool Runner IIとすると
 5Vで動作する超音波センサーに直に接続
 できません。インタフェースを接続します。

 インタフェース回路は、以下。



 1サイクルを100msとして、この間にトリガーを出力します。
 100msを測定するためのカウンタを用意します。

 カウンタの値を利用して、トリガーを10usのパルスを生成し
 立上り、立下り時のカウント値を記憶します。

 パルス生成は、次のように単純にしました。



 VHDLコードでは、次のように定義。

  -- 100ms counter
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= 0 ;
    elsif rising_edge(iSCLK) then
      if ( iCNT = CNTMAX ) then
        iCNT <= 0 ;
      else
        iCNT <= iCNT + 1 ;
      end if ;
    end if ;
  end process ;

  -- generate TRIGGER (10us)
  iUTRG <= '1' when ( iCNT < TRGMAX ) else '0' ;

 シフトレジスタを使い、立上り、立下りをキャッチします。




  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iURES_SFT <= "000" ;
    elsif rising_edge(iSCLK) then
      iURES_SFT <= iURES_SFT(1 downto 0) & URES ;
    end if ;
  end process ;
  iURES_LH <= '1' when ( iURES_SFT = "011" ) else '0' ;
  iURES_HL <= '1' when ( iURES_SFT = "110" ) else '0' ;

 立上り、立下りのトリガーを利用し、カウント値
 を記憶していきます。

  process (iSCLK)
  begin
    if rising_edge(iSCLK) then
      -- clear
      if ( iCNT = CNTMAX ) then
        iBEGINX <= (others => '0') ;
        iFINEX  <= (others => '0') ;
      end if ;
      -- measure (L -> H)
      if ( iURES_LH = '1' ) then
        iBEGINX <= conv_std_logic_vector(iCNT,17) ;
      end if ;
      -- measure (H -> L)
      if ( iURES_HL = '1' ) then
        iFINEX  <= conv_std_logic_vector(iCNT,17) ;
      end if ;
    end if ;
  end process ;

 カウント値の差を求めるために、シーケンサを利用します。

 100msを1サイクルとし、99ms経過したときにシーケンサが
 起動→記憶カウント値を複写→カウント値の差分計算と続け
 ます。

 シーケンサは4usで作業を終えるので、99.5msの時点で
 結果が出ます。

 最終VHDLコードは、次のようにしました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity tstusen is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ; -- 4MHz
    -- sensor handler signal
    UTRG   : out std_logic ; -- TRG
    URES   : in  std_logic ; -- ECHO
    -- gate status (1:close 0:open)
    GSTATE : out std_logic ;
    -- monitor
    DOUT   : out std_logic_vector(16 downto 0) ;
    LOUT   : out std_logic --;
  );
end tstusen ;

architecture behavioral of tstusen is
  -- values
  CONSTANT TRGMAX    : integer :=    11 ;
  CONSTANT CNTMAX    : integer := 99999 ; -- 100ms
  CONSTANT CNTLAST   : integer := 99000 ; --  99ms
  CONSTANT CNTTARGET : integer :=  2000 ; --   2ms => 340mm
  -- 1us generator (1MHz)
  signal iSCNT : std_logic_vector(1 downto 0) ;
  signal iSCLK : std_logic  ;
  -- 100ms counter
  signal iCNT : integer range 0 to CNTMAX ;
  -- trigger
  signal iUTRG : std_logic ;
  -- echo
  signal iURES_SFT : std_logic_vector(2 downto 0) ;
  signal iURES_HL  : std_logic ;
  signal iURES_LH  : std_logic ;
  -- detector
  signal iBEGINX : std_logic_vector(16 downto 0) ;
  signal iFINEX  : std_logic_vector(16 downto 0) ;
  -- sequencer
  signal iSTATE  : std_logic_vector( 1 downto 0) ;
  signal iBEGIN  : std_logic_vector(16 downto 0) ;
  signal iFINE   : std_logic_vector(16 downto 0) ;
  signal iDIFF   : std_logic_vector(16 downto 0) ;
  signal iGSTATE : std_logic ; 
begin
  -- output
  UTRG   <= iUTRG ;
  GSTATE <= iGSTATE ;
  LOUT   <= not iGSTATE ;
  DOUT  <= iDIFF ;

  -- generate 1MHz (1us)
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSCNT <= "00" ;
    elsif rising_edge(CLOCK) then
      iSCNT <= iSCNT + '1' ;
    end if ;
  end process ;
  iSCLK <= '1' when ( iSCNT = "00" ) else '0' ;

  -- 100ms counter
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= 0 ;
    elsif rising_edge(iSCLK) then
      if ( iCNT = CNTMAX ) then
        iCNT <= 0 ;
      else
        iCNT <= iCNT + 1 ;
      end if ;
    end if ;
  end process ;

  -- generate TRIGGER (10us)
  iUTRG <= '1' when ( iCNT < TRGMAX ) else '0' ;

  -- synchronizer
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iURES_SFT <= "000" ;
    elsif rising_edge(iSCLK) then
      iURES_SFT <= iURES_SFT(1 downto 0) & URES ;
    end if ;
  end process ;
  iURES_LH <= '1' when ( iURES_SFT = "011" ) else '0' ;
  iURES_HL <= '1' when ( iURES_SFT = "110" ) else '0' ;

  -- detector
  process (iSCLK)
  begin
    if rising_edge(iSCLK) then
      -- clear
      if ( iCNT = CNTMAX ) then
        iBEGINX <= (others => '0') ;
        iFINEX  <= (others => '0') ;
      end if ;
      -- measure (L -> H)
      if ( iURES_LH = '1' ) then
        iBEGINX <= conv_std_logic_vector(iCNT,17) ;
      end if ;
      -- measure (H -> L)
      if ( iURES_HL = '1' ) then
        iFINEX  <= conv_std_logic_vector(iCNT,17) ;
      end if ;
    end if ;
  end process ;

  -- sequencer
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE  <= "00" ;
      iDIFF   <= (others => '0') ;
      iBEGIN  <= (others => '0') ;
      iFINE   <= (others => '0') ;
    elsif falling_edge(iSCLK) then
      case conv_integer(iSTATE) is
        -- clear counter
        when 0 => if ( iCNT = CNTLAST ) then
                    iSTATE <= "01" ;
                    iDIFF  <= (others => '0') ;
                  else
                    iSTATE <= "00" ;
                  end if ;
        -- copy
        when 1 => iSTATE <= "11" ;
                  iBEGIN <= iBEGINX ;
                  iFINE  <= iFINEX  ;
        -- calculate
        when 3 => iSTATE <= "10" ;
                  if conv_integer(iFINE) > conv_integer(iBEGIN) then
                    iDIFF  <= iFINE - iBEGIN ;
                  end if ;
        -- return first state
        when 2 => iSTATE <= "00" ;
        -- default
        when others => 
                  iSTATE <= "00" ;
      end case ;
    end if ;
  end process ;
  iGSTATE <= '1' when ( conv_integer(iDIFF) < CNTTARGET ) else '0' ;

end behavioral;

 ピンアサインは、以下。

# system
NET "CLOCK"  LOC = "P22" ;
NET "nRESET" LOC = "P99" ;

# Ultra sononic sensor interface
NET "UTRG"   LOC = "P1" ;
NET "URES"   LOC = "P2" ;
NET "GSTATE" LOC = "P3" ;

# monitor LED
NET "LOUT"   LOC = "P4" ;

# difference
NET "DOUT<0>"  LOC = "P6" ;
NET "DOUT<1>"  LOC = "P7" ;
NET "DOUT<2>"  LOC = "P8" ;
NET "DOUT<3>"  LOC = "P9" ;
NET "DOUT<4>"  LOC = "P10" ;
NET "DOUT<5>"  LOC = "P11" ;
NET "DOUT<6>"  LOC = "P12" ;
NET "DOUT<7>"  LOC = "P13" ;
NET "DOUT<8>"  LOC = "P14" ;
NET "DOUT<9>"  LOC = "P15" ;
NET "DOUT<10>" LOC = "P16" ;
NET "DOUT<11>" LOC = "P17" ;
NET "DOUT<12>" LOC = "P18" ;
NET "DOUT<13>" LOC = "P19" ;
NET "DOUT<14>" LOC = "P23" ;
NET "DOUT<15>" LOC = "P24" ;
NET "DOUT<16>" LOC = "P27" ;


目次

inserted by FC2 system