目次

試走会

 札幌国際情報高校で開催されるMCR大会の初期の頃から
 懇意にしている技術者集団から試走会を開いてよいかと
 打診が来たのが1月中旬でした。

 自宅の物置2Fのコースでは、全長がせいぜい20m程度。
 長い距離を動かしたとき、マシンがどんな挙動をするのか
 知りたい気持ちもあったので、メール打診にYesと即答。

 試走会の場所は、北広島市にある中央公民館です。



 事前にmugen2012のコンセプト説明をPowerPointで作成し
 送付しておきました。

mugen2012説明資料

 説明資料では、動作に関する内容を割愛したので
 ここに記しておきます。

 センサーからの情報が入手できたならば、シーケンサで
 各モータのカウント値、DUTY比を確定します。他に遅延
 時間用カウンタを指定してマシンを制御します。

 これらのパラメータをVHDLコードで記述しました。
 今回は動作モードを4分割したので、4つのVHDL
 コードに入れてます。

 センサー情報を与えると、次の3つのパラメータを
 出力するデコーダとして定義しました。

 スタートスイッチを押すとBLIND_RUNモードになります。
 このパラメータを記述したVHDLコードは以下です。

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

entity bservo is
  port (
    -- input
    SELIN : in  std_logic_vector(1 downto 0) ;
    -- servo motor counter
    SVCNT : out std_logic_vector(7 downto 0) ;
    -- duty ratio
    DUTY  : out std_logic_vector(5 downto 0) ;
    -- delay counter
    DCNT  : out std_logic_vector(7 downto 0) --;
  );
end bservo;

architecture Behavioral of bservo is
  -- servo motor counter
  signal iSVCNT : std_logic_vector(7 downto 0);
  -- delay counter
  signal iDUTY  : std_logic_vector(5 downto 0);
  -- delay counter
  signal iDCNT  : std_logic_vector(7 downto 0);
begin
  -- output
  SVCNT <= iSVCNT ;
  DUTY  <= iDUTY  ;
  DCNT  <= iDCNT  ;

  -- servo motor counter
  iSVCNT <= conv_std_logic_vector(150,8) ; -- default

  -- DUTY ratio
  iDUTY <= conv_std_logic_vector(10,6) when ( SELIN = "00" ) else -- 10 %
           conv_std_logic_vector(25,6) when ( SELIN = "01" ) else -- 25 %
           conv_std_logic_vector(35,6) when ( SELIN = "10" ) else -- 35 %
           conv_std_logic_vector(50,6) when ( SELIN = "11" ) else -- 50 %
           conv_std_logic_vector( 0,6) ; -- default

  -- delay counter
  iDCNT <= conv_std_logic_vector(100,8) when ( SELIN = "00" ) else -- 10 %
           conv_std_logic_vector(100,8) when ( SELIN = "01" ) else -- 25 %
           conv_std_logic_vector(200,8) when ( SELIN = "10" ) else -- 35 %
           conv_std_logic_vector( 50,8) when ( SELIN = "11" ) else -- 50 %
           conv_std_logic_vector(  0,8) ; -- default

end Behavioral;

 BLIND_RUNの次に、NORMALモードになります。
 NORMALのパラメータを記述したVHDLコードは
 以下です。

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

entity nservo is
  port (
    -- input
    SELIN : in  std_logic_vector(3 downto 0) ;
    -- servo motor counter
    SVCNT : out std_logic_vector(7 downto 0) ;
    -- duty ratio
    DUTY  : out std_logic_vector(5 downto 0) ;
    -- delay counter
    DCNT  : out std_logic_vector(7 downto 0) --;
  );
end nservo;

architecture Behavioral of nservo is
  -- servo motor counter
  signal iSVCNT : std_logic_vector(7 downto 0);
  -- delay counter
  signal iDUTY  : std_logic_vector(5 downto 0);
  -- delay counter
  signal iDCNT  : std_logic_vector(7 downto 0);
begin
  -- output
  SVCNT <= iSVCNT ;
  DUTY  <= iDUTY  ;
  DCNT  <= iDCNT  ;

  -- servo motor counter
  iSVCNT <= conv_std_logic_vector(130,8) when ( SELIN = X"1"  ) else -- exstra_right
            conv_std_logic_vector(135,8) when ( SELIN = X"2"  ) else -- big_right
            conv_std_logic_vector(140,8) when ( SELIN = X"3"  ) else -- right
            conv_std_logic_vector(145,8) when ( SELIN = X"4"  ) else -- tiny_right
            conv_std_logic_vector(155,8) when ( SELIN = X"6"  ) else -- tiny_left
            conv_std_logic_vector(160,8) when ( SELIN = X"7"  ) else -- left
            conv_std_logic_vector(165,8) when ( SELIN = X"8"  ) else -- big_left
            conv_std_logic_vector(170,8) when ( SELIN = X"9"  ) else -- exstra_left
            conv_std_logic_vector(150,8) ; -- center

  -- DUTY ratio
  iDUTY <= conv_std_logic_vector(35,6) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector(45,6) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector(45,6) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector(50,6) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector(50,6) when ( SELIN = X"5" ) else -- center
           conv_std_logic_vector(50,6) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector(45,6) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector(45,6) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(35,6) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector(30,6) ; -- default
  
  -- delay counter
  iDCNT <= conv_std_logic_vector(  9,8) when ( SELIN = X"0" ) else -- all_black
           conv_std_logic_vector(103,8) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector( 19,8) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector( 19,8) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector( 59,8) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector( 59,8) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(103,8) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector( 99,8) ; -- default

end Behavioral;

 NORMALモード処理に必要なパラメータを定義すると
 シーケンサを定義できます。

 NORMALから、CRANK、LANE_CHANGEに遷移させるため
 白線、左半白線、右半白線を判定するコードが必要
 になります。

 この3つのセンサー情報から、状態遷移ができるように
 シーケンサを記述しました。

  process (nRESET,iPCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE    <= 0    ;
      iBSEL     <= "00" ;
      iDIR      <= "00" ;
      iDIRX     <= "11" ;
      iPWMRATE  <= conv_std_logic_vector(0,6);
    elsif rising_edge(iPCLK) then
      case conv_integer(iSTATE) is
        -- wait start trigger
        when 0 => if ( iTRG = '1' ) then 
                    iSTATE <= 1 ;
                    iBSEL  <= "00" ;
                  else
                    iSTATE <= 0 ;
                  end if ; 
        -- send blind run trigger (10%)
        when 1 => iSTATE   <= 2 ;
                  iSVRATE  <= iSVRATE_B ; -- center
                  iPWMRATE <= iDUTY_B   ;
                  iTCNT    <= conv_integer(iTCNT_B) ;
        -- timer up (10%)
        when 2 => if ( iTCNT = 0 ) then
                    iSTATE <= 3 ;
                    iBSEL <= "01" ;
                  else
                    iSTATE <= 2 ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (25%)	
        when 3 => iSTATE   <= 4 ;
                  iSVRATE  <= iSVRATE_B ; -- center
                  iPWMRATE <= iDUTY_B   ;
                  iTCNT    <= conv_integer(iTCNT_B) ;
        -- timer up (25%)
        when 4 => if ( iTCNT = 0 ) then
                    iSTATE <= 5 ;
                    iBSEL  <= "10" ;
                  else
                    iSTATE <= 4 ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (35%)
        when 5 => iSTATE   <= 6 ;
                  iSVRATE  <= iSVRATE_B ; -- center
                  iPWMRATE <= iDUTY_B   ;
                  iTCNT    <= conv_integer(iTCNT_B) ;
        -- timer up (35%)
        when 6 => if ( iTCNT = 0 ) then
                    iSTATE <= 7 ;
                    iBSEL  <= "11" ;
                  else
                    iSTATE <= 6 ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- send blind run trigger (50%)
        when 7 => iSTATE   <= 8 ;
                  iSVRATE  <= iSVRATE_B ; -- center
                  iPWMRATE <= iDUTY_B   ;
                  iTCNT    <= conv_integer(iTCNT_B) ;
        -- timer up (50%)
        when 8 => if ( iTCNT = 0 ) then
                    iSTATE <= 9 ;
                  else
                    iSTATE <= 8 ;
                    iTCNT  <= iTCNT - 1 ;
                  end if ;
        -- branch NORMAL
        when 9 => iSTATE <= 10 ;

        -- <NORMAL>
        -- <NORMAL> get sensor data
        when 10 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= 11 ;
        -- <NORMAL> (judge)
        when 11 => if ( iJUDGE = SENSOR_ALL_WHITE ) then
                     iSTATE   <= 14                    ; -- branch CRANK
                     iSVRATE  <= iSVRATE_N             ;
                     iPWMRATE <= iDUTY_N               ;
                     iTCNT    <= conv_integer(iTCNT_N) ; -- delay
                   elsif ( iJUDGE = SENSOR_LEFT_WHITE ) then
                     iDIR     <= "10"                  ; -- left
                     iSTATE   <= 22                    ; -- branch LANE_CHANGE
                     iSVRATE  <= iSVRATE_N             ;
                     iPWMRATE <= iDUTY_N               ;
                     iTCNT    <= conv_integer(iTCNT_N) ; -- delay
                   elsif ( iJUDGE = SENSOR_RIGHT_WHITE ) then
                     iDIR     <= "01"                  ; -- right
                     iSTATE   <= 22                    ; -- branch LANE_CHANGE
                     iSVRATE  <= iSVRATE_N             ;
                     iPWMRATE <= iDUTY_N               ;
                     iTCNT    <= conv_integer(iTCNT_N) ; -- delay
                   else
                     iSTATE   <= 12                    ; -- branch NORMAL
                     iSVRATE  <= iSVRATE_N             ; -- servo counter
                     iPWMRATE <= iDUTY_N               ; -- duty ratio
                     iTCNT    <= conv_integer(iTCNT_N) ; -- delay
                     iDIR     <= "00"                  ; -- center
                   end if ;
        -- <NORMAL> time up
        when 12 => if ( iTCNT = 0 ) then
                     iSTATE <= 13;
                   else
                     iSTATE <= 12 ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <NORMAL> return first state
        when 13 => iSTATE <= 10 ;

        -- <CRANK>
        -- <CRANK> delay
        when 14 => if ( iTCNT = 0 ) then
                     iSTATE  <= 15        ; -- branch
                     iSVRATE <= iSVRATE_C ; -- servo counter
                   else
                     iSTATE <= 14        ; -- stay
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK> get road information
        when 15 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= 16 ;
        -- <CRANK> (judge)
        when 16 => if ( iJUDGE = SENSOR_LEFT_WHITE ) then
                     iDIR     <= "10"                  ; -- left
                     iSTATE   <= 18                    ; -- state
                     iSVRATE  <= iSVRATE_C             ; -- servo counter
                     iPWMRATE <= iDUTY_C               ; -- duty ratio
                     iTCNT    <= conv_integer(iTCNT_C) ; -- delay
                   elsif ( iJUDGE = SENSOR_RIGHT_WHITE ) then
                     iDIR     <= "01"                  ; -- right
                     iSTATE   <= 18                    ; -- state
                     iSVRATE  <= iSVRATE_C             ; -- servo counter
                     iPWMRATE <= iDUTY_C               ; -- duty ratio
                     iTCNT    <= conv_integer(iTCNT_C) ; -- delay
                   else
                     iDIR     <= "00"                  ; -- center
                     iSTATE   <= 17                    ; -- state
                     iSVRATE  <= iSVRATE_C             ; -- servo counter
                     iPWMRATE <= iDUTY_C               ; -- duty ratio
                     iTCNT    <= conv_integer(iTCNT_C) ; -- delay
                   end if ;
        -- <CRANK> time up
        when 17 => if ( iTCNT = 0 ) then
                     iSTATE  <= 15                          ; -- state
                     iSVRATE <= conv_std_logic_vector(150,8); -- stearing
                   else
                     iSTATE <= 17 ; -- stay
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <CRANK>  time up ROTATE
        when 18 => if ( iTCNT = 0 ) then
                     iSTATE <= 19 ; -- state
                   else
                     iSTATE <= 18 ; -- stay
                     iTCNT  <= iTCNT - 1 ;
                   end if ;  
        -- <CRANK> get road information
        when 19 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= 20 ;
        -- <CRANK> (judge)
        when 20 => if ( iJUDGE = SENSOR_CENTER ) then
                     iDIR   <= "00" ; -- left
                     iSTATE <= 21   ; -- state
                   else
                     iSTATE <= 19 ; -- state
                   end if ;		  
        -- <CRANK> transfer NORMAL
        when 21 => iSTATE <= 10 ; -- state

        -- <LANE_CHANGE>
        -- <LANE_CHANGE> delay
        when 22 => if ( iTCNT = 0 ) then
                     iSTATE  <= 23            ; -- branch
                     iSVRATE <= iSVRATE_L     ; -- servo counter
                     iDIRX   <= iDIR xor "11" ; -- return direction
                   else
                     iSTATE <= 22 ; -- stay
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> get sensor information
        when 23 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= 24 ;
        -- <LANE_CHANGE> judge
        when 24 => if ( iJUDGE = SENSOR_ALL_BLACK ) then
                     iSTATE <= 26 ; -- run black area
                     -- left side lane_change
                     if ( iDIR = "10" ) then
                       iSVRATE <= conv_std_logic_vector(135,8);
                     end if ;
                     -- right side lane_change
                     if ( iDIR = "01" ) then
                       iSVRATE <= conv_std_logic_vector(165,8);
                     end if ;
                     iPWMRATE <= iDUTY_L               ;
                     iTCNT    <= conv_integer(iTCNT_L) ;
                   else
                     iSTATE   <= 25                    ; -- state
                     iSVRATE  <= iSVRATE_L             ; -- servo counter
                     iPWMRATE <= iDUTY_L               ; -- duty ratio
                     iTCNT    <= conv_integer(iTCNT_L) ; -- delay
                   end if ;
        -- <LANE_CHANGE> time up except ALL_BLACK
        when 25 => if ( iTCNT = 0 ) then
                     iSTATE <= 23 ;
                   else
                     iSTATE <= 25 ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> time up ALL_BLACK
        when 26 => if ( iTCNT = 0 ) then
                     iSTATE  <= 27 ;
                     iSVRATE <= conv_std_logic_vector(150,8); -- stearing
                   else
                     iSTATE <= 26 ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> get road state
        when 27 => iJSENSOR <= iSENSOR ;
                   iSTATE   <= 28 ;
        -- <LANE_CHANGE> judge
        when 28 => if ( iJUDGE = SENSOR_CENTER ) then
                     iSTATE <= 29 ;
                   else
                     iSTATE <= 27 ;
                   end if ;
        -- <LANE_CHANGE> reverse stearing
        when 29 => iSTATE <= 30 ; -- state
                   -- left side lane_change
		             if ( iDIRX = "10" ) then
                     iSVRATE <= conv_std_logic_vector(135,8);
                   end if ;
                   -- right side lane_change
		             if ( iDIRX = "01" ) then
                     iSVRATE <= conv_std_logic_vector(165,8);
                   end if ;
                   iPWMRATE <= conv_std_logic_vector(32,6) ; -- DUTY
                   iTCNT    <= 10 ;
        -- <LANE_CHANGE> tiemr up
        when 30 => if ( iTCNT = 0 ) then
                     iSTATE  <= 31                          ; -- state
                     iSVRATE <= conv_std_logic_vector(150,8); -- stearing
                     iDIR    <= "00"                        ; -- center
                   else
                     iSTATE <= 30 ;
                     iTCNT  <= iTCNT - 1 ;
                   end if ;
        -- <LANE_CHANGE> return NORMAL run
        when 31 => iSTATE <= 10 ;
        -- default
        when others => iSTATE <= 0 ;
      end case ;
    end if ;
  end process ;

 NORMALからCRANKへの状態遷移には、白線を利用し
 NORMALからLANE_CHANGEへの状態遷移は、半白線を
 使います。

 シーケンサを回路図で記述すると、配線が入り組んで
 動作を追うのが大変ですが、VHDLであれば、プログラ
 ミング言語と同じ感覚で記述できます。

 CRANK処理に必要ならパラメータを記述した
 VHDLコードは、以下です。

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

entity cservo is
  port (
    -- input
    SELIN : in  std_logic_vector(3 downto 0) ;
    -- servo motor counter
    SVCNT : out std_logic_vector(7 downto 0) ;
    -- duty ratio
    DUTY  : out std_logic_vector(5 downto 0) ;
    -- delay counter
    DCNT  : out std_logic_vector(7 downto 0) --;
  );
end cservo;

architecture Behavioral of cservo is
  -- servo motor counter
  signal iSVCNT : std_logic_vector(7 downto 0);
  -- delay counter
  signal iDUTY  : std_logic_vector(5 downto 0);
  -- delay counter
  signal iDCNT  : std_logic_vector(7 downto 0);
begin
  -- output
  SVCNT <= iSVCNT ;
  DUTY  <= iDUTY  ;
  DCNT  <= iDCNT  ;

  -- servo motor counter
  iSVCNT <= conv_std_logic_vector(130,8) when ( SELIN = X"1" ) else -- exstra_right
            conv_std_logic_vector(135,8) when ( SELIN = X"2" ) else -- big_right
            conv_std_logic_vector(140,8) when ( SELIN = X"3" ) else -- right
            conv_std_logic_vector(145,8) when ( SELIN = X"4" ) else -- tiny_right
            conv_std_logic_vector(155,8) when ( SELIN = X"6" ) else -- tiny_left
            conv_std_logic_vector(160,8) when ( SELIN = X"7" ) else -- left
            conv_std_logic_vector(165,8) when ( SELIN = X"8" ) else -- big_left
            conv_std_logic_vector(170,8) when ( SELIN = X"9" ) else -- exstra_left
            conv_std_logic_vector(170,6) when ( SELIN = X"A" ) else -- right_white
            conv_std_logic_vector(130,6) when ( SELIN = X"B" ) else -- left_white
            conv_std_logic_vector(150,8) ; -- center

  -- DUTY ratio
  iDUTY <= conv_std_logic_vector(25,6) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector(30,6) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector(30,6) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector(35,6) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector(35,6) when ( SELIN = X"5" ) else -- center
           conv_std_logic_vector(35,6) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector(30,6) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector(30,6) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(25,6) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector(25,6) when ( SELIN = X"A" ) else -- right_white
           conv_std_logic_vector(25,6) when ( SELIN = X"B" ) else -- left_white
           conv_std_logic_vector(30,6) ; -- default
  
  -- delay counter
  iDCNT <= conv_std_logic_vector(  9,8) when ( SELIN = X"0" ) else -- all_black
           conv_std_logic_vector(103,8) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector( 19,8) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector( 19,8) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector( 59,8) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector( 59,8) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(103,8) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector( 49,6) when ( SELIN = X"A" ) else -- right_white
           conv_std_logic_vector( 49,6) when ( SELIN = X"B" ) else -- left_white
           conv_std_logic_vector( 19,8) ; -- default

end Behavioral;

 NORMALとCRANKでは、サーボモータの振れ角とDCモータに
 与えるDUTY比が若干異なります。
 これらを含めて、一つのVHDLコードにまとめられますが
 バグが入りやすいので、それぞれのモードに1ファイル
 のVHDLコードを用意しました。

 LANE_CHANGEに使うパラメータを記述したVHDLコードは
 次のようになります。

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

entity lservo is
  port (
    -- input
    SELIN : in  std_logic_vector(3 downto 0) ;
    -- servo motor counter
    SVCNT : out std_logic_vector(7 downto 0) ;
    -- duty ratio
    DUTY  : out std_logic_vector(5 downto 0) ;
    -- delay counter
    DCNT  : out std_logic_vector(7 downto 0) --;
  );
end lservo;

architecture Behavioral of lservo is
  -- servo motor counter
  signal iSVCNT : std_logic_vector(7 downto 0);
  -- delay counter
  signal iDUTY  : std_logic_vector(5 downto 0);
  -- delay counter
  signal iDCNT  : std_logic_vector(7 downto 0);
begin
  -- output
  SVCNT <= iSVCNT ;
  DUTY  <= iDUTY  ;
  DCNT  <= iDCNT  ;

  -- servo motor counter
  iSVCNT <= conv_std_logic_vector(130,8) when ( SELIN = X"1" ) else -- exstra_right
            conv_std_logic_vector(135,8) when ( SELIN = X"2" ) else -- big_right
            conv_std_logic_vector(140,8) when ( SELIN = X"3" ) else -- right
            conv_std_logic_vector(145,8) when ( SELIN = X"4" ) else -- tiny_right
            conv_std_logic_vector(155,8) when ( SELIN = X"6" ) else -- tiny_left
            conv_std_logic_vector(160,8) when ( SELIN = X"7" ) else -- left
            conv_std_logic_vector(165,8) when ( SELIN = X"8" ) else -- big_left
            conv_std_logic_vector(170,8) when ( SELIN = X"9" ) else -- exstra_left
            conv_std_logic_vector(170,6) when ( SELIN = X"A" ) else -- right_white
            conv_std_logic_vector(130,6) when ( SELIN = X"B" ) else -- left_white
            conv_std_logic_vector(150,8) ; -- center

  -- DUTY ratio
  iDUTY <= conv_std_logic_vector(25,6) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector(30,6) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector(30,6) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector(35,6) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector(35,6) when ( SELIN = X"5" ) else -- center
           conv_std_logic_vector(35,6) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector(30,6) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector(30,6) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(25,6) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector(25,6) when ( SELIN = X"A" ) else -- right_white
           conv_std_logic_vector(25,6) when ( SELIN = X"B" ) else -- left_white
           conv_std_logic_vector(30,6) ; -- default
  
  -- delay counter
  iDCNT <= conv_std_logic_vector( 69,8) when ( SELIN = X"0" ) else -- all_black
           conv_std_logic_vector(103,8) when ( SELIN = X"1" ) else -- exstra_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"2" ) else -- big_right
           conv_std_logic_vector( 59,8) when ( SELIN = X"3" ) else -- right
           conv_std_logic_vector( 19,8) when ( SELIN = X"4" ) else -- tiny_right
           conv_std_logic_vector( 19,8) when ( SELIN = X"6" ) else -- tiny_left
           conv_std_logic_vector( 59,8) when ( SELIN = X"7" ) else -- left
           conv_std_logic_vector( 59,8) when ( SELIN = X"8" ) else -- big_left
           conv_std_logic_vector(103,8) when ( SELIN = X"9" ) else -- exstra_left
           conv_std_logic_vector( 19,8) ; -- default

end Behavioral;

 これらのVHDLコードで記述した回路をFPGAに入れた後
 MCR-VCマシンを、車に積みこみ、会場に移動します。
 (移動経路は、以下。)
   駐車場出発→能開大→銭函IC→札幌料金所
   →大谷地IC→札夕線→北広島

 以後は、日記風に書いていきます。


 到着後、マシンのセッティングをして早速試走とは  いきませんでした。(T_T)  スタートボタンを押しても、2種のモータのどちらも  動きません。こういう時は、慌てずに、ハードウエア  チェック。  モータ制御基板には、動作確認用LEDがあるので  これらを使って、ハードウエアのブロックを1個  1個チェックします。  スタートボタンを押すと、緑LEDが点灯する仕様に  設計したので、確認します。  点灯しているので、FPGAからは、間違いなく制御  パルスを出力しています。念のためマルチメータ  の周波数カウンタで、パルス出力ピンの周波数を  測定したところ、100kHz前後なので、FPGAからの  信号はOKでした。  制御パルスが送られているので、次に電源チェック  にうつります。  マルチメータの電圧レンジで、DCDCコンバータから5V  より多少高い電圧が出力されているので、問題なし。  2つのモータにパルスを出力する回路には、フォトカプラ  が入っています。このフォトカプラからパルスが出ている  のかを、周波数カウンタで測定すると0Hzです。  フォトカプラに正しく電源が供給されていないという  事実から、電源コネクタの逆挿しと判断しました。  モータ制御基板の4ピンコネクタをみると、逆に入って  いました。正しい配置で挿入すると、サーボモータが  動き、ホームポジションで停止しました。  これを教訓に、モータ制御基板に電源パイロットLEDを  つけることにしました。  センサーを外した状態で、スタートボタンを押して  直進することを確認できました。
 コースにマシンを載せてから、スタートボタンを押すと  ソロリソロリとは動きます。スピード不足は、明らかで  DUTY比を、それぞれアップさせました。  DUTY比を上げても、亀の歩み状態は改善されません。  タイヤがコースをグリップしていないようです。  ギャラリーから、タイヤのグリップがないのは、ドライブ側  DCモータ駆動力がコースに伝わっていないからと指摘が。  重心がシャーシ中央付近にあるため、これを後方にする  対策をすればよいと、アドバイスを貰えました。  前方荷重から後方荷重になるようにする方法を考えます。  帰宅後、次のようにシャーシの構成を変更しました。  モータの上に、プラスチックプレートを挟んで  バッテリーをおきます。モータに錘を抱かせた  状態になるので、前方荷重から後方荷重になり  ます。  バッテリーの位置を調整できるように、プラスチック  プレートを1枚まるまる使い、重心を少しですが移動  できるようにしました。  FPGAボード、センサーモニタLED基板をバッテリーの  上に配置し、後方荷重の手助けにしました。
 サーボモータにロッドをつけ、BCSセンサーを左右に動かす  方式をとっていましたが、これではサーボモータに、強大な  トルクを要求することになり、動きません。  ギャラリーには、MCR大会で完走マシンを出した技術者がいる  ので、アドバイスを貰いました。  サーボモータにロッドをつけて、左右に振るのではなく  ダイレクトドライブで、シャーシの下のシャフトの回転  にすべきであると。  帰宅途中に、ダイソーに立ち寄り、ゼンマイで動く  玩具の車を入手し、シャフトつきの小さなタイヤを  ゲットしました。それを使い、次のように改造して  あります。  サーボモータの上にスペースができたので  BCSを配置しました。全景は、以下です。  2月4日の真夜中と2月5日午前を費やし  メカ改造を終えました。  電子回路は、モータドライブ回路とLEDによるモニタ  を除いて、FPGAの中に入れる仕様なのでメカ改造に  集中できました。ユニットごとに担当が決まっている  構成にしておいたことが活きました。  2月6日にメールがきて、もっと後方荷重をというので  さらに、プラスチックプレートから、はみ出るくらいの  位置までバッテリーを下げました。  後方荷重になっているのが、わかる写真は以下です。  バッテリーが、トルクを出して後方荷重になっているのを  示す写真です。  骨材を3mmの長ビスを多用し、さらにポリジョイントを  使い高さを調整しました。完成したマシンを上部から見る  と、次のようになりました。
目次

inserted by FC2 system