BASIC4MCU | 질문게시판 | 코드비젼, mega128을 이용한 타이머 인터럽트 사용한 모터의 키제어
페이지 정보
작성자 방구석MCU 작성일2020-11-06 18:01 조회3,445회 댓글1건본문
처음 질문올립니다.
코드 비젼을 이용해서 모터 제어를 하고 있습니다.
전체 코드는 아래에 나와있습니다. 이게 bldc 홀센서 모터를 제어하고 있었습니다.
시계 방향, 반시계 방향 상은 모두 다 맞추었고 메인루틴안에 while(1) 안에 넣게 되었을 때 부드럽게 돌아가는 것을 확인하였습니다.
다음에 타이머 인터럽트를 이용해서 키제어 루틴을 읽어와서 모터를 제어하는 것인데
여기서 오랫동안 막혀있었습니다. 타이머0 오버플로우 인터럽트를 이용해서 20ms마다 키제어를 읽어오도록 코드를 짰는데
이걸 제 나름대로 적용시켜서 코드를 짜봤는데, 모터 회전이 버벅거리는 현상이 나타나게 되었습니다.(방향은 제대로 되어있는데, 이전보다 훨씬더 버벅거리면서 돌아갑니다.)
긴글 읽어주셔서 감사합니다. 혹시 어떤 부분이 문제인지 확인해주 실 수 있으신가요?
#include <io.h>
#include <mega128.h>
#include <stdio.h>
#include <delay.h>
#include "mydef_ver3.h"
#include "lcd.h"
// Declare your global variables here
u08 sec;
u08 time_count;
bit time_flag;
u16 tmp_buf[10];
u08 tmp_index;
u08 lcd_mode;
u08 temp;
u08 pwm;
bit over;
u08 str_motor[] = "MOTOR CO";
u08 str_name[] = "NTROLLER";
u08 str_start[] = "TART]";
u08 str_welcome[] = "WELCOME:";
u08 str_title1[] = "DESIGNED";
u08 str_title2[] = " BY KYT";
u08 str_keyread[] = "Key-scan";
u08 str_press[] = "PRESS [S";
u08 str_ad[] = "AD-VALUE";
u08 str_second[] = "SECOND: ";
u08 str_pwm[] = "PWM ";
u08 str_duty[] = "DUTY";
u08 str_blank[] = " ";
u08 str_cw[] = "CW";
u08 str_ccw[] = "CCW";
unsigned char direction='x';
volatile unsigned char Hall;
volatile unsigned int count;
volatile unsigned int i;
void update_lcd(void);
void pwm1_control(u08 a);
void step(u08 y);
void keypress();
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //20ms 마다 타이머 오버플로우 인터럽트 발생
{
if(count == 1)
{
keypress();
count = 0;
}
else count = count + 1;
TCNT0=40;
}
void keypress(void)
{
u08 old_key = 0;
u08 new_key;
new_key = KEY_IN & KEY_MASK;
if(new_key!=old_key){
switch(new_key){
case START:
lcd_home();
lcd_clear();
lcd_control_write(0x80);
lcd_print_data(str_pwm,4);
lcd_control_write(0xC0);
lcd_print_data(str_duty,4);
if(pwm == 0 || direction == 'x')
{
if(temp == 0)
{
temp = 20;
}
direction = '+';
pwm = temp;
}
else if(direction == '+' || direction == '-')
{
for(;pwm=0;)
{
pwm = pwm - 20;
delay_ms(500);
}
PORTD = 0x00;
direction = 'x';
}
break;
case CW:
if(direction == '+')
{
for(; pwm==0; pwm = pwm - 20)
{
delay_ms(500);
}
direction = '-' ;
for(; pwm == temp; pwm = pwm + 20)
{
delay_ms(500);
}
}
else if(direction == '-')
{
for(; pwm == 0; pwm = pwm - 20)
{
delay_ms(500);
}
direction = '+' ;
for(; pwm == temp; pwm = pwm + 20)
{
delay_ms(500);
}
}
break;
case UP:
if(pwm >= 240) pwm = 240;
else
pwm = pwm + 20;
break;
case DOWN:
if(pwm <= 20) pwm =20;
else
pwm = pwm -20;
break;
}
temp = pwm;
step(temp) ;
delay_ms(200);
pwm1_control(temp);
lcd_control_write(0xC7);
lcd_print_data("%",1);
}
old_key = new_key;
}
void step(u08 y)
{
// #asm("cli")
OCR1AL = y;
OCR1BL = y;
OCR1CL = y;
Hall = PIND & 0x38;
if(direction == '+')
{if(Hall == 0x10) //CW
{
OCR1AL;
PORTD = 0b00000100;
} // CW 0~60
else if(Hall == 0x30)
{
OCR1BL;
PORTD = 0b00000100;
}
// CW 60~120
else if(Hall == 0x20)
{
OCR1BL;
PORTD = 0b00000001;
}
// 120~180
else if(Hall == 0x28)
{
OCR1CL;
PORTD = 0b00000001;
}
//180~240
else if(Hall == 0x08)
{OCR1CL;
PORTD = 0b00000010;}
//240~300
else if(Hall == 0x18)
{
OCR1AL;
PORTD = 0b00000010;
}
//300~360
}
else if(direction == '-')
{if(Hall == 0x20) //CCW
{
OCR1AL;
PORTD = 0b00000010;
}
// CCW 0~60
else if(Hall == 0x30)
{
OCR1CL;
PORTD = 0b00000010;
}
// CCW 60~120
else if(Hall == 0x10)
{
OCR1CL;
PORTD = 0b00000001;
}
// CCW 120~180
else if(Hall == 0x18)
{
OCR1BL;
PORTD = 0b00000001;
}
// CCW 180~240
else if(Hall == 0x08)
{
OCR1BL;
PORTD = 0b00000100;
}
// CCW 240~300
else if(Hall == 0x28)
{
OCR1AL;
PORTD = 0b00000100;
}
// CCW 300~360
}
}
void beep(void)
{
BUZ_RLY = BUZ_RLY | BUZZER_ON;
delay_ms(100);
BUZ_RLY = BUZ_RLY & BUZZER_OFF;
}
void pwm1_control(u08 x)
{
u08 l,m,n,o,p;
s16 duty_ratio;
l = 0x30+ (x/100);
m = 0x30+ (x%100)/10;
n = 0x30+ (x%10);
lcd_control_write(0x84);
lcd_data_write(l);
lcd_data_write(m);
lcd_data_write(n);
duty_ratio = x*0.39; //100/255
o = 0x30+ duty_ratio/10;
p = 0x30+ duty_ratio%10;
lcd_control_write(0xC5);
lcd_data_write(o);
lcd_data_write(p);
}
#define ADC_VREF_TYPE 0x20 //AD0 INPUT
void main(void)
{
// Declare your local variables here
u08 i;
u08 a,b,c;
u08 old_key,new_key;
DDRA = 0x00;
PORTA = 0x00; //LCD DATA PORT
DDRB = 0xf0; //INPUT & OUTPUT MODE
PORTB = 0xEf;
delay_ms(3); // 상단 커패시터 충전
PORTB = 0x0f;
DDRC = 0xf0;
PORTC =0x0F; //BCD KEY INPUT AND LCD CONTROL PORT
DDRD= 0x07;
PORTD=0x00; //Hole sensor & Low input
DDRE = 0x00;
PORTE =0x00 | (0x03 << 6);
DDRF = 0x00;
PORTF =0x00; //CURRENT SENSING
DDRG = 0xFF;
PORTG = 0x00; //BUZZER AND RELAY CONTROL PORT
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
ASSR=0<<AS0;
TCCR0=7;
TCNT0=40; //11.0592M/1024/216 = 50Hz (20ms)
TIMSK=1;
OCR0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 43.200 kHz
// Mode: Ph. correct PWM top=0x00FF
// OC1A output: Non-Inverted PWM
// OC1B output: Non-Inverted PWM
// OC1C output: Non-Inverted PWM
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 11.806 ms
// Output Pulse(s):
// OC1A Period: 11.806 ms Width: 0.97222 ms
// OC1B Period: 11.806 ms Width: 0.97222 ms
// OC1C Period: 11.806 ms Width: 0.97222 ms
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Compare C Match Interrupt: Off
TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (1<<COM1C1) | (0<<COM1C0) | (0<<WGM11) | (1<<WGM10); //Phase correct mode
TCCR1B=0x04;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x15; // PWM 1
OCR1BH=0x00;
OCR1BL=0x15; // PWM 2
OCR1CH=0x00;
OCR1CL=0x15; // PWM 3
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
TCCR2=(0<<WGM20) | (0<<COM21) | (0<<COM20) | (0<<WGM21) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;
// Timer/Counter 3 initialization
// Clock source: System Clock
// Clock value: Timer3 Stopped
// Mode: Normal top=0xFFFF
// OC3A output: Disconnected
// OC3B output: Disconnected
// OC3C output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer3 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Compare C Match Interrupt: Off
TCCR3A=(0<<COM3A1) | (0<<COM3A0) | (0<<COM3B1) | (0<<COM3B0) | (0<<COM3C1) | (0<<COM3C0) | (0<<WGM31) | (0<<WGM30);
TCCR3B=0x00;
TCNT3H=0x00;
TCNT3L=0x00;
ICR3H=0x00;
ICR3L=0x00;
OCR3AH=0x00;
OCR3AL=0x00;
OCR3BH=0x00;
OCR3BL=0x00;
OCR3CH=0x00;
OCR3CL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
// INT3: Off
// INT4: Off
// INT5: Off
// INT6: Off
// INT7: Off
EICRA=(0<<ISC31) | (0<<ISC30) | (0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EICRB=(0<<ISC71) | (0<<ISC70) | (0<<ISC61) | (0<<ISC60) | (0<<ISC51) | (0<<ISC50) | (0<<ISC41) | (0<<ISC40);
EIMSK=(0<<INT7) | (0<<INT6) | (0<<INT5) | (0<<INT4) | (0<<INT3) | (0<<INT2) | (0<<INT1) | (0<<INT0);
// USART0 initialization
// USART0 disabled
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
// USART1 initialization
// USART1 disabled
UCSR1B=(0<<RXCIE1) | (0<<TXCIE1) | (0<<UDRIE1) | (0<<RXEN1) | (0<<TXEN1) | (0<<UCSZ12) | (0<<RXB81) | (0<<TXB81);
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
SFIOR=(0<<ACME);
// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x87;
lcd_mode = 1;
lcd_init();
lcd_clear();
lcd_home();
lcd_control_write(0x80);
lcd_print_data(str_motor,8);
lcd_control_write(0xC0);
lcd_print_data(str_name,8);
delay_ms(3000);
lcd_home();
lcd_clear();
lcd_control_write(0x80);
lcd_print_data(str_title1,8);
lcd_control_write(0xC0);
lcd_print_data(str_title2,7);
delay_ms(3000);
lcd_home();
lcd_clear();
lcd_control_write(0x80);
lcd_print_data(str_press,8);
lcd_control_write(0xC0);
lcd_print_data(str_start,5);
/*lcd_home();
lcd_clear();
lcd_control_write(0x80);
lcd_print_data(str_pwm,4);
lcd_control_write(0xC0);
lcd_print_data(str_duty,4); */
//*********************** SECTION m8 *******************
#asm("sei")
//*********************** SECTION m9 ********************
BUZ_RLY = 0x00;
old_key = 0;
//*********************** SECTION m10 ********************
while (1)
{
keypress();
}
}
댓글 1
조회수 3,445master님의 댓글
master 작성일
인터럽트 함수 안에서는 가능한 빨리 처리를 마치고 빠져나와야 합니다...만
keypress();
시간이 많이 걸리는 함수를 사용하고 있어서 체류 시간이 제법 깁니다.
LCD도 키지말고, 딜레이도 사용하지 않도록 만들어보세요