目次

メカ変更

 左右に別個のモータを配置する方式では、首振り運動が
 発生します。低速では、首振りでも走行に問題はないと
 言えますが、高速にすると首振りがあると、路面情報を
 誤認識して、コースアウトします。

 高速走行マシンに仕上げたいので、前輪をサーボモータ
 後輪をDCモータにしたメカに変更します。

 シャーシにDCモータをつけた状態は、以下です。



 サーボモータは、手元にあった素性のわからないものです。



 サーボモータの特性がわからないと、駆動回路やファームウエア
 を作れないので、動作テストシステムを考えました。



 サーボモータの駆動回路は、以下です。



 駆動回路は、非常に単純です。



 パルスをフォトカプラの入力に与え、別に用意した電源から
 必要な波高値のパルスを出力します。テスト用電源は、以下
 の簡単なものを用意しました。



 3Vのコイン電池を並列にしたものを、直列にして6Vに
 しています。3Vは、DCモータの駆動に利用します。

 DIPスイッチは、DUTY比を設定するため、100〜200の
 整数をカバーできる8ビットにしました。



 トリガースイッチで、DUTY比を設定したいので、2モータの
 ドライブ回路のスイッチを使います。



 サーボモータの特性を調べるために利用したVHDLコードは
 以下です。

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

entity svtst is
  generic (
    TOPX : integer := 5 ;
    XMAX : integer := 24 ;
    TOPY : integer := 9 ;
    YMAX : integer := 500 ;
    TOPZ : integer := 3 ;
    ZMAX : integer := 5 --;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- PWM input
    DUTYX  : in  std_logic_vector(7 downto 0) ;
    -- front SERVO
    SVOUT  : out std_logic ; -- front SERVO control 
    -- latch trigger
    SGTRG  : in  std_logic ; 
    -- monitor
    MOUT   : out std_logic_vector(7 downto 0) --;
  );
end svtst;

architecture Behavioral of svtst is
  -- component clock generator
  component clkgenx is
    generic (
      TOPX : integer ; 
      RMAX : integer --;
    );
    port (
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- output
      CLKOUT : out std_logic -- ;
    );
  end component ;
  -- component SPWMX
  component spwmx is 
    port(
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- input
      RATE   : in  std_logic_vector(7 downto 0) ;
      -- output
      SVOUT  : out std_logic --;
    );
  end component ;
  -- clock 
  signal iPCLK  : std_logic ;
  signal iPWCLK : std_logic ;
  signal iSCLK  : std_logic ;
  -- trigger
  signal iSGTRG_SFT : std_logic_vector(2 downto 0) ;
  signal iTRG       : std_logic ;
  -- duty ratio
  signal iDUTYX : std_logic_vector(7 downto 0) ;
  signal iDUTY  : integer range  0 to 255 ;
  -- Servo PWM
  signal iSVRATE : std_logic_vector(7 downto 0) ;
  signal iSVOUT  : std_logic ;
  -- sequencer
  signal iSTATE : std_logic_vector(1 downto 0) ;
begin
  -- component clock generator (48MHz/48 = 1MHz)
  CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iPCLK);
  -- component clock generator (100kHz/1000 = 100Hz)
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iSCLK,iPWCLK);
  -- component clock generator ( 1MHz/10 = 100kHz)
  CLKZ : clkgenx generic map (TOPZ,ZMAX) port map (nRESET,iPCLK,iSCLK);
  -- component SPWMX
  SPWM : spwmx port map (nRESET,iSCLK,iSVRATE,iSVOUT);

  -- output
  SVOUT <= iSVOUT  ; -- front SERVO control
  MOUT  <= not iSVRATE ;

  -- trigger
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iSGTRG_SFT <= "000" ;
    elsif rising_edge(iPWCLK) then
      iSGTRG_SFT <= iSGTRG_SFT(1 downto 0) & (not SGTRG) ;
    end if ;
  end process ;
  iTRG <= '1' when ( iSGTRG_SFT = "011" or iSGTRG_SFT = "001" ) else '0' ;

  -- get DUTY ratio
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iDUTYX <= conv_std_logic_vector(150,8) ;
    elsif rising_edge(iPWCLK) then
      iDUTYX <= DUTYX ;
    end if ;
  end process ;

  -- master sequencer
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE <= "00" ;
      iDUTY  <= 100 ;
      iSVRATE <= conv_std_logic_vector(100,8) ;
    elsif rising_edge(iPWCLK) then
      case conv_integer(iSTATE) is
        -- wait start trigger
        when 0 => if ( iTRG = '1' ) then
                    iSTATE <= "01" ;
                  else
                    iSTATE <= "00" ;
                  end if ;
        -- judge
        when 1 => if ( conv_integer(iDUTYX) < 50 ) then
                    iDUTY <= 50 ;
                  elsif ( conv_integer(iDUTYX) > 150 ) then
                    iDUTY <= 150 ;
                  else
                    iDUTY <= conv_integer(iDUTYX) ;
                  end if ;
                  iSTATE <= "11" ;
        -- copy
        when 3 => iSTATE <= "10" ;
                  iSVRATE <= conv_std_logic_vector(iDUTY,8) ;
        -- return first state
        when 2 => iSTATE <= "00" ;
        -- default
        when others => iSTATE <= "00" ;
      end case ;
    end if ;
  end process ;

end Behavioral;

 DUTY比をDIPスイッチで指定後、トリガースイッチで
 パルス出力回路で使うカウンタ値を変更します。

 実際のパルスを出力する回路のVHDLコードは、以下です。

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

-- CLOCK 100kHz

entity spwmx is
  port(
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- input
    RATE   : in  std_logic_vector(7 downto 0) ;
    -- output
    SVOUT  : out std_logic --;
  );
end spwmx ;

architecture Behavioral of spwmx is
  -- counter
  signal iPCNT  : integer range 0 to 1000 ;
  signal iRATE  : std_logic_vector(7 downto 0) ;
  signal iSVOUT : std_logic ;
begin
  -- output
  SVOUT <= iSVOUT ;

  -- comparator
  iSVOUT <= '1' when ( iPCNT < conv_integer(iRATE) ) else '0' ;

  -- divider
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iPCNT <= 0 ;
      iRATE <= conv_std_logic_vector(100,8) ;
    elsif rising_edge( CLOCK ) then
      if ( iPCNT = 1000 ) then
        iPCNT <= 0 ;
        iRATE <= RATE ;
      else
        iPCNT <= iPCNT + 1 ;
      end if ;
    end if ;
  end process ;

end Behavioral;

 手持ちのサーボモータは、10ms周期で0.5msから1.5msの
 パルス幅で、0度〜180度となりました。

 サーボモータの特性がわかったので、ドライブ回路を設計します。



 基板は、以下のようになりました。



 DCモータを回転させる電源電圧は3V程度とし、FETのゲート
 には、5V程度を印加します。

 モータドライブ回路に加えて、センサー情報、走行モードを
 LEDで表示します。



 この基板をテストするVHDLコードは、以下です。

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

entity drvtst is
  generic (
    TOPX : integer := 5 ;
    XMAX : integer := 24 ;
    TOPY : integer := 9 ;
    YMAX : integer := 500 --;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- sensor input
    SW     : in  std_logic_vector(7 downto 0) ;
    -- sensor output
    SOUT   : out std_logic_vector(7 downto 0) --;
  );
end drvtst;

architecture Behavioral of drvtst is
  -- component clock generator
  component clkgenx is
    generic (
      TOPX : integer ; 
      RMAX : integer --;
    );
    port (
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- output
      CLKOUT : out std_logic -- ;
    );
  end component ;
  -- clock 
  signal iPCLK  : std_logic ;
  signal iPWCLK : std_logic ;
  -- input
  signal iSW    : std_logic_vector(7 downto 0) ;
  signal iSOUT  : std_logic_vector(7 downto 0) ;
begin
  -- component clock generator (48MHz/48 = 1MHz)
  CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iPCLK);
  -- component clock generator (1MHz/1000 = 1kHz)
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iPCLK,iPWCLK);

  -- input
  iSW(1 downto 0) <= SW(1 downto 0) ;
  iSW(7 downto 2) <= not SW(7 downto 2) ;

  -- output
  SOUT <= iSOUT ;

  -- generate sensor information
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iSOUT <= (others => '1') ;
    elsif rising_edge(iPWCLK) then
      iSOUT <= iSW ;
    end if ;
  end process ;

end Behavioral;

 スイッチで設定した論理値を、そのままか反転して基板上の
 LEDに出力しますが、スイッチの押すタイミングを工夫すると
 DCモータへPWM波形を出力できます。

 ドライブ回路のテストを終えてから、実際にマシンを動かす
 VHDLコードをFPGAにダウンロードして、走行させました。
 このVHDLコードは以下です。

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

entity mcrvcx1 is
  generic (
    TOPX : integer := 6 ;
    XMAX : integer := 47 ;
    TOPY : integer := 8 ;
    YMAX : integer := 239 ;
    TOPZ : integer := 9 ;
    ZMAX : integer := 499 ;
    SENSOR_ALL_BLACK   : integer := 0 ;
    SENSOR_TINY_RIGHT  : integer := 1 ;
    SENSOR_RIGHT       : integer := 2 ;
    SENSOR_BIG_RIGHT   : integer := 3 ;
    SENSOR_CENTER      : integer := 4 ;
    SENSOR_TINY_LEFT   : integer := 5 ;
    SENSOR_LEFT        : integer := 6 ;
    SENSOR_BIG_LEFT    : integer := 7 ;
    SENSOR_LEFT_WHITE  : integer := 8 ;
    SENSOR_RIGHT_WHITE : integer := 9 ;
    SENSOR_ALL_WHITE   : integer := 10 -- ;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- sensor input
    SENSOR : in  std_logic_vector(7 downto 0) ;
    -- sensor output
    SOUT   : out std_logic_vector(7 downto 0) ;
    -- front SERVO
    SVOUT  : out std_logic ; -- front SERVO control 
    -- rear PWM
    POUT   : out std_logic ; -- rear PWM wave 
    -- start goal trigger	 
    SGTRG  : in  std_logic ; 
    GLED   : out std_logic ; -- run
    RLED   : out std_logic ; -- cross white line
    -- monitor
    MOUT   : out std_logic_vector(1 downto 0) --;
  );
end mcrvcx1;

architecture Behavioral of mcrvcx1 is
  -- component clock generator
  component clkgenx is
    generic (
      TOPX : integer ; 
      RMAX : integer --;
    );
    port (
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- output
      CLKOUT : out std_logic -- ;
    );
  end component ;
  -- judge
  component judge is
    port (
      -- input
      DIN  : in  std_logic_vector(7 downto 0) ;
      -- output
      JOUT : out std_logic_vector(3 downto 0) --;
    );
  end component ;
  -- component PWM
  component pwmx is
    port(
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- input
      RATE   : in  std_logic_vector(5 downto 0) ;
      -- output
      POUT   : out std_logic --;
    );
  end component ;
  -- component SPWMX
  component spwmx is 
    port(
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- input
      RATE   : in  std_logic_vector(7 downto 0) ;
      -- output
      SVOUT  : out std_logic --;
    );
  end component ;
  -- clock 
  signal iPCLK  : std_logic ;
  signal iPWCLK : std_logic ;
  signal iSCLK  : std_logic ;
  -- trigger
  signal iSGTRG_SFT : std_logic_vector(2 downto 0) ;
  signal iTRG       : std_logic ;
  -- sensor
  signal iSENSOR : std_logic_vector(7 downto 0) ;
  -- master sequencer
  signal iSTATE     : std_logic_vector(5 downto 0) ;
  signal iDIRECTION : std_logic_vector(1 downto 0) ;
  -- judge run sequencer
  signal iTCNT    : integer range 0 to 300 ;
  signal iJSENSOR : std_logic_vector(7 downto 0) ;
  signal iJUDGE    : std_logic_vector(3 downto 0) ;
  signal iMODE    : integer range 0 to 3 ;
  -- PWM 
  signal iSVRATE  : std_logic_vector(7 downto 0) ;
  signal iSVOUT   : std_logic ;
  signal iPWMRATE : std_logic_vector(5 downto 0) ;
  signal iPWMOUT  : std_logic ;
  signal iGLED    : std_logic ;
  signal iRLED    : std_logic ;
  -- mode
  signal iMSEL    : std_logic_vector(1 downto 0) ;
begin
  -- component clock generator (48MHz/96 = 500kHz)
  CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iPCLK);
  -- component clock generator (48MHz/480 = 100kHz)
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,CLOCK,iPWCLK);
  -- component clock generator (100kHz/1000 = 100Hz)
  CLKZ : clkgenx generic map (TOPZ,ZMAX) port map (nRESET,iPWCLK,iSCLK);
  -- judge
  JUDGEX : judge port map (iJSENSOR,iJUDGE) ;
  -- component PWM
  PWM : pwmx port map (nRESET,iPCLK,iPWMRATE,iPWMOUT);
  -- component SPWMX
  SPWM : spwmx port map (nRESET,iPWCLK,iSVRATE,iSVOUT);

  -- output
  SOUT  <= not SENSOR ;
  SVOUT <= iSVOUT  ; -- front SERVO control 
  POUT  <= iPWMOUT ; -- rear PWM wave 
  GLED  <= not iGLED ;
  RLED  <= not iRLED ;

  MOUT  <= not iMSEL ;

  -- monitor
  iGLED <= '1' when ( conv_integer(iSTATE) > 0 ) else '0' ;
  iRLED <= '1' when ( iSENSOR = X"FF" ) else '0' ;

  -- internal status
  iMSEL <= "00" when ( iMODE = 0 ) else -- BLIND_RUN
           "01" when ( iMODE = 2 ) else -- CRANK
           "10" when ( iMODE = 3 ) else -- LANE_CHANGE
           "11" ;                       -- NORMAL

  -- trigger
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iSGTRG_SFT <= "000" ;
    elsif rising_edge(iSCLK) then
      iSGTRG_SFT <= iSGTRG_SFT(1 downto 0) & (not SGTRG) ;
    end if ;
  end process ;
  iTRG <= '1' when ( iSGTRG_SFT = "011" or iSGTRG_SFT = "001" ) else '0' ;

  -- generate sensor information
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iSENSOR <= (others => '0') ;
    elsif rising_edge(iPWCLK) then
      iSENSOR <= SENSOR ;
    end if ;
  end process ;

  -- master sequencer
  process (nRESET,iSCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE     <= (others => '0') ;
      iDIRECTION <= "00" ;
      iSVRATE    <= conv_std_logic_vector(100,8); -- center
      iPWMRATE   <= conv_std_logic_vector(  0,6);
    elsif rising_edge(iSCLK) then
      case conv_integer(iSTATE) is
        -- wait start trigger
        when 0 => if ( iTRG = '1' ) then 
                    iSTATE <= conv_std_logic_vector(1,6) ;
                  else
                    iSTATE <= (others => '0') ;
                  end if ; 
        -- send blind run trigger (10%)
        when 1 => iSTATE   <= conv_std_logic_vector(  2,6);
                  iSVRATE  <= conv_std_logic_vector(100,8); -- center
                  iPWMRATE <= conv_std_logic_vector( 10,6);
                  iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
        -- timer up (10%)
        when 2 => if ( iTCNT = 0 ) then
                    iSTATE <= conv_std_logic_vector( 3,6) ;
                  else
                    iSTATE <= conv_std_logic_vector( 2,6) ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (25%)	
        when 3 => iSTATE   <= conv_std_logic_vector( 4,6) ;
                  iPWMRATE <= conv_std_logic_vector(25,6) ;
                  iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
        -- timer up (25%)
        when 4 => if ( iTCNT = 0 ) then
                    iSTATE <= conv_std_logic_vector( 5,6) ;
                  else
                    iSTATE <= conv_std_logic_vector( 4,6) ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (35%)
        when 5 => iSTATE   <= conv_std_logic_vector( 6,6) ;
                  iPWMRATE <= conv_std_logic_vector(35,6) ;
                  iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
        -- timer up (35%)
        when 6 => if ( iTCNT = 0 ) then
                    iSTATE <= conv_std_logic_vector( 7,6) ;
                  else
                    iSTATE <= conv_std_logic_vector( 6,6) ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (50%)
        when 7 => iSTATE   <= conv_std_logic_vector( 8,6) ;
                  iPWMRATE <= conv_std_logic_vector(50,6) ;
                  iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
        -- timer up (50%)
        when 8 => if ( iTCNT = 0 ) then
                    iSTATE <= conv_std_logic_vector( 9,6) ;
                  else
                    iSTATE <= conv_std_logic_vector( 8,6) ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- branch NORMAL
        when 9 => iSTATE <= conv_std_logic_vector(10,6) ;

        -- <NORMAL>
        -- <NORMAL> get sensor data
        when 10 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= conv_std_logic_vector(11,6) ;
        -- <NORMAL> (judge)
        when 11 => if ( iJUDGE = SENSOR_ALL_WHITE ) then
                     iSTATE <= conv_std_logic_vector(14,6) ;
                   elsif ( iJUDGE = SENSOR_LEFT_WHITE ) then
                     iDIRECTION <= "10" ; -- left
                     iSTATE     <= conv_std_logic_vector(30,6) ;
                   elsif ( iJUDGE = SENSOR_RIGHT_WHITE ) then
                     iDIRECTION <= "01" ; -- right
                     iSTATE     <= conv_std_logic_vector(30,6) ;
                   elsif ( iJUDGE = SENSOR_CENTER ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector(100,8); -- center
                     iPWMRATE <= conv_std_logic_vector( 35,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_TINY_RIGHT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector( 89,8); --
                     iPWMRATE <= conv_std_logic_vector( 30,6);
                     iTCNT    <= 50 ; -- 0.5sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_RIGHT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector( 79,8); --
                     iPWMRATE <= conv_std_logic_vector( 25,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_BIG_RIGHT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector( 70,8); --
                     iPWMRATE <= conv_std_logic_vector( 20,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_TINY_LEFT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector(111,8); --
                     iPWMRATE <= conv_std_logic_vector( 30,6);
                     iTCNT    <= 50  ; -- 0.5sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_LEFT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector(120,8); --
                     iPWMRATE <= conv_std_logic_vector( 25,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   elsif ( iJUDGE = SENSOR_BIG_LEFT ) then
                     iSTATE   <= conv_std_logic_vector( 12,6);
                     iSVRATE  <= conv_std_logic_vector(130,8); --
                     iPWMRATE <= conv_std_logic_vector( 20,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   else
                     iDIRECTION <= "00" ; -- center
                     iTCNT      <= 100 ; -- 1sec 100Hz = 10ms
                     iSTATE     <= conv_std_logic_vector(12,6) ;
                   end if ;
        -- <NORMAL> time up
        when 12 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(13,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(12,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <NORMAL> return first state
        when 13 => iSTATE <= conv_std_logic_vector(10,6) ;


        -- <CRANK> slow move
        when 14 => iSTATE   <= conv_std_logic_vector( 15,6);
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 25,6);
                   iTCNT    <= 300 ; -- 3sec 100Hz = 10ms
        -- <CRANK> time up
        when 15 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(16,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(15,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> get road information
        when 16 => iJSENSOR   <= iSENSOR ;
                   iDIRECTION <= "00" ; -- center
                   iSTATE     <= conv_std_logic_vector(17,6) ;
        -- <CRANK> judge
        when 17 => if ( iJUDGE = SENSOR_RIGHT_WHITE ) then
                     iSTATE     <= conv_std_logic_vector(19,6);
                     iDIRECTION <= "01" ; -- right
                   elsif ( iJUDGE = SENSOR_LEFT_WHITE ) then
                     iSTATE     <= conv_std_logic_vector(19,6);
                     iDIRECTION <= "10" ; -- left
                   -- keep this state and delay
                   else
                     iSTATE   <= conv_std_logic_vector( 18,6);
                     iSVRATE  <= conv_std_logic_vector(100,8);
                     iPWMRATE <= conv_std_logic_vector( 30,6);
                     iTCNT    <= 100 ; -- 1sec 100Hz = 10ms
                   end if ;

        -- <CRANK> timer up
        when 18 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(17,6);
                   else
                     iSTATE <= conv_std_logic_vector(18,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> turn
        when 19 => iSTATE <= conv_std_logic_vector(20,6);
                   iTCNT  <= 200 ; -- 2sec 100Hz = 10ms
                   -- right_turn
                   if ( iDIRECTION = "01" ) then
                     iSVRATE  <= conv_std_logic_vector(150,8); -- max angle
                     iPWMRATE <= conv_std_logic_vector( 30,6);
                   -- left_white
                   elsif ( iDIRECTION = "10" ) then
                     iSVRATE  <= conv_std_logic_vector( 50,8); -- min angle
                     iPWMRATE <= conv_std_logic_vector( 30,6);
                   end if ;
        -- <CRANK> turn time up
        when 20 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(21,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(20,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> get road information
        when 21 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= conv_std_logic_vector(22,6) ;
        -- <CRANK> judge center
        when 22 => -- center
                   if ( iJUDGE = SENSOR_CENTER ) then
                     iSTATE <= conv_std_logic_vector(24,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(23,6) ;
                     iTCNT  <= 100 ; -- 1sec 100Hz = 10ms
                   end if ;
        -- <CRANK> turn delay center time up
        when 23 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(22,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(23,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> complete turn
        when 24 => 
                   iSTATE   <= conv_std_logic_vector(25,6) ;
                   iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 30,6);
        -- <CRANK> delay exit turn time up
        when 25 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(26,6);
                   else
                     iSTATE <= conv_std_logic_vector(25,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> center move
        when 26 => iSTATE   <= conv_std_logic_vector( 27,6);
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 35,6);
                   iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
        -- <CRANK> exit center move time up
        when 27 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(28,6);
                   else
                     iSTATE <= conv_std_logic_vector(27,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- dummy
        when 28 => iSTATE <= conv_std_logic_vector(29,6);
        -- <CRANK> NORMAL run
        when 29 => iSTATE <= conv_std_logic_vector(10,6);

        -- <LANE_CHANGE>
        -- <LANE_CHANGE>  blind run
        when 30 => iSTATE   <= conv_std_logic_vector( 31,6);
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 35,6);
                   iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
        -- <LANE_CHANGE> blind run delay time up
        when 31 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(32,6);
                   else
                     iSTATE <= conv_std_logic_vector(31,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> get sensor data
        when 32 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= conv_std_logic_vector(33,6);
        -- <LANE_CHANGE> judge all black
        when 33 => if ( iJUDGE = SENSOR_ALL_BLACK ) then
                     iSTATE <= conv_std_logic_vector(34,6);
                   else
                     iSTATE <= conv_std_logic_vector(31,6);
                   end if ;
        -- <LANE_CHANGE> turn
        when 34 => iSTATE <= conv_std_logic_vector(35,6);
                   iTCNT  <= 200 ; -- 2sec 100Hz = 10ms
                   -- right_turn
                   if ( iDIRECTION = "01" ) then
                     iSVRATE  <= conv_std_logic_vector(128,8);
                     iPWMRATE <= conv_std_logic_vector( 40,6);
                   -- left_white
                   elsif ( iDIRECTION = "10" ) then
                     iSVRATE  <= conv_std_logic_vector( 72,8);
                     iPWMRATE <= conv_std_logic_vector( 40,6);
                   end if ;
        -- <LANE_CHANGE> turn time up
        when 35 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(36,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(35,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> center move
        when 36 => iSTATE   <= conv_std_logic_vector( 37,6);
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 35,6);
                   iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
        -- <LANE_CHANGE> turn time up
        when 37 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(38,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(37,6) ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> get sensor data
        when 38 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= conv_std_logic_vector(39,6) ;
        -- <LANE_CHANGE> judge center
        when 39 => if ( iJUDGE = SENSOR_CENTER ) then
                     iSTATE <= conv_std_logic_vector(40,6) ;
                   else
                     iSTATE <= conv_std_logic_vector(39,6) ;
                   end if ;
        -- <LANE_CHANGE> turn
        when 40 => iSTATE <= conv_std_logic_vector(41,6) ;
                   iTCNT  <= 200 ; -- 2sec 100Hz = 10ms
                   -- right_turn (reverse)
                   if ( iDIRECTION = 1 ) then
                     iSVRATE  <= conv_std_logic_vector( 72,8);
                     iPWMRATE <= conv_std_logic_vector( 35,6);
                   -- left_white (reverse)
                   elsif ( iDIRECTION = 2 ) then
                     iSVRATE  <= conv_std_logic_vector(128,8);
                     iPWMRATE <= conv_std_logic_vector( 35,6);
                   end if ;
        -- <LANE_CHANGE> time up
        when 41 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(42,6);
                   else
                     iSTATE <= conv_std_logic_vector(41,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> center move
        when 42 => iSTATE   <= conv_std_logic_vector( 43,6);
                   iSVRATE  <= conv_std_logic_vector(100,8); -- center
                   iPWMRATE <= conv_std_logic_vector( 35,6);
                   iTCNT    <= 200 ; -- 2sec 100Hz = 10ms
        -- <LANE_CHANGE> time up
        when 43 => if ( iTCNT = 0 ) then
                     iSTATE <= conv_std_logic_vector(44,6);
                   else
                     iSTATE <= conv_std_logic_vector(43,6);
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> return NORMAL
        when 44 => iSTATE     <= conv_std_logic_vector(10,6) ;
                   iDIRECTION <= "00" ; -- center
        -- default
        when others => iSTATE <= (others => '0') ;
      end case ;
    end if ;
  end process ;

  iMODE <= 0 when ( conv_integer(iSTATE) < 10 )                               else -- BLIND_RUN
           1 when (  9 < conv_integer(iSTATE) and conv_integer(iSTATE) < 15 ) else -- NORMAL
           2 when ( 13 < conv_integer(iSTATE) and conv_integer(iSTATE) < 30 ) else -- CRANK
           3 ;

end Behavioral;


 実際に走行させると、DCモータとサーボモータが同時に
 動くとき、電力を一気に消費するため、制御性が悪く
 なりました。
 4.8Vに、5V出力DCDCコンバータを接続してから、制御
 基板に出力し、安定性を上げました。

 さらに、DCモータへの出力電圧を安定化するため
 シリーズパスレギュレータを入れました。



 パワートランジスタのベースエミッタ間電圧を0.6Vとして
 OPアンプの電圧出力が、3.9V程度になるようにしました。
 LM358は、出力電圧の最大値は5Vでは、3.5V程度になり
 パワートランジスタのエミッタから2.9Vが出力される計算
 です。電流容量を増やすため、2トランジスタ構成に。

 シリーズパスレギュレータを入れた制御基板は以下です。



 センサーボードを載せたマシンの全体は、以下となりました。



 BarCodeScanner、GameBoyCameraを載せるために、ダイソーから
 プラスチック製カードスタンドを入手。



 カードスタンドは、そのままでも、ほどよい傾斜があるのと
 自由に角度を変更できるので採用です。


目次

inserted by FC2 system