SPAC1N 뉴 아두이노 2WD 자동차 스마트카 로봇 PART2(프로그램)

PART2에서는 SPAC1N 스마트카를 구동하기 위한 초음파 테스트와 LCD 표시하기, 모터 구동하기의 사전 테스트와 실제 장애물 회피 프로그램을 아두이노 보드에 업로드하여 실제 주행을 해봅니다.

PART2 - SPAC1N 테스트 및 구동

SPAC1N 아두이노 자동차는 아두이노 우노 보드를 사용하여 2바퀴 구동의 스마트카를 구성한 조립키트입니다. 초음파센서로 장애물을 감지하고 LCD에 실제 장애물과의 거리를 표시하며 장애물이 있으면 이를 회피하여 장애물이 없는 곳으로 진행을 계속합니다. 2바퀴 모터 구동을 위해 L298N 모터 드라이브 모듈을 사용합니다.

 

아래는 키트에 포함된 아두이노 우노 R3 호환보드입니다. USB 드라이버만 별도로 설치하시면 기존 아두이노 우노 보드와 100% 동일하게 동작합니다.

 

참고: 일부 윈도우즈7와 윈도우즈8/8.1/10 에서는 인터넷이 연결되어 있는 경우 별도의 드라이버 설치없이 자동으로 설치됩니다. 이 경우 드라이버를 수동으로 설치할 필요가 없습니다.
윈도우즈에서 자동으로 드라이버를 설치하지 못하는 경우에만 아래 드라이버를 설치하시기 바랍니다.

 

아래 링크의 드라이버를 다운로드합니다.

 

아두이노 우노 R3 호환보드용 CH340 USB드라이버

 

다운로드한 드라이버파일의 압축을 풀고 SETUP.EXE를 실행하면 아래의 창이 나타나며 INSTALL버튼을 누르면 드라이버가 설치됩니다.

 

드라이버를 설치한 후 아두이노 우노 보드를 USB에 연결하면 장치관리자에서 아래와 같이 시리얼포트가 등록되어 있는 것을 확인할 수 있습니다.

아래 링크로 가시면 아두이노 IDE 소프트웨어 설치파일을 다운로드할 수 있으며 기본적인 아두이노 IDE 사용법을 익힐 수 있습니다.

아두이노IDE 설치 및 사용방법 링크

 

1. 초음파센서 테스트

SPAC1N에서 사용된 초음파센서는 HC-SR04로서 초음파를 발사하고 물체에 반사되어 오는 초음를 감지하여 물체와의 거리를 측정합니다.

기본원리는 다음과 같습니다.

먼저 MCU의 IO포트를 이용해서 모듈의 TRIG핀으로 약 10us 정도의 High level 펄스를 보냅니다.
-> 일종의 모듈측에 거리측정을 시작하라는 START 신호입니다.

그러면 모듈의 내부에서는 40KHz의 초음파를 정면으로 발사하고나서 장애물에 반사되어 오는 초음파를 감지합니다.

반사 신호가 되돌아오면 모듈에서 ECHO 핀을 통해 MCU의 IO로 측정거리만큼의 High level 펄스 신호를 보내줍니다.

아두이노 보드에서는 모듈에서 받은 High 펄스의 시간을 계산해서 다음 식에 의해 거리로 환산합니다.

측정거리 = (High level 펄스 시간 x 음속(340m/s)) / 2

모듈의 핀맵은 다음과 같습니다.

  1. VCC - 5V DC 전압을 인가합니다.
  2. TRIG - 트리거 펄스(START 신호)를 받기 위한 핀입니다.
  3. ECHO - 측정된 거리에 해당하는 High level 펄스를 출력합니다.
  4. GND - Ground 입니다.

특징

  • 구동 전압 : DC 5V
  • 정격 전류 : <2mA
  • 감지 거리 : 2-400cm
  • 유효 각도 : <15°
  • 정  밀  도 : 0.3 cm

결선도

PART1에서 조립한 상태에서도 USB케이블만 PC와 연결하여 테스트가 가능합니다.

아래 링크에서 아두이노 보드용 라이브러리를 다운받아서 압축을 풀고 아두이노 IDE 소프트웨어가 설치된 디렉토리에서 하위 library 디렉토리에 붙여넣습니다.

라이브러리

 

소스코드

아래는 소스코드입니다. 아두이노 IDE에 붙여넣기 하여 컴파일하고 업로드합니다.

#include <Ultrasonic.h> 

Ultrasonic sensor(9,8,30000); // (Trig핀, Echo핀, 최대거리 단위는 us) 즉 30000us = 약 5미터

int distance = 0; //거리를 저장할 변수를 선언합니다.

void setup() {
  
Serial.begin(9600); //시리얼포트를 초기화합니다.
  
}

void loop() {
  
  distance = sensor.Ranging(CM);  // 거리를 측정하고 distance 변수에 저장합니다.
  Serial.print("Distance "); // "Distance "를 시리얼모니터에 출력합니다.
  Serial.print(distance); // distance 변수에 저장된 값을 출력합니다.
  Serial.println(" cm"); // 센티미터 단위를 출력합니다.
  delay (2000); // 2초간 딜레이를 한 후에 다시 반복합니다.
  
}

다음은 프로그램 업로드 후 시리얼 모니터로 본 결과입니다.

2. IIC LCD 구동 및 초음파 거리표시 테스트

SPAC1N에서 장애물과의 거리표시용으로 사용되는 LCD를 구동해봅니다.

 

LCD 디스플레이를 사용하면 컨트롤러의 다양한 상태를 사람이 알기 쉽게 전달이 가능합니다. 여기서 사용되는 LCD는 16X2 영문 텍스트를 표현이 가능합니다. 원래 아두이노 보드로 LCD에 텍스트를 표시하기 위해서는 많은 데이터 선을 연결해야 하지만 IIC 모듈이 장착된 LCD를 사용하면 전원선을 포함하여 총 4개의 선만 연결하면 됩니다.
IIC 통신방식(또는 I2C)은 필립스에서 개발한 직렬통신 방식으로 데이터(SDA)선과 클록(SCL)선의 두 개의 선으로 양방향 통신을 합니다.

아두이노 보드에서 IIC 방식의 LCD를 제어하기 위해서는 별도의 라이브러리를 설치하여야 합니다.

아래 링크에서 라이브러리를 다운받아서 압축을 풀고 아두이노 IDE 소프트웨어가 설치된 디렉토리에서 하위 library 디렉토리에 붙여넣습니다.

라이브러리

 

아래와 같이 아두이노 보드와 IIC LCD를 결선합니다. PART1에서 결선이 되었으면 그대로 테스트하면 됩니다.

소스코드

아래는 소스코드입니다. 아두이노 IDE에 붙여넣기 하여 컴파일하고 업로드합니다.


#include <Wire.h> 
#include <LiquidCrystal_I2C.h> 

LiquidCrystal_I2C lcd(0x27,16,2);  // LCD IIC 어드레스는 0x27, 16X2 LCD로 설정

void setup()
{
  lcd.init();  // LCD 초기화
  lcd.clear(); // LCD 화면 클리어
  lcd.backlight(); // 백라이트 켜기
  lcd.print("Hello, world!"); // 첫번째 라인 문자 표시
  lcd.setCursor(0,1); // 두번째 라인으로 이동
  lcd.print("SCIPIA SPAC1N!");
}

void loop()
{
}

아래는 SPAC1N에 업로드한 후 테스트한 모습입니다.

LCD화면에 표시가 안되는 경우 아래와 같이 LCD 뒷면의 가변저항을 글씨가 표시될 때까지 서서히 돌려주십시요.

 

아래는 초음파센서로 측정한 거리를 LCD 화면에 표시하는 표시하는 프로그램입니다.

 


#include <Ultrasonic.h> 
#include <Wire.h> 
#include <LiquidCrystal_I2C.h> 

Ultrasonic sensor(9,8,30000); // (Trig핀, Echo핀, 최대거리 단위는 us) 즉 30000us = 약 5미터
int Distance = 0; //거리를 저장할 변수를 선언합니다.

LiquidCrystal_I2C lcd(0x27,16,2);  // LCD IIC 어드레스는 0x27, 16X2 LCD로 설정


void setup() {

  lcd.init();  // LCD 초기화
  lcd.backlight(); //LCD 백라이트 ON
  
}

void loop() {
  
  Distance = sensor.Ranging(CM);  // 거리를 측정하고 distance 변수에 저장합니다.
  lcd.home();
  lcd.print("    Distance:   ");
  lcd.setCursor(6,2);
  lcd.print(Distance);
  lcd.print("cm      ");
  delay (2000); // 2초간 딜레이를 한 후에 다시 반복합니다.
  
}

아래는 SPAC1N에 업로드한 후 테스트한 모습입니다.

 

3. L298N 모터 구동 테스트

이제 스마트카를 움직이기 위한 모터 구동테스를 합니다. 2개의 기어드 모터가 사용되며, 양쪽의 2개의 모터의 구동방향을 제어함으로써 스마트카를 전진, 후진, 좌회전, 우회전을 가능하게 합니다.

2바퀴의 직류모터 구동을 위해 L298N 모터드라이브 모듈을 사용합니다. 

특징

  • 디지털 구동전압 : DC 5V
  • 모터드라이브 전압 : 5~35V
  • 디지털 구동 전류 : 0~36mA
  • 드라이브 전류: 최대 2A
  • 동작 모드 : H-bridge

결선도

아래 링크에서 아두이노 보드용 라이브러리를 다운받아서 아두이노 IDE 소프트웨어가 설치된 디렉토리에서 하위 library 디렉토리에 붙여넣습니다.

라이브러리

 

소스코드

아래는 소스코드입니다. 아두이노 IDE에 붙여넣기 하여 컴파일하고 업로드합니다. 전진, 후진, 좌회전, 우회전의 간단한 모터제어를 해볼 수 있습니다.

 

#include <ControlMotor.h> // 라이브러리를 사용합니다.
// 아두이노 보드에서 사용할 핀을 설정합니다.
ControlMotor control(2,3,7,4,5,6); // 우측모터1,우측모터2,좌측모터1,좌측모터2,우측PWM,좌측PWM

int speed = 150; //모터속도를 저장할 변수를 선언합니다. 초기속도는 150입니다.

void setup() 
{
} 
 
void loop() 
{//한쪽 모터는 시계방향, 다른 모터는 반시계방향으로 회전합니다.
//따라서 자동차는 전진을 하게 됩니다. 속도는 점점 증가합니다.
 while(speed < 254){
 speed++;
 control.Motor(speed,1); 
 delay (200);}
//한쪽 모터는 반시계방향, 다른 모터는 시계방향으로 회전합니다.
//따라서 자동차는 후진을 하게 됩니다.
  control.Motor(-180,1);
  delay(3000);
//두 개의 모터가 시계방향으로 회전합니다.
//따라서 자동차는 왼쪽으로 회전합니다.
  control.Motor(200,100);
  delay(3000);
//두 개의 모터가 반시계방향으로 회전합니다.
//따라서 자동차는 오른쪽으로 회전합니다.
  control.Motor(200,-100);
  delay(3000);
//두 개의 모터가 정지합니다.
  control.Motor(0,1);
  delay(3000);
  
  speed = 150;//변수를 재설정합니다.
}

4. 최종 SPAC1N 아두이노 자동차 장애물 회피 구동

이제는 앞의 테스트를 바탕으로 최종적으로 SPAC1N을 구동해 봅니다.

 

소스코드

아래는 최종 소스코드입니다. 아두이노 IDE에 붙여넣기 하여 컴파일하고 업로드합니다. 초음파센서로 장애물을 확인하고 장애물을 피해서 SPAC1N이 이동을 합니다.

 


#include <ControlMotor.h>//모터제어 라이브러리를 사용합니다.
// 아두이노 보드에서 사용할 핀을 설정합니다.
ControlMotor control(2,3,7,4,5,6); // 우측모터1,우측모터2,좌측모터1,좌측모터2,우측PWM,좌측PWM

#include <Ultrasonic.h>//HC-SR04 초음파센서 라이브러리를 사용합니다.
Ultrasonic sensor(9,8,30000); // (Trig핀, Echo핀, 최대거리 단위는 us) 즉 30000us = 약 5미터

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

int mesurement_speed = 5;//센서 측정 속도를 조정합니다.
long int distance = 0; //거리를 저장할 변수를 선언합니다.
int random_value = 0;//랜덤값을 저장합니다. 


void Distance_display(int Distance) //LCD 거리표시 함수
{
  if((2<Distance)&(Distance<400)) // 거리가 3~399CM 인 경우
  {
    lcd.home();
    lcd.print("    Distance:   ");
    lcd.setCursor(6,2);
    lcd.print(Distance);
    lcd.print("cm      ");
  }
  else //센서 측정범위를 벗어난 경우
  {
    lcd.home();
    lcd.print("Out of range !!!");
    lcd.setCursor(6,2);
    lcd.print("        ");
    
  }
  delay(250);
  //lcd.clear();
}

void forward()
{
  control.Motor(150,1);
}

void backward()
{
  control.Motor(-150,1);
}

void turn_left()
{
  control.Motor(170,-100);
}

void turn_right()
{
  control.Motor(170,100);
}

void brake()
{
  control.Motor(0,1);
}

void setup() 
{ 
  lcd.init(); //LCD 초기화
  lcd.backlight(); //LCD 백라이트 ON
 
} 

 
void loop() 
{ 
  forward();//자동차가 전진합니다.
  distance=sensor.Ranging(CM);//거리를 측정하고 distance 변수에 저장합니다.

  delay(mesurement_speed);//센서측정 속도를 제어하기 위한 딜레이.

  Distance_display(distance);// LCD에 장애물과의 거리를 표시합니다.
 
  random_value = random (2);//자동차가 한쪽 방향으로만 회전하는 것을 막기 위해 랜덤값을 만듭니다.
  while(distance<30)  //장애물과의 거리가 30cm 이하일 경우에 적용됩니다.
  {
    //delay(mesurement_speed); //센서측정 속도를 제어하기 위한 딜레이.
    brake(); //모터를 정지시킵니다.
    //distance = sensor.Ranging(CM);
    delay(250);
    Distance_display(distance);// LCD에 장애물과의 거리를 표시합니다.

    if (distance<10) // 장애물과 거리가 너무 가까운 경우
    {
      backward();//자동차가 0.4초 동안 후진합니다..
      delay(400);
      brake(); //모터를 정지시킵니다.
      delay(500);
      distance = sensor.Ranging(CM); //거리를 측정합니다.
    }
    else
    {
      if(random_value==0) // 랜덤값이 0인경우에 해당됩니다.
      {
        turn_right();//자동차가 0.4초동안 오른쪽으로 회전합니다.
        delay(400);
      }
      else if (random_value==1) //랜덤값이 1인경우에 해당됩니다.
      {
        turn_left();//자동차가 0.4초동안 왼쪽으로 회전합니다.
        delay(400);
      }
      brake(); //모터를 정지시킵니다.
      delay(500);
      distance = sensor.Ranging(CM); //거리를 측정합니다.
      //delay(500);
    }
  }
} 

 

 

Topic: