[아두이노] RC카 장애물 감지시 방향 전환 기초

IOT/아두이노|2019. 2. 22. 11:52

[아두이노] RC카 장애물 감지시 방향 전환 기초



초음파레이더의 원리는 지난 시간에 기초 실험으로 살펴 보았습니다. 하다보니깐 RC카 자율주행할 때 초음파 센서로 장애물 감지을 할 경우가 문득 떠오르더군요. 그래서 초음파레이더 만들기 소스를 그대로 이용하여 몇부분만 추가하여 코딩을 완성했습니다. 그냥 갑자기 떠오른 생각이라서 코딩은 깔끔하지 않네요. 막 떠오르는데로 코딩한거니 그 점을 감안해서 코딩을 보시기 바랍니다.

1. 회로도 구성


  • 준비물 : 서보모터 2개, 초음파센서 1개, 아두이노우노
  • 내용 :45~ 125도 서보모터를 회전시키면서 초음파센서로 거리를 측정부분은 그대로 유지한 상태에서 RC카 앞바퀴 방향 제어용 서보모터를 추가하자.


머리속에서 각 부품을 실제 RC카에 배치를 상상해 보세요. 첫번째 초음파센서가 서보모터에 부착되어 있고 두번째 서보모터는 RC카 앞바퀴에 연결되었다고 상상 해보세요.

3. 코딩


  • 사용함수 : attach(사용핀), write(각도), pulseIn(입력핀, HIGH), Serial.begin(9600), Serial.print(출력값),Serial.println(출력값)
  • 내용 : 간단히 서보모터가 회전은 45~125도 범위를 잡고 전방의 장애물 탐지를 초음파센서가 담당하게 코딩하고 앞바퀴담당 서보모터는 거리 50이하 일때 전방 90도 기준으로 좌측에 장애물 발견시 우측으로 우측 장애물 발견시 좌측으로 회전시키는 코딩을 한다.

설계

앞바퀴 방향 제어를 하기 위해서 서보모터를 제어해야겠죠.

그래서 서보모터 객체를 하나 더 선언합니다.

Servo servo2;

그리고 핀을 10번을 사용하기 위해서 연결합니다.

int servoPin2 = 10;
servo2.attach(servoPin2); //angle (0~180)

앞바퀴 장애물 방향전환 조건문을 만듭니다.(하나의 패턴으로 자율주행 첫단추로 접근하는 시작 코딩)

  if(m_distance<=50 && m_angle>90) {    
    servo2.write(45);
    delay(50);   
  }
  else if (m_distance<=50 && m_angle<90){
    servo2.write(125);
    delay(50);   
  }
  else {
    servo2.write(90);
    delay(50);   
  }
  if(m_distance<=50 && m_angle>90) {    

if조건문

  • 첫번째 조건식 : "장애물(벽) 거리가 50cm 이하이고 각도가 90도 보다 큰가?" (왼쪽장애물확인)
    그러면 왼쪽 장애물이 너무 가까우니깐 오른쪽으로 핸들을 꺽어야 겠죠.
  • 두번째 조건식 : "그게 아니면 장애물(벽) 거리가 50cm 이하이고 각도가 90도보다 작은가?"(오른쪽장애물확인)
    그러면 오른쪽 장애물이 너무 가까우니깐 왼쪽으로 핸들을 꺽어야 겠죠.
  • 거짓이면 : 그냥 앞바퀴 방향각 90도로 정중앙 정면을 향하게 한다.

즉, 조건식으로 50cm이하일때 현재 방향에 따른 핸들의 방향을 결정하게 됩니다. 50cm이하에 장애물이 없으면 그냥 정면으로 계속 진행하도록 로직을 짜봤습니다.
여기서 핸들 각도를 변수로 빼면 중복되는 코딩이 3번 반복되는데 이걸 하나로 줄일 수 있겠지만 우선은 동작을 좀 더 직관적으로 이해할 수 있도록 하기 위해서 수정은 안했습니다.

초음파레이더 소스와 위에 방향전환 로직을 합쳐서 전체코딩을 을 살펴보면

#include <Servo.h>

Servo servo1;
Servo servo2;
int servoPin1 = 9;
int servoPin2 = 10;
int m_distance=0;
int m_angle=45;
int m_chk=0;

void setup() {
  Serial.begin(9600);
  servo1.attach(servoPin1); //angle (0~180)
  servo2.attach(servoPin2); //angle (0~180)
}

void loop() {
  
  //초음파센서 몸체 회전
  servo1.write(m_angle);
  delay(50);
  
  m_distance=CalDistance(7);  //초음파센서로 거리계산함수   
  Serial.print("d : ");
  Serial.println(m_distance);
  
  //앞바퀴 장애물 방향전환
  if(m_distance<=50 && m_angle>90) {    
    servo2.write(45);
    delay(50);   
  }
  else if (m_distance<=50 && m_angle<90){
    servo2.write(125);
    delay(50);   
  }
  else {
    servo2.write(90);
    delay(50);   
  }
  
  //초음파센서 회전각
  if(m_chk==0){
    if(m_angle<125)m_angle+=1;
    else m_chk=1;
  }
  else{
    if(m_angle>45)m_angle-=1;
    else m_chk=0;
  }
  
}

int CalDistance (int Pin){  //초음파센서(3핀) 예제를 그대로 외부함수로 빼냄
  pinMode(Pin,OUTPUT); //출력모드로  사용
  digitalWrite(Pin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(Pin,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(Pin,LOW); 
  
  pinMode(Pin,INPUT);    //입력모드로 사용
  int duration = pulseIn(Pin, HIGH);
  
  int distance = duration / 57.5;  //가상시뮬레이션의 오차율을 줄이기 위해 이걸로 테스트 함.

  return distance; //거리값 리턴
}

5. 결과


설계과정은 이번에 생략하고 결과만 시뮬레이터로 돌려 보는 장면만 보여 드립니다. 지난시간에 회로도 만드는 과정을 해봤으니 구지 중복해서 다시 똑같은 것을 찍을 필요는 없고 서보모터만 하나 추가했기 때문에 결과만으로 충분해서 회로도 배치과정은 생략했네요.

마무리


오늘은 아두이노 RC카에 주행에 관한 첫 단추인 방향전환에서 하나의 패턴을 기초 패턴으로 로직을 만들었습니다. 이걸로 주행이 가능하지 않습니다. 단지 이렇게 코딩해 놓고 조금씩 패턴을 늘리고 로직을 늘려가야 합니다.

여기서는 단적으로 왼쪽 장애물 감지시 레드존에 들어가고 바로 오른쪽으로 45도 회전을 시켜서 그린존으로 탈출하는 코딩입니다. 어떤 문제가 있을까요 바로 현재 RC카의 주행 속력에 대한 장애물과의 거리별로 방향전환 각도를 가변적으로 해야합니다. 그래야 매끄렇게 회전이 됩니다. 그리고 또 문제는 가령 전방 직선도로로 달릴때 통과 할 수 공간이 충분하지만 가력 왼쪽이나 오른쪽 방향에 장애물이나 벽과의 거리가 50 이하면 그냥 방향핸들을 반대 방향으로 꺽어버리는 문제가 방생합니다. 즉, 전방에 안전거리 확보가 확인되면 그상태로 주행하고 안전거리가 미확인시 좌우측에 위험거리가 감지되면 방향을 전환하더록 로직을 수정해야겠죠.

이렇게 주행에서의 문제들을 하나씩 찾아내고 그걸 해결하는 패턴들을 하나씩 만들어 내야합니다. 그래야 자율주행이 가능해지는 것이죠. 다른 방식으로 장애물 감지되면 그상태에서 주행이 정지되고 안전거리 확보 패턴로직 주행을 하고 다시 안전거리가 확보되면 주행을 다시 시작하는 방식으로도 변경할 수 있겠죠.

코딩을 쉽게 하기 위해서는 실제 장난감 자동차를 방에서 손으로 밀면서 주행을 시켜보세요 그리고 관찰하면 이런 상황일때 이걸 어떻게 어떻게 빠져나올지 손으로 자동차를 움직이시고 그 움직을 잘 기억했다가 그 움직이는 동작 패턴을 코딩화 하시면 됩니다.

암튼 집에 굴러다니는 장단감을 가지고 한번 손으로 밀면서 띠따! 빵빵! 하면서 가지고 노세요. 그리고 나서 그 움직임을 기역했다가 코딩을 상상해보세요.


댓글()