Pid 제어 코드 | 아두이노 Pid 모터 속도제어_[반지하공작실] 답을 믿으세요

당신은 주제를 찾고 있습니까 “pid 제어 코드 – 아두이노 PID 모터 속도제어_[반지하공작실]“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: you.tfvp.org/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 반지하 공작실 이(가) 작성한 기사에는 조회수 13,490회 및 좋아요 146개 개의 좋아요가 있습니다.

pid 제어 코드 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 아두이노 PID 모터 속도제어_[반지하공작실] – pid 제어 코드 주제에 대한 세부정보를 참조하세요

아두이노에서 PID제어를 이용한 모터 속도제어입니다.
PID제어는 정말 많은 곳에 사용되는 피드백제어인데요.
인터넷을 찾아봐도 대부분 PID의 계념만 설명하지 소스를 보여주는
경우는 많이 없어서 이번에 PID소스와 함깨 PID제어에 대해서 분석
해보았습니다.
소스 링크
https://drive.google.com/file/d/1ygiDdquDE-rtVqrOWtJ-chiPgG0JfFQK/view?usp=sharing

pid 제어 코드 주제에 대한 자세한 내용은 여기를 참조하세요.

PID 제어 : 이론, 코딩 및 파라미터 튜닝 방법 – 네이버 블로그

물 온도 제어부터 드론 자세제어까지 제어에 필요한 가장 기본인 PID 제어를 … 코드로 표현하면 이렇다. … PITCH축을 예로 P제어 소스를 짜보자면.

+ 여기에 표시

Source: m.blog.naver.com

Date Published: 11/23/2021

View: 1290

드론 DIY | 아두이노 PID 제어 코드 (코드 첨부)

지난 포스팅에서 PID의 원리가 뭔지, 대체 왜 필요한지에 대해 구구절절 설명했다. 따라서 이번 포스팅에서는 사실 가장 중요한? 아두이노 코드에 …

+ 여기를 클릭

Source: hyongdoc.tistory.com

Date Published: 4/14/2021

View: 3571

PID 제어와 아두이노 예제 코드

PID 제어를 쓸 일이 생길수 있을 것 같아서 자료를 정리중입니다. 어차피 저도 이론적인 내용을 상세히 알지는 못하므로… 이론을 쉽게 정리하고 아두 …

+ 더 읽기

Source: www.hardcopyworld.com

Date Published: 7/1/2022

View: 7021

PID 제어기 알고리즘을 코드로 표현

대덕소프트웨어마이스터고 재학생입니다. 드론 개발, MCU 제어에 대한 관심이 제일 많습니다.

+ 여기에 보기

Source: lovely-embedded.tistory.com

Date Published: 12/26/2021

View: 7306

8-2. Arduino Car로 PID 제어 – 킹포도의 코딩

PID 제어 Cruise System구현에 들어가에기 전에 전에 작성한 글에서는 PID 제어를 사용하지 않은 … 아래 소스코드는 PID Control의 샘플코드입니다.

+ 더 읽기

Source: kingpodo.tistory.com

Date Published: 9/27/2021

View: 1313

엔코더 모터 제어 (3. PID 제어로 속도 제어 [PID 함수들 만들기 …

피드백 제어는 이러한 방식으로 동작되며, 이번 장에서는 PID 제어를 통해 모터의 속도를 … 위의 개념들을 코드로 표현하면 변수에 해당합니다.

+ 여기를 클릭

Source: pkr7098.tistory.com

Date Published: 2/20/2022

View: 1509

Top 31 Pid 제어 코드 Quick Answer – Chewathai27

드론 DIY | 아두이노 PID 제어 코드 (코드 첨부). Article author: hyongdoc.tistory.com; Reviews from users: 3419 ⭐ Ratings; Top rated: 3.5 …

+ 여기에 자세히 보기

Source: chewathai27.com

Date Published: 9/20/2021

View: 8924

Arduino uno, PID control, 아두이노 우노 PID 제어 라이브러리 …

PID (proportional integral derivative control) control – PID 제어 라이브러리 다운 – PID 제어 코드 분석 PID (proportional integral derivative …

+ 더 읽기

Source: setoo0922.tistory.com

Date Published: 10/8/2021

View: 7940

PID제어중에 P제어란? – 원원이의 블로그

안녕하세요 오늘은 PID제어중에 P제어에 대해 자세히 알아보겠습니다 P제어는 … 이제 실제로 코드구현을 아두이노를 통해서 테스트를 해보겠습니다.

+ 여기를 클릭

Source: wowon.tistory.com

Date Published: 6/10/2021

View: 625

주제와 관련된 이미지 pid 제어 코드

주제와 관련된 더 많은 사진을 참조하십시오 아두이노 PID 모터 속도제어_[반지하공작실]. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

아두이노 PID 모터 속도제어_[반지하공작실]
아두이노 PID 모터 속도제어_[반지하공작실]

주제에 대한 기사 평가 pid 제어 코드

  • Author: 반지하 공작실
  • Views: 조회수 13,490회
  • Likes: 좋아요 146개
  • Date Published: 2019. 5. 28.
  • Video Url link: https://www.youtube.com/watch?v=HtTbnWNpPiw

PID 제어 : 이론, 코딩 및 파라미터 튜닝 방법

먼저 비례제어로 초기값을 목표값 근처로 크게 끌어올리고 적분제어로 보다 더 근접하게 끌어올린다. 마지막으로 미분제어를 통해 오버슈팅을 잡는다.

PID 제어는 기본적으로 제어하려는 대상의 출력값을 측정하여 이를 원하고자 하는 설정값과 비교하여 오차를 계산하고, 이 오차값으로 제어에 필요한 제어값을 계산하는 구조로 되어 있다.

PID 제어의 수식은 다음과 같이 세 항을 더해 제어값을 구한다.

드론 DIY | 아두이노 PID 제어 코드 (코드 첨부)

지난 포스팅에서 PID의 원리가 뭔지, 대체 왜 필요한지에 대해 구구절절 설명했다.

따라서 이번 포스팅에서는 사실 가장 중요한? 아두이노 코드에 대해 쓰려고 한다.

서술하기에 앞서, 아두이노라는 녀석이 어떻게 동작하는지 알 필요가 있다. 이미 C언어를 어느정도 아는 사람이라면 척보면 다 알지만, 코딩을 처음 해보는 사람들에게는 매우 생소할 것이므로!

처음 C를 배우는 사람도 할 수 있게끔 설명하고자 한다.

1. 아두이노 코딩을 위해 반드시 알아야할 팩트들

아두이노 IDE를 먼저 받아야하는데, 그건 지난 포스팅에 있으므로!

오늘은 바로 코딩을 보도록 하겠다.

아두이노 IDE를 실행시키면 다음과 같은 문구들이 뜬다.

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

void가 뭔지, setup은 뭔지, loop는 뭔지 ()는 뭐고 {}는 뭔지. 아마 처음하는 사람이라면 아무것도 모를 것이다. 그런데 모든 걸 다 알아야 코딩을 할 수 있는게 아니다. 코딩이 뭔가? 알고리즘아닌가? 결국 아두이노 드론을 만드는데 있어서 가장 중요한건 알고리즘이다!

C언어(컴퓨터 프로그래밍 언어)라는 건 결국 우리가 생각한 알고리즘을 언어적으로 풀어주는 데 필요할 뿐, 알고리즘 자체가 될 수는 없기 때문이다.

고로 알고리즘을 짜고, 그 알고리즘을 코딩으로 적용할 줄만 알면 된다. 물론 엄밀히 말하면 프로그래밍 언어에 대한 지식이 있어야 응답속도와 반응성 등과 같은 정밀한 곳에서 더 이점을 가질 수 있겠지만.. 흔히 만드는 아두이노 드론 정도는 딱히 몰라도 가능하다. 고로 시작해보자.

아두이노는 크게 2부분으로 나뉘어져 있다.

void setup, void loop 가 바로 그것이다.

먼저 셋업 부분은 뭘까?

void setup() {

// put your setup code here, to run once:

}

친절하게 아두이노에서 설명해주고 있다. PUT YOUR SETUP CODE HERE, TO RUN ONCE:

즉, 딱 한번만 실행될 코드를 setup 부분에 채워넣으라는 것이다.

void loop() {

// put your main code here, to run repeatedly:

}

다음은 루프 부분. PUT YOUR MAIN CODE HERE, TO RUN REPEATEDLY:

즉, 루프 안에 들어가 있는 코드는 리피트!! 반복된다. 아두이노에 업로드하는 순간부터 영원히 반복된다. loop 안에 있는 건 그냥 영원히~~~ 위에서부터 아래로 코드가 실행되게 되는 것이다. setup은 위에서부터 아래로 한차례 실행되고 마는 부분이고, loop는 영원히 계속 반복되면서 실행되게 된다.

따라서 PID를 코딩으로 한다면, 어떤 부분을 setup에 넣고 어떤 부분을 loop에 넣을지를 생각해야한다.

PID는 이전 포스팅에서 말했지만, P, I, D 제어를 각각 한 후 그 제어값을 모두 더하여 적용 하게 된다.

즉, P제어 + I제어 + D제어 = PID 제어값 이 되는 것이다.

그리고 PID는 오차와 관련된 개념이라고 했다. loop가 어느정도 주기를 갖고 계속 반복되면서 실행될텐데, 매번 실행될때마다 오차가 달라질 것이다. 따라서 loop안에는 매번 달라지는 오차를 가지고 P, I, D 제어값을 새롭게 갱신해주어야 할 필요가 있다.

프로그래밍언어에서는 변수라는 게 있다. 말그대로 변하는 수다. P, I, D 게인값들은 변하지 않는 상수로 지정되어야 하고 오차가 변수로 지정되어야 할 것이다. (꼭 그런건 아니지만 일반적으로!)

그런데 아두이노는 P, I, D 라는 개념이 없다. 아무것도 모른다. 고로 그게 뭔지, 미리 선언해줄 필요가 있다.

예를 들어, Kp, Ki, Kd를 각각 PID의 게인값이라고 생각해보자. 그리고 난 그 값에 각각 1.2, 2.5, 3.2을 지정해주고 싶다.

그렇다면 아래와 같이 선언해주면 된다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

자, 우측은 이해하기가 쉽다. Kp = 1.2 이런 부분은 직관적으로 와닿을 것이다. 그런데 좌측에 double은 뭔가?

아두이노는 우리가 선언하려는 숫자가 정수인지, 실수인지도 모른다. 그걸 우리가 말해주지 않으면 얘는 해석을 못한다. 1.2는 정수가 아니라 실수 영역에 있기 때문에 실수 변수를 얘기하는 double로 선언해주어야 한다. 정수 변수는 int 로 바꿔주면 된다.

자 이제 게인값들을 선언했으니, 오차도 선언해주도록 하자. 오차는 error 라고 하겠다. 오차는 정수보다는 실수인게 더 섬세하고 좋을 것 같으니 실수로 선언!

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

이 경우는 error에 특정 값을 넣지 않았다. 왜? 이건 변수니까 말이다. Kp, i, d는 상수로 고정시킬 것이기 때문에 저렇게 미리 선언해놓은 거고, error는 루프가 계속 반복실행됨에 따라 변하는 수이기 때문에 굳이 넣지 않았다. 저렇게 아무것도 넣지 않으면 초기값이 0으로 자동배정되는 걸로 알고 있다.

이제, 오차에 필요한 현재값과 목표값을 선언해보도록 하자.

목표값은 이전 포스팅에서 예를 든 것처럼, 10도라고 하고 desired_angle로 선언하겠다. 그리고 현재값은 mpu6050을 통해 추출한 각도값으로, 실제 코드는 있다고 가정하고 그 값은 current_angle 이라고 하겠다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

double desired_angle = 10; double current_angle;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

자, 이게 error을 정의할 필요가 있다. error는 오차이다. 즉, 목표값에서 현재값을 뺀 수치가 될 것이다. 그리고 이 오차는 매 순간순간 달라질 것이다. 드론이 첨엔 10도 오차가 있다가, 그 쪽으로 회전을 시작하면 9도 8도 … 1도 0도까지 점점 오차가 줄어들게 아닌가. 고로 매 순간순간 갱신해줘야하는 변수가 되는 것이다. 그렇다면? 당연히 loop안에서 선언되어야 한다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

double desired_angle = 10; double current_angle;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

}

처음에 넣은 current_angle갱신코드란? 이건 현재 각도값을 의미하는데, 현재 드론이 기울어진 각도값도 mpu6050의 연산에 의해 실시간으로 변화되어야만 한다. 따라서 loop안에 넣어준거고, 이 부분은 mpu6050에 관련된 코딩이 필요하기 때문에 생략하고 위와 같이 표시하였다.

자, 이제 오차인 error가 아두이노에서 선언되어 해석가능해졌으므로, 본격적으로 PID 제어를 시작해보자.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control = I_control + Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

error_previous = error;

}

이번엔 추가된 게 좀 많다. 먼저 loop안을 보면, P컨트롤, I컨트롤, D컨트롤, 그리고 error_previous, Time 등과 같은 새로운 변수들이 선언된 것을 알 수 있다.

고로 맨 윗부분에 선언해준 것이다. 특히 Time은 한 루프가 도는 데 걸리는 시간을 의미한다. 내가 만든 드론은 한 루프 도는데 걸리는 시간이 약 3~4ms기 때문에 0.004로 해준건데, 사실 꼭 이렇게 할 필요는 없다. 그냥 4로 해도되고 4000으로 해도되고. Time이 수식적으로 가지는 의미는 그냥 ‘상수’일 뿐이다. 따라서 아무렇게나 지정해줘도, 또 다른 상수인 Kd나 Ki로 커버할만한 수준이기만 하면 되는것이다.

쉽게 생각해서, 4 * 6이나, 3 * 8이나 똑같은 수 아닌가. 곱해서 똑같이 나오게 숫자를 조정할 수 있기 때문에 꼭 time을 주기로 맞춰줄 필요는 없다는 것이다.

그리고 가장 아래보면 error_previous = error라고 선언한 부분이 있다. 아두이노에서는 이럴 때 우측에 있는 녀석을 좌측값으로 저장하라고 해석한다.

즉, error_previous라는건 지금 루프가 아니라 바로 이 전에 루프가 실행될 때의 error값을 의미한다.

만약 처음 error가 3이라고 해보자. 그러면 loop는 위에서부터 아래로 실행될 것이므로 error_previous에도 3이 저장 될 것이다.

그리고 loop가 다시 돌았을 때, 갱신된 현재각도에 의해 오차인 error가 5가 되었다고 해보자. 그리고 D_control을 보면, Kd * (5 – 3) / 0.004 가 될 것이다.

즉 컨트롤 부분에서 계산할 때 바로 직전의 에러 값이 previous에 저장되는 것이다.

I_control 부분은, 기존 I_control 값에다가 추가로 I 제어를 통해 얻은 값을 더하라는 것이다. 이전 포스팅에서 I 제어의 역할이 오차를 누적시켜 최종적으로 오차를 0으로 보내는 데 있다고 했는데, 이와 같은 방법으로 ‘누적’ 시킨다.

다만 언어적으로 좀 더 편하게 쓸 수 있다.

I_control += Ki * error * Time

이렇게 +=라고 하면, 위와 똑같은 의미를 가진다. 그냥 언어적인 것이니까 외우고 사용하면 된다.

이제 다음으로 넘어가보자.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004; double PID_control;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control += Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

PID_control = P_control + I_control + D_control; PID_control = constrain(PID_control, 0, 255); analogWrite(6, PID_control);

error_previous = error;

}

PID_control이라는 변수를 또 만들었다. 말했듯이, PID제어값은 P, I, D 제어를 통해 나온 값들을 모두 더한 값이므로 그냥 더해준 것이다.

그 뒤에 나오는 constrain은, 아두이노에서 제공하는 함수이다.

저걸 쉽게 얘기하면, PID_control이라는 값이 0부터 255까지의 숫자 범위를 가지도록 제한하는 것이다.

예를들어 PID_control이 -100이라는 값이 되면, 0으로 저장이 되고, 1000이라는 값이 되면 255로 저장이 된다. 0과 255사이의 값은 그 값 그대로 저장된다.

이렇게 해주는 이유는, 그 뒤에 나오는 anaglogWrite이라는 함수가 0부터 255사이의 숫자만 받아들이기 때문이다.

analogWrite은 전압을 인가하는 함수로, 6번 핀에 0~255 사이에 해당하는 전압을 주라는 명령신호다. 0은 0V, 255는 5V를 주게 되는데

사실 실제 드론을 만들 때는 이 함수를 쓰지 않을 것이다. servo 라이브러리를 활용하여 다른 함수를 쓸 예정인데

이 포스팅의 목적은 아무튼 PID 제어 코드의 기본을 설명하는 것이기 때문에 그냥 그대로 가는걸로..

최종적으로 나온 PID_control 이라는 값이 가장 중요하다. 이게 PID 제어를 통해 구한 제어값이 되기 때문이다.

다음으로, 조금 보기좋게 코드를 정리하기 위해 다음과 같이 해보았다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004; double PID_control;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly: pidcontrol();

}

void pidcontrol() {

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control += Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

PID_control = P_control + I_control + D_control; PID_control = constrain(PID_control, 0, 255); analogWrite(6, PID_control);

error_previous = error;

}

뭐가 달라졌나?

바로 void pidcontrol 이라는걸 만들었다는 데 있다. 이건 쉽게 말해, 그냥 그룹으로 묶어놓는거라고 보면 된다.

loop가 가장 중요한 부분인데, 위위처럼 loop안에 모든 코드를 작성하게 되면 보기가 매우 불편하다. 때문에 항목별로 묶어서 따로 이렇게 정리해놓는 것이다. loop안에는 pidcontrol() 이라고만 선언해주면, pidcontrol이라고 선언된 그룹이 실행되게 된다.

고로 위랑 위위는 똑같은 코드이다! 정리해서 보기가 더 수월할 뿐!

이게 전부다!

PID 제어는 이렇게 하면 된다. 시작할때 오차는 10도였겠지만 시간이 흐르면 0으로 점점 줄어들어 원하는 목표값에 도달할 것이다.

단, Kp, Ki, Kd라는 게인값을 잘 맞추었다면 말이다. 이전 포스팅에서 움짤을 하나 사용했었는데, 그것처럼 반응을 보일 것이다. 제대로 게인값을 맞추지 않으면 오차가 오히려 더 커질 수도 있다. 드론이라는 시스템에 맞춰 적당한 값을 맞춰주어야 하는데 이 부분은 실험을 통해서 검증할 수 있다.

아무튼 제어 코드는 이와 같다. 실제 드론을 날릴때는 이중 pid라고 하여, pid 제어를 겹으로 싸서 이중으로 만든 걸 쓸텐데 별로 어려울 건 없다. 똑같다! 그냥 겹으로 한번 싸주기면 하면 된다.

최종 코드는 계속 포스팅하면서 써가는 걸로.

*** 19.12 수정사항

안녕하세요.

많은 분들이 아두이노 코드를 요청하셔서 제작했던 코드를 아래 포스팅에 첨부하였습니다.

https://hyongdoc.tistory.com/270

PID 제어와 아두이노 예제 코드

PID 제어를 쓸 일이 생길수 있을 것 같아서 자료를 정리중입니다. 어차피 저도 이론적인 내용을 상세히 알지는 못하므로… 이론을 쉽게 정리하고 아두이노 코드로 옮기는 작업을 해야죠. 정리되는대로 이 페이지는 업데이트 됩니다.

[출처] PID제어란!!|작성자 화이팅

1. PID 제어란 ?

자동제어 방식 가운데서 가장 흔히 이용되는 제어방식으로 PID 제어라는 방식이 있다.

이 PID란,

P: Proportinal(비례)

I: Integral(적분)

D: Differential(미분)

의 3가지 조합으로 제어하는 것으로 유연한 제어가 가능해진다.

2. 단순 On/Off 제어

단순한 On/Off 제어의 경우에는 제어 조작량은 0%와 100% 사이를 왕래하므로 조작량의 변화가 너무 크고, 실제 목표값에 대해 지나치게 반복하기 때문에, 목표값의 부근에서 凸凹를 반복하는 제어로 되고 만다. 이 모양을 그림으로 나타내면 아래 그림과 같이 된다.

3. 비례 제어 (P 제어 )

이에 대해 조작량을 목표값과 현재 위치와의 차에 비례한 크기가 되도록 하며, 서서히 조절하는 제어 방법이 비례 제어라고 하는 방식이다. 이렇게 하면 목표값에 접근하면 미묘한 제어를 가할 수 있기 때문에 미세하게 목표값에 가까이 할 수 있다. 이 모양은 아래 그림과 같이 나타낼 수 있다.

-PID제어기에서 반드시 사용하는 가장 기본적인 제어이며 구현하기가 쉽다. 이 제어만으로는 적분기가 플랜트에 없을 경우에 정상상태 오차가 발생할 수 있다.

-비례제어란 기준신호와 되먹임 신호 사이의 차인 오차신호에 적당한 비례상수 이득을 곱해서 제어신호를 만들어내는 제어기법을 말하며, 오차신호에 비례하는(Proportional) 제어신호를 만든다는 뜻에서 이 기법에 의한 제어기를 비례제어기(Proportional Controller), 또는 영문약자를 써서 P제어기라고 부른다

?장점 – 구성이 간단하여 구현하기가 쉽다.

?단점 – 이득의 조정만으로는 시스템의 성능을 여러 가지 면에서 함께 개선시키기는 어렵다. 상승시간과 초과 사이의 상충문제를 절충하지 못함.

4. 적분 제어 (I 제어 )

정상상태 오차를 없애는데 사용. 계수조정이 잘못되면 시스템이 불안해지고 반응이 느려진다.

5. 비례미분 제어 (PD 제어 )

-오차신호를 미분하여 제어신호를 만들어내는 미분제어를 비례제어에 병렬로 연결하여 사용하는 제어기법. 비례제어 부분과 미분제어를 함께 쓴다는 뜻에서 이 기법에 의한 제어기를 비례미분 제어기(proportional-derivative controller), 또는 PD제어기 라고 한다. D요소를 부가한 것으로 인해 PD제어기는 단순한 P 제어기보다 응답이 빠르다.

-오차신호의 미분값에 비례하는 제어신호를 되먹임시켜 오차 신호의 변화를 억제하는 역할을 하기 때문에 감쇠비를 증가시키고 초과를 억제하는 데에 효과적이다. 이러한 미분제어의 효과를 고려하여 PD제어기를 적절히 설계하면 시스템의 과도응답 특성을 개선시킬 수 있다. PD제어기를 사용하는 경우에 시스템 형식이 증가하지 않기 때문에 정상상태 응답특성은 개선되지 않으므로 주의 하여야 한다.

Kp: 상승시간(rise time) 감소, 정상상태 오차 제거에

Ki : 정상상태 오차 제거, 과도응답 특성 나빠짐.

Kd: 시스템의 안정성 증가, 오버슈트, 과도응답 특성을 향상시킴

6. PI 제어

비례 제어로 잘 제어할 수 있을 것으로 생각하겠지만, 실제로는 제어량이 목표값에 접근하면 문제가 발생한다. 그것은 조작량이 너무 작아지고, 그 이상 미세하게 제어할 수 없는 상태가 발생한다. 결과는 목표값에 아주 가까운 제어량의 상태에서 안정한 상태로 되고 만다. 이렇게 되면 목표값에 가까워지지만, 아무리 시간이 지나도 제어량과 완전히 일치하지 않는 상태로 되고 만다. 이 미소한 오차를 “잔류편차”라고 한다. 이 잔류편차를 없애기 위해 사용되는 것이 적분 제어이다. 즉, 미소한 잔류편차를 시간적으로 누적하여, 어떤 크기로 된 곳에서 조작량을 증가하여 편차를 없애는 식으로 동작시킨다. 이와 같이, 비례 동작에 적분 동작을 추가한 제어를 “PI 제어”라 부른다. 이것을 그림으로 나타내면 아래 그림과 같이 된다.

-비례적분 제어란 오차신호를 적분하여 제어신호를 만들어내는 적분제어를 병렬로 연결하여 사용하는 제어기법을 가리킨다. 비례제어 부분과 더불어 오차신호를 적분(integral)하여 제어신호를 만드는 적분제어를 함께 쓴다는 뜻에서 이 기법에 의한 제어기를 비례적분 제어기(proportional-integral controller), 또는 영문약자를 써서 PI제어기라고 부른다. 정상상태 오차를 없애면서 시스템의 반응을 빠르게 하려면 비례적분 제어기를 사용하면 된다.

?장점 – P제어기와 I 제어기의 단점을 서로 보완해 줌으로써 전달함수에 시스템의 유형을 높여주고 정상상태 오차를 줄여주면서 과도응답으로 발생한 시스템의 느린 반응을 빠르게 할 수 있다. 감쇠비를 증가시키고 동시에 정상상태 오차도 개선.

?단점 – Gain계수조정이 잘못되면 시스템이 불안해지고 반응이 느려진다. Overshoot가 증가하고 Ts가 증가한다. 이러한 단점을 보완하기 위해서는 D제어기를 사용함으로써 해결된다. 상승시간이 느려지는 등 과도응답에는 불리하다.

7. 미분 제어와 PID 제어

PI 제어로 실제 목표값에 가깝게 하는 제어는 완벽하게 할 수 있다. 그러나 또 하나 개선의 여지가 있다. 그것은 제어 응답의 속도이다. PI 제어에서는 확실히 목표값으로 제어할 수 있지만, 일정한 시간(시정수)이 필요하다. 이때 정수가 크면 외란이 있을 때의 응답 성능이 나빠진다.

즉, 외란에 대하여 신속하게 반응할 수 없고, 즉시 원래의 목표값으로는 돌아갈 수 없다는 것이다. 그래서, 필요하게 된 것이 미분 동작이다. 이것은 급격히 일어나는 외란에 대해 편차를 보고, 전회 편차와의 차가 큰 경우에는 조작량을 많이 하여 기민하게 반응하도록 한다. 이 전회와의 편차에 대한 변화차를 보는 것이 “미분”에 상당한다. 이 미분동작을 추가한 PID 제어의 경우, 제어 특성은 아래 그림과 같이 된다. 이것으로 알 수 있듯이 처음에는 상당히 over drive하는 듯이 제어하여, 신속히 목표값이 되도록 적극적으로 제어해 간다.

-PD제어기는 시스템의 제동비를 증가시켜서 과도응답특성을 개선시키지만 정상상태 응답을 개선하는 데에는 효과가 없으며, PI제어기는 정상상태 오차를 개선시키지만 상승시간이 느려지는 등 과도응답에는 불리하다는 것을 알았다. 따라서, 정상상태 응답과 과도상태 응답을 모두 개선하려면 PI 와 PD제어기의 장점들을 조합하는 방법을 자연스럽게 생각할 수 있는데, 이러한 목적으로 제안된 제어기가 바로 PID 제어기이다.

8. 컴퓨터에 의한 PID 제어 알고리즘

원래 PID 제어는 연속한 아날로그량을 제어하는 것이 기본으로 되어 있다. 그러나, 컴퓨터의 프로그램으로 PID 제어를 실현하려고 하는 경우에는 연속적인 양을 취급할 수 없다. 왜냐하면, 컴퓨터 데이터의 입출력은 일정시간 간격으로밖에 할 수 없기 때문이다. 게다가 미적분 연산을 착실히 하고 있는 것에서는 연산에 요하는 능력으로 인해 고성능의 컴퓨터가 필요하게 되고 만다. 그래서 생각된 것이 샘플링 방식(이산값)에 적합한 PID 연산 방식이다.

우선, 샘플링 방식의 PID 제어의 기본식은 다음과 같이 표현된다.

조작량 = Kp×편차 + Ki×편차의 누적값 + Kd×전회 편차와의 차

(비례항) (적분항) (미분항)

기호로 나타내면,

MVn = MVn-1 + ΔMVn

ΔMVn = Kp(en-en-1) + Ki en + Kd((en-en-1)-(en-1-en-2))

MVn, MVn-1: 금회, 전회 조작량

ΔMVn: 금회 조작량 미분

en, en-1, en-2: 금회, 전회, 전전회의 편차

이것을 프로그램으로 실현하기 위해서는 이번과 전회의 편차값만 측정할 수 있으면 조작량을 구할 수 있다.

9. 파라미터를 구하는 방법

PID 제어 방식에 있어서의 과제는 각 항에 붙는 정수, Kp, Ki, Kd를 정하는 방법이다.

이것의 최적값을 구하는 방법은 몇 가지 있지만, 어느 것이나 난해하며, 소형의 마이크로컴퓨터로 실현하기 위해서는 번거로운 것이다(tuning이라 부른다). 그래서, 이 파라미터는 cut and try로 실제 제어한 결과에서 최적한 값을 구하고, 그 값을 설정하도록 한다.

참고로 튜닝의 수법을 소개하면 스텝 응답법과 한계 감도법이 유명한 수법이다.

또, 프로세스 제어 분야에서는 이 튜닝을 자동적으로 실행하는 Auto tuning 기능을 갖는 자동제어 유닛도 있다. 이것에는 제어 결과를 학습하고, 그 결과로부터 항상 최적한 파라미터값을 구하여 다음 제어 사이클에 반영하는 기능도 실장되어 있다.

여기서 스텝 응답법에 있어서 파라미터를 구하는 방법을 소개한다. 우선, 제어계의 입력에 스텝 신호를 가하고, 그 출력 결과가 아래 그림이라고 하자(파라미터는 적당히 설정해 둔다).

위 그림과 같이 상승의 곡선에 접선을 긋고, 그것과 축과의 교점, 정상값의 63%에 해당하는 값으로 된 곳의 2점에서,

L: 낭비시간 T: 시정수 K: 정상값의 3가지 값을 구한다.

이 값으로부터, 각 파라미터는 아래 표와 같이 구할 수 있다.

제어 동작 종별 Kp의 값 Ki의 값 Kd의 값 비례 제어 0.3~0.7T/KL 0 0 PI 제어 0.35~0.6T/KL 0.3~0.6/KL 0 PID 제어 0.6~0.95T/KL 0.6~0.7/KL 0.3~0.45T/K

이 파라미터에 범위가 있지만, 이 크기에 의한 차이는 특성의 차이로 나타나며, 아래 그림과 같이, 파라미터가 많은 경우에는 미분, 적분 효과가 빨리 효력이 나타나므로 아래 그림의 적색선의 특성과 같이 overshoot이 크게 눈에 띈다. 파라미터가 작은 쪽의 경우는 하측 황색선의 특성과 같이 된다.

10. PID 게인 조정 및 제어 특성

PID 제어의 최적의 계수는 상태와 시스템에 따라서 달라진다. 이는 사용자의 시스템에 맞는 개별 제어 특성을 고려하여 게인 파라미터를 설정하는 것이 필요하다는 것을 의미한다. 다음은 PID 제어에 요구되는 특성들이다.

· 안정된 성능

· 빠른 응답

· 아주 작은 정상상태 편차

안정된 성능 영역 내에서 Kp, Ki, Kd의 각 파라미터를 조정해야 한다. 일반적으로 각각의 게인(Kp, Ki, Kp) 파라미터를 증가시키면(적분시정수 Ti 는 감소), 빠른 응답을 얻을 수 있다. 그러나 너무 많이 증가시키면 제어가 불안정하게 된다. 왜냐하면 피드백 값이 연속적으로 증가하거나 감소하기 때문에 제어의 진동을 야기시키게 된다. 최악의 경우 시스템은 발산모드가 된다. 다음은 각각의 파라미터를 조정하기 위한 방법이다.

(1) 목표값을 변화한 후, 응답이 너무 느리다.

→ P-게인(Kp)을 올린다. 응답은 빠르나 불안정하다.

→ P-게인(Kp)을 내린다.

(2) 목표값과 피드백값이 같아지지 않는다.

→ 적분 시간 Ti를 감소시킨다. 불안정하게 진동하며 일치한다.

→ 적분 시간 Ti를 증가시킨다.

(3) Kp를 올린 후, 응답이 여전히 느리다.

→ D-게인(Kd)을 올린다. 여전히 불안정하다.

→ D-게인(Kd)을 내린다.

* 각 게인 조정의 예(Kp & Ti)

· 목표값에 스텝변화가 주었을 때 피드백 신호의 응답이나 인버터의 출력주파수를 확인하면 된다

· 오실로스코프나 기타의 측정장비를 사용하여 피드백값이나 인버터의 출력주파수의 파형을 관찰한다(주파수 모니터).

· 디지털 입력신호에 의해서 변하는 목표값을 먼저 비교하여, 스텝응답으로 목표값을 변화시킬 수 있다.

· 프로세싱 전에는 제어시스템이 안정화되어야만 한다.

* 비례게인의 조정(Kp)

I-제어와 D-제어 없이 P-제어에 의해서만 구동을 시작한다(나머지는 0으로 설정).

먼저 P-게인을 최소값으로 설정하고 어떻게 동작하는 가를 본다. 결과값을 보고서 P-게인을 점차적으로 증가시킨다. 아주 만족할 만한 성능을 발휘할 때까지 이러한 절차를 반복한다(또 다른 방법은 최대 P-게인을 설정하고 성능을 관측한다. 만약 시스템이 불안정하면 중간값을 설정하고 어떻게 동작하는가를 관측한다. 이러한 절차를 계속해서 반복하면 된다). 만약 시스템이 불안정하다면 P-게인을 줄인다. 만약 허용범위에서 정상상태 편차가 존재한다면 P-게인의 조정은 완전히 완료된 것이다.

– 적분시간의 조정(Ti) & Kp의 값의 재조정 최소 적분시간을 설정함으로써 조정을 시작한다. 만약 조정이 어렵다면 P-게인을 줄인다. 편차가 수렴하지 않는 경우에는 적분시간을 줄인다. 만약 이 시간 동안 제어가 불안정하다면 P-게인을 줄인다. 안정된 파라미터를 찾을 때까지 계속해서 이러한 절차를 반복한다.

(1) 비례동작 (Proportional action) – P 동작

제어기는 기준 입력과 현재값과의 편차를 줄이는 방향으로 제어한다. 그때, 제어장치에 동작신호 Z(t)가 주어졌을 때, 조작량 y(t)가 얻어지는 경우, 즉 조작량 y(t)가 동작신호 Z(t)에 비례하여 변할 때의 그 관계식은

y(t) = K Z(t)

가 된다. 이것을 비례동작이라 한다. 여기서 K는 비례정수로 비례동작을 강하게 할 것인가, 약하게 할 것인가를 결정한다. 비례정수의 크기가 크면 기준입력에 현재치가 빠르게 접근하나 출력이 진동하여 제어의 안정성에 악영향을 미칠 수 있고, 비례정수의 크기가 작으면 기준입력에 천천히 현재치가 접근하며 잔류편차가 생길 우려가 있다.

(2) 적분동작 (Integral control action) – I 동작

제어대상에 주어지는 조작량의 변화속도가 동작신호에 비례 하는 동작, 적분동작은 적분 시간을 조정하여 적분동작을 크게 또는 작게 한다. 즉 적분시간을 길게 하면 조작량이 적어지고 따라서 기준치에 접근하는 시간이 길어진다. 적분시간이 짧으면 조작량이 많아지게 되어 기준치에 접근하는 시간이 짧아진다. 적분동작의 관계식은

y(t) = K Z(t) dt

가 된다. 적분동작은 단독으로 사용되지 않으며 P동작이나 D동작과 결합하여 PI, PID동작에 사용한다. 적분동작은 P동작에서 발생할 수 있는 잔류편차를 없앨 수 있다. 적분시간이 너무 짧으면 제어 불능 상태에 빠질 수 있다.

(3) 미분동작 (Derivative action)

조작량 y(t)가 동작신호 Z(t)에 미분동작을 한다. 미분동작은 편차의 변화율에 상응하는 조작량을 연산하여 편차의 변화를 억제한다. 미분동작의 관계식은

y(t) = K dZ(t)/dt

가 된다. 미분동작은 단독으로 사용되지 않으며 P동작이나 D동작과 결합하여 PI, PID동작에 사용한다. 일반적으로 미분동작을 사용한 제어기는 기준 입력에 접근하는 속도가 빨라지고 현재치의 급변이나 외란을 억제하는 효과가 있다.

(4) PID 제어 유니트

비례 적분 미분 동작은 위에서 설명한 3가지 동작을 조합한 동작으로 관계식은

y(t) = K ( Z 1/Ti Z(t) dt Td dZ(t)/dt )가 된다.

PID 제어기 알고리즘을 코드로 표현

표준 PID 제어기 알고리즘은 다음과 같습니다.

이 알고리즘을 코드로 간단하게 표현하자면 다음과 같습니다.

Error = Setpoint – Input; PTerm = Kp * Error; ITerm += Ki * Error * dt;

현재 오차(Error)는 설정(Setpoint) 값에서 현재 입력(Input) 값을 빼서 구합니다.

비례항(PTerm)은 비례항 이득값(Kp)에 현재 오차를 곱해서 구합니다.

적분항(ITerm)은 적분항 이득값(Ki)에 현재 오차와 주기(dt)를 곱해서 더해줍니다.

미분항(DTerm)을 구하기 위해서는 다음과 같이 구합니다.

dError = Error – prevError ; DTerm = Kd * ( dError / dt ) ;

오차 변화(dError)는 현재 오차(Error)에서 이전 오차(prevError)를 뺀 값입니다.

미분이라는 것이, 그래프의 순간의 기울기(오차 변화율)를 알고자 하는 것이기 때문에 짧은 순간의 오차 변화량을 순간 시간 변화량(주기)으로 나눠줍니다.(dError / dt)

마지막으로, 미분항(DTerm)은 미분항 이득값(Kd)에 오차 변화율을 곱해서 구합니다.

출력 값은 다음과 같습니다.

Output = PTerm + ITerm + DTerm ;

참고 문헌 : 아두이노로 드론 만들고 직접 코딩하기

8-2. Arduino Car로 PID 제어

반응형

1. PID 제어 Cruise System구현에 들어가에기 전에

전에 작성한 글에서는 PID 제어를 사용하지 않은 Cruise System을 구현하였고 그것에 문제점에 대하여 이야기했습니다. 아무런 지식이 없는 상태에서 바로 이글을 보신다면 이해가 어려운 부분이 생길 수 있습니다. 이전 글을 참고하시면서 보시는것을 추천드립니다. 또한 갑자기 난이도가 높아지는것을 느끼실 겁니다. 천천히 내용을 읽어보시고 다른 자료도 참고 부탁드립니다.

2. PID Control

PID Control을 사용하여 Arduino Car에 Cruise System을 구현하기 전에 PID Control이 무엇인지 알아보겠습니다. PID 제어는 실제 응용분야에서 많이 사용되는 제어기법입니다. 이러한 PID는 드론, 자동차, 온도등 안정적인 모터를 제어하는 부분에서 사용됩니다. 그러면 Cruise System에 PID Control이 어떻게 사용되는지 알아보겠습니다. 전에 올렸던 글을 보시면 안정적인 속도를 제어하기 위해서는 거리별 단계를 나누어 속도를 통제한다고 하였습니다. 그러면 그 단계가 무수히 많아진다면 좀더 좋은 속도제어가 될것이며 이를 가능하게 하는것이 PID 제어입니다. 아래 그림을 보시면 이해가 편하실 것입니다.

1) PID Control이란?

PID Control의 명칭의 P는 Proportional(비례), I는 Integral(적분), Differential(미분)의 앞글자를 따온 단어입니다. 즉 비례와 적분, 미분을 사용하여 적절한 값을 도출해 제어에 응용하는 기법입니다. 이는 대상의 출력값을 측정하여 이를 원하는 설정값과 비교하여 오차를 계산하고, 이 오차를 이용하여 제어에 필요한 제어값을 계산하는 구조입니다.

표준적인 형태의 PID 제어기는 아래의 식과 같이 세개의 항을 더하여 제어 값을 계산하도록 되어있습니다.

PID 제어서 각각의 항들은 오차값, 오차값의 적분, 오차값의 미분에 비례하기 때문에 비례-적분-미분 제어기라는 명칭을 가집니다.

비례항 : 현재 상태에서의 오차값의 크기에 비례한 제어작용을 한다.

적분항 : 정상상태 오차를 없애는 작용을한다.

미분항 : 출력값의 급격한 변화에 제동을 걸어 안정성을 향샹시킨다.

PID 제어기는 위와 같은 표준식으로 사용하기도 하지만, 경우에 따라서는 약간 변형된 형태로 사용되는 경우도 많습니다. 그 예가 P제어

PI제어, PD제어가 있습니다. 아래 사진은 PID를 이해하는데 많은 도움이 될꺼같아 위키백과에서 가져왔습니다. 나머지 설명들도 그래프를 같이 봐주시기 바랍니다.

<출처 - 위키백과>

2) P Control

비례 제어라고 불리며 설정값과 출력값의 편차에 비례해 연속적으로 변화하는 제어 방식으로, 출력값이 설정값에 근접할수록 미세하게 제어가 가능합니다. 비례제어는 출력값과 설정값이 차이가 적어질수록 서서히 감도가 좋아져 규칙적인 사이클이 발생하지만 잔류 편차로 인해 출력값이 설정값과 정확하게 일치하지 못하는 상태가 지속됩니다.

3) PI Control

비례 제어에서 발생하는 잔류 편차를 적분 동작으로 제어해 오차를 줄이기 위한 제어 방법입니다. 이 적분 제어는 정상 상태이때 오차를 제거하는 동작을 합니다. 전류 편차를 누적한 후 출력량을 늘려 오차를 제거하는 방식으로 적분 동작을 이용해 설정값에 빠르게 도달할 수 있다는 장점이 있습니다.

4) PD Control

비례 제어에서 과출력 상태에서 생기는 오차를 미분 동작으로 제어하기 위한 제어 방법입니다. 미분 제어는 급격한 출력값의 변동이 필요할 때, 기존 동작의 편차를 파악해서 출력값을 조절해 오차를 줄이고 다시 안정상태로 돌아가는 동작을 합니다. 미분 제어는 안정성을 향상시킬 수 있는 장점이 있습니다.

5) PID Control

비례 제어를 기본으로, 적분, 미분 제어를 결합한 최종형태입니다. 적분 제어를 통해 정상적 상태에서 오차를 줄이고와 응답속도를 높여주고 미분제어를 통해서 과출력 상태에서의 오차를 줄여 안정적인 상태로만듭니다. PID제어는 이런식으로 서로 단점을 보안하고 장점을 극대화 해줍니다.

5) Gain 값(제어 파라메터)

위에 그래프와 식을 보시면 라는 값이 있는데 이것이 Gain값입니다. 이는 위 그래프를 보시면 gain값이 변화에 따라 어떠한 그래프가 만들어지는지 아실 수 있습니다. 이러한 적절한 Gain값을 구하는 방식은 수학적 방법과 실험적 방법이 있는데 이를 구하여 수정하는 것을 튜닝이라고 합니다. 수학적으로 구하는 방법으로 대표적인 것은 지글러-니콜스 방법이라고합니다. 하지만 매우 어려워서 보통 실험을 통해서 gain값을 수정한다고합니다. 저도 gain값을 직접 넣어 실험을 해보면서 이 값을 구하였습니다.

3. PID Control Sample Code

아래 소스코드는 PID Control의 샘플코드입니다. 아래 코드를 활용해서 PID제어를 하시면 됩니다. 단 요즘 Arduino Library를 보시면 PID를 제공하고 있습니다. 저는 사용해본적이 없지만 그것도 해보시면 좋을꺼 같습니다.

/*gain값 실험을 통해서 직접 수정해 보시는것이 좋습니다. */ float Kp = 0.3; float Ki = 1.2; float Kd = 1.5; float error; // error값이란 설정값과 출력값의 편차를 말합니다. float errorPrevious; //전에 error값을 기억해둡니다. float safeDistance; //안전거리, 설정값입니다. float distance; // 현재 거리, 출력값입니다. double PControl, IControl, DControl; // 비례, 적분, 미분 제어항의 결과 값입니다. double Time = 0.004; //한번의 연산을 하는데 걸리는 시간입니다. 1회 loop의 시간입니다. double PIDControl; // P,I,D Contorl의 결과값입니다. void setup() { } void loop() { distance = 갱신 코드; // 장애물과의 거리를 가져옵니다. error = safeDistance – distance; // 안전거리와 장애물과의 거리를 빼서 error값을 구합니다. PControl = Kp * error; //비례항 입니다. IControl += Ki * error * Time; // 적분항 입니다. DControl = Kd * (error – errorPrevious) / Time; // 미분항입니다. PIDControl = PControl + IControl + DControl; // P, I, D 결과값을 더해줍니다. PIDControl = constrain(PIDControl, 0, 255); // constrain이라는 함수는 입력값은 값을 0 ~ 255사이 값으로 변환해서 반환합니다. analogWrite(6, PIDControl); //모터를 PIDControl값으로 PWM신호를 보내 움직입니다. errorPrevious = error; //이전 에러값를 기억합니다. }

다음글에서는 이 PID Control을 활용해서 Cruise 시스템을 구현해보겠습니다.

반응형

엔코더 모터 제어 (3. PID 제어로 속도 제어 [PID 함수들 만들기 Part 01])

반응형

관련글

엔코더 모터 제어 (0. 소개) (tistory.com)

엔코더 모터 제어 (1. 펄스및 위치 측정) (tistory.com)

엔코더 모터 제어 (2. 속도 계산) (tistory.com)

서론

엔코더 모터는 위치 제어뿐만 아니라 속도제어도 가능합니다. 전장에서 알아 봤던 M 또는 T 방식으로 현재 RPM을 측정하고, 이를 기반으로 현재 속도를 수정하고, 목표치에 맞춰질 수 있도록 제어량을 조절하는 것입니다.

즉 다음과 같은 피드백 방식으로 속도를 제어합니다.

그림01

PWM 신호와 피드백 제어를 통해 얻은 값을 더하여 모터를 동작시킵니다. 모터가 동작되면 모터의 속도를 측정하고 피드백 제어에서 오차를 계산하여 PWM 값과 다시 결합하여 제어량을 결정합니다.

피드백 제어는 이러한 방식으로 동작되며, 이번 장에서는 PID 제어를 통해 모터의 속도를 제어해 보겠습니다.

PID 제어

변수 생성

에러 계산 함수

P 제어 함수

I 제어 함수

D 제어 함수

PID 함수

결과 영상

참고 자료

STM32F103ZET6 Reference Manual

STM32F10xxx/20xxx/21xxx/L1xxxx Cortex®-M3 programming manual

PID제어란? (tistory.com)

PID 제어

PID 제어를 하기 위해선 다음의 개념들이 필요합니다.

개념 설명 변수 목표값 우리가 목표로하는 모터의 RPM target 현재값 현재 모터의 RPM current 실시간 에러값 목표 RPM과 현재 RPM 사이의 차이값입니다. realError 누적 에러값 목표 RPM과 현재 RPM 사이의 차이를 누적한 값입니다. accError 에러 변화량 현재 에러와 이전 에러 사이의 차입니다. errorGap P 제어량 P 제어를 통해 얻은 제어량 pControl P gain P 제어에 사용되는 계수 (상수) P_GAIN I 제어량 I 제어를 통해 얻은 제어량 iControl I gain I 제어에 사용되는 계수 (상수) I_GAIN D 제어량 D 제어를 통해 얻은 제어량 dControl D gain D 제어에 사용되는 계수 (상수) D_GAIN 최종 제어향 P, I, D 제어량을 합친 제어향 pidControl 미분계수 값 d/dt에 해당되는 값 (상수) TIME

에러 계산 함수

에러의 종류가 실시간 에러, 누적 에러가 있기 때문에 이들을 계산하는 함수를 선언합니다.

void calculateErrors(void) { errorGap = target – current – realError; realError = target – current; // 실시간 에러는 단순히 목표값 – 현재값을 의미합니다. accError += realError; /* 누적 에러는 실시간 에러를 계속해서 더한 값입니다. I 제어를 위해 사용됩니다. */ }

errorGap는 현재 에러와 이전 에러사이의 변화량이며, D 제어를 위해 사용합니다.

realError는 목표값과 현재값 사이의 차 즉, 목표값 – 현재값을 의미합니다. P 제어를 위해 사용합니다.

accError는 realError값을 누적한 값으로 I 제어를 위해 사용됩니다.

변수 생성

위의 개념들을 코드로 표현하면 변수에 해당합니다. (물론 몇몇 개념들을 상수로 선언합니다.)

#define P_GAIN 1 #define I_GAIN 1 #define D_GAIN 1 #define TIME 4 unsigned int target = 0; unsigned int current = 0; unsigned int pControl = 0; unsigned int iControl = 0; unsigned int dControl = 0; unsigned int pidControl = 0; unsigned int realError = 0; unsigned int accError = 0; unsigned int errorGap = 0;

수학적으로만 봤을 때는 모두 실수값인 double형으로 선언해야하지만, MCU는 기본적으로 실수 연산을 못하기 때문에 int 형으로 선언한 것입니다.

해당 변수들은 글로벌 변수로 선언해주셔야합니다. (main 위에다 선언)

P 제어 함수

unsigned int pControlSystem(void) { pControl = P_GAIN * realError; return pControl; }

P 제어는 단순히 오차 * 계수에 해당됩니다.

I 제어 함수

unsigned int iControlSystem(void) { iControl = I_GAIN * (accError * TIME); return iControl; }

I 제어는 시작부터 지금까지의 오차를 기준으로하는 제어 방법입니다.

수학적으로 보면 다음과 같습니다.

그림02

여기서 realError을 누적한 값이 accError이고, dt는 TIME이니 위의 함수와 같은 수식이 나오게 됩니다.

D 제어 함수

unsigned int dControlSystem(void) { dControl = D_GAIN * (errorGap / TIME); return dControl; }

PID 제어 함수

unsigned int pidControlSystem(void) { pidControl = pControl + iControl + dControl; return pidControl; }

결과 영상

노란색 선은 목표값이고, 초록색은 현재값입니다.

50 RPM -> 100 RPM -> 150 RPM -> 200 RPM -> 250 RPM -> 300 RPM -> 0 RPM -> 50 RPM -> …

위의 순서를 따라 목표값을 바꾸면서 모터의 현재 속도가 어떻게 반응하는지 영상을 통해 알아봤습니다.

Continue

반응형

Top 31 Pid 제어 코드 Quick Answer

PID 제어, 파트 1: PID 제어란?

PID 제어, 파트 1: PID 제어란?

카테고리 이동

앤아버

이 블로그

공부방

카테고리 글

카테고리

이 블로그

공부방

카테고리 글

Read More

태그

관련글

댓글111

광고

공지사항

최근글

인기글

최근댓글

태그

전체 방문자

티스토리툴바

Read More

Read More

Read More

Read More

프로토타이핑 – 12 아두이노 PID 튜토리얼 + PID제어기(wiki)

티스토리툴바

Read More

관련글

서론

PID 제어

결과 영상

Continue

태그

stm32실전 Related Posts

티스토리툴바

Read More

See also

See also Top 28 피자 굽는 치킨 마을 Top 11 Best Answers

우선 Input값을 쉽게 바꿔주기 위해 가변저항 연결

화질이 별로지만 위의 궁금증 해결

태그

관련글

댓글0

공지사항

최근글

인기글

최근댓글

티스토리툴바

Read More

2015년 9월 4일 금요일

프로필

추천 게시물

Daddy Makers

전체 페이지뷰

팔로어

구독

블로그 보관함

태그

가장 많이 본 글

Read More

See more articles in the same category here: Chewathai27.com/to/blog.

지난 포스팅에서 PID의 원리가 뭔지, 대체 왜 필요한지에 대해 구구절절 설명했다.

따라서 이번 포스팅에서는 사실 가장 중요한? 아두이노 코드에 대해 쓰려고 한다.

서술하기에 앞서, 아두이노라는 녀석이 어떻게 동작하는지 알 필요가 있다. 이미 C언어를 어느정도 아는 사람이라면 척보면 다 알지만, 코딩을 처음 해보는 사람들에게는 매우 생소할 것이므로!

처음 C를 배우는 사람도 할 수 있게끔 설명하고자 한다.

1. 아두이노 코딩을 위해 반드시 알아야할 팩트들

아두이노 IDE를 먼저 받아야하는데, 그건 지난 포스팅에 있으므로!

오늘은 바로 코딩을 보도록 하겠다.

아두이노 IDE를 실행시키면 다음과 같은 문구들이 뜬다.

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

void가 뭔지, setup은 뭔지, loop는 뭔지 ()는 뭐고 {}는 뭔지. 아마 처음하는 사람이라면 아무것도 모를 것이다. 그런데 모든 걸 다 알아야 코딩을 할 수 있는게 아니다. 코딩이 뭔가? 알고리즘아닌가? 결국 아두이노 드론을 만드는데 있어서 가장 중요한건 알고리즘이다!

C언어(컴퓨터 프로그래밍 언어)라는 건 결국 우리가 생각한 알고리즘을 언어적으로 풀어주는 데 필요할 뿐, 알고리즘 자체가 될 수는 없기 때문이다.

고로 알고리즘을 짜고, 그 알고리즘을 코딩으로 적용할 줄만 알면 된다. 물론 엄밀히 말하면 프로그래밍 언어에 대한 지식이 있어야 응답속도와 반응성 등과 같은 정밀한 곳에서 더 이점을 가질 수 있겠지만.. 흔히 만드는 아두이노 드론 정도는 딱히 몰라도 가능하다. 고로 시작해보자.

아두이노는 크게 2부분으로 나뉘어져 있다.

void setup, void loop 가 바로 그것이다.

먼저 셋업 부분은 뭘까?

void setup() {

// put your setup code here, to run once:

}

친절하게 아두이노에서 설명해주고 있다. PUT YOUR SETUP CODE HERE, TO RUN ONCE:

즉, 딱 한번만 실행될 코드를 setup 부분에 채워넣으라는 것이다.

void loop() {

// put your main code here, to run repeatedly:

}

다음은 루프 부분. PUT YOUR MAIN CODE HERE, TO RUN REPEATEDLY:

즉, 루프 안에 들어가 있는 코드는 리피트!! 반복된다. 아두이노에 업로드하는 순간부터 영원히 반복된다. loop 안에 있는 건 그냥 영원히~~~ 위에서부터 아래로 코드가 실행되게 되는 것이다. setup은 위에서부터 아래로 한차례 실행되고 마는 부분이고, loop는 영원히 계속 반복되면서 실행되게 된다.

따라서 PID를 코딩으로 한다면, 어떤 부분을 setup에 넣고 어떤 부분을 loop에 넣을지를 생각해야한다.

PID는 이전 포스팅에서 말했지만, P, I, D 제어를 각각 한 후 그 제어값을 모두 더하여 적용 하게 된다.

즉, P제어 + I제어 + D제어 = PID 제어값 이 되는 것이다.

그리고 PID는 오차와 관련된 개념이라고 했다. loop가 어느정도 주기를 갖고 계속 반복되면서 실행될텐데, 매번 실행될때마다 오차가 달라질 것이다. 따라서 loop안에는 매번 달라지는 오차를 가지고 P, I, D 제어값을 새롭게 갱신해주어야 할 필요가 있다.

프로그래밍언어에서는 변수라는 게 있다. 말그대로 변하는 수다. P, I, D 게인값들은 변하지 않는 상수로 지정되어야 하고 오차가 변수로 지정되어야 할 것이다. (꼭 그런건 아니지만 일반적으로!)

그런데 아두이노는 P, I, D 라는 개념이 없다. 아무것도 모른다. 고로 그게 뭔지, 미리 선언해줄 필요가 있다.

예를 들어, Kp, Ki, Kd를 각각 PID의 게인값이라고 생각해보자. 그리고 난 그 값에 각각 1.2, 2.5, 3.2을 지정해주고 싶다.

그렇다면 아래와 같이 선언해주면 된다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

자, 우측은 이해하기가 쉽다. Kp = 1.2 이런 부분은 직관적으로 와닿을 것이다. 그런데 좌측에 double은 뭔가?

아두이노는 우리가 선언하려는 숫자가 정수인지, 실수인지도 모른다. 그걸 우리가 말해주지 않으면 얘는 해석을 못한다. 1.2는 정수가 아니라 실수 영역에 있기 때문에 실수 변수를 얘기하는 double로 선언해주어야 한다. 정수 변수는 int 로 바꿔주면 된다.

자 이제 게인값들을 선언했으니, 오차도 선언해주도록 하자. 오차는 error 라고 하겠다. 오차는 정수보다는 실수인게 더 섬세하고 좋을 것 같으니 실수로 선언!

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

이 경우는 error에 특정 값을 넣지 않았다. 왜? 이건 변수니까 말이다. Kp, i, d는 상수로 고정시킬 것이기 때문에 저렇게 미리 선언해놓은 거고, error는 루프가 계속 반복실행됨에 따라 변하는 수이기 때문에 굳이 넣지 않았다. 저렇게 아무것도 넣지 않으면 초기값이 0으로 자동배정되는 걸로 알고 있다.

이제, 오차에 필요한 현재값과 목표값을 선언해보도록 하자.

목표값은 이전 포스팅에서 예를 든 것처럼, 10도라고 하고 desired_angle로 선언하겠다. 그리고 현재값은 mpu6050을 통해 추출한 각도값으로, 실제 코드는 있다고 가정하고 그 값은 current_angle 이라고 하겠다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

double desired_angle = 10; double current_angle;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

}

자, 이게 error을 정의할 필요가 있다. error는 오차이다. 즉, 목표값에서 현재값을 뺀 수치가 될 것이다. 그리고 이 오차는 매 순간순간 달라질 것이다. 드론이 첨엔 10도 오차가 있다가, 그 쪽으로 회전을 시작하면 9도 8도 … 1도 0도까지 점점 오차가 줄어들게 아닌가. 고로 매 순간순간 갱신해줘야하는 변수가 되는 것이다. 그렇다면? 당연히 loop안에서 선언되어야 한다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error;

double desired_angle = 10; double current_angle;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

}

처음에 넣은 current_angle갱신코드란? 이건 현재 각도값을 의미하는데, 현재 드론이 기울어진 각도값도 mpu6050의 연산에 의해 실시간으로 변화되어야만 한다. 따라서 loop안에 넣어준거고, 이 부분은 mpu6050에 관련된 코딩이 필요하기 때문에 생략하고 위와 같이 표시하였다.

자, 이제 오차인 error가 아두이노에서 선언되어 해석가능해졌으므로, 본격적으로 PID 제어를 시작해보자.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control = I_control + Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

error_previous = error;

}

이번엔 추가된 게 좀 많다. 먼저 loop안을 보면, P컨트롤, I컨트롤, D컨트롤, 그리고 error_previous, Time 등과 같은 새로운 변수들이 선언된 것을 알 수 있다.

고로 맨 윗부분에 선언해준 것이다. 특히 Time은 한 루프가 도는 데 걸리는 시간을 의미한다. 내가 만든 드론은 한 루프 도는데 걸리는 시간이 약 3~4ms기 때문에 0.004로 해준건데, 사실 꼭 이렇게 할 필요는 없다. 그냥 4로 해도되고 4000으로 해도되고. Time이 수식적으로 가지는 의미는 그냥 ‘상수’일 뿐이다. 따라서 아무렇게나 지정해줘도, 또 다른 상수인 Kd나 Ki로 커버할만한 수준이기만 하면 되는것이다.

쉽게 생각해서, 4 * 6이나, 3 * 8이나 똑같은 수 아닌가. 곱해서 똑같이 나오게 숫자를 조정할 수 있기 때문에 꼭 time을 주기로 맞춰줄 필요는 없다는 것이다.

그리고 가장 아래보면 error_previous = error라고 선언한 부분이 있다. 아두이노에서는 이럴 때 우측에 있는 녀석을 좌측값으로 저장하라고 해석한다.

즉, error_previous라는건 지금 루프가 아니라 바로 이 전에 루프가 실행될 때의 error값을 의미한다.

만약 처음 error가 3이라고 해보자. 그러면 loop는 위에서부터 아래로 실행될 것이므로 error_previous에도 3이 저장 될 것이다.

그리고 loop가 다시 돌았을 때, 갱신된 현재각도에 의해 오차인 error가 5가 되었다고 해보자. 그리고 D_control을 보면, Kd * (5 – 3) / 0.004 가 될 것이다.

즉 컨트롤 부분에서 계산할 때 바로 직전의 에러 값이 previous에 저장되는 것이다.

I_control 부분은, 기존 I_control 값에다가 추가로 I 제어를 통해 얻은 값을 더하라는 것이다. 이전 포스팅에서 I 제어의 역할이 오차를 누적시켜 최종적으로 오차를 0으로 보내는 데 있다고 했는데, 이와 같은 방법으로 ‘누적’ 시킨다.

다만 언어적으로 좀 더 편하게 쓸 수 있다.

I_control += Ki * error * Time

이렇게 +=라고 하면, 위와 똑같은 의미를 가진다. 그냥 언어적인 것이니까 외우고 사용하면 된다.

이제 다음으로 넘어가보자.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004; double PID_control;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly:

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control += Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

PID_control = P_control + I_control + D_control; PID_control = constrain(PID_control, 0, 255); analogWrite(6, PID_control);

error_previous = error;

}

PID_control이라는 변수를 또 만들었다. 말했듯이, PID제어값은 P, I, D 제어를 통해 나온 값들을 모두 더한 값이므로 그냥 더해준 것이다.

그 뒤에 나오는 constrain은, 아두이노에서 제공하는 함수이다.

저걸 쉽게 얘기하면, PID_control이라는 값이 0부터 255까지의 숫자 범위를 가지도록 제한하는 것이다.

예를들어 PID_control이 -100이라는 값이 되면, 0으로 저장이 되고, 1000이라는 값이 되면 255로 저장이 된다. 0과 255사이의 값은 그 값 그대로 저장된다.

이렇게 해주는 이유는, 그 뒤에 나오는 anaglogWrite이라는 함수가 0부터 255사이의 숫자만 받아들이기 때문이다.

analogWrite은 전압을 인가하는 함수로, 6번 핀에 0~255 사이에 해당하는 전압을 주라는 명령신호다. 0은 0V, 255는 5V를 주게 되는데

사실 실제 드론을 만들 때는 이 함수를 쓰지 않을 것이다. servo 라이브러리를 활용하여 다른 함수를 쓸 예정인데

이 포스팅의 목적은 아무튼 PID 제어 코드의 기본을 설명하는 것이기 때문에 그냥 그대로 가는걸로..

최종적으로 나온 PID_control 이라는 값이 가장 중요하다. 이게 PID 제어를 통해 구한 제어값이 되기 때문이다.

다음으로, 조금 보기좋게 코드를 정리하기 위해 다음과 같이 해보았다.

double Kp = 1.2; double Ki = 2.5; double Kd = 3.2; double error; double error_previous;

double desired_angle = 10; double current_angle;

double P_control, I_control, D_control; double Time = 0.004; double PID_control;

void setup() { // put your setup code here, to run once:

}

void loop() { // put your main code here, to run repeatedly: pidcontrol();

}

void pidcontrol() {

current_angle갱신 코드; error = desired_angle – current_angle;

P_control = Kp * error; I_control += Ki * error * Time; D_control = Kd * (error – error_previous) / Time;

PID_control = P_control + I_control + D_control; PID_control = constrain(PID_control, 0, 255); analogWrite(6, PID_control);

error_previous = error;

}

뭐가 달라졌나?

바로 void pidcontrol 이라는걸 만들었다는 데 있다. 이건 쉽게 말해, 그냥 그룹으로 묶어놓는거라고 보면 된다.

loop가 가장 중요한 부분인데, 위위처럼 loop안에 모든 코드를 작성하게 되면 보기가 매우 불편하다. 때문에 항목별로 묶어서 따로 이렇게 정리해놓는 것이다. loop안에는 pidcontrol() 이라고만 선언해주면, pidcontrol이라고 선언된 그룹이 실행되게 된다.

고로 위랑 위위는 똑같은 코드이다! 정리해서 보기가 더 수월할 뿐!

이게 전부다!

PID 제어는 이렇게 하면 된다. 시작할때 오차는 10도였겠지만 시간이 흐르면 0으로 점점 줄어들어 원하는 목표값에 도달할 것이다.

단, Kp, Ki, Kd라는 게인값을 잘 맞추었다면 말이다. 이전 포스팅에서 움짤을 하나 사용했었는데, 그것처럼 반응을 보일 것이다. 제대로 게인값을 맞추지 않으면 오차가 오히려 더 커질 수도 있다. 드론이라는 시스템에 맞춰 적당한 값을 맞춰주어야 하는데 이 부분은 실험을 통해서 검증할 수 있다.

아무튼 제어 코드는 이와 같다. 실제 드론을 날릴때는 이중 pid라고 하여, pid 제어를 겹으로 싸서 이중으로 만든 걸 쓸텐데 별로 어려울 건 없다. 똑같다! 그냥 겹으로 한번 싸주기면 하면 된다.

최종 코드는 계속 포스팅하면서 써가는 걸로.

*** 19.12 수정사항

안녕하세요.

많은 분들이 아두이노 코드를 요청하셔서 제작했던 코드를 아래 포스팅에 첨부하였습니다.

https://hyongdoc.tistory.com/270

Arduino uno, PID control, 아두이노 우노 PID 제어 라이브러리 활용

반응형

– PID (proportional integral derivative control) control

– PID 제어 라이브러리 다운

– PID 제어 코드 분석

PID (proportional integral derivative control) control

2020/09/20 – [정리, 공부해요/전기, 전자, 통신] – PID 제어 (Proportional Integral Derivative control) 원리/정리/튜닝

PID 제어에 관한 원리는 이전 포스팅에서 정리해 두었습니다.

PID 제어 라이브러리 다운

www.arduinolibraries.info/libraries/pid

PID 라이브러리 파일을 받을 수 있는 링크입니다.

혹은 아래에서 다운 받으시면 됩니다 🙂

PID-1.2.0.zip 0.01MB

내PC – 문서 – Arduino – libraries

아두이노 라이브러리 폴더에, 알집을 푸시면 됩니다.

(libraries 폴더 안에 PID-1.2.0, 압축파일 안의 폴더를 푸시면 됩니다.)

PID 제어 코드 분석

/******************************************************** * PID Basic Example * Reading analog input 0 to control analog PWM output 3 ********************************************************/ #include #define PIN_INPUT 0 #define PIN_OUTPUT 3 //Define Variables we’ll be connecting to double Setpoint, Input, Output; //Specify the links and initial tuning parameters double Kp=2, Ki=5, Kd=1; PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); void setup() { //initialize the variables we’re linked to Input = analogRead(PIN_INPUT); Setpoint = 100; //turn the PID on myPID.SetMode(AUTOMATIC); } void loop() { Input = analogRead(PIN_INPUT); myPID.Compute(); analogWrite(PIN_OUTPUT, Output); }

PID myPID(&Input ~~): 사용할 변수 설정

myPID.SetMode(AUTOMATIC): PID 세팅, PID모드 켜기

myPID.Compute(): 받은 Input을 Setpoint와 비교해서 Output값 계산

코드를 보고 궁금했던 부분:

1. Input 값과 Setpoint의 비교 비율

Input 들어온 값을 곧이 곧대로 Setpoint와 비교하는 라이브러리 코드인지,

아니면 인풋 값인 0 ~ 1023을 특정 비율로 줄이거나 늘려서 Setpoint 값과 비교하는 것인지

2. Input과 Setpoint의 어떤 차이에 따라 Output 값이 결정 되는지

이부분은 Kp, Ki, Kd의 값에 따라 달라질 것이라 판단됨

코드를 돌려보니 DIRECT 와 REVERSE 에 따라 변화 확인

3. 아웃풋 값은 0~255 범위인지

300×250

우선 Input값을 쉽게 바꿔주기 위해 가변저항 연결

int pin = A0; int val; void setup(){ Serial.begin(9600); pinMode(pin,INPUT); } void loop(){ val=analogRead(pin); Serial.println(val); delay(100); }

화질이 별로지만,, 위의 궁금증 해결

DIRECT: Input 값이 Setpoint를 넘어서면 그 값을 줄여 맞추기 위해 Output 출력

REVERSE: Input 값이 Setpoint 보다 낮아지면 그 값을 늘려 맞추기 위해 Output 출력

(저는 실험 셋업 온도가 특정 지점 이상으로 올라가지 못하게 쿨링을 해주는 것이 목적이기에 REVERSE를 사용합니다.)

Setpoint: 500, DIRECT

Input(가변저항 값)이 500을 넘는 근처부터 Output(제어값) 비례해서 상승. ~150정도까지 상승

Output 최대 255, Input값(시스템에서 센싱 값)이 Setpoint로 부터 100~200 차이만 나도 Output 출력은 최대가 됩니다.

Setpoint: 300, REVERSE

Setpoint인 300보다 낮아지는 순간부터 Output값 급상승, 255까지

REVERSE의 경우 (DIRECT는 반대로 Input이 내려 갔을 시 발생), Input 값이 Setpoint보다 높아지면, 값이 더 올라가던가 변하지 않아도 빠르게 Output 값이 0에 수렴함을 볼 수 있습니다.

마무리

위의 내용을 참고해서 코드를 짜시면, 간단히 PID 컨트롤을 할 수 있지 않을까 합니다.

물론, Kp/Ki/Kd 값은 자신의 시스템에 맞게 튜닝 하셔야 합니다 🙂

반응형

PID제어중에 P제어란?

안녕하세요 오늘은 PID제어중에 P제어에 대해 자세히 알아보겠습니다

P제어는 비례제어이고 CLOSE-LOOP 제어의 일종입니다/ CLOSE-LOOP제어란 지령치를 주고 그 지령치에 대한 피드백을 받은 다음에 그 피드백을 반영해서 지령치를 주는 것입니다.

예) 목표값이 500인 상태

입력값을 500을 줬는데 출력값이 300이나왔고 오차는 200입니다. (출력값은 예를든 상태, 오차 = 목표값-출력값)

그러면 다시 입력값 200을 줍니다

출력값이 300이였는데 입력값을 200줬으니 출력값이 500이 나왔고 목표값과 일치합니다

P제어(Proportional)로 해결한 상태이고 비례적입니다

이제 실제로 코드구현을 아두이노를 통해서 테스트를 해보겠습니다

테스트방법은 목표값을 설정해놓고 가변저항을 현재값이라고 봅니다

Colored By Color Scripter ™ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 double Kp = 5; //게인 double error_value; //에러값 double goal_value= 0; //목표값 double current_value; //입력값(현재값) double P_control; //지령값 int hardwareError_value; //가변저항 에러 void setup() { Serial.begin(9600); } void loop() { current_value = analogRead(A0); if (hardwareError_value==1023) //가변저항 돌릴때 노이즈 방지 { } else { Serial.print(goal_value); Serial.print( ” ” ); Serial.print(current_value); Serial.print( ” ” ); Serial.print(P_control); Serial.print( ” ” ); Serial.println(error_value); } error_value = goal_value -current_value; //에러값은 목표값에서 현재값을 뺀 값이다. P_control = Kp * error_value; delay(100); }

빨강 : 입력값(현재값 current_value) 파랑 : 목표값(goal_value) 주황 : 에러값(error_value) 초록 : 지령값(P_control)

위의 그래프를 보면 입력값에 따라서 오차값이 나오고 오차값에 따라서 P제어를 하는 모습입니다

여기서 Kp를 게인값이라고 하는데 게인값에 따라서 목표값에 도달하는 속도가 달라집니다

P_control = Kp * error_value;

위의 코드에서 Kp가 커진다면 P_control값도 커질 것입니다

Kp(P게인)값을 높이면 목표값에 도달하는 시간이 짧아집니다

그러나 값이 너무 크면 오버슈트가 발생하게 됩니다

그래서 튜닝을 통해서 Kp의 값을 적절하게 조절해야 합니다

위의 그래프를 보면 목표값이 있고 Kp의 값에 따라서 현재값이 달라지는걸 볼 수 있습니다

Kp의 값이 0.5로 가장 작을때 Reference에 도달하는 속도가 느립니다

그러나 Kp의 값이 1.6으로 가장 클때 Reference로 도달하는 시간이 짧고 오버슈팅이 생깁니다

Kp가 1.1일때는 오버슈팅이 적어졌고 도달시간도 적당해 보입니다

일반적으로 P제어만 사용하지않고 PI, PID등 다른 제어들과 같이 사용하는데 다른 제어들은 다음에 알아보겠습니다

P제어-현재

키워드에 대한 정보 pid 제어 코드

다음은 Bing에서 pid 제어 코드 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 아두이노 PID 모터 속도제어_[반지하공작실]

  • 아두이노
  • PID제어
  • 모터제어
  • PID컨트롤
  • PID control
  • 피드백제어

아두이노 #PID #모터 #속도제어_[반지하공작실]


YouTube에서 pid 제어 코드 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 아두이노 PID 모터 속도제어_[반지하공작실] | pid 제어 코드, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

Leave a Comment