目次

試走前チェック(センサー関連)

 センサーは、GBC(Game Boy Camera)を利用。




 GBCそのものをマイコンに接続して処理すると負担が
 大きいので、Arduinoを利用して密着タイプセンサー
 と等価な画像処理後に4ビットの情報を出力。





 移動制御を担当するマイコンでは、4ビットの情報を
 センサーデータとして、2個のモータのDUTY比を生成。





 4ビットの情報を生成するために、発振器とカウンタを
 利用した治具を作成して対応します。

 Arduino基板があるので、内蔵EEPROMに32個の路面情報
 を書き込んで、トリガーを与えると自動出力する仕様
 のスケッチを作成しました。

 手元にあるArduino基板を活用します。



 机上エミュレーションでスケッチは作成済。

#include <EEPROM.h>
#include <MsTimer2.h>

#define OFF 0
#define ON  1

#define BSIZE 8

#define MASK0F 0x0f
#define MASKF0 0xf0

byte sbuf[BSIZE] ;
byte sindex ;
byte cmd ;
byte timcnt ;
byte scnt ;
byte edat[16] ;
byte bnum ;
byte dport ;
byte asc_hex[16] ;

boolean UFLAG ;
boolean OFLAG ;
boolean WFLAG ;
char ch ;

void  rs_putchar(char x)
{
  Serial.write(x);
}

void  rs_puts(char *x)
{
  while ( *x ) {
    rs_putchar( *x ) ;
    x++ ;
  }
}

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

void  binary_display(byte x)
{
  byte ii ;
  byte j ;
  for ( ii = 0 ; ii < 8 ; ii++ ) {
    j = 7 - ii ;
    rs_putchar( '0'+((x >> j) & 1) );
  }
}

void show_help() 
{
  rs_puts("? help");            crlf();
  rs_puts("B set bnum");        crlf();
  rs_puts("b get bnum");        crlf();
  rs_puts("O run");             crlf();
  rs_puts("o idel");            crlf();
  rs_puts("E set sensor data") ;crlf();
  rs_puts("e show sensor data");crlf();
  rs_puts("C clear EEPROM");    crlf();
}

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

  return result ;
}

void  put_eeprom(byte xadr,byte xdat)
{
  EEPROM.write(xadr,xdat);
}

byte  get_eeprom(byte xadr)
{
  return( EEPROM.read(xadr) );
}

void update_trigger()
{
  /* set flag */
  WFLAG = ON ;
  /* impress */
  if ( timcnt & 1 ) { PORTB |=  0x20 ; }
  else              { PORTB &= ~0x20 ; }
  /* increment */
  timcnt++ ;
}

void setup()
{
  /* set communication speed */
  Serial.begin(9600);
  sindex = 0 ;
  /* port value */
  PORTD = 0x01 ;
  PORTB = 0x00 ;
  /* port direction */
  DDRB  = 0xff ;
  DDRD  = 0xfe ;
  /* clera flags */
  UFLAG = OFF ;
  OFLAG = OFF ;
  WFLAG = OFF ;
  /* others */
  scnt = 0 ;
  timcnt = 0 ;
  /* set charactor values */
  asc_hex[0]  = '0' ; asc_hex[1]  = '1' ;
  asc_hex[2]  = '2' ; asc_hex[3]  = '3' ;
  asc_hex[4]  = '4' ; asc_hex[5]  = '5' ;
  asc_hex[6]  = '6' ; asc_hex[7]  = '7' ;
  asc_hex[8]  = '8' ; asc_hex[9]  = '9' ;
  asc_hex[10] = 'A' ; asc_hex[11] = 'B' ;
  asc_hex[12] = 'C' ; asc_hex[13] = 'D' ;
  asc_hex[14] = 'E' ; asc_hex[15] = 'F' ;
  /* message */
  rs_puts("Hello");
  crlf();
  /* 1000ms period */
  MsTimer2::set(1000,update_trigger);
  /* enable */ 
  MsTimer2::start();
}

void loop()
{
  byte i ;
  byte tmp[4] ;
  /* command interpreter */
  if ( UFLAG == ON ) {
    /* clear flag */
    UFLAG = OFF ;
    /* get command */
    cmd = *(sbuf+0) ;
    /* new line */
    crlf();
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* enable output */
    if ( cmd == 'O' ) { 
      /* clear */
      scnt = 0 ;
      /* copy */
      for ( i = 0 ; i < 8 ; i++ ) {
        /* get data */
        *(tmp+0) = get_eeprom( (bnum << 4) | i );
        /* separate */
        *(edat+2*i)   = *(tmp+0) & MASK0F ;
        *(edat+2*i+1) = (*(tmp+0) & MASKF0) >> 4 ;
      }
      /* enable */
      OFLAG = ON ;
    }
    /* disable output */
    if ( cmd == 'o' ) { OFLAG = OFF ; }
    /* set EEPROM data */
    if ( cmd == 'E' ) {
      /* get address */
      *(tmp+0) = get_hex( *(sbuf+1) );
      *(tmp+1) = get_hex( *(sbuf+2) );
      *(tmp+2) = (*(tmp+0) << 4) | *(tmp+1) ;
      /* get data */
      *(tmp+0) = get_hex( *(sbuf+3) );
      *(tmp+1) = get_hex( *(sbuf+4) );
      *(tmp+3) = (*(tmp+0) << 4) | *(tmp+1) ;
      /* store */
      put_eeprom( *(tmp+2) , *(tmp+3) );
    }
    /* show EEPROM context */
    if ( cmd == 'e' ) {
      /* loop */
      for ( i = 0 ; i < 112 ; i++ ) {
        /* get code */
        *(tmp+2) = get_eeprom( i ) ;
        /* separate */
        *(tmp+0) = *(tmp+2) & MASK0F ;
        *(tmp+1) = (*(tmp+2) >> 4) & MASK0F ;
        /* show */
        rs_putchar( asc_hex[*(tmp+0)] ); rs_putchar(' ');
        rs_putchar( asc_hex[*(tmp+1)] ); rs_putchar(' ');
        /* new line */
        if ( (i & 7) == 7 ) { crlf(); }
      }
      /* new line */
      crlf();
    }
    /* set block number */
    if ( cmd == 'B' ) { bnum = get_hex( *(sbuf+1) ); }
    /* show block number */
    if ( cmd == 'b' ) {
      rs_putchar( bnum + '0' );
      crlf();
    }
    /* clear EEPROM */
    if ( cmd == 'C' ) {
      *(tmp+0) = 0x00 ;
      for ( i = 0 ; i < 112 ; i++ ) {
        /* store */
        put_eeprom( i , *(tmp+0) );
        /* progress */
        rs_putchar('@');
        /* new line */
        if ( (i & MASK0F) == MASK0F ) { crlf(); }
      }
      /* new line */
      crlf();
    }
  }
  /* timer handler */
  if ( WFLAG == ON ) {
    /* clear flag */
    WFLAG = OFF ;
    /* perform */
    if ( OFLAG == ON ) {
      /* impress */
      dport = *(edat+scnt);
      dport <<= 4 ;
      dport &= MASKF0;
      PORTD = dport ;
      /* debug */
      binary_display( dport );
      crlf();
      /* increment */
      scnt++ ;
      /* judge */
      if ( scnt == 16 ) { scnt = 0 ; }
    }
  }
}

/* receive interrupt */
void serialEvent()
{
  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      UFLAG = ON ;
    }
  }
}

 端末ソフトを利用すれば、MCR_VCの移動を制御する
 マイコンに接続して、路面センサーの取得情報での
 動作確認ができます。




 Arduinoからセンサー情報を出力するので、制御用マイコンは
 モニタLEDに該当する情報の再生をします。




 この他に路面状態を表示するLEDが2個あるので、3状態を
 2個のLEDの点灯状態に組み合わせて処理。



 路面状態に合わせたモータのDUTY比は、次のモニタLED基板で
 表示できるようにしてみました。




 シフトレジスタ74HC164とLEDを使い、左右のモータのDUTY比に
 相当する点灯パターンを表示。DUTY比を4ビットで表現すると
 して、左右のDUTY比を8で割った商を各々使います。

 8で割った商は、元の値を右に3ビットシフトするだけで
 計算できるので、コード量が増えることもなく実装可能。

 試走前のチェックをしてきたなら、LEDの表示はロジックICを利用
 して、まとめらると気付きました。

 LCDを利用するときは、ピン数を減らすため、74HC164をシリアル
 パラレル変換のバッファで利用しています。これをロジックICへ
 拡張するだけ。回路は以下。




 LEDは32個ありますが、1個1mAとすると最高で32mA流れます。
 すべてのLEDが点灯することはないので、20mA程度と判断でき
 電源の負担になることはないでしょう。

 1ポート=8ビットとすると、6ビットで32LEDを担当できるので
 ATmega168を使ったArduinoでも対応できます。


目次

inserted by FC2 system