BASIC4MCU | 질문게시판 | 답변 : 스위치로 PI 모터 제어
페이지 정보
작성자 master 작성일2024-11-12 05:53 조회196회 댓글0건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=23917
본문
DDRB=0xFF; // 포트 B를 출력으로 설정(PWM 신호 출력)
DDRB=0x10; TCCR0=0b01101010; // PB4를 출력으로 설정(OC0) // Fast PWM 모드,8분주,Clear OC0 on compare match
DDRB=0x02; TCCR2=0b01101010; // PB7를 출력으로 설정(OC2)// Fast PWM 모드,8분주,Clear OC2 on compare match
첫번째 라인에서 모든 비트를 출력으로 설정했으니 2번째,3번째 라인이 필요치 않으나
DDRB=0x90;
PB4,PB7만 출력으로 하고 싶다면 이렇게 설정하면 되겠습니다.
각각 따로 설정하려면
DDRB=0x10; TCCR0=0b01101010; // PB4를 출력으로 설정(OC0) // Fast PWM 모드,8분주,Clear OC0 on compare match
DDRB|=0x80; TCCR2=0b01101010; // PB7를 출력으로 설정(OC2)// Fast PWM 모드,8분주,Clear OC2 on compare match
2번째부터는 |= 연산자를 사용해야 하며
비트7은 0x80 입니다.
//DDRD=0x00; // 포트 D를 입력으로 설정(인터럽트 입력,encoder 신호)리셋디폴트가 입력이므로 이 설정은 해도 되고 안해도 됩니다.//Timer2_init() 함수를 호출하는 곳이 없습니다.
OCR2 출력은 불가능하겠습니다.
//
PORTE=0x00; // PE0 핀을 풀다운 저항으로 설정 (기본값 LOW)
AVR은 풀다운 저항 설정이 없습니다.풀업저항만 가능하죠풀다운 저항이 필요하다면 외부에 풀다운 저항을 연결하세요//무한루프의 실행시간은 굉장히 짧습니다.(수 us 정도)스위치를 누르고 있는 시간은 이에비해서 상당히 느리므로(짧게 눌러도 수백ms)여러번 스위치를 체크하게 되고, start=1; start=0; 이 반복해서 실행되며, 마지막에 어느 것이 실행 될런지 모르는 상태가 됩니다.//ISR(TIMER1_OVF_vect){ // 100ms_delay_ms(1000);}100ms 주기의 인터럽트에서 1000ms 딜레이를 사용하게 되면 메인함수는 실행되지 못하게 되고인터럽트 주기는 1000ms가 됩니다.인터럽트 함수 안에서 딜레이는 사용하지 않는 것이 좋습니다.시간이 많이 걸리는 함수는 메인에서 처리합니다.//ISR(INT0_vect){ num1++; num2++; } // 엔코더한개의 엔코더로 모터2개를 각각 PID 제어를 하나요?엔코더가 1개면 어떻게 속도지정을 각각 할 수 있죠?다른 부분들은 코드를 도와드릴 수 있는데 이 부분은 해결하셔야겠습니다.//#include <avr/io.h>#include <avr/interrupt.h>//#define F_CPU 16000000UL // CPU 주파수 16MHz#include <util/delay.h>#include <stdio.h>//volatile char sw_flag=0,tx_flag=0,start=0;volatile char buffer[200];volatile int reference1=100,reference2=100; // 목표 각속도volatile int current_speed1=0,current_speed2=0; // 현재 각속도volatile unsigned int num1=0,num2=0; // 엔코더 관련 변수volatile double error1=0,error2=0;volatile double integral1=0,integral2=0;volatile double control1=0,control2=0;volatile double Kp=0.01,Ki=0.01;//void u0_txd(char d){ while(!(UCSR0A&0x20)); UDR0=d; }void u0_Str(char*s){ while(*s)u0_txd(*s++); }//void PI_control1(){error1=reference1-current_speed1; integral1+=error1; control1=Kp*error1+Ki*integral1;if(control1>255)control1=255; if(control1<0)control1=0;OCR0=(int)control1;}//void PI_control2(){error2=reference2-current_speed2; integral2+=error2; control2=Kp*error2+Ki*integral2;if(control2>255)control2=255; if(control2<0)control2=0;OCR2=(int)control2;}//ISR(INT0_vect){ num1++; num2++; } // 엔코더//ISR(TIMER1_OVF_vect){ // 100mscurrent_speed1=(num1*10.0); // 각속도(1초 단위로 환산)current_speed2=(num2*10.0); // 모터 2 속도num1=0; num2=0;TCNT1=40536;if(start){ PI_control1(); PI_control2(); tx_flag=1; }}//int main(void){PORTA=0xFF; DDRA=0xFF; // 출력으로 설정//DDRD=0x00; // 포트 D를 입력으로 설정(인터럽트 입력,encoder 신호)//DDRB=0x90; TCCR0=0b01101010; TCCR2=0b01101010; // PB4를 출력으로 설정(OC0) // PB7를 출력으로 설정(OC2)// Fast PWM 모드,8분주TCCR1B=0x03; TCNT1=40536; TIMSK=0X04; // 64분주 // Timer1 overflow interrupt // 16MHz에서 100ms 주기EICRA=0x03; EIMSK=0x01; // INT0 rising edge // INT0 활성화UBRR0L=103; UCSR0B=0x18; // 9600 baud rate 설정 // 송신 가능,수신 가능 설정sei();while(1){if(PINE&1){ // 스위치가 켜져 있으면if(sw_flag==0){ sw_flag=1; start=1; _delay_ms(50); }}else{ // 스위치가 꺼져 있으면if(sw_flag){ sw_flag=0; start=0; OCR0=0; OCR2=0; _delay_ms(50); }}//if(tx_flag){ tx_flag=0;sprintf(buffer,"speed1: %3d,speed2: %3d\r\n",current_speed1,current_speed2); u0_Str(buffer);}}}
댓글 0
조회수 196등록된 댓글이 없습니다.