目次
前
次
デジタル回路で車を動かす
IchigoJamのBASICで、ライントレーサを動かす
ことができました。
プログラムでできることは、回路でも可能です。
最近は、マイクロコンピュータで済ませる傾向が
ありますが、何らかの原因でプログラムを失うと
動作できません。
ハードウエアだけで実現する方法を考えます。
プログラムを眺めます。
20 R=IN(1):L=IN(2)
25 ? L,R
30 OUT 4,1:OUT 2,1
50 IF R=0 THEN OUT 4,R:WAIT 15
60 IF L=0 THEN OUT 2,L:WAIT 15
100 GOTO 20
デジタル回路で繰り返しさせるには
カウンタを利用。次のようにすれば
よいはず。
カウンタ4024は、Q1からQ7をもっていますので
Q6が'1'になった瞬間にリセットし、0から32を
繰り返します。
デジタル回路でプログラムと等価なことを
やらせるには、カウンタ利用のシーケンサ
を使います。
カウンタはクロックを入れておけば
必ずループを作るので、カウンタの
出力にデコーダを接続して、他回路
に命令を出す構成にします。
図で描くと、以下。
シーケンサは、ステートマシンとも呼ばれるので
カウンタの出力をステートとして、何をするのか
を書き出します。
0
1 ドライブ回路に(1,1)を出力
2
3 センサー情報を記憶
4 ドライブ回路にセンサー情報を加工した値を出力
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 0に戻る
このシーケンサでは、時間待ちを何もしない
ステートを用意して対応。
シーケンサを実現する回路は、以下。
Q1からQ5があるので、状態は0から31になってます。
Q1からQ4の出力をデコーダに伝達するには、Q5が'0'を
出力している場合に限定。Q1からQ4では、0から15を
出力しますが、Q5が'1'のときは、0を出力しカウンタ
として動作していないように見せます。
シーケンサの出力信号をデコードして
センサー信号を記憶し、襷がけにして
ドライブ回路に出力するようにします。
ドライブ回路に、制御信号を出力するため
セレクタを使っています。セレクタのため
RSラッチを使って、切り替えておきます。
全体をまとめます。
シーケンサ部分をPIC12F1501を利用すると、次の回路に。
発振器、カウンタ、デコーダを1チップにまとめれます。
ファームウエアは、以下。
/*
File Name : seqx.c
Pin assignment
GP0 -> set (74HC74 SET)
GP1 -> trigger (74HC74 CLK)
GP2 -> monitor LED
GP3 -> RESET
GP4 -> input
GP5 -> input
*/
/* redefine data type */
typedef unsigned char UBYTE ;
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 6
volatile UBYTE tflag ;
volatile UBYTE sflag ;
volatile UBYTE aport ;
volatile UBYTE state ;
volatile UBYTE xcnt ;
volatile UBYTE ycnt ;
/* function prototype */
void init_usr(void);
void snd_set(void);
void snd_trg(void);
/* interrupt handler */
void interrupt(void)
{
/* timer 0 generate 1kHz */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* set flag */
tflag = ON ;
}
}
void snd_set(void)
{
/* get PORTA state */
aport = PORTA ;
/* send 'L' */
aport = aport & 0xfe ;
/* impress */
PORTA = aport ;
/* send 'H' */
aport = aport | ON ;
/* impress */
PORTA = aport ;
}
void snd_trg(void)
{
/* get PORTA state */
aport = PORTA ;
/* send 'H' */
aport = aport | 2 ;
/* impress */
PORTA = aport ;
/* send 'L' */
aport = aport & 0xfd ;
/* impress */
PORTA = aport ;
}
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* timer handler */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* update */
state = state + 1 ;
/* update */
state = state % 4 ;
/* enable sequence */
sflag = ON ;
/* increment */
xcnt = xcnt + 1 ;
/* judge */
if ( xcnt == 250 ) {
xcnt = 0 ;
ycnt = ycnt + 1 ;
}
/* monitor */
aport = PORTA ;
if ( ycnt & 1 ) { aport = aport | 4 ; }
else { aport = aport & 0xfb ; }
/* impress */
PORTA = aport ;
}
/* sequence */
if ( sflag == ON ) {
/* clear flag */
sflag = OFF ;
/* set */
if ( state == 0 ) { snd_set(); }
/* latch */
if ( state == 2 ) { snd_trg(); }
}
}
}
/* define function body */
void init_usr(void)
{
/* 4MHz */
OSCCON = (0x0d << 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 = 0x01 ;
/* I/O directions */
TRISA = 0xf8 ; /* bit0,1,2 as output , others as input */
/* pull-up */
WPUA = 0x30 ;
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
125kHz/250 = 500Hz
*/
OPTION_REG = 0x02 ;
/* 256 - 6 = 250 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
tflag = OFF ;
sflag = OFF ;
/* others */
state = 0 ;
xcnt = 0 ;
ycnt = 0 ;
}
目次
前
次