BASIC4MCU | 질문게시판 | 코드비젼, mega128을 이용한 타이머 인터럽트 사용한 모터의 키제어(2)
페이지 정보
작성자 방구석MCU 작성일2020-11-11 00:16 조회14,529회 댓글1건본문
안녕하세요 마스터님
마스터님이 말씀해주신 대로 keypress() 루틴에서
딜레이나 lcd루틴을 빼고, 주석처리를 하니 버튼을 누를 때, 모터가 부드럽게 회전하였습니다.
감사합니다. 근데 한 가지 또 문제가 있는데,
아래 코드를 보시면 모터 스피드를 UP, DOWN시키는 키를 한번 누를 때마다 스피드가 일정하게 증가하는(+20)
것이 아니라 갑자기 PWM = 240 풀스피드로 증가하거나 풀스피드에서 최저 속도로 내려오는 등 버튼이 한번 누를 때
여러번 눌린것으로 ATMEGA128이 판단하는 거 같습니다.
혹시 무엇이 문제인지 알려주실 수 있으신가요?
#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 lcdcontrol(void);
void pwm1_control(u08 a);
void step(void);
void keypress();
void beep(void);
void pwm_upcontrol(void)
{
if(pwm >= 240)
pwm = 240;
else
{
pwm = pwm + 20;
}
OCR1AL = pwm;
OCR1BL = pwm;
OCR1CL = pwm;
}
void pwm_downcontrol(void)
{
if(pwm <= 20)
pwm = 20;
else
{
pwm = pwm -20;
}
OCR1AL = pwm;
OCR1BL = pwm;
OCR1CL = pwm;
}
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(50);
}
PORTD = 0x00;
direction = 'x';
}
break;
case CW:
if(direction == '+')
{
for(; pwm==0; pwm = pwm - 20)
{
delay_ms(50);
}
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:
pwm_upcontrol();
break;
case DOWN:
pwm_downcontrol();
break;
}
step();
/*pwm1_control(temp);
lcd_control_write(0xC7);
lcd_print_data("%",1);*/
}
old_key = new_key;
}
void step(void)
{
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
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0x28;
// Place your code here
if(count == 1)
{
keypress();
count = 0;
i = i + 1;
} else count = count + 1;
}
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: 10.800 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 20 ms
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x28;
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);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10);
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(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
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
조회수 14,529master님의 댓글
master 작성일
코드가 길어서 상세하게 봐드릴 시간은 없고요
추측컨데
예를들면 0.3초 동안 키를 누른다면
10ms마다 키를 체크하는 경우 30번 키 체크가 됩니다.
금새 최고점까지 올라가게 되겠죠
이를 해결하기 위한 방법으로는
엣지검출해서 오래 누르고 있어도 1회만 키가 누른 것으로 체크 하든지
키를 누르면 처리를 한 후 변수를 set 시키고, 변수가 set 되어 있으면 키를 누르지 않을 때까지 아무런 처리를 하지 않다가, 키를 누르지 않으면 변수를 clear 시켜서 다시 키를 입력 받을 수 있는 상태로 두는 방법도 있습니다.