目次
前
次
LPC1114Arduino化
mugen2015までは、MCR_VCマシンを動かすため、一部にArduinoを
利用していました。
ATmega168、ATmega328を¥200、¥250で秋月電子から入手可能で
北海道職業能力開発大校の非常勤講師をしていた頃に、学生実習の
サポートで使ったので、様々なアプリケーションを作成しました。
秋月電子の通販サイトで、IchigoJamが紹介されていました。
このIchigoJamで使われているマイコンは、32ビットでは定番
のARMでした。型番はLPC1114。
IchigoJamに興味をもち、自作の互換基板を半田付けして
使ってみました。
128kバイトのEEPROMを載せると、Basicプログラムを100程度入れる
ことができます。Basicでは動作が遅いのと、I/Oポート数が少ない
と不満を持っていました。
LPC1114を、Arduinoと同じように使えるという情報を
掴んだので、どんなものかと調べてみました。
「LPCXpresso IDE」を利用して、C/C++でファームウエアを開発する
ところまではやっていました。さらに、IchigoJamのファームウエア
をダウンロードするために、FlashMagicも使えます。
これらに、eXodusinoを加えればよいとか。
回路図を作成し、基板の半田付けをしました。
回路図は、以下。
作成した基板です。
上の基板で、MCR_VCマシンの動作をエミュレートするため
雛形になるスケッチをATmega168で作成。内容は、以下。
#include <MsTimer2.h>
#define OFF 0
#define ON OFF+1
#define MD_IDLE 0
#define MD_RUN MD_IDLE+1
#define ALL_BLACK 0
#define ALL_WHITE 1
#define LEFT_WHITE 2
#define RIGHT_WHITE 3
#define CENTER 4
#define TINY_RIGHT 5
#define RIGHT 6
#define BIG_RIGHT 7
#define TINY_LEFT 8
#define LEFT 9
#define BIG_LEFT 10
#define BOTH_WHITE 11
#define ILLEAGAL 12
#define TSK_ID_MAX 9
#define TSK_ID0 0
#define TSK_ID1 1
#define TSK_ID2 2
#define TSK_ID3 3
#define TSK_ID4 4
#define TSK_ID5 5
#define TSK_ID6 6
#define TSK_ID7 7
#define TSK_ID8 8
#define XNORMAL 1
#define XCRANK 2
#define XROTATE 3
#define XLANE 4
#define XCHANGE 5
#define XBLIND 6
#define DIR_CENTER 0
#define DIR_RIGHT 1
#define DIR_LEFT 2
#define TTS_SUSPEND 0
#define TTS_WAIT TTS_SUSPEND+1
#define TTS_READY TTS_SUSPEND+2
typedef struct {
void (*tsk)(void);
word wcount ;
} TCBP ;
TCBP tcbx[TSK_ID_MAX] ;
TCBP pcur_tsk ;
long timcnt ;
char sbuf[8] ;
char sindex ;
byte UFLAG ;
char cmd ;
byte EFLAG ;
word xready ;
word xsuspend ;
word xwaitq ;
byte run_tsk ;
byte WFLAG ;
byte dcnt ;
byte state ;
byte xdir[2] ;
byte xcnt1 ;
byte xcnt2 ;
byte xcnt3 ;
byte xcnt4 ;
byte xcnt5 ;
byte xcnt6 ;
byte road[96];
void serialEvent();
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *x)
{
while ( *x != '\0' ) {
rs_putchar( *x ) ;
x++ ;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help"); crlf();
rs_puts("E enable"); crlf();
rs_puts("e disable"); crlf();
}
void show_info(byte x)
{
switch ( x ) {
case ALL_BLACK : rs_puts("ALL_BLACK") ; break ;
case ALL_WHITE : rs_puts("ALL_WHITE") ; break ;
case LEFT_WHITE : rs_puts("LEFT_WHITE") ; break ;
case RIGHT_WHITE : rs_puts("RIGHT_WHITE"); break ;
case CENTER : rs_puts("CENTER") ; break ;
case TINY_RIGHT : rs_puts("TINY_RIGHT") ; break ;
case RIGHT : rs_puts("RIGHT") ; break ;
case BIG_RIGHT : rs_puts("BIG_RIGHT") ; break ;
case TINY_LEFT : rs_puts("TINY_LEFT") ; break ;
case LEFT : rs_puts("LEFT") ; break ;
case BIG_LEFT : rs_puts("BIG_LEFT") ; break ;
case BOTH_WHITE : rs_puts("BOTH_WHITE") ; break ;
default : rs_puts("ILLEAGAL") ; break ;
}
}
void init_road()
{
byte i ;
/* clear */
for ( i = 0 ; i < 96 ; i++ ) {
*(road+i) = CENTER ;
}
/* NORMAL */
*(road+ 0) = CENTER ; *(road+ 1) = TINY_RIGHT ;
*(road+ 2) = CENTER ; *(road+ 3) = TINY_LEFT ;
*(road+ 4) = ALL_WHITE ; *(road+ 5) = CENTER ;
*(road+ 6) = CENTER ; *(road+ 7) = LEFT_WHITE ;
*(road+ 8) = CENTER ; *(road+ 9) = CENTER ;
*(road+10) = RIGHT_WHITE ; *(road+11) = CENTER ;
*(road+12) = TINY_LEFT ; *(road+13) = CENTER ;
*(road+14) = TINY_RIGHT ; *(road+15) = CENTER ;
/* CRANK */
*(road+ 0+16) = CENTER ; *(road+ 1+16) = LEFT_WHITE ;
*(road+ 2+16) = TINY_LEFT ; *(road+ 3+16) = TINY_RIGHT ;
*(road+ 4+16) = CENTER ; *(road+ 5+16) = ALL_BLACK ;
*(road+ 6+16) = CENTER ; *(road+ 7+16) = ILLEAGAL ;
*(road+ 8+16) = CENTER ; *(road+ 9+16) = RIGHT_WHITE ;
*(road+10+16) = TINY_LEFT ; *(road+11+16) = TINY_RIGHT ;
*(road+12+16) = CENTER ; *(road+13+16) = ALL_BLACK ;
*(road+14+16) = CENTER ; *(road+15+16) = ILLEAGAL ;
/* ROTATE */
*(road+ 0+32) = ALL_BLACK ; *(road+ 1+32) = ALL_BLACK ;
*(road+ 2+32) = BIG_LEFT ; *(road+ 3+32) = BIG_LEFT ;
*(road+ 4+32) = LEFT ; *(road+ 5+32) = TINY_LEFT ;
*(road+ 6+32) = CENTER ; *(road+ 7+32) = TINY_RIGHT;
*(road+ 8+32) = ILLEAGAL ; *(road+ 9+32) = ILLEAGAL ;
*(road+10+32) = ILLEAGAL ; *(road+11+32) = ILLEAGAL ;
*(road+12+32) = ILLEAGAL ; *(road+13+32) = ILLEAGAL ;
*(road+14+32) = ILLEAGAL ; *(road+15+32) = ILLEAGAL ;
/* LANE */
*(road+ 0+48) = CENTER ; *(road+ 1+48) = TINY_LEFT ;
*(road+ 2+48) = CENTER ; *(road+ 3+48) = TINY_RIGHT ;
*(road+ 4+48) = CENTER ; *(road+ 5+48) = ALL_BLACK ;
*(road+ 6+48) = ILLEAGAL ; *(road+ 7+48) = ILLEAGAL ;
*(road+ 8+48) = ILLEAGAL ; *(road+ 9+48) = ILLEAGAL ;
*(road+10+48) = ILLEAGAL ; *(road+11+48) = ILLEAGAL ;
*(road+12+48) = ILLEAGAL ; *(road+13+48) = ILLEAGAL ;
*(road+14+48) = ILLEAGAL ; *(road+15+48) = ILLEAGAL ;
/* CHANGE */
*(road+ 0+64) = ALL_BLACK ; *(road+ 1+64) = ALL_BLACK ;
*(road+ 2+64) = ALL_BLACK ; *(road+ 3+64) = ALL_BLACK ;
*(road+ 4+64) = BIG_LEFT ; *(road+ 5+64) = LEFT ;
*(road+ 6+64) = TINY_LEFT ; *(road+ 7+64) = CENTER ;
/* BLIND */
*(road+ 0+80) = ALL_BLACK ; *(road+ 1+80) = ALL_BLACK ;
*(road+ 2+80) = ALL_BLACK ; *(road+ 3+80) = ALL_BLACK ;
*(road+ 4+80) = BIG_LEFT ; *(road+ 5+80) = LEFT ;
*(road+ 6+80) = TINY_LEFT ; *(road+ 7+80) = CENTER ;
}
void cre_tsk(byte tid,void (*tsk)(void))
{
tcbx[tid].tsk = tsk;
tcbx[tid].wcount = 0;
}
void sta_tsk(byte tid,byte sta)
{
word tmp ;
tmp = (1 << tid);
if ( sta == TTS_READY ) { xready |= tmp; }
if ( sta == TTS_SUSPEND ) { xsuspend |= tmp; }
if ( sta == TTS_WAIT ) { xwaitq |= tmp; }
}
void rsm_tsk(byte tid)
{
word tmp ;
tmp = (1 << tid);
xready |= tmp;
xsuspend &= ~tmp;
xwaitq &= ~tmp;
}
void sus_tsk(byte tid)
{
word tmp ;
tmp = (1 << tid);
xready &= ~tmp;
xsuspend |= tmp;
xwaitq &= ~tmp;
}
void slp_tsk(void)
{
sus_tsk(run_tsk);
}
void wai_tsk(word x)
{
word tmp ;
tmp = (1 << run_tsk);
xready &= ~tmp;
xsuspend &= ~tmp;
xwaitq |= tmp;
tcbx[run_tsk].wcount = x ;
}
byte is_tsk_ready(byte tid)
{
return( (xready >> tid) & ON ) ;
}
void init_os()
{
/* clear flag */
WFLAG = OFF ;
/* create */
cre_tsk(TSK_ID0,tsk0_proc);
cre_tsk(TSK_ID1,tsk1_proc);
cre_tsk(TSK_ID2,tsk2_proc);
cre_tsk(TSK_ID3,tsk3_proc);
cre_tsk(TSK_ID4,tsk4_proc);
cre_tsk(TSK_ID5,tsk5_proc);
cre_tsk(TSK_ID6,tsk6_proc);
cre_tsk(TSK_ID7,tsk7_proc);
cre_tsk(TSK_ID8,tsk8_proc);
/* initialize state */
sta_tsk(TSK_ID0,TTS_READY);
sta_tsk(TSK_ID1,TTS_SUSPEND);
sta_tsk(TSK_ID2,TTS_SUSPEND);
sta_tsk(TSK_ID3,TTS_SUSPEND);
sta_tsk(TSK_ID4,TTS_SUSPEND);
sta_tsk(TSK_ID5,TTS_SUSPEND);
sta_tsk(TSK_ID6,TTS_SUSPEND);
sta_tsk(TSK_ID7,TTS_READY);
sta_tsk(TSK_ID8,TTS_READY);
/* clear counter */
xcnt1 = 0 ;
}
void timer_handler()
{
byte i ;
word xtmp ;
for ( i = 0 ; i < TSK_ID_MAX ; i++ ) {
/* judge */
if ( xwaitq & (1 << i) ) {
xtmp = tcbx[i].wcount ;
xtmp-- ;
tcbx[i].wcount = xtmp ;
if ( xtmp == 0 ) { rsm_tsk(i); }
}
}
}
byte get_sensor(byte xid,byte xc)
{
byte result ;
byte xptr ;
/* default */
result = 0 ;
/* check ID */
if ( xid > TSK_ID6 ) { result = 0 ; }
else {
/* calculate address */
xptr = ((xid-1) << 4) | xc ;
/* get data */
result = *(road+xptr);
}
return result ;
}
void tsk0_proc()
{
/* judge */
if ( EFLAG == ON ) {
/* IDLE -> RUN */
if ( state == MD_IDLE ) {
xcnt1 = 0 ;
state = MD_RUN ;
rsm_tsk( XNORMAL ) ;
rs_puts("-> NORMAL");
crlf();
}
}
if ( EFLAG == OFF ) {
/* RUN -> IDLE */
if ( state == MD_RUN ) {
state = MD_IDLE ;
rs_puts(" suspend all task");
crlf();
sus_tsk( TSK_ID1 ) ;
sus_tsk( TSK_ID2 ) ;
sus_tsk( TSK_ID3 ) ;
sus_tsk( TSK_ID4 ) ;
sus_tsk( TSK_ID5 ) ;
sus_tsk( TSK_ID6 ) ;
}
}
}
void tsk1_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
show_hex( xcnt1 );
/* get code */
xx = get_sensor(XNORMAL,xcnt1);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* judge */
if ( xx == ALL_WHITE ) {
xcnt2 = 0 ;
/* TSK_ID2(CRANK) */
rsm_tsk( XCRANK ) ;
eflag = ON ;
}
if ( xx == LEFT_WHITE || xx == RIGHT_WHITE ) {
/* set directions */
if ( xx == LEFT_WHITE ) {
*(xdir+0) = DIR_LEFT ;
*(xdir+1) = DIR_RIGHT ;
}
if ( xx == RIGHT_WHITE ) {
*(xdir+0) = DIR_RIGHT ;
*(xdir+1) = DIR_LEFT ;
}
/* TSK_ID4(LANE) */
xcnt4 = 0 ;
rsm_tsk( XLANE ) ;
eflag = ON ;
}
/* DEBUG */
crlf();
xcnt1++;
if ( xcnt1 == 16 ) { xcnt1 = 0 ; }
/* delay 100ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 15 );
}
}
void tsk2_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
rs_putchar('\t');
show_hex( xcnt2 );
/* get code */
xx = get_sensor(XCRANK,xcnt2);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* DEBUG */
if ( xcnt2 == 0 ) {
crlf();
rs_puts("+ CRANK +");
crlf();
}
/* judge */
if ( xx == ALL_BLACK ) {
xcnt3 = 0 ;
/* */
rs_puts("DIR:");
if ( *(xdir+0) == DIR_LEFT ) { rs_putchar('L'); }
if ( *(xdir+0) == DIR_RIGHT ) { rs_putchar('R'); }
rs_puts("\t>>ROTATE");
crlf();
/* TSK_ID3(ROTATE) */
rsm_tsk( XROTATE ) ;
eflag = ON ;
}
if ( xx == LEFT_WHITE || xx == RIGHT_WHITE ) {
/* set directions */
if ( xx == LEFT_WHITE ) {
*(xdir+0) = DIR_LEFT ;
*(xdir+1) = DIR_RIGHT ;
}
if ( xx == RIGHT_WHITE ) {
*(xdir+0) = DIR_RIGHT ;
*(xdir+1) = DIR_LEFT ;
}
}
/* DEBUG */
crlf();
xcnt2++;
if ( xcnt2 == 16 ) { xcnt2 = 0 ; }
/* delay 100ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
void tsk3_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
rs_puts("\t\t");
show_hex( xcnt3 );
/* get code */
xx = get_sensor(XROTATE,xcnt3);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* DEBUG */
if ( xcnt3 == 0 ) {
crlf();
rs_puts("+ ROTATE + ");
crlf();
}
/* judge */
if ( xx == CENTER ) {
*(xdir+0) = DIR_CENTER ;
*(xdir+1) = DIR_CENTER ;
rs_puts("\t>>NORMAL");
crlf();
/* TSK_ID1(NORMAL) */
rsm_tsk( XNORMAL ) ;
eflag = ON ;
}
/* DEBUG */
crlf();
xcnt3++;
if ( xcnt3 == 16 ) { xcnt3 = 0 ; }
/* delay 1000ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
void tsk4_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
rs_putchar('\t');
show_hex( xcnt4 );
/* get code */
xx = get_sensor(XLANE,xcnt4);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* DEBUG */
if ( xcnt4 == 0 ) {
crlf();
rs_puts("+ LANE +");
crlf();
}
/* judge */
if ( xx == ALL_BLACK ) {
xcnt5 = 0 ;
/* message */
rs_puts("\t>>CHANGE");
crlf();
/* TSK_ID5(CHANGE) */
rsm_tsk( XCHANGE ) ;
eflag = ON ;
}
/* DEBUG */
crlf();
xcnt4++;
if ( xcnt4 == 16 ) { xcnt4 = 0 ; }
/* delay 1000ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
void tsk5_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
rs_puts("\t\t");
show_hex( xcnt5 );
/* get code */
xx = get_sensor(XCHANGE,xcnt5);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* DEBUG */
if ( xcnt5 == 0 ) {
crlf();
rs_puts("+ CHANGE +");
rs_puts("\tDir:");
if ( *(xdir+0) == DIR_LEFT ) { rs_putchar('L'); }
if ( *(xdir+0) == DIR_RIGHT ) { rs_putchar('R'); }
crlf();
}
/* judge */
if ( xcnt5 == 8 ) {
xcnt6 = 0 ;
/* message */
rs_puts("\t>>BLIND");
crlf();
/* TSK_ID5(BLIND) */
rsm_tsk( XBLIND ) ;
eflag = ON ;
}
/* DEBUG */
crlf();
xcnt5++;
if ( xcnt5 == 16 ) { xcnt5 = 0 ; }
/* delay 1000ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
void tsk6_proc()
{
byte xx ;
byte eflag ;
/* */
eflag = OFF ;
rs_puts("\t\t\t");
show_hex( xcnt6 );
/* get code */
xx = get_sensor(XBLIND,xcnt6);
rs_putchar('\t');
show_info( xx );
rs_putchar('\t');
/* DEBUG */
if ( xcnt6 == 0 ) {
crlf();
rs_puts("+ BLIND +");
rs_puts("\tDir:");
if ( *(xdir+1) == DIR_LEFT ) { rs_putchar('L'); }
if ( *(xdir+1) == DIR_RIGHT ) { rs_putchar('R'); }
crlf();
}
/* judge */
if ( xx == CENTER ) {
/* message */
rs_puts("\t>>NORMAL");
crlf();
/* TSK_ID1(NORMAL) */
rsm_tsk( XNORMAL ) ;
eflag = ON ;
}
/* DEBUG */
crlf();
xcnt6++;
if ( xcnt6 == 16 ) { xcnt6 = 0 ; }
/* delay 1000ms */
if ( eflag == ON ) {
eflag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
void tsk7_proc(void)
{
/* command intepreter */
if ( UFLAG == ON ) {
/* clear flag */
UFLAG = OFF ;
/* new line */
crlf() ;
/* get command */
cmd = sbuf[0] ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'E' ) { EFLAG = ON ; }
/* disable */
if ( cmd == 'e' ) { EFLAG = OFF; }
}
}
void tsk8_proc(void)
{
/* impress */
if ( dcnt & ON ) { PORTB |= (1 << 5); }
else { PORTB &= ~(1 << 5); }
/* increment */
dcnt++ ;
/* delay 500ms */
wai_tsk( 50 );
}
void update_trigger()
{
WFLAG = ON ;
}
char get_hex(byte x)
{
char result ;
/* default */
result = '0' ;
/* convert */
if ( x < 10 ) { result = x + '0' ; }
if ( x > 9 ) { result = x - 10 + 'A' ; }
return result ;
}
void show_hex(byte x)
{
byte dh ;
byte dl ;
/* separate */
dh = (x >> 4) & 15 ;
dl = x & 15 ;
/* */
rs_putchar( get_hex( dh ) ) ;
rs_putchar( get_hex( dl ) ) ;
}
void binary_display(byte x)
{
int i ;
for ( i = 7 ; i > -1 ; i-- ) {
rs_putchar('0'+((x >> i) & ON));
}
}
/* initialize */
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* */
PORTB = 0xff ;
PORTC = 0xff ;
/* data direction */
DDRB = 0xff ;
DDRC = 0x00 ;
/* initialize variables */
sindex = 0 ;
UFLAG = OFF ;
dcnt = 0 ;
xcnt1 = 0 ;
timcnt = 0 ;
/* initialize USO */
init_os();
run_tsk = TSK_ID0 ;
state = MD_IDLE ;
/* initialize table */
init_road();
/* trigger period */
MsTimer2::set(10,update_trigger);
/* enable */
MsTimer2::start();
/* direction */
*(xdir+0) = DIR_CENTER ;
*(xdir+1) = DIR_CENTER ;
/* */
crlf();
show_help();
}
/* main */
void loop()
{
/* RTOS handling */
{
/* 10ms has passed */
if ( WFLAG == ON ) {
/* clear flag */
WFLAG = OFF ;
/* call */
timer_handler();
}
/* round robbin */
pcur_tsk = tcbx[run_tsk] ;
if ( is_tsk_ready( run_tsk ) != OFF ) { (*(pcur_tsk.tsk))(); }
run_tsk++;
if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }
}
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
UFLAG = ON ;
}
}
}
LPC1114のハードウエアに合わせる前に、メモリ上にセンサー
情報を定義し、それを参照してタスクを動かします。
マシンを制御するタスクが、センサー情報により切り替わり
必要な処理を実行しているのかを調べることに特化してます。
端末接続すると、以下のコマンドが使えると表示。
コマンド'E'で、センサー情報を取得して、タスクを切り替える
ことをエミュレートしていき、コマンド'e'で終了。
センサー情報は、タスクのIDとカウンタ値から計算できるように
専用関数を定義。
byte get_sensor(byte xid,byte xc)
{
byte result ;
byte xptr ;
/* default */
result = 0 ;
/* check ID */
if ( xid > TSK_ID6 ) { result = 0 ; }
else {
/* calculate address */
xptr = ((xid-1) << 4) | xc ;
/* get data */
result = *(road+xptr);
}
return result ;
}
タスクのIDは4ビットで表現できるので、タスクが専用で使える
カウンタを用意し、そのカウンタの値を配列の添字に利用。
カウンタは4ビットとしていますが、利用できるメモリ容量が
増えれば8ビットにして、より実際のコースに近い情報を定義
できます。
センサー情報を格納した配列の定義は、ひとつの関数で処理。
添字とセンサー情報値を対応表を作成できます。
void init_road()
{
byte i ;
/* clear */
for ( i = 0 ; i < 96 ; i++ ) {
*(road+i) = CENTER ;
}
/* NORMAL */
*(road+ 0) = CENTER ; *(road+ 1) = TINY_RIGHT ;
*(road+ 2) = CENTER ; *(road+ 3) = TINY_LEFT ;
*(road+ 4) = ALL_WHITE ; *(road+ 5) = CENTER ;
*(road+ 6) = CENTER ; *(road+ 7) = LEFT_WHITE ;
*(road+ 8) = CENTER ; *(road+ 9) = CENTER ;
*(road+10) = RIGHT_WHITE ; *(road+11) = CENTER ;
*(road+12) = TINY_LEFT ; *(road+13) = CENTER ;
*(road+14) = TINY_RIGHT ; *(road+15) = CENTER ;
/* CRANK */
*(road+ 0+16) = CENTER ; *(road+ 1+16) = LEFT_WHITE ;
*(road+ 2+16) = TINY_LEFT ; *(road+ 3+16) = TINY_RIGHT ;
*(road+ 4+16) = CENTER ; *(road+ 5+16) = ALL_BLACK ;
*(road+ 6+16) = CENTER ; *(road+ 7+16) = ILLEAGAL ;
*(road+ 8+16) = CENTER ; *(road+ 9+16) = RIGHT_WHITE ;
*(road+10+16) = TINY_LEFT ; *(road+11+16) = TINY_RIGHT ;
*(road+12+16) = CENTER ; *(road+13+16) = ALL_BLACK ;
*(road+14+16) = CENTER ; *(road+15+16) = ILLEAGAL ;
/* ROTATE */
*(road+ 0+32) = ALL_BLACK ; *(road+ 1+32) = ALL_BLACK ;
*(road+ 2+32) = BIG_LEFT ; *(road+ 3+32) = BIG_LEFT ;
*(road+ 4+32) = LEFT ; *(road+ 5+32) = TINY_LEFT ;
*(road+ 6+32) = CENTER ; *(road+ 7+32) = TINY_RIGHT;
*(road+ 8+32) = ILLEAGAL ; *(road+ 9+32) = ILLEAGAL ;
*(road+10+32) = ILLEAGAL ; *(road+11+32) = ILLEAGAL ;
*(road+12+32) = ILLEAGAL ; *(road+13+32) = ILLEAGAL ;
*(road+14+32) = ILLEAGAL ; *(road+15+32) = ILLEAGAL ;
/* LANE */
*(road+ 0+48) = CENTER ; *(road+ 1+48) = TINY_LEFT ;
*(road+ 2+48) = CENTER ; *(road+ 3+48) = TINY_RIGHT ;
*(road+ 4+48) = CENTER ; *(road+ 5+48) = ALL_BLACK ;
*(road+ 6+48) = ILLEAGAL ; *(road+ 7+48) = ILLEAGAL ;
*(road+ 8+48) = ILLEAGAL ; *(road+ 9+48) = ILLEAGAL ;
*(road+10+48) = ILLEAGAL ; *(road+11+48) = ILLEAGAL ;
*(road+12+48) = ILLEAGAL ; *(road+13+48) = ILLEAGAL ;
*(road+14+48) = ILLEAGAL ; *(road+15+48) = ILLEAGAL ;
/* CHANGE */
*(road+ 0+64) = ALL_BLACK ; *(road+ 1+64) = ALL_BLACK ;
*(road+ 2+64) = ALL_BLACK ; *(road+ 3+64) = ALL_BLACK ;
*(road+ 4+64) = BIG_LEFT ; *(road+ 5+64) = LEFT ;
*(road+ 6+64) = TINY_LEFT ; *(road+ 7+64) = CENTER ;
/* BLIND */
*(road+ 0+80) = ALL_BLACK ; *(road+ 1+80) = ALL_BLACK ;
*(road+ 2+80) = ALL_BLACK ; *(road+ 3+80) = ALL_BLACK ;
*(road+ 4+80) = BIG_LEFT ; *(road+ 5+80) = LEFT ;
*(road+ 6+80) = TINY_LEFT ; *(road+ 7+80) = CENTER ;
}
ATmega168を利用したArduinoでは、SRAMが2kバイトなので
センサー情報定義に96バイトを使うと、容量を圧迫しますが
LPC1114では、SRAMが4kバイトあるので、気にすることなく
センサー情報定義の容量を増やせます。
センサー情報を、スケッチ作成時のたびに格納するのは
面倒なので、EEPROMに入れておき、パワーオンで入力と
しておきます。
利用したEEPROMは、IICバス対応のもの。
ArduinoでSDカード中のテキストファイルからEEPROMに転送します。
手持ちのSDカードシールドは、Arduino対応なので
直接接続できるのかも知れませんが、時間を有効
に使うために、専用治具としておきます。
実機でセンサーであるGame Boy Cameraユニットに接続する
ピンは、以下。
モータ制御は、ArduinoにPWM波形生成ピンがあるので
writeAnalog関数を使います。
ATmega168を利用した純正のArduinoで動作確認後
LPC1114利用のArduino互換器にスケッチを転送し
動作確認できました。
writeAnalogのパラメータで、ピン番号が異なるだけ
なので、マクロを定義して対応します。
/* ATmega168 */
#define LEFT_PWM_PIN 10
#define WRITE_PWM_PIN 9
/* LPC1114 */
#define LEFT_PWM_PIN 6
#define WRITE_PWM_PIN 3
下位で利用できる関数ができたので、DCモータに与える
DUTY比の計算ルーチンを挟んでから、writeAnalog関数
でPWM波形を出力します。
目次
前
次