본문 바로가기

IT/아두이노

아두이노와 조도센서를 활용해 서보모터를 조작하기

반응형

안녕하세요.

 

오늘은 아두이노와 조도센서를 활용해 서보모터를 조작해보겠습니다.

 

1. 회로 구성과 코드

(1) 부품 리스트

  • 서보모터
  • 조도센서
  • 10K 저항
  • 미니 브레드 보드
  • F-F 점퍼선(양쪽 모두 뾰족한 점퍼선)
  • 아두이노 우노

(2) 연결

ㄱ. 조도센서

우선 조도센서는 연속적인 값을 입력 받아야 하므로

아두이노의 A0핀에 연결합니다.

A0 핀은 아날로그 핀으로, 연속적인 값인 아날로그 값을 읽을 수 있는 핀입니다.

이때, 10K 저항과 GND에 같이 연결해줘야 합니다.

마지막으로 조도센서의 나머지 핀은 5V 핀에 연결합니다.

 

자세한 회로 연결은 아래 사진을 참고해주세요.

빨간색 선은 5V

파란색 선은 GND

노란색 선은 A0

요렇게 연결되어있습니다.

여기서 아두이노 조도센서 코드를 알려드리겠습니다.

void setup() {
	Serial.begin(9600);
	int Light = analogRead(A0);
}

void loop() {
	Serial.println(Light);
}

코드가 정말 단순하죠?

 

아두이노에서 void setup()은 처음 아두이노에 전원이 인가되었을때 한번만 실행하는 코드를 담는 공간입니다.
{ }요 괄호 안에 코드들을 넣으면 됩니다.

 

여기서는 Serial.begin(9600);이라는 명령어를 넣었는데,

아두이노 보드의 시리얼 통신의 시작을 알리고, 전송 속도를 지정하는 명령어입니다.

9600이 바로 전송 속도인데, 보통은 9600의 속도로 통신합니다.

 

int Light = analogRead(A0);는 조도센서에서 읽은 값을 변수에 저장하는 코드입니다.

변수는 값을 담는 상자라고 생각하시면 되는데, Light라는 변수를 설정해주는 겁니다.

int는 정수형 변수를 선언하라는 의미입니다.

analogRead(A0)는 아날로그 값을 읽어들이는 코드입니다.

우리는 A0핀에 조도센서를 연결했으니 A0라고 입력해둔 것입니다.

 

또한 void loop()는 아두이노에 전원이 인가되어있는 동안 반복해서 실행되는 코드를 담는 공감입니다.

역시 { } 괄호안에 코드들을 넣으면 됩니다.

Serial.println(Light); 시리얼포트로 값을 출력하는 코드입니다.

Light라는 변수에 센서 값을 담아두기로 했으므로,

변수의 이름을 집어넣어 변수 값을 출력해줍니다.

 

ㄴ. 서보모터

서보모터는 세개의 핀을 사용합니다.

5V 전압을 입력받는 붉은 핀

GND와 연결하는 갈색 핀

PWM 신호를 입력받는 주황핀 입니다.

저는 5V와 GND를 각각 아두이노에 연결해준 뒤

PWM 핀은 7번 핀에 연결해주었습니다.

아두이노에서 디지털 핀은 PWM(Pulse Width Modulation)출력을 지원합니다.

 

여기서 디지털 핀은 디지털이라는 의미 대로 0과 1의 값만 출력할 수 있는 핀입니다.

그리고 PWM(Pulse Width Modulation)은 '주기 폭 변조'라는 이름 답게

0과 1 값을 출력하는 주기를 변형시켜 다양한 값을 출력할 수 있습니다.

 

말로만 설명하면 좀 어렵죠?

위 그림을 보시면 조금 더 이해하기 편하실 겁니다.

0V와 5V의 값만 출력 가능하고,

파형의 모양에 따라 다른 값을 가지게 됩니다.

 

사설이 좀 길었는데, 결국 너무 깊이 알진 않아도 상관 없습니다.

일단 결선을 해볼까요?

위 그림과 같이 결선을 해주시면 됩니다.

 

이제 서보모터 조작 코드를 알려드릴게요.

#include <Servo.h>

#define SERVO 7

Servo servo;

void setup() {
	servo.attach(SERVO);
}

void loop() {
	servo.write(angle);
	delay(1000);
}

조도센서와는 좀 다르죠?

#include <Servo.h>는 라이브러리를 사용하기 위한 코드입니다.

라이브러리는 특정 목적을 위한 코드들을 미리 모아놓은 집합체입니다. 

우리는 서보모터를 제어하는게 목적이므로

서보모터를 제어하는 코드들이 담겨있는 Servo.h라는 라이브러리를 사용하는 것입니다.

 

#define SERVO 7은

SERVO라는 변수에 숫자 7을 할당하라는 의미입니다.

 

Servo servo;는 우리가 사용할 서보모터를 servo라는 변수로 선언해주는 의미입니다.

 

servo.attach(SERVO);는 우리가 사용할 서보모터 servo를 아두이노 핀에 할당해준다는 의미입니다.

SERVO라는 변수에는 아까 7이라는 숫자를 할당해주었죠?

결국 servo라는 서보모터에 7번 핀을 할당하라는 의미입니다.

이 코드는 여러번 수행할 필요 없으므로 void setup() 부분에 넣어줍니다.

 

servo.write(angle);은 서보모터를 특정 각도로 움직이라는 의미입니다.

angle이라고 적힌 칸에는 필요한 각도를 지정해주면 됩니다.

 

delay(1000);은 아두이노 명령어 사이에 지연시간을 주라는 의미입니다.

1000은 1000ms로, 1초를 의미합니다.

 

ㄷ. 조도센서 + 서보모터

이제 각 부품의 사용 방법을 알았으니 이제 조도센서 값에 따라 서보모터를 움직여보겠습니다.

// 서보모터를 제어하기 위해 Servo.h 라이브러리를 포함합니다.
#include <Servo.h>

// SERVO라는 변수에 숫자 7을 할당합니다.
#define SERVO 7

// servo라는 객체를 생성해줍니다.
Servo servo;

// 정수형 변수인 angle에 숫자 0을 할당합니다.
int angle = 0;

// void setup은 아두이노에서 처음에 한번만 실행시킬 코드를 집어넣는 곳임
void setup() {
	
	// servo.attach(SERVO)는 서보모터를 몇번 핀으로 컨트롤 할지를 설정하는 함수.
	// servo.attach(숫자) 형태로 사용한다.
	// SERVO라는 변수에 저장된 숫자가 7이므로 7번 핀에 연결된 서보 모터를 제어한다는 뜻.
	servo.attach(SERVO);
}

// void loop는 아두이노에서 계속 반복할 코드를 집어넣는 곳임.
void loop() {
	
	// analogRead(A0)는 몇번 핀에서 아날로그 값을 읽어들일지를 설정하는 함수.
	// analogRead(핀번호) 형태로 사용한다. 
	// 정수형 변수 Light에 A0핀에서 읽어들인 아날로그 값을 저장한다.
	int Light = analogRead(A0);
	
	// angle이라는 변수에 map() 함수를 사용해서 서보모터의 각도를 설정한다.
	// map() 함수는 map(변수, 변수의 최소값, 변수의 최대값, 변환할 최소값, 변환할 최대값) 형태로 사용한다.
	// 우리는 Light 변수에 저장된 값을 불러오며, 이 변수에 저장된 값의 최소값과 최대값을 각각 0과 1023으로 지정한다.
	// 그리고, 0과 1023 사이의 값을 0과 180 사이의 값으로 변환한다.
	angle = map(Light, 0, 1023, 0, 180);

	// servo.write(angle)은 서보모터를 지정한 각도로 움직이는 함수.
	// servo.write(숫자) 형태로 사용한다.
	// angle이라는 변수에 각도가 숫자로 저장되므로 해당 각도로 서보모터를 움직인다는 뜻.
	servo.write(angle);
    
	// delay(1000) 는 동작 사이에 대기시간을 주는 함수
	// delay(숫자) 형태로 사용한다.
	// 단위는 ms이며, 1000을 넣으면 1초간 대기한다.
	// 여기서는 1000을 넣었으니 1000ms(=1초) 동안 대기한다. 
	delay(1000);
}

일단 전체 코드와 주석입니다.

여기서 중요한 부분은

angle = map(Light, 0, 1023, 0, 180); 부분입니다.

angle이라는 변수에 map이라는 함수를 이용해서 각도를 매핑해줍니다.

map 함수는 아래와 같이 사용합니다.

map(입력값, 입력값의 최소값, 입력값의 최대값, 최소각도, 최대각도);

우리는 Light라는 변수에 조도센서에서 읽어들인 값을 집어넣으므로

입력값 부분에는 Light를 집어넣습니다.

조도센서는 0부터 1023사이의 값을 인식할 수 있으므로

입력값의 최소값과 최대값은 0과 1023을 집어넣습니다.

그리고 우리가 다루는 서보모터는 0도에서 180도까지 동작할 수 있으므로

최소각도와 최대각도는 0과 180을 집어넣습니다.

 

설명은 길었습니다만, 결국 map이라는 함수는

0~1023의 값을 가지는 조도센서의 값을

0~180의 각도로 변환시켜주는 함수입니다.

 

이렇게 조도센서의 값을 각도로 변환해서, angle이라는 변수에 집어넣는 것입니다.

 

아래 영상은 회로의 동작 모습입니다.

조도센서를 손가락으로 가리니 서보모터가 동작하고 있습니다.

 

2. 동작 원리

(1) 조도센서

본문에서 사용한 조도센서는 빛의 양에 따라 저항의 세기가 달라지는 일종의 가변저항입니다.

기본적으로 조도센서에 전류가 흐르고, 빛의 양에 따라 조도센서의 저항값이 달라지고,

조도센서에 흐르는 전류의 세기가 달라집니다.

 

조도센서에 붙여준 10K 저항은, 5V의 전압이 조도센서에 그대로 흐를 경우 조도 센서가 타버릴수도 있으므로

전압을 조금 낮춰주기 위해 붙여주는 것입니다.

 

(2) 서보모터

서보모터의 내부에는 여러개의 기어가 맞물려있고, 특정 기어에 가변저항이 연결되어있습니다.

모터가 돌아가면 가변저항도 돌아가고, 가변저항 값의 변화를 인지하여 현재 각도가 몇도인지 알 수 있게 됩니다.

만약 아두이노에서 서보모터를 90도까지 회전시키라는 명령을 내리면,

서보모터 안에 있는 가변저항이 돌아가다가 90도에 해당하는 가변저항 값에 도달했을때 멈추게 되는 것입니다.

 

3. 마치며

센서값에 따라 모터를 제어하는 회로는

아두이노를 다루다 보면 정말 많이 만날 수 있는 형태입니다.

이렇게 복합적인 형태의 회로를 분석할때는

전체 회로를 한번에 분석하는것보다

센서만 떼어서, 모터만 떼어서 분석하는 것이 훨씬 이해하기 편합니다.

반응형