目次

マシン完成

 メカハードの上に、マイコン関係基板を載せ
 カメラを取り付けられるようにしました。
 (前年度の反省から、カメラを配置した
  前方が軽くなるようにしてあります。)



 最頂部まで130mm程度になり、車検をパスできる車高に。

 カメラ基板は、ネームプレートを利用した
 角度を可変できる構造にしました。

 傾け状態



 立てた状態



 画像処理を実現するためには、40MHz程度のクロックが
 必要と判断し、マイコンとしてARMのADuC7026、FPGAと
 してSpartan3の50kゲート品を基板に入れました。



 ARMのクロック周波数が41.78MHz
 Spartan3のクロック周波数を40MHz
 にして動かします。

 ARMの担当内容は、以下。

  • スタートスイッチを判断し、FPGAを動かす。
  • FPGA生成のセンサーデータから制御パラメータ計算
  • FPGAに対し移動指示  Spartan3の担当内容は、次のように。
  • カメラを制御し、画像データを取得
  • 画像データからセンサーデータ生成
  • ARMの要求によりセンサーデータを出力
  • ARMの指示によりモータ制御
  • コースに照射するLED光制御  電源は、ENELOOPタイプのバッテリーを  使うことに。  4本を1組として、モータ用とマイコン用に  分けて使います。マイコン用は、基板の下に  モータ用はベース台車の電池ボックスに入れ  使います。  ARMとSpartan3の接続が、設計通りかを調べるため  ファームウエアとVHDLコードを書きました。  接続テストなので、ARMから出力したデータをSpartan3  が受け取り、LEDに表示する仕様にしました。  ARMのファームウエアは、以下です。 #include <ADuC7026.h> #define OFF 0 #define ON OFF+1 /* data definitions */ typedef unsigned char UBYTE ; typedef signed char SBYTE ; typedef unsigned short UWORD ; typedef signed short SWORD ; typedef unsigned long ULONG ; typedef signed long SLONG ; void IRQ_Handler(void) __irq; void init_usr(void); #define MASKFF 0xFF #define MASK0F 0x0F #define MASK80 0x80 #define MASK40 0x40 #define MASK20 0x20 #define MASK10 0x10 #define MASK08 0x08 #define MASK04 0x04 #define MASK02 0x02 #define MASK01 0x01 #define MASKF0 0xF0 ULONG timcnt ; void rs_putchar(UBYTE x); void crlf(void); void rs_puts(UBYTE *x); UBYTE get_hex(UBYTE x); void show_help(void); void show_led(void); /* global variables */ volatile UBYTE uflag ; volatile UBYTE sbuf[8] ; volatile UBYTE sindex ; volatile UBYTE cmd ; volatile UBYTE asc_hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; volatile UBYTE p2dat ; volatile UBYTE p3dat ; int main(void) { UBYTE tmp ; /* initialize user */ init_usr(); /* show message */ rs_puts("Hello"); crlf(); /* endless loop */ while(ON) { /* command interrpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* judge */ cmd = *(sbuf+0) ; if ( cmd == '?' ) { show_help(); } /* set port values */ if ( cmd == 'F' || cmd == 'R' ) { crlf(); /* value */ tmp = get_hex( *(sbuf+1) ) ; tmp <<= 4 ; tmp |= get_hex( *(sbuf+2) ) ; /* P2 or P3 */ if ( cmd == 'R' ) { p3dat = tmp ; GP3DAT &= 0xff00ffff ; GP3DAT |= (tmp << 16) ; } else { p2dat = tmp ; GP2DAT &= 0xff00ffff ; GP2DAT |= (tmp << 16) ; } } /* show duty */ if ( cmd == 'S' ) { show_led(); } } } /* dummy return */ return (0); } void IRQ_Handler(void) __irq { volatile UBYTE ch ; /* judge UART receive interruption */ if ( (IRQSTA & UART_BIT) == UART_BIT ) { /* judge */ if ( COMSTA0 & 1 ) { /* clear flag */ ch = COMRX ; *(sbuf+sindex) = ch ; sindex++ ; if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } } /* judge timer3 interruption (1s) */ if ( (IRQSTA & WATCHDOG_TIMER_BIT) == WATCHDOG_TIMER_BIT ) { /* clear timer3 interrupt flag */ T3CLRI = 0xff ; /* blink */ GP4DAT ^= (1 << 23); } } void init_usr(void) { /* select clock 10.44MHz initialized in start up routine */ PLLKEY1 = 0xaa ; PLLCON = 0x01 ; PLLKEY2 = 0x55 ; /* power control initialized in start up routine */ /* clear flag */ uflag = OFF ; /* clear counter */ timcnt = 0 ; /* initialize UART */ { /* set baud rate 19200 bps CD = 2 */ COMCON0 = 0x80 ; /* select COMDIV1 and COMDIV0 */ COMDIV0 = 0x11 ; COMDIV1 = 0x00 ; /* set conditions */ COMCON0 = 0x03 ; /* select COMRX and COMTX , 8bit data , 1 stop bit , no parity */ /* enable interrupt */ COMIEN0 = 0x01 ; /* ERBFI */ } /* P0 */ { /* */ GP0DAT = 0xFF3C0000 ; } /* P1 */ { /* use UART */ GP1CON = 0x00000011 ; /* */ GP1DAT = 0xfe000000 ; } /* P2 */ { /* all bits outputs */ GP2DAT = 0xff000000 ; } /* P3 */ { /* all bits outputs */ GP3DAT = 0xff000000 ; } /* P4 */ { GP4DAT = 0xff000000 ; } /* initialize timer 3 (1s) */ { T3LD = 32768 ; /* (32.768kHz / 32768) = 1 Hz */ T3CON = 0xc0 ; /* enable , cyclic , 1/1 */ } /* clear */ p2dat = 0 ; p3dat = 0 ; /* enable timer 3 interrupt and UART interrupt */ IRQEN = WATCHDOG_TIMER_BIT | UART_BIT ; } /* UART putchar */ void rs_putchar(UBYTE x) { /* ? transmmit buffer empty */ while( (COMSTA0 & 0x40) == 0 ) ; /* set value */ COMTX = x ; } /* carriage return and line feed */ void crlf(void) { rs_putchar('\r'); rs_putchar('\n'); } /* UART puts */ void rs_puts(UBYTE *x) { while ( *x != '\0' ) { rs_putchar( *x ) ; x++ ; } } /* convert ASCII to number */ UBYTE get_hex(UBYTE x) { UBYTE result ; /* default */ result = 0 ; /* judge */ if ( '0' <= x && x <= '9' ) { result = x - '0' ; } if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; } if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; } return result ; } /* show help */ void show_help(void) { rs_puts("? help") ; crlf(); rs_puts("F set P2 values") ; crlf(); rs_puts("R set P3 values") ; crlf(); rs_puts("S show") ; crlf(); } void show_led(void) { UBYTE i ; UBYTE msg[9] ; /* clear buffer */ for ( i = 0 ; i < 9 ; i++ ) { *(msg+i) = '\0' ; } /* P2 */ for ( i = 0 ; i < 8 ; i++ ) { *(msg+i) = ((p2dat >> (7-i)) & 1) + '0' ; } rs_puts("P2 "); rs_puts( msg ); crlf(); /* P3 */ for ( i = 0 ; i < 8 ; i++ ) { *(msg+i) = ((p3dat >> (7-i)) & 1) + '0' ; } rs_puts("P3 "); rs_puts( msg ); crlf(); }  P2、P3をSpartan3と接続しています。  端末からLEDの点灯パターンを、ARMに与えて  接続をチェックします。  Spartan3のVHDLコードです。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity clktst is generic ( TOPX : integer := 7 ; XMAX : integer := 100 ; TOPY : integer := 11 ; YMAX : integer := 1250 --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- inputs GP2 : in std_logic_vector(7 downto 0) ; GP3 : in std_logic_vector(7 downto 0) ; -- outputs GDAT0 : out std_logic_vector(7 downto 0) ; GDAT1 : out std_logic_vector(7 downto 0) ; GDAT2 : out std_logic_vector(7 downto 0) ; -- monitor RLED : out std_logic ; GLED : out std_logic --; ); end clktst ; architecture Behavioral of clktst 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 iMCLK : std_logic ; signal iSCLK : std_logic ; -- pin check signal iCNT : integer range 0 to 80 ; signal iGDAT : std_logic_vector(7 downto 0) ; signal iGDAT0 : std_logic_vector(7 downto 0) ; signal iGDAT1 : std_logic_vector(7 downto 0) ; begin -- component clock generator (20MHz/100kHz = 200) CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iMCLK); -- component clock generator (100kHz/1250 = 4Hz) CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iMCLK,iSCLK); -- output GLED <= not iMCLK ; RLED <= not iSCLK ; GDAT0 <= not iGDAT0 ; GDAT1 <= not iGDAT1 ; GDAT2 <= not iGDAT ; -- counter process (nRESET,iSCLK) begin if ( nRESET = '0' ) then iCNT <= 0 ; elsif rising_edge(iSCLK) then iCNT <= iCNT + 1 ; if ( iCNT = 80 ) then iCNT <= 0 ; end if ; end if ; end process ; iGDAT <= "00000001" when ( iCNT = 0 ) else "00000010" when ( iCNT = 1 ) else "00000100" when ( iCNT = 2 ) else "00001000" when ( iCNT = 3 ) else "00010000" when ( iCNT = 4 ) else "00100000" when ( iCNT = 5 ) else "01000000" when ( iCNT = 6 ) else "10000000" when ( iCNT = 7 ) else "00000000" ; -- latch process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iGDAT0 <= (others => '0') ; iGDAT1 <= (others => '0') ; elsif rising_edge(iMCLK) then iGDAT0 <= GP3 ; iGDAT1 <= GP2 ; end if ; end process ; end Behavioral;  LEDは負論理で動作してるので、ARMから受け取った  データを反転して、出力します。  Spartan3の接続仕様は、次のUCFファイルの内容になります。 # Spartan3 50k gates # system NET "CLOCK" LOC = "P36" ; NET "nRESET" LOC = "P50" ; # G0 NET "GDAT0<0>" LOC = "P1" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<1>" LOC = "P2" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<2>" LOC = "P4" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<3>" LOC = "P5" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<4>" LOC = "P8" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<5>" LOC = "P9" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<6>" LOC = "P11" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT0<7>" LOC = "P12" | DRIVE = 8 | SLEW = SLOW ; # G1 (camera data signals) NET "GDAT1<0>" LOC = "P13" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<1>" LOC = "P14" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<2>" LOC = "P15" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<3>" LOC = "P16" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<4>" LOC = "P17" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<5>" LOC = "P21" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<6>" LOC = "P22" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT1<7>" LOC = "P23" | DRIVE = 8 | SLEW = SLOW ; # G2 # group G2 (camera control signals) NET "GDAT2<0>" LOC = "P27" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<1>" LOC = "P28" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<2>" LOC = "P30" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<3>" LOC = "P32" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<4>" LOC = "P34" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<5>" LOC = "P35" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<6>" LOC = "P53" | DRIVE = 8 | SLEW = SLOW ; NET "GDAT2<7>" LOC = "P54" | DRIVE = 8 | SLEW = SLOW ; # Bank 4 (2.5V) G3 NET "RLED" LOC = "P47" | DRIVE = 8 | SLEW = SLOW ; NET "GLED" LOC = "P49" | DRIVE = 8 | SLEW = SLOW ; # G3 NET "GP3<0>" LOC = "P55" ; NET "GP3<1>" LOC = "P59" ; NET "GP3<2>" LOC = "P60" ; NET "GP3<3>" LOC = "P61" ; NET "GP3<4>" LOC = "P62" ; NET "GP3<5>" LOC = "P63" ; NET "GP3<6>" LOC = "P64" ; NET "GP3<7>" LOC = "P65" ; # G4 NET "GP2<0>" LOC = "P67" ; NET "GP2<1>" LOC = "P68" ; NET "GP2<2>" LOC = "P71" ; NET "GP2<3>" LOC = "P72" ; NET "GP2<4>" LOC = "P74" ; NET "GP2<5>" LOC = "P75" ; NET "GP2<6>" LOC = "P79" ; NET "GP2<7>" LOC = "P80" ;  システムを、ブロック図で示すと以下。  画像データ処理、モータ制御はFPGAが担当し  ARMは移動のための情報処理を担当します。  ARMでの画像データ処理することも可能ですが  割込み等が頻発すると、移動処理が疎かになる  ので、FPGAに任せられる内容は、すべて任せる  ようにします。  動かすために、必要となる内容は以下。
    • タイヤ直径35mm 1回転で進む距離は約10.5mm
    • 前部にLED射光器をおく
    • 後部にエンコーダを接続
     エンコーダは、1回転3パルス出力する仕様で  16ビットカウンタを利用すると、65537まで  パルスカウントできます。  1回転=10.5mmなので、16ビットカウント値を  フルで当てると、約230mまで判断できます。  MCRのコースは、1周60m前後なのでマイコンか  FPGA内に16ビットカウンタをひとつ用意すると  1周走り終わったかを判定できます。  他に、車体スピードも逆算で求められる  ので、精度の高い走行が可能になります。
  • 目次

    inserted by FC2 system