目次

ultrasonic sensor handler

 最近の超音波センサーは、距離を時間に換算して
 出力するタイプが出てきている。



 制御は簡単で、TRGでスタートパルスを与え
 ECHOがHになるまでの時間を計測する。

 タイミングチャートで見ると、非常に簡単。



 この超音波センサーを利用して、ドアが開いているか
 閉じているのかを表示する回路を考える。



 ドアのオープン、クローズはLEDの点灯、消灯で
 表示してみる。

 動作確認には、次のXC9572を実装した基板を利用。



 超音波センサーは、60msの間隔をあけてTRGを
 与えなければならないので、シーケンサを利用
 して、周期処理を実現する。

 シーケンスは、以下。
  1. 60msごとのトリガーを待つ。トリガーが着たら2ステートに遷移
  2. 外部カウンタリセット、TRGを出力し、3ステートに遷移
  3. タイムアウトかECHOの到着で、フラグに論理値を設定し、4ステートに遷移
  4. 1ステートにもどる
 60msごとのトリガーは、後で考えるとして  シーケンスをコードで記述。 process (nRESET,iCLK) begin if ( nRESET = '0' ) then iSTATE <= "00" ; iGSTATE <= '0' ; elsif rising_edge(iCLK) then case conv_integer(iSTATE) is -- wait trigger when 0 => if ( iSTRG = '1' ) then iSTATE <= "01" ; else iSTATE <= "00" ; end if ; -- reset and send trigger when 1 => iSTATE <= "11" ; -- wait trigger when 3 => if ( iURES = '1' ) then -- answer back iSTATE <= "10" ; iGSTATE <= '1' ; elsif ( iTOUT = '1' ) then -- time out iSTATE <= "10" ; iGSTATE <= '0' ; else iSTATE <= "11" ; end if ; -- return first state when 2 => iSTATE <= "00" ; -- default when others => iSTATE <= "00" ; end case ; end if ; end process ;  TRGのパルス幅は、10usなので、シーケンサは  この周期で動かす。  利用しているテスト基板のマスタークロックは  4MHzなので、100kHz(10us)を生成しシーケンサ  を動かすクロックとする。  単純な分周回路で実現。 process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iCNT <= 0 ; elsif rising_edge(CLOCK) then if ( iCNT = 39 ) then iCNT <= 0 ; else iCNT <= iCNT + 1 ; end if ; end if ; end process ; iCLK <= '1' when ( iCNT = 0 ) else '0' ; -- 100kHz(10us)  シーケンサを動かすため、必要になるトリガーは  3種類あるので、個別に考えていく。  60msトリガー   60msは10usを入力するカウンタで実現。 process (nRESET,iCLK) begin if ( nRESET = '0' ) then iSCNT <= 0 ; elsif rising_edge(iCLK) then if ( iSCNT = 5999 ) then iSCNT <= 0 ; else iSCNT <= iSCNT + 1 ; end if ; end if ; end process ; iSTRG <= '1' when ( iSCNT = 0 ) else '0' ;  タイムアウトトリガー   音速を340m/sとして、超音波センサーと   ドアの間を200mmとすれば、往復に400mm   必要となり、3msあればECHOが返ってくる。   3msは10usを入力するカウンタで実現。 process (nRESET,iCLK) begin if ( nRESET = '0' ) then iTCNT <= 0 ; elsif rising_edge(iCLK) then if ( iSTATE = "01" or iTCNT = 300 ) then iTCNT <= 0 ; else iTCNT <= iTCNT + 1 ; end if ; end if ; end process ; iTOUT <= '1' when ( iTCNT = 299 ) else '0' ;   シーケンサから、カウンタのリセットをかけるため   状態変数とロールフローで判定。  ECHOトリガー   ECHOのL→Hの変化をシフトレジスタを利用し捕捉。   チャタリングを除去する処理と同じように   シフトレジスタを使い、実現。 process (nRESET,iCLK) begin if ( nRESET = '0' ) then iURES_SFT <= "000" ; elsif rising_edge(iCLK) then iURES_SFT <= iURES_SFT(1 downto 0) & URES ; end if ; end process ; iURES <= '1' when ( iURES_SFT = "001" ) else '0' ;   シーケンサと同期しながら動作すればよいので   シフトレジスタのクロックは、100kHzに。  以上をまとめる。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity usensor 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 MCLK : out std_logic ; MGSTATE: out std_logic --; ); end usensor ; architecture behavioral of usensor is -- divider signal iCLK : std_logic ; signal iCNT : integer range 0 to 39 ; -- 60ms generator signal iSTRG : std_logic ; signal iSCNT : integer range 0 to 5999 ; -- timer out generator signal iTOUT : std_logic ; signal iTCNT : integer range 0 to 300 ; -- trigger signal iURES : std_logic ; signal iURES_SFT : std_logic_vector(2 downto 0) ; -- sequencer signal iSTATE : std_logic_vector(1 downto 0) ; signal iGSTATE : std_logic ; begin -- output UTRG <= '1' when ( iSTATE = "01" ) else '0' ; GSTATE <= iGSTATE ; -- monitor MCLK <= not iCLK ; MGSTATE <= not iGSTATE ; -- clock divider CLOCK = 4MHz process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iCNT <= 0 ; elsif rising_edge(CLOCK) then if ( iCNT = 39 ) then iCNT <= 0 ; else iCNT <= iCNT + 1 ; end if ; end if ; end process ; iCLK <= '1' when ( iCNT = 0 ) else '0' ; -- 100kHz(10us) -- 60ms generator process (nRESET,iCLK) begin if ( nRESET = '0' ) then iSCNT <= 0 ; elsif rising_edge(iCLK) then if ( iSCNT = 5999 ) then iSCNT <= 0 ; else iSCNT <= iSCNT + 1 ; end if ; end if ; end process ; iSTRG <= '1' when ( iSCNT = 0 ) else '0' ; -- time out process (nRESET,iCLK) begin if ( nRESET = '0' ) then iTCNT <= 0 ; elsif rising_edge(iCLK) then if ( iSTATE = "01" or iTCNT = 300 ) then iTCNT <= 0 ; else iTCNT <= iTCNT + 1 ; end if ; end if ; end process ; iTOUT <= '1' when ( iTCNT = 299 ) else '0' ; -- synchronizer process (nRESET,iCLK) begin if ( nRESET = '0' ) then iURES_SFT <= "000" ; elsif rising_edge(iCLK) then iURES_SFT <= iURES_SFT(1 downto 0) & URES ; end if ; end process ; iURES <= '1' when ( iURES_SFT = "001" ) else '0' ; -- sequencer process (nRESET,iCLK) begin if ( nRESET = '0' ) then iSTATE <= "00" ; iGSTATE <= '0' ; elsif rising_edge(iCLK) then case conv_integer(iSTATE) is -- wait trigger when 0 => if ( iSTRG = '1' ) then iSTATE <= "01" ; else iSTATE <= "00" ; end if ; -- reset and send trigger when 1 => iSTATE <= "11" ; -- wait trigger when 3 => if ( iURES = '1' ) then -- answer back iSTATE <= "10" ; iGSTATE <= '1' ; elsif ( iTOUT = '1' ) then -- time out iSTATE <= "10" ; iGSTATE <= '0' ; else iSTATE <= "11" ; end if ; -- return first state when 2 => iSTATE <= "00" ; -- default when others => iSTATE <= "00" ; end case ; end if ; end process ; end behavioral;  LEDを点灯、消灯は、正論理、負論理の  どちらも使えるように、2出力を用意。  ピンアサインは、以下 # system NET "CLOCK" LOC = "P5" ; NET "nRESET" LOC = "P39" ; # sensor control NET "UTRG" LOC = "P1" ; NET "URES" LOC = "P2" ; NET "MCLK" LOC = "P9" ; # monitor # gate state NET "GSTATE" LOC = "P11" ; NET "MGSTATE" LOC = "P12" ; # monitor  接続は、次の中継コネクタを利用。  XC9572の最大容量72マクロセルのうち、37マクロ  セルを利用。マスタークロックを4MHzから1MHzに  変更すると、XC9536で充分。
目次

inserted by FC2 system