目次
前
次
試走前チェック(センサー関連)
センサーは、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でも対応できます。
目次
前
次