<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NTREXGO - 디바이스마트, 엔티렉스 컨텐츠 통합 사이트 &#187; Project To Build</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/project-to-build/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ntrexgo.com</link>
	<description>엔티렉스, 디바이스마트 컨텐츠 통합 사이트</description>
	<lastBuildDate>Thu, 03 Mar 2022 06:47:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>[36호]카멜레온 DIY LED 이야기 2</title>
		<link>http://www.ntrexgo.com/archives/31253</link>
		<comments>http://www.ntrexgo.com/archives/31253#comments</comments>
		<pubDate>Fri, 20 May 2016 04:44:16 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[프로젝트]]></category>
		<category><![CDATA[36호]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[LED]]></category>
		<category><![CDATA[Project To Build]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=31253</guid>
		<description><![CDATA[디바이스마트매거진 36호 &#124; 카멜레온 DIY LED의 기본 LED인 WS2812B의 동작 원리에 대한 이야기로 시작해 보겠습니다. 어떤 분야든 개념과 원리가 중요하니까요. ]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ptb.jpg" rel="lightbox[31253]"><img alt="36 카멜레온 ptb" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ptb-620x235.jpg" width="620" height="235" /></a></p>
<p>&nbsp;</p>
<p><span style="font-size: xx-large"><strong>카멜레온 DIY LED 이야기 2</strong></span></p>
<p><span style="font-size: medium"><strong>WS2812B의 동작원리와 12색상환 만들기</strong></span></p>
<p>&nbsp;</p>
<p style="text-align: right">글 | 신상석 ssshin@jcnet.co.kr</p>
<table style="background-color: #e2e2e2;;width: 620px" border="0" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>디바이스마트 매거진 독자 여러분, 안녕하세요. 앞으로 5회에 걸쳐 [카멜레온 DIY LED 이야기]를 진행할 신상석입니다.<br />
이 이야기는 WS2812B라는 컬러 LED를 기반으로 제작된 [카멜레온 DIY LED] 시리즈를 이용하여 생활에 필요한 다양한 형상을 꾸며보고 이것을 다양한 컬러로 디스플레이 해보는 내용입니다. 앞으로 진행할 내용에 대하여 간단히 알아보면 다음과 같습니다. (약간 변경될 수도 있습니다.)<br />
앞으로 즐겁고 유익한 강의가 될 수 있도록 많은 격려와 성원 부탁드립니다.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>디바이스마트 매거진 독자 여러분, 안녕하세요.</p>
[카멜레온 DIY LED 이야기] 두번째 시간이 돌아왔습니다.<br />
뜸하게 만나므로 지난 시간에 어디까지 이야기했는지 기억이 잘 나지 않으실 것 같은데, 지난 시간에는 카멜레온 DIY LED에 대한 정의, 형태, 종류, 타 모듈과의 비교, 응용 예 등과 같이 전반적인 소개가 이루어졌습니다. 이번 호부터는 좀 더 세부적으로 카멜레온 DIY LED에 대하여 알아보는 시간을 갖도록 하겠습니다. 일단은, 카멜레온 DIY LED의 기본 LED인 WS2812B의 동작 원리에 대한 이야기로 시작해 보겠습니다. 어떤 분야든 개념과 원리가 중요하니까요.</p>
<p><span style="color: #008000;font-size: medium"><strong>WS2812B의 동작 원리</strong></span></p>
<p>WS2812B의 특징은 간단하게 말해서, “내가 원하는 개수만큼 연속적으로 간단하게 연결하면서, 내가 원하는 시간에 내가 원하는 컬러(껐다 켰다 포함)로 자유롭게 표현할 수 있는 LED”라고 이야기한 바 있습니다.<br />
WS2812B의 외관 모습은 지난번에 보았으므로 오늘은 신호선과 핀 배열을 살펴보겠습니다. 아래와 같이 생겼습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-01.jpg" rel="lightbox[31253]"><img class="wp-image-31343 aligncenter" alt="36 카멜레온 01" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-01.jpg" width="301" height="142" /></a></p>
<p>4핀 중, VCC(+)와 GND(-)는 전원이고, DIN과 DOUT은 각각 데이터입력, 데이터출력 신호입니다. VCC와 GND는 3.5 V ~ 5.3 V 사이의 전원으로 여러 개의 WS2812B가 연결되는 경우에도 모두에게 공통으로 연결되어져야만 합니다. DIN은 WS2812B로 전달되는 데이터의 입력 신호선이고, DOUT은 DIN으로 들어온 데이터 중 자신이 사용하지 않는 데이터를 통과(bypass)시키는 출력 신호선인데, 여러 개의 WS2812B를 연결하는 경우에는 앞쪽 WS2812B의 DOUT이 뒤쪽 WS2812B의 DIN에 연결되는 형태로 직렬(시리얼) 연결합니다. 데이터를 공급해주는 제어기를 포함한 연결 관계를 그림으로 나타내 보면 아래와 같이 되겠습니다. 연결 방식은 상당히 간결한 편이지요.</p>
<table style="width: 620px;border: 1px solid #c8c8c8" border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-02.jpg" rel="lightbox[31253]"><img class="wp-image-31344 aligncenter" alt="36 카멜레온 02" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-02-620x409.jpg" width="496" height="327" /></a></td>
</tr>
<tr>
<td style="text-align: center">데이터를 공급해주는 제어기를 포함한 연결 관계</td>
</tr>
</tbody>
</table>
<p>이렇게 연결하고도 LED마다 따로따로 여러가지 색채와 동작을 표현할 수 있다는 것이 신기할 따름인데… 과연 어떻게 동작하는 것일까요? 살펴 보겠습니다.<br />
세부적인 내부 회로도가 공개되어 있지 않아 정확하게 알 수는 없지만, 데이터시트에 나온 내용을 기준으로 WS2812B의 동작 방법을 설명하면 다음과 같습니다.</p>
<p style="padding-left: 30px">· 내부에 R(Red), G(Green), B(Blue)에 해당하는 컬러 LED와 이를 제어하는 로직이 함께 통합되어 있음<br />
· DIN으로 입력된 데이터는 내부의 데이터 래치에 의하여 저장되고 신호증폭 로직을 거쳐 DOUT으로 출력됨<br />
· 전원이 켜지거나, 데이터리셋이 되면, 내부 로직은 DIN 포트로부터 데이터를 받아들이는데, 처음 24비트는 자신의 내부 데이터 래치로 보내고 이후의 데이터는 DOUT 포트로 bypass하여 내보냄. 한편, LOW 전압이 50uS 이상 지속되면 데이터 리셋으로 간주하고 다시 처음부터 시작함<br />
· 내부에 전송된 3바이트(24비트) 데이터는 1바이트(8비트)씩 녹색, 빨강, 파랑의 컬러 LED 값을 나타내며, 전송 순서도 녹빨파(GRB, Green, Red, Blue) 순임</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-03.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31345" alt="36 카멜레온 03" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-03.jpg" width="454" height="68" /></a></p>
<p style="padding-left: 30px">· 전원은 3.5 V ~ 5.3 V까지 사용이 가능하며, 입력 데이터는 0.7 x VCC 이상의 전압이면 HIGH, 0.3 x VCC 이하의 전압이면 LOW로 처리됨 (5 V 전원의 경우 3.5 V 이상이면 HIGH, 1.5 V 이하이면 LOW)<br />
· 데이터 전송 프로토콜은 펄스폭의 길이로 데이터값을 산정하는 방식을 사용하며, 아래와 같은 규격으로 판정함</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-04.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31346" alt="36 카멜레온 04" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-04.jpg" width="258" height="178" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ict-888.png" rel="lightbox[31253]"><img class="alignnone  wp-image-31369" alt="36 카멜레온 ict 888" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ict-888-620x195.png" width="496" height="156" /></a></p>
<p>&nbsp;</p>
<p>즉, DIN 라인의 레벨이 400ns LOW + 850ns HIGH 를 유지하면 1비트의 데이터 HIGH로 인식하고, 800ns HIGH + 450ns LOW 를 유지하면 1비트의 LOW로 인식하는 방식<br />
이와 같은 규격을 기준으로 처음 그림과 같은 연결에서 데이터가 전송되는 방법을 나타내면 아래 그림과 같습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-06.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31348" alt="36 카멜레온 06" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-06-620x365.jpg" width="496" height="292" /></a></p>
<p>예를 들어 만약 첫번째 LED에는 빨강, 두번째 LED에는 파랑, 세번째 LED에는 녹색으로 LED를 1초 동안 켜고 싶다면, 제어기에서는 (<span style="color: #ffffff;background-color: #008000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #ff0000">0xFF</span> ▶<span style="color: #ffffff;background-color: #3366ff"> 0&#215;00</span>) ▶ (<span style="color: #ffffff;background-color: #008000">0&#215;00</span> ▶<span style="color: #ffffff;background-color: #ff0000"> 0&#215;00</span> ▶<span style="color: #ffffff;background-color: #3366ff"> 0xFF</span>) ▶ (<span style="color: #ffffff;background-color: #008000">0xFF </span>▶ <span style="color: #ffffff;background-color: #ff0000">0&#215;00</span> ▶<span style="color: #ffffff;background-color: #3366ff"> 0&#215;00</span>) 을 보내면 LED가 원하는 색으로 켜지고 1초 후에 다시 (<span style="color: #ffffff;background-color: #008000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #ff0000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #3366ff">0&#215;00</span>) ▶ (<span style="color: #ffffff;background-color: #008000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #ff0000">0&#215;00</span> ▶<span style="color: #ffffff;background-color: #3366ff"> 0&#215;00</span>) ▶ (<span style="color: #ffffff;background-color: #008000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #ff0000">0&#215;00</span> ▶ <span style="color: #ffffff;background-color: #3366ff">0&#215;00</span>) 을 보내면 LED가 모두 꺼지게 됩니다.</p>
<p>처음에 연속해서 9바이트의 데이터를 보내면, 첫번째 LED에서 3바이트를 사용하고, 이후 전달된 6바이트는 2번째 LED로 전달되며, 마찬가지로 두번째 LED는 전달된 6바이트 중 처음 3바이트를 사용하고 마지막 3바이트는 세번째 LED로 보내게 되는 방식을 사용하는 것입니다. 1초가 지난 후에 다시 9바이트의 데이터를 보내면 이것은 50us 보다 긴 시간 이후에 들어온 데이터이므로 이전 데이터의 연속으로 보지 않고, 새로운 데이터가 들어온 것으로 간주하여 다시 첫번째 LED에서 3바이트를 사용하는 방식으로 진행되겠습니다.</p>
<p>이런 원리를 잘만 이용하면, WS2812B LED를 내가 원하는 개수만큼 원하는 형태로 연결한 후, 이들의 색상이 시간에 따라 변화하도록 프로그램하는 것이 가능할 것 같네요. 오, 뭔가 있을 법한 느낌!!!</p>
<p><span style="font-size: medium;color: #008000"><strong>LED(JLED-BAR-1) 1개 불 켜기</strong></span></p>
<p>그럼, 이제 문제는 0, 1 데이터, 나아가서 GRB 데이터, 더 나아가서 여러 개의 WS2812B 연결시의 데이터를 어떻게 프로그램으로 생성할 수 있는가 하는 것인데…<br />
“천리길도 한 걸음부터”라고 했으니 일단 WS2812B 1개로 구성된 카멜레온 DIY LED인 JLED-BAR-1에 파랑색 불을 켜는 것으로부터 시작해 보겠습니다. 이 후 이것을 응용해서 1600만가지 이상의 컬러를 골라서 디스플레이 해보는 데까지 가보시지요. (와우!!!)<br />
일단 JLED-BAR-1의 모습을 보실까요. 짜잔~~~!</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ptb555.jpg" rel="lightbox[31253]"><img class="alignnone size-full wp-image-31370" alt="36 카멜레온 ptb555" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-ptb555.jpg" width="325" height="122" /></a><br />
앞면에는 WS2812B가 1개 배치되어 있고(컨덴서 1개 포함), 뒷면에는 2.54mm 1X3 핀헤더가 양쪽으로 배치되어 있습니다. 뒷면의 실크 표시는, V는 VCC(+5V), G는 GND, I는 DIN(데이터입력), O는 DOUT(데이터 출력)입니다.</p>
<p>JLED-BAR-1은 WS2812B를 기반으로 하여 이미 출시되어 있는 다른 상품과 확연히 차이가 나는 것이 3가지 있습니다.</p>
<p>첫째, 1X3 입력핀과 1X3 출력핀의 형태가 DIP 타입(2.54mm 핀헤더 타입)입니다. 입출력 신호가 SMD로 되어 있는 것은 납땜을 해야하는 번거로움이 있지만 이렇게 DIP 타입을 사용하면 케이블이나 점퍼 등을 사용하여 연결을 매우 쉽게 할 수 있는 장점이 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-09.jpg" rel="lightbox[31253]"><img class="wp-image-31351 aligncenter" alt="36 카멜레온 09" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-09.jpg" width="482" height="270" /></a> <a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-11.jpg" rel="lightbox[31253]"><img class="wp-image-31353 aligncenter" alt="36 카멜레온 11" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-11.jpg" width="482" height="270" /></a></p>
<p>둘째, 가로와 세로의 길이가 각각 1cm입니다. BAR 시리즈의 경우는 LED가 증가할 때마다 1cm씩 가로 길이가 증가하도록 설계되어 있습니다. 이렇게 하면 용도에 따라 매우 편리하게 적용이 가능합니다. 예를 들어 30cm X 20 cm 되는 액자의 테두리를 BAR 시리즈로 만든다면 가로는 JLED-BAR-10을 3개 연속 연결하면 딱 알맞게 적용이 되는 것이지요. 급할 때는 자 대용으로도 사용이 가능합니다. 그러면 아래 JLED-BAR-10 의 길이는 얼마일까요? (답이 없어도 알겠죠?)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-10.jpg" rel="lightbox[31253]"><img class="wp-image-31352 aligncenter" alt="36 카멜레온 10" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-10.jpg" width="470" height="69" /></a></p>
<p>셋째, 그림으로는 식별이 잘 안되지만 1X3 입출력 핀헤더는 가장자리에서 안쪽으로 1.27mm 거리에 위치합니다. 이렇게 되면 카멜레온 DIY LED 모듈 여러 개를 연속적으로 연결시 2X3 쇼트핀(JLED-CON-0, 2핀간의 거리 2.54mm)으로 바로 연결이 가능하므로 레고처럼 붙였다 떼었다 하는 동작이 매우 용이합니다. JLED-BAR-1과 JLED-TRI-3을 쇼트핀 3개로 결합한 형태를 보시지요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-12.jpg" rel="lightbox[31253]"><img class="wp-image-31354 aligncenter" alt="36 카멜레온 12" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-12.jpg" width="482" height="270" /></a></p>
<p>쇼트핀 3개가 하나로 결합되어 있는 JLED-CON-0를 연결하면 아래와 같이 좀 더 깔끔하게 연결할 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-13.jpg" rel="lightbox[31253]"><img class="wp-image-31355 aligncenter" alt="36 카멜레온 13" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-13.jpg" width="482" height="270" /></a></p>
<p>앞면도 보여드리지요.</p>
<p style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-14.jpg" rel="lightbox[31253]"><img class=" wp-image-31356 aligncenter" alt="36 카멜레온 14" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-14.jpg" width="482" height="270" /></a></p>
<p>자, 그럼 이제 JLED-BAR-1을 아두이노에 연결하여 파랑색 불을 켜는 것을 예로 들어 본격적으로 프로그램을 시작해 보겠습니다.<br />
일단, 제어기 연결은 해놓고 시작합니다. 아두이노 UNO를 제어기로 사용하는 경우 아래와 같이 연결이 되겠습니다. 아두이노와 JLED-BAR-1의 신호쌍으로 +5V-V(VCC)(빨강선), GND-G(GND)(검정선), D2-I(DIN)(녹색선)을 각각 연결합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-16.jpg" rel="lightbox[31253]"><img class="wp-image-31357 aligncenter" alt="36 카멜레온 16" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-16.jpg" width="482" height="270" /></a> <a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-17.jpg" rel="lightbox[31253]"><img class="wp-image-31358 aligncenter" alt="36 카멜레온 17" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-17.jpg" width="482" height="270" /></a> <a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-18.jpg" rel="lightbox[31253]"><img class="wp-image-31359 aligncenter" alt="36 카멜레온 18" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-18.jpg" width="482" height="315" /></a><br />
파랑색 불이 들어오게 하려면 제어기(아두이노)에서 (<span style="color: #ffffff;background-color: #008000">0&#215;00</span>,<span style="color: #ffffff;background-color: #ff0000"> 0&#215;00</span>,<span style="color: #ffffff;background-color: #3366ff"> 0xFF</span>)의 24비트 데이터를 JLED-BAR-1으로 보내주어야 합니다. 첫번째 데이터인 <span style="color: #ffffff;background-color: #008000">0&#215;00</span>을 보내려면 ‘0’ 을 나타내는 비트 신호를 8번 연속해서 보내주어야 하는데, 규격에 보면 ‘0’ 신호는 실제 WS2812B의 DIN 라인의 레벨을 ‘800ns HIGH + 450ns LOW’로 유지하여야 합니다. 우리는 제어기(아두이노)의 데이터 포트인 D2를 연결하였으므로 이 핀을 ‘800ns HIGH + 450ns LOW’로 8번 만들면 되겠네요.</p>
<p>엥? 그런데 어떻게 만들죠?</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>digitalWrite(D2) = HIGH;<br />
delay_ns(400); // nano sec 딜레이함수<br />
digitalWrite(D2) = LOW;<br />
delay_ns(850); // nano sec 딜레이함수</p>
</div>
<p>이렇게 하면 될까요?</p>
<p>바로 문제에 봉착하게 됩니다. 첫번째 문제는 delay_ns() 라는 ns 단위 딜레이 함수가 아두이노에 존재하지 않는다는 것이고,(ms, us 딜레이 함수는 있는데…) 두번째 문제는 혹시 함수를 새로 만든다고 가정해도, ns 와 같이 아주 짧은 시간 동안의 딜레이를 적용할 수 있는 정확한 함수를 프로그램 하는 것이 가능하지 않을 것으로 판단된다는 것이고, 세번째 문제는 혹 이런 함수를 비슷하게 작성한다 하더라도 실제 이 함수를 실행하는데 소요되는 시간을 매우 정교하게 제어하는 것이 어렵다는 사실입니다.</p>
<p>그렇다면 … 어떻게 해야 하나요?</p>
<p>예. 정답! 이것을 해결하려면, 고급 언어인 C 언어 레벨에서의 프로그램을 포기하고 어셈블리(assembly) 언어를 이용하여 프로그램을 작성하여야 합니다.<br />
어셈블리 언어는 기계어이므로, 실행 속도가 정해져 있습니다. 예를 들어 ‘nop’ 이라는 어셈블리 명령어는 거의 모든 프로세서에서 1 클록의 시간만을 사용합니다. 제어기(아두이노)가 만약 16Mhz 클록으로 동작하는 제어기(아두이노)라고 가정하면 ‘nop’을 실행하는데 걸리는 시간은 1/16000000 초 = 62.5ns가 됩니다. 이것을 잘 이용한다면 우리가 필요로 하는 형태의 데이터를 만들 수도 있을 것 같네요. 한 번 같이 해보실까요?</p>
<p>아두이노 UNO(16Mhz 클록)을 기준으로 ‘0’ 데이터를 한 번 만들어 보겠습니다.</p>
<p>‘0’ 데이터는 400ns HIGH + 850ns LOW 의 쌍으로 이루어집니다.<br />
400ns의 HIGH를 유지하려면, 400/62.5 = 6.4 = 약 6 클록이 필요하고, 850ns의 LOW를 유지하려면, 850/62.5 = 13.6 = 약 14 클록이 필요하므로, 아래와 같이 프로그램하면 될 것 같습니다. (규격에 보면 +/- 2 클록 정도의 오차는 허용이 되므로 정수배를 취하여도 무방함)</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>// WS2812B ‘0’ 데이터 만들기<br />
PORTD |= 0b00000100; // D2 디지털핀을 1로 만듬, 1-2 클록 소모(?)<br />
asm volatile(“nop”); // 첫번째 nop, 어셈블리 명령어로 실행, 컴파일러 최적화 금지!<br />
asm volatile(“nop”); // 두번째 nop, 어셈블리 명령어로 실행, 컴파일러 최적화 금지!<br />
…<br />
…<br />
asm volatile(“nop”); // 다섯번째 “nop”, 여기까지 6-7 클록 소모(?)<br />
PORTD |= 0b00000000; // D2 디지털핀을 0으로 만듬, 1-2 클록 소모(?)<br />
asm volatile(“nop”); // 첫번째 nop, 어셈블리 명령어로 실행, 컴파일러 최적화 금지!<br />
asm volatile(“nop”); // 두번째 nop, 어셈블리 명령어로 실행, 컴파일러 최적화 금지!<br />
…<br />
…<br />
asm volatile(“nop”); // 열세번째 “nop” , 여기까지 14-15 클록 소모(?)</p>
</div>
<p>D2 핀의 상태를 바꾸려는 명령어는 최소한 1-2 클록은 소모될 것이라고 가정하고 ‘nop’ 명령어를 필요한 개수보다 1개 적은 개수만큼만 시행하면 가장 근접한 신호 파형을 만들 수 있을 것입니다. 물론, 좀 더 정확하게 측정하려면 어셈블리어로 컴파일된 .S 파일을 분석하던지 실제 이 부분의 실행 파형을 오실로스코프로 확실하게 확인하는 것이 좋겠습니다. 우리는 일단 그냥 사용해 보고 실제 프로그램을 실행해서 정말 되는지를 확인해 보는 것으로 하겠습니다. 그리고, 1비트 데이터를 보낼 때마다 위와 같은 프로그램을 직접 써 넣어 프로그램할 수는 없으니까, 이것을 마크로(MACRO)를 이용하여 선언을 해 놓은 것이 좋을 듯 합니다.</p>
<p>아래와 같이 마크로를 정의해 놓으면 조금 편리하게 사용할 수 있겠네요.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define NOP asm volatile(“nop”)<br />
#define NOP2 NOP; NOP<br />
#define NOP3 NOP2; NOP<br />
#define NOP5 NOP3; NOP2<br />
#define NOP6 NOP3; NOP3<br />
#define NOP12 NOP6; NOP6<br />
#define NOP13 NOP6; NOP6; NOP</p>
</div>
이것을 이용하여 ‘0’ 데이터 만들기를 표현해 보면,</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>// WS2812B ‘0’ 데이터 만들기<br />
PORTD |= 0b00000100; // D2 디지털핀을 1로 만듬<br />
NOP5; // 5번의 “nop”<br />
PORTD &amp;= 0b11111011; // D2 디지털핀을 0으로 만듬<br />
NOP13; // 13번의 “nop”</p>
</div>
<p>같은 방법으로 ‘1’ 데이터를 만들어 보겠습니다.<br />
400ns의 HIGH를 유지하려면, 800/62.5 = 12.8 = 약 13클록이 필요하고, 450ns의 LOW를 유지하려면, 450/62.5 = 7.2 = 약 7클록이 필요하므로, 아래와 같이 프로그램하면 될 것 같습니다. (규격에 보면 150ns(+/- 2 클록 이상)의 오차가 허용이 되므로 정수배를 취하여도 무방합니다.)</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>// WS2812B ‘1’ 데이터 만들기<br />
PORTD |= 0b00000100; // D2 디지털핀을 1로 만듬<br />
NOP12; // 12번의 “nop”<br />
PORTD |= 0b00000000; // D2 디지털핀을 0으로 만듬<br />
NOP6; // 6번의 “nop”</p>
</div>
<p>0과 1을 만드는 것도 계속 사용할 것이니, 아예 이것도 ‘CODE0’, ‘CODE1’이라는 마크로로 선언해 놓는 것이 좋겠습니다. 덤으로 데이터리셋은 LOW 상태로 50us를 유지하는 것이므로 이것까지 ‘RES’라는 마크로로 함께 선언해 놓겠습니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define CODE0 PORTD |= 0b00000100; NOP12; PORTD &amp;= 0b11111011; NOP6<br />
#define CODE1 PORTD |= 0b00000100; NOP5; PORTD &amp;= 0b11111011; NOP13<br />
#define RES PORTD &amp;= 0b00000000; delay Microseconds(50)</p>
</div>
<p>자, 이제 기본 준비가 되었으니, 파랑색을 나타내는 (G, R, B) 값 (0&#215;00, 0&#215;00, 0xFF) 총 24비트의 값을 연속적으로 보내는 프로그램을 작성해 봅시다. 1비트 값을 보내는 코딩을 확장하여 순서대로 8비트씩 3번, 총 24비트를 전송하면 되겠습니다. G-&gt;R-&gt;B 순으로 보내야 하고, 바이트 내에서는 HIGH 비트 순으로 먼저 보내는 것이 규격이므로, 아래와 같이 되겠네요.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define NOP asm volatile(“nop”)<br />
#define NOP2 NOP; NOP<br />
#define NOP3 NOP2; NOP<br />
#define NOP5 NOP3; NOP2<br />
#define NOP6 NOP3; NOP3<br />
#define NOP12 NOP6; NOP6<br />
#define NOP13 NOP6; NOP6; NOP</p>
<p>#define CODE0 PORTD |= 0b00000100; NOP5; PORTD &amp;= 0b11111011; NOP13<br />
#define CODE1 PORTD |= 0b00000100; NOP12; PORTD &amp;= 0b11111011; NOP6<br />
#define RES PORTD &amp;= 0b00000000; delayMicroseconds(50)</p>
<p>void setup()<br />
{<br />
pinMode(2, OUTPUT);<br />
}</p>
<p>void loop()<br />
{<br />
RES; // WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // G(Green)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // R(Red)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // B(Blue)<br />
}<br />
</div>
<p>잘 되려나요? 한 번 해보겠습니다.<br />
아두이노 스케치 돌리고, 컴파일 &amp; 다운로드 얍!</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-19.jpg" rel="lightbox[31253]"><img class="alignnone size-full wp-image-31360" alt="36 카멜레온 19" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-19.jpg" width="602" height="338" /></a></p>
<p>파랑색 불이 잘 켜졌네요. 잘 된 것이겠죠?<br />
그럼, 한 숨 돌리고, 잠시 쉬었다가, 조금 더 전진해 보도록 하겠습니다.<br />
10분간 휴식~!</p>
<p><span style="font-size: medium;color: #008000"><strong>JLED-BAR-1으로 무지개색 불 켜기</strong></span></p>
<p>파랑색 불 켜는 것에 성공하였으니, 빨강색과 녹색 불 켜는 것은 쉽게 할 수 있겠지요?. 빨강색은 (G, R, B) 값을 (0&#215;00, 0xFF, 0&#215;00)로, 녹색은 (G, R, B) 값을 (0xFF, 0&#215;00, 0&#215;00)로 보내면 되니까 바로 되겠습니다. 그런데, 노랑색을 디스플레이 하려면, 어떻게 해야 할까요?</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-20.jpg" rel="lightbox[31253]"><img class="alignnone size-full wp-image-31361" alt="36 카멜레온 20" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-20.jpg" width="280" height="266" /></a></p>
<p>그림에서와 같이 빛의 3원색은 빨강, 녹색, 파랑이고, 노랑색은 빨강과 녹색을 동일 비율로 합하면 될 것 같으므로, 노랑색은 (<span style="color: #ffffff;background-color: #008000">G</span>, <span style="color: #ffffff;background-color: #ff0000">R</span>, <span style="color: #ffffff;background-color: #0000ff">B</span>) 값인 (<span style="color: #ffffff;background-color: #008000">0xFF</span>, <span style="color: #ffffff;background-color: #ff0000">0xFF</span>,<span style="color: #ffffff;background-color: #0000ff"> 0&#215;00</span>) = (0b<span style="color: #ffffff;background-color: #008000">11111111</span><span style="color: #ffffff;background-color: #ff0000">11111111</span><span style="color: #ffffff;background-color: #0000ff">00000000</span>)을 생성하여 보내면 될 것 같습니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>void loop()<br />
{<br />
RES; // WS2812B 리셋, 0 상태로 50us delay<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // G(Green)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // R(Red)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
}</p>
</div>
결국, 내가 원하는 컬러를 디스플레이 하려면 위의 방법처럼 그 컬러에 해당되는 (<span style="color: #000000;background-color: #ffffff">G, R, B</span>) 값을 찾아서 거기에 해당되는 코드를 보내주면 되겠네요. 원하는 컬러의 (G, R, B) 값은 보통 아래와 같은 색상표에서 제공하므로 이것을 이용하면 되겠구요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-21.jpg" rel="lightbox[31253]"><img class="alignnone size-large wp-image-31362" alt="36 카멜레온 21" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-21-620x347.jpg" width="620" height="347" /></a></p>
<p><span style="color: #ff0000;background-color: #ffffff">조심하여야 할 것은 일반적인 색상표는 코드를 (R, <span style="color: #ffffff;background-color: #008000">G</span>,<span style="color: #ffffff;background-color: #0000ff"> B</span>) 순으로 표시하므로 이것을<strong> WS2812B로 전송할 때</strong>는 이 순서를 그대로 사용하면 안되고<strong> (<span style="color: #ffffff;background-color: #008000">G</span>, R, <span style="color: #ffffff;background-color: #0000ff">B</span>) 순으로 순서를 바꾸어 전송</strong>하여야 한다는 점입니다. 잊으시면 안됩니다!</span></p>
<p>예를 들어 주황색을 디스플레이하고 싶다면, 주황색의 (<span style="color: #ffffff;background-color: #ff0000">R</span>,<span style="color: #ffffff;background-color: #008000"> G</span>,<span style="color: #ffffff;background-color: #0000ff"> B</span>) 값은 (FF, 66, 00)이므로 (<span style="color: #ffffff;background-color: #008000">G</span>, <span style="color: #ffffff;background-color: #ff0000">R</span>,<span style="color: #ffffff;background-color: #0000ff"> B</span>) 코드값은 (66, FF, 00)=0b<span style="color: #ffffff;background-color: #008000">01100110</span><span style="color: #ffffff;background-color: #ff0000">11111111</span><span style="color: #ffffff;background-color: #0000ff">00000000 </span>이 되므로 프로그램은 아래와 같이 됩니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>void loop()<br />
{<br />
RES; // WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE1; CODE1; CODE0; CODE0; CODE1; CODE1; CODE0; // G(Green)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // R(Red)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
}</p>
</div>
<p>자, 그러면 이제 무지개색 표현에 도전해 보도록 합시다.<br />
한가지 컬러가 디스플레이 되는 시간을 1초 정도로 하면 보기가 좋을 것 같습니다.<br />
빨강색을 디스플레이하고 1초 기다렸다가, 다음에는 주황색을 디스플레이하고… 이렇게 7가지 컬러를 디스플레이하면 되겠네요. 1초 딜레이는 아두이노 라이브러리 delay()을 이용하면 쉽게 되겠지요? 모두 한 번 해 보겠습니다. 5분 기다려 봅니다.</p>
<p>(5, 4, 3, 2, 1, 0)<br />
같이 해보시지요.</p>
<p>일단, 빨주노초파남보에 해당되는 (<span style="color: #ffffff;background-color: #008000">G</span>, <span style="color: #ffffff;background-color: #ff0000">R</span>, <span style="color: #ffffff;background-color: #0000ff">B</span>) 코드를 위 색상표에서 눈대중으로 찾으면,<br />
빨강 = (<span style="color: #ffffff;background-color: #008000">00</span>, <span style="color: #ffffff;background-color: #ff0000">FF</span>, <span style="color: #ffffff;background-color: #0000ff">00</span>), 주황 = (<span style="color: #ffffff;background-color: #008000">66</span>, <span style="color: #ffffff;background-color: #ff0000">FF</span>, <span style="color: #ffffff;background-color: #0000ff">00</span>), 노랑 = (<span style="color: #ffffff;background-color: #008000">FF</span>, <span style="color: #ffffff;background-color: #ff0000">FF</span>,<span style="color: #ffffff;background-color: #0000ff"> 00</span>), 초록 = (<span style="color: #ffffff;background-color: #008000">FF</span>, <span style="color: #ffffff;background-color: #ff0000">00</span>, <span style="color: #ffffff;background-color: #0000ff">00</span>), 파랑 = (<span style="color: #ffffff;background-color: #008000">00</span>, <span style="color: #ffffff;background-color: #ff0000">00</span>,<span style="color: #ffffff;background-color: #0000ff"> FF</span>),남색 = (<span style="color: #ffffff;background-color: #008000">00</span>, <span style="color: #ffffff;background-color: #ff0000">33</span>, <span style="color: #ffffff;background-color: #0000ff">99</span>), 보라 = (<span style="color: #ffffff;background-color: #008000">00</span>,<span style="color: #ffffff;background-color: #ff0000"> 66</span>,<span style="color: #ffffff;background-color: #0000ff"> FF</span>) 정도로 표시될 것 같습니다.<br />
무식한 방법이긴 하지만 이 코드를 이용하여 위에서 사용했던 방법을 반복적으로 7번 사용하면서 디스플레이될 컬러만 순서대로 바꾸어주면 됩니다. 뭐 저라고 뾰족한 수는 없습니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define NOP asm volatile(“nop”)<br />
#define NOP2 NOP; NOP<br />
#define NOP3 NOP2; NOP<br />
#define NOP5 NOP3; NOP2<br />
#define NOP6 NOP3; NOP3<br />
#define NOP12 NOP6; NOP6<br />
#define NOP13 NOP6; NOP6; NOP</p>
<p>#define CODE0 PORTD |= 0b00000100; NOP5; PORTD &amp;= 0b11111011; NOP13<br />
#define CODE1 PORTD |= 0b00000100; NOP12; PORTD &amp;= 0b11111011; NOP6<br />
#define RES PORTD &amp;= 0b00000000; delayMicroseconds(50)</p>
<p>void setup()<br />
{<br />
pinMode(2, OUTPUT); // D2를 데이터비트로 사용<br />
}</p>
<p>void loop()<br />
{<br />
RES; // 빨강, WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // G(Green)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // R(Red)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
delay (1000); // 1초 디스플레이</p>
<p>RES; // 주황, WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE1; CODE1; CODE0; CODE0; CODE1; CODE1; CODE0; // G(Green)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // R(Red)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
delay (1000); // 1초 디스플레이</p>
<p>RES; // 노랑, WS2812B 리셋, 0 상태로 50us delay<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // G(Green)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // R(Red)<br />
CODE0; CODE0<br />
; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
delay (1000); // 1초 디스플레이</p>
<p>RES; // 초록, WS2812B 리셋, 0 상태로 50us delay<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // G(Green)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // R(Red)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // B(Blue)<br />
delay (1000); // 1초 디스플레이</p>
<p>RES; // 파랑, WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // G(Green)<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // R(Red)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // B(Blue)<br />
delay (1000);// 1초 디스플레이</p>
<p>RES; // 남색, WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // G(Green)<br />
CODE0; CODE0; CODE1; CODE1; CODE0; CODE0; CODE1; CODE1; // R(Red)<br />
CODE1; CODE1; CODE1; CODE0; CODE1; CODE1; CODE1; CODE0; // B(Blue)<br />
delay (1000); // 1초 디스플레이</p>
<p>RES; // 보라, WS2812B 리셋, 0 상태로 50us delay<br />
CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; CODE0; // G(Green)<br />
CODE0; CODE1; CODE1; CODE0; CODE0; CODE1; CODE1; CODE0; // R(Red)<br />
CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; CODE1; // B(Blue)<br />
delay (1000); // 1초 디스플레이<br />
}</p>
</div>
다들 잘 디스플레이 되나요?</p>
<p>잘 되셨다면 자축의 물개박수~~~</p>
<p>내가 원하는 7가지 무지개 색깔을 디스플레이 하는데 성공하였다는 이야기는 R, G, B로 나타낼 수 있는 모든 경우의 컬러를 디스플레이할 수 있다는 이야기가 됩니다. 총 몇가지나 될까요? R, G, B 강도를 나타내는 비트가 각각 8비트씩이므로 만들어질 수 있는 총 가지수는 256X256X256 = 16,777,226(1600만 이상)이 됩니다.</p>
<p>와~ 내가 JLED-BAR-1 1개를 가지고 표현할 수 있는 컬러가 1600만가지라니… 뭔가 좀 뿌듯한 감정이 올라오는 것도 같죠?</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;color: #008000"><strong>JLED-RING-12 로 12색상환 만들기</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-22.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31363" alt="36 카멜레온 22" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-22-620x584.jpg" width="278" height="262" /></a></p>
<p>이제 1개의 WS2812B LED의 색상은 자유롭게 표현 가능하므로 이번에는 여러 개의 WS2812B LED가 연속적으로 연결된 형태에서 다양한 색상을 만들어 보는 연습을 해보겠습니다. 목표는 WS2812B 12개를 연속적으로 연결하여 둥근 링 형태를 구성하고 여기에 12가지 컬러를 넣어 아래와 같은 12 색상환을 만들어보는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-23.jpg" rel="lightbox[31253]"><img class="alignnone size-full wp-image-31364" alt="36 카멜레온 23" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-23.jpg" width="213" height="216" /></a><br />
12색상환은 초등학교 미술시간에 한번쯤은 색칠해 보았을 것으로 생각되는데요. 마침 카멜레온 DIY LED에 이것과 비슷하게 생긴 JLED-RING-12 라는 제품이 있으니 여기에 색상을 입히면 안성맞춤이 될 것 같네요.</p>
<p>JLED-RING-12는 앞에서 WS2812B 동작 원리를 설명하면서 사용하였던 연결관계 그림과 동일한 방법으로 WS2812B 12개를 직렬(시리얼)로 연결한 둥근 반지(RING) 형태를 띄고 있습니다.</p>
<p>프로그램 방법은 JLED-BAR-1에서 사용한 것과 거의 동일합니다. 조금 다른 것은 JLED-BAR-1의 컬러를 준비할 때는 1개의 RGB 쌍을 준비하였다면, 이번에는 12개의 RGB 쌍을 준비하여야 한다는 것과, 이 데이터를 순서대로 딜레이없이<span style="color: #ff0000"><strong>(중요!, 딜레이가 50us를 넘으면 12개 LED가 켜지는 것이 아니고 1개 LED만 컬러가 12번 바뀌면서 켜짐)</strong> </span>연속해서 내보내야 한다는 것입니다.</p>
<p>그럼 준비를 해볼까요?</p>
<p>인터넷에서 12색상환에 사용될 12가지 색상에 대한 코드를 찾아보니 아래와 같이 나옵니다. (RGB 순)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-ict-카멜레온-666.png" rel="lightbox[31253]"><img class="alignnone  wp-image-31371" alt="36 ict 카멜레온 666" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-ict-카멜레온-666-620x121.png" width="496" height="97" /></a></p>
<p>조금 번거롭긴 하지만 아직 라이브러리를 사용하는 방법을 배우지 않았으니, 오늘은 그냥 머슴처럼 꾹 참고 한 개씩 순서대로 내보내는 코딩으로 계속 가겠습니다. (좀 더 깔끔하고 간단한 방법은 다음 시간에…)<br />
숫자가 많이 나오므로 마크로 정의를 음성기호(phonetic alphabet)로 더 만들어 사용하면 편할 것 같으므로 아래와 같이 형태로 마크로를 추가합니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define ONE CODE0; CODE0; CODE0; CODE1 // 1 = 0&#215;1 = 0b0001<br />
#define TWO CODE0; CODE0; CODE1; CODE0 // 2 = 0&#215;2 = 0b0010<br />
…<br />
#define ALPHA CODE1; CODE0; CODE1; CODE0; // 10 = 0xa = 0b1010<br />
…<br />
#define FOXTROT CODE1; CODE1; CODE1; CODE1; // 15 = 0xf = 0b1111</p>
</div>
자, 준비가 다 되었으면 이제 실전 코딩입니다. GO~</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#define NOP asm volatile(“nop”)<br />
#define NOP2 NOP; NOP<br />
#define NOP3 NOP2; NOP<br />
#define NOP5 NOP3; NOP2<br />
#define NOP6 NOP3; NOP3<br />
#define NOP12 NOP6; NOP6<br />
#define NOP13 NOP6; NOP6; NOP<br />
#define CODE0 PORTD |= 0b00000100; NOP5; PORTD &amp;= 0b11111011; NOP13<br />
#define CODE1 PORTD |= 0b00000100; NOP12; PORTD &amp;= 0b11111011; NOP6<br />
#define RES PORTD &amp;= 0b00000000; delayMicroseconds(50)</p>
<p>#define ZERO CODE0; CODE0; CODE0; CODE0 // 0 = 0&#215;00 = 0b0000<br />
#define ONE CODE0; CODE0; CODE0; CODE1 // 1 = 0&#215;01 = 0b0001<br />
#define TWO CODE0; CODE0; CODE1; CODE0 // 2 = 0&#215;02 = 0b0010<br />
#define THREE CODE0; CODE0; CODE1; CODE1 // 3 = 0&#215;03 = 0b0011<br />
#define FOUR CODE0; CODE0; CODE1; CODE1 // 4 = 0&#215;04 = 0b0100<br />
#define FIVE CODE0; CODE0; CODE1; CODE1 // 5 = 0&#215;05 = 0b0101<br />
#define SIX CODE0; CODE0; CODE1; CODE1 // 6 = 0&#215;06 = 0b0110<br />
#define SEVEN CODE0; CODE0; CODE1; CODE1 // 7 = 0&#215;07 = 0b0111<br />
#define EIGHT CODE0; CODE0; CODE1; CODE1 // 8 = 0&#215;08 = 0b1000<br />
#define NINE CODE0; CODE0; CODE1; CODE1 // 9 = 0&#215;09 = 0b1001<br />
#define ALPHA CODE0; CODE0; CODE1; CODE1 // 10 = 0x0a = 0b1010<br />
#define BRAVO CODE0; CODE0; CODE1; CODE1 // 11 = 0x0b = 0b1011<br />
#define CHARLIE CODE0; CODE0; CODE1; CODE1 // 12 = 0x0c = 0b1100<br />
#define DELTA CODE0; CODE0; CODE1; CODE1 // 13 = 0x0d = 0b1101<br />
#define ECHO CODE0; CODE0; CODE1; CODE1 // 14 = 0x0e = 0b1110<br />
#define FOXTROT CODE1; CODE1; CODE1; CODE1; // 15 = 0x0f = 0b1111</p>
<p>void setup()<br />
{<br />
pinMode(2, OUTPUT); // D2를 데이터비트로 사용<br />
}</p>
<p>void loop()<br />
{<br />
// WS2812B 리셋, 0 상태로 50us delay<br />
RES;<br />
// 빨강 : 0xff0000 ▶ 0x00ff00<br />
ZERO; ZERO; FOXTROT; FOXTROT; ZERO; ZERO;<br />
// 다홍 : 0xdc143c ▶ 0x14dc3c<br />
ONE; FOUR; DELTA; CHARLIE; THREE; CHARLIE;<br />
// 주황 : 0xff7f00 ▶ 0x7fff00<br />
SEVEN; FOXTROT; FOXTROT; FOXTROT; ZERO; ZERO;<br />
// 귤색 : 0xf89b00 ▶ 0x9bf800<br />
NINE; BRAVO; FOXTROT; EIGHT; ZERO; ZERO;<br />
// 노랑 : 0xffd400 ▶ 0xd4ff00<br />
DELTA; FOUR; FOXTROT; FOXTROT; ZERO; ZERO;<br />
// 연두 : 0x66cc00 ▶ 0xcc6600<br />
CHARLIE; CHARLIE; SIX; SIX; ZERO; ZERO;<br />
// 녹색 : 0x00ff00 ▶ 0xff0000<br />
FOXTROT; FOXTROT; ZERO; ZERO; ZERO; ZERO;<br />
// 청록 : 0&#215;005666 ▶ 0&#215;560066<br />
FIVE; SIX; ZERO; ZERO; SIX; SIX;<br />
// 파랑 : 0x0000ff ▶ 0000ff<br />
ZERO; ZERO; ZERO; ZERO; FOXTROT; FOXTROT;<br />
// 남색 : 0x080b54 ▶ 0x0b0854<br />
ZERO; BRAVO; ZERO; EIGHT; FIVE; FOUR;<br />
// 보라 : 0xee82ee ▶ 0x82eeee<br />
EIGHT; TWO; ECHO; ECHO; ECHO; ECHO;<br />
// 자주 : 0&#215;800080 ▶ 0&#215;008080<br />
ZERO; ZERO; EIGHT; ZERO; EIGHT; ZERO;<br />
RES;<br />
}<br />
</div>
<p>컴파일 ▶ 업로드 하면, … 와우~~~ 멋진 색상환이 나왔습니다.<br />
환상적이네요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-24.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31365" alt="36 카멜레온 24" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-24-620x376.jpg" width="496" height="301" /></a></p>
<p>너무 밝아서 가까이에 가서 다시 크게 찍어 본 사진을 올려 봅니다. 또렷ㅍ하지는 않네요.<br />
실제 색상은 훨씬 더 화려하고 또렷합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-25.jpg" rel="lightbox[31253]"><img class="alignnone  wp-image-31366" alt="36 카멜레온 25" src="http://www.ntrexgo.com/wp-content/uploads/2016/05/36-카멜레온-25-620x382.jpg" width="496" height="306" /></a></p>
<p>여러분도 모두 성공하셨죠? 또 축하의 박수!<br />
그리고, 또 하나의 중요한 사실은 이제 컬러 세팅하는 방법과 여러 개의 WS2812B를 제어하는 방법을 습득했으므로, 이제부터는 어떤 모양, 어떤 컬러, 어떤 동작도 조금씩만 응용하면 모두 다 만들 수 있는 능력을 갖추었다는 사실입니다. 엄청난 힘을 갖게 된 것이지요. 어벤저스(?) 같은 힘!<br />
물론, 조금 찜찜하게 남아 있는 부분도 있습니다.<br />
CODE0, CODE1을 생성하는 처리 방법이 확실하지 않다는 점과, 코드 작성이 MACRO로 하나씩 작성하도록 되어 있어 지루하다는 점입니다. 이것 때문일까요? JLED-RING-12의 불빛이 아주 살짝 흔들리는 것 같기도 하구요. 어쨌든, 여기에 대한 해결책은 다음 번 이야기 “카멜레온 DIY LED를 위한 아두이노 라이브러리”에서 깔끔하게 해결하는 것으로 하겠습니다.<br />
즐거운 시간 되셨나요? 오늘밤에는 꿈 속에서 알록달록한 12가지 아름다운 꿈이 펼쳐지도록 여러분의 머리맡에 12색상환 프로그램을 수행하는 JLED-RING-12를 켜놓고 주무시는 경험을 해보는 것도 좋겠습니다. 그럼, 이번 호의 이야기는 여기서 마치고 다음 호에서는 좀 더 재미있는 이야기를 가지고 다시 만나겠습니다. 안녕히 계십시오.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/31253/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[34호] 너무 쉬운 아두이노 DIY ⑥ &#8211; 스마트폰으로 조종하는 스마트카</title>
		<link>http://www.ntrexgo.com/archives/30243</link>
		<comments>http://www.ntrexgo.com/archives/30243#comments</comments>
		<pubDate>Fri, 15 Jan 2016 04:59:23 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[blog-posts]]></category>
		<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[프로젝트]]></category>
		<category><![CDATA[34호]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[Project To Build]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[스마트카]]></category>
		<category><![CDATA[스마트폰]]></category>
		<category><![CDATA[아두이노]]></category>
		<category><![CDATA[조종]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=30243</guid>
		<description><![CDATA[디바이스마트매거진 34호 &#124; 오늘의 주제는 ‘스마트폰으로 조종하는 스마트카’입니다. 스마트폰으로 조종하여 전진, 후진, 좌회전, 우회전 및 정지가 가능한 스마트카를 만들어 보겠습니다. 마지막이어서 조금은 어려울 수도 있겠지만 그동안 기본기를 많이 갈고 닦았으므로 무난히 다 잘 하실 수 있으리라 생각합니다.]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-아두이노.jpg" rel="lightbox[30243]"><img alt="34 아두이노" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-아두이노.jpg" width="620" height="174" /></a></p>
<p style="text-align: right;">글 | 신상석 ssshin@jcnet.co.kr</p>
<p> <div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>이 강의는 아두이노를 가지고 간단하게 생활에 필요한 용품을 만들어 보는 강의입니다. 뚝딱뚝딱 뭔가 자신만의 DIY 용품을 만들어 보는 쏠쏠한 재미가 있는 강의라고나 할까요? 이미 주변에 아두이노와 관련한 많은 책이 출간되었고 카페나 블로그를 통하여 강의가 진행된 경우도 꽤나 많이 있는데도 불구하고, 이 지면을 통하여 강의를 개설한 이유는 다음과 같습니다.</p>
<p>1. 아두이노의 초보자들을 위한 쉽고 재미있는 강의가 거의 없는 것 같아, 가능하면 초등학생(?)까지도 함께 해 볼 수 있는 그런 강의를 한 번 해보고 싶어서…<br />
2. 아두이노를 가지고 뭔가 조금은 다른, 자신만의 창의적인(?) DIY를 할 수 있는 자리를 만들어주고 싶어서…<br />
3. 디바이스마트매거진은 임베디드와 관련된 독자들이 많고, 발행 부수도 많아, 저와 제가 속한 회사(제이씨넷) 그리고 임베디드홀릭 카페의 홍보에 도움이 될 것 같아서…</p>
<p>현재 구상하고 있는 회차별 내용을 간략하게 정리해 보면 다음과 같습니다. (변경될 수 있습니다.)</p>
<table style="border: 1px solid #e2dee2; width: 340px;" border="1" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="text-align: center;">회차</td>
<td>내용</td>
</tr>
<tr>
<td style="text-align: center;">1</td>
<td>3색 신호등 만들기</td>
</tr>
<tr>
<td style="text-align: center;">2</td>
<td>카멜레온 반지, 스위치를 이용한 신호등 게임기</td>
</tr>
<tr>
<td style="text-align: center;">3</td>
<td>FND로 만드는 디지털전압계, 카운트다운 계수기</td>
</tr>
<tr>
<td style="text-align: center;">4</td>
<td>어두워지면 켜지는 정원등, 공중회전그네</td>
</tr>
<tr>
<td style="text-align: center;">5</td>
<td>캐롤송 카드, 컬러링 온도계</td>
</tr>
<tr>
<td style="text-align: center;">6</td>
<td>스마트폰으로 조정하는 스마트카</td>
</tr>
</tbody>
</table>
<p>앞으로 즐겁고 알찬 강의가 될 수 있도록 최선을 다할 것을 약속 드리며, 이 강의를 보는 독자들도 메일이나 카페를 통하여 Q&amp;A(Question &amp; Answer)나 피드백을 주셔서, 함께 정감을 나눌 수 있는 계기가 되기를 기대해 봅니다.<br />
</div>
<p>&nbsp;</p>
<p>여러분, 안녕하세요.<br />
쏜살갈이 시간은 흘러 어느덧 [너무 쉬운 아두이노 DIY] 강좌의 마지막 회입니다. 지난해 따뜻해지는 봄 기운을 느끼며 첫 회를 시작했는데, 시기도 적절하게 겨울 자락에 마지막 회로 마감하게 되었습니다. 유종지미(有終之美), ‘끝을 잘 맺는 아름다움’의 의미처럼 함께 마무리를 잘 해 보도록 하겠습니다.<br />
오늘의 주제는 ‘스마트폰으로 조종하는 스마트카’입니다. 스마트폰으로 조종하여 전진, 후진, 좌회전, 우회전 및 정지가 가능한 스마트카를 만들어 보겠습니다. 마지막이어서 조금은 어려울 수도 있겠지만 그동안 기본기를 많이 갈고 닦았으므로 무난히 다 잘 하실 수 있으리라 생각합니다.<br />
스마트카는 요즈음 IT에서 핫이슈가 되고 있는 분야입니다.<br />
구글은 완전한 자율주행이 가능한 자동차를 2018년까지 출시하기로 하고, 현재 상당한 진전을 이루고 있는 상태입니다. 3D 카메라, 레이저, 음파 센서, GPS 등의 다양한 전자기기가 장착되고 있으며, 이들을 통합 제어하는 구글오토라는 소프트웨어도 탑재하고 있습니다. 스마트카 시장에는 구글뿐만 아니라 테슬라, 애플 등의 IT업체와 BMW, 폭스바겐 등의 완성차 업체도 도전장을 내놓은 상태입니다. 이쪽 동네 이야기는 일단 시작하면 이야기가 길어지므로… 여기서 싹둑, 다시 본론으로 돌아갑니다.<br />
우리는 동작 원리에만 중점을 두어 최소한의 기능만 포함된 아주 간단한 스마트카를 만들어 보도록 하겠습니다.</p>
<p><span style="color: #ffffff; font-size: medium; background-color: #008000;"><strong>■ 내 자동차(Bory) 규격 및 준비물   </strong></span></p>
<p>자동차의 종류는 다양하여 승용차도 있고 트럭도 있고, 승용차 중에도 고급 승용차도 있고, 경차도 있지만 우리의 자동차는 그저 차체 프레임에 바퀴가 달려있어 굴러갈 수 있는 정도의 자동차로 일단 한정하겠습니다. 하지만 진짜 자동차에는 없는 기능으로, 스마트폰으로 명령을 내릴 수도 있고, 장착 여부에 따라서는 라인트레이서나 자율주행자동차도 될 수 있는 꽤 멋진 DIY 자동차가 될 수 있을 것입니다.<br />
일단 이름을 먼저 정하고 규격을 정한 다음 차근차근 구현해 보도록 하지요. 제 자동차의 이름은 보리(Bory)로 하겠습니다. 예전에 집에서 애완용으로 키웠던 페릿에게 붙여준 이름인데요. 이름이 구수하고 정겨워서 이것으로 합니다. 여러분도 자기 나름대로 이름을 붙이고 시작해 보시기를….<br />
자, 그러면 다음 단계로 규격을 정해볼까요?</p>
<p><strong>[보리(Bory) 스마트카 규격]</strong><br />
· 스마트폰의 앱으로 전진, 후진, 좌회전, 우회전 운행 가능<br />
· 아두이노 UNO로 제어<br />
· 크기는 손바닥 크기 정도<br />
· 뒤쪽에 바퀴 2개(모터 장착), 앞쪽에 바퀴(캐스터) 1개(모터 미장착, 지지대용)<br />
· 전원은 건전지(또는 리튬전지) 등의 휴대용 전원으로 공급</p>
<p><strong>[보리(Bory) 스마트카 형태]</strong><br />
아래 JARDUINO-UNO-CAR(V2.0)과 비슷한 모습</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-01.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30497" alt="34 프로젝트 01" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-01.jpg" width="496" height="412" /></a><br />
이러한 규격을 만족하기 위하여 필요한 부품을 살펴보면 아래와 같이 될 것 같습니다.</p>
<p>1. 아두이노 UNO가 있어야 하고,<br />
2. 차체(프레임)가 있어야 하겠습니다.<br />
3. 차체에 연결할 바퀴가 2개 있어야 하고,<br />
4. 앞쪽에는 캐스터(지지용 바퀴)가 1개 필요합니다.<br />
5. 바퀴 2개를 구동하려면 모터(DC 모터)가 2개 필요하겠죠?<br />
6. 이 모터를 구동할 모터 드라이버도 역시 준비해야겠네요..<br />
7. 스마트폰과 통신을 하기 위해서는 블루투스 시리얼 모듈이 있어야 하고,,<br />
8. 스마트카의 전원으로는 모터에 전원을 공급할 배터리(홀더)가 필요하며, 아두이노와, 모터드라이버, 블루투스 시리얼 모듈에 전원을 공급할 배터리(홀더) + 전원공급기가 필요하겠습니다. (일반적으로 모터는 전류를 많이 사용하고, 순간적인 과전류로 인한 전압강하도 일어나는 부품이므로 아두이노나 다른 부품과는 다른 전원을 사용하는 것이 좀 더 안전한 방법이기 때문에 2개의 다른 전원 소스를 사용하는 것이 좋습니다.)<br />
9. 마지막으로 모터(바퀴)나 캐스터 등을 차체에 고정할 브라켓이나 서포터, 나사, 전선 등도 다수 필요하겠습니다.</p>
<p>이 부품들은 따로 따로 하나씩 임의로 구해도 되지만 너무 복잡하므로 일정 부분 이미 상품으로 제공되는 것을 사용하도록 하겠습니다. 아래와 같이 정리가 되겠네요.</p>
<table style="width: 620px;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>부품</td>
<td>개수</td>
<td>기능</td>
<td>기타</td>
</tr>
<tr>
<td>아두이노 UNO</td>
<td style="text-align: center;">1</td>
<td>스마트카 제어</td>
<td>아두이노 UNO<br />
정품 및 호환 제품</td>
</tr>
<tr>
<td>JKIT-CAR-1</td>
<td style="text-align: center;">2</td>
<td>아두이노 AVR 카 베이스 (차체 1개, 바퀴 2개, 모터 2개,<br />
캐스터 1개, 건전지홀더 1개, 브라켓 및 서포터, 나사 다수 포함,<br />
아두이노/AVR은 미포함)</td>
<td></td>
</tr>
<tr>
<td>JMODMOTOR-1</td>
<td style="text-align: center;">1</td>
<td>4.5~13.5V, 1.2A, 2채널 모터 드라이버(바퀴 구동)</td>
<td></td>
</tr>
<tr>
<td>JMOD-BT-1</td>
<td style="text-align: center;">1</td>
<td>블루투스 시리얼 모듈 (스마트폰과 통신)</td>
<td></td>
</tr>
<tr>
<td>JBATT-U5-LC (리튬전지 포함)</td>
<td style="text-align: center;">1</td>
<td>아두이노 및 기타 모듈에 전원 공급</td>
<td></td>
</tr>
<tr>
<td>소형 브레드보드</td>
<td style="text-align: center;">1</td>
<td>HC-SR04 장착용</td>
<td></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<table style="width: 620px;" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-02.jpg" rel="lightbox[30243]"><img class="wp-image-30498 aligncenter" alt="34 프로젝트 02" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-02-284x300.jpg" width="159" height="168" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-03.jpg" rel="lightbox[30243]"><img class="wp-image-30499 aligncenter" alt="34 프로젝트 03" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-03-300x291.jpg" width="168" height="163" /></a></td>
</tr>
<tr>
<td style="text-align: center;">JKIT-CAR-1 + 아두이노 UNO</td>
<td style="text-align: center;">JMOD-MOTOR-1</td>
</tr>
<tr>
<td style="text-align: center;"><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-04.jpg" rel="lightbox[30243]"><img class="wp-image-30500 aligncenter" alt="34 프로젝트 04" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-04-300x225.jpg" width="192" height="144" /></a></td>
<td style="text-align: center;"><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-05.jpg" rel="lightbox[30243]"><img class="alignnone size-medium wp-image-30501" alt="34 프로젝트 05" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-05-300x128.jpg" width="300" height="128" /></a></td>
</tr>
<tr>
<td style="text-align: center;">JMOD-BT-1</td>
<td style="text-align: center;">리튬전지 + JBATT-U5-LC</td>
</tr>
</tbody>
</table>
<p>그러면 위의 부품들을 가져다가 대충 한 번 연결해 보지요. 이런 형태가 될라나요?</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-06.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30502" alt="34 프로젝트 06" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-06.jpg" width="620" height="505" /></a><br />
기계적인 부분을 제외하면, 조금 더 자세하게 살펴보아야 할 부품은 모터드라이버, 블루투스 시리얼 모듈 정도인데, 모터드라이버는 이전 강좌에서 자세히 다루었으므로 생략하고, 블루투스 시리얼 모듈에 대해서만 기초 지식을 조금 더 보충한 후에 본격적인 스마트카 제작에 나서겠습니다.</p>
<p><span style="font-size: medium; color: #ffffff; background-color: #008000;"><strong>■ 시리얼 통신    </strong></span></p>
<p>블루투스 시리얼 모듈의 동작을 이해하려면 먼저 UART(Universal Asynchronous Receiver/Transmitter) 시리얼 통신에 대한 기초 지식을 갖추어야 합니다.<br />
일반적으로 컴퓨터나 전자기기 간에 데이터나 정보를 주고 받는 행위를 통신이라고 하는데, 이들은 사람이 아니므로 반드시 미리 정해진 규칙을 따라야만 통신이 가능합니다. 예를 들어, 나는 한국어로 이야기하고, 상대방은 아랍어로 이야기한다면 서로 알아들을 수가 없다는 것이지요. 한국어면 한국어, 아랍어면 아랍어 등, 한가지 규칙을 가지고 이야기해야만 대화가 가능하며, 이 경우도 사용하는 언어를 양쪽 사람이 모두 자유롭게 정확한 의미로 사용할 수 있어야 한다는 것은 물론입니다.<br />
아두이노도 외부 PC나 전자기기와 통신할 수 있는 통신 규칙(보통 통신 프로토콜(Communication Protocol)이라고 함)을 가지고 있는데, 그 중 대표적인 것이 시리얼통신입니다. 통신을 하려면 상대방과 연결되는 통로가 있어야 하는데, 여기서 돌발 퀴즈!<br />
아두이노가 PC와 통신을 한다고 하면 어떤 통로를 이용하여 통신을 할까요?</p>
<p>10초 드립니다. 10, 9, 8, 7, 6, 5, 4, 3, 2, 1. 종료!</p>
<p>뭐죠? 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방식으로 통신한다고 생각하면 되겠습니다. 어려운걸 쉽게 설명하려니 더 어렵네요. 이 말이 더 어렵나요?<br />
사실 시리얼통신(UART통신)의 세부적인 동작을 이해하는 것은 조금 시간이 걸리는 이야기인데, 여기서는 그냥 아래와 같은 특징을 가지고 동작한다고 이해하는 정도로 넘어가겠습니다.</p>
<p><strong>[시리얼 통신 기능/동작 설명]</strong><br />
(1) 사용하는 통신라인(신호)은 TxD, RxD, GND의 3개 선입니다.<br />
TxD는 송신 데이터, RxD는 수신 데이터, GND는 접지(0V) 신호이며, 통신하고자 하는 쌍방은 GND-GND, TxD-RXD, RxD-TxD의 짝으로 연결하여야 합니다. TxD는 Transmit Data의 약어로 송신 데이터를 의미하고, RxD는 Received Data의 약어로 수신 데이터를 의미하지요. 한쪽에서 TxD로 데이터를 보내면 상대방은 RxD로 데이터를 받아야 하므로 TxD-RxD, RxD-TxD의 쌍으로 신호를 연결하여야만 정상적인 통신이 가능합니다.</p>
<p>(2) PC(또는 스마트폰 등 상대방)와 아두이노는 서로 통신 속도가 맞아야 통신이 가능합니다.<br />
1초 동안에 주고 받을 수 있는 데이터 비트 수를 보레이트(baudrate)라고 하는데 시리얼통신에서는 이 보레이트를 서로 동일하게 맞추어야 통신이 가능합니다. 보레이트는 여러가지가 있지만 가장 많이 사용하는 것은 9600/38400/115200 baud이고, 아두이노에서는 9600 baud가 가장 많이 사용됩니다. 예를 들어, 9600 baud는 1초에 9600 비트(바이트로는 1200 바이트)가 되며, 통신시 들어가는 오버헤드를 감안하면 약 1,000 바이트, 즉 1,000개의 문자를 1초 동안에 주거나 받을 수 있는 정도의 통신 속도가 됩니다.</p>
<p>(3) 데이터는 한 문자(바이트) 단위로 전송됩니다.(write/read)<br />
데이터를 주고받는 단위는 한 바이트입니다. 바이트의 값은 어떤 값도 가능하지만 아래의 테이블과 같은 ASCII 코드를 이용하여 데이터를 주고 받는 것이 보통입니다. 예를 들어 ‘A’라는 글자는 표에서 찾아보면 16진수로 0&#215;41, 10진수로는 65의 값을 갖습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-07.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30503" alt="34 프로젝트 07" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-07.jpg" width="496" height="549" /></a></p>
<p>기왕 테이블이 나온 김에 보너스로 자주 사용되는 제어문자 몇 가지만 더 알아두고 가겠습니다.</p>
<table style="width: 620px;" border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>ASCII 값</td>
<td>약어</td>
<td>이름</td>
<td>C 에서의 표기</td>
<td>기능</td>
</tr>
<tr>
<td>0&#215;00</td>
<td>NUL</td>
<td>Null</td>
<td>￦0</td>
<td>문장의 마지막을 나타냄</td>
</tr>
<tr>
<td>0&#215;08</td>
<td>BS</td>
<td>Back Space</td>
<td>￦b</td>
<td>커서 위치를 1칸 전 위치로</td>
</tr>
<tr>
<td>0x0a</td>
<td>LF/NL</td>
<td>Line Feed(New Line)</td>
<td>￦n</td>
<td>커서 위치를 1줄 아래 위치로</td>
</tr>
<tr>
<td>0x0d</td>
<td>CR</td>
<td>Carrage Return</td>
<td>￦r</td>
<td>커서 위치를 줄 첫번째 위치로</td>
</tr>
</tbody>
</table>
<p>예를 들어 PC등의 화면에서 한 문장을 끊어서 줄바꿈을 하려면 ‘0x0d’, ‘0x0a’를 문장의 마지막에 보내주면 됩니다. (물론 실제 프로그램 작성시에는 라이브러리를 사용하므로 직접 이것을 넣어주는 일은 별로 없겠습니다.)</p>
<p>(4) 새로운 데이터를 보내기 위하여는 관련 플래그를 체크한 후에, 송신 가능한 상태이면 송신버퍼에 쓰면(write) 데이터를 전송할 수 있습니다. 아두이노에서는 이와 같은 기능을 모두 라이브러리로 제공하므로 우리는 제공되는 함수를 그냥 사용하면 됩니다.</p>
<p>(5) 새로운 데이터가 들어왔다는 사실은 관련 플래그를 체크하면 알 수 있고, 이 때 수신버퍼를 읽으면 전송된 데이터를 가져올 수 있습니다. 아두이노에서는 이와 같은 기능을 모두 라이브러리로 제공하므로 우리는 그냥 제공되는 함수를 사용하면 됩니다.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium; color: #ffffff; background-color: #008000;"><strong>■ 시리얼 통신을 위한 아두이노 라이브러리    </strong></span></p>
<p>이번에는 UART 통신을 위한 아두이노 라이브러리를 자세히 살펴보겠습니다. 블루투스 시리얼 통신을 하려면 미리 알아두어야 하는 라이브러리입니다.<br />
시리얼 장치의 baudrate를 결정하는 함수는 Serial.begin( ) 입니다. 이 함수는 처음에 한 번만 실행되면 되므로 setup( ) 프로그램에서 사용하면 되겠습니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">void Serial.begin(baudrate)</span><br />
<span style="color: #008080;"> &#8211; baudrate : 실제 설정할 baudrate 값으로 9600, 38400, 115200 등이 사용됨</span></p>
<p>그런데, 이 라이브러리는 조금 이상한 점이 있네요?<br />
즉, 이제까지 배운 함수는 이름이 문자열로만 이루어졌는데, 이번에 나타난 함수는 이름에 ‘.’을 포함하고 있습니다. 음… 이게 뭘까?<br />
이것은 위 함수가 C에서 사용하는 함수가 아니라 C++에서 사용되는 클래스(Class)임을 나타냅니다. (C++의 클래스 개념이 어려운 분은 따로 공부하시기 바라며, 여기서는 그냥 ‘여러가지 비슷한 속성을 갖는 멤버들의 그룹 명칭’ 정도로 이해하고 넘어갑니다.) 즉, Serial은 아두이노가 시리얼통신을 수행할 때 필요한 클래스임을 나타내며 ‘.’ 뒤의 부분은 이 클래스에 속하는 멤버 함수를 표시하는 것이지요. 그러므로 Serial.begin( )은 Serial 클래스에 속하는 멤버 함수 중 begin( ) 함수를 의미하는 것입니다. 뒤에도 나오겠지만, Serial.available( ), Serial.write( ) 등도 같은 구조를 가지고 있습니다. 한편, Serial은 기본 클래스로 구분되어 있어 별도로 #include를 사용한 헤더파일을 포함하지 않아도 바로 처리가 되도록 되어있다는 점도 함께 알아두시면 왜 “#include …”문이 없어도 Serial.xxx( ) 함수가 실행되는지를 이해할 수 있을 것입니다.<br />
데이터가 들어왔는지를 검사하는 라이브러리는 Serial.avaliable( ) 함수입니다.<br />
UART 통신을 통하여 들어온 데이터의 개수가 리턴되며 최대 64까지의 값을 가질 수 있지만 보통은 1 또는 0 값이 리턴됩니다. 1이면 데이터가 1개 들어온 것이고, 0이면 전송된 데이터가 없는 것이지요.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">int Serial.avaliable( )</span><br />
<span style="color: #008080;"> &#8211; return 값 : 입력된 데이터 수 (보통은 데이터가 있으면 1, 없으면 0)</span></p>
<p>상대방이 보낸 데이터 수신하는 라이브러리는 Serial.read( )입니다. 전송된 데이터가 여러 개 있다 하더라도 읽혀지지 않은 가장 먼저 입력된 데이터 1개만을 읽어오게 됩니다. 그러므로 입력된 데이터가 여려 개 있다면 이 함수를 여러 번 수행하여 순서대로 모든 데이터를 읽어오면 되겠습니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">char Serial.read( )</span><br />
<span style="color: #008080;"> &#8211; return 값 : 입력된 데이터 버퍼의 첫번째 데이터(1 문자)</span></p>
<p>데이터를 상대방에게 송신하는 라이브러리는 Serial.write( )입니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">int Serial.write(char val)</span><br />
<span style="color: #008080;"> &#8211; val : 전송(출력, write)하고자 하는 데이터값</span><br />
<span style="color: #008080;"> &#8211; return 값 : 전송된 데이터의 개수(문자수), 보통은 사용하지 않음</span></p>
<p>여러 개의 데이터를 한꺼번에 송신하는 라이브러리로는 Serial.print( )와 Serial.println( )이 있습니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">void Serial.print(val)</span><br />
<span style="color: #008080;"> &#8211; val : 디스플레이되는 값으로 ASCII 처리가 기본, 실제 처리 예는 아래 참조</span><br />
<span style="color: #008080;"> * Serial.print(78) → “78”</span><br />
<span style="color: #008080;"> * Serial.print(1.23456) → “1.23” (소수점의 경우는 소수 둘째자리까지만 처리)</span><br />
<span style="color: #008080;"> * Serial.print(‘N’) → “N”</span><br />
<span style="color: #008080;"> * Serial.print(“Hello world.”) → “Hello world.”</span></p>
<p style="padding-left: 60px;"><span style="color: #008080;">void Serial.print(val, format)</span><br />
<span style="color: #008080;"> &#8211; val : 디스플레이되는 값으로 ASCII 처리가 기본, 실제 처리 예는 아래 참조</span><br />
<span style="color: #008080;"> &#8211; format : 정수의 경우는 진법(BIN : 2진법, DEC : 10진법, HEX : 16진법), 소수점의 경우는 소수점 아래 표시 개수</span><br />
<span style="color: #008080;"> * Serial.print(78, BIN) → “1001110”</span><br />
<span style="color: #008080;"> * Serial.print(78, DEC) →”78”</span><br />
<span style="color: #008080;"> * Serial.print(78, HEX) → “4E”</span><br />
<span style="color: #008080;"> * Serial.print(1.23456, 0) → “1”</span><br />
<span style="color: #008080;"> * Serial.print(1.23456, 4) → “1.2345”</span></p>
<p style="padding-left: 60px;"><span style="color: #008080;">void Serial.println(val)</span><br />
<span style="color: #008080;"> &#8211; Serial.print(val)과 동일하나 단지 마지막에 CR(Carrage Return, ‘\r’, 0x0d)와 NL(New Line, ‘\n’, 0x0a)가 더 추가되어 전송됨. 결과적으로는 한 줄 아래의 처음부터 디스플레이됨(줄바꿈)</span></p>
<p style="padding-left: 60px;"><span style="color: #008080;">void Serial.println(val, format)</span><br />
<span style="color: #008080;"> &#8211; Serial.println(val, format)과 동일하나 단지 마지막에 CR(Carrage Return, ‘\r’, 0x0d)와 NL(New Line, ‘\n’, 0x0a)가 더 추가되어 전송됨. 결과적으로는 한 줄 아래의 처음부터 디스플레이됨(줄바꿈)</span></p>
<p>이 외에도 더 많은 라이브러리가 있지만 이 정도면 일반적인 프로그램에서는 충분할 것 같네요.<br />
블루투스는 휴대폰, 노트북, 이어폰 등의 휴대기기를 서로 연결하여 정보를 교환할 수 있게 하는 무선 기술 표준 중의 하나로 ISM(Industrial Scientific and Medical) 주파수 대역인 2400~2483.5MHz를 사용합니다. ISM이란 산업, 과학, 의료용으로 할당된 주파수 대역인데 전파 사용에 대해 허가를 받을 필요가 없어서 아마추어 무선, 무선랜, 블루투스 등이 이 ISM 대역을 사용하고 있습니다. 블루투스는 기기 간 마스터(Master)와 슬레이브(slave) 구성으로 연결되는데, 두 기기가 동기화(paring)되지 못하면 통신이 이루어지지 않습니다. 하나의 마스터 기기에는 최대 7대의 슬레이브 기기를 연결할 수 있으며, 마스터 기기와 슬레이브 기기 간 통신만 가능할 뿐 슬레이브 기기 간의 통신은 불가능합니다. 물론, 스마트폰은 마스터 기능과 슬레이브 기능을 모두 가지고 있고, 우리가 사용하려는 블루투스 시리얼 모듈인 JMOD-BT-1도 마스터와 슬레이브 기능을 가지고 있습니다.(단, JMOD-BT-1은 사용시 마스터나 슬레이브 중 하나로 고정됩니다.)<br />
Bluetooth 2.0 규격의 경우, 보통 10m 이내 거리 (100m까지 되는 것도 있음)에서 통신이 가능하며, 10Mbps 이하의 데이터 전송 속도를 가집니다. 최근에는 저전력 버전인 BLE 4.0 이상 버전도 출시가 되고 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-09.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30505" alt="34 프로젝트 09" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-09.jpg" width="347" height="262" /></a></p>
<p>블루투스의 유래는 옛 스칸디나비아 지역을 통일한 덴마크와 노르웨이의 국왕 해럴드 블루투스(Harold “Bluetooth” Gormsson, ?~985 혹은 986)의 별명에서 나왔습니다. 그는 블루투스(Bluetooth, 푸른이빨)라는 별명을 가지고 있었는데, 그것은 블루베리를 좋아해 항상 치아가 푸르게 물들어 있었기 때문이라는 설과, 파란색 의치를 해 넣었기 때문이라는 설이 유력합니다. 위와 같이 생기신 분이지요. 입을 꽉 다물고 있어서 이빨이 푸른색인지는 확인이 안되지만요.<br />
어쨌든, 블루투스 SIG(개발자모임)는 자신들이 개발한 기술이 통신장치들을 하나의 무선 기술 규격으로 통일하기를 바라는 마음에서 공식명칭을 블루투스로 정했답니다. 이에 따라 블루투스의 공식 로고도 해러드 왕의 이니셜인 H(옛 스칸디나비아 룬 문자)와 블루투스의 이니셜인 B를 합하여 아래와 같이 만들어졌습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-10.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30506" alt="34 프로젝트 10" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-10.jpg" width="434" height="103" /></a><br />
블루투스 소개가 조금 길어졌네요. 너무 길어지면 또 지루하니까 이 정도에서 정리 끝!</p>
<p>&nbsp;</p>
<p><span style="color: #ffffff; font-size: medium; background-color: #008000;"><strong>■ 블루투스(Bluetooth) 통신을 이용한 스마트폰-아두이노 연결   </strong></span></p>
<p>블루투스 시리얼 모듈은 UART(Universial Asynchronous Receiver/Transmitter) 방식의 시리얼 통신을 블루투스 통신으로 변환시켜주는 모듈입니다. 이 모듈의 실제적인 세부 동작 원리 및 실행 방법은 조금 복잡할 수 있으므로, 우리는 개념적으로만 이해하면 쉬울 것 같습니다.<br />
블루투스 시리얼 모듈은 한마디로 UART 통신 방식의 유선 연결을 블루투스 방식의 무선 연결로 바꾸어주는 모듈입니다. 아래 그림은 블루투스 시리얼 모듈의 개념도로, 그림에서와 같이 유선으로 수신된 RXD 신호는 무선으로 송신하고, 무선으로 수신된 데이터는 TXD 신호로 내보내는 역할을 하는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-11.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30507" alt="34 프로젝트 11" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-11.jpg" width="496" height="133" /></a></p>
<p>실제로 두 개의 시스템이 블루투스 시리얼 모듈을 이용하여 어떻게 시리얼 통신을 수행할 수 있는지에 대한 예를 보이면 아래와 같습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-12.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30508" alt="34 프로젝트 12" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-12.jpg" width="496" height="389" /></a></p>
<p>그림(A)는 아두이노 UNO 2개를 UART 통신을 이용하여 연결할 때의 연결도입니다. 아두이노 UNO는 UART 포트를 가지고 있으므로 서로의 UART 포트를 연결(TX-RX 짝으로)하면 시리얼 통신이 가능합니다. 그런데 만약 아두이노 UNO 1개가 손이 닿지 않거나 선을 연결할 수 없는 곳에 위치한다면 어떻게 하시겠습니까? 이런 경우에는 무선으로 연결할 수 있으면 되겠지요? 이럴 때 유선통신의 내용을 무선으로 바꿔주는 역할을 하는 것이 유선-to-무선 변환기이고 블루투스 시리얼(UART-to-블루투스)모듈은 이러한 변환기의 일종이라고 생각하시면 되겠습니다.<br />
그림(B)는 2개의 아두이노 UNO 각각에 블루투스 시리얼 모듈을 연결한 후 2개의 시스템을 블루투스 통신으로 연결하는 경우로, 이렇게 되면 2개의 아두이노 UNO 사이에는 유선으로 연결하지 않아도 통신이 가능하게 됩니다.<br />
이는, 그림(C)에 나타난 것처럼 블루투스 시리얼 모듈을 단지 유선을 무선으로 매질만 바꾸어 주는 기기라 생각하면(실제로도 그러함) 점선으로 보이는 것과 같이 직접 유선으로 연결한 것과 동일한 효과를 얻을 수 있기 때문이지요.<br />
이와 같이 생각한다면, 스마트폰의 경우 블루투스 기능을 가지고 있고, 이를 이용할 수 있는 터미널용 앱이 있으므로, 그림(D)와 같이 스마트폰과 아두이노 UNO 사이를 연결하는 경우에도 통신이 가능하다고 볼 수 있겠습니다.<br />
결과적으로 우리가 스마트폰의 가상 터미널 앱을 이용하여 특정한 값을 블루투스 통신으로 전송한다면, 이는 블루투스 시리얼 모듈을 통하여 결국 아두이노 UNO의 UART 포트로 전송되므로 아두이노 UNO의 프로그램에서 이 값을 받아서 처리할 수 있게 되는 것입니다. 또한, 반대의 경우를 생각하면 아두이노 UNO 에서 만들어진 어떤 값이 스마트폰으로 전달되어 스마트폰의 화면으로 나타낼 수도 있겠습니다. 예를 들어 실제로 우리가 나중에 스마트폰의 앱을 통하여 아래와 같이 특정 숫자를 아두이노로 보내면 아두이노는 이 숫자에 해당되는 기능을 실행할 수 있다는 것입니다.</p>
<p>‘1’ : 직진 ‘2’ : 좌회전 ‘3’ : 정지 ‘4’ : 우회전 ‘5’ : 후진</p>
<p>레알(REAL)? 레알(REAL)!</p>
<p><span style="color: #b70000; font-size: medium;"><strong>아두이노 UNO에 블루투스 시리얼 모듈을 연결하기</strong></span></p>
<p>기본적인 이론은 알았으므로 이제 아두이노 UNO에 블루투스 시리얼 모듈인 JMOD-BT-1을 연결하여 블루투스 연결을 완성해 보겠습니다.</p>
<table style="width: 620px;" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-04.jpg" rel="lightbox[30243]"><img class="alignnone size-medium wp-image-30500" alt="34 프로젝트 04" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-04-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-14.jpg" rel="lightbox[30243]"><img class="alignnone size-medium wp-image-30510" alt="34 프로젝트 14" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-14-300x168.jpg" width="300" height="168" /></a></td>
</tr>
</tbody>
</table>
<p>아두이노 UNO와는 UART 통신을 하게 되므로 JMOD-BT-1에서 아두이노 UNO와 연결해야 하는 핀은 TXD(송신 데이터), RXD(수신 데이터) 신호선과, 전원 핀인 VCC(3.3V~5V, 전원)와 GND(그라운드)로 총 4핀입니다. (나머지 핀들은 JMOD-BT-1의 세팅 시 필요한 핀이므로 실제 통신에서는 사용하지 않습니다.)<br />
그런데 여기서 한 가지 문제가 있습니다. 그것은 아두이노 UNO는 1개의 UART 인터페이스만을 가지고 있고, 이 UART 포트는 아두이노의 업로드 및 시리얼 모니터 연결용으로 이미 USB 쪽으로 연결이 되어 있다는 것입니다. 즉, 이 UART 포트를 함께 사용하는 경우, 우리는 시리얼 모니터와 블루투스 시리얼을 동시에 사용할 수 없을 뿐만 아니라, 아두이노 업로드 시에도 블루투스 시리얼 쪽의 경로와 충돌이 날 가능성 등을 고려해야 하는 아주 불편한 상황을 감수해야 합니다.<br />
그러면, 방법이 없을까요? 아니오~ 좋은 방법이 하나 있습니다.<br />
그것은 가상 UART인 소프트웨어시리얼(SoftwareSerial)을 이용하는 것입니다.<br />
소프트웨어시리얼은 아두이노의 일반적인 입출력(GPIO : General Purpose Input Output) 핀(D0~D13, A0~A5)을 이용하여 UART의 기능을 하도록 소프트웨어로 라이브러리화한 것으로, UART의 기능을 거의 그대로 재현할 수 있는 아두이노 라이브러리입니다.<br />
시리얼모니터에서 사용하는 클래스인 Serial과 비슷한 형태의 클래스로 SoftwareSerial을 제공하고 있으며, 멤버 함수도 begin, read, write 등을 Serial과 동일하게 사용할 수 있습니다.<br />
형태는 아래와 같습니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">SoftwareSerial(unit8_t rx, unit8_t tx, bool inverse_logic = false)</span><br />
<span style="color: #008080;">rx : 수신 핀 번호</span><br />
<span style="color: #008080;">tx : 송신 핀 번호</span><br />
<span style="color: #008080;">inverse_logic : 송수신 비트 반전 (TRUE : 반전, FALSE : 반전하지 않음, default는 FALSE)</span></p>
<p>프로그램에서 사용하실 때는 첫 부분에 아래와 같은 선언이 필요하고,</p>
<p style="padding-left: 60px;"><span style="color: #008080;">#include &lt;SoftwareSerial.h&gt;</span></p>
<p style="padding-left: 60px;"><span style="color: #008080;">SoftwareSerial ABC = SoftwareSerial(RX, TX);</span><br />
<span style="color: #008080;">ABC : 이 스케치에서 SoftwareSerial로 사용할 이름</span><br />
<span style="color: #008080;">RX : RX핀으로 사용할 핀 번호</span><br />
<span style="color: #008080;">TX ; TX 핀으로 사용할 핀 번호</span></p>
<p>실제 사용시에는 Serial 클래스와 같이, 아래와 같은 형태로 사용하면 됩니다.</p>
<p style="padding-left: 60px;"><span style="color: #008080;">ABC.begin(115200);</span></p>
<p>오, 요런 방법이 있었네요. 그러면 이것을 이용하여 아두이노 UNO와 JMOD-BT-1을 직접 연결해 보도록 하겠습니다. SoftwareSerial에 사용된 핀은 RX는 4번(D4), TX는 5번(D5)를 사용하는 것으로 하지요. 한가지 조심하여야 하는 것은 송신 핀과 수신 핀의 연결인데요. 앞에서도 언급하였지만, 두 기기의 연결에서 한 쪽의 송신핀(TXD)은 다른쪽의 수신핀(RX)에, 한 쪽의 수신핀(RXD)은 다른 쪽의 송신핀(TX)에 연결하여야 한다는 점은 꼭 확인하고 연결하셔야 합니다.<br />
아래와 같이 연결하면 될 것 같네요. JMOD-BT-1의 뒷면에 신호 이름이 적혀있으니 잘 보고 연결하시기 바랍니다.</p>
<table style="width: 620px;" border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td style="text-align: center;">아두이노 UNO 핀</td>
<td style="text-align: center;">JMOD-BT-1핀</td>
</tr>
<tr>
<td style="text-align: center;">+5V</td>
<td style="text-align: center;">VCC</td>
</tr>
<tr>
<td style="text-align: center;">GND</td>
<td style="text-align: center;">GND</td>
</tr>
<tr>
<td style="text-align: center;">D4(RX, SoftwareSerial)</td>
<td style="text-align: center;">TXD</td>
</tr>
<tr>
<td style="text-align: center;">D5(TX, SoftwareSerial</td>
<td style="text-align: center;">RXD</td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-15.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30511" alt="34 프로젝트 15" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-15.jpg" width="620" height="446" /></a></p>
<p><span style="color: #b70000; font-size: medium;"><strong>스마트폰의 블루투스 앱으로 아두이노와 통신하기</strong></span></p>
<p>자, 연결은 되었으니 이번에는 실제로 스마트폰과 아두이노 UNO가 블루투스를 이용하여 통신이 가능한지 알아보기 위한 테스트를 실행해 보겠습니다.<br />
일단 스마트폰에 블루투스 앱이 필요할텐데…, 이것은 이미 존재하는 앱을 가져다가 사용하는 것이 좋겠습니다. 블루투스 통신을 위한 앱은 여러가지가 있지만, 나중에 스마트카를 조종하는 것을 고려하여 버튼을 이용하여 데이터를 보낼 수 있도록 설계된 ‘블루투스 컨트롤러(Bluetooth Controller)’라는 앱을 사용하는 것으로 하겠습니다. 이 앱은 안드로이드 스마트폰의 ‘PLAY 스토어’에서 ‘블루투스 컨트롤러’(“Bluetooth Controller”)이라는 이름으로 검색하면 찾을 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-21.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30530" alt="35 PTB CAP (2)" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-21.jpg" width="496" height="247" /></a></p>
<p>스마트폰의 ‘블루투스’ 항목을 ‘ON’ 상태로 설정한 후에 위와 같이 ‘Bluethooth Controller’ 앱을 실행하면 아래와 같은 화면이 나타나는데, 여기에서 위쪽 오른쪽에 있는 [키 설정] 메뉴를 누르면 다음의 화면이 나타납니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-11.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30531" alt="35 PTB CAP (1)" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-11.jpg" width="496" height="310" /></a></p>
[키 이름]에 자신이 원하는 이름을 넣고, [데이터 설정]에는 통신 시 이 키를 눌렀을 때 아두이노 쪽으로 전달될 데이터값(예를 들어 ‘1’)을 넣으면 됩니다. 우리는 나중에 스마트카를 제어해야 하므로 제공되는 9개의 칸에 아래와 같이 직관적으로 배치 하겠습니다.</p>
<table style="width: 500px;" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td style="text-align: center;"></td>
<td style="text-align: center;">전진(&#8220;1&#8243;)</td>
<td style="text-align: center;"></td>
</tr>
<tr>
<td style="text-align: center;">좌회전(&#8220;2&#8243;)</td>
<td style="text-align: center;">정지(&#8220;3&#8243;)</td>
<td style="text-align: center;">우회전(&#8220;4&#8243;)</td>
</tr>
<tr>
<td style="text-align: center;"></td>
<td style="text-align: center;">후진(&#8220;5&#8243;)</td>
<td style="text-align: center;"></td>
</tr>
</tbody>
</table>
[OK]를 누루면 아래의 화면이 나타납니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-3.jpg" rel="lightbox[30243]"><img alt="35 PTB CAP (3" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-3.jpg" width="581" height="337" /></a></p>
<p>자, 연결이 잘 되었는지 테스트를 해볼까요? 아두이노 UNO에는 블루투스를 통하여 들어온 데이터를 되돌려 보내는(echoback하는) 프로그램을 업로드하여 스마트폰에서 보낸 데이터(예를 들어 ‘1’, ‘2’ 등)가 다시 스마트폰으로 되돌아 오면 성공이 되겠습니다.</p>
<p><strong>[테스트 규격]</strong><br />
· 스마트폰 블루투스 콘트롤러 앱에서 보낸 데이터가 아두이노 UNO까지 전달되었다가 되돌아 오는 블루투스 통신 시스템<br />
· 통신 경로 : 스마트폰 블루투스 콘트롤러 앱 → (블루투스 통신) → JMOD-BT-1 TXD → 아두이노 RX → echoback(아두이노 프로그램) → 아두이노 TX → JMOD-BT-1 RXD → (블루투스 통신) → 스마트폰 블루투스 콘트롤러 앱</p>
<p><strong>[알고리즘]</strong><br />
· SoftwareSerial로 정해진 핀을 설정하고, baudrate는 115200(JMOD-BT-1의 기본 설정)으로 설정한 후, RX 핀으로 수신된 데이터는 항상 TX 핀으로 송신(echoback)</p>
<p>설명하느라 많은 시간을 할애했지만, 실제 프로그램은 너무 쉬워서 알고리즘이라고 할 것도 없습니다. 바로 스케치 프로그램으로 넘어갑니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#include &lt;SoftwareSerial.h&gt;</p>
<p>#define SS_RX 4 // SoftSerial RX 핀번호 = 4<br />
#define SS_TX 5 // SoftSerial TX 핀번호 = 5</p>
<p>SoftwareSerial btSerial = SoftwareSerial(SS_RX, SS_TX); // 블루투스시리얼은 SoftSerial 사용<br />
// 4번, 5번 핀 할당</p>
<p>void setup()<br />
{<br />
btSerial.begin(115200); // 블루투스 시리얼 모듈(JMOD-BT-1) 통신 속도<br />
= 115200<br />
}</p>
<p>void loop()<br />
{<br />
if (btSerial.available()) // 블루투스 시리얼 모듈을 통하여 데이터가 수신되면<br />
{<br />
data = btSerial.read(); // 그 데이터를 읽어서<br />
btSerial.write(data); // 블루투스 시리얼 모듈을 통하여 다시 송신(loopback)<br />
}<br />
}</p>
</div>
<p>얼른 업로드하고, 앱을 이용하여 연결이 잘 되었는지 확인해 보겠습니다.</p>
<p>1. 스마트폰에서 블루투스 컨트롤러 앱을 실행하고</p>
<p>2. 아두이노 UNO에 연결된 JMOD-BT-1과 패어링(pairing : 블루투스 마스터와 블루투스 슬레이브가 통신할 수 있는 상태로 진입하는 것)을 한 후<br />
<span style="color: #ff0000;">(주의 : 처음 연결할 때는 PIN 번호를 물어보게 되는데 이 때는 ‘1234’를 입력합니다.)</span></p>
<p>3. 버튼을 눌러 대응되는 숫자가 되돌아 오는지 확인(즉, ‘전진’ 버튼을 누르면 ‘1’, 좌회전을 버튼을 누르면 ‘2’, 정지 버튼을 누르면 ‘3,’ 우회전 버튼을 누르면 ‘4’, 후진 버튼을 누르면 ‘5’, 값이 스마트폰 앱 화면 창에 나타나면 성공!)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-31.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30524" alt="34 프로젝트 31" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-31.jpg" width="620" height="318" /></a></p>
<p>&nbsp;</p>
<h1><span style="font-size: small;"><a href="https://www.youtube.com/watch?v=VpklRysoiu0" target="_blank">블루투스 통신을 이용한 스마트폰과 아두이노 연결 영상보러가기</a></span></h1>
<p><span style="color: #ffffff; font-size: medium; background-color: #008000;"><strong>■ 내 스마트카 조립     </strong></span></p>
<p>자, 이제 필요한 기본 지식은 모두 갖추었으니 드디어 내 차를 만들고 운전해 볼 시간입니다. 실제로 이미 자동차를 가지고 계신 분도 있고, 아직은 없는 분도 있겠지만, 오늘 DIY할 스마트카는 아두이노 장난감차니까, 부담없이 내 맘대로 만들어서 내 멋대로 이리저리 마구 운전해 봅시다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-21.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30515" alt="34 프로젝트 21" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-21.jpg" width="620" height="453" /></a></p>
<p><strong>[아두이노 연결]</strong><br />
아~ 이 그림 하나 그리느라고 거의 4시간이나 잡아먹었습니다.<br />
중간에 배터리 연결 형태가 바뀌기도 하고, fritzing과 캡처, 포토샵, 파워포인트 \…로 이렇게 꾸미는 것이 꽤 많은 시간을 필요로 하네요. 어쨌든 좌충우돌하여 완성입니다. 야호~</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-4.png" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30537" alt="35 PTB CAP (4" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-4.png" width="513" height="286" /></a></p>
<p>연결된 부분을 잠시 설명해 보면, 아래 표와 같습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-5.png" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30538" alt="35 PTB CAP (5" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-5.png" width="508" height="429" /></a><br />
전원 연결은 아래와 같습니다.<br />
모터드라이버 연결 시에는 약간 주의할 것이 있는데, PWM 신호는 아날로그 출력이므로 신호에 물결 표시(~, tild)가 있는 D3, D5, D6, D9, D10, D11번 핀에 연결해야 한다는 것입니다. 이러한 이유로 PWMA는 D6에, PWMB는 D9에 할당하였습니다. PWM 출력이 가능한 모터가 2개인 것을 제외하고는 지난 시간에 다 해본 것이므로 모터드라이버와 블루투스 시리얼과의 연결은 특별한 설명이 더 필요하지는 않을 것 같습니다. <span style="color: #808080;"><em>(기억이 나지 않으면 지난번 강의를 참조!!!)</em></span><br />
마지막으로 좀 더 설명하고 넘어가야 하는 것은 전원에 관련된 것입니다. 도입 부분에서도 약간 언급하였는데, 이번 DIY는 자동차이므로 PC로부터 USB 케이블을 통하여 공급되는 전원은 사용할 수가 없습니다. 그러므로 휴대용 전원으로 사용되는 건전지나 수은전지, 리튬전지 등을 이용하여 전원을 공급해야 하지요. 여러가지 경우를 여기서 모두 설명하기에는 내용이 좀 길어지므로 이번에는 우리가 사용할 방법만 간단하게만 설명하겠습니다.</p>
<p>일단 모터를 구동하는 전원과 아두이노 및 다른 모듈에서 사용할 전원은 분리하도록 합니다. 모터는 일반적으로 전류를 많이 사용하고, 모터마다 사용 전압도 다르며, 기동시 순간적인 과전류로 인한 전원 소스의 흔들림(전압강하)도 생길 수 있는 부품이어서 아두이노나 블루투스 시리얼 모듈로 공급되는 전원과는 다른 전원 소스를 사용하는 것을 권장합니다.</p>
<p>만약, 모터가 5V로 구동이 가능하여 동일한 5V 전원 소스로 사용하려 할 때에는 전원 소스의 전류 공급용량이 충분한지, 전원 드랍(drop)은 영향이 없는지 등의 여부를 잘 살펴서 사용하셔야 불안정한 동작을 방지할 수 있습니다. 우리는 1.5V 건전지 4개를 직렬 연결한 배터리 홀더에 넣어서, 6V를 모터의 전원으로 사용하겠습니다. 그리고 아두이노와 블루투스 시리얼 모듈, 그리고 모터드라이버 모듈의 제어 부분 전원으로는 5V를 공급해야 하므로 이것은 리튬전지(4.2V)를 스텝업 레귤레이터를 이용하여 5V로 만들어 주는 전원조종기인 제이씨넷의 JBATT-U5-LC를 사용하겠습니다. (참고로, JBATT-U5-LC는 리튬전지를 사용하고 USB 케이블로 충전이 가능하며, 전원 ON/OFF 스위치가 내장된 소형 전원공급기입니다.) 물론, 시중에 나와 있는 임의의 전압공급기 모듈을 사용해도 되고, 직접 전압공급기 회로를 제작하여 사용해도 되지요. 또는, 7V 이상의 전원 소스가 있다면 아두이노 VIN 핀으로 직접 이 전원을 넣어주고, +5V 핀으로부터 블루투스 시리얼 모듈과 모터드라이버 모듈의 제어 부분 전원을 연결하여 사용하는 것도 한가지 방법이 되겠습니다.</p>
<p>모터드라이버 모듈의 경우는 내부에서 사용하는 전원과 모터로 공급되는 전원, 2개를 모두 연결해주어야 하는 것에 주의하셔야 하고, 2개의 전원소스의 GND는 어떤 형태로든 연결되어 있어야 함에 주의하시기 바랍니다. 조금 복잡할 수 있으므로 모터 드라이버의 핀 연결을 확대하여 다시 한 번 연결 형태를 정리해 보면 아래와 같이 되겠습니다. 6V 전원(건전지홀더)의 GND는 외부에서 5V 전원의 GND와 연결한다는 의미로 점선 &#8211; - &#8211; 으로 표시하였습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-22.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30516" alt="34 프로젝트 22" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-22.jpg" width="620" height="471" /></a></p>
<p><strong>[조립하기]</strong><br />
이제 조립을 하기 위한 모든 준비는 끝난 것 같네요. 프로그램을 하기 전에 일단 조립부터 해보고(빨리 만들고 싶으니까요.) 이후에 프로그램을 준비해 보는 것으로 하시지요. 선이 제법 많고 부속 모듈도 많으므로 공간을 잘 이용해서 배치하고 연결하여야 할 것 같습니다. 저는 편하게 양면테이프를 이용하여 아래와 같이 모듈 뒤쪽에 붙이고 이것을 적당하게 배치하여 처리하였습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-23.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30517" alt="34 프로젝트 23" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-23.jpg" width="620" height="464" /></a></p>
<p>초기 앞면, 뒷면을 조립하면 아래와 같은 모양이 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-24.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30518" alt="34 프로젝트 24" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-24.jpg" width="298" height="385" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-25.jpg" rel="lightbox[30243]"><img class="alignnone  wp-image-30519" alt="34 프로젝트 25" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-25.jpg" width="298" height="319" /></a></p>
<p>그리고 각 모듈과 전원까지 모두 연결하면~</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-26.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30520" alt="34 프로젝트 26" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-26.jpg" width="620" height="428" /></a><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-27.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30521" alt="34 프로젝트 27" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-27.jpg" width="620" height="499" /></a><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-28.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30522" alt="34 프로젝트 28" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-28.jpg" width="620" height="414" /></a></p>
<p>짠~~~! 이렇게 만들어졌습니다.<br />
선들이 조금 난잡하여 폼이 덜 나긴 하지만, 전원까지 넣어주면 불이 반짝반짝 하는게 꽤 그럴 듯 하게 보입니다. 작은 끈 같은 것으로 선을 묶어주면 좀 깔끔해 질 것도 같지만, 근처에는 현재 눈에 띄지가 않으므로 생략! 그냥 산발한 채로 넘어갑니다.<br />
어쨌거나 조립은 잘 완성되어 기분은 좋아졌습니다.<br />
노동하느라 애썼으니까 커피 한 잔하면서 휴식을 조금 취한 후 다시 와서 마지막 프로그램을 완성하도록 하겠습니다.<br />
10분간 휴식~~~</p>
<p><span style="font-size: medium; color: #ffffff; background-color: #008000;"><strong>■ 내 스마트카 프로그램     </strong></span></p>
<p>이제 차체는 모두 완성하였으니 스케치 프로그램만 작성하여 업로드해 봅시다.<br />
블루투스 연결 쪽은 소프트시리얼로 처리해야 한다는 것을 염두에 두고, 전체적인 알고리즘을 생각해 보겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-6.png" rel="lightbox[30243]"><img alt="35 PTB CAP (6" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-6.png" width="545" height="299" /></a></p>
<p>스마트폰에서 들어온 입력을 검사하여 각 숫자에 대응되는 동작인 전진, 후진, 좌회전, 우회전, 정지의 5가지 기능 중 하나를 실행하면 되겠습니다. 또한, 각 기능은 모터 2개의 동작으로 구현할 수 있는데 이는 아래의 표를 확인하기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-7.png" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30539" alt="35 PTB CAP (7" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/35-PTB-CAP-7.png" width="597" height="187" /></a></p>
<p>예를 들어 좌회전 기능을 구현한다면, 왼쪽 바퀴(모터)는 천천히 전진하고 오른쪽 바퀴(모터)는 앞으로 전진하면 차제가 왼쪽으로 기울면서 좌회전하는 형태가 되겠습니다. 실제로 좀 더 부드럽게 동작하려면 왼쪽 바퀴(모터)는 조금 천천히 구동되고, 오른쪽 바퀴(모터)는 빨리 구동되는 형태로 구현하면 되겠지요. (이 동작은 PWMA, PWMB의 값을 아날로그적으로 0~255까지 조절이 가능하므로 적당한 값을 주어 구현이 가능합니다.)<br />
<span style="color: #ff0000;">편의상 스마트카의 오른쪽 바퀴(모터)는 모터A를, 왼쪽 바퀴(모터)는 모터B를 할당합니다.</span><br />
이번에도 설명이 좀 길었는데 실제 구현은 크게 어렵지 않게 될 것 같네요. 여러분의 힘으로 한 번 생각해 보시고 스스로 먼저 구현해 보시지요. 약 20분 기다립니다.</p>
<p>(20), (19), (18), …… (3), (2), (1), (0) !</p>
<p>아래를 보시지요.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#include&lt;SoftwareSerial.h&gt;</p>
<p>#defineSS_RX 4 // SoftSeiral RX 핀 &lt;-&gt; JMOD-BT-1의 TXD 연결<br />
#defineSS_TX 5 // SoftSerial TX 핀 &lt;-&gt; JMOD-BT-1의 RXD 연결</p>
<p>#define FORWARD ‘1’ // 전진 명령어<br />
#define FORWARD_L ‘2’ // 좌회전 명령어<br />
#define FORWARD_R ‘4’ // 우회전 명령어<br />
#define BACKWARD ‘5’ // 후진 명령어<br />
#define STOP ‘3’ // 정지 명령어</p>
<p>#defineSPEED_100 255 // PWM값 255(0~255), 100% 값<br />
#defineSPEED_75 192 // PWM값 192(0~255), 75% 값<br />
#defineSPEED_50 128 // PWM값 128(0~255), 50% 값<br />
#defineSPEED_25 64 // PWM값 64 (0~255),25% 값<br />
#defineSPEED_0 0 // PWM값0(LOW) (0~255), 0% 값</p>
<p>SoftwareSerialbtSerial = SoftwareSerial(SS_RX, SS_TX);</p>
<p>constint pwma = 6; // 모터 APWM 입력핀<br />
constint ain1 = 7; // 모터 AIN1 입력핀<br />
constint ain2 = 8; // 모터 AIN2 입력핀<br />
constint pwmb = 9; // 모터 BPWM 입력핀<br />
constint bin1 = 10; // 모터 BIN1 입력핀<br />
constint bin2 = 11; // 모터 BIN2 입력핀</p>
<p>voidforw() // 전진 처리,모터 A = 전진, 모터 B = 전진<br />
{<br />
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_75);<br />
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_75);<br />
}</p>
<p>voidforwL() // 좌회전 처리, 모터 A= 전진, 모터B = 약하게 전진<br />
{<br />
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_75);<br />
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_50);<br />
}</p>
<p>voidforwR() // 우회전 처리, 모터 A = 약하게 전진, 모터B = 전진<br />
{<br />
digitalWrite(ain1, HIGH); digitalWrite(ain2,LOW); analogWrite(pwma, SPEED_50);<br />
digitalWrite(bin1, HIGH); digitalWrite(bin2,LOW); analogWrite(pwmb, SPEED_75);<br />
}</p>
<p>voidback() // 후진 처리,모터 A = 후진, 모터 B = 후진<br />
{<br />
digitalWrite(ain1, LOW); digitalWrite(ain2,HIGH); analogWrite(pwma, SPEED_75);<br />
digitalWrite(bin1, LOW); digitalWrite(bin2,HIGH); analogWrite(pwmb, SPEED_75);<br />
}</p>
<p>voidstop() // 정지 처리,모터 A = 정지, 모터 B = 정지<br />
{<br />
analogWrite(pwma, SPEED_0);<br />
analogWrite(pwmb, SPEED_0);<br />
}</p>
<p>voidsetup()<br />
{<br />
pinMode(pwma, OUTPUT); // 모터 제어핀은 아두이노 입장에서 모두 출력<br />
pinMode(ain1, OUTPUT);<br />
pinMode(ain2, OUTPUT);<br />
pinMode(pwmb, OUTPUT);<br />
pinMode(bin1, OUTPUT);<br />
pinMode(bin2, OUTPUT);<br />
btSerial.begin(115200); // JMOD-BT-1 통신baudrate = 115200(초기값)<br />
}</p>
<p>voidloop()<br />
{<br />
char rxData;<br />
if (btSerial.available() &gt; 0) // 스마트폰으로부터의 입력 데이터가 있는지확인<br />
{<br />
rxData = btSerial.read(); //데이터(명령어)가무엇인지 확인<br />
if (rxData == FORWARD) forw(); // 전진 명령 처리<br />
elseif (rxData == FORWARD_L) forwL(); // 좌회전 명령 처리<br />
elseif (rxData == FORWARD_R) forwR(); // 우회전 명령 처리<br />
elseif (rxData == BACKWARD) back(); // 후진 명령 처리<br />
elseif (rxData == STOP) stop(); // 정지 명령 처리<br />
else;<br />
}<br />
delay(100);<br />
}<br />
</div>
<p>모터 제어에서 “analogWrite(pwma,SPEED_75)”와 같이 PWM 핀에 192(=SPEED_75)와 같은 값을 주는 것은 전체값인 255(SPEED_100)을 주었을 때 모터가 너무 빨리 회전하여 스마트카가 너무 빨리 움직일 것 같아 적당한 값을 준 것이며, 한편으로는 모터에 의하여 소모되는 전력을 조금 적게 하여 건전지의 수명을 조금 연장하려는 의미도 있습니다.<br />
이제 준비가 되었으니 업로드하고, 앱을 이용하여 프로그램이 잘 되었는지 확인해 보겠습니다. 이전 예에서 사용한 형태와 똑같이 앱을 구성하여 실행하는 것으로 합니다.</p>
<p>1. 스마트폰에서 블루투스 컨트롤러 앱을 실행하고</p>
<p>2. 아두이노 UNO에 연결된 JMOD-BT-1과 패어링(pairing : 블루투스 마스터와 블루투스 슬레이브가 통신할 수 있는 상태로 진입)한 후<br />
<span style="color: #ff0000;">(주의 : 처음 연결할 때는 PIN 번호를 물어보게 되는데 이 때는 ‘1234’를 입력합니다.)</span></p>
<p>3. 버튼을 눌러 정해진 명령대로 스마트카가 움직이는지 확인 (전진 버튼을 누르면 ‘1’, 좌회전을 버튼을 누르면 ‘2’, 정지 버튼을 누르면 ‘3,’ 우회전 버튼을 누르면 ‘4’, 후진 버튼을 누르면 ‘5’ 값이 스마트폰 → JMOD-BT-1 → 아두이노로 전달되고 아두이노는 이 명령어에 해당되는 기능을 수행</p>
<p>진짜 그렇게 되는지 동영상을 보시겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-30.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30523" alt="34 프로젝트 30" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-30.jpg" width="620" height="345" /></a><a href="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-32.jpg" rel="lightbox[30243]"><img class="alignnone size-full wp-image-30525" alt="34 프로젝트 32" src="http://www.ntrexgo.com/wp-content/uploads/2016/01/34-프로젝트-32.jpg" width="620" height="345" /></a></p>
<p><a href="http://serviceapi.nmv.naver.com/flash/convertIframeTag.nhn?vid=692FC5251832776F46E37E48F7778B839E76&amp;outKey=V1224038aa41defe898a3141b435665847e8823f7bae11b25cbdf141b435665847e88&amp;width=720&amp;height=438" target="_blank">동영상 보러가기</a><br />
와우, 보리(Bory) 스마트카가 제대로 움직입니다!!<br />
내가 조종하는대로 막 가네요.!<br />
여러분의 스마트카도 여러분의 의도대로 잘 움직이나요?<br />
그렇다구요?<br />
예, 모두들 잘 되었습니다. 축하드립니다.<br />
만약 혹시라도 잘 안되신 분들은 선 연결이나 조립, 프로그램에 문제가 없는지 차근차근 다시 점검하고 수정한다면 모두들 잘 되시리라 생각합니다.</p>
<p>오늘은 [스마트폰으로 조종하는 스마트카]를 DIY하여 보았는데요.<br />
오늘의 강좌를 마지막으로 이번 [너무 쉬운 아두이노 DIY] 강좌 전체를 마칩니다. 그동안 이 강좌를 사랑해주시고 성원해주신 여러분께 진심으로 감사의 말씀을 드리며, 다음에 좋은 인연으로 다시 만날 수 있기를 희망하겠습니다.<br />
여러분, 2016년 새해 복 많이 받으십시오. 감사합니다.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/30243/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[23호]적외선 조명 제어기를 만들어보자!</title>
		<link>http://www.ntrexgo.com/archives/25403</link>
		<comments>http://www.ntrexgo.com/archives/25403#comments</comments>
		<pubDate>Tue, 01 Apr 2014 05:10:02 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[blog-posts]]></category>
		<category><![CDATA[DIY 실험실]]></category>
		<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[프로젝트]]></category>
		<category><![CDATA[23호]]></category>
		<category><![CDATA[Project To Build]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=25403</guid>
		<description><![CDATA[디바이스마트 매거진 23호 &#124; 필자는 예전부터 항상 리모컨으로 TV를 끄고 켜는데 왜 전등은 리모컨으로 끌 수 없을까? 라는 생각을 갖고 있었다.
어떤 아파트는 리모컨으로 끄고 켤 수 있던데 그런 리모컨 기능이 있는 전등은 왜 항상 부모님 방에만 설치된 것일까?
내 방에도 리모컨 전등을 달아보자 라는 생각에 제작하게 되었다.]]></description>
				<content:encoded><![CDATA[<p><span style="background-color: #3366ff;color: #ffffff"><strong>이불 속에서 불을 끄고 켜자!</strong></span></p>
<p><span style="font-size: x-large;color: #000080"><strong>적외선 조명 제어기를 만들어보자!</strong></span></p>
<p>필자는 예전부터 항상 리모컨으로 TV를 끄고 켜는데 왜 전등은 리모컨으로 끌 수 없을까? 라는 생각을 갖고 있었다.<br />
어떤 아파트는 리모컨으로 끄고 켤 수 있던데 그런 리모컨 기능이 있는 전등은 왜 항상 부모님 방에만 설치된 것일까?<br />
내 방에도 리모컨 전등을 달아보자 라는 생각에 제작하게 되었다.</p>
<p><span style="background-color: #800000"><strong><span style="color: #ffffff">이 프로젝트는 220V를 절연되지 않은 상태에서 직접 사용하므로 감전에 주의하고, </span></strong></span><br />
<span style="background-color: #800000"><strong><span style="color: #ffffff">프로그램을 구울 때 PC와 절대로 접속하지 않도록 하며, </span></strong></span><br />
<span style="background-color: #800000"> <strong><span style="color: #ffffff">신체 일부가 회로물에 닿지 않도록 주의하도록 한다. 인적 물적 사고에 대한 책임은 디바이스마트와 필자에게 없다.</span></strong></span></p>
<p><span style="color: #ffffff;background-color: #3366ff"><strong>원격조명제어 부품리스트와 사진</strong></span></p>
<p><img class="alignnone size-full wp-image-25419" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/001_부품목록사진.jpg" width="660" height="438" /></p>
<table style="border-color: #cdcdca;border-width: 1px;width: 620px" border="1" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="text-align: center">참조</td>
<td style="text-align: center">종류순</td>
<td style="text-align: center">품명(검색어)</td>
<td style="text-align: center">설명</td>
<td style="text-align: center">필요수량</td>
</tr>
<tr>
<td style="text-align: center">1</td>
<td style="text-align: center">U1</td>
<td style="text-align: center">ATTINY13A-PU</td>
<td style="text-align: center">주 제어부</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">U2</td>
<td style="text-align: center">MOC3043</td>
<td style="text-align: center">절연 신호 전달</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">3</td>
<td style="text-align: center">U3</td>
<td style="text-align: center">603LM</td>
<td style="text-align: center">리모컨 수신부</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">4</td>
<td style="text-align: center">Q</td>
<td style="text-align: center">BTA08-600BRG</td>
<td style="text-align: center">AC 스위치</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">5</td>
<td style="text-align: center">C</td>
<td style="text-align: center">MF 1uF/250VAC,20</td>
<td style="text-align: center">입력 전류 제한</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">6</td>
<td style="text-align: center">C</td>
<td style="text-align: center">E/C 16V 470uF (85℃)-10EA</td>
<td style="text-align: center">리플방지</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">7</td>
<td style="text-align: center">C</td>
<td style="text-align: center">HV(B) Ceramic 0.01uF, 1kV</td>
<td style="text-align: center">스버너</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">8</td>
<td style="text-align: center">R</td>
<td style="text-align: center">WCR 100Ω 5W</td>
<td style="text-align: center">입력 전류 제한</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">9</td>
<td style="text-align: center">R</td>
<td style="text-align: center">1/4W 5% Axial Resistor 106J (10MΩ)</td>
<td style="text-align: center">방전 저항</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">R</td>
<td style="text-align: center">1/4W 5% Axial Resistor 391J (390Ω)</td>
<td style="text-align: center">트라이악 게이트</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">11</td>
<td style="text-align: center">R</td>
<td style="text-align: center">1/4W 5% Axial Resistor 391J (390Ω)</td>
<td style="text-align: center">트라이악 게이트</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">12</td>
<td style="text-align: center">R</td>
<td style="text-align: center">1/4W 5% Axial Resistor 391J (390Ω)</td>
<td style="text-align: center">LED전류제한</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">13</td>
<td style="text-align: center">R</td>
<td style="text-align: center">1/4W 5% Axial Resistor 390J (39Ω)</td>
<td style="text-align: center">스너버</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">14</td>
<td style="text-align: center">D</td>
<td style="text-align: center">DB105</td>
<td style="text-align: center">정류</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">D</td>
<td style="text-align: center">1N4733A (10개)-5.1V</td>
<td style="text-align: center">전압제한</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">16</td>
<td style="text-align: center">D</td>
<td style="text-align: center">원통평면형-5파이 투명 LED(녹색)</td>
<td style="text-align: center">상태표시 LED</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">17</td>
<td style="text-align: center">D</td>
<td style="text-align: center">원통평면형-5파이 투명 LED(노랑)</td>
<td style="text-align: center">상태표시 LED</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">J</td>
<td style="text-align: center">BR-762C (2핀)</td>
<td style="text-align: center">입출력 터미널</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">19</td>
<td style="text-align: center">SW</td>
<td style="text-align: center">KLT-1105B</td>
<td style="text-align: center">리모컨 학습 스위치</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">20</td>
<td style="text-align: center"></td>
<td style="text-align: center">RIC-DIP-8핀</td>
<td style="text-align: center">IC 소켓 8핀</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">21</td>
<td style="text-align: center"></td>
<td style="text-align: center">BA4-50&#215;120-단면</td>
<td style="text-align: center">기판</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">22</td>
<td style="text-align: center"></td>
<td style="text-align: center">PCB서포트 플라스틱-L자형(10개)</td>
<td style="text-align: center">기판 서포터 타입1</td>
<td style="text-align: center">4</td>
</tr>
<tr>
<td style="text-align: center">23</td>
<td style="text-align: center"></td>
<td style="text-align: center">트위스트락서포트-12NB(10개)</td>
<td style="text-align: center">전선 고정용 서포터</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">24</td>
<td style="text-align: center"></td>
<td style="text-align: center">DH15A(방열판)</td>
<td style="text-align: center">트라이악 방열용</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">25</td>
<td style="text-align: center"></td>
<td style="text-align: center">부싱(3파이)</td>
<td style="text-align: center">트라이악 절연용</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">26</td>
<td style="text-align: center"></td>
<td style="text-align: center">퓨즈홀더 F-520</td>
<td style="text-align: center">제품보호</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">27</td>
<td style="text-align: center"></td>
<td style="text-align: center">퓨즈 5&#215;20-0.5A</td>
<td style="text-align: center">제품보호</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">28</td>
<td style="text-align: center"></td>
<td style="text-align: center">5267-03 (색상옵션)</td>
<td style="text-align: center">리모컨 연장선</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">29</td>
<td style="text-align: center"></td>
<td style="text-align: center">5264-03 (색상옵션)</td>
<td style="text-align: center">리모컨 연장선</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">30</td>
<td style="text-align: center"></td>
<td style="text-align: center">5264용 클림프전선</td>
<td style="text-align: center">리모컨 연장선</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">31</td>
<td style="text-align: center"></td>
<td style="text-align: center">5264용 클림프전선</td>
<td style="text-align: center">리모컨 연장선</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">32</td>
<td style="text-align: center"></td>
<td style="text-align: center">5264용 클림프전선</td>
<td style="text-align: center">리모컨 연장선</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">33</td>
<td style="text-align: center"></td>
<td style="text-align: center">절연전선HIV(IEC90℃)-검정1M + 미니수축튜브(사은품)</td>
<td style="text-align: center">제품 연결용</td>
<td style="text-align: center">2</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>제작방법</strong></span></p>
<p><img class="alignnone size-full wp-image-25420" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/003_터미널블록삽입.jpg" width="660" height="438" /></p>
<p><strong>01. 터미널블록삽입</strong><br />
터미널 블록을 삽입한다. AC를 직접 받아 AC를 출력하는데 작은 커넥터를 사용하긴 어려울 것이다. 특히 기존 등기구의 전선을 연결해야 하는데 전선 굵기가 굵기 때문에 터미널블록을 사용하였다.</p>
<p><img class="alignnone size-full wp-image-25421" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/004_시멘트저항삽입.jpg" width="660" height="438" /></p>
<p><strong>02. 시멘트저항삽입</strong><br />
시멘트 저항을 삽입한다. 5W의 시멘트저항을 사용하였으며 마일러콘덴서에 빠르게 충전되면서 과전류가 흐르는 것을 방지한다.</p>
<p><img class="alignnone size-full wp-image-25422" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/005_마일러콘덴서삽입.jpg" width="660" height="438" /></p>
<p><strong>03. 마일러콘덴서삽입</strong><br />
마일러콘덴서를 삽입한다. 이 콘덴서는 내압이 AC기준 250V, DC기준 500V이상의 제품을 구매해야 한다. 콘덴서 용량만큼의 작은 전류만 통과시켜 220V를 직접 받아도 초간단 정전류 회로가 구성되어 부하에 따라 낮은 전압을 만들어 낸다.</p>
<p><img class="alignnone size-full wp-image-25423" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/006_납땜후커팅.jpg" width="660" height="438" /></p>
<p><strong>04. 납땜후커팅</strong><br />
납땜한 후에는 다리를 잘라낸다. 다리는 접지 말고 세워놓도록 하는데 접어서 납땜할 경우 수리를 위해 부품을 교체하기가 어렵기 때문이다. 커팅 후에는 회로도대로 단자 간 연결을 하는데 220V부분은 굵게 처리한다.</p>
<p><img class="alignnone size-full wp-image-25424" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/007_퓨즈홀더삽입.jpg" width="660" height="438" /></p>
<p><strong>05. 퓨즈홀더삽입</strong><br />
이번 프로젝트는 220V를 직접 사용하기 때문에 위험할 수 있으므로 퓨즈를 장착한다. 교체형 퓨즈를 장착하기 위해 퓨즈홀더를 부착하였다.</p>
<p><img class="alignnone size-full wp-image-25425" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/008_브릿지다이오드삽입.jpg" width="660" height="438" /></p>
<p><strong>06. 브릿지다이오드삽입</strong><br />
브릿지 다이오드를 삽입한다. 조명은 AC를 사용하고 이번 프로젝트는 AC를 입력받지만 적외선 수광부나 IC같은 부품들은 DC를 사용해야 하므로 AC를 DC로 변환해주는 브릿지 다이오드를 사용한다. 브릿지 다이오드는 4개의 정류다이오드로 구성되며 출력 측에 콘덴서와 함께 DC로 만들어 주는 역할을 한다.</p>
<p><img class="alignnone size-full wp-image-25426" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/009_저항및다이오드다리접기.jpg" width="660" height="438" /></p>
<p><strong>07. 저항 및 다이오드 다리접기</strong><br />
1/4W급의 저항들과 다이오드는 다리가 수평으로 펴져있으므로 기판에 끼울 수 있도록 미리 다리를 구부려 놓는다.</p>
<p><img class="alignnone size-full wp-image-25427" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/010_저항및다이오드삽입.jpg" width="660" height="438" /></p>
<p><strong>08. 저항 및 다이오드 삽입</strong><br />
저항과 다이오드를 삽입한다. 저항 일부는 AC콘덴서에 충전된 에너지를 방전하는 역할과 나머지는 대부분 연결된 소자를 보호하기 위한 전류제한기능을 가지고 있다. 다이오드는 5.1V의 전위를 갖는 제너다이오드인데, 부하사용이 적으면 부하도 결국 입력 전압까지 찾아가는데 이렇게 되면 소자들이 파괴될 것이다. 5.1V가 넘으면 스스로 전류를 흘려보내 방전하여 항상 5V가 유지되도록 해준다.</p>
<p><img class="alignnone size-full wp-image-25428" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/011_ic소켓삽입.jpg" width="660" height="438" /></p>
<p><strong>09. IC 소켓 삽입</strong><br />
주 제어 MCU는 ATtiny13A-PU를 사용한다. 직접 납땜할 경우 교체가 어려우므로 IC소켓을 사용하였다.</p>
<p><img class="alignnone size-full wp-image-25429" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/012_세라믹콘덴서삽입.jpg" width="660" height="438" /></p>
<p><strong>10. 세라믹 콘덴서 삽입</strong><br />
IC소켓 주변으로 세라믹 콘덴서를 삽입한다. 리모컨 수신 때 또는 여러 가지 이유로 발생하는 리플을 제거하는 역할을 한다.</p>
<p><img class="alignnone size-full wp-image-25430" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/013_전해콘덴서삽입.jpg" width="660" height="438" /></p>
<p><strong>11. 전해콘덴서 삽입</strong><br />
전해콘덴서는 브릿지 다이오드와 함께 AC를 거의 완벽한 DC로 만들어주는 역할을 한다.</p>
<p><img class="alignnone size-full wp-image-25431" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/014_LED삽입.jpg" width="660" height="438" /></p>
<p><strong>12. LED 삽입</strong><br />
제품의 상태나 설정 상태를 보여주는 LED를 삽입한다. LED는 두 개가 서로 다른 극성이 되도록 병렬로 연결하므로 서로 다른 방향으로 삽입하도록 한다.</p>
<p><img class="alignnone size-full wp-image-25432" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/015_트라이악을방열판부착.jpg" width="660" height="438" /></p>
<p><strong>13. 트라이악을 방열판에 부착</strong><br />
트라이악을 방열판에 부착한다. 단순 등기구만 사용한다면 방열판은 필요 없지만 1A이상의 전류가 흐르는 경우 방열판이 필요할 수 있다. 나사를 끼울 때 부싱을 함께 사용하면 끝을 모르고 나사를 조이다 나사 선이 나가는 것을 방지할 수 있다. 방열판 크기가 크지 않으므로 부하는 연속 250W이상 흐르지 않도록 한다.</p>
<p><img class="alignnone size-full wp-image-25434" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/017_포토커플러삽입.jpg" width="660" height="438" /></p>
<p><strong>14. 포토커플러 삽입</strong><br />
AC라인과 MCU포트간 절연을 위해 포토커플러를 사용하였다.<br />
위상이 바뀌는 제로 크로스 시점에 ON이 되는 기능이 있는 포토커플러이므로 전등이 켜질 때 전기적으로 더욱 안정될 수 있다.</p>
<p><img class="alignnone size-full wp-image-25435" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/018_몰렉스삽입.jpg" width="660" height="438" /></p>
<p><strong>15. 몰렉스 삽입</strong><br />
적외선 수신부를 연결할 수 있도록 몰렉스를 사용하였다. 조명에 가려 리모컨이 인식이 안 될 수 있으므로 리모컨 수광센서는 두개를 사용하였다. 수광센서는 오픈드레인 출력이므로 두개가 병렬로 연결되도 문제가 없다.</p>
<p><img class="alignnone size-full wp-image-25436" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/019_고압세라믹삽입.jpg" width="660" height="438" /></p>
<p><strong>16. 고압 세라믹 삽입</strong><br />
고압세라믹을 삽입한다. 1kV타입을 사용하였는데 고압 세라믹은 보통 청색이다. 트라이악이 ON/OFF가 되는 시점에 상승 하강시간에 소자에 무리가 가는 것을 막아준다.</p>
<p><img class="alignnone size-full wp-image-25437" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/020_텍트스위치삽입.jpg" width="660" height="438" /></p>
<p><strong>17. 텍트스위치 삽입</strong><br />
텍트스위치를 삽입한다. 리모컨을 학습시키거나 전원이 투입될 경우(벽 스위치가 켜질 경우) 조명상태를 결정하게 하는 버튼이다.</p>
<p><img class="alignnone size-full wp-image-25438" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/021_클렘프전선에수축튜브끼우기.jpg" width="660" height="438" /></p>
<p><strong>18. 클림프 전선에 수축 튜브 끼우기</strong><br />
클림프 전선에 적외선 수광부를 직접 연결할 것이므로 수축튜브를 끼워놓는다.</p>
<p><img class="alignnone size-full wp-image-25439" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/022_적외선센서연결하기.jpg" width="660" height="438" /></p>
<p><strong>19. 적외선 센서 연결하기</strong><br />
클림프 전선에 적외선 수광부를 직접 연결한다. 너무 오래 납땜하면 수광부가 망가지므로 미리 양쪽에 납을 충분히 묻힌 후 빠르게 붙이도록 한다.</p>
<p><img class="alignnone size-full wp-image-25440" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/023_몰렉스에클렘프전선끼우기.jpg" width="660" height="438" /></p>
<p><strong>20. 몰렉스에 클림프 전선 끼우기</strong><br />
클림프가 삽입된 반대측 전선은 몰렉스에 끼워 완성한다.</p>
<p><img class="alignnone size-full wp-image-25441" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/024_L자형서포터끼우기.jpg" width="660" height="438" /></p>
<p><strong>21. L자형 서포터 끼우기</strong><br />
기판이 조명 등 기구 철재프레임에 직접 닿으면 납땜 면이 닿으면서 쇼트가 발생할 수 있다. 따라서 천장 철재 프레임에 부착하여도 안전하도록 L자형 서포터를 이용하였다.</p>
<p><img class="alignnone size-full wp-image-25442" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/026_프로그램굽기.jpg" width="660" height="438" /></p>
<p><strong>22. 프로그램 굽기</strong><br />
모두 조립되었고 결선도 완료했다면 테스터기로 올바르게 연결되었는지 확인한다. 다이오드의 극성, 트라이악의 극성 등 극성이 있는 부품의 방향도 확인한다. MCU에 www.itstyle.kr/ntrex/irLamp에서 동영상 및 소스프로그램, 회로도를 다운로드 받을 수 있다.<br />
사진은 필자가 만들어둔 다운로드 툴일 뿐이고, 독자들은 다운로드 툴을 이용하여도 좋고 ISP단자를 직접 연결하여 작업하여도 좋다. 단 220V가 인가된 상태에서는 PC접속을 할 수 없다. (절연되지 않아 220V가 연결된 상태에서 PC와 접속하면 고장 또는 화재가 발생할 수 있다.)</p>
<p><img class="alignnone size-full wp-image-25451" alt="027_프로그램로딩1" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/027_프로그램로딩1.png" width="315" height="486" /></p>
<p><strong>23. 프로그램로딩1</strong><br />
AVR Studio 4를 사용하여 다운로드 하는데, Tools-&gt;Program AVR-&gt;Auto Connect를 눌러 접속한다.</p>
<p><img class="alignnone  wp-image-25452" alt="028_프로그램로딩2" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/028_프로그램로딩2.png" width="442" height="455" /></p>
<p><strong>24. 프로그램로딩2</strong><br />
ATtiny13A를 선택하고 Read Signature를 눌러 정상적으로 인식되는지 확인한다.</p>
<p><img class="alignnone  wp-image-25453" alt="029_프로그램로딩3" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/029_프로그램로딩3-602x620.png" width="434" height="446" /></p>
<p><strong>25. 프로그램로딩3</strong><br />
다운로드 받은 hex파일을 불러오고 Program을 눌러 다운로드한다.</p>
<p><img class="alignnone  wp-image-25454" alt="030_프로그램로딩4" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/030_프로그램로딩4-602x620.png" width="421" height="434" /></p>
<p><strong>26. 프로그램로딩4</strong><br />
Int. RC Osc. 8MHz를 선택하고, BOD를 4.3V에 맞춰 설정한다. CK DIV8은 체크 해제한다.</p>
<p><img class="alignnone size-large wp-image-25443" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/031_구멍뚫기-620x464.jpg" width="620" height="464" /></p>
<p>27. 구멍뚫기<br />
천장 등기구 철제 프레임에 미리 구멍을 뚫어 나사를 박을 위치를 생각한다.</p>
<p><img class="alignnone size-large wp-image-25448" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/036_적외선센서연결하기2-620x464.jpg" width="620" height="464" /></p>
<p><strong>28. 드라이버</strong><br />
L자형 서포터를 사용한 이유가 나사구멍이 정확하게 맞지 않아도 끼울 수 있기 때문인데, 나사구멍에 맞춰 방향을 돌려 나사를 끼운다.</p>
<p><img class="alignnone size-large wp-image-25445" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/033_전원입력연결하기-620x464.jpg" width="620" height="464" /></p>
<p><strong>29. 전원 입력 연결하기</strong><br />
천장에서 나오는 전원선을 Line In 단자에 연결한다. 필자는 디바이스마트에서 판매하는 HIV 동심선을 이용하여 천장의 짧은 전선을 연장하였다.</p>
<p><img class="alignnone size-large wp-image-25446" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/034_전원출력연결하기-620x464.jpg" width="620" height="464" /></p>
<p><strong>30. 전원 출력 연결하기</strong><br />
기존 등기구 전선을 Line Out단자에 연결한다. 트라이악의 동작에 따라 등기구가 꺼졌다 켜질 것이다.</p>
<p><img class="alignnone size-large wp-image-25447" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/035_적외선센서연결하기-620x464.jpg" width="620" height="464" /></p>
<p><strong>31. 적외선 센서 연결하기 1</strong><br />
등기구 프레임 나사구멍이나 홀을 통해 적외선 센서를 빼낸다. 기판은 등기구 내부에 들어가고 적외선 센서는 외부에 노출되어야 한다.</p>
<p><img class="alignnone size-large wp-image-25448" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/036_적외선센서연결하기2-620x464.jpg" width="620" height="464" /></p>
<p><strong>32. 적외선 센서 연결하기 2</strong><br />
빼낸 적외선 센서를 기판에 끼운다.</p>
<p><img class="alignnone size-large wp-image-25449" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/037_설치된되습-620x464.jpg" width="620" height="464" /></p>
<p><strong>33. 설치된 모습</strong><br />
설치가 완료된 모습. 정상적으로 설치가 되면 벽 스위치를 켰을 때 자동으로 등이 켜진다. (리모컨이 없어도 기존 벽 스위치로 조작이 가능하도록 전원이 켜질 경우 자동으로 들어오도록 되어 있다.)</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>LED의 점등 방식설명</strong></span></p>
<table style="border-color: #dbdbdb;border-width: 1px;;width: 620px" border="1" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="text-align: center"><strong>LED 점등 방법(우측으로 진행)</strong></td>
<td style="text-align: center"><strong>설명</strong></td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #00ff00">●●●●</span><span style="color: #ff6600">●●●●</span><span style="color: #00ff00">●●●●</span><span style="color: #ff6600">●●●●</span></td>
<td style="text-align: center">최초 부팅시</td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #00ff00">●●●●●●●●●●●●●●●●</span></td>
<td style="text-align: center">리모컨 학습 완료</td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #ff6600">●●●●●●●●●●●●●●●●</span></td>
<td style="text-align: center">리모컨 학습 준비중</td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #ff6600">●</span>○○○<span style="color: #ff6600">●</span>○○○<span style="color: #ff6600">●</span>○○○<span style="color: #ff6600">●</span>○○○</td>
<td style="text-align: center">세팅 안 됨</td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #00ff00">●</span>○○○<span style="color: #00ff00">●</span>○○○<span style="color: #00ff00">●</span>○○○<span style="color: #00ff00">●</span>○○○</td>
<td style="text-align: center">세팅됨/조명 꺼짐</td>
</tr>
<tr>
<td style="text-align: center"><span style="color: #ff6600">●</span>○○○<span style="color: #00ff00">●</span>○○○<span style="color: #ff6600">●</span>○○○<span style="color: #00ff00">●</span>○○○</td>
<td style="text-align: center">세팅됨/조명 켜짐</td>
</tr>
</tbody>
</table>
<p><span style="color: #ff6600">●</span> : 황색 LED 점등, <span style="color: #00ff00">●</span> : 녹색 LED 점등, ○ : LED 소등 / 우측으로 시간이 진행합니다. 녹색과 황색 LED의 점등 방법을 설명하고 있으며 2개의 LED가 동시에 점등될 수는 없도록 설계되어 있다.</p>
<p>2개의 LED로 간단하게 장치의 상태를 파악하고 점검할 수 있다.</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>버튼 사용 방법</strong></span></p>
<table style="border-color: #cccccb;border-width: 1px;;width: 620px" border="1" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="text-align: center">누른 시간</td>
<td style="text-align: center">기능 명칭</td>
<td style="text-align: center">기능에 대한 설명</td>
</tr>
<tr>
<td style="text-align: center">2초 이상</td>
<td style="text-align: center">전등 상태 반전</td>
<td style="text-align: center">조명을 장치에서 직접 끄거나 켤 때 사용<br />
(현재 조명상태를 반전한다.)</td>
</tr>
<tr>
<td style="text-align: center">5초 이상</td>
<td style="text-align: center">리모컨 학습</td>
<td style="text-align: center">리모컨을 학습 시킬 때 사용</td>
</tr>
</tbody>
</table>
<p>우선 리모컨을 학습시키기 앞서 사용가능한 리모컨은 TC9012와 NEC방식 또는 흡사한 방식만 사용 가능하며 TV를 기준으로 했을 때 대표적으로 LG와 삼성전자, 아남, 대우일렉트로닉스, 가온미디어 같은 국내 제조회사들이 만드는 리모컨은 다 인식된다.</p>
<p>버튼을 2초간 누르면 전등 상태가 반전이 된다. 2초가 지나도 계속 누르고 있으면(노란불 점등), 리모컨 학습모드에 진입한다. 이 때 학습시키고자 하는 리모컨 버튼을 눌러 학습시키면 녹색불이 들어오고 내부 롬에 저장된다. 리모컨 키는 TV전원이나 외부입력 등 자주사용하는 키가 아닌 특수목적으로 잘 사용하지 않는 키를 학습시켜야 TV와 전등이 같이 제어되는 일이 없다.</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>리모컨 조작 방법</strong></span></p>
<p>전등을 끄고 켤 때 학습시킨 버튼만 누르면 된다.</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>타이머 설정하기</strong></span></p>
<p>타이머를 설정하고자 한다면 학습시킨 버튼을 연속으로 남은시간에 1을 더한 만큼 누르면 된다(누르는 간격은 5초 이내).<br />
만약 4번 누르면 최초의 1번 누른 것은 조명 상태를 결정하고 3번은 시간값으로 사용되는데, 3시간 뒤에 조명 상태가 반전한다.</p>
<p><span style="color: #00ff00">●</span><span style="color: #ff6600">●</span>-1sec-<span style="color: #ff6600">●</span>○-1sec-<span style="color: #00ff00">●</span>○-1sec-<span style="color: #ff6600">●</span>○-1sec-</p>
<p>단순 전등 상태만 나타내고 있는 모습.<br />
(전등 상태에 따라 녹색 또는 황색으로 표시됨)</p>
<p><span style="color: #00ff00">●</span>○<span style="color: #00ff00">●</span>○<span style="color: #00ff00">●</span>○-1sec-    <span style="color: #ff6600">●</span>○<span style="color: #ff6600">●</span>○<span style="color: #ff6600">●</span>○-1sec-</p>
<p><span style="color: #00ff00">●</span>○<span style="color: #00ff00">●</span>○<span style="color: #00ff00">●</span>○-1sec-    <span style="color: #ff6600">●</span>○<span style="color: #ff6600">●</span>○<span style="color: #ff6600">●</span>○-1sec-</p>
<p>타이머가 맞춰진 만큼 LED가 점등하며 시간이 지날수록 LED의 점멸 횟수는 줄어든 후 조명 상태가 반전된다.<br />
다시 리모컨을 누르면 전등 상태가 반전되면서 타이머는 해제된다. 타이머를 다시 맞추려면 다시 시간 값에 1을 더한 만큼 눌러주면 된다.</p>
<hr />
<p><span style="color: #ffffff;background-color: #008000"><strong>리모컨 포맷의 구조</strong></span></p>
<p>우선 우리 주변에 사용되는 리모컨은 적외선을 이용하여 통신하며, 데이터에 따라 ON, OFF를 반복하여 전송한다. 이 때 주변의 방해요소(태양광, 형광등 같은 각종 빛)에 극복할 수 있도록 38kHz의 케리어 주파수(제조사에 따라 더 높거나 낮을 수 있다)에 실어보낸다.</p>
<p>적외선 센서는 각종 빛을 수신하지만 이중 38kHz만 통과시키도록 BPF(대역 통과 필터)를 거친 후 이것을 NPN TR을 통해 데이터로 출력하게 된다.<br />
케리어 주파수에 대해서는 리모컨 제조사와 적외선 센서 제조사가 신경 써야할 부분으로 원리만 알고 자세한 것은 알지 않아도 문제가 없다.</p>
<p><span style="background-color: #008000;color: #ffffff"><strong>리모컨 포맷의 전체 구조</strong></span></p>
<p><img class="alignnone  wp-image-25455" alt="23project01" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/23project01.bmp" width="603" height="154" /></p>
<p>리드코드, 16Bit(2Byte)의 커스텀 코드, 8Bit(1Byte)의 데이터 코드, 반전된 8Bit의 데이터 코드로 이루어진다.<br />
첫 번째 프레임은 리드코드인데, TC9012는 4.5ms의 On 시간과, 4.5ms의 Off 시간을 갖는데, 비슷하지만 NEC규격은 9ms의 On 시간과, 4.5ms의 Off 시간을 갖는다.</p>
<p>이번 프로젝트에서는 리드코드는 참조만 할 뿐 그 시간은 중요하게 생각하지 않으므로 TC9012와 NEC포멧 모두를 사용할 수 있다.</p>
<table style="border-color: #dbdbdb;border-width: 1px;;width: 620px" border="1" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="text-align: center">데이터가 “0”일 때</td>
<td style="text-align: center">데이터가 “1”일 때</td>
</tr>
<tr>
<td style="text-align: center"> <img class="alignnone size-large wp-image-25418" alt="23project02" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/23project02.bmp" /></td>
<td style="text-align: center"> <img class="alignnone size-large wp-image-25450" alt="23project03" src="http://www.ntrexgo.com/wp-content/uploads/2014/05/23project03.bmp" /></td>
</tr>
<tr>
<td style="text-align: center">0.56ms의 On 시간과<br />
0.565ms의 Off 시간을 갖는다.</td>
<td style="text-align: center">0.56ms의 On 시간과<br />
1.69ms의 Off 시간을 갖는다.</td>
</tr>
</tbody>
</table>
<p>커스텀, 데이터 코드는 위 표처럼 On 시간과 Off 시간을 가지고 리모컨 신호의 종류를 가려낸다.<br />
커스텀 코드는 제조사 및 모델 라인업에 따라 결정되며, 데이터 코드는 해당 제품의 리모컨 키 값을 담고 있다. 데이터 코드는 8비트만 있고 뒤에 값은 반전되어 있는데, 두 데이터의 값을 비교해 검증하는 목적도 있고, 1과 0의 데이터 전송 길이가 다르므로 만약 데이터 코드가 0xff라면 총 길이는 18ms가 소요되지만, 0&#215;00라면 총 길이는 9ms에 불과해 리모컨 버튼에 따라 전송 속도가 모두 달라지므로 어떠한 버튼을 눌러도 전송 속도가 동일하게 나오게 하려고 반전하는 이유도 있다.</p>
<p>receive:</p>
<p style="padding-left: 30px">in _SREG,SREG ; 인터럽트 진입시 상태 레지스터 백업<br />
push tmp ; 연산 데이터 비교를 위한 레지스터 백업</p>
<p style="padding-left: 30px">outiw TCNT,0 ; 리모컨 타이머를 0으로 초기화</p>
<p style="padding-left: 30px">pusw x ; 타이머 값 비교에 사용될 레지스터를 백업<br />
pusw z ; 간접주소 사용에 필요한 레지스터를 백업<br />
in xL,ICR1L<br />
in xH,ICR1H<br />
mov tmp,remote_count<br />
cpi tmp,33 ;;; 스타트 1 + 커스텀 16 + 데이터 16 = 총 33비트<br />
brne PC+2<br />
rjmp receive_out ;;; 비트 수가 33개가 넘어가면 잘못된 수신으로 판단.<br />
cpi tmp,32<br />
brcs PC+12<br />
ldi tmp,high(4000) ;;; 스타트 On시간을 비교.<br />
cpi xL,low(4000)<br />
cpc xH,tmp<br />
brcc PC+2<br />
rjmp ir_range_ov ;;; 스타트 On시간이 4~5mS를 벗어나면 무효, 이후 들어오는 비트 신호는 무시<br />
ldi tmp,high(5000)<br />
cpi xL,low(5000)<br />
cpc xH,tmp<br />
brcs PC+2<br />
rjmp receive_out ;;; 스타트 On시간이 4~5mS 이내이면 유효, 다음 비트가 들어올 때 까지 대기(인터럽트 종료)<br />
rjmp ir_range_ov<br />
ldi tmp,high(1080) ;;; 커스텀 또는 데이터 비트 비교 시작<br />
cpi xL,low(1080)<br />
cpc xH,tmp<br />
brcs PC+7<br />
ldi tmp,high(1220)<br />
cpi xL,low(1220)<br />
cpc xH,tmp<br />
brcc PC+3<br />
clc ; 커스텀 또는 데이터 비트가 1.08~1.22mS 범위면 비트 “0”으로 간주<br />
rjmp PC+10<br />
ldi tmp,high(2150)<br />
cpi xL,low(2150)<br />
cpc xH,tmp<br />
brcs ir_range_ov<br />
ldi tmp,high(2350)<br />
cpi xL,low(2350)<br />
cpc xH,tmp<br />
brcc ir_range_ov<br />
sec ; 커스텀 또는 데이터 비트가 2.15~2.35mS 범위면 비트 “1”으로 간주<br />
ror ir_code_buff4<br />
ror ir_code_buff3<br />
ror ir_code_buff2<br />
ror ir_code_buff1 ;;; 4바이트를 우측으로 시프트</p>
<p style="padding-left: 30px">tst remote_count<br />
brne receive_out ; 33비트가 모두 수신되었으면 데이터로 사용</p>
<p style="padding-left: 30px">ldiw z,ir_data<br />
; ldi remote_data,0<br />
clr remote_reg</p>
<p>loop_search:<br />
;;; 일치하는 코드가 나올 때 까지 루프<br />
;;; (그러나 1개의 버튼만 사용하므로 1회만 실행함)</p>
<p style="padding-left: 30px">ldd tmp,z+0<br />
cp ir_code_buff1,tmp ; 첫번째 코드 비교 (커스텀 코드 1번)<br />
brne next_search</p>
<p style="padding-left: 30px">ldd tmp,z+1<br />
cp ir_code_buff2,tmp ; 두번째 코드 비교<br />
(커스텀 코드 2번)<br />
brne next_search</p>
<p style="padding-left: 30px">ldd tmp,z+2<br />
cp ir_code_buff3,tmp ; 세번째 코드 비교 (데이터 코드 1번)<br />
brne next_search</p>
<p style="padding-left: 30px">ldd tmp,z+3<br />
cp ir_code_buff4,tmp ; 네번째 코드 비교 (데이터 코드 2번)<br />
breq find_code</p>
<p>next_search:</p>
<p>;;; 리피트 코드 처리 및 다른 코드 비교처리<br />
;;; 이번 프로젝트는 1개의 버튼만 사용되고, 연속적으로 눌렀을 때 사용되는 기능이 없으므로<br />
;;; 리피트 및 다른 코드비교는 이번 프로젝트에서 사용되지 않음.</p>
<p>ext_io_skip:</p>
<p style="padding-left: 30px">popw z<br />
popw x</p>
<p style="padding-left: 30px">out SREG,_SREG ; 인터럽트 진입 이전의 상태로 상태 레지스터 복구<br />
pop tmp<br />
reti ; 인터럽트 복구(스텍에 저장된 인터럽트 실행 전 주소로 이동하고 인터럽트를 활성화)</p>
<hr />
<p><span style="background-color: #3366ff;color: #ffffff"><strong>코드 설명</strong></span></p>
<p>AVR 어셈블리 명령을 사용하고 있으며 일부 명령은 메크로로 간소화 하였으므로 자세한 정보가 필요하면 코드를 다운로드 하기 바란다.<br />
기본적으로 AVR 내에 내장된 타이머를 이용하며 외부 인터럽트가 발생하면 타이머 값을 이용해 시간 값을 비교하는 방식이다.<br />
적외선 수신 센서에서 비트를 하나씩 보내주면 비트가 오는 시간을 측정해 데이터의 유효성 및 종류를 판단하고 비트를 조합하여 4바이트의 리모컨 데이터를 만들어 내는 것이다.</p>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>회로도</strong></span></p>
<div id='wpdm_file_9' class='wpdm_file wpdm-only-button'><div class='cont'></br><div class='btn_outer'><div class='btn_outer_c' style='background-image: url(http://www.ntrexgo.com/wp-content/plugins/download-manager/icon/file_extension_pdf.png);'><a class='btn_left  ' rel='9' title='23-디바이스마트 매거진 적외선리모컨조명제어_회로도' href='http://www.ntrexgo.com/?wpdmact=process&did=OS5ob3RsaW5r'  >적외선리모컨조명제어 회로도 Download</a><span class='btn_right'>&nbsp;</span></div></div><div class='clear'></div></div></div>
<p><span style="background-color: #3366ff;color: #ffffff"><strong>저자 소개</strong></span></p>
<p>제작·사진·글:  이민주 객원 기자<br />
www.itstyle.kr 운영자</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/25403/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[18호]스펙트럼 아날라이저 만들기!!</title>
		<link>http://www.ntrexgo.com/archives/13894</link>
		<comments>http://www.ntrexgo.com/archives/13894#comments</comments>
		<pubDate>Fri, 10 May 2013 01:59:04 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[프로젝트]]></category>
		<category><![CDATA[18호]]></category>
		<category><![CDATA[Project To Build]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[스펙트럼]]></category>
		<category><![CDATA[아날라이저]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13894</guid>
		<description><![CDATA[디바이스마트 매거진 18호 &#124; 클럽이나 노래방에서 큰 음악과 함께 조명은 분위기를 한층 더 띄워준다. 가정에서 커다란 조명을 가져다 둘 수 없으니 소형화된 스팩트럼 아날라이저가 생기면 좋겠다는 생각을 했다.단순 악세사리 역할은 물론이고 실용성을 높이기 위해 라인선택 기능을 추가하여 두가지 소스기기를 연결할 수 있도록 하였다.]]></description>
				<content:encoded><![CDATA[<table style="width: 620px" border="0">
<tbody>
<tr>
<td width="300"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA004.jpg" rel="lightbox[13894]"><img class="alignnone size-medium wp-image-13908" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA004-300x199.jpg" width="300" height="199" /></a></td>
<td><span style="font-size: medium;color: #808080"><strong>눈과 귀가 모두 즐거운</strong></span></p>
<p><strong><span style="font-size: x-large">스펙트럼 아날라이저</span></strong></p>
<p><strong></strong><strong><span style="font-size: x-large">만들기!!</span></strong></p>
<p style="text-align: right">
<p style="text-align: right">글 | 이민주 객원기자 itstyle@itstyle.kr</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>작업할 때, 운동을 하거나 공부를 할 때 음악과 함께 하면 때로는 능률이 오르거나 집중하게 한다. 하지만 쉬는 시간 또는 음악만을 위해 시간을 투자하는 사람들은 음악을 감상하며 눈을 어디에 두어야 할까? 명상을 한다며 항상 눈을 감을 순 없는 노릇이다.<br />
클럽이나 노래방에서 큰 음악과 함께 조명은 분위기를 한층 더 띄워준다. 가정에서 커다란 조명을 가져다 둘 수 없으니 소형화된 스팩트럼 아날라이저가 생기면 좋겠다는 생각을 했다.<br />
단순 악세사리 역할은 물론이고 실용성을 높이기 위해 라인선택 기능을 추가하여 두가지 소스기기를 연결할 수 있도록 하였다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA016.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13920" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA016-620x465.jpg" width="620" height="465" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA017.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13921" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA017-620x465.jpg" width="620" height="465" /></a></td>
</tr>
<tr>
<td><span style="color: #1e67cc"><strong>1. 제작에 필요한 부품들과 공구이다.</strong></span></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA018.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13922" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA018-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>2. LED ARRAY 삽입</strong></span><br />
화면부가 가장 중요하므로 먼저 제작할 것이다. 머릿속으로 LED의 배치를 구상하고 전면부 PCB에 LED를 부착한다. 좌·우 간격을 잘 생각하여 LED Array를 순서대로 끼운다. 극성이 있으므로 모두 같은 방향으로 배치한다.</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA019.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13923" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA019-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>3. 납땜</strong></span><br />
기판을 뒤집어 납땜한다. 부품이 빠지지 않게 손으로 고정한 상태에서 뒤집는다. 납땜은 모서리 한쪽을 먼저 납땜하고 손으로 살짝 누른 상태에서 납을 녹여 완전히 밀착한다. 대각선 위치의 핀에도 같은 방법으로 밀착하여 납땜한 후 나머지도 납땜한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA020.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13924" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA020-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>4. 눈금 LED 삽입</strong></span><br />
LED Array는 10개지만 음압의 높이를 쉽게 가늠하도록 좌우에는 눈금 표시용 LED를 취향에 맞게 적절히 배치한다. 전원이 켜지면 항상 켜있는 LED이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA021.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13925" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA021-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>5. 주파수 LED 삽입</strong></span><br />
LED Array 아래 10개의 정사각형 LED를 부착한다. 주파수 영역 표시용 LED로 사용될 것이고 남는 LED는 모드표시나 채널, 버튼 조광용으로 사용될 것이다. 일부 상태 표시 LED를 제외하면 눈금LED처럼 항상 켜있는 LED들이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA022.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13926" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA022-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>6. 스위치 삽입</strong></span><br />
LED Array 아래 10개의 정사각형 LED를 부착한다. 주파수 영역 표시용 LED로 사용될 것이고 남는 LED는 모드표시나 채널, 버튼 조광용으로 사용될 것이다. 일부 상태 표시 LED를 제외하면 눈금LED처럼 항상 켜있는 LED들이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA023.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13927" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA023-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>7. 몰렉스 삽입</strong></span><br />
기판 하단에는 기판 연결용 몰렉스를 삽입한다. 90도 타입 제품을 삽입해야 기판이 수직으로 고정된다.참고로 몰렉스가 기판에 차지하는 공간 때문에 완성된 제품의 디자인이 조금 아쉬웟다. 핀 헤더 나 케이블을 이용해 위 아래가 좀 더 슬림하게 만들어지면 좋을 것 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA024.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13928" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA024-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>8. 몰렉스 결합</strong></span><br />
삽입한 몰렉스에는 반대쪽 몰렉스도 삽입해 놓는다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA025.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13929" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA025-620x465.jpg" width="620" height="465" /></a><br />
<strong><span style="color: #1e67cc">9A. 기판 절단</span> </strong><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA026.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13930" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA026-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>9B. 기판 구멍 뚫기</strong></span><br />
기판이 너무 길어지면 만들어지는 제품이 너무 커지므로 2층으로 구성할 예정이다.2층 기판으로 “BA7-80&#215;100-단면”를 사용할 예정인데, 이 크기보다 약간 크게 만들 수 있도록 “BA8-80&#215;130-단면”을 잘랐다. 서포터 홀도 같은 위치에 뚫는다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA027.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13931" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA027-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>10. 기판 수직으로 세우기</strong></span><br />
1층 기판에 전면부 기판을 수직으로 세워 삽입하여 납땜하고 몰렉스를 분리한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA028.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13932" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA028-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>11A. 어댑터잭 삽입 위한 구멍 뚫기</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA029.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13933" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA029-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>11B. 어댑터잭 삽입</strong></span><br />
커터 칼이나 아크릴 칼을 이용해 기판에 적절히 구멍을 뚫어 어댑터 잭을 삽입한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA030.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13934" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA030-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>12. 오디어잭 삽입</strong></span><br />
오디오 잭을 삽입한다. 필자가 실수로 반대로 생각해 청색을 하나만 녹색 두개를 신청해서 반대로 사용하고 있지만, 표준으로는 녹색이 출력이고 청색이 입력이다. 이 제품은 입력 선택기능이 있다. 따라서 출력인 녹색 1개와 입력인 청색 2개가 필요하다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA031.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13935" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA031-620x465.jpg" width="620" height="465" /></a></p>
<p><span style="color: #1e67cc"><strong>13.TR ARRAY 삽입</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA032.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13936" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA032-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>14. HEF4069 삽입</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA033.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13937" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA033-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>15.LM3915 삽입</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA034.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13938" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA034-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>16.HEF4017 삽입</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA035.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13939" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA035-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>17.TLC555 삽입</strong></span></p>
<p>각종 IC를 삽입한다.<br />
이번 DIY는 하드웨어에 전부 의존하는데, 555는 클럭 발진, LM324는 BPF와 덧셈기, 4016은 BPF신호 선택기, 4017은 Dynamic구동과 함께 BPF 신호 선택, 4069는 버튼 스위치, LM3915는 레벨메터 출력, UDN2981AT는 LED구동 버퍼로 간략히 설명할 수 있다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA036.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13940" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA036-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>18. RELAY 삽입</strong></span><br />
릴레이를 삽입한다. 릴레이는 두 개가 있는데, ON시 모든 소자에 전원을 공급하기 위한 일종의 전원 스위치 역할을 하는 것과 다른 하나는 2개의 음향신호를 1개만 선택할 수 있는 역시 스위치의 역할을 하고 있다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA037.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13941" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA037-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>19. 저항 삽입</strong></span><br />
IC주변에 저항을 삽입한다. LED기판에도 저항을 연결한다. BPF회로 주변에는 저항이 많이 들어가는데 바뀌지 않도록 주의한다.<br />
참고로 LM3915출력에는 전류제한기능이 있어 이것에 연결되는 레벨메터 LED에는 저항이 필요 없다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA038.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13942" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA038-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>20. 세라믹 콘덴서 삽입</strong></span><br />
BPF 주변과 바이패스에 많이 쓰이고 있으며 일부에는 스위치에도 쓰이고 있다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA039.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13943" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA039-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>21. 전해콘덴서 삽입</strong></span><br />
전해콘덴서는 BPF출력 단에서 교류성분을 제거하는데 사용되고 있고, -12V를 생성하는 역할과 함께 전원부에 쓰인다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA040.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13944" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA040-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>22. 2층 기판 연결위한 핀헤더 소켓 삽입</strong></span><br />
1층기판에만 부품을 배치하기에는 공간이 약간 협소하므로 2층기판을 만들 것인데, 핀 헤더를 이용하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA042.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13898" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA042-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>23. 핀헤더 핀 작업된 모습</strong></span><br />
릴레이의 부품의 높이를 고려하고 내부가 보이도록 만들 것이라 조금 높은 핀 헤더를 이용했다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA043.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13899" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA043-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>24A. 2층 기판 핀헤더 핀 삽입</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA044.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13900" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA044-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>24B. 2층 기판 핀헤더 핀 삽입</strong></span><br />
2층 기판에 부품을 꽂고 핀 헤더 핀을 삽입한다. 2층 기판에는 핀 헤더 핀을 이용해 접속할 예정인데, 우선 1층 기판에 핀 헤더 소켓을 삽입한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA045.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13901" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA045-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>25. 주파수 대역, 버튼에 넣을 문자 인쇄</strong></span><br />
주파수 대역 표시용 LED와 상태표시 LED전면에 간단한 아이콘이나 주파수를 적을 예정이다. 하얀색 종이에 흰 글씨와 검정색 배경으로 글씨를 적어 인쇄한 후 뒷면에 양면테이프를 붙여 LED크기에 맞게 자른다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA047.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13903" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA047-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>26. 인쇄문자 부착</strong></span><br />
LED에 하나씩 문자를 붙인다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA046.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13902" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA046-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>27.기판 완성</strong></span><br />
만들어진 3장의 기판을 합친 모습이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA048.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13904" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA048-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>28. 포맥스 가공</strong></span><br />
케이스로 측면과 전면은 아크릴로, 기판이 고정되는 하부는 포맥스를 이용할 것인데, 포맥스는 커터칼로 쉽게 잘린다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA013.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13917" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA013-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>29. 구멍 뚫기</strong></span><br />
기판 크기와 여유공간을 감안하고 위치를 표시하고 드릴로 구멍을 뚫으면 그곳이 서포터 자리가 된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA014.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13918" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA014-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>30. 서포터 삽입</strong></span><br />
드릴로 구멍을 뚫은 자리에 0.5mm 금속 서포터와 너트를 체결한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA011.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13915" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA011-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>31. 뒷면 가공</strong></span><br />
뒷면 역시 위치를 잡고 구멍을 낸다. DC 잭의 경우 직사각형 모양이므로 칼로 구멍을 낸 뒤 끌 같은 것으로 깔끔하게 처리한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA012.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13916" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA012-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>32. 아크릴 가공</strong></span><br />
아크릴은 아크릴 전용 칼로 자른다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA009.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13913" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA009-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>33. 버튼 구멍 뚫기</strong></span><br />
전면부의 경우 3개의 버튼이 있고 이곳의 구멍도 뚫는다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA010.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13914" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA010-620x465.jpg" width="620" height="465" /></a><br />
<strong>34. 아크릴 부착</strong><br />
측면과 상부는 투명 아크릴을 이용했는데, 순간접착제를 이용해 부착한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA008.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13912" alt="SAMSUNG DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA008-620x413.jpg" width="620" height="413" /></a><br />
<span style="color: #1e67cc"><strong>35. 케이스에 조립</strong></span><br />
만들어진 케이스에 기판을 넣고 조립하여 완성.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA006.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13910" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA006-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>36A. 조립 완료한 모습, 전면</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA007.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13911" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA007-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>36B. 조립 완료한 모습, 후면</strong></span><br />
이렇게 해서 완성된 앞(위), 뒤(아래) 모습이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA005.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13909" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA005-620x465.jpg" width="620" height="465" /></a><br />
<span style="color: #1e67cc"><strong>37.시험하기</strong></span><br />
펑션제너레이터를 이용하여 정상적으로 대역이 표시되는지 확인하자.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA001.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13905" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA001-620x329.jpg" width="620" height="329" /></a><br />
<span style="color: #1e67cc"><strong>38. 사용방법1</strong></span><br />
이 제품은 릴레이를 통해 음향신호를 선택할 수 있으므로 두 개의 소스에 동시에 연결할 수 있다.<br />
예를 들면 LINE 1에는 PC를 연결해놓고 LINE 2는 MP3나 휴대폰에 연결할 수 있도록 해놓는다면 복잡한 선 교체 없이 가볍게 버튼을 눌러 소스기기를 선택할 수 있다.<br />
선택된 채널 LED가 점등된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA002.jpg" rel="lightbox[13894]"><img class="alignnone size-full wp-image-13906" alt="18PTBSPA002" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA002.jpg" width="500" height="200" /></a><br />
<span style="color: #1e67cc"><strong>39A. 사용방법2</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA003.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13907" alt="18PTBSPA003" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA003-620x248.jpg" width="620" height="248" /></a><br />
<span style="color: #1e67cc"><strong>39B. 사용방법2</strong></span><br />
LM3915 자체 기능에는 BAR모드와 DOT모드 2가지 표시방법이 있다. 역시 버튼을 눌러 선택할 수 있다.<br />
선택된 표시방법 LED가 점등된다.</p>
<p>사용하지 않을 때에는 전원을 끌 수 있는데 채널 Line선택 릴레이도 같이 꺼지므로 1번 채널만 출력되게 된다.<br />
전원을 껐을 때에는 약 20mA정도(대부분 Stand by LED) 소모하고 전원을 켰을 때에는 많은 LED가 켜지면서 약 200~350mA정도 소모한다.</p>
<p><span style="color: #1e67cc"><strong>·작동원리</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA0451.jpg" rel="lightbox[13894]"><img class="alignnone size-full wp-image-13953" alt="18PTBSPA045" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA0451.jpg" width="429" height="435" /></a></p>
<p>3개의 스위치는 누를 때 마다 4069의 상태가 변화하여 스위치의 상태를 기억한다.<br />
전원을 켜면 4069의 출력으로 Relay가 우선 작동해 메인 전원이 공급되고, 자기유지 회로를 통해 4069출력 대신 TR Array를 통해 작동하여 4069의 부담을 줄여준다.<br />
555에서 4kHz정도 빠른(인간의 입장에서) 속도로 발진하게 되면 LM324N에서 사용할 -12V를 만들기 위해 차지펌프 원리를 이용하여 -12V(실제로는 -10V 정도)를 생성한다.<br />
잡음이나 안정도가 떨어지지만 어차피 음 영역은 사용하지 않아 저렴하게 구성하기에는 전혀 무관하다.<br />
LM324N에서는 좌/우 두 개의 신호를 합치는 역할과 증폭, BPF부분을 담당하고 있다.<br />
555출력은 4017로도 공급되는데, Q0~Q9까지 순서대로 빠른 속도로 이동하게 해준다.<br />
이것은 LED 다이내믹 신호를 만들어 DN2981AT를 거쳐 LED 세로줄을 제어하면서 동시에 HEF4016 아날로그 스위치를 통해 10개의 BPF출력을 1개만 선택할 수 있게 해준다.<br />
선택된 BPF출력은 LM3915를 통해 그래프로 표현되는데, HEF4017이 만약 1kHz 대역을 선택했다면 동시에 1kHz에 해당하는 BPF출력과 1kHz에 해당하는 LED 세로줄을 ON시켜주므로 대역에 맞추어 스팩트럼으로 표현되는 것이다.</p>
<p>음향기기(소스기기) 연결이 번거로웠던 사람이라면, 시각 효과를 좋아하는 사람들, 음악에 취미가 있는 사람들은 하나쯤 만들어보자.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA004.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13908" alt="OLYMPUS DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA004-620x411.jpg" width="620" height="411" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA015.jpg" rel="lightbox[13894]"><img class="alignnone size-large wp-image-13919" alt="SAMSUNG DIGITAL CAMERA" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA015-620x413.jpg" width="620" height="413" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="http://www.youtube.com/watch?hl=ko&amp;gl=KR&amp;client=mv-google&amp;v=UtbLO9_dObc&amp;nomobile=1" target="_blank"><span style="color: #1e67cc"><strong>▶ 동영상 보러가기 </strong></span></a></p>
<p>&nbsp;</p>
<p><strong><span style="color: #1e67cc">▶ 부품목록</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA0461.jpg" rel="lightbox[13894]"><img class="alignnone  wp-image-13974" alt="18PTBSPA046" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18PTBSPA0461.jpg" width="557" height="767" /></a></p>
<p><span style="color: #3366ff"><strong>▶ 회로도</strong></span></p>
<p>&nbsp;</p>
<div id='wpdm_file_4' class='wpdm_file wpdm-only-button'><h3>[18호]스펙트럼 아날라이저 - 메인보드</h3><div class='cont'><div class='btn_outer'><div class='btn_outer_c' style='background-image: url(http://www.ntrexgo.com/wp-content/plugins/download-manager/icon/old-go-bottom.png);'><a class='btn_left  ' rel='4' title='[18호]스펙트럼 아날라이저 - 메인보드' href='http://www.ntrexgo.com/?wpdmact=process&did=NC5ob3RsaW5r'  >Download</a><span class='btn_right'>&nbsp;</span></div></div><div class='clear'></div></div></div>
<div id='wpdm_file_5' class='wpdm_file wpdm-only-button'><h3>[18호]스펙트럼 아날라이저 - 디스플레이보드</h3><div class='cont'><div class='btn_outer'><div class='btn_outer_c' style='background-image: url(http://www.ntrexgo.com/wp-content/plugins/download-manager/icon/old-go-bottom.png);'><a class='btn_left  ' rel='5' title='[18호]스펙트럼 아날라이저 - 디스플레이보드' href='http://www.ntrexgo.com/?wpdmact=process&did=NS5ob3RsaW5r'  >Download</a><span class='btn_right'>&nbsp;</span></div></div><div class='clear'></div></div></div>
<div id='wpdm_file_3' class='wpdm_file wpdm-only-button'><h3>[18호]스펙트럼 아날라이저 - 필터보드</h3><div class='cont'><div class='btn_outer'><div class='btn_outer_c' style='background-image: url(http://www.ntrexgo.com/wp-content/plugins/download-manager/icon/old-go-bottom.png);'><a class='btn_left  ' rel='3' title='[18호]스펙트럼 아날라이저 - 필터보드' href='http://www.ntrexgo.com/?wpdmact=process&did=My5ob3RsaW5r'  >Download</a><span class='btn_right'>&nbsp;</span></div></div><div class='clear'></div></div></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13894/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[14호] 안드로이드를 이용한 탱크 조종</title>
		<link>http://www.ntrexgo.com/archives/2049</link>
		<comments>http://www.ntrexgo.com/archives/2049#comments</comments>
		<pubDate>Sat, 25 Aug 2012 04:12:13 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[프로젝트]]></category>
		<category><![CDATA[16호]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[Project To Build]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[안드로이드]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=2049</guid>
		<description><![CDATA[디바이스마트 매거진 14호 &#124; 안드로이드를 이용한 탱크 조종을 하고자 하였다. 통신 방식은 블루투스를 이용하고 탱크측 제어는 Attiny2313를 이용하였고, 단순 전후진만이 아닌 다른 동작들을 추가 하였다.]]></description>
				<content:encoded><![CDATA[<h3><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband03.jpg" rel="lightbox[2049]"><img class=" wp-image-2071 alignleft" alt="14ptband03" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband03-300x221.jpg" width="216" height="159" /></a>2012 DIY 프로젝트 작품 공모전 &#8211; 도전상</h3>
<h2><strong><span style="color: #008080">안드로이드를 이용한 </span></strong></h2>
<h2><strong><span style="color: #008080">탱크 조종</span></strong></h2>
<p style="padding-left: 420px">글 | 김종욱 bear1215@korea.com</p>
<p style="padding-left: 420px">
<p style="padding-left: 420px">
<p>&nbsp;</p>
<p><strong style="color: #008000">심사평</strong></p>
<p style="padding-left: 30px">근래 관심을 받는 안드로이드와 일반 주행 로봇을 결합한 작품이다. 무선조종기 대신 안드로이드 OS를 이용하여 해당 OS가 설치된 장비(폰, 태블릿 등)에서 로봇을 조종할 수 있도록 되어있다. 일반 사용자의 DIY 컨셉에 맞춰 본다면 쉽게 접근할 수 있는 내용이다. 단, 안드로이드 측 프로그램에 대한 구현방법에 대한 설명 등이 문서상 미흡한 것이 아쉬움으로 남는다.</p>
<p><span style="color: #008000"><strong>개발 동기 및 목적</strong></span></p>
<p style="padding-left: 30px">안드로이드를 이용한 탱크 조종을 하고자 하였다. 통신 방식은 블루투스를 이용하고 탱크측 제어는 Attiny2313를 이용하였고, 단순 전후진만이 아닌 다른 동작들을 추가 하였다. 1.전후진, 2.좌회전, 3.우회전, 4.좌후진, 5.우후진, 6.포탑 회전(좌우), 7.포신의 상하 이동, 8.포탄 발사(BB탄 발사), 9.전조등/후미등 켜기</p>
<p>&nbsp;</p>
<p><span style="color: #008000"><strong>단계별 과정</strong></span></p>
<p><strong><span style="color: #33cccc">1. 구조도(상세 블럭도 및 회로도 참조)</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2082" alt="구조도" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband-241x300.jpg" width="241" height="300" /></a><br />
<strong><span style="color: #33cccc">2. 전원</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband01.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2083" alt="14ptband01" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband01-300x142.jpg" width="300" height="142" /></a></p>
<p>전원은 기존의 밧데리를 이용한다. (9.7V 1000mA)<br />
정전원 변환은 LM2575-5.0를 사용하였다. 전원은 9.7V를 모터 구동 전원으로 사용하고 제어부인 Attiny2313은 5.0V 전원을 사용한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband02.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2084" alt="14ptband02" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband02-300x135.jpg" width="300" height="135" /></a><br />
탱크부 구성<br />
기존의 RF 제어부를 제거하고 모터, 밧데리 등은 그대로 사용한다. 탱크의 구성은 아래의 표와 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband014.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2096" alt="14ptband014" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband014-300x125.jpg" width="300" height="125" /></a><br />
<strong><span style="color: #33cccc">3. 탱크 제어부 구성</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband03.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2071" alt="14ptband03" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband03-300x221.jpg" width="300" height="221" /></a><br />
탱크 제어는 Attiny2313을 사용한다.<br />
가. MPU : Attiny2313<br />
나. 주모터 제어 : L293B(정역 회전용 2set)<br />
다. 포탑 모터 : LB1630(정역 회전용 1set)<br />
라. 포신 모터 : ULN2803(1/8)<br />
마. 포 발사 모터 : ULN2803(1/8)<br />
바. 전조등 : ULN2803(1/8)<br />
사. 후미등 : ULN2803(1/8)</p>
<p><strong><span style="color: #33cccc">4. 탱크 제어부 통신 모듈</span></strong><br />
탱크 제어부와 안드로이드 폰 연결은 bluetooth모듈을 사용하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband04.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2072" alt="14ptband04" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband04-300x161.jpg" width="300" height="161" /></a></p>
<p><a href="http://www.devicemart.co.kr/goods/view.php?seq=15592" target="_blank">my Bluetooth-EX 모듈 구입하러 가기</a></p>
<p><strong><span style="color: #33cccc">5. 안드로이드 프로그램</span></strong><br />
<span style="color: #666699"><strong>Program : android측</strong></span><br />
<span style="color: #666699"><strong> tankControl.java</strong></span></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">tankControl.java 소스보기</h3><div class="symple-toggle-container">
<p>package kr.sunejune;</p>
<p>import android.R;<br />
import android.app.Activity;<br />
import android.bluetooth.BluetoothAdapter;<br />
import android.bluetooth.BluetoothDevice;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.os.Handler;<br />
import android.os.Message;<br />
import android.util.Log;<br />
import android.view.Gravity;<br />
import android.view.Menu;<br />
import android.view.MenuInflater;<br />
import android.view.MenuItem;<br />
import android.view.View;<br />
import android.view.ViewGroup;<br />
import android.widget.Button;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
import android.view.View.OnClickListener;</p>
<p>public class TankControl extends Activity implements OnClickListener {</p>
<p>private static final String TAG = &#8220;TankControl&#8221;;<br />
private static final boolean D = false;</p>
<p>// Message types sent from the BluetoothChartService Handler<br />
public static final int MESSAGE_STATE_CHANGE = 1;<br />
public static final int MESSAGE_READ = 2;<br />
public static final int MESSAGE_DEVICE_NAME = 4;<br />
public static final int MESSAGE_TOAST = 5;</p>
<p>// Key names received from the BluetoothChartService Handler<br />
public static final String DEVICE_NAME = &#8220;device_name&#8221;;<br />
public static final String TOAST = &#8220;toast&#8221;;</p>
<p>// Name of the connected device<br />
private String mConnectedDeviceName = null;</p>
<p>// Intent request codes<br />
private static final int REQUEST_CONNECT_DEVICE = 1;<br />
private static final int REQUEST_ENABLE_BT = 2;</p>
<p>// Local Bletooth adapetr<br />
private BluetoothAdapter mBluetoothAdapter = null;<br />
// Member object for the chat services<br />
private SvrServer mSvcServer = null;</p>
<p>private TextView mStatus;</p>
<p>finish();<br />
/*<br />
// Called when the activity is first created.<br />
static final int[] BUTTONS = {<br />
R.id.ball,<br />
R.id.turrent_left,<br />
R.id.turrent_stop,<br />
R.id.turrent_right,<br />
R.id.f_center,<br />
R.id.f_left,<br />
R.id.f_right,<br />
R.id.t_center,<br />
R.id.t_left,<br />
R.id.t_right,<br />
R.id.c_center,<br />
R.id.c_left,<br />
R.id.c_right,<br />
R.id.gun_up,<br />
R.id.gun_dn,<br />
R.id.gun_stop<br />
};<br />
*/<br />
int ball_f = 0;<br />
TextView _out1 = null;<br />
TextView _out2 = null;<br />
TextView _out3 = null;</p>
<p>@Override<br />
public void onCreate(Bundle savedInstanceState) {</p>
<p>// TODO Auto-generated method stub<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.tankcontrol);<br />
setOnClickListener((ViewGroup)findViewById(R.id.tblButtons));</p>
<p>mStatus = (TextView)findViewById(R.id.txtStatus);</p>
<p>mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();</p>
<p>if( mBluetoothAdapter == null){<br />
Toast.makeText(this, &#8220;Bluetooth is not available&#8221;, Toast.LENGTH_SHORT).show();<br />
finish();<br />
return;<br />
}</p>
<p>_out1 = (TextView)findViewById(R.id.text1);<br />
_out2 = (TextView)findViewById(R.id.text2);<br />
_out3 = (TextView)findViewById(R.id.text3);</p>
<p>_out1.setText(&#8220;Hello&#8221;);<br />
_out1.setBackgroundColor(0xFFFFFF00);<br />
_out1.setGravity(Gravity.CENTER);</p>
<p>_out2.setText(&#8220;멈춤&#8221;);<br />
_out2.setBackgroundColor(0xFFFF00FF);<br />
_out2.setGravity(Gravity.CENTER);</p>
<p>_out3.setText(&#8220;멈춤&#8221;);<br />
_out3.setBackgroundColor(0xFF00FFFF);<br />
_out3.setGravity(Gravity.CENTER);</p>
<p>}</p>
<p>@Override<br />
protected void onStart() {<br />
// TODO Auto-generated method stub<br />
super.onStart();<br />
/*<br />
if(D) Log.e(TAG,&#8221;++ ON START ++&#8221;);</p>
<p>if( !mBluetoothAdapter.isEnabled() ) {<br />
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);<br />
startActivityForResult(enableIntent, REQUEST_ENABLE_BT );<br />
}<br />
else {<br />
if(mSvcServer == null) {<br />
mSvcServer = new SvrServer(this, mHandler);<br />
}<br />
}<br />
*/<br />
}</p>
<p>@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
MenuInflater inflater = getMenuInflater();<br />
inflater.inflate(R.menu.option_menu, menu);<br />
return true;<br />
}<br />
@Override<br />
public boolean onOptionsItemSelected(MenuItem item) {<br />
switch(item.getItemId()){<br />
case R.id.scan :<br />
/*<br />
Intent serverIntent = new Intent(this, DeviceListActivity.class);<br />
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);<br />
*/</p>
<p>Intent serverIntent = new Intent(this, DeviceListActivity.class);<br />
startActivityForResult(serverIntent , REQUEST_CONNECT_DEVICE);<br />
return true;<br />
}<br />
return false;<br />
}<br />
@Override<br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
if(D) Log.d(TAG,&#8221;onActivityResult&#8221;+resultCode);</p>
<p>switch(requestCode){<br />
case REQUEST_CONNECT_DEVICE :<br />
if(resultCode == Activity.RESULT_OK){<br />
String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);<br />
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);<br />
mSvcServer.connect(device);<br />
}<br />
break;<br />
case REQUEST_ENABLE_BT :<br />
if(resultCode == Activity.RESULT_OK){<br />
if(mSvcServer == null) {<br />
mSvcServer = new SvrServer(this, mHandler);<br />
}<br />
}<br />
else {<br />
Log.d(TAG,&#8221;BT not enable&#8221;);<br />
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();<br />
finish();<br />
}<br />
break;<br />
}<br />
}</p>
<p>public void onInit(int status) {<br />
if(D) Log.d(TAG, &#8220;onInit&#8221;);<br />
}</p>
<p>private View[] getChildViews(ViewGroup group){<br />
int childCount = group.getChildCount();<br />
final View[] childViews = new View[childCount];<br />
for(int index = 0; index &lt; childCount; index++) {<br />
childViews[index] = group.getChildAt(index);<br />
}<br />
return childViews;<br />
}</p>
<p>private void setOnClickListener(ViewGroup group){<br />
View[] childViews = getChildViews(group);<br />
for(View view:childViews){<br />
if(view instanceof Button) {<br />
view.setOnClickListener(this);<br />
}<br />
else if(view instanceof ViewGroup) {<br />
setOnClickListener((ViewGroup) view);<br />
}<br />
}<br />
}</p>
<p>private int sendToQue(String data){<br />
if(mSvcServer.getState() != SvrServer.STATE_CONNECTED) {<br />
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();<br />
return -1;<br />
}<br />
return mSvcServer.toQue(data);<br />
}</p>
<p>private final Handler mHandler = new Handler() {<br />
@Override<br />
public void handleMessage(Message msg) {<br />
switch (msg.what) {<br />
case MESSAGE_STATE_CHANGE:<br />
if (D)<br />
Log.i(TAG, &#8220;MESSAGE_STATE_CHANGE: &#8221; + msg.arg1);<br />
switch (msg.arg1) {<br />
case SvrServer.STATE_CONNECTED:<br />
mStatus.setText(R.string.status_connected_to);<br />
mStatus.append(mConnectedDeviceName);<br />
break;<br />
case SvrServer.STATE_CONNECTING:<br />
mStatus.setText(R.string.status_connecting);<br />
break;<br />
case SvrServer.STATE_LISTEN:<br />
case SvrServer.STATE_NONE:<br />
mStatus.setText(R.string.status_not_connected);<br />
break;<br />
}<br />
break;<br />
// TODO: remove MESSAGE_READ<br />
case MESSAGE_READ:<br />
byte[] readBuf = (byte[]) msg.obj;<br />
// construct a string from the valid bytes in the buffer<br />
String readMessage = new String(readBuf, 0, msg.arg1);<br />
// mConversationArrayAdapter.add(mConnectedDeviceName+&#8221;: &#8221; +<br />
// readMessage);<br />
break;<br />
case MESSAGE_DEVICE_NAME:<br />
// save the connected device&#8217;s name<br />
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);<br />
Toast.makeText(getApplicationContext(),<br />
&#8220;Connected to &#8221; + mConnectedDeviceName,<br />
Toast.LENGTH_SHORT).show();<br />
break;<br />
case MESSAGE_TOAST:<br />
Toast.makeText(getApplicationContext(),<br />
msg.getData().getString(TOAST), Toast.LENGTH_SHORT)<br />
.show();<br />
break;<br />
}<br />
}<br />
};</p>
<p>public void gun_text()<br />
{<br />
Button b_up = (Button)findViewById(R.id.gun_up);<br />
Button b_dn = (Button)findViewById(R.id.gun_dn);<br />
Button b_st = (Button)findViewById(R.id.gun_stop);<br />
b_up.setText(&#8220;포신 UP&#8221;);<br />
b_dn.setText(&#8220;포신 DN&#8221;);<br />
b_st.setText(&#8220;포멈춤&#8221;);<br />
}</p>
<p>public void turrent_text()<br />
{<br />
Button b_up = (Button)findViewById(R.id.turrent_left);<br />
Button b_dn = (Button)findViewById(R.id.turrent_right);<br />
Button b_st = (Button)findViewById(R.id.turrent_stop);<br />
b_up.setText(&#8220;포탑_좌&#8221;);<br />
b_dn.setText(&#8220;포탑_우&#8221;);<br />
b_st.setText(&#8220;포탑멈춤&#8221;);<br />
}<br />
public void move_text()<br />
{<br />
Button b1_1 = (Button)findViewById(R.id.f_left);<br />
Button b1_2 = (Button)findViewById(R.id.f_center);<br />
Button b1_3 = (Button)findViewById(R.id.f_right);<br />
b1_1.setText(&#8220;전_좌&#8221;);<br />
b1_2.setText(&#8220;전_전&#8221;);<br />
b1_3.setText(&#8220;전_우&#8221;);<br />
Button b2_1 = (Button)findViewById(R.id.c_left);<br />
Button b2_2 = (Button)findViewById(R.id.c_center);<br />
Button b2_3 = (Button)findViewById(R.id.c_right);<br />
b2_1.setText(&#8220;좌_좌&#8221;);<br />
b2_2.setText(&#8220;멈춤&#8221;);<br />
b2_3.setText(&#8220;우_우&#8221;);<br />
Button b3_1 = (Button)findViewById(R.id.t_left);<br />
Button b3_2 = (Button)findViewById(R.id.t_center);<br />
Button b3_3 = (Button)findViewById(R.id.t_right);<br />
b3_1.setText(&#8220;후_좌&#8221;);<br />
b3_2.setText(&#8220;후_후&#8221;);<br />
b3_3.setText(&#8220;후_우&#8221;);<br />
}</p>
<p>@Override<br />
public void onClick(View v){<br />
if(v instanceof Button) {<br />
int btn_id = v.getId();<br />
Button btn = (Button)findViewById( btn_id );<br />
switch ( btn_id ) {<br />
case R.id.ball :<br />
if( ball_f == 0 ) {<br />
if(sendToQue(&#8220;A&#8221;)==0) {<br />
btn.setText(&#8220;발사중(A)&#8221;);<br />
_out1.setText(&#8220;포 발사&#8221;);<br />
ball_f = 1;<br />
}<br />
}<br />
else {<br />
sendToQue(&#8220;B&#8221;);<br />
btn.setText(&#8220;발사대기(B)&#8221;);<br />
_out1.setText(&#8220;Hello&#8221;);<br />
ball_f = 0;<br />
}<br />
break;<br />
case R.id.gun_up :<br />
if(sendToQue(&#8220;C&#8221;) == 0) {<br />
gun_text();<br />
btn.setText(&#8220;..ing(C)&#8221;);<br />
_out1.setText(&#8220;포신 UP&#8221;);<br />
}<br />
break;<br />
case R.id.gun_dn :<br />
if(sendToQue(&#8220;E&#8221;) == 0) {<br />
gun_text();<br />
btn.setText(&#8220;..ing(E)&#8221;);<br />
_out1.setText(&#8220;포신 DOWN&#8221;);<br />
}<br />
break;<br />
case R.id.gun_stop :<br />
if(sendToQue(&#8220;D&#8221;) == 0) {<br />
gun_text();<br />
btn.setText(&#8220;STOP(D)&#8221;);<br />
_out1.setText(&#8220;포신 STOP&#8221;);<br />
}<br />
break;<br />
case R.id.turrent_left :<br />
if(sendToQue(&#8220;F&#8221;) == 0) {<br />
turrent_text();<br />
btn.setText(&#8220;..ing(F)&#8221;);<br />
_out2.setText(&#8220;좌&#8221;);<br />
}<br />
break;<br />
case R.id.turrent_right :<br />
if(sendToQue(&#8220;H&#8221;) == 0) {<br />
turrent_text();<br />
btn.setText(&#8220;..ing(H)&#8221;);<br />
_out2.setText(&#8220;우&#8221;);<br />
}<br />
break;<br />
case R.id.turrent_stop :<br />
if(sendToQue(&#8220;G&#8221;) == 0) {<br />
turrent_text();<br />
btn.setText(&#8220;STOP(G)&#8221;);<br />
_out2.setText(&#8220;멈춤&#8221;);<br />
}<br />
break;<br />
case R.id.f_left :<br />
if(sendToQue(&#8220;I&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(I)&#8221;);<br />
_out3.setText(&#8220;전_좌 &#8220;);<br />
}<br />
break;<br />
case R.id.f_center :<br />
if(sendToQue(&#8220;J&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(J)&#8221;);<br />
_out3.setText(&#8220;전_전 &#8220;);<br />
}<br />
break;<br />
case R.id.f_right :<br />
if(sendToQue(&#8220;K&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(K)&#8221;);<br />
_out3.setText(&#8220;전_우 &#8220;);<br />
}<br />
break;<br />
case R.id.c_left :<br />
if(sendToQue(&#8220;L&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(L)&#8221;);<br />
_out3.setText(&#8220;좌_좌 &#8220;);<br />
}<br />
break;<br />
case R.id.c_center :<br />
if(sendToQue(&#8220;M&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;STOP(M)&#8221;);<br />
_out3.setText(&#8220;멈춤&#8221;);<br />
}<br />
break;<br />
case R.id.c_right :<br />
if(sendToQue(&#8220;N&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(N)&#8221;);<br />
_out3.setText(&#8220;우_우 &#8220;);<br />
}<br />
break;<br />
case R.id.t_left :<br />
if(sendToQue(&#8220;O&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(O)&#8221;);<br />
_out3.setText(&#8220;후_좌 &#8220;);<br />
}<br />
break;<br />
case R.id.t_center :<br />
if(sendToQue(&#8220;P&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(P)&#8221;);<br />
_out3.setText(&#8220;후_후&#8221;);<br />
}<br />
break;<br />
case R.id.t_right :<br />
if(sendToQue(&#8220;Q&#8221;) == 0) {<br />
move_text();<br />
btn.setText(&#8220;..ing(Q)&#8221;);<br />
_out3.setText(&#8220;후_우 &#8220;);<br />
}<br />
break;<br />
}<br />
}<br />
}</p>
<p>}<br />
</div></div>
<p><strong><span style="color: #666699">Program : android측</span></strong><br />
<strong><span style="color: #666699">SvrServer.java</span></strong></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">SvrServer.java 소스보기</h3><div class="symple-toggle-container">
<p>package kr.sunejune;</p>
<p>import java.util.UUID;<br />
import java.io.IOException;<br />
import java.io.InputStream;<br />
import java.io.OutputStream;</p>
<p>import android.bluetooth.BluetoothAdapter;<br />
import android.bluetooth.BluetoothDevice;<br />
import android.bluetooth.BluetoothServerSocket;<br />
import android.bluetooth.BluetoothSocket;<br />
import android.content.Context;<br />
import android.os.Handler;<br />
import android.os.Bundle;<br />
import android.os.Message;<br />
import android.util.Log;</p>
<p>public class SvrServer {<br />
// Debug<br />
private static final String TAG = &#8220;SvrServer&#8221;;<br />
private static final boolean D = false;</p>
<p>// Name for the SDP record when creating server socket<br />
private static final String NAME =&#8221;TankCon&#8221;;</p>
<p>// Generic UUID for SPP<br />
private static final UUID MY_UUID = UUID.fromString(&#8220;00001101-0000-1000-8000-00805F9B34FB&#8221;);</p>
<p>private final BluetoothAdapter mAdapter;<br />
private final Handler mHandler;<br />
private AcceptThread mAccepThread;<br />
private ConnectThread mConnectThread;<br />
private ConnectedThread mConnectedThread;<br />
private int mState;</p>
<p>// Constants that indicate the current connection state<br />
public static final int STATE_NONE = 0;<br />
public static final int STATE_LISTEN = 1;<br />
public static final int STATE_CONNECTING = 2;<br />
public static final int STATE_CONNECTED = 3;</p>
<p>public SvrServer(Context context, Handler handler) {<br />
mAdapter = BluetoothAdapter.getDefaultAdapter();<br />
mState = STATE_NONE;<br />
mHandler = handler;<br />
}</p>
<p>private synchronized void setState(int state) {<br />
if( D ) Log.d(TAG, &#8220;setState()&#8221;+mState+&#8221;==&gt;&#8221;+state);<br />
mState = state;</p>
<p>mHandler.obtainMessage(TankControl.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();<br />
}</p>
<p>public synchronized int getState() {<br />
return mState;<br />
}</p>
<p>public synchronized void start() {<br />
if(D) Log.d(TAG, &#8220;start&#8221; );<br />
if(mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; }<br />
if(mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; }<br />
if(mAccepThread == null) { mAccepThread = new AcceptThread(); mAccepThread.start(); }<br />
setState(STATE_LISTEN);<br />
}</p>
<p>public synchronized void connect(BluetoothDevice device){<br />
if(D) Log.d(TAG,&#8221;connect to:&#8221; + device);</p>
<p>if(mState == STATE_CONNECTING) {<br />
if(mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; }<br />
}</p>
<p>if(mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; }</p>
<p>mConnectThread = new ConnectThread(device);<br />
mConnectThread.start();<br />
setState(STATE_CONNECTING);<br />
}</p>
<p>public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {<br />
if(D) Log.d(TAG, &#8220;connected&#8221;);</p>
<p>if(mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; }<br />
if(mConnectedThread != null) { mConnectedThread.cancel(); mConnectThread = null; }<br />
if(mAccepThread != null) { mAccepThread.cancel(); mAccepThread = null; }</p>
<p>mConnectedThread = new ConnectedThread(socket);<br />
mConnectedThread.start();</p>
<p>Message msg = mHandler.obtainMessage( TankControl.MESSAGE_DEVICE_NAME );<br />
Bundle bundle = new Bundle();<br />
bundle.putString( TankControl.DEVICE_NAME, device.getName() );<br />
msg.setData(bundle);<br />
mHandler.sendMessage(msg);</p>
<p>setState(STATE_CONNECTED);</p>
<p>}</p>
<p>public synchronized void stop() {<br />
if(D) Log.d(TAG,&#8221;stop&#8221;);<br />
if(mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; }<br />
if(mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; }<br />
if(mAccepThread != null) { mAccepThread.cancel(); mAccepThread = null; }<br />
setState(STATE_NONE);<br />
}</p>
<p>public int toQue(String data) {<br />
ConnectedThread r; // temp<br />
synchronized(this) {<br />
if(mState != STATE_CONNECTED ) return -1;<br />
r = mConnectedThread;<br />
}<br />
return r.toQue(data);<br />
}</p>
<p>private void connectionFail() {<br />
if(D) Log.d(TAG,&#8221;connectionFail&#8221;);<br />
setState(STATE_LISTEN);</p>
<p>Message msg = mHandler.obtainMessage( TankControl.MESSAGE_TOAST );<br />
Bundle bundle = new Bundle();<br />
bundle.putString(TankControl.TOAST, &#8220;Unable to connect device&#8221;);<br />
msg.setData(bundle);<br />
mHandler.sendMessage(msg);<br />
}</p>
<p>private void connectionLost() {<br />
if(D) Log.d(TAG, &#8220;connectionLost&#8221;);<br />
setState(STATE_LISTEN);</p>
<p>Message msg = mHandler.obtainMessage(TankControl.MESSAGE_TOAST);<br />
Bundle bundle = new Bundle();<br />
bundle.putString(TankControl.TOAST, &#8220;Device connection was lost&#8221;);<br />
msg.setData(bundle);<br />
mHandler.sendMessage(msg);<br />
}<br />
private class AcceptThread extends Thread {<br />
private final BluetoothServerSocket mmServerSocket;</p>
<p>public AcceptThread() {<br />
BluetoothServerSocket tmp = null;</p>
<p>try {<br />
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);<br />
} catch ( IOException e ) {<br />
Log.e(TAG, &#8220;listen() failed&#8221;, e);<br />
}<br />
mmServerSocket = tmp;<br />
}</p>
<p>@Override<br />
public void run() {<br />
if(D) Log.d(TAG, &#8220;BEGIN mAcceptThread&#8221;+this);<br />
setName(&#8220;AcceptThread&#8221;);<br />
BluetoothSocket socket = null;</p>
<p>while( mState != STATE_CONNECTED ) {<br />
try {<br />
socket = mmServerSocket.accept();<br />
} catch (IOException e) {<br />
Log.e(TAG, &#8220;accept() failed&#8221;, e);<br />
break;<br />
}</p>
<p>if(socket != null) {<br />
synchronized ( SvrServer.this ) {<br />
switch(mState) {<br />
case STATE_LISTEN :<br />
case STATE_CONNECTING :<br />
connected(socket, socket.getRemoteDevice());<br />
break;<br />
case STATE_NONE :<br />
case STATE_CONNECTED :<br />
try {<br />
socket.close();<br />
}catch (IOException e) {<br />
Log.e(TAG,&#8221;Could not close unwanted socket&#8221;, e);<br />
}<br />
break;<br />
}<br />
}<br />
}<br />
}<br />
if(D) Log.d(TAG,&#8221;END mAcceptThread&#8221;);<br />
}</p>
<p>public void cancel() {<br />
if(D) Log.d(TAG,&#8221;cancel&#8221;+this);<br />
try {<br />
mmServerSocket.close();<br />
}catch(IOException e) {<br />
Log.e(TAG,&#8221;close() of server failed&#8221;,e);<br />
}<br />
}<br />
}</p>
<p>private class ConnectThread extends Thread {<br />
private final BluetoothSocket mmSocket;<br />
private final BluetoothDevice mmDevice;</p>
<p>public ConnectThread(BluetoothDevice device) {<br />
mmDevice = device;<br />
BluetoothSocket tmp = null;</p>
<p>try {<br />
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);<br />
}catch(IOException e) {<br />
Log.e(TAG,&#8221;create() failed&#8221;, e);<br />
}<br />
mmSocket = tmp;<br />
}</p>
<p>@Override<br />
public void run() {<br />
Log.i(TAG,&#8221;BEGIN ConnectThrtead&#8221;);<br />
setName(&#8220;ConnectThread&#8221;);</p>
<p>mAdapter.cancelDiscovery();</p>
<p>try{<br />
mmSocket.connect();<br />
}catch(IOException e1) {<br />
connectionFail();<br />
try {<br />
mmSocket.close();<br />
}catch (IOException e2) {<br />
Log.e(TAG,&#8221;unable to close() socket during connection failure&#8221;, e2);<br />
}<br />
SvrServer.this.start();<br />
return;<br />
}</p>
<p>synchronized ( SvrServer.this ) {<br />
mConnectThread = null;<br />
}</p>
<p>connected(mmSocket, mmDevice );<br />
}</p>
<p>public void cancel() {<br />
try {<br />
mmSocket.close();<br />
}catch(IOException e) {<br />
Log.e(TAG,&#8221;close() of connect socket failed&#8221;, e);<br />
}<br />
}<br />
}</p>
<p>private class ConnectedThread extends Thread {<br />
private final BluetoothSocket mmSocket;<br />
private final InputStream mmInStream;<br />
private final OutputStream mmOutStream;</p>
<p>public ConnectedThread(BluetoothSocket socket) {<br />
Log.d(TAG, &#8220;create ConnectedThread&#8221;);<br />
mmSocket = socket;<br />
InputStream tmpIn = null;<br />
OutputStream tmpOut = null;</p>
<p>// Get the BluetoothSocket input and output streams<br />
try {<br />
tmpIn = socket.getInputStream();<br />
tmpOut = socket.getOutputStream();<br />
} catch (IOException e) {<br />
Log.e(TAG, &#8220;temp sockets not created&#8221;, e);<br />
}</p>
<p>mmInStream = tmpIn;<br />
mmOutStream = tmpOut;<br />
}</p>
<p>@Override<br />
public void run() {<br />
Log.i(TAG, &#8220;BEGIN mConnectedThread&#8221;);<br />
byte[] buffer = new byte[1024];<br />
int bytes;</p>
<p>// Keep listening to the InputStream while connected<br />
while (true) {<br />
try {<br />
// Read from the InputStream<br />
// TODO: add dogkick!!<br />
bytes = mmInStream.read(buffer);</p>
<p>// Send the obtained bytes to the UI Activity<br />
mHandler.obtainMessage(TankControl.MESSAGE_READ, bytes, -1, buffer).sendToTarget();<br />
} catch (IOException e) {<br />
Log.e(TAG, &#8220;disconnected&#8221;, e);<br />
connectionLost();<br />
break;<br />
}<br />
}<br />
}</p>
<p>public int toQue(String in_data) {<br />
int ret = 0;<br />
try {<br />
String data = in_data;<br />
/*<br />
if (0 &lt; left) data += &#8216;F&#8217;;<br />
else if (0 &gt; left) {data += &#8216;B&#8217;; left = -left;}<br />
else data +=&#8217;H';<br />
if (0 &lt; right) data += &#8216;F&#8217;;<br />
else if (0 &gt; right) {data += &#8216;B&#8217;; right = -right;}<br />
else data +=&#8217;H';</p>
<p>if (left != 0) data += (char)(left&amp;0xff);<br />
if (right != 0) data += (char)(right&amp;0xff);<br />
*/<br />
mmOutStream.write(data.getBytes());<br />
ret = 0;<br />
} catch (IOException e) {<br />
Log.e(TAG, &#8220;Exception during write&#8221;, e);<br />
ret = -1;<br />
}<br />
return ret;<br />
}</p>
<p>public void cancel() {<br />
try {<br />
mmSocket.close();<br />
} catch (IOException e) {<br />
Log.e(TAG, &#8220;close() of connect socket failed&#8221;, e);<br />
}<br />
}</p>
<p>}</p>
<p>}<br />
</div></div>
<p><span style="color: #666699"><strong>Program : android측</strong></span><br />
<span style="color: #666699"><strong>DeviceListActivity.java</strong></span></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">DeviceListActivity.java 소스보기</h3><div class="symple-toggle-container">
<p>/*</p>
<p>* Copyright (C) 2009 The Android Open Source Project<br />
*<br />
* Licensed under the Apache License, Version 2.0 (the &#8220;License&#8221;);<br />
* you may not use this file except in compliance with the License.<br />
* You may obtain a copy of the License at<br />
*<br />
* http://www.apache.org/licenses/LICENSE-2.0<br />
*<br />
* Unless required by applicable law or agreed to in writing, software<br />
* distributed under the License is distributed on an &#8220;AS IS&#8221; BASIS,<br />
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<br />
* See the License for the specific language governing permissions and<br />
* limitations under the License.<br />
*/</p>
<p>package kr.sunejune;</p>
<p>import java.util.Set;</p>
<p>import android.app.Activity;<br />
import android.bluetooth.BluetoothAdapter;<br />
import android.bluetooth.BluetoothDevice;<br />
import android.content.BroadcastReceiver;<br />
import android.content.Context;<br />
import android.content.Intent;<br />
import android.content.IntentFilter;<br />
import android.os.Bundle;<br />
import android.util.Log;<br />
import android.view.View;<br />
import android.view.Window;<br />
import android.view.View.OnClickListener;<br />
import android.widget.AdapterView;<br />
import android.widget.ArrayAdapter;<br />
import android.widget.Button;<br />
import android.widget.ListView;<br />
import android.widget.TextView;<br />
import android.widget.AdapterView.OnItemClickListener;</p>
<p>/**<br />
* This Activity appears as a dialog. It lists any paired devices and<br />
* devices detected in the area after discovery. When a device is chosen<br />
* by the user, the MAC address of the device is sent back to the parent<br />
* Activity in the result Intent.<br />
*/<br />
public class DeviceListActivity extends Activity {<br />
// Debugging<br />
private static final String TAG = &#8220;DeviceListActivity&#8221;;<br />
private static final boolean D = false;</p>
<p>// Return Intent extra<br />
public static String EXTRA_DEVICE_ADDRESS = &#8220;device_address&#8221;;</p>
<p>// Member fields<br />
private BluetoothAdapter mBtAdapter;<br />
private ArrayAdapter&lt;String&gt; mPairedDevicesArrayAdapter;<br />
private ArrayAdapter&lt;String&gt; mNewDevicesArrayAdapter;</p>
<p>@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);</p>
<p>// Setup the window<br />
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);<br />
setContentView(R.layout.device_list);</p>
<p>// Set result CANCELED incase the user backs out<br />
setResult(Activity.RESULT_CANCELED);</p>
<p>// Initialize the button to perform device discovery<br />
Button scanButton = (Button) findViewById(R.id.button_scan);<br />
scanButton.setOnClickListener(new OnClickListener() {<br />
public void onClick(View v) {<br />
doDiscovery();<br />
v.setVisibility(View.GONE);<br />
}<br />
});</p>
<p>// Initialize array adapters. One for already paired devices and<br />
// one for newly discovered devices<br />
mPairedDevicesArrayAdapter = new ArrayAdapter&lt;String&gt;(this, R.layout.device_name);<br />
mNewDevicesArrayAdapter = new ArrayAdapter&lt;String&gt;(this, R.layout.device_name);</p>
<p>// Find and set up the ListView for paired devices<br />
ListView pairedListView = (ListView) findViewById(R.id.paired_devices);<br />
pairedListView.setAdapter(mPairedDevicesArrayAdapter);<br />
pairedListView.setOnItemClickListener(mDeviceClickListener);</p>
<p>// Find and set up the ListView for newly discovered devices<br />
ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);<br />
newDevicesListView.setAdapter(mNewDevicesArrayAdapter);<br />
newDevicesListView.setOnItemClickListener(mDeviceClickListener);</p>
<p>// Register for broadcasts when a device is discovered<br />
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);<br />
this.registerReceiver(mReceiver, filter);</p>
<p>// Register for broadcasts when discovery has finished<br />
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);<br />
this.registerReceiver(mReceiver, filter);</p>
<p>// Get the local Bluetooth adapter<br />
mBtAdapter = BluetoothAdapter.getDefaultAdapter();</p>
<p>// Get a set of currently paired devices<br />
Set&lt;BluetoothDevice&gt; pairedDevices = mBtAdapter.getBondedDevices();</p>
<p>// If there are paired devices, add each one to the ArrayAdapter<br />
if (pairedDevices.size() &gt; 0) {<br />
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);<br />
for (BluetoothDevice device : pairedDevices) {<br />
mPairedDevicesArrayAdapter.add(device.getName() + &#8220;\n&#8221; + device.getAddress());<br />
}<br />
} else {<br />
String noDevices = getResources().getText(R.string.none_paired).toString();<br />
mPairedDevicesArrayAdapter.add(noDevices);<br />
}<br />
}</p>
<p>@Override<br />
protected void onDestroy() {<br />
super.onDestroy();</p>
<p>// Make sure we&#8217;re not doing discovery anymore<br />
if (mBtAdapter != null) {<br />
mBtAdapter.cancelDiscovery();<br />
}</p>
<p>// Unregister broadcast listeners<br />
this.unregisterReceiver(mReceiver);<br />
}</p>
<p>/**<br />
* Start device discover with the BluetoothAdapter<br />
*/<br />
private void doDiscovery() {<br />
if (D) Log.d(TAG, &#8220;doDiscovery()&#8221;);</p>
<p>// Indicate scanning in the title<br />
setProgressBarIndeterminateVisibility(true);<br />
setTitle(R.string.scanning);</p>
<p>// Turn on sub-title for new devices<br />
findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);</p>
<p>// If we&#8217;re already discovering, stop it<br />
if (mBtAdapter.isDiscovering()) {<br />
mBtAdapter.cancelDiscovery();<br />
}</p>
<p>// Request discover from BluetoothAdapter<br />
mBtAdapter.startDiscovery();<br />
}</p>
<p>// The on-click listener for all devices in the ListViews<br />
private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {<br />
public void onItemClick(AdapterView&lt;?&gt; av, View v, int arg2, long arg3) {<br />
// Cancel discovery because it&#8217;s costly and we&#8217;re about to connect<br />
if (mBtAdapter.isDiscovering()) {<br />
mBtAdapter.cancelDiscovery();<br />
}</p>
<p>// Get the device MAC address, which is the last 17 chars in the View<br />
String info = ((TextView) v).getText().toString();<br />
String address = info.substring(info.length() &#8211; 17);</p>
<p>// Create the result Intent and include the MAC address<br />
Intent intent = new Intent();<br />
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);</p>
<p>// Set result and finish this Activity<br />
setResult(Activity.RESULT_OK, intent);<br />
finish();<br />
}<br />
};</p>
<p>// The BroadcastReceiver that listens for discovered devices and<br />
// changes the title when discovery is finished<br />
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {<br />
@Override<br />
public void onReceive(Context context, Intent intent) {<br />
String action = intent.getAction();</p>
<p>// When discovery finds a device<br />
if (BluetoothDevice.ACTION_FOUND.equals(action)) {<br />
// Get the BluetoothDevice object from the Intent<br />
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);<br />
// If it&#8217;s already paired, skip it, because it&#8217;s been listed already<br />
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {<br />
mNewDevicesArrayAdapter.add(device.getName() + &#8220;\n&#8221; + device.getAddress());<br />
}<br />
// When discovery is finished, change the Activity title<br />
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {<br />
setProgressBarIndeterminateVisibility(false);<br />
setTitle(R.string.select_device);<br />
if (mNewDevicesArrayAdapter.getCount() == 0) {<br />
String noDevices = getResources().getText(R.string.none_found).toString();<br />
mNewDevicesArrayAdapter.add(noDevices);<br />
}<br />
}<br />
}<br />
};</p>
<p>}<br />
</div></div>
<p><strong><span style="color: #33cccc">6. AVR 프로그램</span></strong><br />
<strong><span style="color: #666699">Program : ATTINY2313측</span></strong></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">Program : ATTINY2313측 소스보기</h3><div class="symple-toggle-container">
<p>/*</p>
<p><em id="__mceDel"> Project : USART TEST1<br />
tiny2313_uart1.c<br />
Date : 2008-05-23<br />
Company : AvrMall.com<br />
Chip type : ATtiny2313-10SI<br />
Clock : 12.000000 MHz<br />
Comment : ATTINY2313으로 UART송수신 테스트 프로그램<br />
Used with AVRSTUDIO V4.14 (WINAVR) .<br />
*/</em></p>
<p>#include &lt;avr/io.h&gt;</p>
<p>#define F_CPU 12000000UL // 16 MHz<br />
//#define F_CPU 14.7456E6<br />
//#include &lt;util/delay.h&gt;<br />
// Common Functions.<br />
void Delay_us(unsigned int time_us);<br />
void Delay_ms(unsigned int time_ms);</p>
<p>void USART_Init(void);<br />
void putchar_0(char data);<br />
void com_puts(char sbuf[]);<br />
void putchar_0(char data);<br />
int getchar_0(void);<br />
void cpu_setup(void);<br />
void Delay_us(unsigned int time_us)<br />
{<br />
unsigned int i;</p>
<p>for(i=0; i&lt;time_us; i++) // 4 cycle +<br />
{<br />
asm(&#8220;PUSH R0&#8243;); // 2 cycle +<br />
asm(&#8220;POP R0&#8243;); // 2 cycle +<br />
asm(&#8220;PUSH R0&#8243;); // 2 cycle +<br />
asm(&#8220;POP R0&#8243;); // 2 cycle + =12 cycle for 11.0592MHZ<br />
//asm(&#8220;PUSH R0&#8243;); // 2 cycle +<br />
//asm(&#8220;POP R0&#8243;); // 2 cycle = 16 cycle = 1us for 16MHz<br />
}<br />
}</p>
<p>void Delay_ms(unsigned int time_ms)<br />
{<br />
unsigned int i;</p>
<p>for(i=0; i&lt;time_ms;i++)<br />
Delay_us(1000);<br />
}<br />
void USART_Init(void)<br />
{<br />
// 9600Bps, 8Data, 1 Stop, No Parity<br />
UCSRA=0&#215;00;<br />
UCSRB=0&#215;18;<br />
UCSRC=0&#215;06;<br />
UBRRH=0&#215;00;<br />
UBRRL=0&#215;12;<br />
}<br />
// COM1 스트링 송신 //<br />
void com_puts(char sbuf[])<br />
{<br />
char ch;<br />
int i = 0;</p>
<p>ch = sbuf[i++]; // 전송할 데이터<br />
while(ch != 0){<br />
putchar_0(ch); // 1바이트 송신<br />
ch = sbuf[i++]; // 전송할 데이터<br />
}<br />
}</p>
<p>void putchar_0(char data)<br />
{<br />
/* Wait for empty transmit buffer */<br />
while (!((UCSRA) &amp; (1&lt;&lt;UDRE)));</p>
<p>/* Put data into buffer, sends the data */<br />
UDR = data;<br />
}</p>
<p>int getchar_0(void)<br />
{<br />
/* Wait for data to be received */<br />
while ( !(UCSRA &amp; (1&lt;&lt;RXC)) );</p>
<p>/* Get and return received data from buffer */<br />
return(UDR);<br />
}</p>
<p>void cpu_setup(void)<br />
{<br />
USART_Init();//USART 초기화<br />
DDRB = 0b01111111; // Port B IO mode : b7 (Input), b6-b0(Output)<br />
DDRD &amp;= 0b01111100; // Port B IO mode : d0-1 (UART), b6-b2(Output)<br />
}<br />
int main(void)<br />
{<br />
unsigned char cmd;<br />
unsigned char i_h=0;<br />
unsigned char i_t=0;<br />
unsigned char i_f=0;<br />
unsigned char i_u=0;</p>
<p>cpu_setup(); // cpu 초기화</p>
<p>com_puts(&#8220;\r\n&#8221;);<br />
com_puts(&#8220;- ATTINY2313 USART TEST -\r\n&#8221;);<br />
com_puts(&#8220;Press a or b \r\n&#8221;);</p>
<p>while(1)<br />
{<br />
cmd = getchar_0();//PC로부터 받은 값을 d에 저장한다.</p>
<p>switch (cmd) {<br />
case &#8216;i&#8217; :<br />
PORTB = 0b00000000;<br />
break;</p>
<p>// 전조등(h:4) / 후미등(t:5) , off(o)<br />
case &#8216;h&#8217; :<br />
case &#8216;R&#8217; :<br />
if(i_h == 1) {<br />
PORTB &amp;= 0b11001111;<br />
i_h=0;<br />
}<br />
else {<br />
PORTB |= 0b00010000;<br />
i_h=1;<br />
}<br />
break;<br />
case &#8216;t&#8217; :<br />
case &#8216;S&#8217; :<br />
if(i_t == 0) {<br />
PORTB |= 0b00100000;<br />
i_t=1;<br />
}<br />
else {<br />
PORTB &amp;= 0b11001111;<br />
i_t=0;<br />
}<br />
break;</p>
<p>case &#8216;o&#8217; :<br />
case &#8216;T&#8217; :<br />
PORTB &amp;= 0b11001111;<br />
break;<br />
// 포탄 발사(f:3:A) off(w:B)<br />
case &#8216;f&#8217; :<br />
case &#8216;A&#8217; :<br />
if(i_f == 0) {<br />
PORTB |= 0b00001000;<br />
i_f=1;<br />
}<br />
else {<br />
PORTB &amp;= 0b11110111;<br />
i_f=0;<br />
}<br />
break;<br />
case &#8216;B&#8217; :<br />
case &#8216;q&#8217; :<br />
PORTB &amp;= 0b11110111;<br />
break;<br />
// 포신 동작(u:2) off(c)<br />
case &#8216;u&#8217; :<br />
case &#8216;C&#8217; :<br />
PORTB |= 0b00000100;<br />
i_u=1;<br />
break;<br />
case &#8216;E&#8217; :<br />
PORTB &amp;= 0b11111011;<br />
i_u=0;<br />
break;<br />
case &#8216;c&#8217; :<br />
case &#8216;D&#8217; :<br />
PORTB &amp;= 0b11111011;<br />
break;</p>
<p>// 포탑 좌(l:0) 우(r:1) , off(m)<br />
case &#8216;l&#8217; :<br />
case &#8216;F&#8217; :<br />
PORTB &amp;= 0b11111100;<br />
PORTB |= 0b00000001;<br />
break;<br />
case &#8216;r&#8217; :<br />
case &#8216;H&#8217; :<br />
PORTB &amp;= 0b11111100;<br />
PORTB |= 0b00000010;<br />
break;<br />
case &#8216;m&#8217; :<br />
case &#8216;G&#8217; :<br />
PORTB &amp;= 0b11111100;<br />
break;</p>
<p>// 이동 전진(w:2-1,3-0 , 4-1,5-0) 후진(x:2-0,3-1 , 4-0,5-1)<br />
// 전좌(a:2-0,3-0 , 4-1,5-0) 전우(d:2-1,3-0 , 4-0,5-0) ,<br />
// 후좌(a:2-0,3-1 , 4-0,5-0) 후우(d:2-0,3-0 , 4-1,5-0) ,<br />
// off(s)<br />
case &#8216;O&#8217; : // 후좌<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01001000;<br />
break;<br />
case &#8216;Q&#8217; : // 후우<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01010000;<br />
break;<br />
case &#8216;w&#8217; :<br />
case &#8216;J&#8217; : // 전_전<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01010100;<br />
break;<br />
case &#8216;x&#8217; :<br />
case &#8216;P&#8217; : // 후_후<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01101000;<br />
break;<br />
case &#8216;a&#8217; :<br />
case &#8216;I&#8217; : // 전_좌<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01010000;<br />
break;<br />
case &#8216;d&#8217; :<br />
case &#8216;K&#8217; : // 전우<br />
PORTD &amp;= 0b10000011;<br />
PORTD |= 0b01000100;<br />
break;<br />
case &#8216;s&#8217; :<br />
case &#8216;M&#8217; : // 멈춤<br />
PORTD &amp;= 0b10000011;<br />
break;<br />
default :<br />
;<br />
// putchar_0(&#8216;c&#8217;);<br />
}<br />
Delay_ms(100);<br />
}<br />
}<br />
</div></div>
<p><strong><span style="color: #33cccc">7. 관련 회로도</span></strong></p>
<p><span style="color: #339966">7.1 전체 Block</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband06.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2074" alt="14ptband06" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband06-300x249.jpg" width="300" height="249" /></a><br />
<span style="color: #339966">7.2 ATTINY2313 Board V1.2 회로도</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband07.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2075" alt="14ptband07" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband07-300x224.jpg" width="300" height="224" /></a><br />
<span style="color: #339966">7.3 L293B : 전후진용 주 모터 (좌우, 정, 역 회전 : 양방향)</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband08.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2076" alt="14ptband08" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband08-300x95.jpg" width="300" height="95" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband09.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2077" alt="14ptband09" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband09-300x241.jpg" width="300" height="241" /></a><br />
<span style="color: #339966"> 7.4 LB1630 : 포탑 (정. 역 회전 : 양방향)</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband010.jpg" rel="lightbox[2049]"><img class="alignnone size-full wp-image-2078" alt="14ptband010" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband010.jpg" width="297" height="132" /></a><br />
<span style="color: #339966"> 7.5 ULN2803 : 포신, 포발사, 전조등, 후미등 (정회전:단방향)</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband011.jpg" rel="lightbox[2049]"><img class="alignnone size-full wp-image-2079" alt="14ptband011" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband011.jpg" width="231" height="205" /></a><br />
<span style="color: #339966"> 7.6 bluetooth : myBluetooh-EX 모듈</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband012.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2080" alt="14ptband012" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband012-300x100.jpg" width="300" height="100" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband013.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2081" alt="14ptband013" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband013-300x148.jpg" width="300" height="148" /></a><br />
<strong><span style="color: #33cccc">8. 완성</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband05.jpg" rel="lightbox[2049]"><img class="alignnone size-medium wp-image-2073" alt="14ptband05" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/14ptband05-300x114.jpg" width="300" height="114" /></a></p>
<p><strong><span style="color: #008000">소요비용</span></strong></p>
<p>탱크 : 75,000원<br />
Attiny2313 보드 : 11,000원<br />
제어 보드 제작 : 약 20,000원(손실까지)<br />
블루투스 모듈 : 26,300원<br />
전체 : 132,300원</p>
<p><strong><span style="color: #008000">참고 웹사이트</span></strong></p>
<p><strong>참고 Site</strong></p>
<p><a title="탱크조립보러가기" href="http://web.suapapa.net:8080/wordpress/?p=471" target="_blank">탱크 조립</a></p>
<p><a title="아두이노 모터 컨트롤 보드 만들기" href="http://web.suapapa.net:8080/wordpress/?p=473" target="_blank" rel="bookmark">아두이노 모터 컨트롤 보드 만들기</a></p>
<p><a title="아두이노+블루투스+안드로이드" href="http://web.suapapa.net:8080/wordpress/?p=474" target="_blank" rel="bookmark">아두이노+블루투스+안드로이드</a></p>
<p><a href="http://cafe.naver.com/carroty.cafe?iframe_url=/ArticleRead.nhn%3Fclubid=10750951%26page=1%26menuid=0%26inCafeSearch=true%26searchBy=1%26query=%C5%CA%C5%A9%26includeAll=%26exclude=%26include=%26exact=%26searchdate=all%26media=0%26sortBy=date%26articleid=130057%26referrerAllArticles=true" target="_blank"><strong>완성후 게시물</strong></a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/2049/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
