目次
前
次
DCモータドライバIC選定
Youtube動画を見ると、DCモータのドライバICに
L279を利用しているとの情報が得られました。
国内でL279を入手できなそうなので、TIのSN754410NE
を入手してみました。
18ピンICで、ピンアサインは以下。
VCC2にモータ用電源を接続し、各Y出力から
電源電圧を出力できます。
Y出力の制御は、A入力を使いますが、内蔵
ドライバを利用するか否かの制御にEN入力
が割り当てされています。
真理値表から、理解できるのですが、制御の
ための電圧はVCC1に与え、モータ電圧はVCC2
を使う仕様。
モータに接続する前に、ブレッドボード上で
次のように配線し、動作を確認しました。
電源電圧が出力されていれば、LEDが点灯するので
A入力に論理レベルの'H'と'L'のいずれかを与えて
動作を調べています。
各A入力に論理値を与え、Y出力の電圧を調べるため
次のオシロジイラズを使いました。
MCRマシンでは、2個のDCモータを利用して
前進、左回転、右回転、後退等の動作になる
ので、配線の仕方でHブリッジを構成できる
のかを、内部等価回路で確認してみます。
内部等価回路は、以下。
1出力がハーフブリッジ構成なので、2組の
ハーフブリッジを利用してHブリッジを構成
して、モータの前進と後退を制御できるはず。
次のように配線して、動作を確認してみます。
CON_1、CON_2に、論理レベルの組合せ(H,L)、(L,H)、(L,L)を
与えて、モータが回転することと回転方向を確認します。
論理レベルの組合せと動作は、以下。
- (H,L) 右回転
- (L,H) 左回転
- (L,L) 停止
配線では、次の内部回路となります。
ハーフブリッジを2個使ってのフルブリッジに
すれば、2個のA入力の組合せで、回転方向を
制御可能。
左右で2個のフルブリッジを構成できるので
次の配線でモータを2個制御できます。
A入力は4つあるので、PWM波形を与えられるように
AND回路を使います。
ANDはダイオードと抵抗を使い、INVERTERは
トランジスタを使えばよいと考えます。
回路では、以下。
ドライバICを利用するときには、次のブロック図で
モータの回転を許可するか否かと回転数を制御する
ための2つのコンピュータを使うのが楽でしょう。
上にあるコンピュータをPIC12F1501として
プッシュスイッチをスタート/ストップの
トリガーとするファームウエアは、以下。
#define OFF 0
#define ON OFF+1
#define MASKFF 0xff
#define PCNTMAX 2000
typedef unsigned char UBYTE ;
typedef union {
struct {
unsigned B0:1;
unsigned B1:1;
unsigned B2:1;
unsigned B3:1;
unsigned B4:1;
unsigned B5:1;
unsigned B6:1;
unsigned B7:1;
} BIT ;
unsigned char DR ;
} FLAGSP ;
volatile FLAGSP xflags ;
#define TFLAG xflags.BIT.B0
#define SFLAG xflags.BIT.B1
#define SWIN PORTA.F5
#define EOUT PORTA.F0
#define CNTBEGIN 6
volatile UBYTE swsft ;
/* interrupt handler */
void interrupt(void)
{
/* timer0 interrupt */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* set event flag */
TFLAG = ON ;
}
}
/* function prototype */
void init_usr(void);
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* watch switch state */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* mask */
swsft = swsft & 3 ;
/* shift */
swsft = swsft + swsft ;
/* get switch state */
if ( SWIN == OFF ) { swsft = swsft + 1 ; }
/* judge */
if ( swsft == ON ) {
if ( SFLAG == ON ) { SFLAG = OFF ; }
else { SFLAG = ON ; }
}
}
/* impress */
EOUT = SFLAG ;
}
}
/* define function body */
void init_usr(void)
{
/* select 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 */
LATA = 0 ;
/* I/O directions */
TRISA = 0x38 ; /* bit0,1,2 as output , others as input */
/* pull-up */
WPUA = 0x30 ;
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz (BUS clock) -> 1MHz/4 = 250kHz
*/
OPTION_REG = 0x01 ;
/* 256 - 6 = 250 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.TMR0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flags */
xflags.DR = 0 ;
/* clear shift register */
swsft = 0 ;
}
路面センサーからの情報を3ビットだとして
下のコンピュータをPIC12F1501とした場合の
ファームウエアは、以下。
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 6
#define PCNTMAX 100
#define XLP PORTA.F5
#define XRP PORTA.F4
typedef unsigned char UBYTE ;
volatile UBYTE xflag ;
#define TFLAG xflag.F0
volatile UBYTE stmp ;
volatile UBYTE pcnt ;
volatile UBYTE rightp ;
volatile UBYTE leftp ;
volatile UBYTE right ;
volatile UBYTE left ;
volatile UBYTE aport ;
/* interrupt handler */
void interrupt(void)
{
/* timer0 interrupt */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* impress */
aport = 0 ;
if ( pcnt < left ) { aport.F5 = ON ; }
if ( pcnt < right ) { aport.F4 = ON ; }
PORTA = aport ;
/* increment */
pcnt = pcnt + 1 ;
/* judge */
if ( pcnt == PCNTMAX ) {
/* clear counter */
pcnt = 0 ;
/* reload */
right = rightp ;
left = leftp ;
}
}
/* timer1 interrupt */
if ( PIR1.TMR1IF == ON ) {
/* clear flag */
PIR1.TMR1IF = OFF ;
/* reload */
TMR1H = 61536 / 256 ;
TMR1L = 61536 % 256 ;
/* set flag */
TFLAG = ON ;
}
}
/* function prototype */
void init_usr(void);
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* event */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* get sensor data */
stmp = PORTA ;
stmp = stmp & 7 ;
/* default */
rightp = 50 ;
leftp = 50 ;
/* tiny right */
if ( stmp == 1 ) {
rightp = 60 ;
leftp = 50 ;
}
/* right */
if ( stmp == 3 ) {
rightp = 70 ;
leftp = 40 ;
}
/* tiny left */
if ( stmp == 4 ) {
rightp = 50 ;
leftp = 60 ;
}
/* left */
if ( stmp == 6 ) {
rightp = 40 ;
leftp = 70 ;
}
}
}
}
/* 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 */
LATA = 0 ;
/* I/O directions */
TRISA = 0x07 ; /* bit0,1,2,3 as inputs , others as outpus */
/* pull-up */
WPUA = 0x07 ;
/* initialize Timer 0 */
{
/*
16MHz/4 = 4MHz (BUS clock) -> 4MHz/4 = 1MHz prescaler = 1:4
*/
OPTION_REG = 0x01 ;
/* 256 - 6 = 250 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.TMR0IE = ON ;
}
/* initialize Timer 1 */
{
/* set counter 0 - 4000 */
TMR1H = 61536 / 256 ;
TMR1L = 61536 % 256 ;
/* disable gate control */
T1GCON = 0x00 ;
/* enable timer 1 */
T1CON = 0x05 ;
/* enable timer 1 interrupt */
PIE1.TMR1IE = ON ;
/* enable peripheral interrupt */
INTCON.PEIE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
xflag = 0 ;
/* initialize variables */
pcnt = 0 ;
right = 50 ;
left = 50 ;
}
2つのプログラムを合体し、PIC16F628Aに
入れてしまうと、以下。
/*
file name mcr2.c
abstract control MCR machine
CPU PIC16F628A
CLOCK 5MHz
PORTA
5 nRESET
4 start trigger
3
2
1
0 enable
PORTB
7
6
5 left
4 right
3
2 sensor_C
1 sensor_B
0 sensor_A
*/
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 6
#define PCNTMAX 100
#define SWIN PORTA.F4
#define EOUT PORTA.F0
#define XLP PORTB.F5
#define XRP PORTB.F4
typedef unsigned char UBYTE ;
volatile UBYTE xflag ;
/* set flag bit */
#define TFLAG xflag.F0
#define UFLAG xflag.F1
#define SFLAG xflag.F2
volatile UBYTE swsft ;
volatile UBYTE stmp ;
volatile UBYTE pcnt ;
volatile UBYTE rightp ;
volatile UBYTE leftp ;
volatile UBYTE right ;
volatile UBYTE left ;
volatile UBYTE bport ;
/* interrupt handler */
void interrupt(void)
{
/* timer0 interrupt */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* impress */
bport = 0 ;
if ( pcnt < left ) { bport.F5 = ON ; }
if ( pcnt < right ) { bport.F4 = ON ; }
PORTB = bport ;
/* increment */
pcnt = pcnt + 1 ;
/* initialize */
TMR0 = CNTBEGIN ;
/* judge */
if ( pcnt == PCNTMAX ) {
/* clear counter */
pcnt = 0 ;
/* reload */
right = rightp ;
left = leftp ;
/* set flag */
TFLAG = ON ;
}
}
/* timer1 interrupt */
if ( PIR1.TMR1IF == ON ) {
/* clear flag */
PIR1.TMR1IF = OFF ;
/* reload */
TMR1H = 61536 / 256 ;
TMR1L = 61536 % 256 ;
/* set flag */
UFLAG = ON ;
}
}
/* function prototype */
void init_usr(void);
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* watch switch state */
if ( UFLAG == ON ) {
/* clear flag */
UFLAG = OFF ;
/* mask */
swsft = swsft & 3 ;
/* shift */
swsft = swsft + swsft ;
/* get switch state */
if ( SWIN == OFF ) { swsft = swsft + 1 ; }
/* judge */
if ( swsft == ON ) {
if ( SFLAG == ON ) { SFLAG = OFF ; }
else { SFLAG = ON ; }
}
}
/* impress */
EOUT = SFLAG ;
/* event */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* get sensor data */
stmp = PORTB ;
stmp = stmp & 7 ;
/* default */
rightp = 50 ;
leftp = 50 ;
/* tiny right */
if ( stmp == 1 ) {
rightp = 60 ;
leftp = 50 ;
}
/* right */
if ( stmp == 3 ) {
rightp = 70 ;
leftp = 40 ;
}
/* tiny left */
if ( stmp == 4 ) {
rightp = 50 ;
leftp = 60 ;
}
/* left */
if ( stmp == 6 ) {
rightp = 40 ;
leftp = 70 ;
}
}
}
}
/* define function body */
void init_usr(void)
{
/* I/O values */
PORTA = 0x00 ;
PORTB = 0x00 ;
/* I/O directions */
TRISA = 0xf0 ; /* upper : inputs , lower : outputs */
TRISB = 0x0f ; /* upper : outputs , lower : inputs */
/* initialize Timer 0 */
{
/*
5MHz/4 = 1.25MHz (BUS clock) -> 1.25MHz/4 = 312.5kHz prescaler = 1:4
*/
OPTION_REG = 0x01 ;
/* 256 - 6 = 250 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.TMR0IE = ON ;
}
/* initialize Timer 1 */
{
/* set counter 0 - 5000 */
TMR1H = 60536 / 256 ;
TMR1L = 60536 % 256 ;
/* enable timer 1 */
T1CON = 0x05 ;
/* enable timer 1 interrupt */
PIE1.TMR1IE = ON ;
/* enable peripheral interrupt */
INTCON.PEIE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flags */
xflag = 0 ;
/* initialize variables */
pcnt = 0 ;
right = 50 ;
left = 50 ;
}
目次
前
次