試走会
札幌国際情報高校で開催される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の長ビスを多用し、さらにポリジョイントを
使い高さを調整しました。完成したマシンを上部から見る
と、次のようになりました。
目次
前
次