目次

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)を
 与えて、モータが回転することと回転方向を確認します。

 論理レベルの組合せと動作は、以下。

 配線では、次の内部回路となります。




 ハーフブリッジを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 ;
}


目次

inserted by FC2 system