brunch

You can make anything
by writing

C.S.Lewis

by Cylogic Oct 11. 2020

43.아홉 번째 장난감:자율 주행 자동차 만들기#3

자율 주행 자동차 코딩 하기

이제 복잡한 코딩 시간이다.

쉽게 가기 위하여 여러 개의 함수로 동작을 구분하여 설명하도록 한다.


앞서 연결했던 선을 참조해야 하므로 연결된 내용을 다시 가져와서 보면서 코드를 정리하겠다.



제일 먼저 해야 할 일은 연결된 핀을 정의하는 것이다.

위와 같이 핀 연결에 대한 사항을 모두 정의하면 된다.

서보모터의 경우 좌우 움직임을 0~90도까지 회전하려고 하여 초기에는 45도로 고정하여 정면을 보게 한다.

stopMotors는 모든 모터를 정지하라는 함수이다.

모든 움직임은 별도의 함수를 통해 구현할 것이므로, 우리가 모터의 움직임을 위하여 만들어야 할 함수들은 아래와 같다.


void forward()  // 직진하라

void backward() // 후진하라

void left() // 좌측으로 움직여라

void right() // 우측으로  움직여라

stopMotors() // 멈춰라


좌우 장애물을 판단하고 방향을 결정하기 위한 함수는 다음과 같다.

float check_distance() // 좌우중 어디에 장애물이 멀리 있는지 판단하여 방향 전환

void changeDirection() // 초음파 센서의 거리 측정


이상을 하나씩 살펴보고 잘 조합하는 방법을 배워야 한다.


모터가 스톱을 하는 경우는 좌우 바퀴 모두의 전원이 LOW 상태이어야 한다.

그 코드는 아래와 같다.

void stopMotors() {

  digitalWrite(INL1, LOW);

  digitalWrite(INL2, LOW);

  digitalWrite(INR1, LOW);

  digitalWrite(INR2, LOW);

}


앞으로 갈 때는 모든 모터가 같은 방향으로 움직여야 한다.

왜 1,2의 HIGH, LOW가 반대이냐 하면 그렇게 모터에 들어간 전선의 방향이 정해져 있기 때문이다.

아래의 방향이 앞으로 가는 방향이라면 그 반대의 방향으로 HIGH, LOW를 선택하면 모터가 뒤로 가는 방향이 되는 것이다. 이 값은 각자 설치된 모터에 따라 확인하며 정리하면 된다.


void forward() {

  digitalWrite(INL1, HIGH);

  digitalWrite(INL2, LOW);

  digitalWrite(INR1, LOW);

  digitalWrite(INR2, HIGH);

}


그렇다면 뒤로 가는 코드는 당연히 아래와 같이 될 것이다.

void backward() {

  digitalWrite(INL1, LOW);

  digitalWrite(INL2, HIGH);

  digitalWrite(INR1, HIGH);

  digitalWrite(INR2, LOW);

}


좌로 가려면 오른쪽 바퀴는 앞으로 구르고 왼쪽 바퀴는 뒤로 굴러야 쉽게 방향이 전환된다.

void left() {

  digitalWrite(INL1, LOW);

  digitalWrite(INL2, HIGH);

  digitalWrite(INR1, LOW);

  digitalWrite(INR2, HIGH);

}


우로 가려면 왼쪽 바퀴는 앞으로 구르고 오른쪽 바퀴는 뒤로 굴러야 쉽게 방향이 전환된다.

void right() {

  Serial.println("right...");

  digitalWrite(INL1, HIGH);

  analogWrite(INL2, LOW);

  digitalWrite(INR1, HIGH);

  analogWrite(INR2, LOW);

}


이제 장애물에 대한 판단과 방향 전환을 어떻게 할지를 코드로 만들어 보자 

이 코드는 앞에 있는 장애물의 거리이다. 이전에 만든 코드와는 조금 다르게 만들어 보았다.

모두 아주 정밀한 계산은 온도를 측정하지 않는 한 불가능하다.

어찌 되었건 거리를 측정하여 그 cm 값을 return 한다.


float check_distance() {

  digitalWrite(tPin, LOW);

  delayMicroseconds(10);

  digitalWrite(tPin, HIGH);

  delayMicroseconds(10);

  digitalWrite(tPin, LOW);

  float duration = pulseIn(ePin, HIGH);

  float distance = ((float)(340 * duration) / 10000) / 2;

  return distance;

}


여기까지는 하드웨어를 구동하는 기본 코드를 한 것이고, 이제부터는 제작자의 기량과 기획에 따라 마음껏 바꾸어도 되는 가장 중요한 코드이다. 독자들께서 원하시는 형태로 수정을 하고 싶다면 이곳을 수정하면 된다.

이곳은 좀 자세히 설명하려 한다.


void changeDirection(){  


  int lDist;    // 좌측 장애물의 거리

  int rDist;    // 우측 장애물의 거리

  delay(300); 


  Srv.write(90);  // 초음파 센서의 방향을 좌로 돌린다.

  delay(300);     // 잠깐 여유를 두어야 한다. 이 부분을 넣지 않아서 문제가 많았다.

                           // 만일 좌우 거리 값이 틀리면 좀 더 delay값을 늘려 보시라.

  lDist=check_distance();     // 좌측 장애물 거리 측정

  delay(600);    


  Srv.write(0);   // 초음파 센서의 방향을 우로 돌린다.

  delay(300);     // 잠깐 여유를 두어야 한다. 이 부분을 넣지 않아서 문제가 많았다.

  rDist=check_distance();      // 우측 장애물 거리 측정

  delay(600);


  Srv.write(45);   // 다시 정면을 본다.

  if (lDist<rDist){     // 왼쪽에 장애물이 가깝다면

    right();                 // 오른쪽으로 방향 전환

    delay(300);         // 우측 회전 양을 이 값으로 조절

    stopMotors();     // 멈춤

  }

  else{                       // 오른쪽 장애물이 가깝다면 

    left();                    // 왼쪽으로 방향 전환

    delay(300);          // 좌측 회전 양을 이 값으로 조절

    stopMotors();      // 멈춤

  }

  delay(500);

}


모든 코드의 해석을 한 줄씩 첨부하였으니 잘 확인하여 이해하시길 바란다.

이제 이 모든 코드를 실행하는 loop 함수를 확인해 보자.


프로그램이 시작하면 주행 중 정면 20cm 앞에 장애물이 있는 경우 changeDirection 함수를 불러 좌 또는 우측으로 장애물을 피해 가라는 명령이 정리되어 있다.


3편으로 나누어진 "자율주행 자동차 만들기"가 끝났다.


조금 복잡한 내용이었을지 모르지만 이 코드들이 모든 아두이노 장난감 자동차를 전후좌우로 움직이는 코드의 근간이다. 이 코드를 이용하여 차후에 블루투스나 무선으로 조종하는 자동차를 만들게 될 것이니 잘 이해하시길 바란다.

다시 한번 자동차의 뭄직임을 보며 마무리 하자.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari