目次
前
次
デバッグ治具作成
センサーとしてGameBoyCamera(GBC)を利用します。
長いコースを用意できる期間が限られているため
机上でセンサー情報を与えて、マシン動作を確認
します。
マシン動作の確認には、専用治具を作成しました。
GBCにはArduinoを接続して、センサー情報は4ビットに
抽象化してから、制御担当のマイコンに渡します。
制御担当マイコンに、センサー情報を与えられるように
8ピンのマイコンで治具を構成しました。
回路図は、以下。
出力しているセンサー情報が何かわかるように
デコーダICを接続しています。
マイコンPIC12F1501のソースコードは、以下。
#define OFF 0
#define ON OFF+1
#define ALL_BLACK 0
#define ALL_WHITE ALL_BLACK+1
#define LEFT_WHITE ALL_BLACK+2
#define RIGHT_WHITE ALL_BLACK+3
#define CENTER ALL_BLACK+4
#define TINY_RIGHT ALL_BLACK+5
#define RIGHT ALL_BLACK+6
#define BIG_RIGHT ALL_BLACK+7
#define TINY_LEFT ALL_BLACK+8
#define LEFT ALL_BLACK+9
#define BIG_LEFT ALL_BLACK+10
#define BOTH_WHITE ALL_BLACK+11
#define ILLEAGAL ALL_BLACK+12
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
#define XCNTMAX 12000
#define CNTBEGIN 6
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
volatile UWORD xcnt ;
volatile UBYTE tflag ;
volatile UBYTE dflag ;
volatile UBYTE eflag ;
volatile UBYTE state ;
volatile UBYTE pat[8] ;
volatile UBYTE tmp ;
volatile UBYTE sensor ;
/* function prototype */
void init_usr(void);
void gen_pat(void);
/* interrupt handler */
void interrupt(void)
{
/* timer0 interrupt */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* impress */
xcnt++ ;
/* judge */
if ( xcnt == XCNTMAX ) {
/* clear */
xcnt = 0 ;
/* set flag */
tflag = ON ;
}
}
/* pin change interrupt */
if ( INTCON.IOCIF == ON ) {
/* clear flag */
IOCAF.IOCAF5 = OFF ;
/* event flag */
eflag = ON ;
}
}
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* event */
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* change mode */
dflag++ ;
dflag &= ON ;
}
/* timer interrupt */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* execute */
if ( dflag == ON ) {
/* get pattern */
tmp = *(pat+state);
/* handling */
if ( state & ON ) {
tmp >>= 4 ;
state++ ;
/* judge */
if ( state == 16 ) { state = 0 ; }
}
tmp &= 0x0f ;
/* generate code */
sensor = ((tmp & 8) << 1) | (tmp & 7);
/* impress */
PORTA = sensor ;
}
}
}
}
/* define function body */
void init_usr(void)
{
/* select 16MHz */
OSCCON = (0x0f << 3) | 0x03 ;
/* disable A/D converter */
ADCON0.ADON = OFF ;
ADCON2 = 0 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* I/O state */
PORTA = CENTER ;
/* I/O directions */
TRISA = 0x28 ; /* bit0,1,2,4 as output , others as input */
/* pull-up */
WPUA = 0x20 ;
/* pin change interrupt */
{
/* L -> H edge */
IOCAP.IOCAP5 = ON ;
/* enable */
INTCON.IOCIE = ON ;
}
/* initialize Timer 0 */
{
/*
16MHz/4 = 4MHz (BUS clock) -> 4MHz/4 = 1MHz prescaler = 1:4
*/
OPTION_REG = 0x01 ;
/* 256 - 10 = 246 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.TMR0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
tflag = OFF ;
dflag = OFF ;
eflag = OFF ;
/* initialize variables */
xcnt = 0 ;
/* sensor */
gen_pat();
}
void gen_pat(void)
{
*(pat+0) = (CENTER << 4) | CENTER ;
*(pat+1) = (RIGHT << 4) | TINY_RIGHT ;
*(pat+2) = (CENTER << 4) | TINY_RIGHT ;
*(pat+3) = (LEFT << 4) | TINY_LEFT ;
*(pat+4) = (CENTER << 4) | TINY_LEFT ;
*(pat+5) = (BIG_RIGHT << 4) | CENTER ;
*(pat+6) = (TINY_RIGHT << 4) | RIGHT ;
*(pat+7) = (CENTER << 4) | CENTER ;
}
センサー情報は、16パターンを8バイトに格納しています。
センサー情報は4ビットなので、1バイトに2パターンを
格納。センサー情報設定は、ひとつの関数にまとめてある
ので、更新すれば複雑なパターンもエミュレートできます。
ピン数の多いマイコンを利用すれば、シリアルインタフェースを
利用して、センサー情報の出現パターンを変更したり、いくつか
の出現パターンをまとめて入れておけるようになります。
部品が揃うまで、CPLDの中にシーケンサとデコーダを入れて
対応しました。
シーケンサのVHDLコードは、以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity tseq is
Port (
-- system
nRESET : in std_logic;
CLOCK : in std_logic; -- 4MHz
-- monitor
MCLK : out std_logic ;
-- counter out
SQOUT : out std_logic_vector(3 downto 0)
);
end tseq;
architecture Behavioral of tseq is
-- clock divider
signal iCNT : integer range 0 to 3999999 ;
signal iCLK : std_logic ;
--
signal iSEQ : std_logic_vector(3 downto 0) ;
begin
-- output
SQOUT <= iSEQ ;
MCLK <= not iCLK ;
-- clock divider
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iCNT = 3999999 ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
iCLK <= '1' when ( iCNT > 1999999 ) else '0' ;
-- counter
process ( nRESET , iCLK )
begin
if ( nRESET = '0' ) then
iSEQ <= "0000" ;
elsif rising_edge( iCLK ) then
iSEQ <= iSEQ + '1' ;
end if ;
end process ;
end Behavioral;
デコーダのVHDLコードは、74LS138の真理値表示の一部を
そのまま記述。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity tx138 is
port (
DIN : in std_logic_vector(3 downto 0) ;
DOUT : out std_logic_vector(15 downto 0) --;
) ;
end tx138;
architecture Behavioral of tx138 is
signal iDIN : integer range 0 to 15 ;
signal iDOUT : std_logic_vector(15 downto 0) ;
begin
-- input
iDIN <= conv_integer(DIN) ;
-- output
DOUT <= not iDOUT ;
-- decoder
iDOUT <= X"0001" when ( iDIN = 0 ) else
X"0002" when ( iDIN = 1 ) else
X"0004" when ( iDIN = 2 ) else
X"0008" when ( iDIN = 3 ) else
X"0010" when ( iDIN = 4 ) else
X"0020" when ( iDIN = 5 ) else
X"0040" when ( iDIN = 6 ) else
X"0080" when ( iDIN = 7 ) else
X"0100" when ( iDIN = 8 ) else
X"0200" when ( iDIN = 9 ) else
X"0400" when ( iDIN = 10 ) else
X"0800" when ( iDIN = 11 ) else
X"1000" when ( iDIN = 12 ) else
X"2000" when ( iDIN = 13 ) else
X"4000" when ( iDIN = 14 ) else
X"8000" when ( iDIN = 15 ) else
X"0000" ;
end Behavioral;
出力したいセンサー情報をまとめます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity tpat is
Port (
DIN : in std_logic_vector(3 downto 0) ;
DOUT : out std_logic_vector(3 downto 0) --;
);
end tpat;
architecture Behavioral of tpat is
-- constant table
CONSTANT ALL_BLACK : integer := 0 ;
CONSTANT ALL_WHITE : integer := 1 ;
CONSTANT LEFT_WHITE : integer := 2 ;
CONSTANT RIGHT_WHITE : integer := 3 ;
CONSTANT CENTER : integer := 4 ;
CONSTANT TINY_RIGHT : integer := 5 ;
CONSTANT RIGHT : integer := 6 ;
CONSTANT BIG_RIGHT : integer := 7 ;
CONSTANT TINY_LEFT : integer := 8 ;
CONSTANT LEFT : integer := 9 ;
CONSTANT BIG_LEFT : integer := 10 ;
CONSTANT BOTH_WHITE : integer := 11 ;
CONSTANT ILLEAGAL : integer := 12 ;
-- internal registers
signal iDIN : integer range 0 to 15 ;
signal iDOUT : integer range 0 to 15 ;
begin
-- input
iDIN <= conv_integer(DIN) ;
-- output
DOUT <= conv_std_logic_vector(iDOUT,4) ;
-- decoder
iDOUT <= CENTER when ( iDIN = 0 ) else
CENTER when ( iDIN = 1 ) else
TINY_RIGHT when ( iDIN = 2 ) else
RIGHT when ( iDIN = 3 ) else
TINY_RIGHT when ( iDIN = 4 ) else
CENTER when ( iDIN = 5 ) else
TINY_LEFT when ( iDIN = 6 ) else
LEFT when ( iDIN = 7 ) else
TINY_LEFT when ( iDIN = 8 ) else
TINY_LEFT when ( iDIN = 9 ) else
CENTER when ( iDIN = 10 ) else
CENTER when ( iDIN = 11 ) else
BIG_RIGHT when ( iDIN = 12 ) else
RIGHT when ( iDIN = 13 ) else
TINY_RIGHT when ( iDIN = 14 ) else
CENTER when ( iDIN = 15 ) else
ILLEAGAL ;
end Behavioral;
3つのブロックをトップレベルで接続。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity mcrd is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 4MHz
-- monitor
MCLK : out std_logic ;
-- sequencer output
SQOUT : out std_logic_vector(3 downto 0) ;
-- decoder output
DCOUT : out std_logic_vector(15 downto 0) --;
);
end mcrd ;
architecture behavioral of mcrd is
-- clock divider
signal iCLK : std_logic ;
-- sequencer
signal iSQOUT : std_logic_vector(3 downto 0) ;
-- internal pattern
signal iPATOUT : std_logic_vector(3 downto 0) ;
-- decoder
component tx138 is
port (
DIN : in std_logic_vector(3 downto 0) ;
DOUT : out std_logic_vector(15 downto 0) --;
) ;
end component;
component tpat is
Port (
DIN : in std_logic_vector(3 downto 0) ;
DOUT : out std_logic_vector(3 downto 0) --;
);
end component;
-- sequencer
component tseq is
Port (
-- system
nRESET : in std_logic;
CLOCK : in std_logic; -- 4MHz
-- monitor
MCLK : out std_logic ;
-- counter out
SQOUT : out std_logic_vector(3 downto 0)
);
end component;
begin
-- output
MCLK <= not iCLK ;
SQOUT <= iSQOUT ;
-- module instance (decoder)
DECXinst : tx138 port map (
DIN => iPATOUT ,
DOUT => DCOUT
);
-- module instance (pattern)
TPATinst : tpat port map (
DIN => iSQOUT ,
DOUT => iPATOUT
);
-- module instance
TSEQinst : tseq port map (
-- system
nRESET => nRESET ,
CLOCK => CLOCK ,
-- monitor
MCLK => iCLK ,
-- counter out
SQOUT => iSQOUT
);
end behavioral;
XC9572を利用した場合のピン割り当ては、以下。
# system
NET "CLOCK" LOC = "P5" ;
NET "nRESET" LOC = "P39" ;
# monitor
NET "SQOUT<0>" LOC = "P1" ;
NET "SQOUT<1>" LOC = "P2" ;
NET "SQOUT<2>" LOC = "P3" ;
NET "SQOUT<3>" LOC = "P4" ;
NET "MCLK" LOC = "P9" ;
# lower
NET "DCOUT<0>" LOC = "P11" ;
NET "DCOUT<1>" LOC = "P12" ;
NET "DCOUT<2>" LOC = "P13" ;
NET "DCOUT<3>" LOC = "P14" ;
NET "DCOUT<4>" LOC = "P18" ;
NET "DCOUT<5>" LOC = "P19" ;
NET "DCOUT<6>" LOC = "P20" ;
NET "DCOUT<7>" LOC = "P22" ;
# upper
NET "DCOUT<8>" LOC = "P24" ;
NET "DCOUT<9>" LOC = "P25" ;
NET "DCOUT<10>" LOC = "P26" ;
NET "DCOUT<11>" LOC = "P27" ;
NET "DCOUT<12>" LOC = "P28" ;
NET "DCOUT<13>" LOC = "P29" ;
NET "DCOUT<14>" LOC = "P33" ;
NET "DCOUT<15>" LOC = "P34" ;
波形観測用にサウンドカードに接続する
アダプタを作成しました。回路は、以下。
実際に利用するPC上のソフトウエアは、フリー
で使えるものをダウンロードしました。
サウンドカードでは、最高周波数として10kHz程度の
交流信号のみ観測できます。周波数の上限としては
厳しいですが、あるとないとでは大違いです。
利用するにはデスクトップタイプのPCが必要ですが
1チャネルでもよければ、ノートPCでも使えます。
手軽に持ち運びできるように、タッパウエアに入れ
使い勝手を良くしています。
電源は006P電池を利用し、9Vを4.5V
の正負電源にします。
GBC(GameBoyCamera)を利用するとき、レンズの前に偏光板を
おくかどうかやLED照明を使うかどうかの条件を決めます。
偏光板の着脱とLED光照射の指定を簡単にするため、マイコン
による条件の指定をすると、その環境を用意できるように
治具を作成。
偏光板は、サーボモータでGBCのレンズの前に置くか遠ざける
ようにし、LED照明はMOSFETのスイッチで電流を流すか止める
ことができるようにします。
治具のハードウエアは簡単ですが、条件設定をArduinoから
できるように、PIC12F1501のファームウエアを書きました。
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
/* pin assignment */
#define SOUT PORTA.F0
#define LOUT PORTA.F1
#define SWCR PORTA.F2
#define SWDN PORTA.F4
#define SWUP PORTA.F5
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 236
#define MASK03 0x03
#define SCNTMAX 2000
#define XCNTMAX 10000
#define LUPPER 200
#define LLOWER 100
volatile UWORD scnt ;
volatile UWORD xcnt ;
volatile UBYTE duty ;
volatile UBYTE dutyx ;
volatile UBYTE sflag ;
volatile UBYTE eflag ;
volatile UBYTE usft ;
volatile UBYTE dsft ;
volatile UBYTE csft ;
/* function prototype */
void init_usr(void);
/* interrupt handler */
void interrupt(void)
{
/* generate 100kHz */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* set flag */
sflag = ON ;
/* increment */
xcnt += 1 ;
/* judge */
if ( xcnt == XCNTMAX ) {
xcnt = 0 ;
eflag = ON ;
}
}
}
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* generate servo motor PWM */
if ( sflag == ON ) {
/* clear flag */
sflag = OFF ;
/* impress */
if ( scnt < dutyx ) { SOUT = ON ; }
else { SOUT = OFF ; }
/* update */
scnt += 1 ;
/* judge */
if ( scnt == SCNTMAX ) {
/* clear */
scnt = 0 ;
/* update */
dutyx = duty ;
}
}
/* shift register handling */
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* shift */
usft = usft + usft ;
dsft = dsft + dsft ;
csft = csft + csft ;
/* mask */
usft &= MASK03 ;
dsft &= MASK03 ;
csft &= MASK03 ;
/* update LSB */
if ( SWUP == OFF ) { usft |= ON ; }
if ( SWDN == OFF ) { dsft |= ON ; }
if ( SWCR == OFF ) { csft |= ON ; }
/* judge */
if ( usft == MASK03 ) { duty = LUPPER ; }
if ( dsft == MASK03 ) { duty = LLOWER ; }
if ( csft == MASK03 ) {
if ( LOUT == ON ) { LOUT = OFF ; }
else { LOUT = ON ; }
}
}
}
}
/* define function body */
void init_usr(void)
{
/* select 16MHz */
OSCCON = (15 << 3) | MASK03 ;
/* disable A/D converter */
ADCON0.ADON = OFF ;
ADCON2 = 0 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* I/O directions */
TRISA = 0x3C ; /* bit 0 and bit 1 as output , others as input */
/* pull-up */
WPUA = 0x3C ;
/* initialize Timer 0 */
{
/*
16MHz/4 = 4MHz -> 4MHz/2 = 2MHz prescaler = 1:2
2MHz = 2000kHz , 2000kHz / 100kHz = 20
*/
OPTION_REG = 0x00 ;
/* 256 - 20 = 236 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
sflag = OFF ;
eflag = OFF ;
/* initialize variables */
scnt = 0 ;
xcnt = 0 ;
duty = LLOWER ;
}
タイマー割込みで、スイッチの状態を読込み、サーボモータに
与えるパルス幅を変えられるようにしました。上、下を指定
するボタンとLED光の照射制御の3ボタンにまとめています。
GBCとArduinoは、1枚のプレートに実装したので、空いている
スペースにPIC121501とモータドライバを半田付けした基板を
入れます。
目次
前
次