산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

부품 및 소모품

부품수량비고
아두이노 나노 R3 (Arduino Nano R3)1
스파크펀 레드봇 라인 팔로워 센서1
TCRT5000 4채널 적외선 라인 트래커 센서 모듈1
HC-06 블루투스 모듈1안드로이드 연동용
안드로이드 기기1파라미터 튜닝용
4xAA 배터리 홀더2모터용, 로직용 각각 1세트
연속 회전 서보 (RobotGeek SM-S4303R)2좌/우 바퀴 구동용

앱 및 온라인 서비스

프로젝트 소개

이 프로젝트의 목적은 PID 제어를 사용하는 라인 팔로워 로봇을 만드는 것입니다. 또한 안드로이드 기기를 이용해 주요 제어 파라미터를 쉽게 설정하고 빠르게 튜닝할 수 있게 합니다.

이 프로젝트는 라인 팔로워 로봇의 잠재성을 탐구하는 2부작 프로젝트의 첫 번째 파트입니다. 2부에서는 미로 해결 로봇(Maze Solver Robot)을 아두이노와 간단한 인공지능 기법으로 구현할 예정입니다.

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

1단계: 자재 목록 (BOM)

필요한 자재는 매우 단순하며 최종 로봇 비용은 약 $75(약 10만 원) 수준으로 저렴합니다:

2단계: 모터 설정

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇
PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

모터로 2개의 연속 회전 서보(SM-S4303R)를 사용했습니다. 3M 커맨드 스트립, 글루, 양면 테이프 등으로 단단하게 결합해 하나의 블록처럼 만듭니다. 이 서보들은 데이터 입력으로 받는 펄스 폭에 따라 정해진 속도로 회전합니다. 이 서보의 펄스 폭 범위는 1.0ms(1,000µs) ~ 2.0ms(2,000µs)입니다. 다른 서보는 다를 수 있습니다.

두 서보를 물리적으로 연결한 후, 회로도에 따라 외부 5V/6V로 전원 공급하고 아두이노 신호를 연결합니다:

연결 후 가장 먼저 1.5ms 펄스를 보내 모터가 "정지"하는지 확인하세요. 안 되면 서보 하단의 노란 볼트(조정 나사)로 완전 정지 위치 조정하세요.

참고: 물리적 조정이 없는 서보라면 코드 내 1500 마이크로초 값을 위아래로 조정해 완전 정지를 찾으세요.

#include <Servo.h>
Servo leftServo;
Servo rightServo;

void setup() {
  leftServo.attach(5);
  rightServo.attach(3);
  leftServo.writeMicroseconds(1500);
  rightServo.writeMicroseconds(1500);
}
void loop() { }

3단계: 바디 조립 및 이동 테스트

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇
PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

서보가 반대 방향으로 장착되어 있어 속도 범위가 다릅니다:

핀 13에 외부 LED 추가 (신호/테스트용, 내부 LED는 케이블 사이에 가려 보기 어려움). 핀 9에 버튼 연결 (테스트 및 로봇 시작용으로 유용).

while(digitalRead(buttonPin)) { } // 버튼 누를 때까지 대기
motorTurn(LEFT, 500);
motorTurn(RIGHT, 500);

아래 코드로 모터 종합 테스트 가능 (전진, 후진, 정지, 좌회전, 우회전). 필요시 딜레이 조정으로 회전 각도 보정. 좌우 펄스 값을 약간 다르게 해 모터 불균형 보정도 가능.

4단계: 블루투스 모듈 (선택 사항)

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

HC-06 블루투스 모듈을 브레드보드에 장착. 아두이노 라이브러리 SoftwareSerial 사용.

로봇은 블루투스 유무와 상관없이 작동합니다. 코드는 BT를 활성화하지 않으면 기본 파라미터를 사용하도록 작성되어 있습니다. 이 튜토리얼 마지막 부분에서 안드로이드 앱으로 로봇 파라미터 튜닝 및 수동 제어하는 방법을 다룹니다. 블루투스와 앱 사용은 선택 사항입니다 (예: 라인 팔로워 대회 출전 시).

5단계: 라인 센서 장착

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇
PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

아두이노 핀 연결:

본 프로젝트에서는 4채널 통합 모듈 + 개별 센서 1개 조합을 사용했습니다. 모든 센서 호환됩니다. 단순화를 위해 회로도에는 5개 개별 센서로 표시했지만 최종 결과는 동일합니다.

6단계: IR 센서 로직 구현

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

IR 센서는 개별 IR LED와 IR 포토다이오드로 구성. LED에서 방출된 IR 빛이 표면에 반사되어 포토다이오드로 돌아옵니다. 포토다이오드는 표면 반사율에 비례하는 출력 전압 생성 (밝은 표면 = 높은 값, 검정/어두운 표면 = 낮은 값).

사용한 센서 모듈의 내장 IC는 단순 디지털 신호 출력 (HIGH: 검정/어두움, LOW: 밝음). 모듈의 포텐쇼미터로 '검정'/'밝음' 기준 임계값 조정. 검정/어두운 색 반사 시 HIGH("1"), 그 외 밝은 색은 LOW("0") 출력.

5개 센서 배열은 검은 선 중앙에 하나의 센서만 오면 그 센서만 HIGH 출력되도록 장착. 센서 간격은 2개 센서가 검은 선 폭을 동시에 커버해 둘 다 HIGH 출력되도록 계산.

라인 팔로잉 시 가능한 센서 배열 출력 패턴:

0 0 0 0 1
0 0 0 1 1
0 0 0 1 0
0 0 1 1 0
0 0 1 0 0   ← 중앙 (이상적)
0 1 1 0 0
0 1 0 0 0
1 1 0 0 0
1 0 0 0 0

5개 센서로 '에러 변수'를 생성해 로봇의 선 위 위치를 제어합니다.

최적 조건: 로봇이 중앙에 있어 선이 중간 센서(센서 2) 바로 아래에 있을 때. 출력: 0 0 1 0 0 → error = 0.

로봇이 왼쪽으로 치우치면 (선이 오른쪽으로 움직이는 것처럼 보임) error는 양수 증가. 오른쪽으로 치우치면 error는 음수 증가.

에러 변수와 센서 상태 매핑:

0 0 1 0 0  → Error = 0
0 0 0 0 1  → Error = 4
0 0 0 1 1  → Error = 3
0 0 0 1 0  → Error = 2
0 0 1 1 0  → Error = 1
0 1 1 0 0  → Error = -1
0 1 0 0 0  → Error = -2
1 1 0 0 0  → Error = -3
1 0 0 0 0  → Error = -4

아두이노 코드에서 각 센서에 특정 이름 할당 (가장 왼쪽 센서를 "0"으로):

const int lineFollowSensor0 = 12;
const int lineFollowSensor1 = 18;
const int lineFollowSensor2 = 17;
const int lineFollowSensor3 = 16;
const int lineFollowSensor4 = 19;

센서 값 저장을 위한 배열 변수:

int LFSensor[5] = {0, 0, 0, 0, 0};

각 배열 위치를 센서 출력으로 지속 업데이트:

LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);

에러 변수 생성을 위한 로직:

if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==0)&&(LFSensor[3]==0)&&(LFSensor[4]==1)) error = 4;
else if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==0)&&(LFSensor[3]==1)&&(LFSensor[4]==1)) error = 3;
else if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==0)&&(LFSensor[3]==1)&&(LFSensor[4]==0)) error = 2;
else if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==1)&&(LFSensor[3]==1)&&(LFSensor[4]==0)) error = 1;
else if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==1)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) error = 0;
else if((LFSensor[0]==0)&&(LFSensor[1]==1)&&(LFSensor[2]==1)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) error = -1;
else if((LFSensor[0]==0)&&(LFSensor[1]==1)&&(LFSensor[2]==0)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) error = -2;
else if((LFSensor[0]==1)&&(LFSensor[1]==1)&&(LFSensor[2]==0)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) error = -3;
else if((LFSensor[0]==1)&&(LFSensor[1]==0)&&(LFSensor[2]==0)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) error = -4;

7단계: 방향 제어 - 비례 제어 (P)

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

이 시점에서 로봇은 조립 완료되고 작동 가능합니다. 모터 기본 테스트, 센서 출력 읽기, 라인 위 테스트를 해보셨을 겁니다. 이제 진짜 '두뇌', '인공지능'의 첫걸음인 라인 유지 제어 로직을 구현합니다.

단순 비례 제어 (P):

로봇이 선 위를 달리고 센서 출력이 "0 0 1 0 0"이면 error = 0. 양쪽 모터가 같은 속도로 전진.

예: iniMotorSpeed = 250 → 좌측 서보 1,250µs, 우측 서보 1,750µs 펄스 → 절반 속도 전진.

rightServo.writeMicroseconds(1500 + iniMotorPower);
leftServo.writeMicroseconds(1500 - iniMotorPower);

로봇이 왼쪽으로 치우쳐 센서 3도 커버되면 출력: "0 0 1 1 0", error = 1. 오른쪽으로 틀어야 함 → 우측 서보 속도 감소(펄스 폭 감소), 좌측 서보 속도 증가(펄스 폭 감소).

rightServo.writeMicroseconds(1500 + iniMotorPower - error);
leftServo.writeMicroseconds(1500 - iniMotorPower - error);

하지만 1마이크로초 변화로는 현실적 보정 불가. 더 큰 수 필요. error에 상수 곱하기 → 비례 상수 Kp.

int Kp = 50;
rightServo.writeMicroseconds(1500 + iniMotorPower - Kp*error);
leftServo.writeMicroseconds(1500 - iniMotorPower - Kp*error);

모터 동작 요약:

치우침이 클수록 error 커지고 중앙 복귀 속도 빨라짐. 이것이 비례 제어(P)이며, 더 복잡한 PID 제어의 P 구성 요소입니다.

8단계: PID 제어 (선택 사항)

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

이 부분은 건너뛰셔도 됩니다. 앞서 설명한 비례 제어만으로도 충분히 잘 작동합니다. 더 복잡한 제어 시스템을 원한다면 계속 읽으세요.

PID(비례, 적분, 미분)는 가장 일반적인 제어 방식 중 하나입니다. 대부분의 산업 제어 루프가 PID 변형을 사용합니다. PID 루프 튜닝 방법은 여러 가지가 있으며, 여기서는 수동 튜닝 기법을 사용합니다.

PID를 스프링으로 비유: 스프링은 원래 길이가 있고, 늘어나거나 압축되면 가능한 빨리 원래 길이로 돌아가려 함. 마찬가지로 PID 알고리즘은 제어 대상 물리량의 설정값(set point)을 가지며, 이것이 변경되면 시스템이 다른 특성을 제어해 최단 시간에 설정값으로 복귀시킴. 크루즈 컨트롤, 로봇, 온도/전압 조절기 등 물리량 제어가 필요한 곳 어디든 사용.

PID 작동 원리

시스템은 센서로 현재 물리량 값을 측정해 설정값과의 '오차(error)' 또는 '편차(deviation)' 계산. 이 오차를 최소화해 이상적으로 0으로 만들어야 함. 가능한 빨리. 이상적으로 시스템 응답에 지연이 없어야 함.

PID 구현

i) 오차 항 (e): 설정값과 현재 값의 차이. Error = set_point - current_value (우리 경우는 로봇의 선 위 위치에서 구한 error 변수)

ii) 비례 항 (P): 오차에 비례. P = error. 설정값 도달 위해 필요한 물리량 변화 크기 결정. 제어 루프 상승 시간(얼마나 빨리 설정값 도달) 결정.

iii) 적분 항 (I): 이전 모든 오차 값의 합. I = I + error. 설정값으로부터의 변화에 대한 시스템 반응 속도 담당. 비례 항이 필요로 하는 정상 상태 오차 제거용. 보통 소형 로봇에서는 정상 상태 오차 관심 적고 루프 튜닝 복잡해져 적분 항 생략.

iv) 미분 항 (D): 현재 순간 오차와 이전 순간 오차의 차이. D = error - previousError. 물리량이 설정값에 가까워질 때 변화율 늦춤. 오버슈트(과도 보정) 감소용.

방정식:

PIDvalue = (Kp*P) + (Ki*I) + (Kd*D)

상수:

튜닝 접근법 (시행착오법):

  1. Kd = 0으로 두고 Kp만 먼저 튜닝. Kp = 25가 좋은 시작점. 앞서 Kp=50이 내 로봇에 잘 작동했음.
  2. 로봇 반응이 적당해지면 미분 항(Kd) 튜닝. Kp와 Kd 각각을 Kp의 절반으로 시작. 예: Kp=50으로 잘 작동하면 Kp=25, Kd=25로 시작.
  3. Kd(미분 게인) 증가 → 오버슈트 감소. 로봇 불안정해지면 Kd 감소.
  4. 로봇 반응 너무 느리면 값 증가, 너무 빨라 불안정하면 값 감소.

또 다른 요소: 실제 샘플/루프 속도. 코드의 delay 문으로 설정. 이 파라미터를 빠르게/느리게 조정해도 성능에 큰 차이. 역시 시행착오로 최적값 탐색.

위 접근법 기반 구현 함수:

void calculatePID() {
  P = error;
  I = I + error;
  D = error - previousError;
  PIDvalue = (Kp*P) + (Ki*I) + (Kd*D);
  previousError = error;
}

앞서 사용한 단순 Kp 상수를 이 PIDvalue로 대체:

void motorPIDcontrol() {
  int leftMotorSpeed = 1500 - iniMotorPower - PIDvalue;
  int rightMotorSpeed = 1500 + iniMotorPower - PIDvalue;
  leftServo.writeMicroseconds(leftMotorSpeed);
  rightServo.writeMicroseconds(rightMotorSpeed);
}

※ Kd와 Ki가 0이면 PIDvalue = Kp*error로 앞서 단계와 동일.

9단계: 최종 코드

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

이 단계에서 로봇은 멈추지 않고 계속 루프를 돌며 라인을 따라갑니다. 기본 루프 프로그램:

void loop() {
  readLFSsensors(); // 센서 읽기, 센서 배열 저장, error 계산
  calculatePID();
  motorPIDcontrol();
}

하지만 더 완전하고 현실적인 작동을 위해 라인으로 수행하는 기본 '명령어' 몇 가지 추가 필요. 새 변수 mode 도입, 3가지 상태 정의:

#define STOPPED 0
#define FOLLOWING_LINE 1
#define NO_LINE 2

모든 센서가 검은 선 감지 → 출력: 1 1 1 1 1. 이 조건을 STOPPED 모드로 정의하고 로봇 '완전 정지' 수행.

if((LFSensor[0]==1)&&(LFSensor[1]==1)&&(LFSensor[2]==1)&&(LFSensor[3]==1)&&(LFSensor[4]==1)) {
  mode = STOPPED;
}

라인 팔로워 로봇에서 흔한 상황: '선 없음' 발견 → 출력: 0 0 0 0 0. 이 경우 180도 회전하거나 선 찾을 때까지 작은 각도로 회전 후 정상 라인 팔로우 재개.

else if((LFSensor[0]==0)&&(LFSensor[1]==0)&&(LFSensor[2]==0)&&(LFSensor[3]==0)&&(LFSensor[4]==0)) {
  mode = NO_LINE;
}

완전한 loop():

void loop() {
  readLFSsensors();
  switch (mode) {
    case STOPPED:
      motorStop();
      break;
    case NO_LINE:
      motorStop();
      motorTurn(LEFT, 180);
      break;
    case FOLLOWING_LINE:
      calculatePID();
      motorPIDcontrol();
      break;
  }
}

실제 최종 코드에는 추가 로직과 초기화 필요 변수들이 포함됩니다. 위 설명에서는 단순화를 위해 생략했지만 최종 코드를 보면 모두 명확해집니다.

10단계: 안드로이드 앱으로 PID 제어 튜닝

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

이전 코드의 robotDefines.h 탭에 PID 제어용 상수 정의:

float Kp=50; float Ki=0; float Kd=0;

앞서 설명했듯 PID 컨트롤러에 올바른 상수를 정하는 최적의 방법은 '시행착오' 방법론. 단점은 매번 변경 시 재컴파일 필요. 이 과정을 가속화하기 위해 안드로이드 앱으로 '설정 단계(Set-Up Phase)'에서 상수를 전송하게 만들었습니다.

전용 안드로이드 앱 개발. 주요 기능:

.aia 파일(MIT App Inventor에서 수정 가능)과 .apk 파일(안드로이드 기기 직접 설치용) 제공.

11단계: PID 원격 튜닝용 코드 수정

설정 단계에서 로봇을 선 위에 놓기 전 PID 파라미터를 전송할 수 있는 루프 추가:

while (digitalRead(buttonPin) && !mode) {
  checkBTcmd(); // BT 원격 제어 명령 수신 확인
  manualCmd();
  command = "";
}
checkPIDvalues();
mode = STOPPED;

수동 명령 함수:

void manualCmd() {
  switch (command[0]) {
    case 'g': mode = FOLLOWING_LINE; break;
    case 's': motorStop(); break;
    case 'f': motorForward(); break;
    case 'r': motorTurn(RIGHT, 30); motorStop(); break;
    case 'l': motorTurn(LEFT, 30); motorStop(); break;
    case 'b': motorBackward(); break;
    case 'p': Kp = command[2]; break;
    case 'i': Ki = command[2]; break;
    case 'd': Kd = command[2]; break;
  }
}

영상에서 안드로이드 앱 사용 테스트 확인 가능. PID 설정 포함 최종 코드 제공.

12단계: 결론

PID 제어와 안드로이드 연동으로 만드는 라인 팔로잉 로봇

이것은 라인 팔로워 로봇의 잠재성을 탐구하는 더 복잡한 프로젝트의 첫 번째 파트입니다. 다음 파트에서는 이 프로젝트를 기반으로 미로 해결 로봇을 개발할 예정입니다. 다른 분들이 전자공학, 로봇, 아두이노 등에 대해 더 배우는 데 기여할 수 있길 바랍니다.

이 프로젝트 업데이트 파일은 GitHub에서 확인 가능. 더 많은 튜토리얼은 블로그 MJRoBot.org 방문.

남반구에서 인사드립니다! 감사합니다. - Marcelo

코드

GitHub: https://github.com/Mjrovai/MJRoBot-Line-Follower

주요 코드 스니펫들은 본문 내에 포함되어 있습니다.

회로도

Fritzing 파일: oIDhLcHQ30lDgVBXZvb8.fzz

제조공정

  1. 21세기 로보틱스: 분산 시스템, 텔레프레즌스, 우주 탐사
  2. 라즈베리 파이와 KY-033 라인 트래킹 센서로 문 열림/선 감지하기
  3. 라즈베리 파이 센서 및 액추에이터 제어 마스터하기: 가속도계, 서보 모터, 데이터 스트리밍
  4. 라즈베리 파이 & 안드로이드 스마트폰으로 WiFi 제어 로봇 만들기
  5. 비트만 바텐펠트, 고강도 사출 성형 자동화용 WX153 신규 로봇 라인 출시
  6. FANUC, SCARA 로봇 라인 확대: 6개 모델, 3~20kg 페이로드, 400~1,100mm 리치
  7. 아두이노, 1Sheeld, IR 제어로 만능 안드로이드 리모컨 만들기
  8. 산업용 라인 팔로잉 로봇: 자재 이송용 아두이노 기반 자율 주행 로봇
  9. MATLAB/Simulink에서 3D 로봇 그리퍼 PID 제어 마스터하기
  10. 첨단 자동화 제어 시스템으로 포장 품질 보증 간소화하기