아두이노 블루투스 배터리 - adu-ino beullutuseu baeteoli

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

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

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

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

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

여러분, 안녕하세요.
쏜살갈이 시간은 흘러 어느덧 [너무 쉬운 아두이노 DIY] 강좌의 마지막 회입니다. 지난해 따뜻해지는 봄 기운을 느끼며 첫 회를 시작했는데, 시기도 적절하게 겨울 자락에 마지막 회로 마감하게 되었습니다. 유종지미(有終之美), ‘끝을 잘 맺는 아름다움’의 의미처럼 함께 마무리를 잘 해 보도록 하겠습니다.
오늘의 주제는 ‘스마트폰으로 조종하는 스마트카’입니다. 스마트폰으로 조종하여 전진, 후진, 좌회전, 우회전 및 정지가 가능한 스마트카를 만들어 보겠습니다. 마지막이어서 조금은 어려울 수도 있겠지만 그동안 기본기를 많이 갈고 닦았으므로 무난히 다 잘 하실 수 있으리라 생각합니다.
스마트카는 요즈음 IT에서 핫이슈가 되고 있는 분야입니다.
구글은 완전한 자율주행이 가능한 자동차를 2018년까지 출시하기로 하고, 현재 상당한 진전을 이루고 있는 상태입니다. 3D 카메라, 레이저, 음파 센서, GPS 등의 다양한 전자기기가 장착되고 있으며, 이들을 통합 제어하는 구글오토라는 소프트웨어도 탑재하고 있습니다. 스마트카 시장에는 구글뿐만 아니라 테슬라, 애플 등의 IT업체와 BMW, 폭스바겐 등의 완성차 업체도 도전장을 내놓은 상태입니다. 이쪽 동네 이야기는 일단 시작하면 이야기가 길어지므로… 여기서 싹둑, 다시 본론으로 돌아갑니다.
우리는 동작 원리에만 중점을 두어 최소한의 기능만 포함된 아주 간단한 스마트카를 만들어 보도록 하겠습니다.

■ 내 자동차(Bory) 규격 및 준비물   

자동차의 종류는 다양하여 승용차도 있고 트럭도 있고, 승용차 중에도 고급 승용차도 있고, 경차도 있지만 우리의 자동차는 그저 차체 프레임에 바퀴가 달려있어 굴러갈 수 있는 정도의 자동차로 일단 한정하겠습니다. 하지만 진짜 자동차에는 없는 기능으로, 스마트폰으로 명령을 내릴 수도 있고, 장착 여부에 따라서는 라인트레이서나 자율주행자동차도 될 수 있는 꽤 멋진 DIY 자동차가 될 수 있을 것입니다.
일단 이름을 먼저 정하고 규격을 정한 다음 차근차근 구현해 보도록 하지요. 제 자동차의 이름은 보리(Bory)로 하겠습니다. 예전에 집에서 애완용으로 키웠던 페릿에게 붙여준 이름인데요. 이름이 구수하고 정겨워서 이것으로 합니다. 여러분도 자기 나름대로 이름을 붙이고 시작해 보시기를….
자, 그러면 다음 단계로 규격을 정해볼까요?

[보리(Bory) 스마트카 규격]
· 스마트폰의 앱으로 전진, 후진, 좌회전, 우회전 운행 가능
· 아두이노 UNO로 제어
· 크기는 손바닥 크기 정도
· 뒤쪽에 바퀴 2개(모터 장착), 앞쪽에 바퀴(캐스터) 1개(모터 미장착, 지지대용)
· 전원은 건전지(또는 리튬전지) 등의 휴대용 전원으로 공급

[보리(Bory) 스마트카 형태]
아래 JARDUINO-UNO-CAR(V2.0)과 비슷한 모습


이러한 규격을 만족하기 위하여 필요한 부품을 살펴보면 아래와 같이 될 것 같습니다.

1. 아두이노 UNO가 있어야 하고,
2. 차체(프레임)가 있어야 하겠습니다.
3. 차체에 연결할 바퀴가 2개 있어야 하고,
4. 앞쪽에는 캐스터(지지용 바퀴)가 1개 필요합니다.
5. 바퀴 2개를 구동하려면 모터(DC 모터)가 2개 필요하겠죠?
6. 이 모터를 구동할 모터 드라이버도 역시 준비해야겠네요..
7. 스마트폰과 통신을 하기 위해서는 블루투스 시리얼 모듈이 있어야 하고,,
8. 스마트카의 전원으로는 모터에 전원을 공급할 배터리(홀더)가 필요하며, 아두이노와, 모터드라이버, 블루투스 시리얼 모듈에 전원을 공급할 배터리(홀더) + 전원공급기가 필요하겠습니다. (일반적으로 모터는 전류를 많이 사용하고, 순간적인 과전류로 인한 전압강하도 일어나는 부품이므로 아두이노나 다른 부품과는 다른 전원을 사용하는 것이 좀 더 안전한 방법이기 때문에 2개의 다른 전원 소스를 사용하는 것이 좋습니다.)
9. 마지막으로 모터(바퀴)나 캐스터 등을 차체에 고정할 브라켓이나 서포터, 나사, 전선 등도 다수 필요하겠습니다.

이 부품들은 따로 따로 하나씩 임의로 구해도 되지만 너무 복잡하므로 일정 부분 이미 상품으로 제공되는 것을 사용하도록 하겠습니다. 아래와 같이 정리가 되겠네요.

부품개수기능기타아두이노 UNO1스마트카 제어아두이노 UNO
정품 및 호환 제품JKIT-CAR-12아두이노 AVR 카 베이스 (차체 1개, 바퀴 2개, 모터 2개,
캐스터 1개, 건전지홀더 1개, 브라켓 및 서포터, 나사 다수 포함,
아두이노/AVR은 미포함)JMODMOTOR-114.5~13.5V, 1.2A, 2채널 모터 드라이버(바퀴 구동)JMOD-BT-11블루투스 시리얼 모듈 (스마트폰과 통신)JBATT-U5-LC (리튬전지 포함)1아두이노 및 기타 모듈에 전원 공급소형 브레드보드1HC-SR04 장착용JKIT-CAR-1 + 아두이노 UNOJMOD-MOTOR-1JMOD-BT-1리튬전지 + JBATT-U5-LC

그러면 위의 부품들을 가져다가 대충 한 번 연결해 보지요. 이런 형태가 될라나요?


기계적인 부분을 제외하면, 조금 더 자세하게 살펴보아야 할 부품은 모터드라이버, 블루투스 시리얼 모듈 정도인데, 모터드라이버는 이전 강좌에서 자세히 다루었으므로 생략하고, 블루투스 시리얼 모듈에 대해서만 기초 지식을 조금 더 보충한 후에 본격적인 스마트카 제작에 나서겠습니다.

■ 시리얼 통신    

블루투스 시리얼 모듈의 동작을 이해하려면 먼저 UART(Universal Asynchronous Receiver/Transmitter) 시리얼 통신에 대한 기초 지식을 갖추어야 합니다.
일반적으로 컴퓨터나 전자기기 간에 데이터나 정보를 주고 받는 행위를 통신이라고 하는데, 이들은 사람이 아니므로 반드시 미리 정해진 규칙을 따라야만 통신이 가능합니다. 예를 들어, 나는 한국어로 이야기하고, 상대방은 아랍어로 이야기한다면 서로 알아들을 수가 없다는 것이지요. 한국어면 한국어, 아랍어면 아랍어 등, 한가지 규칙을 가지고 이야기해야만 대화가 가능하며, 이 경우도 사용하는 언어를 양쪽 사람이 모두 자유롭게 정확한 의미로 사용할 수 있어야 한다는 것은 물론입니다.
아두이노도 외부 PC나 전자기기와 통신할 수 있는 통신 규칙(보통 통신 프로토콜(Communication Protocol)이라고 함)을 가지고 있는데, 그 중 대표적인 것이 시리얼통신입니다. 통신을 하려면 상대방과 연결되는 통로가 있어야 하는데, 여기서 돌발 퀴즈!
아두이노가 PC와 통신을 한다고 하면 어떤 통로를 이용하여 통신을 할까요?

10초 드립니다. 10, 9, 8, 7, 6, 5, 4, 3, 2, 1. 종료!

뭐죠? USB 케이블? 예. 맞습니다. 아두이노가 PC와 연결되어 있는 것은 이것 한 개밖에 없으니까요. USB(Universal Serial Bus) 케이블은 피복에 싸여서 속을 볼 수는 없지만 이를 절단해 보면 보통 4개의 전선으로 구성되어 있습니다. 2개는 +5V와 GND 선으로 PC에서 아두이노로 전원을 공급해 주는 전원 선이고, 나머지 2개는 데이터를 주고 받는 통신 선입니다. 아두이노는 이 데이터 라인을 통하여 PC와 정보를 주고 받는데 이 통신 프로토콜을 시리얼(Serial) 통신이라고 합니다. (엄밀하게 말하면 시리얼 통신의 의미는 데이터를 한 개씩 순차적으로(Serial) 보내고 받는다는 일반적인 용어이고, 실제로 여기서 사용되는 통신은 UART(Universal Asynchronous Receiver/Transmitter)라는 이름의 프로토콜을 사용하지만 보통 아두이노에서 시리얼 통신이라고 하면 이 방식을 의미합니다.) 점점 복잡하게 만드는 것인지는 모르겠지만 좀 더 엄밀하게 말하면 USB 방식도 다양한 시리얼통신 방식 중의 하나이고 여기서는 (PC쪽 UART ←→ UART를 USB 방식으로 변환) ←→ USB 케이블 ←→ (USB를 UART 방식으로 변환 ←→ 아두이노쪽 UART) 형태로 사용되므로, 실제 눈으로 보이는 것은 USB 케이블이지만 PC와 아두이노 양쪽에서 사용하는 진짜 통신 방식은 UART 방식입니다. 아두이노에서 시리얼통신이다하면 우리는 그냥 이 UART방식으로 통신한다고 생각하면 되겠습니다. 어려운걸 쉽게 설명하려니 더 어렵네요. 이 말이 더 어렵나요?
사실 시리얼통신(UART통신)의 세부적인 동작을 이해하는 것은 조금 시간이 걸리는 이야기인데, 여기서는 그냥 아래와 같은 특징을 가지고 동작한다고 이해하는 정도로 넘어가겠습니다.

[시리얼 통신 기능/동작 설명]
(1) 사용하는 통신라인(신호)은 TxD, RxD, GND의 3개 선입니다.
TxD는 송신 데이터, RxD는 수신 데이터, GND는 접지(0V) 신호이며, 통신하고자 하는 쌍방은 GND-GND, TxD-RXD, RxD-TxD의 짝으로 연결하여야 합니다. TxD는 Transmit Data의 약어로 송신 데이터를 의미하고, RxD는 Received Data의 약어로 수신 데이터를 의미하지요. 한쪽에서 TxD로 데이터를 보내면 상대방은 RxD로 데이터를 받아야 하므로 TxD-RxD, RxD-TxD의 쌍으로 신호를 연결하여야만 정상적인 통신이 가능합니다.

(2) PC(또는 스마트폰 등 상대방)와 아두이노는 서로 통신 속도가 맞아야 통신이 가능합니다.
1초 동안에 주고 받을 수 있는 데이터 비트 수를 보레이트(baudrate)라고 하는데 시리얼통신에서는 이 보레이트를 서로 동일하게 맞추어야 통신이 가능합니다. 보레이트는 여러가지가 있지만 가장 많이 사용하는 것은 9600/38400/115200 baud이고, 아두이노에서는 9600 baud가 가장 많이 사용됩니다. 예를 들어, 9600 baud는 1초에 9600 비트(바이트로는 1200 바이트)가 되며, 통신시 들어가는 오버헤드를 감안하면 약 1,000 바이트, 즉 1,000개의 문자를 1초 동안에 주거나 받을 수 있는 정도의 통신 속도가 됩니다.

(3) 데이터는 한 문자(바이트) 단위로 전송됩니다.(write/read)
데이터를 주고받는 단위는 한 바이트입니다. 바이트의 값은 어떤 값도 가능하지만 아래의 테이블과 같은 ASCII 코드를 이용하여 데이터를 주고 받는 것이 보통입니다. 예를 들어 ‘A’라는 글자는 표에서 찾아보면 16진수로 0×41, 10진수로는 65의 값을 갖습니다.

기왕 테이블이 나온 김에 보너스로 자주 사용되는 제어문자 몇 가지만 더 알아두고 가겠습니다.

ASCII 값약어이름C 에서의 표기기능0×00NULNull₩0문장의 마지막을 나타냄0×08BSBack Space₩b커서 위치를 1칸 전 위치로0x0aLF/NLLine Feed(New Line)₩n커서 위치를 1줄 아래 위치로0x0dCRCarrage Return₩r커서 위치를 줄 첫번째 위치로

예를 들어 PC등의 화면에서 한 문장을 끊어서 줄바꿈을 하려면 ‘0x0d’, ‘0x0a’를 문장의 마지막에 보내주면 됩니다. (물론 실제 프로그램 작성시에는 라이브러리를 사용하므로 직접 이것을 넣어주는 일은 별로 없겠습니다.)

(4) 새로운 데이터를 보내기 위하여는 관련 플래그를 체크한 후에, 송신 가능한 상태이면 송신버퍼에 쓰면(write) 데이터를 전송할 수 있습니다. 아두이노에서는 이와 같은 기능을 모두 라이브러리로 제공하므로 우리는 제공되는 함수를 그냥 사용하면 됩니다.

(5) 새로운 데이터가 들어왔다는 사실은 관련 플래그를 체크하면 알 수 있고, 이 때 수신버퍼를 읽으면 전송된 데이터를 가져올 수 있습니다. 아두이노에서는 이와 같은 기능을 모두 라이브러리로 제공하므로 우리는 그냥 제공되는 함수를 사용하면 됩니다.

■ 시리얼 통신을 위한 아두이노 라이브러리    

이번에는 UART 통신을 위한 아두이노 라이브러리를 자세히 살펴보겠습니다. 블루투스 시리얼 통신을 하려면 미리 알아두어야 하는 라이브러리입니다.
시리얼 장치의 baudrate를 결정하는 함수는 Serial.begin( ) 입니다. 이 함수는 처음에 한 번만 실행되면 되므로 setup( ) 프로그램에서 사용하면 되겠습니다.

void Serial.begin(baudrate)
– baudrate : 실제 설정할 baudrate 값으로 9600, 38400, 115200 등이 사용됨

그런데, 이 라이브러리는 조금 이상한 점이 있네요?
즉, 이제까지 배운 함수는 이름이 문자열로만 이루어졌는데, 이번에 나타난 함수는 이름에 ‘.’을 포함하고 있습니다. 음… 이게 뭘까?
이것은 위 함수가 C에서 사용하는 함수가 아니라 C++에서 사용되는 클래스(Class)임을 나타냅니다. (C++의 클래스 개념이 어려운 분은 따로 공부하시기 바라며, 여기서는 그냥 ‘여러가지 비슷한 속성을 갖는 멤버들의 그룹 명칭’ 정도로 이해하고 넘어갑니다.) 즉, Serial은 아두이노가 시리얼통신을 수행할 때 필요한 클래스임을 나타내며 ‘.’ 뒤의 부분은 이 클래스에 속하는 멤버 함수를 표시하는 것이지요. 그러므로 Serial.begin( )은 Serial 클래스에 속하는 멤버 함수 중 begin( ) 함수를 의미하는 것입니다. 뒤에도 나오겠지만, Serial.available( ), Serial.write( ) 등도 같은 구조를 가지고 있습니다. 한편, Serial은 기본 클래스로 구분되어 있어 별도로 #include를 사용한 헤더파일을 포함하지 않아도 바로 처리가 되도록 되어있다는 점도 함께 알아두시면 왜 “#include …”문이 없어도 Serial.xxx( ) 함수가 실행되는지를 이해할 수 있을 것입니다.
데이터가 들어왔는지를 검사하는 라이브러리는 Serial.avaliable( ) 함수입니다.
UART 통신을 통하여 들어온 데이터의 개수가 리턴되며 최대 64까지의 값을 가질 수 있지만 보통은 1 또는 0 값이 리턴됩니다. 1이면 데이터가 1개 들어온 것이고, 0이면 전송된 데이터가 없는 것이지요.

int Serial.avaliable( )
– return 값 : 입력된 데이터 수 (보통은 데이터가 있으면 1, 없으면 0)

상대방이 보낸 데이터 수신하는 라이브러리는 Serial.read( )입니다. 전송된 데이터가 여러 개 있다 하더라도 읽혀지지 않은 가장 먼저 입력된 데이터 1개만을 읽어오게 됩니다. 그러므로 입력된 데이터가 여려 개 있다면 이 함수를 여러 번 수행하여 순서대로 모든 데이터를 읽어오면 되겠습니다.

char Serial.read( )
– return 값 : 입력된 데이터 버퍼의 첫번째 데이터(1 문자)

데이터를 상대방에게 송신하는 라이브러리는 Serial.write( )입니다.

int Serial.write(char val)
– val : 전송(출력, write)하고자 하는 데이터값
– return 값 : 전송된 데이터의 개수(문자수), 보통은 사용하지 않음

여러 개의 데이터를 한꺼번에 송신하는 라이브러리로는 Serial.print( )와 Serial.println( )이 있습니다.

void Serial.print(val)
– val : 디스플레이되는 값으로 ASCII 처리가 기본, 실제 처리 예는 아래 참조
* Serial.print(78) → “78”
* Serial.print(1.23456) → “1.23” (소수점의 경우는 소수 둘째자리까지만 처리)
* Serial.print(‘N’) → “N”
* Serial.print(“Hello world.”) → “Hello world.”

void Serial.print(val, format)
– val : 디스플레이되는 값으로 ASCII 처리가 기본, 실제 처리 예는 아래 참조
– format : 정수의 경우는 진법(BIN : 2진법, DEC : 10진법, HEX : 16진법), 소수점의 경우는 소수점 아래 표시 개수
* Serial.print(78, BIN) → “1001110”
* Serial.print(78, DEC) →”78”
* Serial.print(78, HEX) → “4E”
* Serial.print(1.23456, 0) → “1”
* Serial.print(1.23456, 4) → “1.2345”

void Serial.println(val)
– Serial.print(val)과 동일하나 단지 마지막에 CR(Carrage Return, ‘\r’, 0x0d)와 NL(New Line, ‘\n’, 0x0a)가 더 추가되어 전송됨. 결과적으로는 한 줄 아래의 처음부터 디스플레이됨(줄바꿈)

void Serial.println(val, format)
– Serial.println(val, format)과 동일하나 단지 마지막에 CR(Carrage Return, ‘\r’, 0x0d)와 NL(New Line, ‘\n’, 0x0a)가 더 추가되어 전송됨. 결과적으로는 한 줄 아래의 처음부터 디스플레이됨(줄바꿈)

이 외에도 더 많은 라이브러리가 있지만 이 정도면 일반적인 프로그램에서는 충분할 것 같네요.
블루투스는 휴대폰, 노트북, 이어폰 등의 휴대기기를 서로 연결하여 정보를 교환할 수 있게 하는 무선 기술 표준 중의 하나로 ISM(Industrial Scientific and Medical) 주파수 대역인 2400~2483.5MHz를 사용합니다. ISM이란 산업, 과학, 의료용으로 할당된 주파수 대역인데 전파 사용에 대해 허가를 받을 필요가 없어서 아마추어 무선, 무선랜, 블루투스 등이 이 ISM 대역을 사용하고 있습니다. 블루투스는 기기 간 마스터(Master)와 슬레이브(slave) 구성으로 연결되는데, 두 기기가 동기화(paring)되지 못하면 통신이 이루어지지 않습니다. 하나의 마스터 기기에는 최대 7대의 슬레이브 기기를 연결할 수 있으며, 마스터 기기와 슬레이브 기기 간 통신만 가능할 뿐 슬레이브 기기 간의 통신은 불가능합니다. 물론, 스마트폰은 마스터 기능과 슬레이브 기능을 모두 가지고 있고, 우리가 사용하려는 블루투스 시리얼 모듈인 JMOD-BT-1도 마스터와 슬레이브 기능을 가지고 있습니다.(단, JMOD-BT-1은 사용시 마스터나 슬레이브 중 하나로 고정됩니다.)
Bluetooth 2.0 규격의 경우, 보통 10m 이내 거리 (100m까지 되는 것도 있음)에서 통신이 가능하며, 10Mbps 이하의 데이터 전송 속도를 가집니다. 최근에는 저전력 버전인 BLE 4.0 이상 버전도 출시가 되고 있습니다.

블루투스의 유래는 옛 스칸디나비아 지역을 통일한 덴마크와 노르웨이의 국왕 해럴드 블루투스(Harold “Bluetooth” Gormsson, ?~985 혹은 986)의 별명에서 나왔습니다. 그는 블루투스(Bluetooth, 푸른이빨)라는 별명을 가지고 있었는데, 그것은 블루베리를 좋아해 항상 치아가 푸르게 물들어 있었기 때문이라는 설과, 파란색 의치를 해 넣었기 때문이라는 설이 유력합니다. 위와 같이 생기신 분이지요. 입을 꽉 다물고 있어서 이빨이 푸른색인지는 확인이 안되지만요.
어쨌든, 블루투스 SIG(개발자모임)는 자신들이 개발한 기술이 통신장치들을 하나의 무선 기술 규격으로 통일하기를 바라는 마음에서 공식명칭을 블루투스로 정했답니다. 이에 따라 블루투스의 공식 로고도 해러드 왕의 이니셜인 H(옛 스칸디나비아 룬 문자)와 블루투스의 이니셜인 B를 합하여 아래와 같이 만들어졌습니다.


블루투스 소개가 조금 길어졌네요. 너무 길어지면 또 지루하니까 이 정도에서 정리 끝!

■ 블루투스(Bluetooth) 통신을 이용한 스마트폰-아두이노 연결   

블루투스 시리얼 모듈은 UART(Universial Asynchronous Receiver/Transmitter) 방식의 시리얼 통신을 블루투스 통신으로 변환시켜주는 모듈입니다. 이 모듈의 실제적인 세부 동작 원리 및 실행 방법은 조금 복잡할 수 있으므로, 우리는 개념적으로만 이해하면 쉬울 것 같습니다.
블루투스 시리얼 모듈은 한마디로 UART 통신 방식의 유선 연결을 블루투스 방식의 무선 연결로 바꾸어주는 모듈입니다. 아래 그림은 블루투스 시리얼 모듈의 개념도로, 그림에서와 같이 유선으로 수신된 RXD 신호는 무선으로 송신하고, 무선으로 수신된 데이터는 TXD 신호로 내보내는 역할을 하는 것입니다.

실제로 두 개의 시스템이 블루투스 시리얼 모듈을 이용하여 어떻게 시리얼 통신을 수행할 수 있는지에 대한 예를 보이면 아래와 같습니다.

그림(A)는 아두이노 UNO 2개를 UART 통신을 이용하여 연결할 때의 연결도입니다. 아두이노 UNO는 UART 포트를 가지고 있으므로 서로의 UART 포트를 연결(TX-RX 짝으로)하면 시리얼 통신이 가능합니다. 그런데 만약 아두이노 UNO 1개가 손이 닿지 않거나 선을 연결할 수 없는 곳에 위치한다면 어떻게 하시겠습니까? 이런 경우에는 무선으로 연결할 수 있으면 되겠지요? 이럴 때 유선통신의 내용을 무선으로 바꿔주는 역할을 하는 것이 유선-to-무선 변환기이고 블루투스 시리얼(UART-to-블루투스)모듈은 이러한 변환기의 일종이라고 생각하시면 되겠습니다.
그림(B)는 2개의 아두이노 UNO 각각에 블루투스 시리얼 모듈을 연결한 후 2개의 시스템을 블루투스 통신으로 연결하는 경우로, 이렇게 되면 2개의 아두이노 UNO 사이에는 유선으로 연결하지 않아도 통신이 가능하게 됩니다.
이는, 그림(C)에 나타난 것처럼 블루투스 시리얼 모듈을 단지 유선을 무선으로 매질만 바꾸어 주는 기기라 생각하면(실제로도 그러함) 점선으로 보이는 것과 같이 직접 유선으로 연결한 것과 동일한 효과를 얻을 수 있기 때문이지요.
이와 같이 생각한다면, 스마트폰의 경우 블루투스 기능을 가지고 있고, 이를 이용할 수 있는 터미널용 앱이 있으므로, 그림(D)와 같이 스마트폰과 아두이노 UNO 사이를 연결하는 경우에도 통신이 가능하다고 볼 수 있겠습니다.
결과적으로 우리가 스마트폰의 가상 터미널 앱을 이용하여 특정한 값을 블루투스 통신으로 전송한다면, 이는 블루투스 시리얼 모듈을 통하여 결국 아두이노 UNO의 UART 포트로 전송되므로 아두이노 UNO의 프로그램에서 이 값을 받아서 처리할 수 있게 되는 것입니다. 또한, 반대의 경우를 생각하면 아두이노 UNO 에서 만들어진 어떤 값이 스마트폰으로 전달되어 스마트폰의 화면으로 나타낼 수도 있겠습니다. 예를 들어 실제로 우리가 나중에 스마트폰의 앱을 통하여 아래와 같이 특정 숫자를 아두이노로 보내면 아두이노는 이 숫자에 해당되는 기능을 실행할 수 있다는 것입니다.

‘1’ : 직진 ‘2’ : 좌회전 ‘3’ : 정지 ‘4’ : 우회전 ‘5’ : 후진

레알(REAL)? 레알(REAL)!

아두이노 UNO에 블루투스 시리얼 모듈을 연결하기

기본적인 이론은 알았으므로 이제 아두이노 UNO에 블루투스 시리얼 모듈인 JMOD-BT-1을 연결하여 블루투스 연결을 완성해 보겠습니다.

아두이노 UNO와는 UART 통신을 하게 되므로 JMOD-BT-1에서 아두이노 UNO와 연결해야 하는 핀은 TXD(송신 데이터), RXD(수신 데이터) 신호선과, 전원 핀인 VCC(3.3V~5V, 전원)와 GND(그라운드)로 총 4핀입니다. (나머지 핀들은 JMOD-BT-1의 세팅 시 필요한 핀이므로 실제 통신에서는 사용하지 않습니다.)
그런데 여기서 한 가지 문제가 있습니다. 그것은 아두이노 UNO는 1개의 UART 인터페이스만을 가지고 있고, 이 UART 포트는 아두이노의 업로드 및 시리얼 모니터 연결용으로 이미 USB 쪽으로 연결이 되어 있다는 것입니다. 즉, 이 UART 포트를 함께 사용하는 경우, 우리는 시리얼 모니터와 블루투스 시리얼을 동시에 사용할 수 없을 뿐만 아니라, 아두이노 업로드 시에도 블루투스 시리얼 쪽의 경로와 충돌이 날 가능성 등을 고려해야 하는 아주 불편한 상황을 감수해야 합니다.
그러면, 방법이 없을까요? 아니오~ 좋은 방법이 하나 있습니다.
그것은 가상 UART인 소프트웨어시리얼(SoftwareSerial)을 이용하는 것입니다.
소프트웨어시리얼은 아두이노의 일반적인 입출력(GPIO : General Purpose Input Output) 핀(D0~D13, A0~A5)을 이용하여 UART의 기능을 하도록 소프트웨어로 라이브러리화한 것으로, UART의 기능을 거의 그대로 재현할 수 있는 아두이노 라이브러리입니다.
시리얼모니터에서 사용하는 클래스인 Serial과 비슷한 형태의 클래스로 SoftwareSerial을 제공하고 있으며, 멤버 함수도 begin, read, write 등을 Serial과 동일하게 사용할 수 있습니다.
형태는 아래와 같습니다.

SoftwareSerial(unit8_t rx, unit8_t tx, bool inverse_logic = false)
rx : 수신 핀 번호
tx : 송신 핀 번호
inverse_logic : 송수신 비트 반전 (TRUE : 반전, FALSE : 반전하지 않음, default는 FALSE)

프로그램에서 사용하실 때는 첫 부분에 아래와 같은 선언이 필요하고,

#include

SoftwareSerial ABC = SoftwareSerial(RX, TX);
ABC : 이 스케치에서 SoftwareSerial로 사용할 이름
RX : RX핀으로 사용할 핀 번호
TX ; TX 핀으로 사용할 핀 번호

실제 사용시에는 Serial 클래스와 같이, 아래와 같은 형태로 사용하면 됩니다.

ABC.begin(115200);

오, 요런 방법이 있었네요. 그러면 이것을 이용하여 아두이노 UNO와 JMOD-BT-1을 직접 연결해 보도록 하겠습니다. SoftwareSerial에 사용된 핀은 RX는 4번(D4), TX는 5번(D5)를 사용하는 것으로 하지요. 한가지 조심하여야 하는 것은 송신 핀과 수신 핀의 연결인데요. 앞에서도 언급하였지만, 두 기기의 연결에서 한 쪽의 송신핀(TXD)은 다른쪽의 수신핀(RX)에, 한 쪽의 수신핀(RXD)은 다른 쪽의 송신핀(TX)에 연결하여야 한다는 점은 꼭 확인하고 연결하셔야 합니다.
아래와 같이 연결하면 될 것 같네요. JMOD-BT-1의 뒷면에 신호 이름이 적혀있으니 잘 보고 연결하시기 바랍니다.

아두이노 UNO 핀JMOD-BT-1핀+5VVCCGNDGNDD4(RX, SoftwareSerial)TXDD5(TX, SoftwareSerialRXD

스마트폰의 블루투스 앱으로 아두이노와 통신하기

자, 연결은 되었으니 이번에는 실제로 스마트폰과 아두이노 UNO가 블루투스를 이용하여 통신이 가능한지 알아보기 위한 테스트를 실행해 보겠습니다.
일단 스마트폰에 블루투스 앱이 필요할텐데…, 이것은 이미 존재하는 앱을 가져다가 사용하는 것이 좋겠습니다. 블루투스 통신을 위한 앱은 여러가지가 있지만, 나중에 스마트카를 조종하는 것을 고려하여 버튼을 이용하여 데이터를 보낼 수 있도록 설계된 ‘블루투스 컨트롤러(Bluetooth Controller)’라는 앱을 사용하는 것으로 하겠습니다. 이 앱은 안드로이드 스마트폰의 ‘PLAY 스토어’에서 ‘블루투스 컨트롤러’(“Bluetooth Controller”)이라는 이름으로 검색하면 찾을 수 있습니다.

스마트폰의 ‘블루투스’ 항목을 ‘ON’ 상태로 설정한 후에 위와 같이 ‘Bluethooth Controller’ 앱을 실행하면 아래와 같은 화면이 나타나는데, 여기에서 위쪽 오른쪽에 있는 [키 설정] 메뉴를 누르면 다음의 화면이 나타납니다.

[키 이름]에 자신이 원하는 이름을 넣고, [데이터 설정]에는 통신 시 이 키를 눌렀을 때 아두이노 쪽으로 전달될 데이터값(예를 들어 ‘1’)을 넣으면 됩니다. 우리는 나중에 스마트카를 제어해야 하므로 제공되는 9개의 칸에 아래와 같이 직관적으로 배치 하겠습니다.전진(“1″)좌회전(“2″)정지(“3″)우회전(“4″)후진(“5″)[OK]를 누루면 아래의 화면이 나타납니다.

자, 연결이 잘 되었는지 테스트를 해볼까요? 아두이노 UNO에는 블루투스를 통하여 들어온 데이터를 되돌려 보내는(echoback하는) 프로그램을 업로드하여 스마트폰에서 보낸 데이터(예를 들어 ‘1’, ‘2’ 등)가 다시 스마트폰으로 되돌아 오면 성공이 되겠습니다.

[테스트 규격]
· 스마트폰 블루투스 콘트롤러 앱에서 보낸 데이터가 아두이노 UNO까지 전달되었다가 되돌아 오는 블루투스 통신 시스템
· 통신 경로 : 스마트폰 블루투스 콘트롤러 앱 → (블루투스 통신) → JMOD-BT-1 TXD → 아두이노 RX → echoback(아두이노 프로그램) → 아두이노 TX → JMOD-BT-1 RXD → (블루투스 통신) → 스마트폰 블루투스 콘트롤러 앱

[알고리즘]
· SoftwareSerial로 정해진 핀을 설정하고, baudrate는 115200(JMOD-BT-1의 기본 설정)으로 설정한 후, RX 핀으로 수신된 데이터는 항상 TX 핀으로 송신(echoback)

설명하느라 많은 시간을 할애했지만, 실제 프로그램은 너무 쉬워서 알고리즘이라고 할 것도 없습니다. 바로 스케치 프로그램으로 넘어갑니다.

#include

#define SS_RX 4 // SoftSerial RX 핀번호 = 4
#define SS_TX 5 // SoftSerial TX 핀번호 = 5

SoftwareSerial btSerial = SoftwareSerial(SS_RX, SS_TX); // 블루투스시리얼은 SoftSerial 사용
// 4번, 5번 핀 할당

void setup()
{
btSerial.begin(115200); // 블루투스 시리얼 모듈(JMOD-BT-1) 통신 속도
= 115200
}

void loop()
{
if (btSerial.available()) // 블루투스 시리얼 모듈을 통하여 데이터가 수신되면
{
data = btSerial.read(); // 그 데이터를 읽어서
btSerial.write(data); // 블루투스 시리얼 모듈을 통하여 다시 송신(loopback)
}
}

얼른 업로드하고, 앱을 이용하여 연결이 잘 되었는지 확인해 보겠습니다.

1. 스마트폰에서 블루투스 컨트롤러 앱을 실행하고

2. 아두이노 UNO에 연결된 JMOD-BT-1과 패어링(pairing : 블루투스 마스터와 블루투스 슬레이브가 통신할 수 있는 상태로 진입하는 것)을 한 후
(주의 : 처음 연결할 때는 PIN 번호를 물어보게 되는데 이 때는 ‘1234’를 입력합니다.)

3. 버튼을 눌러 대응되는 숫자가 되돌아 오는지 확인(즉, ‘전진’ 버튼을 누르면 ‘1’, 좌회전을 버튼을 누르면 ‘2’, 정지 버튼을 누르면 ‘3,’ 우회전 버튼을 누르면 ‘4’, 후진 버튼을 누르면 ‘5’, 값이 스마트폰 앱 화면 창에 나타나면 성공!)

■ 내 스마트카 조립     

자, 이제 필요한 기본 지식은 모두 갖추었으니 드디어 내 차를 만들고 운전해 볼 시간입니다. 실제로 이미 자동차를 가지고 계신 분도 있고, 아직은 없는 분도 있겠지만, 오늘 DIY할 스마트카는 아두이노 장난감차니까, 부담없이 내 맘대로 만들어서 내 멋대로 이리저리 마구 운전해 봅시다.

[아두이노 연결]
아~ 이 그림 하나 그리느라고 거의 4시간이나 잡아먹었습니다.
중간에 배터리 연결 형태가 바뀌기도 하고, fritzing과 캡처, 포토샵, 파워포인트 \…로 이렇게 꾸미는 것이 꽤 많은 시간을 필요로 하네요. 어쨌든 좌충우돌하여 완성입니다. 야호~

연결된 부분을 잠시 설명해 보면, 아래 표와 같습니다.


전원 연결은 아래와 같습니다.
모터드라이버 연결 시에는 약간 주의할 것이 있는데, PWM 신호는 아날로그 출력이므로 신호에 물결 표시(~, tild)가 있는 D3, D5, D6, D9, D10, D11번 핀에 연결해야 한다는 것입니다. 이러한 이유로 PWMA는 D6에, PWMB는 D9에 할당하였습니다. PWM 출력이 가능한 모터가 2개인 것을 제외하고는 지난 시간에 다 해본 것이므로 모터드라이버와 블루투스 시리얼과의 연결은 특별한 설명이 더 필요하지는 않을 것 같습니다. (기억이 나지 않으면 지난번 강의를 참조!!!)
마지막으로 좀 더 설명하고 넘어가야 하는 것은 전원에 관련된 것입니다. 도입 부분에서도 약간 언급하였는데, 이번 DIY는 자동차이므로 PC로부터 USB 케이블을 통하여 공급되는 전원은 사용할 수가 없습니다. 그러므로 휴대용 전원으로 사용되는 건전지나 수은전지, 리튬전지 등을 이용하여 전원을 공급해야 하지요. 여러가지 경우를 여기서 모두 설명하기에는 내용이 좀 길어지므로 이번에는 우리가 사용할 방법만 간단하게만 설명하겠습니다.

일단 모터를 구동하는 전원과 아두이노 및 다른 모듈에서 사용할 전원은 분리하도록 합니다. 모터는 일반적으로 전류를 많이 사용하고, 모터마다 사용 전압도 다르며, 기동시 순간적인 과전류로 인한 전원 소스의 흔들림(전압강하)도 생길 수 있는 부품이어서 아두이노나 블루투스 시리얼 모듈로 공급되는 전원과는 다른 전원 소스를 사용하는 것을 권장합니다.

만약, 모터가 5V로 구동이 가능하여 동일한 5V 전원 소스로 사용하려 할 때에는 전원 소스의 전류 공급용량이 충분한지, 전원 드랍(drop)은 영향이 없는지 등의 여부를 잘 살펴서 사용하셔야 불안정한 동작을 방지할 수 있습니다. 우리는 1.5V 건전지 4개를 직렬 연결한 배터리 홀더에 넣어서, 6V를 모터의 전원으로 사용하겠습니다. 그리고 아두이노와 블루투스 시리얼 모듈, 그리고 모터드라이버 모듈의 제어 부분 전원으로는 5V를 공급해야 하므로 이것은 리튬전지(4.2V)를 스텝업 레귤레이터를 이용하여 5V로 만들어 주는 전원조종기인 제이씨넷의 JBATT-U5-LC를 사용하겠습니다. (참고로, JBATT-U5-LC는 리튬전지를 사용하고 USB 케이블로 충전이 가능하며, 전원 ON/OFF 스위치가 내장된 소형 전원공급기입니다.) 물론, 시중에 나와 있는 임의의 전압공급기 모듈을 사용해도 되고, 직접 전압공급기 회로를 제작하여 사용해도 되지요. 또는, 7V 이상의 전원 소스가 있다면 아두이노 VIN 핀으로 직접 이 전원을 넣어주고, +5V 핀으로부터 블루투스 시리얼 모듈과 모터드라이버 모듈의 제어 부분 전원을 연결하여 사용하는 것도 한가지 방법이 되겠습니다.

모터드라이버 모듈의 경우는 내부에서 사용하는 전원과 모터로 공급되는 전원, 2개를 모두 연결해주어야 하는 것에 주의하셔야 하고, 2개의 전원소스의 GND는 어떤 형태로든 연결되어 있어야 함에 주의하시기 바랍니다. 조금 복잡할 수 있으므로 모터 드라이버의 핀 연결을 확대하여 다시 한 번 연결 형태를 정리해 보면 아래와 같이 되겠습니다. 6V 전원(건전지홀더)의 GND는 외부에서 5V 전원의 GND와 연결한다는 의미로 점선 – - – 으로 표시하였습니다.

[조립하기]
이제 조립을 하기 위한 모든 준비는 끝난 것 같네요. 프로그램을 하기 전에 일단 조립부터 해보고(빨리 만들고 싶으니까요.) 이후에 프로그램을 준비해 보는 것으로 하시지요. 선이 제법 많고 부속 모듈도 많으므로 공간을 잘 이용해서 배치하고 연결하여야 할 것 같습니다. 저는 편하게 양면테이프를 이용하여 아래와 같이 모듈 뒤쪽에 붙이고 이것을 적당하게 배치하여 처리하였습니다.

초기 앞면, 뒷면을 조립하면 아래와 같은 모양이 됩니다.

그리고 각 모듈과 전원까지 모두 연결하면~

짠~~~! 이렇게 만들어졌습니다.
선들이 조금 난잡하여 폼이 덜 나긴 하지만, 전원까지 넣어주면 불이 반짝반짝 하는게 꽤 그럴 듯 하게 보입니다. 작은 끈 같은 것으로 선을 묶어주면 좀 깔끔해 질 것도 같지만, 근처에는 현재 눈에 띄지가 않으므로 생략! 그냥 산발한 채로 넘어갑니다.
어쨌거나 조립은 잘 완성되어 기분은 좋아졌습니다.
노동하느라 애썼으니까 커피 한 잔하면서 휴식을 조금 취한 후 다시 와서 마지막 프로그램을 완성하도록 하겠습니다.
10분간 휴식~~~

■ 내 스마트카 프로그램     

이제 차체는 모두 완성하였으니 스케치 프로그램만 작성하여 업로드해 봅시다.
블루투스 연결 쪽은 소프트시리얼로 처리해야 한다는 것을 염두에 두고, 전체적인 알고리즘을 생각해 보겠습니다.

스마트폰에서 들어온 입력을 검사하여 각 숫자에 대응되는 동작인 전진, 후진, 좌회전, 우회전, 정지의 5가지 기능 중 하나를 실행하면 되겠습니다. 또한, 각 기능은 모터 2개의 동작으로 구현할 수 있는데 이는 아래의 표를 확인하기 바랍니다.

예를 들어 좌회전 기능을 구현한다면, 왼쪽 바퀴(모터)는 천천히 전진하고 오른쪽 바퀴(모터)는 앞으로 전진하면 차제가 왼쪽으로 기울면서 좌회전하는 형태가 되겠습니다. 실제로 좀 더 부드럽게 동작하려면 왼쪽 바퀴(모터)는 조금 천천히 구동되고, 오른쪽 바퀴(모터)는 빨리 구동되는 형태로 구현하면 되겠지요. (이 동작은 PWMA, PWMB의 값을 아날로그적으로 0~255까지 조절이 가능하므로 적당한 값을 주어 구현이 가능합니다.)
편의상 스마트카의 오른쪽 바퀴(모터)는 모터A를, 왼쪽 바퀴(모터)는 모터B를 할당합니다.
이번에도 설명이 좀 길었는데 실제 구현은 크게 어렵지 않게 될 것 같네요. 여러분의 힘으로 한 번 생각해 보시고 스스로 먼저 구현해 보시지요. 약 20분 기다립니다.

(20), (19), (18), …… (3), (2), (1), (0) !

아래를 보시지요.

#include

#defineSS_RX 4 // SoftSeiral RX 핀 <-> JMOD-BT-1의 TXD 연결
#defineSS_TX 5 // SoftSerial TX 핀 <-> JMOD-BT-1의 RXD 연결

#define FORWARD ‘1’ // 전진 명령어
#define FORWARD_L ‘2’ // 좌회전 명령어
#define FORWARD_R ‘4’ // 우회전 명령어
#define BACKWARD ‘5’ // 후진 명령어
#define STOP ‘3’ // 정지 명령어

#defineSPEED_100 255 // PWM값 255(0~255), 100% 값
#defineSPEED_75 192 // PWM값 192(0~255), 75% 값
#defineSPEED_50 128 // PWM값 128(0~255), 50% 값
#defineSPEED_25 64 // PWM값 64 (0~255),25% 값
#defineSPEED_0 0 // PWM값0(LOW) (0~255), 0% 값

SoftwareSerialbtSerial = SoftwareSerial(SS_RX, SS_TX);

constint pwma = 6; // 모터 APWM 입력핀
constint ain1 = 7; // 모터 AIN1 입력핀
constint ain2 = 8; // 모터 AIN2 입력핀
constint pwmb = 9; // 모터 BPWM 입력핀
constint bin1 = 10; // 모터 BIN1 입력핀
constint bin2 = 11; // 모터 BIN2 입력핀

voidforw() // 전진 처리,모터 A = 전진, 모터 B = 전진
{
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_75);
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_75);
}

voidforwL() // 좌회전 처리, 모터 A= 전진, 모터B = 약하게 전진
{
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_75);
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_50);
}

voidforwR() // 우회전 처리, 모터 A = 약하게 전진, 모터B = 전진
{
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_50);
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_75);
}

voidback() // 후진 처리,모터 A = 후진, 모터 B = 후진
{
digitalWrite(ain1, LOW); digitalWrite(ain2,HIGH); analogWrite(pwma, SPEED_75);
digitalWrite(bin1, LOW); digitalWrite(bin2,HIGH); analogWrite(pwmb, SPEED_75);
}

voidstop() // 정지 처리,모터 A = 정지, 모터 B = 정지
{
analogWrite(pwma, SPEED_0);
analogWrite(pwmb, SPEED_0);
}

voidsetup()
{
pinMode(pwma, OUTPUT); // 모터 제어핀은 아두이노 입장에서 모두 출력
pinMode(ain1, OUTPUT);
pinMode(ain2, OUTPUT);
pinMode(pwmb, OUTPUT);
pinMode(bin1, OUTPUT);
pinMode(bin2, OUTPUT);
btSerial.begin(115200); // JMOD-BT-1 통신baudrate = 115200(초기값)
}

voidloop()
{
char rxData;
if (btSerial.available() > 0) // 스마트폰으로부터의 입력 데이터가 있는지확인
{
rxData = btSerial.read(); //데이터(명령어)가무엇인지 확인
if (rxData == FORWARD) forw(); // 전진 명령 처리
elseif (rxData == FORWARD_L) forwL(); // 좌회전 명령 처리
elseif (rxData == FORWARD_R) forwR(); // 우회전 명령 처리
elseif (rxData == BACKWARD) back(); // 후진 명령 처리
elseif (rxData == STOP) stop(); // 정지 명령 처리
else;
}
delay(100);
}

모터 제어에서 “analogWrite(pwma,SPEED_75)”와 같이 PWM 핀에 192(=SPEED_75)와 같은 값을 주는 것은 전체값인 255(SPEED_100)을 주었을 때 모터가 너무 빨리 회전하여 스마트카가 너무 빨리 움직일 것 같아 적당한 값을 준 것이며, 한편으로는 모터에 의하여 소모되는 전력을 조금 적게 하여 건전지의 수명을 조금 연장하려는 의미도 있습니다.
이제 준비가 되었으니 업로드하고, 앱을 이용하여 프로그램이 잘 되었는지 확인해 보겠습니다. 이전 예에서 사용한 형태와 똑같이 앱을 구성하여 실행하는 것으로 합니다.

1. 스마트폰에서 블루투스 컨트롤러 앱을 실행하고

2. 아두이노 UNO에 연결된 JMOD-BT-1과 패어링(pairing : 블루투스 마스터와 블루투스 슬레이브가 통신할 수 있는 상태로 진입)한 후
(주의 : 처음 연결할 때는 PIN 번호를 물어보게 되는데 이 때는 ‘1234’를 입력합니다.)

3. 버튼을 눌러 정해진 명령대로 스마트카가 움직이는지 확인 (전진 버튼을 누르면 ‘1’, 좌회전을 버튼을 누르면 ‘2’, 정지 버튼을 누르면 ‘3,’ 우회전 버튼을 누르면 ‘4’, 후진 버튼을 누르면 ‘5’ 값이 스마트폰 → JMOD-BT-1 → 아두이노로 전달되고 아두이노는 이 명령어에 해당되는 기능을 수행