#include#include "m9402.h" #define A_PWM_DUTY_L PBDR1 /* depend on electronics' request */ #define A_PWM_DUTY_R PADR1 /* '' */ /* #define PWM_VELO_SLOW 15.0f */ /* MIRS's velosity (slow) */ /* #define PWM_VELO_FAST 20.0f */ /* '' (fast) */ #define PWM_SLOW_STR 30.0f /* for straight ; 2/7 ,2/11 ,2/12 ,2/13 ,2/14 ,2/16 */ #define PWM_FAST_STR 50.0f #define PWM_SLOW_CUR 10.0f /* for curve ; 2/7 ,2/11 ,2/12 ,2/13 ,2/14 */ #define PWM_FAST_CUR 30.0f #define PWM_SLOW_ROT 10.0f /* for rotation ; 2/7 ,2/11 ,2/12 ,2/13 ,2/14 */ #define PWM_FAST_ROT 20.0f #define PWM_RADI_SHORT 15.0f /* MIRS's radius of motion (short) ,2/14 */ #define PWM_RADI_LONG 40.0f /* '' (long) ,2/14,2/15 */ #define RADI_DTL 4.0f /* 'dtl' means left tire for drive */ #define RADI_DTR 4.0f /* 'dtr' means right tire for drive */ #define LOCA_DTL 10.3f #define LOCA_DTR 10.3f #define PI 3.14159265f #define DEGREEIZE (180.0f/PI) #define PWM_MAX 80 /* limit of pwm duty */ #define PWM_MIN 10 /* '' , 2/13,2/14,2/14 */ #define PWM_MIN_S 20 /* '' (straight) , 2/14 */ #define PWM_NN 10 /* for PWM control , 2/13,2/14,2/14,2/16 */ #define FOOD 10 /* for feedback 2/5 , 2/13,2/14,2/16 */ #define FOOD_S 3 /* 2/16 */ #define FEED_MAX 20 /* 2/14,2/16 */ #define MOTORIZE_L 10 /* duty ratio [%] --> angular frequency [degree/sec], image */ #define MOTORIZE_R 10 /* '' */ extern unsigned char pwm_mode ; /* data of MIRS's motion */ extern int initial[MAXTSK] ; int tire( unsigned char, int ) ; int feedback0( int *, unsigned char, int *, int *) ; /* 2/16 */ int feedback1( int *, unsigned char, int *, int *) ; /* 2/16 */ void pwm_give( void ) { /* index : 0 --- left , 1 --- right */ int tire_dt[2] ; /* angular frequency of tires */ static int tire_t[2] ; /* '' */ int diff_dummy[2] ; /* 2/16 */ int diff[2] ; unsigned int i ; char dir ; /* direction of tires. 1:forward, 0:back */ char data[2] ; /* pwm send data */ char pwm_limit[2] ; /* 2/13 */ char pwm_low[2] ; /* 2/13 */ static char pwm_duty[2] ; /* [-100,100] [%] */ static int control[2] ; static unsigned char last_mode ; /* last pwm_mode */ static char duty_max[2] ; /* 2/15 */ static char duty_min[2] ; /* 2/15 */ static int duty_count[2] ; /* 2/15 */ static int max_flg[2] ; /* 2/15 */ static int min_flg[2] ; /* 2/15 */ if( initial[4] != 0 ) /* initialize : static */ { tire_t[0] = 0 ; tire_t[1] = 0 ; pwm_duty[0] = 0 ; pwm_duty[1] = 0 ; control[0] = 0 ; control[1] = 0 ; last_mode = 0x04 ; /* useless value 0x04 */ duty_max[0] = 0 ; /* 2/15 */ duty_max[1] = 0 ; /* 2/15 */ duty_min[0] = 100 ; /* 2/15 */ duty_min[1] = 100 ; /* 2/15 */ duty_count[0] = 0 ; /* 2/15 */ duty_count[1] = 0 ; /* 2/15 */ max_flg[0] = 0 ; /* 2/15 */ max_flg[1] = 0 ; /* 2/15 */ min_flg[0] = 0 ; /* 2/15 */ min_flg[1] = 0 ; /* 2/15 */ } diff[0] = 0 ; /* 2/7 */ diff[1] = 0 ; diff_dummy[0] = 0 ; /* 2/16 */ diff_dummy[1] = 0 ; /* 2/16 */ tire_dt[0] = sys9(5,1) ; /* real angular frequency of tires */ tire_dt[1] = sys9(5,2) ; /* [deg/sec] */ /* feedback 2/4,2/13 */ if( last_mode != pwm_mode ) { tire_t[0] = tire( pwm_mode, 0 ) ; /* target angular frequency of tires */ tire_t[1] = tire( pwm_mode, 1 ) ; /* [deg/sec] */ if( (pwm_mode&0xd0) == 0xd0 ) /* 2/16 */ { pwm_duty[0] = tire_t[0] / MOTORIZE_L ; pwm_duty[1] = 0 ; } else if( (last_mode&0xc6) == 0x00 ) /* 2/14 */ { pwm_duty[0] = tire_t[0] / MOTORIZE_L ; /* 2/13,2/14 */ pwm_duty[1] = tire_t[1] / MOTORIZE_R ; /* 2/13,2/14 */ } else if( (last_mode&0x02) == 0x02 ) /* for rotation , 2/16 */ { pwm_duty[0] = tire_t[0] / MOTORIZE_L ; /* 2/13,2/14 */ pwm_duty[1] = tire_t[1] / MOTORIZE_R ; /* 2/13,2/14 */ } else if( (pwm_mode&0xc2) == 0x40 ) /* for straight ,2/16 */ { pwm_duty[0] = tire_t[0] / MOTORIZE_L ; /* 2/13,2/14 */ pwm_duty[1] = tire_t[1] / MOTORIZE_R ; /* 2/13,2/14 */ } else if( (last_mode&0x20) != (pwm_mode&0x20) ) /* 2/14 */ { pwm_duty[0] = tire_t[0] / MOTORIZE_L ; pwm_duty[1] = tire_t[1] / MOTORIZE_R ; } control[0] = 0 ; control[1] = PWM_NN ; /* 2/15 */ duty_max[0] = 0 ; /* 2/15 */ duty_max[1] = 0 ; /* 2/15 */ duty_min[0] = 100 ; /* 2/15 */ duty_min[1] = 100 ; /* 2/15 */ duty_count[0] = 0 ; /* 2/15 */ duty_count[1] = 0 ; /* 2/15 */ max_flg[0] = 0 ; /* 2/15 */ max_flg[1] = 0 ; /* 2/15 */ min_flg[0] = 0 ; /* 2/15 */ min_flg[1] = 0 ; /* 2/15 */ } else if( control[0] < control[1] ) /* 2/15 */ { control[0]++ ; } else { /* determine diff[2] in feedback0(), feedback1(), 2/16 */ (void) feedback0( diff_dummy, pwm_mode, tire_dt, tire_t ) ; /* 2/16 */ diff[0] = diff_dummy[0] ; /* for curve ,2/16 */ if( (pwm_mode&0x02) == 0x02 ) /* for rotation ,2/16 */ { diff[0] = diff_dummy[0] ; diff[1] = diff_dummy[1] ; } else /* for curve or straight , 2/16 */ { (void) feedback1( diff_dummy, pwm_mode, tire_dt, tire_t ) ; diff[1] = diff_dummy[1] ; /* for curve ,2/16 */ if( (pwm_mode&0xc2) == 0x40 ) /* for straight ,2/16 */ { diff[0] = FOOD_S * diff_dummy[0] ; diff[1] = FOOD_S * diff_dummy[1] ; } } /* determine limit ,2/13 */ /* high */ pwm_limit[0] = PWM_MAX ; pwm_limit[1] = PWM_MAX ; if( (pwm_mode&0xc6) == 0x00 ) { pwm_limit[0] = 0 ; pwm_limit[1] = 0 ; } if( (pwm_mode&0xc2) == 0x80 ) { pwm_limit[0] = PWM_MAX / 2 ; } if( (pwm_mode&0xc2) == 0xc0 ) { pwm_limit[1] = PWM_MAX / 2 ; } /* low */ pwm_low[0] = PWM_MIN ; /* 2/13 */ pwm_low[1] = PWM_MIN ; /* 2/13 */ if( (pwm_mode&0xc0) == 0x40 ) /* 2/14 */ { pwm_low[0] = PWM_MIN_S ; /* 2/14 */ pwm_low[1] = PWM_MIN_S ; /* 2/14 */ } if( (pwm_mode&0xc2) == 0x80 ) /* 2/15 */ { pwm_low[1] = PWM_MIN_S ; /* 2/15 */ } if( (pwm_mode&0xc2) == 0xc0 ) /* 2/15 */ { pwm_low[0] = PWM_MIN_S ; /* 2/15 */ } /* 2/15,2/16 */ for( i=0 ; i<2 ; i++ ) { if( (pwm_mode&0xc0)==0x40 || i==1 ) /* 2/15,2/16 for right tire feedback */ break ; if( duty_count[i] >= 3 ) { pwm_duty[i] = (duty_max[i]+duty_min[i])/2 ; pwm_low[i] = pwm_duty[i] - 5 ; pwm_limit[i] = pwm_duty[i] + 5 ; if( abs(tire_dt[i]*3/2) < abs(tire_t[i]) ) /* non stop ,2/16 */ { duty_count[i] = 0 ; pwm_duty[0] = tire_t[0]/MOTORIZE_L ; } } } /* feedbacking */ for( i=0 ; i<2 ; i++ ) { if( pwm_duty[i]>=pwm_limit[i] && diff[i]>0 ) /* 2/13 */ {} else if( pwm_duty[i]<=(-pwm_limit[i]) && diff[i]<0 ) /* 2/13 */ {} else if( pwm_duty[i]>0 && pwm_duty[i]<=pwm_low[i] && diff[i]<0 ) /* 2/13 */ {} else if( pwm_duty[i]<0 && pwm_duty[i]>=(-pwm_low[i]) && diff[i]>0 ) /* 2/13 */ {} else { pwm_duty[i] += diff[i] ; } /* protect 2/15 */ if( pwm_duty[i]<0 && tire_t[i]>0 ) /* 2/15 */ { pwm_duty[i] = 1 ; } if( pwm_duty[i]>0 && tire_t[i]<0 ) /* 2/15 */ { pwm_duty[i] = -1 ; } /* for stop 2/15 */ if( tire_t[i] == 0 ) { pwm_duty[i] = 0 ; } } /* 2/15 */ for( i=0 ; i<2 ; i++ ) { if( duty_count[i] >= 3 ) break ; if( pwm_duty[i] >= duty_max[i] ) { duty_max[i] = pwm_duty[i] ; max_flg[i] = 1 ; } else if( max_flg[i] == 1 ) { duty_count[i]++ ; max_flg[i] = 0 ; } else { duty_max[i] = pwm_duty[i]+1 ; /* 2/16 */ } if( pwm_duty[i] <= duty_min[i] ) { duty_min[i] = pwm_duty[i] ; min_flg[i] = 1 ; } else if( min_flg[i] == 1 ) { duty_count[i]++ ; min_flg[i] = 0 ; } else { duty_min[i] = pwm_duty[i]-1 ; } } control[0] = 0 ; } last_mode = pwm_mode ; for( i=0 ; i<2 ; i++ ) /* make data for pwm */ { dir = 1 ; data[i] = (127*pwm_duty[i])/100 ; if( data[i] < 0 ) { dir = 0 ; data[i] *= -1 ; } data[i] = (data[i] << 1) + dir ; } outportb( A_PWM_DUTY_L , (int) data[0] ) ; /* * */ /* ! */ outportb( A_PWM_DUTY_R , (int) data[1] ) ; /* * */ /* ! */ } /* determine tire velocity */ int tire( unsigned char pwm_mode, int i ) /* i : left or right */ { float radi_dt[2] ; float loca_dt[2] ; float velo_t ; /* 't' means 'target' */ float curv_t ; /* '' */ float tire_t[2] ; /* '' */ unsigned char factor ; radi_dt[0] = RADI_DTL ; /* initialize */ radi_dt[1] = RADI_DTR ; loca_dt[0] = (-1) * LOCA_DTL ; loca_dt[1] = LOCA_DTR ; /* remake ; 2/7 */ factor = pwm_mode & 0xc8 ; switch( factor ) /* determine target velocity */ { case 0x00: case 0x40: velo_t = PWM_SLOW_STR ; break ; case 0x08: case 0x48: velo_t = PWM_FAST_STR ; break ; case 0x80: case 0xc0: velo_t = PWM_SLOW_CUR ; break ; case 0x88: case 0xc8: velo_t = PWM_FAST_CUR ; break ; } factor = pwm_mode & 0x0b ; switch( factor ) { case 0x02: case 0x03: velo_t = PWM_SLOW_ROT ; break ; case 0x0a: case 0x0b: velo_t = PWM_FAST_ROT ; break ; } factor = ( pwm_mode >> 4 ) & 0x01 ; switch( factor ) /* determine target radius */ { case 0 : curv_t = PWM_RADI_SHORT ; break ; case 1 : curv_t = PWM_RADI_LONG ; break ; } factor = ( pwm_mode >> 6 ) & 0x03 ; switch( factor ) /* determine target velocity of tires */ { case 0 : tire_t[i] = 0.0 ; break ; case 1 : tire_t[i] = DEGREEIZE * velo_t / radi_dt[i] ; break ; case 2 : tire_t[i] = DEGREEIZE * ( 1.0f + loca_dt[i] / curv_t ) * velo_t / radi_dt[i] ; break ; case 3 : tire_t[i] = DEGREEIZE * ( 1.0f - loca_dt[i] / curv_t ) * velo_t / radi_dt[i] ; break ; } factor = ( pwm_mode >> 5 ) & 0x01 ; switch( factor ) /* for back */ { case 0 : tire_t[i] *= -1.0f ; break ; } factor = pwm_mode & 0x03 ; switch( factor ) /* for rotation */ { case 2 : tire_t[0] *= -1.0f ; tire_t[1] *= 1.0f ; break ; case 3 : tire_t[0] *= 1.0f ; tire_t[1] *= -1.0f ; break ; } return ( (int)tire_t[i] ) ; } /* make feedback data ; 2/13,2/14,2/15 Big change */ /* 2/16 */ int feedback0( int *diff, unsigned char pwm_mode, int *t_dt, int *t_t ) { int tire_dt[2] ; /* 2/7 */ int tire_t[2] ; /* 2/7 */ int i ; /* 2/13 */ int feed_limit[2] ; /* 2/14 */ /* initialize */ tire_dt[0] = t_dt[0] ; tire_dt[1] = t_dt[1] ; tire_t[0] = t_t[0] ; tire_t[1] = t_t[1] ; diff[0] = 0 ; diff[1] = 0 ; /* determine feedback limit 2/14,2/15 */ feed_limit[0] = FEED_MAX ; feed_limit[1] = FEED_MAX ; if( (pwm_mode&0xc2) == 0x80 ) /* 2/14 */ feed_limit[0] /= 2 ; /* 2/14,2/15 */ if( (pwm_mode&0xc2) == 0xc0 ) /* 2/14 */ feed_limit[1] /= 2 ; /* 2/14,2/15 */ /* for feedback , 2/13,2/14 */ for( i=0 ; i<2 ; i++ ) { diff[i] = (tire_t[i] - tire_dt[i]) ; if( diff[i]>0 && diff[i]<=FOOD ) diff[i] = FOOD ; if( diff[i]<0 && diff[i]>=(-FOOD) ) diff[i] = (-FOOD) ; diff[i] /= FOOD ; if( diff[i] > feed_limit[i] ) diff[i] = feed_limit[i] ; if( diff[i] < (-feed_limit[i]) ) diff[i] = (-feed_limit[i]) ; } return 0 ; } /* make feedback data */ /* 2/16 */ int feedback1( int *diff, unsigned char pwm_mode, int *t_dt, int *t_t ) { int tire_dt[2] ; /* 2/7 */ int tire_t[2] ; /* 2/7 */ int left_curv ; int right_curv ; int factor ; int motion ; /* initialize */ tire_dt[0] = t_dt[0] ; tire_dt[1] = t_dt[1] ; tire_t[0] = t_t[0] ; tire_t[1] = t_t[1] ; diff[0] = 0 ; diff[1] = 0 ; motion = 0 ; /* front */ /* for rotation mode */ factor = pwm_mode & 0x03 ; switch( factor ) { /* 2/5,2/16 remake */ /* left rotation */ case 2: /* tire_dt[0] *= -1 ; */ /* tire_t[0] *= -1 ; */ /* motion = 2 ; */ /* break ; */ return 0 ; /* right rotation */ case 3: /* tire_dt[1] *= -1 ; */ /* tire_t[1] *= -1 ; */ /* motion = 3 ; */ /* break ; */ return 0 ; } /* for rear mode */ factor = ( pwm_mode >> 5 ) & 0x01 ; if( factor == 0 ) { tire_dt[0] *= -1 ; tire_dt[1] *= -1 ; tire_t[0] *= -1 ; tire_t[1] *= -1 ; motion = 1 ; } /* when MIRS moves too left , left_curv > 0 */ left_curv = tire_dt[1]*tire_t[0]-tire_dt[0]*tire_t[1] ; /* when MIRS moves too right , right_curv > 0 */ right_curv = -left_curv ; factor = ( pwm_mode >> 6 ) & 0x03 ; switch( factor ) { /* stop mode */ case 0: break ; /* straight mode */ case 1: if( tire_dt[0] > tire_dt[1] ) { diff[0] = -1 ; diff[1] = 1 ; } if( tire_dt[0] < tire_dt[1] ) { diff[0] = 1 ; diff[1] = -1 ; } break ; /* left mode */ case 2: if( tire_dt[0] <= 0 ) { diff[0] = 1 ; } if( tire_dt[1] <= 0 ) { diff[1] = 1 ; } if( tire_dt[0] > 0 && tire_dt[1] > 0 ) { if( left_curv > 0 ) { diff[0] = 1 ; diff[1] = -1 ; } if( left_curv < 0 ) { diff[0] = -1 ; diff[1] = 1 ; } } break ; /* right mode */ case 3: if( tire_dt[0] <= 0 ) { diff[0] = 1 ; } if( tire_dt[1] <= 0 ) { diff[1] = 1 ; } if( tire_dt[0] > 0 && tire_dt[1] > 0 ) { if( right_curv > 0 ) { diff[0] = -1 ; diff[1] = 1 ; } if( right_curv < 0 ) { diff[0] = 1 ; diff[1] = -1 ; } } break ; } switch( motion ) { /* rear */ case 1: diff[0] *= -1 ; diff[1] *= -1 ; break ; /* 2/5,2/16 remake */ /* left rotation */ case 2: /* diff[0] *= -1 ; */ break ; /* right rotation */ case 3: /* diff[1] *= -1 ; */ break ; } /* diff[0] *= FOOD ; */ /* diff[1] *= FOOD ; */ return 0 ; }