당신은 주제를 찾고 있습니까 “아두 이노 pid 제어 – 아두이노 PID 모터 속도제어_[반지하공작실]“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: https://you.tfvp.org/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 반지하 공작실 이(가) 작성한 기사에는 조회수 13,549회 및 좋아요 146개 개의 좋아요가 있습니다.
–오차신호를 미분하여 제어신호를 만들어내는 미분제어를 비례제어에 병렬로 연결하여 사용하는 제어기법. 비례제어 부분과 미분제어를 함께 쓴다는 뜻에서 이 기법에 의한 제어기를 비례미분 제어기(proportional-derivative controller), 또는 PD제어기 라고 한다.
아두 이노 pid 제어 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 아두이노 PID 모터 속도제어_[반지하공작실] – 아두 이노 pid 제어 주제에 대한 세부정보를 참조하세요
아두이노에서 PID제어를 이용한 모터 속도제어입니다.
PID제어는 정말 많은 곳에 사용되는 피드백제어인데요.
인터넷을 찾아봐도 대부분 PID의 계념만 설명하지 소스를 보여주는
경우는 많이 없어서 이번에 PID소스와 함깨 PID제어에 대해서 분석
해보았습니다.
소스 링크
https://drive.google.com/file/d/1ygiDdquDE-rtVqrOWtJ-chiPgG0JfFQK/view?usp=sharing
아두 이노 pid 제어 주제에 대한 자세한 내용은 여기를 참조하세요.
프로토타이핑 – 12. 아두이노 PID 튜토리얼 + PID제어기(wiki)
1.1 비례 제어. 1.2 적분 제어. 1.3 미분 제어. 2. PID 제어 구현. 3. 아두이노 PID 라이브러리. 4. 마치면서. 1. PID란 무엇일까? PID는 비례, 적분, …
Source: throwexception.tistory.com
Date Published: 9/15/2022
View: 1167
8-2. Arduino Car로 PID 제어 – 킹포도의 코딩
PID Control을 사용하여 Arduino Car에 Cruise System을 구현하기 전에 PID Control이 무엇인지 알아보겠습니다. PID 제어는 실제 응용분야에서 많이 …
Source: kingpodo.tistory.com
Date Published: 6/3/2022
View: 8841
아두이노 프로젝트12 – PID 제어를 이용한 공 균형 잡기
PID 제어란 어떠한 기준값과 현재 얻어지는 값에 오차가 있을 때 P(Proportional, 비례), I((Proportional -Integral, 적분), D(Proportional-Derivative, …
Source: m.blog.naver.com
Date Published: 4/20/2021
View: 5336
드론 DIY | 아두이노 PID 제어 코드 (코드 첨부)
지난 포스팅에서 PID의 원리가 뭔지, 대체 왜 필요한지에 대해 구구절절 설명했다. 따라서 이번 포스팅에서는 사실 가장 중요한? 아두이노 코드에 …
Source: hyongdoc.tistory.com
Date Published: 6/24/2021
View: 3697
Arduino uno, PID control, 아두이노 우노 PID 제어 라이브러리 …
아두이노 라이브러리 폴더에, 알집을 푸시면 됩니다. (libraries 폴더 안에 PID-1.2.0, 압축파일 안의 폴더를 푸시면 됩니다.) PID 제어 코드 분석.
Source: setoo0922.tistory.com
Date Published: 10/7/2021
View: 8692
아두이노 드론과 PID 제어 – 찬찬히 로봇 메이커
드론의 제어법을 구글에서 여러번 찾아보았다. 기본은 PID제어를 사용하였고 여기에 추가적으로 P제어를 두번한 PPID(?)제어라던가 D제어를 두번한 PIDD …
Source: sally241.tistory.com
Date Published: 4/3/2022
View: 1434
DC Mouse 3. 아두이노 DC 모터 PID 제어
아두이노 나노로 모터 2개의 엔코더 입력에 문제없음을 확인함 (DC Mouse 2 참조). PID 제어를 구현해본다. 마이크로 마우스에서 직진과 회전 구간을 …
Source: maxpulse.tistory.com
Date Published: 1/22/2022
View: 7235
주제와 관련된 이미지 아두 이노 pid 제어
주제와 관련된 더 많은 사진을 참조하십시오 아두이노 PID 모터 속도제어_[반지하공작실]. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 아두 이노 pid 제어
- Author: 반지하 공작실
- Views: 조회수 13,549회
- Likes: 좋아요 146개
- Date Published: 2019. 5. 28.
- Video Url link: https://www.youtube.com/watch?v=HtTbnWNpPiw
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 )가 된다.
프로토타이핑 – 12. 아두이노 PID 튜토리얼 + PID제어기(wiki)
728×90
https://ko.m.wikipedia.org/wiki/PID_%EC%A0%9C%EC%96%B4%EA%B8%B0
제어 시스템에서 제어기는 시스템의 출력이 목표 입력값이 되도록 고쳐나가야 합니다. 가장 유명한 제어기중 하나는 PID 제어기로 비례, 적분, 미분의 약어라고 할수 있습니다. 이번에는 아두이노 PID 튜토리얼에 대해서 살펴보면서 이 프로젝트에 제어기가 어떻게 사용되는지 알아봅시다.
앞으로 볼 내용은 아래와 같겠습니다.
1. PID가 뭘까?
1.1 비례 제어
1.2 적분 제어
1.3 미분 제어
2. PID 제어 구현
3. 아두이노 PID 라이브러리
4. 마치면서
1. PID란 무엇일까?
PID는 비례, 적분, 미분의 줄임말이라고 할수 있습니다. 또한 시스템에서 제어기가 요란을 대처하는 방법이라고도 할수 있는데요. 여기서 말하는 제어기는 피드백 시스템에 존재하는 제어기를 말합니다. 그래서 특정 수치값을 읽고 내가 할수있는 일을 하는거라고 할수 있겠습니다.
피드벡 시스템은 출력 결과를 입력으로 되돌려주는 시스템이라고 할수 있는데요. 난로의 불을 제어하는 예제로 한번 배워보겠습니다. 간단한 그림은 아래와 같아요.
여러분들이 일정 온도를 유지하고 싶으면, 센서는 매 시간마다 온도를 측정해주고, 이 측정한 온도가 희망 기준 온도에서 증가하거나 감소했을탠대 이 차이를 오차로 피드백하게 해줍니다.
1.1 비례 제어 Proportional Control
비례 제어는 에러를 얼마나 많이 비례해서 제어할수 있는지를 말하고 있습니다. 예를들자면 위 난로에서 연료를 조절하는 전기 밸브가 있다고 합시다. 오차가 작다면, 설정 값과 측정 값이 일치하도록 밸브는 작은 양의 연료를 줄것이고, 오차가 크다면 벨브로 더 많은 연료를 줄겁니다.
=> 현재 상태에서 오차 값 크기에 비례하여 제어(원하는 값에 빨리 도달)
– 좌측은 제어이전, 우측은 P 제어 이후
=> 제어 이전에는 출력이 목표 값(1)에 도달하지 못함
=> P 제어 이후 오차 값(목표 값 – 현재 값)만큼 비례해서 신호를 증폭한다.
1.2 적분 제어 Integral Control
비례제어가 요란을 제거해 주었다면, 적분 제어는 이 오프셋 오차를 제거해서 에러를 0으로 만들어줍니다. 제어기는 시간에 대해 오차가 누적되므로 적분 제어기 없이는 오차에 제대로 대응할수 없습니다.
이전의 예시 계속 보면 연료 출력이 증가하거나 감소한 이후에도 초기 위치가 아닌 지점에서 가만히 있게 됩니다. 적분 제어는 이를 감지해서 연료 밸브를 기존의 자리로 돌려주는 역활을 하겠습니다.
=> 정상상태 오차를 제거(누적된 오차로 인해 원하는 값에 수렴하지 못하는 부분을 제거)
– 좌측은 비례제어만 한 결과, 우측은 PI 제어 결과
=> 비례제어만 한 경우 존재하는 정상상태 오차를 적분 제어를 통해 제거함
=> 하지만 오버슛이 심각해짐
1.3 미분 제어 Derivative Control
마지막으로 미분 졔어는 오차의 변화율을 조절시킵니다. 만약 적분 제어에 누적 오차가 보이는 경우에 미분 제어가 이 오차를 예측하여 얼마나 오차가 빠르게 변하는지를 보고 얼마나 고쳐야 할지 찾아냅다. 비례 제어와 적분 제어가 대처하지 못하는 동역학적 에러에 대해서 최적의 동작을 한다고 할수 있겠습니다.
위 난로 예제에서 120도를 설정했지만 130도에서 140도로 올라가는 상황이라고 해봅시다. 비례적분 제어기는 오차의 크기에 대응해서 동작하고는 있지만, 오차가 빠르게 발생하는 경우에서는 대처하기가 어려우나 미분 제어기는 오치의 변화율을 보고 이에 맞게 조절할수가 있습니다.
– 좌측은 PI 제어기, 우측은 PID 제어기
=> 기존의 출력갑이 크게 변하는데 미분 제어를 통해 오버슛을 줄이고 안정하게 만든다
– PID는 위와 같은 형태로 사용하기도 되지만 P 제어기, PI 제어기, PD 제어기만 사용하는 경우도 있음
– PID 제어시 발생가능한 문제
1) 계산된 제어값이 구동기가 동작할수 있는 한계 보다 커 구동기 포화(sturation)이 발생하는 경우
2) 오차 적분값이 크게 누적되어 출력이 설정에 가까워지면 제어가 작아져야하나 큰 값을 출력하여
설정값에 도달하는데 많은 시간이 걸리는 경우
-> 위 문제를 적분기의 와이드업이라 함 => 안티 와이드업 기법으로 PID 제어기를 보완해주어야함
– 제어 파라미터 K_p, K_i, K_d를 제어 이득, 게인이라 부름. 적절한 이득값을 얻는 과정을 튜닝(tunning)이라고 함.
https://ko.m.wikipedia.org/wiki/PID_%EC%A0%9C%EC%96%B4%EA%B8%B0
다시 돌아와서
설정 입력값 r(t)가 있고, 출력으로 y(t), 제어 입력 u(t). 오차 e(t)가 있겠습니다. 위 난로 예제에서 보면 r(t)는 희망 온도, y(t)는 실제 온도라 할수 있습니다. e(t)는 실제 온도와 희망 온도의 차이라할수있고, u(t)는 PID 제어기로 교정한 신호의 총합이라 할수 있겠습니다.
원하는 성능을 얻을수 있또록 PID 제어기의 값들을 고치는 작업을 튜닝이라 부르며, 위 그림에서 K 상수들을 잘 조절해주어야 합니다.
코드로 PID 제어하기
아두이노 스캐치에서 PID 제어기를 구현하려면 5개의 파라미터가 필요합니다
-> 비례, 적분, 미분 상수와 입력값과 기준 설정 값
PID 계산은 반드시 내부 루프 함수에 있어야하며, 함수 시작시에는 수행 시간 (elapsed time)을 설정해주어야 합니다. 현재 시간은 millis()로 얻겠습니다.
currentTime = millis(); elapsedTime = currentTime – previousTime;
오차는 설정 지점과 입력의 차이로 얻겠습니다.
error = setPoint – input;
적분 오차는 시간에 대한 누적 오차라 하였으니 아두이노로 구현하려면 다음과 같이 경과시간 * 오차를 해주면 되겠습니다.
cumError += error * elapsedTime;
미분 오차는 에러의 변화율이므로 다음과 같이 하겠습니다.
rateError = (error – lastError)/elapsedTime;
이제 제어 입력 u(t)를 정리하면 아래와 같겠습니다. 여기서 Kp, Ki, Kd는 이전에 설정한 상수가 됩니다.
output = Kp * error + Ki * cumError + Kd * rateError;
마지막으로 다음 반복회차를 위해서 변수들을 아래와 같이 지정해줍시다.
lastError = error; previousTime = currentTime;
이제 조금 더 제대로 해보면, 다음과같은 휠이 달린 모터가 있다고 해봅시다. 우리는 휠이 저 위치에 있기를 바라고 있습니다. 바퀴에 로터리 엔코더가 재 바퀴 각도에 대한 정보를 알려주므로 우리가 바라는 지점에서의 각도를 0이라 합시다.
휠이 위치를 벗어날떄마다 조정을 해주어야 하는데, 보통 모터는 PWM 펄스 폭 변조를 통해 제어됩니다. 펄스가 넓을수록 모터 회전이 더 빨라집니다.
이제 아두이노에서 다음과 같이 간단한 제어 예시를 구현해봅시다.
//PID constants double kp = 2 double ki = 5 double kd = 1 unsigned long currentTime, previousTime; double elapsedTime; double error; double lastError; double input, output, setPoint; double cumError, rateError; void setup(){ setPoint = 0; //set point at zero degrees } void loop(){ input = analogRead(A0); //read from rotary encoder connected to A0 output = computePID(input); delay(100); analogWrite(3, output); //control the motor based on PID value } double computePID(double inp){ currentTime = millis(); //get current time elapsedTime = (double)(currentTime – previousTime); //compute time elapsed from previous computation error = Setpoint – inp; // determine error cumError += error * elapsedTime; // compute integral rateError = (error – lastError)/elapsedTime; // compute derivative double out = kp*error + ki*cumError + kd*rateError; //PID output lastError = error; //remember current error previousTime = currentTime; //remember current time return out; //have function return the PID output }
위 루프 함수에서는 로터리 엔코더가 휠의 현재 위치를 주고, 그 값이 commputePID()함수의 파라미터로 사용됩니다. 이 함수는 PWM으로 모터 제어에 사용할 값을 반환해 줍니다.
300×250
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 시스템을 구현해보겠습니다.
반응형
아두이노 프로젝트12 – PID 제어를 이용한 공 균형 잡기
안녕하세요. 오랜만에 아두이노 포스팅을 합니다. 이제 ‘아두이노 작품’이라는 타이틀을 버리고 ‘아두이노 프로젝트’라는 이름을 쓰게 되었습니다.
‘작품’이라고 국어사전에 검색해보니 ‘예술 창작 활동으로 얻어지는 제작물’이라는 뜻이 나옵니다. 하지만 저는 아무래도 예술 활동보다는 프로그래밍과 여러 전기, 전자 부품을 제어하는 활동을 하니 이러한 표현이 어울리지 않는다고 생각하였습니다. 더구나 제가 매 포스팅마다 새로운 분야의 활동을 광범위하게 하니 이러한 활동은 ‘프로젝트’라는 말이 어울릴 것 같습니다. 앞으로는 이러한 제목을 사용할 것입니다.
사족이 길었네요. 이번에 진행한 저의 프로젝트는 ‘PID 제어를 이용한 공 균형 잡기’입니다. 이 프로젝트는 아래 사이트를 참고하여 진행하게 되었습니다.
준비물은 아두이노 우노, 브레드보드, 점퍼선, 가변 저항, 초음파 센서(HC-SR04), 서보 모터(SG-90), 과학상자, 폼보드입니다. 과학상자 대신 아무 프레임을 만들 수 있는 기구도 괜찮습니다. 폼보드 대신 하드보드지나 우드락도 괜찮을 것 같네요.
모델 사진입니다.
fritzing 회로도 사진입니다.
PID 제어란 어떠한 기준값과 현재 얻어지는 값에 오차가 있을 때 P(Proportional, 비례), I((Proportional -Integral, 적분), D(Proportional-Derivative, 미분) 제어를 이용하여 오차값을 줄여나가도록 제어하는 방법입니다.
▲ Kp값이 클수록 반응 속도가 빨라진다.
P 제어는 기준값과 현재값의 오차에 어떠한 비례 상수(Kp)를 곱하여 오차 값을 줄여나가는 방식입니다. 즉 기준값과 현재값의 오차에 비례하여 제어량을 변화시키는 것입니다. 하지만 오차값은 0이 되지 않고 기준값에 한없이 다가가는 형태로 나타나게 됩니다. 위 그래프는 Kp 값에 따른 P 제어를 나타낸 것입니다. 이번 프로젝트에서 도출하였습니다.
▲ Ki값이 클수록 P 제어와 더불어 반응 속도가 빨라진다.
I 제어는 P 제어의 한계를 보완한 제어입니다. P 제어를 통해서는 오차를 0으로 만들 수 없기 때문에 그 오차를 시간으로 적분하여 오차값을 0으로 만들 수 있도록 해줍니다. 이 역시 상수 Ki가 들어가게 되는데, Ki값이 증가할수록 더욱 민감하게 반응하는 성질을 갖고 있습니다. 위 그래프는 Ki 값에 따른 P, I, D제어를 동시에 수행할 때를 나타낸 것입니다.
▲ Kd값이 클수록 그래프의 꺽은 선이 많아진다. 즉 급격한 변화에 대응한다.
D 제어는 외부 변화에 쉽게 대응하기 위한 제어입니다. 오차가 갑자기 증가(오버슈트)하거나 기준값이 변화할 경우 이에 반응해서 값을 변화시켜야 합니다. 이 때 이 변화의 기울기를 미분을 통해 얻음으로서 이러한 제어를 쉽게 수행할 수 있도록 합니다. 이 역시 상수 Kd가 들어가는데, Kd가 커질수록 현재 상태를 쉽게 변화하려 하지 않는 성질이 있습니다. 위 그래프는 기준값이 변화했을 때 P, I, D제어를 이용하여 오차를 감소시키는 것을 나타내었습니다.
즉 정리하자면 P 제어는 오차값을 줄이면서 기준값까지 도달 시간을 줄이는 역할, I 제어는 P 제어의 한계에 의한 오차를 줄이는 역할, D 제어는 급격한 변화에 대응하는 역할이라 할 수 있습니다.
다음은 아두이노 프로그래밍 코드입니다. PID 라이브러리를 따로 사용하였습니다. 이 라이브러리는 첨부파일에 올려놓았습니다. 압축을 푼 후 Arduino→Libraries 폴더에 저장하시면 됩니다.
#include
#include
//PID, 서보모터 라이브러리 const int servoPin = 9;
const int echoPin = 6;
const int trigPin = 7;
const int sensor = A0; //핀 설정
float Kp = 2.0;
float Ki = 1.0;
float Kd = 2.0; //PID 상수 설정, 실험에 따라 달라짐, 중요! double Setpoint, Input, Output, ServoOutput; //PID 제어 변수
float duration, distance1, distance2; //거리 측정 변수
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); //PID 객체 생성
Servo myServo; //서보 객체 생성
void setup() {
Serial.begin(9600); //시리얼 통신 사용 myServo.attach(servoPin);
myServo.write(115); //슬로프가 평형을 이루는 각도 : 115도
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(sensor, INPUT); //입력, 출력 핀
myPID.SetMode(AUTOMATIC); //PID모드를 AUTOMATIC으로 설정
myPID.SetOutputLimits(-50,55); //PID의 값을 최소 -50부터 최대 55까지 설정 }
void loop() {
Setpoint = map(analogRead(sensor), 0, 1023, 5, 40); //가변저항 범위를 슬로프의 길이 범위로 변경
Input = errorCollection(); //오차값 보정한 초음파 센서의 거리 수치를 저장
Serial.print(Input);
Serial.print(“,”);
Serial.println(Setpoint); //시리얼 출력
myPID.Compute(); //PID계산
ServoOutput=115-Output; //서보모터의 각도 설정(115도는 서보모터가 수평을 이루었을 때 각도)
myServo.write(ServoOutput); //서보모터에게 값 전달
}
float readPosition() { //초음파 센서 거리 측정
digitalWrite(trigPin, HIGH);
delayMicroseconds(2);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
float a = ((float)(340 * duration) / 10000) / 2;
return a;
}
float errorCollection() { //초음파 센서로 측정한 값 오차 보정
delay(40);
float distance;
distance2=readPosition(); //distance2에 거리값 저장 if (distance2-distance1>45) { //차가 45보다 크다면, 즉 값이 갑자기 튄다면
distance=distance1; //바로 전 측정한 거리값 사용
} else { //일반적인 경우이면
distance=distance2; //지금 측정한 값을 사용
distance1=distance2; //다음 측정값과 비교하기 위해 저장
}
if (distance>45) { //슬로프 길이가 45cm이므로 45cm보다 더 큰 값이 반환되면 오류
distance=45;
}
return distance; //distance 리턴
}
아무래도 탁구공을 사용하다보니까 초음파 센서가 공을 잘 인식하지 못하는 것 같습니다. 공이 조금만 멀리 가도 값이 이리저리 튀는 현상이 발생해서 오차를 보정하는 코드를 따로 만들었습니다. 비정상적인 값이 인식될 경우 바로 전에 받은 값을 다시 출력하는 방식으로 오차를 한결 줄일 수 있었습니다.
마지막으로 동영상입니다.
드론 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
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 제어
반응형
사실 드론의 하드웨어도 중요하지만(모든 로봇들이 그러하듯) 더욱 중요한 것은 제어법이라고 생각한다.
드론의 제어법을 구글에서 여러번 찾아보았다. 기본은 PID제어를 사용하였고 여기에 추가적으로 P제어를 두번한 PPID(?)제어라던가 D제어를 두번한 PIDD(?)제어를 사용한 사람도 있었다. PPAP제어도?…
우리는 여러 게시물을 찾아보고, 선배들에게도 물어본 결과 그냥 기본적인 PID제어를 사용하기로 하였다. 기본적으로는 PID를 사용하고, 상황에 따라서 다른 것을 추가한다고 한다.
일단 PID제어가 무엇인지 찾아보면,
P제어, I제어, D제어를 계산한 뒤, 그것을 합쳐서 출력을 주는 것을 말한다.
P제어는 Proportional control로써 한글말로 하면 비례제어이다. I제어는 Integral control로써 적분 제어이고, D제어는 Derivative control로써 미분 제어이다.
이것이 왜 필요한가 하면, 그냥 ON/OFF제어를 하면 원하는 값에 다가가기가 쉽지 않다.
예를 들면, 속도를 기준으로 제어를 한다고 했을 때, ON을 액셀을 최대로 밟는 것(또는 어느 기준으로 밟는 것도 상관 없다), OFF를 얙셀을 떼는 것으로 할 수 있다. 그러면 시속 100km로 달리고 싶다고 할 때, 100km까지는 액셀을 밟을 것이다. 그러다가 100이 넘어 101km가 되면 액셀을 뗄 것이다. 그러면 그 전까지 밟는 힘이 값자기 사라지지 않으므로 한 103km까지는 갈 것이다. 그러다가 힘이 떨어져서 100km를 지나쳐 97까지 떨어지고… 이것의 반복이다.
하지만 PID는 정확히 100km를 유지하려고 한다. 왜 이런지 식을 통해 알아보면,
일단 식은 아래와 같다.
PIDoutput =
Kp*e(t)+Ki*(integral)e(t)+Kd*(derivative)*e(t)
하나씩 보면
P제어는 오차 곱하기 Kp값이다. 이때 오차는 현재값과 목표값의 차이다. 위의 식에서는 그것을 error라고 해서 e(t)로 쓰여졌다. 다시 쓰면 ,
P제어 = (목표값-현재값) * Kp 이다.
사실 PID제어에서도 제일 중요한게 P제어이고, Kp값이라고 생각한다. Kp값만 잘 맞춰도 제어의 80퍼센트는 되기 때문이다. 그러면 정확히 어떻게 해야 드론을 제어할 수 있을까? 사실 정답은 잘 모르지만 우리가 한 방법을 소개한다(이 방법은 경험과 지식과 나의 생각이 합쳐져있다).
일단 현재값은 자이로센서가 받는 현재의 각도이다. x축을 기준으로 한다고 하자. 그래서 드론이 그냥 바닥에 놓여있다면 각도는 0도 일테고, 왼쪽으로 기울이면 음의 몇도, 오른쪽으로 기울이면 양의 몇도 이렇게 나올 것이다.
내가 수평을 유지하려고 한다면 목표값은 0이 될 것이다. 그러면 거기에 Kp값을 곱한 값이 P제어값이 될테고 그 값으로 pwm값으로 바꿔준다. 그러면 모터에 그만한 힘이 전해지면서 제어가 된다.(모터에 대한 제어는 다음 포스팅에 올릴 예정이다.)
그러면 Kp값은 어떻게 구하는가? 아마 대부분의 일반적인 사람들은 노가다로 구할 것이다. Kp값에 1을 대입해보고, 2를 대입해보고, 3을 대입해보고… 3정도가 맞는 것 같다라고 하면 거기서 0.1단위로 해보고… 아마 그런식으로 Kp값을 찾을 것이다.
아마 나머지는 매트랩이나 수학적인 계산으로 Kp값을 구할 것이다. 어떨 때 어느정도 힘을 줘야하므로 Kp값이 어느정도면 pwm이 몇정도가 나오고, 그러면 최대 힘의 몇퍼센트이므로 일부 저항 등을 제외하고 고려하면 몇정도가 적당한 값이겠구나 하고 구할 것이다.
나는 아직 아무것도 모르는 어린이이기 때문에 노가다로 구했다. 하지만 중요한 점은 PID 제어를 해보고 게인값을 한 번 구해본 사람과 처음 하는 사람은 확실히 다르다는 점이다. 아무래도 노가다로 구하는 방법은 해본 사람이 확실히 잘한다. 아마 드론에서 처음 PID제어를 하는 사람이라면, 그리고 노가다로 게인값을 구하는 사람이라면 정확한 값을 찾는데 몇 주정도 예상하는 것이 나을 것이다(사실 이게 제어의 전부이기도 하다).
일단 Kp값을 맞추면 드론이 어느정도 중심을 잡으려고 할 것이다. 아마 발산(드론이 오른쪽으로 갔다 왼쪽으로 갔다 하면서 점점 더 오차가 커질 때)하기 바로 전까지 맞추는 게 이상적이라고 생각한다. 그러면 Kp값은 맞춘 것이다. 그런 후에 D제어를 한다.
D제어는 미분제어로, D제어 =(오차의 시간에 대한 미분제어) * Kd 이다. 식으로 쓰면, D = ((e-e0)/t) * Kd(e0는 바로 전 오차, e는 현재 오차, t는 두 오차의 측정 시각 사이의 시간이다.)이다. 즉 위의 그래프에서 빨간색 선이 현재값이라고 하면, 빨간색 그래프의 어느 한 점에서의 기울기라고 할 수 있다.
‘이 제어를 왜 할까’라고 생각을 한다면, 이 제어는 빠른 반응속도 때문에 사용한다고 답할 수 있다. 드론이 날라갈 때, 외력이 작용하지 않는다면 참으로 좋겠지만, 외력은 작용한다. 낮게 떠있을 때에는 바닥과 부딪친 바람이, 높게 떠있을 때에는 바람이 불며 드론에게 외력을 가한다. 그럴때마다, 드론은 빠르게 제 자리를 찾아야 하는데 그 역할을 D제어가 해준다.
쉽게 정리하면, P제어는 오차값이 커져야 힘을 많이 주게 된다. 하지만 D제어는 순간변화율(기울기)에 따라 힘을 주기 때문에 로봇이 순간적으로 변했을 때, 순간적으로 많은 힘을 주어 제 자리를 찾을 수 있게 도와준다.
Kd값을 찾는 방법은 Kp를 찾는 방법과 마찬가지로 시소테스트를 하면서 직접 드론에 외력을 주면서 찾는다. 드론이 왔다갔다하면서 수평을 맞출텐데, Kp값을 맞추고, Kd값을 맞추면 한 번이나 두 번 만에 수평으로 돌아와서 멈춰야한다.
P제어를 한 뒤, P제어값과 D제어값을 합쳐서 pwm에 반영한다.
마지막으로 I제어인데, 사실 인터넷에 찾아봤을 때에는 P제어를 한 뒤에 I제어를 하라고 나와있다. 하지만 나는 개인적으로 I제어가 큰 비중을 차지하지 않는다고 생각이 되어 PD제어를 위주로 하고 I제어를 나중에 하였다. I제어 = (오차들의 합) * Ki이다. 생각해보면 I제어가 있는 이유가, P제어는 오차값이 작을 때, 값이 너무 작아 목표값에 도달할 힘을 내지 못하게 된다. D제어 또한 변화율에 대한 힘이므로 힘이 거의 없을 것이다. 이렇게 기울어져있을 때, 그 작은 오차들을 적분값으로 합해서 힘을 주는 것이 I제어이다.
I제어가 완벽히 되면, P제어만 하면 목표값에 완벽히 도달을 못하고 약간 기울어져있을텐데, 그 기울어짐을 잡아줄 수 있다.
I제어까지 합쳐서 pwm에 반영하면, 완벽한 PID제어가 된다.
경험까지 덧붙여 설명하느라 길어졌지만 PID를 좀 더 정확히 설명하고 싶었다. 다음 포스팅에서는 BLDC의 제어법과 시소테스트, PID제어의 팁 등을 올릴 예정이다.
※혹시 틀린 것, 알려주고 싶은 내용, 궁금한 점은 댓글로 달아주세요 ^^.
반응형
DC Mouse 3. 아두이노 DC 모터 PID 제어
아두이노 나노로 모터 2개의 엔코더 입력에 문제없음을 확인함 (DC Mouse 2 참조)
PID 제어를 구현해본다
마이크로 마우스에서 직진과 회전 구간을 구분해서 동작하는데
직진 구간에서는 벽에 부딪히지 않도록 양쪽 바퀴의 속도 제어를 하면서 움직이고,
회전 구간에서는 정확한 각도만큼 회전할 수 있도록 모터의 각도 제어를 해야 한다.
1. 속도 제어
PID는 에러를 측정하고, 그 에러의 양 자체(P), 에러의 누적량(I), 에러의 변화량(D)을 이용해서 제어하는 것
따라서 무엇을 에러로 정할 것인지가 중요하다.
속도 제어를 할 때는 당연히 에러는 속도가 된다.
속도 측정 방법은 예전 글 참조 -> https://maxpulse.tistory.com/148
모터의 속도와 타이머 설정에 따라 M, T, M/T method 등을 사용해야 하는데…
내 모터의 경우 바퀴가 한 바퀴 회전할 때 4200 펄스이고, 초당 3~4바퀴 이하로 회전하므로 초당 10000 펄스 정도
그러면 10ms 한 번씩 측정하면 100 펄스 안팎일 것이므로 쉽게 M Method를 사용하기로 한다.
속도 측정 후 목표 속도와 비교하여 P, I, D 게인을 적용하면 된다.
void motorPID(){ //10ms마다 호출 speedActualLeft = (leftMotorEncoder – leftMotorEncoderPrevPID)*60*(1000/LOOPTIME)/4200; //속도를 RPM으로 측정하는 코드 : Encoder의 현재값에서 이전값을 뺀후, 측정 시간으로 나누고 Pulse 수 등을 사용해서 RPM 으로 변환한다. LOOPTIME이 PID 제어가 동작하는 주기이다 (나의 경우는 10ms) leftMotorEncoderPrevPID = leftMotorEncoder; //현재 엔코더 값을 다음에 사용하도록 저장
error = (speedRequestLeft) – (speedActualLeft); //에러량을 계산
iTermLeft += (Ki * error); //I 항의 경우 누적해야 하므로 별도로 저장
pidTerm = (Kp * error) + (Kd * (error – lastErrorLeft)) + iTermLeft; //전체 PID 값을 계산
lastErrorLeft = error; //현재 에러 값을 다음에 사용하도록 저장
leftControl = constrain(abs(pidTerm), 0, 255) * ((pidTerm <0)?-1:1); //PID 텀을 모터 제어에 사용되는 값의 범위인 0~255의 값으로 변환하는 함수 LeftMotor_PID( (leftControl>=0)? 1:0, abs(leftControl)); //실제 모터의 PWM 값으로 출력하는 함수 }
2. 각도 제어
에러를 각도로 사용하는 것 말고는 속도 제어 소스와 동일함
void motorPID(){ //10ms마다 호출 double ErrorAngle;
ErrorAngle = (leftMotorEncoderTarget – leftMotorEncoder)*ratio; //엔코더의 차이를 계산한 뒤 ratio를 이용하여 각도 값으로 변경
iTermLeft += (KiAngle * ErrorAngle);
pidTerm = KpAngle * ErrorAngle + iTermLeft + KdAngle*(ErrorAngle – lastErrorDegreeLeft);
lastErrorDegreeLeft = ErrorAngle;
leftControl = constrain(abs(pidTerm), 0, NormalSpeed) * ((pidTerm <0)?-1:1); LeftMotor_PID( (leftControl>=0)? 1:0, abs(leftControl)); }
* 아래 소스들은 P나 PD제어만 적용한 소스이므로 I 나 D는 위의 내용 참고해서 추가하면 됨
(어차피 PID 게인은 각자 맞춰야 함)
속도 제어 소스
DC_Motor_Test_P_Control_Speed.ino 0.00MB
각도 제어 소스
DC_Motor_Test_P_Control_Angle.ino 0.00MB
키워드에 대한 정보 아두 이노 pid 제어
다음은 Bing에서 아두 이노 pid 제어 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 아두이노 PID 모터 속도제어_[반지하공작실]
- 아두이노
- PID제어
- 모터제어
- PID컨트롤
- PID control
- 피드백제어
아두이노 #PID #모터 #속도제어_[반지하공작실]
YouTube에서 아두 이노 pid 제어 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 아두이노 PID 모터 속도제어_[반지하공작실] | 아두 이노 pid 제어, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.