May 28, 2020

디바이스마트 미디어:

[32호]너무 쉬운 아두이노 DIY ④ – 정원등과 공중회전그네

32아두이노04

 

글 | 신상석 ssshin@jcnet.co.kr

 

이 강의는 아두이노를 가지고 간단하게 생활에 필요한 용품을 만들어 보는 강의입니다. 뚝딱뚝딱 뭔가 자신만의 DIY 용품을 만들어 보는 쏠쏠한 재미가 있는 강의라고나 할까요? 이미 주변에 아두이노와 관련한 많은 책이 출간되었고 카페나 블로그를 통하여 강의가 진행된 경우도 꽤나 많이 있는데도 불구하고, 이 지면을 통하여 강의를 개설한 이유는 다음과 같습니다.

1. 아두이노의 초보자들을 위한 쉽고 재미있는 강의가 거의 없는 것 같아, 가능하면 초등학생(?)까지도 함께 해 볼 수 있는 그런 강의를 한 번 해보고 싶어서…
2. 아두이노를 가지고 뭔가 조금은 다른, 자신만의 창의적인(?) DIY를 할 수 있는 자리를 만들어주고 싶어서…
3. 디바이스마트매거진은 임베디드와 관련된 독자들이 많고, 발행 부수도 많아, 저와 제가 속한 회사(제이씨넷) 그리고 임베디드홀릭 카페의 홍보에 도움이 될 것 같아서…

현재 구상하고 있는 회차별 내용을 간략하게 정리해 보면 다음과 같습니다. (변경될 수 있습니다.)

회차 내용
1 3색 신호등 만들기
2 카멜레온 반지, 스위치를 이용한 신호등 게임기
3 FND로 만드는 디지털전압계, 카운트다운 계수기
4 어두워지면 켜지는 정원등, 공중회전그네
5 캐롤송 카드, 컬러링 온도계
6 스마트폰으로 조정하는 스마트카

앞으로 즐겁고 알찬 강의가 될 수 있도록 최선을 다할 것을 약속 드리며, 이 강의를 보는 독자들도 메일이나 카페를 통하여 Q&A(Question & Answer)나 피드백을 주셔서, 함께 정감을 나눌 수 있는 계기가 되기를 기대해 봅니다.

 

여러분, 안녕하세요. 항상 환한 강사 신상석입니다.
지난번 주제였던 [시한폭탄 카운트다운 계수기] DIY는 한 번 만들어 보셨나요? 양방향 대화가 아니어서 질문하는 것이 조금 멋적긴 하지만, “그래도 한 열 분 정도는 시도해보지 않았을까?” 라고 나름 생각하면서 즐겁게 계속 진도 나갑니다.

32PTB 4강 01
오늘은 [어두워지면 저절로 켜지는 정원등]과 [공중회전그네]를 만들어 볼까 합니다.
어둑어둑 해질 무렵의 놀이동산, 노오란 정원등이 하나 둘씩 저절로 켜지고 내가 좋아하는 공중회전그네가 빙글빙글 돌아가는 풍경… 많이 비슷하게는 안되겠지만 기분이라도 이렇게 낭만적으로 상상하면서 한 번 가보도록 하지요.

■ 광센서 ■ 

어두워지면 저절로 켜지는 정원등을 만들려면, 일단 어두워졌다는 사실을 알아야 합니다. 즉, 빛의 밝기를 측정할 수 있는 센서가 있어야 하는데, 이러한 센서를 광센서라고 합니다. 보통 광센서는 아래와 같이 생긴 황화카디늄(CdS) 센서를 많이 사용하는데, 이것은 황화카디늄(CdS) 성분이 빛이 밝아지면 전기저항값이 작아지고, 빛이 어두워지면 전기저항값이 커지는 성질이 있기 때문입니다. 오~ 저항값이 변한다면 가변저항의 역할을 할 수 있다는 것이므로 이 성질을 잘 이용하면 뭔가 해답이 나올 것 같지요? 세부적인 방법은 잠시 후에 기본 회로를 꾸며가면서 살펴보기로 하고 일단은 빛과 광센서에 대하여 먼저 알아보겠습니다.
빛의 밝기는 룩스(LUX)로 측정이 되는데, 엄밀한 정의는 이해도 어렵고 필요도 없으므로 룩스 값에 따른 예를 보면서 이해하는 것이 더 좋을 것 같습니다. 아래를 보시지요.

32 아두이노 02

사람마다 느끼는 것이 다르겠지만 우리는 위의 표와 같이 조금 어두워지는 것 같다고 느껴지는 저녁 황혼의 밝기인 10 룩스 정도에서 정원등이 켜지도록 하겠습니다.
이제 빛의 빛의 밝기에 따라 변하는 광센서의 저항값을 알아봅시다. 아래는 CdS 광센서중의 하나인 GL5537 광센서의 모습과 규격 일부입니다.

32 아두이노 03

우리가 측정하고자 하는 빛의 밝기인 10 LUX는 정도에서 약 20~50KΩ 정도의 저항값을 갖는 것으로 되어 있습니다. 조금은 틀려도 크게 문제는 없을 것이기에 우리는 이 때의 대표 저항값을 중간값인 35 KΩ 라 생각하고 진행하는 것으로 하지요.

■ 아날로그 센서 측정을 위한 기본 회로 ■ 

결국 광센서는 빛의 밝기에 따라 저항값이 변하는 가변저항의 역할을 하는 것이고, 우리의 아두이노는 아날로그 입력으로 전압값을 측정할 수 있는 능력이 있으므로 이 광센서의 저항값이 변함에 따라 특정 지점의 전압이 변하도록 회로를 꾸미면 아두이노로 광센싱이 가능하겠습니다. 지난번에 과제로 내주었던 [FND-과제-2]와 비슷한 회로가 될 것 같은데…
아래와 같이 회로를 꾸며 보도록 하지요.

32 아두이노 065

이렇게 연결한 후 (?V)로 표기된 부분을 아두이노의 아날로그 입력(A0~A5) 핀 중 하나에 연결하고(우리는 A1에 연결) 전압을 측정하면 현재 빛의 밝기를 알 수 있겠습니다. 즉, 광센서의 저항값을 R1, 여기에 직렬로 연결한 저항값을 R2(고정값)으로 설정하고, 양단에 전압 +5V를 인가하면 이 회로에 흐르는 전류(I)는,

5 = R1 x I + R2 x I 에서,
I = 5 / (R1+R2)가 되므로
아날로그 입력(A1)에서 측정한 전압값(?V)은
?V = I x R2 = (5 / (R1+R2)) x R2 가 됩니다.

R2는 고정값인 상수이므로 측정된 전압값(?V)를 알면 결국 R1 값을 구할 수 있고, R1 값을 알면 GL5537의 규격표에서 이에 대응되는 현재 빛의 밝기를 알 수 있게 되는 것이지요.
아하~ 그렇구나~

■ 어두워지면 저절로 켜지는 정원등

자, 이제 기초적인 원리는 이해가 되었으니 오늘의 주제 중 하나인 [어두워지면 저절로 켜지는 정원등]을 만들어 봅시다. 항상 그렇듯이 일단, 어떤 것을 만들 것인지 기능 규격부터 정해볼까요?

[기능 규격]
· 주변이 10 룩스 정도 밝기로 어두워지면 저절로 켜지는 정원등 제작
· LED를 정원등이라고 생각하고 LED의 ON/OFF 제어

※ 실제 정원등을 제어하려면 AC 전원이 연결된 정원등 스위치를 ON/OFF 하여야 하는데 이것은 릴레이로 스위치를 대신하고 이 릴레이를 제어하면 되므로, 여기서는 그냥 원리만을 알아보는 차원에서 정원등을 DC 5V에 대응되는 LED라고 가정하고 진행합니다.

기능 규격을 보니 우리가 공부한 기본 원리를 이용하면 바로 구현이 가능할 것 같습니다. 아래와 같이 하면 되겠네요.

[아두이노 연결]
· GL5537의 규격이 4KΩ ~ 2MΩ 정도의 범위에서 변하므로, 로그 스케일로 그 중간 정도에 있는 값인 200KΩ(또는 그 근처 저항)을 고정저항(R2)으로 선정
· [+5V --- GL5537 광센서 --- 200 KΩ 저항 --- GND] 형태로 회로를 구성하고 GL5537과 200KΩ 저항이 만나는 지점을 아두이노 A1 아날로그 핀에 연결(노란색 도선)
· 아두이노 D3핀(디지털출력, 녹색 도선)에 LED(직렬 저항 포함) 연결

32PTB 4강 04
[알고리즘]
정리된 알고리즘은 아래와 같습니다.

32 아두이노 07
10룩스일 때의 GL5537은 데이터시트에 보면 20~50 KΩ 으로 나타나므로 중간값인 35 KΩ 으로 추정하였을 때 위에서 공부한 이론을 적용하여 10룩스일 때의 전압값(?V)을 계산하여 보면, ?V = (5 / (R1+R2)) x R2 = (5 / (35 + 200)) x 200 = 5 x 200 / 235 이 됩니다. 5V에 대응되는 아날로그로 값은 1024이므로 위의 전압에 해당되는 아날로그 값을 계산하면 5 : 1024 = 5 x 200 / 235 : ?V 의 식으로 표현되므로 ?V 에 해당되는 값을 구하면 ?V = 5 x 200 x 1024 / 235 / 5 = 871 이 되겠습니다.

결론적으로, 위와 같이 연결한 회로에서 10룩스의 밝기가 되면 A0 핀으로는 871값이 읽히게 되므로, 읽은 값이 이 값 보다 작거나 같으면 정원등(LED)을 ON하고, 그렇지 않으면 정원등(LED)를 OFF하도록 스케치 프로그램을 작성하여야 하겠습니다.

[스케치 프로그램]
이제 모든 것이 결정되었으니 프로그램 작성이 가능하겠죠? 바로 갑니다.

const int LED=3;
const int CDS=1;
#define CDS_10 871 // 200/(35+200) * 1024, 10룩스일 때의 CDS 저항값인 35KΩ에 대응되는 아날로그 값 

void setup()
{
pinMode(LED, OUTPUT); // LED 핀은 출력
pinMode(CDS, INPUT); // 광센서 핀은 입력
}

void loop()
{
int value;
value = analogRead(CDS);
if (value <= CDS_10)
digitalWrite(LED, HIGH);
else
digitalWrite(LED, LOW);
delay(1000);
}

에러가 없다면 바로 업로드를 실행한 후 광센서(GL5537) 앞쪽으로 손바닥을 가깝게 가져갔다가 멀리했다가 하는 동작을 반복해 봅시다. 손바닥이 가까이 가면 빛을 차단하게 되므로 어두워져서 빛의 밝기가 10룩스 아래로 내려가게 되어 LED가 켜질 것이고, 다시 멀리하면 빛의 밝기가 10룩스 위로 올라가게 되어 LED가 꺼지게 되겠습니다. 동영상과 같이 된다면 이번 DIY도 성공이네요. 와우~~~

32PTB 4강 05

동영상 보러가기

한가지 더 알려드리고 싶은 것은, 시중에 나와 있는 센서는 광센서와 같이 가변저항의 성질을 이용한 것이 상당히 많다는 사실입니다. 예를 들어 온도센서는 주변 온도에 따라 저항값이 변하는 성질을 이용하며, 압력센서의 경우는, 압력에 따라 저항값이 변하는 성질을 이용하는 것입니다.

이러한 종류의 센서는 지금까지 사용한 방법과 비슷한 방법으로 쉽게 구현할 수 있으므로 이번 예를 잘 응용한다면 앞으로의 다른 DIY 작업도 식은 죽 먹기로… (윽. 너무 오버?)
자, 그러면 첫번째 DIY는 이쯤에서 마치고 잠시 후에는 오늘의 메인 DIY인 공중회전그네 제작에 도전해 보도록 하겠습니다. 조금은 쉬었다 가야겠지요? 모두 10분간 휴식~~~

…(1분)
…(2분)
…(3분)
…(4분)
…(5분)
…(6분)
…(7분)
…(8분)
…(9분)
…(10분)

편안한 휴식이 되셨나요? 그러면 이제 오늘의 메인 DIY인 공중회전그네에 도전해 봅시다.
처음으로 움직이는 작품을 만들어 볼 기회가 되겠네요.
우리가 할 수 있는 것 중에서 단순하면서도 재미있는 것을 이것 저것 생각하다가 찾은 것이 공중회전그네입니다. 이름이 정확한지는 잘 모르겠는데, 롯데월드에 제가 생각한 것과 비슷한 것을 하나 찾았습니다.

32PTB 4강 06
버섯처럼 생긴 부분이 돌아가면 거기에 매달려 있는 그네가 공중에 붕 떠서 도는 것이지요. 저도 타보지는 않았지만 요것, 일반 그네보다는 훨씬 재미있을 것 같으니 여러분도 기회가 되면 꼭 한 번 타보시기 바랍니다.

■  모터  ■ 

어떤 물건을 움직이려면 동력을 발생시키는 주체가 있어야 하는데, 이것이 모터입니다. 모터의 쓰임새는 거의 무한이어서, 자동차 바퀴, 선풍기 날개, 믹서기 커터, 비행기 프로펠러 등등 그 쓰임새는 셀 수가 없을 정도입니다. 그리고 꼭 회전이 아니더라도 자동문, 도어락, 포크레인 집게 등 생명체가 아니면서 움직이는 것의 대부분은 모터에 의한 것이라고 봐도 과언이 아니지요.

그러니까, 우리도 일단 공중회전그네를 만들기 전에 모터에 대하여 조금은 알고 넘어가는 것이 좋을 듯 합니다.
모터(Motor)는 우리말로 전동기라고 하는데, “전류가 흐르는 도체가 자기장 속에서 받는 힘을 이용하여 전기에너지를 역학적에너지로 바꾸는 장치”입니다. 뭔가 좀 어려운 설명인데, 우리는 그냥 “전기를 넣어주면 축을 중심으로 회전하는 것이 모터”다 라고 알아두면 되겠습니다.

어떤 전류를 사용하느냐에 따라 건전지 같은 전원을 사용하면 DC(Direct Current, 직류) 모터, 220V 같은 콘센트 전원을 사용하면 AC(Alternating Current, 교류) 모터로 구분합니다. 또한, 사용하는 형태에 따라서도 일반 모터, 서보(Servo) 모터, 스테핑(Stepping) 모터로 나눌 수가 있는데, 일반 모터는 그냥 왱~ 하면서 돌아가는 모터구요. 서보 모터는 일정한 각도 만큼만 회전하는 모터로 차단기, 자동문 등에 사용하는 모터입니다. 또한, 스테핑 모터는 아주 정밀한 각도를 움직일 수 있도록 만든 모터가 되겠습니다.

우리는 DC 모터를 사용할텐데, DC 모터는 보통 2개의 단자를 가지고 있고 이 단자의 양단에 모터의 정격에 알맞은 전압을 가하면 회전하게 됩니다. 또한, 일반적으로 2단자의 극성을 바꾸면 반대방향으로 회전하게 되지요.

그러면 이제 아두이노에 모터를 연결하는 방법에 대하여 간단히 알아보겠습니다.
요렇게 연결하면 될까요? (M 표시가 있는 것은 모터 심볼입니다.)

32PTB 4강 07
아두이노의 핀 하나(OUT1)를 모터의 한쪽에 연결하고, 모터의 다른 한쪽은 GND에 묶어 놓으면, 아두이노에서 제어가 가능할 것 같습니다. OUT1 = 1이면 모터가 돌고, OUT1 = 0 이면 모터가 정지하겠네요.
음. 한번에 완성?
반대 방향으로도 돌려야 할 필요성도 있겠네요. 모터는 보통 양단의 극성을 바꾸어 전원을 공급하면 반대 방향으로 회전하므로 아래쪽에도 GND 대신 포트를 하나 할당하는 것이 좋겠습니다. 값을 1, 0 마음대로 바꿀 수가 있으니까요. 아래와 같이 연결해 보지요.

32PTB 4강 08
오, 이렇게 되면, OUT1= 1, OUT2 = 0 인 경우는 모터가 정방향으로 돌고, OUT1 = 0, OUT2 = 1 이렇게 만들면 모터가 역방향으로 돌고… OUT1 = 0, OUT2 = 0 또는 OUT1 = 1, OUT1 = 1 이면…
OUT1 및 OUT2 양단 사이에 전위차가 없으니 모터가 정지할 것 같습니다. 괜찮은 설계가 된 것 같네요.

모두 만족? 음. 약간 부족한 것 같네요. 몇가지 더 생각할 게 있어요.
모터라는 녀석은 힘으로 먹고 사는 녀석이어서… 모터가 도는 힘에 비례하여 전류를 많이 소모합니다. 모터마다 5V-1A, 12V-2A, …, 이런 식으로 규격이 정해져 있지요. 요점은 OUT1 ▶ 모터 ▶ OUT2 방향으로 많은 전류를 흐르게 할 수 있는 지의 여부입니다. 예를 들어 1A의 전류를 모터로 흘려보내야 한다면 그 전류를 아두이노의 출력핀에서 공급하는 것이 가능한지를 살펴보아야 합니다. 오우~ NO! 아두이노 디지털출력핀은 전류를 많이 공급하지 못하네요. 기껏해야 한 신호당 약 40mA 정도가 최대랍니다. 엄청나게 모자라네요.
그렇다면 불가능할까요?
아니겠죠? 다른 방법이 당연히 있습니다.
이렇게 많은 양의 전류를 흘려야 하는 경우에는 전류를 아두이노 출력핀에서 직접 공급하지 않고 간접적으로 흐르게 하는 방법을 사용하여야 하는데, 이런 경우 가장 많이 사용하는 방법은 바로 트랜지스터를 이용하는 것입니다.
트랜지스터는 PNP형과 NPN형이 있는데 여기서는 NPN형을 기준으로 한 번 설명해 보겠습니다. 아래와 같이 생겼습니다.

32PTB 4강 09
여기서 B는 베이스(Base), C는 컬렉터(Collector), E는 에미터(Emitter)인데 아래와 같은 특징이 있습니다. (엄밀한 의미로는 틀릴 수 있는 내용이지만 여기서는 쉽게 설명하기 위하여 개념을 간략화 합니다.)

1. B-E(베이스-에미터)간 전압이 0.7V 이상 순방향으로 걸리면 트랜지스터는 턴-온(Turn-On)되었다고 하고, 이 때 C-E(컬렉터-에미터)는 서로 직접 연결된 것으로 간주합니다. (물론 0.2V 정도의 전위차가 있긴 하지만 그냥 직접 연결되었다고 생각해도 무방합니다.)

2. B-E(베이스-에미터)간 전압이 0.7V 이하이면 트랜지스터는 턴-오프(Turn-Off)되었다고 하고, 이 때 C-E(컬렉터-에미터)는 연결이 끊어진 것으로 간주합니다.

3. 턴-온 되는 경우 B-E 경로로는 수 mA 정도만 흘러도 C-E 경로로는 B-E 전류의 10~1000배 정도의 전류, 즉 수십 mA ~ 수 A 정도의 전류를 흘릴 수 있습니다. (그렇게 흘러도 아무런 문제가 되지 않습니다. 즉, 트랜지스터가 그 정도의 전류를 견디어 냅니다.)

PNP형의 경우는 NPN의 경우와 반대라고 생각하고, B-E간의 전압이 역방향으로 걸리면 턴-온 된다고 생각하면 됩니다.
그러면, 이제 이 트랜지스터를 이용하여 우리의 모터 연결을 수정하여 보겠습니다.

트랜지스터가 방향성을 가지므로, 정방향, 역방향을 모두 수용하려면 아래와 같이 2개의 경우가 생기겠네요. 왼쪽의 경우는 OUT1 = 1, OUT2 = 0 이면 Q1, Q2 트랜지스터가 모두 턴-온되어 모터가 회전하고, 오른쪽의 경우는 OUT1 = 0, OUT2 = 1 이면 Q3, Q4 트랜지스터가 모두 턴-온되어 모터가 회전하겠습니다.

32PTB 4강 10

이미 눈치 채신 분이 있으시겠지만 이 경우 트랜지스터는 턴-온, 턴-오프 상태를 갖는 스위치의 역할을 하게 되며, OUT1, OUT2 출력 신호는 아두이노가 생성할 수 있고, 모터에 흐르는 전류는 모두 VCC ▶ 트랜지스터 ▶ 모터 ▶ 트랜지스터 ▶ GND(접지) 로 흐르므로 모터의 전류 용량도 무난히 소화할 수 있겠습니다. 한가지 더 주의 깊게 보아야 할 것은 VCC로 표시된 전압은 +5V가 아니어도 괜찮다는 것입니다. 즉, OUT1이나 OUT2를 결정하는 로직 레벨과 무관하게 모터(M)의 정격에 알맞은 전압(예를 들어 3V~24V)을 걸어주면 된다는 것이지요. 오, 전류도 맘대로 되고, 전압도 맘대로 할 수 있으니, 일거양득(一擧兩得)! 신세대 은어로는 개이득이네요.

다시 돌아가서, 한 개의 모터를 가지고 위 2가지의 경우에 모두 적용되어야 하므로 이제 2개의 회로를 합쳐서 그려보겠습니다. 아래와 같이 될 것 같습니다. 모습이 H 형태와 비슷하다고 하여 이 회로의 이름을 ‘H-브릿지’라고 부릅니다.

32PTB 4강 11
일단, 맞는지 잘 확인해 보시지요. (특히, Q1, Q1, Q3, Q4 위치)
똑같죠? 왠지 멋져 보입니다.
그럼, 최종 점검해 보겠습니다.
OUT1 = 1, OUT2 = 0 이면 Q1 = ON, Q2 = ON, Q3 = OFF, Q4 = OFF이므로 아래 그림과 같이 VCC ▶ Q1 ▶ 모터(M) ▶ Q2 ▶ GND 방향으로 전류가 흘러서 모터가 순방향으로 회전합니다.

32PTB 4강 12
OUT1 = 0, OUT2 = 1 인 경우는 Q1 = OFF, Q2 = OFF, Q3 = ON, Q4 = ON 이므로 모터로 흐르는 전류 방향이 반대가 되므로 역방향으로 회전하겠네요. (여러분이 한번 전류 흐름을 그려보세요.)

또한, OUT1 = 1, OUT2 = 1 이거나, OUT1 = 0, OUT2 = 0 이면 VCC 쪽이거나 GND 쪽에 연결된 트랜지스터가 OFF 되어 모터로 전류가 흐르지 않으므로 모터는 정지하겠습니다.
이것이면 완전 끝인가요?
아쉽게도 좀 더 세부적으로 들어가면, 모터의 정격 전압, 전류 등에 대하여 제대로 알아야 하구요. 이를 구동할 트랜지스터의 타입, 전류 구동 능력, 관성 다이오드(flywheel diode)의 규격 및 이들의 상관 관계 등 세부적인 계산 방법은 간단하지가 않습니다. 또한, 잘못 연결하거나 맞지 않는 규격을 사용할 경우 모터나 트랜지스터에 손상을 일으킬 여지도 있어, 실제로 모터를 동작시킬 때에는 회로를 직접 꾸미기 보다는 이미 잘 동작하도록 제작된 전용 드라이버 칩 또는 이러한 칩을 사용하여 제작한 모듈을 사용하는 경우가 대부분입니다.
그러므로 우리는 기본 원리를 이해하는 정도에서 만족하고, 실제 DIY에서는 전용 모터드라이버 모듈을 사용하도록 하는 것으로 방향을 잡겠습니다.

■ 모터 드라이버 : JMOD-MOTOR-1 ■ 

모터드라이버는 앞에서 이야기한대로 모터를 쉽게 구동할 수 있도록 트랜지스터와 저항, 관성다이오드를 내장함은 물론 모터가 도는 방향도 선택하여 제어할 수 있는 구조를 가진 모듈을 의미하며, 시장에는 여러 종류의 모터드라이버가 출시되어 있습니다. 여기서는 우리의 목적에 적합한 모터드라이버로 제이씨넷 사의 JMOD-MOTOR-1이라는 모터드라이버를 사용하여 설명하도록 하겠습니다. (물론, 규격에 알맞은 다른 모터 드라이버를 사용하셔도 됩니다.)
JMOD-MOTOR-1 은 TB6612FNG 칩 기반의 2채널 DC 모터 드라이버입니다. 4.5V~13.5V 범위의 DC 모터를 사용할 수 있고 채널당 최대 1.2A 까지의 전류를 공급할 수 있으며 다른 모터드라이버에 비하여 효율이 상당히 높다는 장점을 가지고 있습니다. 2.54mm 핀헤더 타입 및 2×5 박스헤더 타입의 인터페이스를 함께 제공하여, 아두이노나 AVR 모듈 등과의 연결이 편리한 아래와 같이 생긴 제품(http://www.devicemart.co.kr/1160053)입니다.
세부 구조 및 핀 배치는 다음과 같습니다.

32PTB 4강 13

제품 상세보러가기

32PTB 4강 14
이론적으로 공부한 H-브릿지 드라이버와 실제 드라이버와의 매핑을 해보면 아래와 같이 됩니다. 한가지 다른 점은 TB6612에는 PWMA 라는 신호가 하나 더 있는데, 이것은 제어 입력인 AIN1, AIN2이 회전하는 경우 속도를 제어하기 위한 제어 신호로 PWMA가 High인 경우만 AIN1, AIN2 신호가 AO1, AO2로 그대로 전달되고, PWMA가 Low인 경우는 전달되지 않는다고 생각하시면 되겠습니다.

그렇다면 PWMA를 High로 했다가 Low로 했다가… 를 적당한 길이로 조정하면 모터가 돌다가 쉬다가… 할테니 속도를 조절할 수가 있겠습니다. 쉽게 설명하려고 했는데 설명이 더 어려운 것 같기도 하고…

32PTB 4강 15
어쨌든 결과적으로, 우리가 제어하여야 할 핀은 PWMA, AIN1, AIN2의 3핀이고, 이 3핀의 값에 따라 AO1, AO2가 결정되어, 결국 모터가 정회전(CW, ClockWise, 시계방향), 역회전(CCW, CounterClockWise, 반시계방향), 정지(Break, Stop) 기능을 아래 표와 같이 수행하게 됩니다. 조금 장황한 듯 하지만 결국 3개의 신호선만 우리가 원하는 대로 알맞게 출력해 주면 모터는 동작하는 것이지요.32아두이노 09

마지막으로, 모터 전원의 경우는 외부에서 따로 제공하여야 하며, +5V 전원이라 할지라도 아두이노에서 사용하고 있는 +5V 전원과는 다른 전원을 사용하는 것이 좋습니다. 왜냐하면 모터는 기본적으로 전류용량이 커서 최소 수백 mA 이상을 사용하며, 또한 모터 기동시에는 이것의 2-3배 정도의 전류가 더 필요하게 되므로, USB 케이블을 통하여 아두이노에 제공되는 전류 용량(보통 500mA)만으로는 부족한 경우가 많아 모터가 동작하지 않거나 아두이노가 리셋이 되는 경우 등 오동작하는 경우가 발생할 수 있기 때문입니다.

■ 간단한 선풍기 ■ 

자, 이제 이론적인 준비가 끝났으니 DIY 작품을 만들어 보도록 하지요. 공중회전그네를 만들기 전에 먼저 간단한 선풍기를 만들어보겠습니다. 선풍기를 만든 다음에 요것을 변신시켜서 공중회전그네를 만들거랍니다.
기본 재료인 모터는 3V DC 모터인 WRE-260을, 소형프로펠러는 아래와 같이 생긴 프로펠러를 사용하도록 하겠습니다. 다른 이유는 없고 그저 값이 싸다는 이유이므로, 다른 모터를 사용하여도 되고, 프로펠러는 그냥 간단히 스카치테이프나 색종이 등을 모터 축에 오려 붙여서 만들어도 되겠습니다.
다행이도 프로펠러는 모터에 꼭 맞네요.

32PTB 4강 16 32PTB 4강 17

 

[기능 규격]

· 소형 DC 모터에 모형 날개를 달고 아두이노로 제어하여 간단한 선풍기 제작
· 5초간 정회전, 2초간 정지, 3초간 역회전, 2초간 정지를 반복 실행

[알고리즘]
정리된 알고리즘은 아래와 같습니다.

32아두이노 09

· 위의 표에서 정회전, 역회전, 정지에 해당되는 PWMA, AIN1, AIN2 값을 정해진 시간 동안 차례로 출력

[아두이노 연결]
PWMA는 아두이노 5번핀에 할당하고, AIN1과 AIN2는 각각 7번핀, 8번핀에 할당

32PTB 4강 18
※ 참고 : 모터 전원용으로 배터리(팩)를 연결할 때 배터리의 (+)는 JMOD-MOTOR-1의 VCC에 직접 연결하고 GND는 아두이노의 GND에 연결하면 추가 배선없이 연결됩니다. 모터가 3V용이어서 1.5V 건전지 2개를 직렬로 연결하여 모터 전원(VCC)에 공급하면 됩니다.

[스케치 프로그램]
자, 이제 연결은 되었으니, 프로그램해서 돌려 봅시다.
장황하게 왔는데, 프로그램은 항상 너무 간단하죠.

const int MOTOR_PWM = 5; // 모터 PWM 입력핀, PWM핀으로 할당
const int MOTOR_IN1 = 7; // 모터 IN1 입력핀
const int MOTOR_IN2 = 8; // 모터 IN2 입력핀 

void setup()
{
pinMode(MOTOR_PWM, OUTPUT);
pinMode(MOTOR_IN1, OUTPUT);
pinMode(MOTOR_IN2, OUTPUT);
}

void loop()
{
digitalWrite(MOTOR_PWM, HIGH); // 3초간 선풍기 정회전
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, LOW);
delay(3000);
digitalWrite(MOTOR_PWM, LOW); // 3초간 선풍기 정지
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
delay(3000);
digitalWrite(MOTOR_PWM, HIGH); // 3초간 선풍기 역회전
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, HIGH);
delay(3000);
digitalWrite(MOTOR_PWM, LOW); // 3초간 선풍기 정지
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, HIGH);
delay(3000);
}

으, 별 것 없죠?
실행 결과은 어떻게 되었나요?
아래 동영상처럼 잘 돌아가나요? 작은 선풍기인데 생각보다는 꽤 쌩쌩~~~ 도네요.

32PTB 4강 19

동영상 보러가기

■ 공중회전그네 

자, 이제 드디어 마지막 목적지인 공중회전그네 DIY 입니다. 앞에서 제작한 선풍기를 약간 개조하여 공중회전그네를 만들어 보겠습니다. 아마도, 어떻게 만들지 벌써 감을 잡으신 분들이 대부분이겠지요?

선풍기를 꺼꾸로 매달아 공중회전그네의 동력으로 쓰고, 선풍기 날개 끝에 구멍을 뚫어 그네를 매달아 회전을 시키는 형태로 하면 될 것 같습니다. 사용하고 싶은 재료를 자유롭게 골라서 만들면 될 것 같구요. 저는 그네줄은 점퍼케이블로 구현하고, 그네는 그냥 클립으로 찝어 그네라고 우기면서 간단히 꾸며려 합니다.

놀이기구이니까 그냥 도는 것 보다는 회전 속도와 회전 방향을 랜덤하게 하면 좀 더 재미가 있을 것 같으니 그렇게 한 번 해보지요.

[기능 규격]
· 여러명의 사람을 태울 수 있는 공중회전그네
· 한 번은 시계 방향, 한 번은 반시계 방향 회전하며 회전 후에는 2초간 정지
· 한 번 회전시 1~9초간 랜덤 시간 회전
· 저속, 중속, 고속의 랜덤 속도로 회전

[필요 함수]
randomSeed(seed)

· 난수 초기화 함수
· seed : 난수 초기화를 위한 초기값

랜덤한 값을 만들어 내기 위한 초기값을 결정하는 함수로 seed값에 따라 랜덤한 값의 시작점이 달라짐. seed값도 랜덤하게 하기 위하여 이 값을 analogRead(A0) 를 수행한 값으로 하면 임의의 랜덤값을 얻을 수 있음

random(min, max) 또는 random(min)

· 난수값 생성 (리턴값)
· min : 난수값의 최소값 (범위 포함)
· max : 난수값의 최대값 + 1 (범위 불포함)

랜덤한 값을 만들어 내는 함수로 min, max 값을 주어 랜덤값의 범위를 결정함

[알고리즘]
정리된 알고리즘은 아래와 같습니다.

32 아두이노 08

여기서 주의하여야 할 점은 2가지입니다.
하나는 난수 생성을 어떻게 하는가 하는 것인데, 앞에서 배운 것처럼, 난수를 발행하려면 초기값을 생성해 주어야 하며 이 함수는 random(seed)입니다. 여기서 seed 값에 따라 난수표의 초기 위치가 결정되므로 seed 값도 random으로 입력할 수 있으면 진정한 난수가 될 수 있겠지요. 그래서 보통 사용하는 방법은 이 seed 값을 analogRead(0), 즉 아날로그 포트 0에 아무 것도 연결하지 않은 상태를 읽는 방법을 사용합니다. 포트 0에 신호를 연결하지 않고 그냥 읽으면 일반적으로 0~1023 사이의 랜덤한 값이 읽히게 되는 전기적인 현상을 이용하는 것이지요.
두번째는 속도를 결정하여 이것을 출력하는 것인데, PWM핀에 출력할 때는 이전 예제와는 다르게 digitalWrite( ) 함수를 사용하면 안되고 analogWrite( ) 함수를 사용하여야 한다는 점입니다.
즉, 고속, 중속, 저속의 3가지 경우에 각각 적당한 0~1023 사이의 PWM 값을 결정하여 analogWrite(PWM포트, PWM값)의 형태로 사용하여야 하겠습니다. (실제로는 돌려보고 적당한 값으로 튜닝하는 것이 맞겠네요.)
프로그램은 선풍기 프로그램을 기본으로 난수 발생 함수만 잘 요리하면 되겠습니다. 혼자서도 하실 수 있는 분들은 아래를 보기 전에 먼저 혼자 해 보시구요.

아래와 비슷하게 되겠네요.

const int MOTOR_PWM = 5; // 모터 PWM 입력핀, PWM핀으로 할당
const int MOTOR_IN1 = 7; // 모터 IN1 입력핀
const int MOTOR_IN2 = 8; // 모터 IN2 입력핀 

#define PWM_HIGH 320 // 빠른 속도, 그네 무게에 따라 조정 필요
#define PWM_MID 80 // 중간 속도, 그네 무게에 따라 조정 필요
#define PWM_LOW 20 // 느린 속도, 그네 무게에 따라 조정 필요
#define PWM_ZERO 0 // 정지

void setup()
{
int value;
pinMode(MOTOR_PWM, OUTPUT);
pinMode(MOTOR_IN1, OUTPUT);
pinMode(MOTOR_IN2, OUTPUT);
value = analogRead(0); // A0 포트에 아무런 입력 신호가 없으면 random한 값이 읽혀지는데 이것을 사용
randomSeed(value); // 위 값을 난수 발생의 초기값(seed)으로 사용
}

void loop()
{
int random_value, level;
random_value = random(1, 4);
switch (random_value)
{
case 1: level = PWM_HIGH; break;
case 2: level = PWM_MID; break;
case 3: level = PWM_LOW; break;
default: break;
}
analogWrite(MOTOR_PWM, level); // 한 번은 정회전
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, LOW);
delay(random(1,10)*1000); // random(1,10)의 결과는 1~9까지의 정수, 즉 1초~9조간 임의의 시간 동안 회전
analogWrite(MOTOR_PWM, PWM_ZERO);
// 한 번 회전 후에는 항상 2초간 정지
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
delay(2000);
analogWrite(MOTOR_PWM, level); // 다음 번은 역회전
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, HIGH);
delay(random(1,10)*1000);
// random(3,9)의 결과는 1~9까지의 정수, 즉 1초~9조간 임의의 시간 동안 회전
analogWrite(MOTOR_PWM, PWM_ZERO);
// 한 번 회전 후에는 항상 2초간 정지
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
delay(2000);
}

돌려 본 결과는 아래와 같습니다.

32PTB 4강 22 32PTB 4강 23

동영상 보러가기

 

빌빌빌… 돌기도 하고, 약간 썡~ 돌기도 하네요.

어쨌든 제가 원했던 공중회전그네와 비슷합니다. 저는 만족!
만들고 시험하노라면 시간이 조금 많이 걸리기는 하는데… 그래도 나름 재미있는 DIY를 해 본 것 같습니다.
저는 사실 조금 게을러서… 꾀를 내어 간단히 만들어 보았지만 여러분은 좀 더 멋있게 정말 공중회전그네처럼 만들어서 동작시켜 보시기를 기대해 보겠습니다.
여기까지 함께 하시느라 고생하셨구요.

다음에는 좀 더 즐겁고 재미있는 내용으로 환하게 다시 만나겠습니다! 모두모두, 안녕~~~

32 아두이노 100

 

Leave A Comment

*