BASIC4MCU | 질문게시판 | 답변 : ATmegq128 PI 제어기 추가
페이지 정보
작성자 master 작성일2024-10-08 21:05 조회195회 댓글1건본문
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
//
#define Kp 1.0
#define Ki 0.5
//
volatile sec_flag=0,char buf[100];
volatile int num=0,target_w=11; // 목표 각속도 11 rad/s
volatile unsigned int w=0;
volatile float We=0,We_int=0,u=0,temp=0;
//
void U0_txd(char d){ while(!(UCSR0A&(1<<UDRE0))); UDR0=d; }
void U0_str(char* s){ while(*s)U0_txd(*s++); }
//
ISR(INT0_vect){ num++; } // 펄스 수 증가
//
ISR(TIMER3_COMPA_vect){ sec_flag=1; }
//
int main(void){
int i;
PORTA=0x01; DDRA=0xFF; DDRB=0xFF; DDRC=0xFF;
TCCR1A=0x81; TCCR1B=0x03; // 고속 PWM
TCCR3B=0x0D; OCR3A=15624; ETIMSK=0x10; // 1sec
UCSR0A=0x02; UCSR0B=0x18; UBRR0L=16; // 115200bps
EICRA=0x03; EIMSK=0x01; // INT0
sei();
while(1){
if(sec_flag){ sec_flag=0;
w=(float)num*7.48; num=0; // 각속도 계산(7.48은 펄스 수를 rad/s로 변환하기 위한 상수)
We=target_w-w;
We_int=temp+We; u=Kp*We+Ki*We_int; temp=We_int;
if(u>255)u=255; if(u<0)u=0; i=u; OCR1A=i;
sprintf(buf,sizeof(buf),"angular_velocity:%5u rad/s,PWM Output:%3d\r\n",w,i); U0_str(buf);
}
}
return 0;
}
펄스 주기가 얼마나 되나요?
80 rad/s 나온다고 했으니 80 / 7.48 = 10.6951871657754
num은 10.7개(10 or 11) 군요?
주기가 93,5ms로 길기 때문에 1초동안의 개 수 보다는 1개의 주기를 측정하는 것이 좋겠습니다.
목표치인 11 rad/s 이 된다면 11 / 7.48 = 1.470588235294118로 680ms가 되어서 초당 1~2개 밖에 측정하지 못하므로 더욱 문제입니다.
엔코더 회전당 펄스 수도 많이 부족한 것 같습니다.
엔코더 부착 모터를 사용하지 않은 상태인가요?
댓글 1
조회수 195master님의 댓글
master 작성일
엔코더 주기를 적어보세요
모터 rpm과 기어비(있는 경우) 및 엔코더 펄스 수에 따라서 엔코더 펄스 주기가 정해집니다.
물론 최저~최대 범위를 적어야겠죠
//
주기에 따라서
1개 펄스의 주기로 속도를 계산하는 것이 좋은지
단위시간동안 들어온 펄스 개수로 속도를 계산하는 것이 좋은지가 결정됩니다.