Did you know that you can navigate the posts by swiping left and right?

AVR을 이용한 PID제어

14 Sep 2018 . category: tech . Comments
#mechatronics #atmega128 #DCmotor #motordrive

첫번째 목표는 DC모터를 제어하는 것이다. PID제어를 통해 내가 목표로 설정한 곳에 최대한의 속도로 부드럽게 다가가는 것을 목표과제로 수행한다.

이를 이용해 이용한 MCU는 AVR이다. 가장 많이 쓴 것이기도 하고 개인적으로 이것밖에 다룰줄 모르기때문에.. 안성진에게 dsp를 써보라는 권유를 받긴 했지만 그건 이후에 생각해보려한다.(틈틈이 찾아보면서 dsp에대해 어느정도 알게되면.)

우선은 제일 중요한 것은 내가 가지고 있는 2A L298 모터드라이버 모듈[SZH-EK001]을 이용하는게 주된 과제였다. 여러 사이트를 돌아다니면서 살펴본 결과

이 모듈의 구조는 다음과 같다. 이를 바탕으로 A enable 구간에는 OC0 PWM을 넣어 주었고 순차적으로 IN1과 IN2에 PB6(OC1B), PB6(OC1C)와 연결해주었다. 이후에 B enable에는 OC3A PWM을 넣어 주었고 순차적으로 IN3,IN4에 PE4(OC3B), PE5(OC3C)와 연에해주었다.

이렇게 모터드라이버 하나를 통해서 두개의 DC 모터를 조절할 계획이고 우선 테스트로 실험을 해보았는데 코드로는

#include <mega128.h>
#include <stdio.h>
#include <delay.h>

#asm
 .equ __lcd_port=0x12;PORTD
#endasm

#include <lcd.h>

char flag = 0, flag2 = 0;

void main(void)
{
    DDRB = 0xFF; // 포트 B 출력 설정
    DDRD = 0xFF; // 포트 D 출력 설정
    PORTB.7 = 1;
    PORTB.6 = 0;
    TCCR0 = 0b01100110;
    
    EIMSK = 0b00010001; //int4, int0 인에이블
    EICRA = 0b00000010; //intn의 하강에지에서 비동기적으로 인터럽트 요구
    EICRB = 0b00000010; //intn의 하강에지에서 인터럽트 요구
    SREG = 0x80;
    
    lcd_init(16);
    lcd_putsf("000%");
    
    while(1);
}

interrupt[EXT_INT0] void external_int0(void)
{
    flag = ++flag%5;
    if(flag==0)
    {
        OCR0 = 0x00;
        lcd_clear();
        lcd_putsf("000%");
    }
    else if(flag==1)
    {
        OCR0 = 0x3F;
        lcd_clear();
        lcd_putsf("025%");
    }
    else if(flag==2)
    {
        OCR0 = 0x7F;
        lcd_clear();
        lcd_putsf("050%");
    }
    else if(flag==3)
    {
        OCR0 = 0xBF;
        lcd_clear();
        lcd_putsf("075%");
    } 
    else if(flag==4)
    {
        OCR0 = 0xFF;
        lcd_clear();
        lcd_putsf("100%");
    }
    delay_ms(5);
}
interrupt[EXT_INT4] void external_int4(void)
{
    flag = ++flag2%2;
    if(flag2==1)
    {
        OCR0 = 0x00;
        PORTB.7=0;
        PORTB.6=1;
    }
    else
    {
        OCR0 = 0x00;
        PORTB.7 = 1;
        PORTB.6 = 0;
    }
    lcd_clear();
    lcd_putsf("000%");
    flag = 0;
    delay_ms(5);
}

분석을 해보자면 flag 변수를 이용하요 일정조건을 만족하면 OCR0의 값을 이용해서 PWM을 조절하고 이를 통해 DC모터가 구동하게 된다. DC모터에 대해선 이전의 블로그 내에 dc모터에대해서에 적혀있다. 이를 통해 실제로 dc모터가 구동되는 것을 확인하였고 이후에는 코드를 수정해서 PID제어 작업에 들어갈 예정이다.

자료지식은 https://m.blog.naver.com/PostView.nhn?blogId=ga1267&logNo=220092791530&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F 에서 배울 수 있었습니다.


Me

github를 이용해 만들어본 블로그입니다.