반응형

【 아두이노 Proj#1】 초음파센서로 자동차 만들기 L298N모듈)

 지난 시간 L298모터 드라이버 모듈을 활용하여 초음파 센서에 반응하여 모터를 구동시키는 실습을 해보았다. 이제 본격적으로 초음파 센싱으로 작동되는 자동차를 만들어보려 한다.  또한 초음파 센서쪽에 서보모터를 부착하여 좌우의 장애물의 유무를 파악하여 장애물이 없는 쪽으로 움직일 수 있도록 하였다. 

▶ 선수 학습 :

1. (기초)#24 DC 모터 제어 하기 4 (L293 & H브릿지 참고)   강좌보기클릭  2(기초)#28 서보(Servo) 모터 제어 하기 1 (서보모터이해)    강좌보기클릭  3(기초)#29 서보(Servo) 모터 제어 하기 2 (서보모터이해)    강좌보기클릭  
4. (센서)#24 초음파센서 경보회로with LCD (초음파 센서이해)    강좌보기클릭


▶ 실습에 사용되는 부품 스팩 ( L298N ) 

 모터 모듈의 상세한 사용 설명은 선수학습 4.번을 참고


▶ 실습 목표 :  

1. L298N 모듈에 대해 이해하고 모터를 연결하여 사용하는 방법에 대해 익힌다.

2. L298N 드라이버 모듈에 별도의 전원이 필요한 경우에 대해 이해 할 수 있다. 

3. 초음파 센서를 비롯한 센서의 신호를 체크하여 N298모듈에 연결된 모터들을 제어 할 수 있다. 

4. 초음파로 장애물을 확인하고 회피기동 프로그램을 작성하여 스스로 움직이는 RC카처럼 구성해볼 수 있다. 


▶ 실습 회로도면 (서보모터 부착회로):

  (이미지 클릭하면 확대 가능)

 ※ 아두이노에 공급되는 전원과 별도로 모터에도 전원을 인가해주면 좋을 것이다.(단일 전원 구성도 가능하나, 바퀴가 힘있게 굴러가지 못하고 작동시간도 매우 짧기 때문에 모터 구동(모듈)쪽에 별도의 전원을 넣어 주는 것이 좋다) 


※ DC(직류) 방식의 모터는 작은 용량(소비전력이 낮은)의 것을 사용하면 되며,  기어가 포함된(기어드) DC 모터를 사용한다면 아두이노의 작은 출력으로도 충분히 제어가 가능하다. 만약 회로연결과 아두이노 프로그램에 문제가 없는데도 동작이 되지 않는 다면, 공급전력에 비해 너무 큰 용량의 DC 모터가 연결된 경우 일 수 있으니,  이런 부분들을 확인 해보면 될 것이다. 이때, 모터드라이버 모듈에 별도의 전원을 넣어주면 해결될 수 있다. 인가 가능한 전원은 5V~36V 사이값 이므로 이를 고려하여 모터를 선택하면 된다.



▶ 실습 절차  : 

1.    위 회로 연결도를 참고하여 부품들을 연결한다
2.    DC 모터의 연결선 방향은 우선 연결 후 프로그램으로 작동시켜보고 방향이 반대가 될 경우 다시 바꾸어 연결하면 된다.
3.    만약 가지고 있는 모터의 용량이 비교적 클 경우 아두이노 전원만으로는 동작이 어려울 수 있으니 회로도에서 처럼 별도 전원을 인가해주면 동작이 잘 될 것이다. (※ 모터 관련 회로에서 대부분의 동작 문제는 모터에 공급되는 전력이 충분치 않아 발생한다) 

5.   전원 하나로 아두이노와 DC모터를 포함한 L298모듈 둘 다를 돌리기에는 한계가 있다따라서 아두이노와 DC모터 모듈 전원을 각각 공급해주어야 하며, 이때 그라운드(GND) 공통으로 연결해주면 된다.

6.  모터 모듈 전원은 최소 5V이상, 모터용량에 따라 넣어 주면 되는데, 모터 구동에는 전압보다 전류가 중요한 역할을 하게 된다실험을 해보면, 모터모듈 전원으로 9V 베터리를 연결 할 때 보다, 1.5V X 4(6V)를 연결할 때가 훨씬 잘 동작될 것이다.(4개의 건전지에서 전류가 충분히 공급 되기 때문)
7. 서보모터는 180도 왕복 회전할 수 있는 것을 사용한다.
8.   초음파 센서에 손이나 장애물을 대어 보아서 모터제어가 잘 되는지 확인한다.

▶ 프로그램 코드 및 설명 : 

/*  L298N 모터 모듈을 활용한 초음파 센서 제어 회로 */

int distance;             /*  초음파센서로 모터제어 하기  */

int triggerPin = 13;

int echoPin = 12;

#define IN1 8  // L298모듈의 제어 신호 입력 핀 번호 지정

#define IN2 9

#define IN3 10

#define IN4 11

float distance;          // 초음파 센서 거리값 변수

int servoPin = 2;     // 서보모터 연결 포트

Servo servo;


void forward() {      // L298 제어용 전진 함수

      digitalWrite(IN1, HIGH);

      digitalWrite(IN2, LOW);

      digitalWrite(IN3, HIGH);

      digitalWrite(IN4, LOW);    }


void back() {         // 후진

      digitalWrite(IN1, LOW);

      digitalWrite(IN2, HIGH);

      digitalWrite(IN3, LOW);

      digitalWrite(IN4, HIGH);   }


void left() {         // 좌회전(왼쪽모터 멈춤:오른쪽모터 전진)

      digitalWrite(IN1, LOW);

      digitalWrite(IN2, LOW);

      digitalWrite(IN3, HIGH);

      digitalWrite(IN4, LOW);  }


void right() {      // 우회전(왼쪽모터 전진:오른쪽모터 멈춤)

      digitalWrite(IN1, HIGH);

      digitalWrite(IN2, LOW);

      digitalWrite(IN3, LOW);

      digitalWrite(IN4, LOW);   }


void stop() {       // 정지

      digitalWrite(IN1, LOW);

      digitalWrite(IN2, LOW);

      digitalWrite(IN3, LOW);

      digitalWrite(IN4, LOW);  }


void setup( )  {

  Serial.begin(9600);

  pinMode(triggerPin, OUTPUT);  // 트리거 핀을 출력으로 설정

  pinMode(echoPin, INPUT);          // 에코 핀을 입력으로 설정

  servo.attach(servoPin);               // 서보모터 연결 지정

  servo.write(90);                            // 초기값으로 정면 응시

  delay(1000);               

}


float getDistanceCM() {      // 초음파 센서 거리 측정 함수(단위:cm)

  digitalWrite(echoPin, LOW);

  digitalWrite(trigPin, LOW);

  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10);

  digitalWrite(trigPin, LOW); 

  distance = pulseIn(echoPin, HIGH)  / 58;  //거리값 계산 후 저장

  return distance;

}


// 거리값 정확도를 위한 평균치 계산 함수(1회이상~ 10회미만으로 조정해보기)

float getStableDistanceCM() {

  int CmSum = 0;

  for (int i = 0; i < 8; i++) {

    CmSum += getDistanceCM();  //, 'sum = sum + cm' 동일

   }

  return CmSum / 8;

}


void loop( ) {

   if ( getStableDistanceCM() < 25 ) {  // 25cm이하 장애물 감지

         stop();

         delay(300);     
         servo.write(180);      // 서보모터 좌회전 후 측정 거리값 변수에 저장     

        delay(500);

        int leftDistance = getStableDistanceCM();

        delay(300);

        servo.write(0);           // 서보모터 우회전 후 측정 거리값 변수에 저장

        delay(500);

        int rightDistance = getStableDistanceCM();

        delay(300);

        servo.write(90);        // 서보모터 중앙으로 원위치

        delay(500);

        back();                         // 0.5초간 후진

        delay(500);

       if (leftDistance > rightDistance {

           left();

       } else {

          right();
       } 

      delay(500);

  }   else {                            // 장애물 감지가 안 될 경우 전진

      forward();

      }

   }

◈  모터 A, B가 동시에 시계방향으로 돌면 전진, 반시계 방향이면 후진이고,

  한쪽바퀴만 돌리거나 두 개의 바퀴를 서로 반대로 돌리면 좌회전 혹은 우회전이 된다.   이를 함수 형태로 만들고 메인 루프에서 적절히 함수들을 호출해서 사용하도록 하였다. 또한 거리값을 계산하는 부분을 함수로 만들었다(getDistanceCM()) , 그리고 얻어진 거리값을 초음파로 측정할 때 오류가 날 수 있기 때문에 1~8회 사이 몇 번 측정후 평균을 내면 편차가 큰 오류값은 걸러낼 수 있고 이를 함수로(getStableDistanceCM()) 만들었다.  

 위 프로그래밍에서는 기본 전진 기동을 하다가, 물체가 20cm 이내로 감지되면 정지를 시키고, 초음파 센서에 달린 서보모터를 좌, 우로 돌려보고 거리값을 각각 측정하여 물체가 없거나 물체와의 거리가 더 먼쪽의 방향으로 회전(좌회전 또는 우회전) 하도록 프로그래밍 한 것이다. 


▶ 실행영상 :  

(전체화면 보기로 보세요)


※ 자동차 몸체는 영상에 있는 것이 아니어도 좋다. 두 바퀴를 안정적으로 고정시킬 수 있는 몸체와 앞 뒤로 기울어지지 않게 볼캐스트(볼 베어링)를 종이박스나, 폼보드 등에 부착해서 직접 만들어도 된다. 


▶ 아두이노 파일(다운) :

UltraSonicRC-CAR_Servo.ino






반응형