目次

シリアルインタフェース拡張

 現在、MCR-VC用システムは、以下の5個のマイコンで
 動作する仕様です。

 これだけのマイコンがあると、階層構造を導入して
 交通整理しないと、システム全体としての統制が
 取れなくなります。

 SubBrainマイコンである、ADcU7026にはシリアル
 ポートが1チャネルだけです。

 1チャネルのシリアルポートを利用して、3つの
 マイコンの制御をできるかを検討しました。

 次のようにテスト環境を作成し、動作させました。



 ホストである、Windowsマシンからは1チャネルの
 シリアルポートが見えています。
 中間に置いたボードで、次の回路を組みます。




 この回路では、ホストが送信したコマンドは
 2つのマイコンが同時に受取ります。
 マイコンのうち、一方だけが返信できます。

 これで、SubBrain computer(ADcU7026)から
 Leg handling(ATtiny2313)、BCS handling(ATtiny2313)、
 GBC handling(ATmega328)の3つのマイコンに、コマンド
 を与えられます。

 BCS handling(ATtiny2313)、GBC handling(ATmega328)から
 はセンサーデータが返送されるので、パラレル受信します。




 この方式を採用すると、ADcU7026に必要な信号線は
 次の18本になります。(電源は、除く。)

 この方式の採用で、SubBrainもホストであるPC
 からは、同じバスに接続されたマイコンに見え
 ます。



 動作テストには、TeraTermを利用しました。

 テスト用シリアルボードは、次のような簡単なものです。



 Leg handlingのファームウエアは、以下に変更します。
#include <avr/io.h>
#include <avr/iotn2313.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define FOSC   4000000
#define BAUD   9600
#define MYUBRR (FOSC/16/BAUD)-1

#define OFF 0
#define ON  OFF+1

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;
typedef   signed char  SBYTE ;
typedef   signed short SWORD ;

typedef union {
  struct {
    unsigned char B0:1;
    unsigned char B1:1;
    unsigned char B2:1;
    unsigned char B3:1;
    unsigned char B4:1;
    unsigned char B5:1;
    unsigned char B6:1;
    unsigned char B7:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP x_flags ;

#define UFLAG x_flags.BIT.B0
#define TFLAG x_flags.BIT.B1

volatile UBYTE sbuf[8] ;
volatile UBYTE sindex ;

volatile UBYTE lduty ;
volatile UBYTE rduty ;

volatile UWORD lcount ;
volatile UWORD rcount ;

char msg[10] ;

volatile UWORD right_velocity ;
volatile UWORD left_velocity  ;
  
#define NO  0
#define YES NO+1

#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0

#define INTERVAL 49999

const prog_char msg_h[] PROGMEM = "H help" ;
const prog_char msg_d[] PROGMEM = "D set" ;

/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void  user_initialize(void);
void  usart_putchar(UBYTE x);
void  crlf(void);
void  usart_puts(UBYTE *x);
UBYTE get_hex(UBYTE x);
void  get_velocity(void);
void  pid(void);
void  show_help(void);

/*------*/
/* main */
/*------*/
int main(void)
{
  UWORD xtmp ;
  UBYTE cmd ;
  UBYTE tmp ;
  /* initialize port and variables */
  user_initialize();
  /* enable interrupt */
  sei();
  /* endless loop */
  while ( ON ) {
    /* usart receive handling */
    if ( UFLAG ) { 
      UFLAG = OFF ;
      /* get command */
      cmd = *(sbuf+0) ;
      /* update duty ratio */
      if ( cmd == 'D' ) {
        /* left duty */
        tmp = get_hex( *(sbuf+1) ) ; 
        tmp = tmp * 10 + get_hex( *(sbuf+2) ) ;
        xtmp = (tmp << 6) / 25 ;
        lduty = xtmp & MASKFF ;
        /* right duty */	
        tmp = get_hex( *(sbuf+3) ) ; 
        tmp = tmp * 10 + get_hex( *(sbuf+4) ) ;
        xtmp = (tmp << 6) / 25 ;
        rduty = xtmp & MASKFF ;
        /* store duty ratio */
        OCR0A = rduty ;
        OCR0B = lduty ;
      } 
      /* help */
      if ( cmd == 'H' ) { show_help() ; }
      /* new line */
      crlf();
    }
    /* 100ms handling */
    if ( TFLAG ) { 
      TFLAG = OFF ;
      pid();
    }
  }
  /* dummy */
  return 0 ;
}

#/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
  UWORD tmp ;
  /* PORT B */
  PORTB = 0b00000000 ; /* 00000000 */
  DDRB  = 0b11111111 ; /* oooooooo */
  /* PORT D */
  PORTD = 0b00001100 ; /* 00001100 */
  DDRD  = 0b11110010 ; /* ooooiioi */
  /* initialize flags */
  x_flags.DR = 0 ;
  /* initialize timer/counter0 */
  {
    TCCR0A = (1 << COM0B1) | (1 << COM0A1) | (3 << WGM00);
    TCCR0B = (7 << CS00) ;
    TCNT0  = 0 ;
    OCR0A  = 128 ;
    OCR0B  = 128 ;
  }
  /* initialize timer/counter1 */
  {
    /* compare match (1/8) -> 500kHz */
    TCCR1B = (1 << WGM12) | (1 << CS10) ;
    TCNT1 = 0 ;
    OCR1A = INTERVAL ;
    OCR1B = 60000 ;
  }
  /* initialize serial */
  {
    sindex = 0 ;
    /* set Baud Rate Registers */
    tmp = MYUBRR ;
    UBRRH = (UBYTE)(tmp >> 8) ;
    UBRRL = (UBYTE)(tmp & MASKFF) ;
    /* Enable receive interrupt , receive module and transmit module */
    UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE) ;
    /* 8 bits , 1 stop , non parity */
    UCSRC = (3 << UCSZ0);	
  }
  /* set INT0 and INT1 */
  MCUCR = (1 << ISC11) | (1 << ISC01) ;
  /* set TIMER1 interrupt */
  TIMSK = (1 << OCIE1A) ;
  /* enable interrupt (global) */
  GIMSK = (1 << INT1) | (1 << INT0) ;
  /* set duty ratio */
  lduty = 0 ;
  rduty = 0 ;
  /* initialize velocity */
  right_velocity = 0 ;
  left_velocity  = 0 ;
}

void  usart_putchar(UBYTE x)
{
  while ( !(UCSRA & (1 << UDRE)) ) ;
  UDR = x ;
}

void  crlf(void)
{
  usart_putchar('\r');
  usart_putchar('\n');
}

void  usart_puts(UBYTE *x)
{
  /* send charactor one by one */
  while ( *x != '\0' ) {
    usart_putchar( *x ) ;
    /* pointer increment */
    x++ ;
  }
  crlf();
}

UBYTE get_hex(UBYTE x)
{
  UBYTE result ;
  /* default */
  result = 0 ;
  /* judge */
  if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
  if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
  if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }

  return result ;
}

/* EXTERNAL INT0 */
ISR(INT0_vect)
{
  rcount++ ;
}

/* EXTERNAL INT1 */
ISR(INT1_vect)
{
  lcount++ ;
}

/* timer1 interrupt */
ISR(TIMER1_COMPA_vect)
{
  TFLAG = ON ;
}

/* UART receive interrupt */
ISR(USART_RX_vect)
{
  volatile UBYTE ch ;
  /* get 1 charactoer */
  ch = UDR ;
  /* store */
  *(sbuf+sindex) = ch ;
  sindex++ ;
  /* judge */
  if ( ch == '\r' ) {
    UFLAG = ON ;
    sindex = 0 ;
  }
}

void  get_velocity(void)
{
  /* disable external interrupt */
  GIMSK = 0 ;
  /* get counter */
  right_velocity = rcount ;
  left_velocity  = lcount ;
  /* clear counter */
  lcount = 0 ;
  rcount = 0 ;
  /* enable  external interrupt */
  GIMSK = (1 << INT1) | (1 << INT0) ;
}

void  pid(void)
{
  UWORD cr ;
  UWORD cl ;
  UBYTE dd ;
  /* judge */
  if ( rduty != lduty ) return ;
  /* get velocity */
  get_velocity();
  cr = right_velocity ;
  cl = left_velocity ;
  /* adjust */
  dd = OCR0B ; 
  /* increment */
  if ( cr > cl ) { dd += (cr - cl) / 10 ; }
  /* decrement */
  if ( cr < cl ) { dd -= (cl - cr) / 10 ; }
  /* update */
  OCR0B = dd ;
}

void  show_help(void)
{
  strcpy_P(msg,msg_h) ; usart_puts((UBYTE *)msg);
  strcpy_P(msg,msg_d) ; usart_puts((UBYTE *)msg); 
}

 コマンドは、'D'としておき、続ける4パラメータに
 左、右のDUTY比を10進2けたとします。


目次

inserted by FC2 system