目次

メカ変更

 試走を繰り返しているうちに、モータを入れたギア
 ボックスの固定エリアが破損してしまいました。



 予備のギアボックスがありますが、遊んでいた移動
 メカに同じギアボックスが使われていたので、代用
 します。



 タイヤを交換し、前方に小さなキャスターを入れました。

 大量のデジタル回路を入れられるFPGA基板と
 モータドライブ回路を載せた基板を実装可能
 になりました。



 前方を左右に振る動作を最小限に抑えるために
 サーボモータを利用した舵角メカを加えます。



 舵角メカには、サーボモータを入れることにし
 CPLD/FPGA基板上に、制御回路とDCDCコンバータ
 を載せます。



 前方に、制御回路とDCDCコンバータをいれても
 充分余裕があります。



 外部回路の動作確認に利用したVHDLコードは以下。

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

entity mcrtsty is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- trigger
    TRG    : in  std_logic ;
    -- DIP switch inputs
    DIN    : in  std_logic_vector(1 downto 0) ;
    -- logic 
    BKWTIN : in  std_logic ;
    -- monitor output
    MLOUT  : out std_logic_vector(1 downto 0);
    MBKT   : out std_logic ;
    -- monitor output
    PWMOUT : out std_logic_vector(1 downto 0);
    -- rotary encoder
    ENC    : out std_logic_vector(1 downto 0);
    RENC   : in  std_logic ;
    LENC   : in  std_logic ;
    -- output
    LOUT   : out std_logic_vector(7 downto 0);
    LOUTX  : out std_logic -- ;
  );
end mcrtsty ;

architecture Behavioral of mcrtsty is
  -- clock generator
  signal iCNT  : std_logic_vector(27 downto 0) ;
  signal iMCLK : std_logic ;
  -- trigger handling
  signal iTRG_SFT : std_logic_vector(2 downto 0) ;
  signal iTRG     : std_logic ;
  -- decoder
  signal iLOUTX : std_logic ;
  signal iLOUT  : std_logic_vector(7 downto 0);
  -- sequencer
  signal iSTATE  : std_logic_vector(1 downto 0) ;
  signal iENABLE : std_logic ;
  signal iPWMOUT : std_logic_vector(1 downto 0) ;
  -- DIP switch inputs
  signal iDIN : std_logic_vector(1 downto 0) ;
  signal iREG : std_logic_vector(1 downto 0) ;
  --
  signal iBKWTIN : std_logic ;
  -- rotary encoder
  signal iRENC      : std_logic ;
  signal iLENC      : std_logic ;
  signal iRENC_SFT  : std_logic_vector(2 downto 0) ;
  signal iLENC_SFT  : std_logic_vector(2 downto 0) ;
  signal iRENC_TRG  : std_logic ;
  signal iLENC_TRG  : std_logic ;
  signal iRENC_CNT  : std_logic_vector(11 downto 0) ;
  signal iLENC_CNT  : std_logic_vector(11 downto 0) ;
  signal iRENC_CNTX : std_logic_vector(11 downto 0) ;
  signal iLENC_CNTX : std_logic_vector(11 downto 0) ;
  signal iROT_STATE : std_logic_vector(1 downto 0) ;
  signal iROT_CNT   : integer range 0 to 100 ;
  signal iROT_CLR   : std_logic ;
  signal iROT_DISTANCE : integer range 0 to 65535 ;
begin
  -- outputs
  LOUTX  <= not iLOUTX ;
  LOUT   <= not iLOUT ;
  MLOUT  <= iREG ;
  PWMOUT <= iPWMOUT ;
  MBKT   <= iBKWTIN ; 
  ENC    <= iLENC & iRENC ;

  -- inputs
  iDIN    <= DIN ;
  iBKWTIN <= BKWTIN ;
  iRENC   <= not RENC ;
  iLENC   <= not LENC ;

  -- clock generator
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= (others => '0') ;
    elsif rising_edge(CLOCK) then
      iCNT <= iCNT + '1' ;
    end if ;
  end process ;
  iMCLK <= iCNT(18) ;

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

  -- sequencer
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE <= "00" ;
    elsif rising_edge(iMCLK) then
      case conv_integer(iSTATE) is
        -- wait trigger
        when 0 => if ( iTRG = '1' ) then
                    iSTATE <= "01" ;
                  else
                    iSTATE <= "00" ;
                  end if ;
        -- dummy skip
        when 1 => iSTATE <= "11" ;
        -- wait trigger
        when 3 => if ( iTRG = '1' ) then
                    iSTATE <= "10" ;
                  else
                    iSTATE <= "11" ;
                  end if ;
        -- return first state
        when 2 => iSTATE <= "00" ;
        -- default
        when others =>
                  iSTATE <= "00" ;
      end case ;
    end if ;
  end process ;
  iENABLE <= iSTATE(0) ;

  -- decoder
  iLOUTX <= iCNT(20) when ( iENABLE = '1' ) else '0' ;
  iLOUT  <= iCNT(27 downto 20) ;

  -- DIP switch inputs
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iREG <= "00" ;
    elsif rising_edge(iMCLK) then
      iREG <= iDIN ;
    end if ;
  end process ;

  iPWMOUT(0) <= iCNT(22) when ( iENABLE = '1' ) else '0' ;
  iPWMOUT(1) <= iCNT(23) when ( iENABLE = '1' ) else '0' ;

  -- rotary encoder
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iRENC_SFT <= "000" ;
      iLENC_SFT <= "000" ;
    elsif rising_edge(iMCLK) then
      iRENC_SFT <= iRENC_SFT(1 downto 0) & iRENC ;
      iLENC_SFT <= iLENC_SFT(1 downto 0) & iLENC ;
    end if ;
  end process ; 
  iRENC_TRG <= '1' when ( iRENC_SFT = "011" or iRENC_SFT = "001" ) else '0' ;
  iLENC_TRG <= '1' when ( iLENC_SFT = "011" or iLENC_SFT = "001" ) else '0' ;

  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iRENC_CNT <= (others => '0') ;
      iLENC_CNT <= (others => '0') ;
    elsif rising_edge(iMCLK) then
      -- right side
      if ( iRENC_TRG = '1' ) then
        iRENC_CNT <= iRENC_CNT + '1' ;
      elsif ( iROT_CLR = '1' ) then
        iRENC_CNT <= (others => '0') ;
      end if ;
      -- left side
      if ( iLENC_TRG = '1' ) then
        iLENC_CNT <= iLENC_CNT + '1' ;
      elsif ( iROT_CLR = '1' ) then
        iLENC_CNT <= (others => '0') ;
      end if ;
    end if ;
  end process ; 

  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iROT_STATE <= "00" ;
      iRENC_CNTX <= (others => '0') ;
      iLENC_CNTX <= (others => '0') ;
      iROT_CNT <= 0 ;
      iROT_DISTANCE <= 0 ;
    elsif rising_edge(iMCLK) then
      case conv_integer(iROT_STATE) is
        -- transfer 
        when 0 => iROT_STATE <= "01" ;
                  iRENC_CNTX <= iRENC_CNT ;
                  iLENC_CNTX <= iLENC_CNT ;
        -- clear and add 
        when 1 => iROT_STATE <= "11" ;
                  iROT_CNT   <= 99 ;
                  iROT_DISTANCE <= iROT_DISTANCE + conv_integer(iRENC_CNTX ) ;
        -- wait 
        when 3 => if ( iROT_CNT = 0 ) then
                    iROT_STATE <= "10" ;
                  else
                    iROT_STATE <= "11" ;
                    iROT_CNT <= iROT_CNT - 1 ;
                  end if ;
        -- return first state 
        when 2 => iROT_STATE <= "00" ;
        -- default 
        when others => 
                  iROT_STATE <= "00" ;
      end case ;
    end if ;
  end process ;
  iROT_CLR <= '1' when ( iROT_STATE = "01" ) else '0' ;

end Behavioral;

 ピンアサインは、以下としてあります。

BLOCK RESETPATHS;
BLOCK ASYNCPATHS;
#
BANK 0 VCCIO 3.3 V;
BANK 1 VCCIO 3.3 V;
BANK 2 VCCIO 3.3 V;
BANK 3 VCCIO 3.3 V;
IOBUF ALLPORTS IO_TYPE=LVCMOS33 ;
# system
LOCATE COMP "nRESET" SITE "70" ;
LOCATE COMP "CLOCK"  SITE "50" ; # 10MHz
# trigger input
LOCATE COMP "TRG" SITE "68" ;
# Black or White logic value select
LOCATE COMP "BKWTIN" SITE "57" ;
# LED output
LOCATE COMP "LOUTX" SITE "71" ;
LOCATE COMP "MBKT"  SITE "38" ;
# rotary encoder
LOCATE COMP "RENC" SITE "52" ;
LOCATE COMP "LENC"  SITE "54" ;
LOCATE COMP "ENC[0]"  SITE "48" ;
LOCATE COMP "ENC[1]"  SITE "55" ;
#
LOCATE COMP "LOUT[0]" SITE "97"  ;
LOCATE COMP "LOUT[1]" SITE "98"  ;
LOCATE COMP "LOUT[2]" SITE "99"  ;
LOCATE COMP "LOUT[3]" SITE "100" ;
LOCATE COMP "LOUT[4]" SITE "104" ;
LOCATE COMP "LOUT[5]" SITE "105" ;
LOCATE COMP "LOUT[6]" SITE "106" ;
LOCATE COMP "LOUT[7]" SITE "107" ;
# DIP switch inputs
LOCATE COMP "DIN[0]" SITE "62"  ;
LOCATE COMP "DIN[1]" SITE "67"  ;
# monitor outpus
LOCATE COMP "MLOUT[0]" SITE "61"  ;
LOCATE COMP "MLOUT[1]" SITE "65"  ;
# PWM_OUT
LOCATE COMP "PWMOUT[0]" SITE "60" ; # right
LOCATE COMP "PWMOUT[1]" SITE "58" ; # left

 サーボモータの動作は、Arduinoを利用しました。



 Arduinoから、0、90、180度の3つの角度に
 相当するパルスを出力してテストしました。
 スケッチは、以下です。

#include <Servo.h>

// pin assignment
#define SERVOPIN 3

#define DMAX 179
#define DMID 90
#define DMIN 0

#define INTERV 200

// create servo object to control a servo
Servo oneservo;

int  val;
char cmd ;
int  xinterval ;

void show_help()
{
  Serial.println("? help");
  Serial.println("s 0 degree");
  Serial.println("m 90 degree");
  Serial.println("l 180 degree");
}

void setup()
{
  // serial
  Serial.begin(9600);
  // attaches the servo
  oneservo.attach(SERVOPIN);
  // place 90 degree
  val = DMID ;
  oneservo.write(val);
  // delay counter
  xinterval = INTERV ;
}
 
void loop()
{
  // serial handling
  if (Serial.available() > 0) {
    // get command
    cmd = Serial.read();
    // judge
    if ( cmd == '?' ) { show_help() ; }
    if ( cmd == 's' ) { val = DMIN ; }
    if ( cmd == 'm' ) { val = DMID ; }
    if ( cmd == 'l' ) { val = DMAX ; }
    // feed back
    switch ( val ) {
      case DMID : Serial.println(" 90 degree"); break ;
      case DMAX : Serial.println("180 degree"); break ;
      default   : Serial.println("  0 degree"); break ;
    }
  }
  // impress
  oneservo.write(val);
  // delay
  delay(xinterval);
}

 トランジスタによる発振回路で作ったDCDCコンバータは
 電流が取れないので、サーボモータを接続するとモニタ
 用LEDが即座に消灯しました。

 5V前後で動作するサーボモータに交換して
 電源を直結すると、Arduinoのパルスで問題
 なく動きました。

 次にBarCodeScannerを接続して、動作確認しました。



 コネクタは、次のように前方に取り付けています。



 前方にサーボモータを取り付け、メカ変更終了。



 サーボモータの上に、櫓を組んでBarCodeScannerを
 実装します。




目次

inserted by FC2 system