目次
前
次
試走前チェック(移動関連)
走行パターンの作成ができたので、試走前チェックに入ります。
試走前に過去に半田付けした制御基板を利用して
ファームウエアの動作を確認。
JICA研修の基板の余りがあったので、必要な部品と
ケーブルを半田付け。
ファームウエアは、ATmega644でRTOSを利用。
ソースコードは、以下。
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef unsigned long ULONG ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
#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 NORMAL 1
#define CRANK 2
#define ROTATE 3
#define LANE 4
#define CHANGE 5
#define BLIND 6
#define DIR_CENTER 0
#define DIR_RIGHT 1
#define DIR_LEFT 2
const prog_char msg_h[] PROGMEM = "? help" ;
const prog_char msg_d[] PROGMEM = "D set duty ratio" ;
const prog_char msg_p[] PROGMEM = "P motor DC power" ;
const prog_char msg_s[] PROGMEM = "S get switch state" ;
const prog_char msg_r[] PROGMEM = "R show road state" ;
const prog_char msg_a[] PROGMEM = "A show active state" ;
volatile UBYTE sbuf[8] ;
volatile UBYTE sindex ;
volatile UBYTE cmd ;
volatile UBYTE dccnt ;
volatile UBYTE leftx ;
volatile UBYTE left ;
volatile UBYTE rightx ;
volatile UBYTE right ;
volatile UBYTE mstate ;
volatile UBYTE dir[2] ;
volatile UBYTE xcnt0 ;
volatile UBYTE xcnt3 ;
volatile UBYTE xcnt4 ;
volatile UBYTE xcnt5 ;
volatile UBYTE xcnt6 ;
void rs_putchar(char x)
{
while ( !(UCSR0A & (1 << UDRE0)) ) {}
UDR0 = x ;
}
void rs_puts(char *x)
{
while ( *x != '\0' ) {
rs_putchar( *x );
x++ ;
}
}
void crlf(void)
{
rs_putchar('\r');
rs_putchar('\n');
}
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 ;
}
void show_help(void)
{
char msg[32];
strcpy_P(msg,msg_h); rs_puts((char *)msg); crlf();
strcpy_P(msg,msg_d); rs_puts((char *)msg); crlf();
strcpy_P(msg,msg_p); rs_puts((char *)msg); crlf();
strcpy_P(msg,msg_s); rs_puts((char *)msg); crlf();
strcpy_P(msg,msg_r); rs_puts((char *)msg); crlf();
strcpy_P(msg,msg_a); rs_puts((char *)msg); crlf();
}
#define FOSC 16000000
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD)-1
volatile UWORD ndx[13];
volatile UWORD cdx[13];
volatile UWORD rdx[13];
volatile UWORD ldx[13];
volatile UWORD chdx[13];
volatile UWORD bldx[13];
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 WFLAG xflags.BIT.B0
#define UFLAG xflags.BIT.B1
#define EFLAG xflags.BIT.B2
#define OFF 0
#define ON OFF+1
#define NO 0
#define YES NO+1
#define MASKFFFF 0xffff
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
#define TSK_ID_MAX 8
#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
typedef struct {
void (*tsk)(void);
UWORD wcount ;
} TCBP ;
#define TTS_SUSPEND 0
#define TTS_WAIT TTS_SUSPEND+1
#define TTS_READY TTS_SUSPEND+2
volatile UWORD xready ;
volatile UWORD xsuspend;
volatile UWORD xwaitq ;
volatile UBYTE run_tsk;
volatile TCBP tcb[TSK_ID_MAX];
/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void init_usr(void);
void init_road_array(void);
void send_road_white(UBYTE x);
void send_road(UBYTE x);
UBYTE get_start(void);
UBYTE get_dir(void);
void put_motor_power(UBYTE x);
void send_dc(UBYTE ldx,UBYTE rdx);
UBYTE get_sensor(void);
void show_state(UBYTE x);
void show_duty(UBYTE ldx,UBYTE rdx);
/*-------------------------*/
/* RTOS functions protoype */
/*-------------------------*/
void init_os(void);
void update_state(UBYTE tid,UBYTE sta);
void cre_tsk(UBYTE tid,void (*tsk)(void));
void sta_tsk(UBYTE tid,UBYTE sta);
void rsm_tsk(UBYTE tid);
void sus_tsk(UBYTE tid);
void slp_tsk(void);
void wai_tsk(UWORD x);
UWORD is_tsk_ready(UBYTE tid);
void timer_handler(void);
void tsk0_proc(void);
void tsk1_proc(void);
void tsk2_proc(void);
void tsk3_proc(void);
void tsk4_proc(void);
void tsk5_proc(void);
void tsk6_proc(void);
void tsk7_proc(void);
/*------*/
/* main */
/*------*/
int main(void)
{
TCBP pcur_tsk ;
/* disable interrupt */
cli() ;
/* initialize */
init_usr();
/* initialize monitor */
init_os();
/* enable interrupt */
sei() ;
/* message */
rs_puts((char *)"Hello");
crlf();
/* loop */
run_tsk = TSK_ID0 ;
while ( ON ) {
/* task dispacher and scheduler */
pcur_tsk = tcb[run_tsk] ;
if ( is_tsk_ready( run_tsk ) != NO ) { (*(pcur_tsk.tsk))(); }
run_tsk++;
if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }
/* timer handler */
if ( WFLAG == ON ) {
/* clear flag */
WFLAG = OFF ;
/* perform */
timer_handler();
}
}
/* dummy */
return 0 ;
}
/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void init_usr(void)
{
UWORD tmp ;
/* PORT A */
PORTA = 0xff ; /* 11111111 */
DDRA = 0xff ; /* oooooooo */
/* PORT B */
PORTB = 0xc0 ; /* 11000000 */
DDRB = 0xcf ; /* ooiioooo */
/* PORT C */
PORTC = 0xff ; /* 11111111 */
DDRC = 0xff ; /* oooooooo */
/* PORT D */
PORTD = 0x01 ; /* 11110001 */
DDRD = 0x0e ; /* iiiioooi */
/* clear flags */
xflags.DR = 0 ;
/* initialize timer0 */
{
/* clear counter */
TCNT0 = 0 ;
/* set compare value */
OCR0A = 249 ;
OCR0B = 252 ;
/* select compare match */
TCCR0A = (1 << WGM01);
/* prescaler /64 => 250kHz */
TCCR0B = (1 << WGM12) | (3 << CS00) ;
/* enable compare match */
TIMSK0 = (1 << OCIE0A) ;
}
/* initialize timer1 */
{
/* clear counter */
TCNT1 = 0 ;
/* set compare value */
OCR1A = 249 ;
OCR1B = 320 ;
/* prescaler /64 => 250kHz */
TCCR1B = (1 << WGM12) | (3 << CS10) ;
/* enable compare match */
TIMSK1 = (1 << OCIE1A) ;
}
/* initialize SCI_0 */
{
/* clear index */
sindex = 0 ;
/* clear buffer */
*(sbuf+0) = '\0' ;
/* set Baud Rate Registers */
tmp = MYUBRR ;
UBRR0H = tmp / 256 ;
UBRR0L = tmp % 256 ;
/* Enable receive interrupt , receive module and transmit module */
UCSR0B = (1 << RXEN0) |( 1 << TXEN0) | (1 << RXCIE0);
/* 8bits 1 stop bit */
UCSR0C = (3 << UCSZ00);
}
/* others */
dccnt = 0 ;
leftx = 0 ;
left = 0 ;
rightx = 0 ;
right = 0 ;
xcnt0 = 0 ;
init_road_array();
}
void init_road_array(void)
{
/* NORMAL */
*(ndx+ALL_BLACK) = (10 << 8) | 10 ;
*(ndx+ALL_WHITE) = (30 << 8) | 30 ;
*(ndx+LEFT_WHITE) = (10 << 8) | 10 ;
*(ndx+RIGHT_WHITE) = (10 << 8) | 10 ;
*(ndx+CENTER) = (50 << 8) | 50 ;
*(ndx+TINY_RIGHT) = (50 << 8) | 55 ;
*(ndx+RIGHT) = (50 << 8) | 60 ;
*(ndx+BIG_RIGHT) = (50 << 8) | 65 ;
*(ndx+TINY_LEFT) = (55 << 8) | 50 ;
*(ndx+LEFT) = (60 << 8) | 50 ;
*(ndx+BIG_LEFT) = (65 << 8) | 50 ;
*(ndx+BOTH_WHITE) = (10 << 8) | 10 ;
*(ndx+ILLEAGAL) = (10 << 8) | 10 ;
/* CRANK */
*(cdx+ALL_BLACK) = (10 << 8) | 10 ;
*(cdx+ALL_WHITE) = (10 << 8) | 10 ;
*(cdx+LEFT_WHITE) = (10 << 8) | 10 ;
*(cdx+RIGHT_WHITE) = (10 << 8) | 10 ;
*(cdx+CENTER) = (30 << 8) | 30 ;
*(cdx+TINY_RIGHT) = (30 << 8) | 35 ;
*(cdx+RIGHT) = (30 << 8) | 40 ;
*(cdx+BIG_RIGHT) = (30 << 8) | 45 ;
*(cdx+TINY_LEFT) = (35 << 8) | 30 ;
*(cdx+LEFT) = (40 << 8) | 30 ;
*(cdx+BIG_LEFT) = (45 << 8) | 30 ;
*(cdx+BOTH_WHITE) = (10 << 8) | 10 ;
*(cdx+ILLEAGAL) = (10 << 8) | 10 ;
/* ROTATE */
*(rdx+ALL_BLACK) = (10 << 8) | 10 ;
*(rdx+ALL_WHITE) = (30 << 8) | 30 ;
*(rdx+LEFT_WHITE) = (10 << 8) | 50 ;
*(rdx+RIGHT_WHITE) = (50 << 8) | 10 ;
*(rdx+CENTER) = (30 << 8) | 30 ;
*(rdx+TINY_RIGHT) = (30 << 8) | 35 ;
*(rdx+RIGHT) = (30 << 8) | 40 ;
*(rdx+BIG_RIGHT) = (30 << 8) | 45 ;
*(rdx+TINY_LEFT) = (35 << 8) | 30 ;
*(rdx+LEFT) = (40 << 8) | 30 ;
*(rdx+BIG_LEFT) = (45 << 8) | 30 ;
*(rdx+BOTH_WHITE) = (25 << 8) | 25 ;
*(rdx+ILLEAGAL) = (10 << 8) | 10 ;
/* LANE */
*(ldx+ALL_BLACK) = (10 << 8) | 10 ;
*(ldx+ALL_WHITE) = (30 << 8) | 30 ;
*(ldx+LEFT_WHITE) = (10 << 8) | 50 ;
*(ldx+RIGHT_WHITE) = (50 << 8) | 10 ;
*(ldx+CENTER) = (30 << 8) | 30 ;
*(ldx+TINY_RIGHT) = (30 << 8) | 35 ;
*(ldx+RIGHT) = (30 << 8) | 40 ;
*(ldx+BIG_RIGHT) = (30 << 8) | 45 ;
*(ldx+TINY_LEFT) = (35 << 8) | 30 ;
*(ldx+LEFT) = (40 << 8) | 30 ;
*(ldx+BIG_LEFT) = (45 << 8) | 30 ;
*(ldx+BOTH_WHITE) = (10 << 8) | 10 ;
*(ldx+ILLEAGAL) = (10 << 8) | 10 ;
/* CHANGE */
*(chdx+ALL_BLACK) = (10 << 8) | 10 ;
*(chdx+ALL_WHITE) = (50 << 8) | 50 ;
*(chdx+LEFT_WHITE) = (10 << 8) | 50 ;
*(chdx+RIGHT_WHITE) = (50 << 8) | 10 ;
*(chdx+CENTER) = (50 << 8) | 50 ;
*(chdx+TINY_RIGHT) = (55 << 8) | 50 ;
*(chdx+RIGHT) = (60 << 8) | 50 ;
*(chdx+BIG_RIGHT) = (65 << 8) | 50 ;
*(chdx+TINY_LEFT) = (50 << 8) | 55 ;
*(chdx+LEFT) = (50 << 8) | 60 ;
*(chdx+BIG_LEFT) = (50 << 8) | 65 ;
*(chdx+BOTH_WHITE) = (10 << 8) | 10 ;
*(chdx+ILLEAGAL) = (10 << 8) | 10 ;
/* BLIND */
*(bldx+ALL_BLACK) = (10 << 8) | 10 ;
*(bldx+ALL_WHITE) = (50 << 8) | 50 ;
*(bldx+LEFT_WHITE) = (10 << 8) | 50 ;
*(bldx+RIGHT_WHITE) = (50 << 8) | 10 ;
*(bldx+CENTER) = (50 << 8) | 50 ;
*(bldx+TINY_RIGHT) = (55 << 8) | 50 ;
*(bldx+RIGHT) = (60 << 8) | 50 ;
*(bldx+BIG_RIGHT) = (65 << 8) | 50 ;
*(bldx+TINY_LEFT) = (50 << 8) | 55 ;
*(bldx+LEFT) = (50 << 8) | 60 ;
*(bldx+BIG_LEFT) = (50 << 8) | 65 ;
*(bldx+BOTH_WHITE) = (10 << 8) | 10 ;
*(bldx+ILLEAGAL) = (10 << 8) | 10 ;
}
/*
Timer0 interrupt
generate 10ms
*/
ISR(TIMER0_COMPA_vect)
{
/* increment */
xcnt0++ ;
/* judge */
if ( xcnt0 == 10 ) {
/* clear */
xcnt0 = 0 ;
/* set flag */
WFLAG = ON ;
}
}
/*
Timer1 interrupt
generate PWM with 10ms periode
*/
ISR(TIMER1_COMPA_vect)
{
UBYTE bport ;
/* now state */
bport = PORTB ;
/* impress */
bport &= ~0x05 ;
if ( dccnt < leftx ) { bport |= 0x04 ; }
if ( dccnt < rightx ) { bport |= 0x01 ; }
PORTB = bport ;
/* increment */
dccnt++ ;
/* judge */
if ( dccnt == 100 ) {
dccnt = 0 ;
leftx = left ;
rightx = right ;
}
}
/* UART interrupt */
ISR(USART0_RX_vect)
{
UBYTE ch ;
/* get 1 charactor */
ch = UDR0 ;
/* store */
*(sbuf+sindex) = ch ;
/* update index */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
UFLAG = ON ;
sindex = 0 ;
}
}
void send_road_white(UBYTE x)
{
UBYTE bport ;
/* get now value */
bport = PORTB ;
/* initialize */
bport |= 0xc0 ;
/* judge */
if ( x == ALL_WHITE ) { bport &= ~0xc0 ; }
if ( x == LEFT_WHITE ) { bport &= ~0x80 ; }
if ( x == RIGHT_WHITE ) { bport &= ~0x40 ; }
/* impress */
PORTB = bport ;
}
void send_road(UBYTE x)
{
UBYTE cport ;
/* judge */
switch ( x ) {
case ALL_BLACK : cport = 0x00 ; break;
case ALL_WHITE : cport = 0xff ; break;
case LEFT_WHITE : cport = 0xf0 ; break;
case RIGHT_WHITE : cport = 0x0f ; break;
case CENTER : cport = 0x18 ; break;
case TINY_RIGHT : cport = 0x0c ; break;
case RIGHT : cport = 0x06 ; break;
case BIG_RIGHT : cport = 0x03 ; break;
case TINY_LEFT : cport = 0x30 ; break;
case LEFT : cport = 0x60 ; break;
case BIG_LEFT : cport = 0xc0 ; break;
case BOTH_WHITE : cport = 0x81 ; break;
default : cport = 0xaa ; break;
}
/* impress */
PORTC = cport ^ MASKFF ;
/* judge */
send_road_white(x);
}
UBYTE get_start(void)
{
return( !(PINB & 0x10) );
}
UBYTE get_dir(void)
{
return( !(PINB & 0x20) );
}
void put_motor_power(UBYTE x)
{
if ( x ) { PORTB |= 0x02 ; }
else { PORTB &= ~0x02 ; }
}
void send_dc(UBYTE ldx,UBYTE rdx)
{
left = ldx ;
right = rdx ;
}
UBYTE get_sensor(void)
{
UBYTE result ;
/* get data */
result = PIND ;
/* shift */
result >>= 4 ;
/* mask */
result &= MASK0F ;
return result ;
}
#define TDAT_BIT 2
#define TCLK_BIT 3
void show_state(UBYTE x)
{
UBYTE aport ;
/* shift */
aport = (1 << x) ;
/* inverse */
aport ^= MASKFF ;
/* impress */
PORTA = aport ;
}
void show_duty(UBYTE ldx,UBYTE rdx)
{
UBYTE result ;
UBYTE dh;
UBYTE dl;
/* calculate */
dh = (ldx >> 3);
dl = (rdx >> 3);
/* concatenate */
result = (dh << 4) | dl ;
/* inverse */
result ^= MASKFF ;
/* impress */
for ( dl = 0 ; dl < 8 ; dl++ ) {
/* data */
PORTD &= ~(1 << TDAT_BIT) ;
if (result & 0x80 ) { PORTD |= (1 << TDAT_BIT) ; }
/* clock : H */
PORTD |= (1 << TCLK_BIT) ;
/* shift */
result <<= 1 ;
/* clock : L */
PORTD &= ~(1 << TCLK_BIT) ;
}
/* default */
PORTD &= ~(1 << TDAT_BIT) ;
}
/*-------------------------*/
/* RTOS functions protoype */
/*-------------------------*/
void init_os(void)
{
/* clear */
xready = 0 ;
xsuspend = 0 ;
xwaitq = 0 ;
/* create task*/
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);
/* set 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);
/* others */
}
void update_state(UBYTE tid,UBYTE sta)
{
UWORD tmp ;
UWORD tmpx ;
/* generate bit code */
tmp = (1 << tid);
tmpx = tmp ^ MASKFFFF ;
/* READY */
if ( sta == TTS_READY ) {
xready |= tmp;
xsuspend &= tmpx;
xwaitq &= tmpx;
}
/* SUSPEND */
if ( sta == TTS_SUSPEND ) {
xready &= tmpx;
xsuspend |= tmp;
xwaitq &= tmpx;
}
/* WAIT */
if ( sta == TTS_WAIT ) {
xready |= tmp;
xsuspend &= tmpx;
xwaitq |= tmp;
}
}
void cre_tsk(UBYTE tid,void (*tsk)(void))
{
tcb[tid].tsk = tsk ;
tcb[tid].wcount = 0;
}
void sta_tsk(UBYTE tid,UBYTE sta)
{
update_state(tid,sta);
}
void rsm_tsk(UBYTE tid)
{
update_state(tid,TTS_READY);
}
void sus_tsk(UBYTE tid)
{
update_state(tid,TTS_SUSPEND);
}
void slp_tsk(void)
{
sus_tsk(run_tsk);
}
void wai_tsk(UWORD x)
{
tcb[run_tsk].wcount = x ;
update_state(run_tsk,TTS_WAIT);
}
UWORD is_tsk_ready(UBYTE tid)
{
return( xready & (1 << tid) );
}
void timer_handler(void)
{
UBYTE i ;
UWORD wtmp ;
/* loop */
for ( i = 0 ; i < TSK_ID_MAX ; i++ ) {
if ( xwaitq & (1 << i) ) {
wtmp = tcb[i].wcount ;
wtmp-- ;
tcb[i].wcount = wtmp ;
if ( wtmp == 0 ) { rsm_tsk(i); }
}
}
}
void tsk0_proc(void)
{
UBYTE xsensor ;
/* show state */
mstate = 0 ;
show_state( mstate );
/* wait trigger */
if ( get_start() == ON ) {
/* enable */
put_motor_power( ON );
}
/* get sensor data */
xsensor = get_sensor();
/* show sensor data */
send_road( xsensor ) ;
/* delay 100ms */
wai_tsk( 10 );
}
void tsk1_proc(void)
{
/* UBYTE xmul ; */
UBYTE flag ;
UBYTE xsensor ;
UWORD tmp ;
/* default */
flag = OFF ;
/* show state */
mstate = 1 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* update motor duty ratio */
tmp = *(ndx+xsensor);
left = (tmp >> 8) & MASKFF ;
right = tmp & MASKFF ;
/* default */
*(dir+0) = DIR_CENTER ;
*(dir+1) = DIR_CENTER ;
/* get sensor */
/*
if ( xsensor == CENTER ) {
climb hill or down hill
if ( sloap ) {
xmul = *(sloapt+sloap) ;
left = (UBYTE)( xmul * left * 1.0 / 100 );
right = (UBYTE)( xmul * right * 1.0 / 100 );
}
}
*/
/* update */
send_dc(left,right);
/* judge */
if ( xsensor == ALL_WHITE ) {
rsm_tsk(CRANK);
flag = ON ;
}
if ( xsensor == LEFT_WHITE ) {
*(dir+0) = DIR_LEFT ;
*(dir+1) = DIR_RIGHT ;
rsm_tsk(LANE);
flag = ON ;
}
if ( xsensor == RIGHT_WHITE ) {
*(dir+0) = DIR_RIGHT ;
*(dir+0) = DIR_LEFT ;
rsm_tsk(LANE);
flag = ON ;
}
/* cyclic */
if ( flag == ON ) {
flag = OFF ;
slp_tsk();
} else {
wai_tsk( 10 );
}
}
void tsk2_proc(void)
{
UBYTE flag ;
UBYTE xsensor ;
UWORD tmp ;
/* default */
flag = OFF ;
/* show state */
mstate = 2 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* update motor duty ratio */
tmp = *(cdx+xsensor);
left = (tmp >> 8) & MASKFF ;
right = tmp & MASKFF ;
/* update */
send_dc(left,right);
/* judge */
if ( xsensor == LEFT_WHITE ) {
*(dir+0) = DIR_LEFT ;
*(dir+1) = DIR_RIGHT ;
}
if ( xsensor == RIGHT_WHITE ) {
*(dir+0) = DIR_RIGHT ;
*(dir+1) = DIR_LEFT ;
}
if ( xsensor == ALL_BLACK ) {
/* initialize sequence counter */
xcnt3 = 0 ;
/* update state */
rsm_tsk(ROTATE);
flag = ON ;
}
/* cyclic */
if ( flag == ON ) {
flag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
/* ROTATE */
void tsk3_proc(void)
{
UBYTE flag ;
UBYTE xsensor ;
/* default */
flag = OFF ;
/* show state */
mstate = 3 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* sequence */
switch ( xcnt3 ) {
/* rotate */
case 0 :
xcnt3 = 1 ;
left = 50 ;
right = 10 ;
if ( *(dir+0) == DIR_RIGHT ) {
left = 10 ;
right = 50 ;
}
break ;
/* judge */
case 1 :
xcnt3 = 1 ;
if ( xsensor == CENTER ) {
left = 30 ;
right = 30 ;
xcnt3 = 2 ;
}
break ;
/* straight and move */
case 2 :
xcnt3 = 3 ;
break ;
/* exit */
case 3 :
rsm_tsk(NORMAL);
flag = ON ;
break ;
/* others */
default:
break;
}
/* update */
send_dc(left,right);
/* cyclic */
if ( flag == ON ) {
xcnt3 = 0 ;
flag = OFF ;
slp_tsk();
} else {
wai_tsk( 100 );
}
}
/* LANE */
void tsk4_proc(void)
{
UBYTE flag ;
UBYTE xsensor ;
UWORD tmp ;
/* default */
flag = OFF ;
/* show state */
mstate = 4 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* update motor duty ratio */
tmp = *(ldx+xsensor);
left = (tmp >> 8) & MASKFF ;
right = tmp & MASKFF ;
/* update */
send_dc(left,right);
/* judge */
if ( xsensor == ALL_BLACK ) {
/* initialize sequence counter */
xcnt5 = 0 ;
/* update state */
rsm_tsk(CHANGE);
flag = ON ;
}
if ( xsensor == LEFT_WHITE ) {
*(dir+0) = DIR_LEFT ;
*(dir+1) = DIR_RIGHT ;
}
if ( xsensor == RIGHT_WHITE ) {
*(dir+0) = DIR_RIGHT ;
*(dir+1) = DIR_LEFT ;
}
/* cyclic */
if ( flag == ON ) {
flag = OFF ;
slp_tsk();
} else {
wai_tsk( 10 );
}
}
/* CHANGE */
void tsk5_proc(void)
{
UBYTE flag ;
UBYTE xsensor ;
/* default */
flag = OFF ;
/* show state */
mstate = 5 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* sequence */
switch ( xcnt5 ) {
/* rotate */
case 0 :
xcnt5 = 1 ;
/* set rotate direction */
left = 50 ;
right = 30 ;
if ( *(dir+0) == DIR_LEFT ) {
left = 30 ;
right = 50 ;
}
break ;
/* straight */
case 1 :
xcnt5 = 2 ;
left = 30 ;
right = 30 ;
break ;
/* move */
case 2 :
xcnt5 = 3 ;
break ;
/* exit */
case 3 :
rsm_tsk(BLIND);
flag = ON ;
break ;
/* others */
default:
break;
}
/* update */
send_dc(left,right);
/* cyclic */
if ( flag == ON ) {
flag = OFF ;
xcnt5 = 0 ;
xcnt6 = 0 ;
slp_tsk();
} else {
wai_tsk( 10 );
}
}
/* BLIND */
void tsk6_proc(void)
{
UBYTE flag ;
UBYTE xsensor ;
/* default */
flag = OFF ;
/* show state */
mstate = 6 ;
show_state( mstate );
/* get sensor */
xsensor = get_sensor();
send_road( xsensor );
/* sequence */
switch ( xcnt6 ) {
/* straight */
case 0 :
xcnt6 = 1 ;
left = 30 ;
right = 30 ;
break ;
/* judge and move */
case 1 :
xcnt6 = 1 ;
if ( xsensor == CENTER ) { xcnt6 = 2 ; }
if ( xsensor == TINY_LEFT ) { xcnt6 = 2 ; }
if ( xsensor == TINY_RIGHT ) { xcnt6 = 2 ; }
break ;
/* rotate */
case 2 :
xcnt6 = 3 ;
/* set rotate direction */
left = 50 ;
right = 30 ;
if ( *(dir+1) == DIR_LEFT ) {
left = 30 ;
right = 50 ;
}
break ;
/* move */
case 3 :
xcnt6 = 4 ;
left = 30 ;
right = 30 ;
break ;
/* exit */
case 4 :
rsm_tsk(NORMAL);
flag = ON ;
break ;
/* others */
default:
break;
}
/* update */
send_dc(left,right);
/* cyclic */
if ( flag == ON ) {
flag = OFF ;
xcnt6 = 0 ;
slp_tsk();
} else {
wai_tsk( 10 );
}
}
void tsk7_proc(void)
{
UBYTE tmp[4] ;
if ( UFLAG == ON ) {
/* clear flag */
UFLAG = OFF ;
/* get command */
cmd = *(sbuf+0);
/* new line */
crlf();
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'P' ) {
/* get code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* impress */
put_motor_power( *(tmp+0) );
}
/* set duty ratio */
if ( cmd == 'D' ) {
/* get left duty */
*(tmp+0) = get_hex( *(sbuf+1) );
*(tmp+1) = get_hex( *(sbuf+2) );
*(tmp+2) = *(tmp+0) * 10 + *(tmp+1) ;
/* get right duty */
*(tmp+0) = get_hex( *(sbuf+3) );
*(tmp+1) = get_hex( *(sbuf+4) );
*(tmp+3) = *(tmp+0) * 10 + *(tmp+1) ;
/* send */
send_dc( *(tmp+2) , *(tmp+3) );
show_duty( *(tmp+2) , *(tmp+3) );
}
/* show switch state */
if ( cmd == 'S' ) {
/* get parameter */
*(tmp+0) = *(sbuf+1) ;
/* perform */
if ( *(tmp+0) == '0' ) {
*(tmp+1) = get_start();
/* show */
rs_putchar( *(tmp+1) + '0' );
}
if ( *(tmp+0) == '1' ) {
*(tmp+3) = get_dir();
rs_putchar( *(tmp+3) + '0' );
}
/* new line */
crlf();
}
/* show road state */
if ( cmd == 'R' ) {
/* get command code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* perform */
send_road( *(tmp+0) ) ;
}
/* show active state */
if ( cmd == 'A' ) {
/* get command code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* perform */
show_state( *(tmp+0) ) ;
}
}
}
API関数とRTOSを使ったので、I/O部分を利用マイコンに合わせて
他の部分はほぼ同じにしています。
ATmega644は、フラッシュROMが64kバイト、SRAMが8kバイトありますが
どちらも10%くらいしか利用していません。
画像処理は、カメラとマイコンの組み合わせで別ユニット
にしたので、この程度のプログラムサイズで済んでいます。
机上でのテストは、次のモータユニットを使いました。
実際にコースを走るマシンは、DCモータとして産業用を
取り付けてあります。
制御基板は構成が同じなので、着脱するだけで済ませられます。
シリアルインタフェースを接続し、1文字コマンドを使い
利用してる関数とハードウエアをチェック
モータを回転させる制御信号は、基板上のモニタLEDを使って
確認できるようにしてあります。
モータを接続する前にLEDの点灯状態で、DUTY比の設定値も
ある程度判断できました。
RTOSを利用している関係で、どのタスクが実行されているかを
8個のLEDのうち、どこが点灯するかを判断できます。
8個のLEDの点灯状態をチェック。
制御基板には2ブロックの8個のLEDがあるので、緑のLED
ブロックを利用しました。
4ビットのセンサー情報から、路面状態をモニタする
LEDブロックは、赤のLEDを利用。
全白線、右片側白線、左片側白線をモニタできるかテスト。
RTOSのタスクの中に、デバッグ専用タスクを入れて対応できました。
タスクは、コマンドインタプリタで構成。
void tsk7_proc(void)
{
UBYTE tmp[4] ;
if ( UFLAG == ON ) {
/* clear flag */
UFLAG = OFF ;
/* get command */
cmd = *(sbuf+0);
/* new line */
crlf();
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'P' ) {
/* get code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* impress */
put_motor_power( *(tmp+0) );
}
/* set duty ratio */
if ( cmd == 'D' ) {
/* get left duty */
*(tmp+0) = get_hex( *(sbuf+1) );
*(tmp+1) = get_hex( *(sbuf+2) );
*(tmp+2) = *(tmp+0) * 10 + *(tmp+1) ;
/* get right duty */
*(tmp+0) = get_hex( *(sbuf+3) );
*(tmp+1) = get_hex( *(sbuf+4) );
*(tmp+3) = *(tmp+0) * 10 + *(tmp+1) ;
/* send */
send_dc( *(tmp+2) , *(tmp+3) );
show_duty( *(tmp+2) , *(tmp+3) );
}
/* show switch state */
if ( cmd == 'S' ) {
/* get parameter */
*(tmp+0) = *(sbuf+1) ;
/* perform */
if ( *(tmp+0) == '0' ) {
*(tmp+1) = get_start();
/* show */
rs_putchar( *(tmp+1) + '0' );
}
if ( *(tmp+0) == '1' ) {
*(tmp+3) = get_dir();
rs_putchar( *(tmp+3) + '0' );
}
/* new line */
crlf();
}
/* show road state */
if ( cmd == 'R' ) {
/* get command code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* perform */
send_road( *(tmp+0) ) ;
}
/* show active state */
if ( cmd == 'A' ) {
/* get command code */
*(tmp+0) = get_hex( *(sbuf+1) );
/* perform */
show_state( *(tmp+0) ) ;
}
}
}
目次
前
次