Application of Interrupt and Timer : Measurement of Motor Speed
incoming Lab. Rotary Encoder A ( rotary) encoder is an electro-mechanical device that converts the angular position of a shaft or axle to digital code or digital pulse absolute/ incremental
incoming Lab. DC motor
incoming Lab. Encoder Incremental Encoder 13 pulses/round/channel 1 pulse = 360/13 도 (motor), 360/50/13 도 (wheel) Motor Speed rpm (round per minute) –rad/sec = rpm*2pi/60 102 rpm (wheel) = 5100 rpm (motor) direction A/B channel 의 위상을 비교 A Ch. B Ch. A Ch. B Ch.
incoming Lab. DC Motor RB-35GM 제어전압 : DC 12V 감속비 [Reduction ration] : 1/50 정격토크 [Rated torque](Kg-cm): 2.0 정격회전수 [Rated speed](rpm):102 Rated torque 60 g-cm, 5100 rpm, current 470 mA 이하, 3.14 W No load speed 6200 rpm, No load current 120 mA 이하
incoming Lab. Measurement of motor speed (I) pulse 간의 시간 측정 Example)
incoming Lab. Measurement of motor speed (I) pulse 간의 시간 측정 예 ) f clk = 1 Mhz, N(prescale) = 100 f timer = f clk /N=10kHz, T timer = 100uSec timer_diff = 100 => 10 mSec timer_diff
incoming Lab. Measurement of motor speed (I) External Interrupt INT 5 : Left motor A channel (PE5) INT 7 : Right motor A channel (PE7) external interrupt 간 timer 비교 EICRB = 0x88; EIMSK = 0xA0; A Ch. tcnt1tcnt2 timer_diff = tcnt2 – tcnt1
incoming Lab. 바퀴구동체 도면
incoming Lab. External interrupt Setting EIMSK : external Interrupt MaSK register EICRB
incoming Lab. Measurement of motor speed (I) timer for external interrupt TCNT0 : 8 bit timer/counter TCNT1 : Motor Speed Control TCNT2, TCNT3 : same prescaler with TCNT1 normal mode no timer interrupt f clk = Hz & prescale : 256 f timer = /256 = T timer = 1/28800 = uSec 예상 ) 102 rpm => uSec => 26 (= timer_diff ) TCCR0 = 0x06;
incoming Lab. Measurement of motor speed (I) TCCRn : Timer/Counter Control Register 1 1 0
incoming Lab. Interrupt Service Routine (INT5, Left Motor) ISP(INT5_vect) { static unsigned char timer_cur = 0, timer_prev = 0; timer_cur = TCNT0; Left_timer_diff = timer_cur – timer_prev; timer_prev; = timer_cur; if ( (PINE & 0x10) == 0 ) Dir_L = 0; // forward else Dir_L = 1; // backward }
incoming Lab. Speed Measurement Program (I) #include void txd_char(unsigned char data){ while( (UCSR0A & 0x20) == 0 ); UDR0 = data; } unsigned char Left_timer_diff, Right_timer_diff; unsigned char Dir_L, Dir_R; int main(){ unsigned char i, time_diff; unsigned char text[] = "\r Left : ";
incoming Lab. Speed Measurement Program (I) DDRB = 0xCF; DDRD = 0x18; DDRE = 0x01; PORTB = 0x01; /* 원하는 방향을 기입 */ EICRB = 0x08; // EICRB = 0x88; EIMSK = 0x20; // EIMSK = 0xA0; TCCR1A = 0x2B; TCCR1B = 0x0A; TCCR1C = 0x00; OCR1B = 0x00; /* 원하는 속도를 기입 0x000 ~ 0x3FF */ // OCR1C = 0x00; /* 원하는 속도를 기입 0x000 ~ 0x3FF */ TCCR0 = 0x06; EIMSK = 0x20; /* Left interrupt 만 enable */ sei();
incoming Lab. Speed Measurement Program (I) while(1){ i=0; while(text[i] != '\0') txd_char(text[i++]); if( Dir_L == 1 ) txd_char('+'); // 부호 출력 else txd_char('-'); time_diff = Left_timer_diff; // 임시 저장 txd_char(time_diff/100 + '0'); // 백의 자리 출력 txd_char((time_diff/10)%10 + '0'); // 십의 자리 출력 txd_char(time_diff%10 + '0'); // 일의 자리 출력 txd_char('\r'); return 0; }
incoming Lab. 연습 Right Motor 에 대해 속도 측정 code 완성 Left/Right motor 에 대해 다양한 속도에 대한 속도측정 RPM 단위로 출력 (UART)
incoming Lab. Measurement of motor speed (I)
incoming Lab. Interrupt Service Routine (INT5, Left Motor) ISR(INT5_vect) { static timer_cur = 0, timer_prev = 0; timer_cur = TCNT0; if (timer_cur >= timer_prev) Left_timer_diff = timer_cur – timer_prev; else Left_timer_diff = 255- timer_prev+timer_cur+1; timer_prev; = timer_cur; if ( (PINE & 0x20) == 0 ) Dir_L = 0; // forward else Dir_L = 1; // backward }
incoming Lab. Interrupt Service Routine (INT5, Left Motor) ISR(INT5_vect) { Left_timer_diff = TCNT0; TCNT0 = 0; if ( (PINE & 0x20) == 0 ) Dir_L = 0; // forward else Dir_L = 1; // backward }
incoming Lab. Measurement of motor speed (II) 일정한 시간 간격 동안 pulse 의 개수 측정 Example)
incoming Lab. Measurement of motor speed (II) clear time on compare match (CTC) mode (output compare interrupt) TCNT0 : 8 bit timer/counter f clk = Hz & prescale : 1024 f timer = /1024 = 7200 T timer = 1/7200 OCR0 = 144 => 144*T timer = 1/50 = 20 mSec 마다 interrupt 발 생 예상 ) 102 rpm => uSec => 22 개 pulse TCCR0 = 0x0F; TIMSK = 0x02;
incoming Lab. Measurement of motor speed (II) TCCRn : Timer/Counter Control Register TIMSK : Timer/Counter Interrupt Mask Register 1 1
incoming Lab. Interrupt Service Routine (INT5, Left Motor) ISP(INT5_vect) { Pulse_L++; if ( (PINE & 0x20) == 0 ) Dir_L = 0; // forward else Dir_L = 1; // backward }
incoming Lab. Interrupt Service Routine (Timer0) ISR(TIMER0_COMP_vect) { static unsigned char no_timer = 0; no_timer++; if ( no_timer >= 10 ) { // 20*10 = 200 mSec no_timer = 0; No_Pulse_L = Pulse_L; No_Pulse_R = Pulse_R; Pulse_L = Pulse_R = 0; }
incoming Lab. Interrupt Service Routine (Timer0) – 20mSec ISR(TIMER0_COMP_vect) { No_Pulse_L = Pulse_L; No_Pulse_R = Pulse_R; Pulse_L = Pulse_R = 0; }
incoming Lab. Speed Measurement Program (II) #include void txd_char(unsigned char data){ while( (UCSR0A & 0x20) == 0 ); UDR0 = data; } unsigned char Pulse_L, Pulse_R, No_Pulse_L, No_Pulse_R; unsigned char Dir_L, Dir_R; int main(){ unsigned char cmd, i=0, no_pulse_l; unsigned char text[] = "\r Left : ";
incoming Lab. Speed Measurement Program (II) /* UART0 초기화 추가 */ DDRB = 0xCF; DDRD = 0x18; DDRE = 0x01; PORTB = 0x01; /* 원하는 방향을 기입 */ EICRB = 0x08; // EICRB = 0x88; EIMSK = 0x20; // EIMSK = 0xA0; TCCR1A = 0x2B; TCCR1B = 0x0A; TCCR1C = 0x00; OCR1B = 0x00; /* 원하는 속도를 기입 0x000 ~ 0x3FF */ // OCR1C = 0x00; /* 원하는 속도를 기입 0x000 ~ 0x3FF */ OCR0 = 144; TCCR0 = 0x0F; /* CTC mode prescale = 1024 */ TIMSK = 0x02; /* Timer Interrupt */ sei();
incoming Lab. Speed Measurement Program (II) while(1){ i=0; while(text[i] != '\0') txd_char(text[i++]); if( Dir_L == 1 ) txd_char('+'); // 부호 출력 else txd_char('-'); no_pulse_l = No_Pulse_L; // 임시 저장 txd_char(no_pulse_l /100 + '0'); // 백의 자리 출력 txd_char((no_pulse_l /10)%10 + '0'); // 십의 자리 출력 txd_char(no_pulse_l %10 + '0'); // 일의 자리 출력 txd_char('\r'); return 0; }
incoming Lab. 연습 Right Motor 에 대해 속도 측정 code 완성 Left/Right motor 에 대해 다양한 속도에 대한 속도측정 RPM 단위로 출력 (UART)