<?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; 11호</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/11%ed%98%b8/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>[11호]이벤트방식으로 구현하는 시퀀스 자동화 제어시스템</title>
		<link>http://www.ntrexgo.com/archives/5349</link>
		<comments>http://www.ntrexgo.com/archives/5349#comments</comments>
		<pubDate>Tue, 28 Feb 2012 06:56:59 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[스페셜 컬럼]]></category>
		<category><![CDATA[11호]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[쇼케이스]]></category>
		<category><![CDATA[시퀀스]]></category>
		<category><![CDATA[자동화]]></category>
		<category><![CDATA[제어시스템]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=5349</guid>
		<description><![CDATA[디바이스마트 매거진 11호 &#124; 본고에서는 제어시스템의 프로그래밍에 대한 여러가지 방식을 비교하고, 실제 생산라인에서 사용될 수 있는 자동 부품분류용 시퀀스 제어시스템을 구성하는 예제를 통하여 이벤트방식으로 제어프로그램을 작성하는 편리함을 살펴보겠습니다.]]></description>
				<content:encoded><![CDATA[<h2><a style="font-size: 1.5em;" href="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy22.jpg" rel="lightbox[5349]"><img class="alignleft" alt="" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy22.jpg" width="163" height="137" /></a></h2>
<h2><strong><span style="color: #666699;">이벤트방식으로 구현하는 </span></strong></h2>
<h2><span style="color: #666699;"><strong>시퀀스 자동화 제어시스템</strong><a href="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy22.jpg" rel="lightbox[5349]"><br />
</a></span></h2>
<p style="padding-left: 390px;">글 : 이지컨트롤 이중우 대표</p>
<p>&nbsp;</p>
<p><strong><span style="color: #800080;">■ 시작하면서&#8230;</span></strong></p>
<p>하나의 자동화 시스템을 구현하는 것은 생각보다 쉽지 않습니다. 일단 자동화 시스템을 구성하는 기계시스템에 대한 이해가 필요하고 기계시스템을 지능적으로 구동하기 위하여 전자적 제어시스템을 구성하여야 합니다. 그러나, 현대의 제어시스템은 기능적 가격적 장점으로 인하여 마이컴이 내장된 프로그램 가능한 제어시스템을 사용하는 경우가 대부분입니다. 현장 엔지니어들이 매우 어려워 하는 부분중 하나는 제어시스템을 동작하기 위한 제어용 프로그램을 작성하는 부분일 것입니다. 본고에서는 제어시스템의 프로그래밍에 대한 여러가지 방식을 비교하고, 실제 생산라인에서 사용될 수 있는 자동 부품분류용 시퀀스 제어시스템을 구성하는 예제를 통하여 이벤트방식으로 제어프로그램을 작성하는 편리함을 살펴보겠습니다.</p>
<p><strong style="font-size: 13px; line-height: 19px;"><span style="color: #800080;">■ 시퀀스 제어시스템</span></strong></p>
<p>아마도 현장에서 가장 많이 사용되고 있는 시퀀스 제어용 컨트롤러는 PLC일 것입니다. 그래서 자동화에 관련된 실무위주 교육을 하고 있는 이공계학과 중 상당수가 PLC를 사용하여 학생들에게 시퀀스제어를 실습하고 있습니다. 릴레이를 사용한 시퀀스 제어반을 대체하기 위하여 GM사에서 시작된 PLC는 단위기능을 가진 모듈들을 연결하여 큰 시스템을 구성할 수 있는 시스템 빌드업이 가능하고, 그래픽 심볼을 사용한 프로그래밍 방식인 래더다이어그램도 많은 단점에도 불구하고 간편한 사용법으로 인하여 널리 사용되고 있습니다.</p>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy004.png" rel="lightbox[5349]"><img class="alignnone size-full wp-image-5360" alt="11Showeasy004" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy004.png" width="156" height="140" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy005.png" rel="lightbox[5349]"><img class="alignnone size-medium wp-image-5361" alt="11Showeasy005" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy005-300x189.png" width="300" height="189" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy006.png" rel="lightbox[5349]"><img class="alignnone size-thumbnail wp-image-5362" alt="11Showeasy006" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy006-150x150.png" width="150" height="150" /></a></td>
</tr>
<tr>
<td style="text-align: center;">릴레이 제어반</td>
<td style="text-align: center;">PLC</td>
<td style="text-align: center;">래더다이어그램</td>
</tr>
</tbody>
</table>
<p>또한 우리나라에서는 보급이 느리지만 필드버스도 세계적으로는 많이 사용되고 있습니다. 대표적인 제품으로는 Profibus, ControlNet, WorldFip, P-Net, InterBus, Ethernet-IP, DeviceNet, CAN Open, CAN Kingdom, ADS-Net, FL-Net 등이 있습니다. 필드버스는 특히 CAN, RS-485, Ethernet 과 같은 통신을 이용하여 수Km의 장거리까지 모듈을 연결할 수 있어 생산현장 전체를 묶을 수 있는 장점이 있습니다.</p>
<p><strong><span style="color: #800080;">■ 실시간 OS, RTOS</span></strong></p>
<p>이러한 우수한 제어시스템들이 있음에도 불구하고 많은 엔지니어들은 마이컴이 장착된 보드에 커넥터를 연결하고 C언어로 프로그램을 작성하는 어려움(?)을 마다하지 않습니다. 그 이유는 아마도 PLC나 필드버스와 같은 제어시스템이 만족시킬 수 없는 가격과 성능 및 확장의 문제 등에서 찾아볼 수 있을 것입니다. 스위치 3개와 릴레이 2개를 동작시키기 위하여 PLC의 전원모듈, CPU모듈, 입력모듈, 릴레이모듈, 베이스모듈을 구입하는 것은 현실적이지 않기 때문입니다. 실제 PLC 응용의 80%는 이런 단순한 시퀀스제어를 위하여 사용된다고 하니 엄청난 손실이 아닐 수 없습니다. 그렇다고 기성품을 사용하는 대신 직접 실제로 마이컴에 프로그램을 작성하기 위하여는 여러가지 어려움을 감수해야만 합니다. 단순히 스위치와 릴레이의 온오프라면 그리 어렵지 않겠지만, 스위치가 온이 된 시간을 측정하기 위하여 타이머를 사용하고, 전압을 측정하기 위하여 A/D 변환을 하는 등의 문제는 개발자에게는 문제되지 않겠지만, 현장에서 즉시 적용해야하는 어플리케이션 엔지니어의 입장에서는 결코 간단한 문제가 아닙니다. 더욱이, 여러개의 작업을 동시에 구동해야 한다든가, 유지보수의 편의성도 갖추어야 한다면 단순히 C언어로 프로그램을 작성하는 수준을 벗어난 복잡한 작업이 될 수 있습니다. 그래서 엔지니어는 구현하고자 하는 문제를 단순화 시켜주고 유지보수도 간편하게 할 수 있을 것으로 기대하면서 RTOS(Real Time OS, 실시간OS)를 적용하는 것을 검토하기 시작합니다. 여기서는 필자가 경험한 내용을 위주로 기술하겠습니다. 매우 주관적인 판단일 수 있습니다. 누구나 그러하듯이 필자도 처음에는 C언어 만을 사용하여 프로그램을 작성하였습니다. 처음에는 그리 어려움이 없었습니다만, 프로그램이 복잡해 지면서 각 기능들 사이에 상호간섭이 발생하기 시작하면서 복잡도가 기하급수적으로 증가하여 한계에 달하였습니다. 그래서 RTOS의 적용을 검토하기 시작하였습니다. 실제 RTOS를 사용하면서 느낀점을 솔직하게 기술하면 다음과 같습니다.</p>
<p style="padding-left: 90px;">● 복잡한 작업을 여러 개의 단순한 태스크(Task, 실행단위)로 나누어 작성할 수 있어 구현의 복잡도가 줄어들어 편리했다. 태스크간의 전환속도가 빨라서 추가적 지연시간에 신경쓰지 않아도 된다.</p>
<p style="padding-left: 90px;">● 실시간OS란 하나의 태스크가 실행중에도 우선순위가 더 높은 태스크가 가로채어 실행할 수 있는 것이 가장 큰 특징이다. 그런데, 실제 응용에서 이런 실시간이 매우 중요한 경우는 그리 많지 않았다.</p>
<p style="padding-left: 90px;">● 세마포어, 동기화, 파이프, 이벤트, 시그널, 조건변수, 메시지큐, 뮤텍스 등등. 공부할 게 너무 많았다.</p>
<p style="padding-left: 90px;">● 우선순위 역전, 데드락 문제등은 언제 발생할지 예측하기도 어려웠다.</p>
<p style="padding-left: 90px;">● 사용하는 마이컴에 포팅해야 한다. 처음에는 애를 많이 먹는다.</p>
<p style="padding-left: 90px;">● 무엇보다도 PC에서 프로그래밍하는 이벤트방식과 달라서 새로 공부해야 한다.</p>
<p>물론 위와 같은 어려움에도 불구하고 핸드폰과 같은 복잡한 응용에서는 RTOS를 사용해야 하겠지만, 시퀀스제어를 하는 엔지니어에게 RTOS보다 간편한 방법은 없을까 고민을 하게 되었습니다.</p>
<p>&nbsp;</p>
<p><strong><span style="color: #800080;">■ 유한상태기계, FSM</span></strong></p>
<p>이후 필자는 UML 방법론에도 포함되어 있는 유한상태도(FSM, Finite State Machine)를 사용하여 임베디드 프로그램을 작성하는 방법론에 푹 빠져 몇년을 보냈습니다. (<a href="http://www.state-machine.com" target="_blank">http://www.state-machine.com</a> 참고)</p>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy007.png" rel="lightbox[5349]"><img class="alignnone size-large wp-image-5363" alt="11Showeasy007" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy007-620x242.png" width="620" height="242" /></a></td>
</tr>
<tr>
<td style="text-align: center;">시한폭탄의 상태도</td>
</tr>
</tbody>
</table>
<p>프로그램의 구조를 사각형으로 표현되는 상태(State)와 화살표로 표현되는 천이(Transition)라는 그림으로 나타낼 수 있다는 점이 너무나 매혹적이었습니다. 이것은 프로그램의 동작에 오류가 있는지를 검증하는 좋은 수단이 될 뿐만아니라 가장 좋은 문서화 수단이기도 하기 때문에 임베디드 프로그램을 작성하기에 매우 좋은 수단으로 생각되었습니다. 그래서 실제로 유한상태도를 동작시키는 OS를 직접 설계하고 구현하기도 하였습니다만 지금은 사용하지 않고 영구보관(?)중에 있습니다.</p>
<p style="padding-left: 90px;">● 프로그램을 상태로 나누므로 단순화 되고, 읽기 좋은 문서화 수단이 되었다.</p>
<p style="padding-left: 90px;">● 상태는 RTOS의 태스크와 비슷(?)한데, RTOS에서 태스크 간의 전환은 빠르게 이루어 지지만, FSM에서 상태간의 천이는 트리탐색의 문제가 되어 시간이 꽤 소요되었다.</p>
<p style="padding-left: 90px;">● 무엇보다 어려운 점은 구현하고자 하는 알고리즘을 상태도로 표현해야 하는데, 상태도를 해석하기는 매우 쉽지만, 작성하기는 결코 쉽지 않았다.</p>
<p><strong><span style="color: #800080;">■ 이벤트방식, Event Driven Programming</span></strong></p>
<p>위에서 언급한 바와 같은 여러 과정을 거쳐 현재 필자가 사용하는 방식은 이벤트 기반(Event Driven) 프로그래밍 방식을 사용하고 있습니다. PC에서 프로그램을 작성해 보신 분들은 누구나 이방식을 사용하여 아래와 같은 이벤트핸들러(이벤트 발생시 실행할 내용을 기술한 함수)를 작성한 경험이 있으리라 생각됩니다. void button_Click( object sender, EventArgs e ) { // 실행할 내용을 프로그램으로 작성한다. } 즉, button이 마우스에 의해 Click될 때 실행하고자 하는 내용을 여기에 작성하면 됩니다. 이때 마우스로 버튼을 클릭한 사건을 이벤트(Event)라 하고, 이벤트를 중심으로 프로그램을 작성하는 방식을 이벤트기반 프로그래밍이라 합니다. 이는 매우 직관적이고 이해하기 쉬워서 그래픽 기반(GUI)으로 동작하는 컴퓨터에서 사용하기에 매우 적합한 방식입니다.</p>
<p style="padding-left: 90px;">● 인간의 사고와 동일한 직관적 구조이므로 동작의 구현 및 이해가 매우 쉽다.예를 들면, SW1=ON 이벤트 발생시 RELAY1=ON으로 하라.</p>
<p style="padding-left: 90px;">● 복잡한 프로그램이 이벤트단위로 분해되어 구현하려는 문제가 단순화 된다.</p>
<p style="padding-left: 90px;">● PC에서와 동일한 방법을 사용하므로 일관성 있는 개발이 가능하고, 별도의 학습이 필요없이 즉시 적용할 수 있다.</p>
<p style="padding-left: 90px;">● 이벤트핸들러는 일종의 함수포인터이고 별도의 호출과정 없이 즉시 실행되므로, RTOS의 태스크전환이나 상태도의 천이속도에 비하여 빠른 실행이 가능하다.</p>
<p>이와 같은 매우 큰 장점이 있지만, 반면 단점도 있습니다.</p>
<p style="padding-left: 90px;">● 우선순위의 개념이 없으므로 이벤트핸들러에서 오랜동안 CPU를 점유하면, 긴급한 이벤트를 제때 처리하지 못하므로, 완전한 실시간성을 구현할 수는 없다.</p>
<p style="padding-left: 90px;">● 이벤트가 너무 자주 발생하면 성능이 저하될 수 있다.</p>
<p>즉, 이벤트핸들러에서 매우 복잡한 이미지 처리를 한다면, 긴급한 이벤트가 실행되지 못하고 대기하게 될 것이다. 대부분의 경우 시퀀스 제어시스템에서 그런 복잡한 처리를 할 일은 거의 없지만, 만일 그런 경우라면 이벤트 핸들러를 단순하게 작성하는 방법을 강구하는 것이 좋습니다. 그리고, 이벤트 발생횟수는 구현하고자 하는 내용에 따라서 매우 빈번할 수도 있습니다. 마우스 하나만 예로 들어도 마우스의 클릭, 더블클릭, 이동, 드래그 등등 매우 많은 이벤트가 있습니다. 고속 CPU를 사용하는 컴퓨터에서는 문제가 없지만, 대부분의 경우 저속 CPU를 사용하는 임베디드 시스템의 경우 컴퓨터에서 처럼 이벤트를 그대로 사용할 수는 없습니다. 그래서 이벤트 구조와 개념을 일부 변경하여 발생횟수를 최소화 하여 사용하고 있습니다.</p>
<p><strong><span style="color: #800080;">■ 이지컨트롤러</span></strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy003.png" rel="lightbox[5349]"><img class="alignnone" alt="11Showeasy003" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy003-428x620.png" width="173" height="250" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy008.png" rel="lightbox[5349]"><img class="alignnone size-medium wp-image-5364" alt="11Showeasy008" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy008-300x189.png" width="300" height="189" /></a></td>
</tr>
</tbody>
</table>
<p>이지컨트롤러의 하드웨어적인 구조는 PLC와 필드버스의 장점을 모방하였습니다. 각각의 모듈은 빌드업이 가능한 모듈러한 구조로 되어 있어 기능확장이 쉬우며, PLC의 베이스모듈을 저가의 플랫케이블로 대체하여 그림처럼 각 모듈의 20핀 버스커넥터를 연결합니다. 이 버스케이블에는 I2C 통신선이 있어 각 모듈을 1Mbps의 고속 통신으로 연결하고, 또한 5V, 24V, GND 전원선이 포함되어 있어서 각 모듈에 별도의 전원을 공급할 필요가 없습니다. 플랫케이블은 필드버스처럼 수킬로미터까지 확장할 수는 없지만, 수십미터까지 확장이 가능하여 그림처럼 쌓아서 배치할 수도 있고 펼칠 수도 있으며 먼 거리에 떨어져서 설치할 수도 있으므로 PLC에 비하여 설치가 매우 편리합니다.</p>
<p>전면의 IO 커넥터는 스크류타입으로 배선을 드라이버로 고정시켜 간편하게 연결할 수 있으며, DINKLE의 결합식 터미널블럭을 사용하여 모듈의 교체시에도 별도의 배선분리를 하지 않아도 되도록 하였으며, 후면에는 24핀 확장커넥터가 있어서 마이컴의 여분의 입출력 핀과 전원 및 통신선이 연결되어 있어 사용자의 회로를 추가하거나 프로그램 디버깅용으로 사용할 수 있도록 하였습니다. IO커넥터의 아래에는 동작표시 LED가 있어서 스위치나 릴레이 등의 IO가 동작하면 그 상태를 표시하므로 배선오류나 동작여부를 쉽게 확인할 수 있습니다. 각 모듈의 기본치수는 PCB기준 50x55mm로 매우 컴팩트하여 장치에 내장하기 적합하고, PCB지지대의 간격은 40mm로 50x50MM DC팬을 사용하면 PCB지지대에 고정할 수 있도록 맞추어져 있습니다. 각 모듈은 저전력 마이컴을 내장하여 릴레이구동과 같은 IO를 제외하면, LED도 저전력 타입을 사용하므로 모듈자체의 구동전력은 수mA 정도로 매우 작게 설계되어 배터리로 구동하거나 태양전지를 사용하는 경우도 사용이 가능하도록 하였습니다.</p>
<p>각 모듈은 내부 구성이 조금씩 차이가 있지만, 기본적인 구성은 비슷합니다. DIO모듈(Digital Input Output)의 경우 그림과 같이 IO커넥터, 버스커넥터, 확장커넥터가 있으며, LPC1114 ARM CORTEX-M0 32BIT 48MHz 마이컴을 사용하고 있으며, 내부에 EEPROM이 있어서 펌웨어를 새로 다운로드하지 않고도 모듈ID, 교정값등의 일부기능을 위한 설정을 변경할 수 있습니다.<br />
버스커넥터로부터 VAA=5V를 공급받아 내부로직을 위한 VCC=3.3V 전원으로 변경하며 VBB=24V를 공급받아 DC-DC에서 VDC=2~20V의 가변 전원을 생성하여 IO커넥터로 출력합니다. 특히 VDC는 스위치나 센서와 같은 외부 장치가 약간의 동작전원을 필요로 한다면 PLC처럼 별도의 외부전원을 설치하지 않아도 이 전원으로 대치할 수 있으므로 매우 편리하게 사용할 수 있습니다. 그외에 스위치, 릴레이, 모터, A/D, D/A 등과 같은 모듈별로 고유의 입출력 인터페이스 회로부로 구성되어 있습니다.</p>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy009.png" rel="lightbox[5349]"><img class="alignnone size-large wp-image-5365" alt="11Showeasy009" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy009-620x356.png" width="620" height="356" /></a></td>
</tr>
<tr>
<td style="text-align: center;">CoIDE 개발환경에서 ColinkEx SWD 디버거를 이용한 디버깅 화면</td>
</tr>
</tbody>
</table>
<p><strong style="font-size: 13px; line-height: 19px;"><span style="color: #800080;">■ 소프트웨어 개발환경</span></strong></p>
<p>이지컨트롤러의 개발환경은 www.CooCox.org에서 제공하는 무료개발툴인 CoIDE와 오픈소스 GCC를 이용하는데, 이클립스 기반이므로 매우 편리한 코드편집과 디버깅환경을 제공합니다. 이지컨트롤러의 소프트웨어 개발환경의 가장 큰 특징은 이벤트기반의 프로그래밍을 가능하도록 지원하는 EventBus라는 프레임워크 라이브러리 입니다. EventBus는 C/C# 두가지 버전으로 제공되는데, C 버전은 모듈에 펌웨어를 작성할 때 사용되는데, 이벤트기반 프로그래밍이 가능하도록 지원하고, 사용자가 여러 모듈을 I2C통신으로 연결하였다는 사실을 의식하지 않고 프로그램을 작성할 수 있도록 도와줍니다. 또한 C# 버전은 버스케이블로 연결된 모듈들을 컴퓨터에 연결할 때 사용되는데, C#으로 작성된 닷넷 라이브러리로써 USB 케이블을 통하여 컴퓨터와 모듈을 연결하면 닷넷 환경에서 모듈들을 제어하는 응용프로그램을 작성할 수 있도록 도와줍니다. 이를 이용하면 스위치, 릴레이, 전압등 모듈의 입출력을 읽어 화면에 표시하거나, 화면의 체크박스를 클릭하여 모듈의 릴레이를 동작시키는 것이 가능하고, 전압을 읽어 화면에 그래프로 표시하는 작업을 매우 간단하게 처리할 수 있습니다. 물론 EventBus 프레임워크를 사용하지 않고 기존의 방식처럼 프로그램을 작성할 수도 있습니다만, 생산성이 매우 차이가 나므로 반드시 EventBus 프레임워크를 사용하기를 권장합니다. 이지컨트롤러의 펌웨어는 EventBus + I/O Driver + Application 으로 구성됩니다. EventBus는 앞에서 언급하였듯이 이벤트기반 프로그래밍을 지원하고, 모듈과 모듈사이 그리고 모듈과 컴퓨터 사이의 연결을 담당하여 사용자가 마치 하나의 모듈에서 프로그램을 작성하는 것처럼 느끼도록 합니다. 그리고 I/O Driver는 순수 C코드로 하드웨어에 관련된 코드입니다. 기본적으로 소스가 제공되지만, 사용자의 고유한 기능을 구현하기 위하여 수정이 가능하도록 완전히 공개되어 있습니다. Application은 실제 구현하고자 하는 프로그램으로 마치 윈도우 폼 프로그램의 이벤트 핸들러와 매우 흡사하여 사용자는 PC에서 프로그램을 작성하는 느낌으로 거부감 없이 개발할 수 있습니다.</p>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy010.png" rel="lightbox[5349]"><img class="alignnone size-large wp-image-5366" alt="11Showeasy010" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy010-620x365.png" width="620" height="365" /></a></td>
</tr>
<tr>
<td style="text-align: center;">비주얼스튜디오에서 EventBus C# 프레임워크를 사용한 개발화면</td>
</tr>
</tbody>
</table>
<p><strong><span style="color: #800080;">■ 펌웨어 프로그래밍</span></strong></p>
<p>이지컨트롤러를 이용하여 그림과 같이 입고부품을 치수별로 분류하는 공장자동화용 시퀀스제어 시스템을 구현하겠습니다.</p>
<table style="border-collapse: collapse;" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy011.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5367" alt="11Showeasy011" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy011.png" width="215" height="170" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy012.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5368" alt="11Showeasy012" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy012.png" width="282" height="219" /></a></td>
</tr>
</tbody>
</table>
<p>시스템에는 컨베이어 벨트와 벨트를 구동하는 DC모터가 있으며, 모터를 온오프시켜 컨베이어 벨트를 회전/정지 시킬 수 있는 두개의 스위치가 있습니다. 그리고, 세개의 실린더와 각 실린더마다 부품의 높이를 검출하는 센서 S1, S2, S3가 있습니다. 오른쪽 시퀀스도는 센서 S1, S2, S3가 동작하면 릴레이 K1, K2, K3가 동작하고, 솔레노이드 밸브 1M, 2M, 3M에 전류가 공급되어 해당하는 공압밸브가 동작하여 실린더가 구동되도록 설계되어 있습니다. 도면에서는 센서 S1이 부품을 검출하였고 릴레이 K1을 통하여 솔레노이드 밸브 1M이 동작하였으며, 밸브에 연결된 High 실린더가 동작하였습니다. 가장 오른쪽에 설치된 센서 S1은 50mm, 가운데의 S2는 40mm, 왼쪽의 S3는 30mm의 높이에 설치되어 있어서, High 실린더는 50mm이상의 부품을 선택하고, Medium 실린더는 40mm ~ 50mm 사이의 부품을 선택하고, Low 실린더는 30mm ~ 40mm 사이의 부품을 선택합니다. 선택되지 않은 30mm 이하의 낮은 부품은 불량이므로 선택되지 않고 그대로 배출됩니다. 위의 릴레이로 구성된 시퀀스 제어시스템을 이지컨트롤러를 사용하여 구현하기 위하여 필요한 입출력으로 분류하면, 3개의 센서 입력을 위한 스위치 접점입력 3개, 솔레노이드 밸브를 구동하기 위한 릴레이 출력 3개, 컨베이어 벨트 구동용 DC모터를 위한 릴레이 출력 1개, 컨베이어 벨트를 온오프시키기 위한 버튼입력용 스위치 접점입력 2개가 필요합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy018.jpg" rel="lightbox[5349]"><img class="alignnone  wp-image-5382" alt="11Showeasy018" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy018-620x304.jpg" width="397" height="194" /></a></p>
<p>즉, 온오프 접점용 입력 5개와 릴레이 출력 4개가 필요하므로, 온오프 접점 10개를 입력받을 수 있는 DIM(Digital Input Module) 모듈과 릴레이 출력 6개를 내장한 DOM(Digital Output Module) 모듈을 사용하고, 전원공급을 위하여 PSM(Power Supply Module)모듈을 사용하여 시스템을 구성하였습니다.</p>
<p>DIM 모듈의 스위치 입력은 싱크(Sink) 타입이므로 외부에서 전류를 공급할 때 동작을 인식합니다. 그림에서 보듯이 DIM 모듈에는 VDC 가변출력전원(포텐쇼미터로 조정)이 내장되어 있으므로 PLC에서 처럼 외부전원이 없어도 센서에 편리하게 전원을 공급할 수 있습니다. 또한 싱크타입이므로 광전스위치의 PNP출력타입이 적합합니다. 요즘 시판되는 센서는 대부분 NPN, PNP를 선택할 수 있도록 선택스위치가 제공됩니다. 이경우 PNP로 선택해야 합니다.</p>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy002.png" rel="lightbox[5349]"><img class="alignnone size-large wp-image-5358" alt="11Showeasy002" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy002-620x192.png" width="620" height="192" /></a></td>
</tr>
<tr>
<td style="text-align: center;">PNP출력 광전스위치 회로와 DIM 모듈의 배선도</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy001.png" rel="lightbox[5349]"><img class="alignnone size-large wp-image-5357" alt="11Showeasy001" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy001-620x170.png" width="620" height="170" /></a></td>
</tr>
<tr>
<td style="text-align: center;">DOM 모듈의 배선도</td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy013.png" rel="lightbox[5349]"><img class="wp-image-5369 alignright" alt="11Showeasy013" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy013-224x620.png" width="134" height="372" /></a>솔레노이드와 DC모터는 수암페어 이상의 전류를 흘려야 하므로 VDC로는 전류용량이 부족하므로 외부에 SMPS를 추가하였습니다. 위와 같이 배선하면 하드웨어적인 시스템 구성은 완성되었습니다.</p>
<p>이제 프로그램을 개발할 개발환경을 설치해야 합니다. 이지컨트롤 카페(cafe.naver.com/easycontrol)를 방문하면 CoIDE를 설치하는 방법 및 EventBus 프레임워크를 다운로드할 수 있도록 자세한 설명이 있으므로, 지면 관계상 여기에서는 생략하도록 하겠습니다. CoIDE에서 컴파일을 마치면 프로그램을 모듈에 다운로드하고 디버깅하기 위하여 SWD 디버거인 ColinkEx를 사용합니다. ColinkEx에는 추가적으로 CP2102가 내장되어 있으므로 PC에서 가상 COM포트로 인식되어 디버깅 및 모듈-PC간 통신에 사용됩니다. 이지컨트롤러에서 모듈과 PC를 USB로 연결하는 방법은 ColinkEx의 COM포트, UUB모듈, USB모듈을 사용하는 3가지 입니다.</p>
<p>프로그램을 작성하기 위하여 별도의 프로젝트를 생성할 필요는 없습니다. 제공되는 예제를 복사해서 새로운 응용프로그램을 작성하면 됩니다. 각각의 모듈에는 미리 EventBus 프레임워크가 다운로드되어 있으므로 버스케이블만 연결하면 모든 모듈은 통신으로 연결된 상태가 됩니다. 이제 우리가 프로그램하고자 하는 모듈에만 프로그램을 작성하면 됩니다. 심지어 모듈은 그대로 두고 컴퓨터에서 응용프로그램만 작성하여도 동작시킬 수 있지만, 여기서는 모듈에서 동작하는 펌웨어를 작성하겠습니다. 어느 모듈에 프로그램을 작성해도 상관없지만, 우리는 DIM모듈은 그대로 두고 DOM모듈에 프로그램을 작성하겠습니다. 일반적으로 출력이 있는 모듈에서 프로그램을 작성하는 것이 여러모로 유리합니다.</p>
<p>Project 뷰에는 응용프로그램이 있는 Application 폴더, 하드웨어 구동을 위한 드라이버 프로그램이 있는 Driver 폴더, EventBus 프레임워크에 대한 헤더파일이 있는 EventBus 링크폴더가 있으며 여타의 설정파일들이 있습니다. EventBus 프레임워크는 라이브러리 형태로 제공되지만 사용자의 프로젝트에 필요한 모든 드라이버 파일의 소스가 완전히 제공되므로 구현이 매우 용이합니다.</p>
<p>Application\default에는 모듈 출고시 기본으로 다운로드된 프로그램의 소스파일이 있고, Application\exam에는 다양한 예제 프로그램이 제공됩니다. 우리가 작성할 응용프로그램을 저장하기 위하여 myproj 폴더를 생성하고 “dom_def.*”를 복사하여 “my_dom.*”로 이름을 변경합니다. Application 폴더에는 많은 응용프로그램이 있으므로 우리가 컴파일할 응용프로그램을 “ezconfig.h”에서 선택해 주어야 합니다. 응용프로그램의 헤더파일 “my_dom.h”을 인크루드시키면 새로 복사해서 만든 응용프로그램이 선택됩니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>ezconfig.h // 프로그램 선택 #include “my_dom.h”</td>
</tr>
</tbody>
</table>
<p>다음으로 선택된 “my_dom.h” 파일에서 DOM_DRV1 선언으로 드라이브 파일 “dom_drv1.c”을 선택하고, MY_DOM 선언으로 “my_dom.c”를 선택합니다. 이제 드라이버 파일은 “dom_drv1.c”, 어플리케이션 파일은 “my_dom.c”를 선택하였습니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Application\myproj\my_dom.h // select the Driver program #define DOM_DRV1// select the Application program<br />
#define MY_DOM// Set the ID of the module to reference<br />
typedef enum {<br />
GCALL = 0,<br />
THIS = 0,// module alias to reference<br />
ID_DIM1 = 3,// Do not change from here<br />
END_OF_MODULE,<br />
ID_PC = 120<br />
} EID;</td>
</tr>
</tbody>
</table>
<p>이제 “my_dom.c”를 수정하여 프로젝트를 완성하겠습니다. “#ifdef DOM_DEF”를 “#ifdef MY_DOM”으로 수정하면 코드는 활성화 되지만, F7키를 눌러 프로젝트를 빌드하면 에러가 발생합니다. 이유는 우리가 새로 생성한 Application\myproj 폴더를 등록하지 않았기 때문에 컴파일러가 파일의 위치를 찾지 못해서 발생하는 에러입니다. “build.xml” 파일을 열고 “Include paths”에서 “Add”를 선택하고 “Workspace”에서 우리가 추가한 “Application\myproj”를 선택합니다.<br />
이제 다시 F7키로 빌드하면 그림처럼 성공적으로 빌드가 됩니다. EventBus 프레임워크의 코드사이즈는 10KB도 채 되지 않는 매우 컴팩트한 사이즈입니다.</p>
<p><a style="font-size: 13px; line-height: 19px;" href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy014.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5370" alt="11Showeasy014" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy014.png" width="413" height="145" /></a></p>
<p>이제 컨베이어 벨트를 제어하는 시퀀스 프로그램을 작성하겠습니다. 코드와 주석만으로 충분히 이해할 수 있겠지만, 약간의 설명을 덧붙이겠습니다. DIM모듈의 스위치 입력상태를 읽어야 하므로 모듈을 선언하고 생성하였습니다. 이렇게 선언함으로써 이지컨트롤러의 여러 모듈들은 서로의 입출력 데이터를 읽고 쓸 수 있습니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Start_EventHandler, End_EventHandler는 이벤트핸들러의 앞,뒤에 위치하며, 이벤트 메시지루프의 시작과 종료에 관련된 처리를 하는 무한루프 매크로입니다. “eventbus.h”를 참고해 주십시오.</td>
</tr>
</tbody>
</table>
<p>프로젝트가 간단하므로 이벤트핸들러를 한개만 추가하였습니다. 즉, dim의 입력이 변하는 이벤트(IN_CHANGED)가 발생하면 실행할 내용을 기술합니다. Event( )는 매크로함수입니다. 스위치 상태를 릴레이에 대입하였으므로 센서가 부품을 감지하여 스위치 입력이 들어오면 릴레이도 동작하게 되고 실린더가 동작하게 됩니다. 컨베이어를 움직이는 DC모터는 Stop 버튼을 누르면 Start 버튼의 상태와 무관하게 무조건 정지하며, Start 버튼은 단독으로 눌러야만 회전합니다. 아무런 스위치도 누르지 않으면 이전 상태를 유지하게 됩니다.</p>
<table style="border-collapse: collapse;" width="600" border="1" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td align="center">Button_Start</td>
<td align="center">Button_Stop</td>
<td align="center">Conveyer</td>
</tr>
<tr>
<td align="center">OFF</td>
<td align="center">OFF</td>
<td align="center">이전상태 유지</td>
</tr>
<tr>
<td align="center">ON</td>
<td align="center">OFF</td>
<td align="center">ON, 회전</td>
</tr>
<tr>
<td align="center">OFF</td>
<td align="center">ON</td>
<td align="center">OFF, 정지</td>
</tr>
<tr>
<td align="center">ON</td>
<td align="center">ON</td>
<td align="center">OFF, 정지</td>
</tr>
</tbody>
</table>
<p>이제 펌웨어 작성을 마쳤습니다. 관심있게 보아야 할 부분은 펌웨어를 작성하는 과정에서 하드웨어적인 내용에 대하여는 전혀 언급하지 않았다는 점입니다. 펌웨어 작성에서 일반적으로 볼 수 있는 GPIO 초기화나 세팅등을 몰라도 펌웨어를 작성할 수 있다는 점입니다. 물론 그러한 드라이버 프로그래밍이 가능한 고급사용자들은 자신만의 기능을 추가적으로 구현할 수 있습니다. 펌웨어만으로도 시퀀스제어 시스템은 잘 동작합니다. 그러나, 컴퓨터에서 제어시스템의 동작을 모니터링 하거나 제어할 수 있다면 더욱 다양한 기능을 구현할 수 있을 것입니다.</p>
<p><strong><span style="color: #800080;">■ PC 응용프로그램</span></strong></p>
<p>Visual Studio 2008에서 C#으로 프로그램을 작성하도록 하겠습니다. 앞에서 언급하였듯이 EventBus_C# 버전 라이브러리를 사용하면 앞에서 구현한 모듈을 매우 쉽게 컴퓨터와 연결할 수 있습니다. 파일&gt;새로만들기&gt;프로젝트(Ctrl+Shift+N) 메뉴를 선택합니다. <a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy015.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5371" alt="11Showeasy015" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy015-620x341.png" width="372" height="205" /></a></p>
<p>프로젝트 이름을 MyProj 라고 입력합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy016.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5372" alt="11Showeasy016" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy016-620x264.png" width="372" height="158" /></a></p>
<p>참조추가에서 다운받은 EventBus_C# 라이브러리인 EventBus.DLL과 닷넷라이브러리인System.management를 추가합니다. 추가된 참조 EventBus를 더블클릭하면 개체브라우저가 열리는데 여기서 EventBus에서 지원하는 여러가지 클래스와 멤버들을 확인할 수 있습니다. <a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy017.png" rel="lightbox[5349]"><img class="alignnone  wp-image-5373" alt="11Showeasy017" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11Showeasy017.png" width="283" height="293" /></a></p>
<p>이제 폼에 연결된 장치에 해당하는 콤포넌트를 배치하겠습니다. 센서와 스위치는 입력장치이므로 사용자가 상태를 변경하는 것이 무의미하므로 Enabled 속성을 False로 합니다. 실제 센서 또는 스위치의 입력이 변하면 그 상태가 체크박스에 표시되도록 하겠습니다. 실린더와 컨베이어 모터는 출력장치이므로 펌웨어에서 이미 제어하고 있지만, 여기서도 체크박스를 클릭하면 실린더 또는 모터를 회전시킬 수 있도록 하겠습니다. 그래픽적으로 실제 실린더를 동작하도록 프로그램한다면 멋진 인터페이스를 구현할 수 있을 것입니다. 특히 산업용 모니터링 장치나 티칭패널의 경우 매우 유용한 인터페이스가 됩니다.</p>
<p>이제 코드를 작성하겠습니다. 메뉴에서 보기&gt;코드(Ctrl+Alt+0) 를 선택하고 코드를 입력합니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Form1.cs<br />
using System;<br />
using System.Collections.Generic;<br />
using System.ComponentModel;<br />
using System.Data;<br />
using System.Drawing;<br />
using System.Linq;<br />
using System.Text;<br />
using System.Windows.Forms;using EventBus; // EventBus 라이브러리 사용선언<br />
using System.Management; // 가상COM포트 자동인식에 필요namespace MyProj<br />
{<br />
public partial class Form1 : Form<br />
{<br />
Serial com; // 가상 COM포트<br />
CDIM dim; // DIM 모듈 이미지<br />
CDOM dom; // DOM 모듈 이미지<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
CheckForIllegalCrossThreadCalls = false;//크로스 스레드 검사 중지<br />
com = new Serial();<br />
dim = new CDIM((byte)EID.MyDim, com);<br />
dom = new CDOM((byte)EID.MyDom, com);<br />
}<br />
}public enum EID : byte<br />
{<br />
GCALL = 0,<br />
THIS = 0,// 어플에서 참조할 모듈 정의<br />
MyDim = 3, // DIM 모듈 ID<br />
MyDom = 5, // DOM 모듈 IDEND_OF_MODULE,<br />
PC = MType.PC<br />
}<br />
}</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>라이브러리를 선언하고, 통신연결을 위한 가상COM포트와 이벤트교환을 위하여 DIM, DOM모듈의 이미지도 선언하고 생성했습니다. 모듈의 ID는 편의상 enum 타입으로 선언 후 사용합니다. 여기서 선언한 ID는 펌웨어에서 사용한 ID와 동일해야 하고 또한 제공되는 ezconfig.exe EEPROM 설정용 프로그램을 이용하여 모듈마다 설정하는 ID와도 동일해야 합니다. 통신은 ID를 주소로 사용하므로 ID는 반드시 일치하도록 하여야 합니다.<br />
이제 이벤트가 발생하면 실행할 이벤트핸들러를 추가합니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Form1.cs<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
dim.Switch0.OnChanged +=<br />
new LogicEventHandler(Switch0_OnChanged);<br />
dim.Switch1.OnChanged +=<br />
new LogicEventHandler(Switch1_OnChanged);<br />
dim.Switch2.OnChanged +=<br />
new LogicEventHandler(Switch2_OnChanged);<br />
dim.Switch3.OnChanged +=<br />
new LogicEventHandler(Switch3_OnChanged);<br />
dim.Switch4.OnChanged +=<br />
new LogicEventHandler(Switch4_OnChanged);dom.Relay0.OnChanged +=<br />
new LogicEventHandler(Relay0_OnChanged);<br />
dom.Relay1.OnChanged +=<br />
new LogicEventHandler(Relay1_OnChanged);<br />
dom.Relay2.OnChanged +=<br />
new LogicEventHandler(Relay2_OnChanged);<br />
dom.Relay3.OnChanged +=<br />
new LogicEventHandler(Relay3_OnChanged);<br />
}void Relay3_OnChanged(object sender, CLogicEventArgs args) {<br />
DCMotor.Checked = args.Value;<br />
}void Relay2_OnChanged(object sender, CLogicEventArgs args) {<br />
CylinderLow.Checked = args.Value;<br />
}void Relay1_OnChanged(object sender, CLogicEventArgs args) {<br />
CylinderMedium.Checked = args.Value;<br />
}void Relay0_OnChanged(object sender, CLogicEventArgs args) {<br />
CylinderHigh.Checked = args.Value;<br />
}void Switch4_OnChanged(object sender, CLogicEventArgs args) {<br />
Start.Checked = args.Value;<br />
}void Switch3_OnChanged(object sender, CLogicEventArgs args) {<br />
Stop.Checked = args.Value;<br />
}void Switch2_OnChanged(object sender, CLogicEventArgs args) {<br />
SensorLow.Checked = args.Value;<br />
}void Switch1_OnChanged(object sender, CLogicEventArgs args) {<br />
SensorMedium.Checked = args.Value;<br />
}</p>
<p>void Switch0_OnChanged(object sender, CLogicEventArgs args) {<br />
SensorHigh.Checked = args.Value;<br />
}</td>
</tr>
</tbody>
</table>
<p>폼이 로드될 때 스위치와 릴레이의 OnChanged 이벤트에 이벤트핸들러를 등록합니다. 이벤트핸들러의 내용은 변경된 값을 화면에 표시하는 단순한 코드입니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Form1.cs<br />
string FindPortName()<br />
{<br />
ManagementObjectSearcher searcher =<br />
new ManagementObjectSearcher(“select * from Win32_SerialPort”);    // 시리얼포트를 검사해서 USB모듈이 연결된 포트를 찾는다.<br />
foreacㅋh (ManagementObject serial in searcher.Get()) {<br />
if (serial[“PNPDeviceID”].ToString().Contains(“5142308698”)) {<br />
return serial[“DeviceID”].ToString();<br />
}<br />
}<br />
return null;<br />
}private void Connect_Click(object sender, EventArgs e)<br />
{<br />
if (com.Connected) {<br />
com.Disconnect();<br />
Connect.Text = “Connect”;<br />
}<br />
else {<br />
string portname = FindPortName();<br />
bool connected = com.Connect(portname);<br />
if (connected) {<br />
Connect.Text = “Disconnect”;// 기존 이미지와 동기화 시킨다.<br />
dim.RequestSync();<br />
dom.RequestSync();<br />
}<br />
}<br />
}</td>
</tr>
</tbody>
</table>
<p>FindPortName 메서드는 연결된 가상COM포트를 자동으로 검색합니다. USB, UUB, ColinkEx모듈의 통신포트는 모두 CP2102를 채택하고 있는데 ROM에 “5142308698” 문자열을 포함하는 이름이 저장되어 있으므로 이를 이용하여 자동으로 포트명을 검색한 것입니다만, com.Connect(“COM5”); 처럼 사용자가 포트명을 직접 입력해도 됩니다. 실제로 WinCE에서는 management 라이브러리를 사용할 수 없으므로 이런 방법을 사용할 수 있습니다.<br />
RequestSync 메서드는 통신이 연결될 때 모듈의 실제 입출력상태와 다를 수 있으므로 모듈에게 입출력 데이터를 전송하도록 요청합니다. 전송받은 값이 이미지(dim, dom)에 저장된 값과 다르면 이벤트가 발생하고 위의 이벤트핸들러가 실행되므로 화면의 표시가 최근 상태로 갱신됩니다.</p>
<table width="550">
<tbody>
<tr bgcolor="#d9dbdb">
<td>Form1.cs<br />
private void CylinderHigh_CheckedChanged<br />
(object sender, EventArgs e) {<br />
dom.Relay0.Value = CylinderHigh.Checked;<br />
dom.Synchronize();<br />
}private void CylinderMedium_CheckedChanged<br />
(object sender, EventArgs e) {<br />
dom.Relay1.Value = CylinderMedium.Checked;<br />
dom.Synchronize();<br />
}private void CylinderLow_CheckedChanged<br />
(object sender, EventArgs e) {<br />
dom.Relay2.Value = CylinderLow.Checked;<br />
dom.Synchronize();<br />
}private void DCMotor_CheckedChanged<br />
(object sender, EventArgs e) {<br />
dom.Relay3.Value = DCMotor.Checked;<br />
dom.Synchronize();<br />
}</td>
</tr>
</tbody>
</table>
<p>마지막으로 폼에서 실린더와 컨베이어 DC모터의 체크박스를 클릭할 때 릴레이가 동작하도록 체크박스의 이벤트핸들러를 작성합니다. 체크박스를 더블클릭하면 자동으로 이벤트핸들러가 생성되고 이벤트에 등록하는 것은 비주얼스튜디오에서 자동으로 이루어 집니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy020.jpg" rel="lightbox[5349]"><img class="alignnone  wp-image-5521" alt="11Showeasy020" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy020.jpg" width="170" height="194" /></a></p>
<p>이제 모두 마쳤습니다. 실행하고 결과를 확인해 보겠습니다. 먼저 Start 스위치를 누르면 컨베이어는 회전합니다. 이때 Connect 버튼을 클릭하면 통신이 연결되고 dim.RequestSync(); dom.RequestSync(); 코드가 실행되어 모듈의 실제 상태와 체크박스 표시가 동기화 되는 것을 볼 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy021.jpg" rel="lightbox[5349]"><img class="alignnone  wp-image-5522" alt="11Showeasy021" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy021.jpg" width="170" height="194" /></a></p>
<p>High 센서가 높이가 높은 부품을 검출하고 실린더가 동작하는 것을 화면으로 확인할 수 있습니다. Start 스위치는 푸쉬버튼이므로 손을 떼면 OFF 되었습니다.</p>
<p><img alt="11Showeasy019" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11Showeasy019.jpg" width="172" height="196" /><br />
Medium 센서가 검출되지 않았지만, 화면에서 마우스로 Medium Cylinder의 체크박스를 클릭하여 강제로 실린더를 동작시켰습니다. 이 기능을 사용하면 장치의 고장을 점검할 때 매우 유용하게 활용할 수 있습니다.</p>
<p><strong><span style="color: #800080;">■ 마지막으로</span></strong></p>
<p>이제까지 시퀀스제어 시스템을 구현하기 위한 소프트웨어 개발방법에 대하여 살펴보고, 이벤트방식으로 구현하는 장점과 이지컨트롤사의 이지컨트롤러 범용제어기와 EventBus 프레임워크를 이용한 이벤트방식의 프로그램작성에 대하여 살펴보았습니다.</p>
<p>짧은 지면관계상 더욱 깊이있는 예제를 다루지는 못하였지만, 이외에도 시간을 제어하는 등의 더욱 다양한 이벤트와 사용자 정의 이벤트라는 막강한 기능을 제공합니다. 자세한 내용은 카페(cafe.naver.com/easycontrol)를 참고해 주십시오. 닷넷환경은 언어간 호환성이 있으므로 C++등의 언어를 사용한 개발도 가능하며, WinCE에서도 고급언어를 이용한 프로그램 개발이 가능하므로 티칭패널등에 사용하면 매우 빠르게 제품을 출시할 수 있을 것입니다.</p>
<p>다음에 기회가 된다면 좀더 유용한 내용으로 다시 뵙겠습니다. 끝까지 읽어주신 독자분들께 감사드립니다.</p>
<p>&nbsp;</p>
<p><span style="text-decoration: underline;"><strong><span style="color: #333333; text-decoration: underline;">* 본 글의 작성에 사용된 EventBus 프레임워크는 버전0.2 입니다.</span></strong></span></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/5349/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[11호]제2회 오픈팩토리</title>
		<link>http://www.ntrexgo.com/archives/5556</link>
		<comments>http://www.ntrexgo.com/archives/5556#comments</comments>
		<pubDate>Sat, 25 Feb 2012 08:50:47 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[핫 뉴스]]></category>
		<category><![CDATA[11호]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[엔티렉스]]></category>
		<category><![CDATA[오픈팩토리]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=5556</guid>
		<description><![CDATA[디바이스마트 매거진 11호 &#124; 오픈팩토리는 로봇산업협회에서 로봇산업에 종사하는 회원사들을 대상으로 로봇산업 활성화와 대기업, 중소기업 상호간 개방 협력 체제 구축을 도모하고, 공장 투어를 통해 해당 기업의 잠재력을 체험하는 목적의 행사로 9월 2일, LS메카피온㈜에 이어서 두번째로 진행되었다.]]></description>
				<content:encoded><![CDATA[<h3><span style="color: #0000ff"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen001.jpg" rel="lightbox[5556]"><img class=" wp-image-5554 alignleft" alt="11hotnopen001" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen001-300x162.jpg" width="240" height="130" /></a></span><span style="color: #3366ff">제2회 오픈팩토리</span></h3>
<h2><span style="color: #000080">&#8220;엔티렉스의 또 다른 자부심&#8221;</span></h2>
<p style="text-align: right">편집부 | press@ntrex.co.kr</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>엔티렉스는 지난 12월 12일, 로봇산업협회 회원사들을 대상으로 오픈팩토리 행사를 개최하였다. 오픈팩토리는 로봇산업협회에서 로봇산업에 종사하는 회원사들을 대상으로 로봇산업 활성화와 대기업, 중소기업 상호간 개방 협력 체제 구축을 도모하고, 공장 투어를 통해 해당 기업의 잠재력을 체험하는 목적의 행사로 9월 2일, LS메카피온㈜에 이어서 두번째로 진행되었다.</p>
<p>이번 행사는 엔티렉스의 신사옥 4층 대강당에서 진행되었으며, 행사 시간이 약간 이른 시간인데다가 기습 한파로 인하여, 초반에는 준비된 좌석의 빈자리가 많이 보였다. 그러나 행사가 중반을 지나면서 좌석이 부족할 정도로 성황리에 개최되었다.</p>
<table style="border-collapse: collapse" width="600" border="1" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen003.jpg" rel="lightbox[5556]"><img class="alignnone size-medium wp-image-5548" alt="11hotnopen003" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen003-300x199.jpg" width="300" height="199" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen005.jpg" rel="lightbox[5556]"><img class="alignnone size-medium wp-image-5550" alt="11hotnopen005" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen005-300x199.jpg" width="300" height="199" /></a></td>
</tr>
<tr>
<td style="text-align: center">행사를 시작하기 앞서 행사순서를 설명하고 있는 모습</td>
<td style="text-align: center">주행 테스트실에서 여러 주행 로봇을 시연하고 있다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen004.jpg" rel="lightbox[5556]"><img class="alignnone size-medium wp-image-5549" alt="11hotnopen004" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen004-300x199.jpg" width="300" height="199" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen006.jpg" rel="lightbox[5556]"><img class="alignnone size-medium wp-image-5551" alt="11hotnopen006" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen006-300x199.jpg" width="300" height="199" /></a></td>
</tr>
<tr>
<td style="text-align: center">로봇 전시실에서 판매 제품에 대해 설명하고 있다.</td>
<td style="text-align: center">메카넘 지게차에 대해 설명하는 모습</td>
</tr>
</tbody>
</table>
<p>행사는 로봇산업협회 정낙균 전무이사의 개회사를 시작으로, 엔티렉스 박경철 상무이사의 환영사, 엔티렉스 로봇연구소 민형기 연구소장의 프리젠테이션으로 이어졌다. 프리젠테이션 이후, 엔티렉스 로봇연구소와 물류센터를 견학하는 시간을 가졌다.</p>
<p>먼저 로봇연구소의 로봇 전시실에서는 엔티렉스의 메카넘 휠 관련 제품과 각종 주행 로봇 플랫폼들에 대하여 설명을 듣고, 별도로 주행 테스트실에서 여러 주행 로봇들을 시연하는 시간을 가졌다. 특히 참석자들은 메카넘 휠에 대한 엔티렉스의 기술력에 대하여 극찬을 아끼지 않았으며, 또한 스케이트 보드 로봇에 대해 높은 관심을 보였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen002.jpg" rel="lightbox[5556]"><img class="size-medium wp-image-5555 aligncenter" alt="11hotnopen002" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11hotnopen002-300x199.jpg" width="300" height="199" /></a></p>
<p>이어서 물류센터를 견학하는 과정에서 참석자들로부터 모범적인 수익 모델 및 유통 채널을 갖춘 회사라는 평가가 있었으며, 더불어 지식경제부 로봇산업과 박정성 과장은 &#8220;엔티렉스는 오픈팩토리에 가장 적합한 기업&#8221; 이라고 극찬하였다.</p>
<p>이번 행사를 통해 엔티렉스는 기존의 부품 및 소재 유통기업에서 로봇을 연구하는 기업이라는 이미지도 구축할 수 있었으며, 특히 로봇 업계에서 훌륭한 수익 모델을 가진 모범적인 기업이라는 인상을 남길 수 있었다.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/5556/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[11호]왜 두 개의 센서를 융합하는가?</title>
		<link>http://www.ntrexgo.com/archives/3930</link>
		<comments>http://www.ntrexgo.com/archives/3930#comments</comments>
		<pubDate>Sat, 25 Feb 2012 07:17:05 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[스페셜 컬럼]]></category>
		<category><![CDATA[11호]]></category>
		<category><![CDATA[pinkwink]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[상보필터]]></category>
		<category><![CDATA[융합]]></category>
		<category><![CDATA[컬럼]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=3930</guid>
		<description><![CDATA[디바이스마트 매거진 11호 &#124; 이번 기획은 두 센서를 융합해서 자세를 측정하는 방법 중 상보필터라는 것을 소개하고, 그 첫번째 시간대로 도대체 왜 센서를 융합할 수 밖에 없었는가에 대한 글을 적고자 한다. 각도를 측정하는 일반적인 방법과 센서들을 몇 개 나열하고  센서를 하나만 사용했을 때의 어려움에 대해 이야기하고자 한다.]]></description>
				<content:encoded><![CDATA[<h3><span style="color: #008000">상보필터 Part 1. </span></h3>
<h2><span style="color: #008000">왜 두 개의 센서를 융합하는가?</span></h2>
<p style="text-align: left">저자약력 : PinkWink.<br />
로봇의 실제 구현에 관련된 모든 것에 관심이 많으며, pinkwink.kr이라는 개인 블로그를 운영중.<br />
2011년부터 은둔 생활을 청산하고 (주)엔티렉스 로봇연구소의 연구소장으로 재직중.<br />
연재와 관련된 질문은 devicezine.co.kr에서 문의바랍니다.</p>
<p><span style="color: #008000"><strong>1. 들어가며</strong></span></p>
<p>저가의 MEMS형 센서를 사용해서 각도를 측정하는 많은 방법들이 소개되어있다. 실제로 인터넷을 조금만 찾아도 정말 많은 방법들이 소개되어 있음을 알 수 있다. 그 방법들에는 단순히 자이로 센서만 사용하는 방법에서부터 자이로 센서와 가속도 센서를 융합해서 사용하는 방법에까지 다양하게 나와있으며, 심지어 학습용으로 몇몇 대표적인 융합방법들을 예제로 제공하는 학습용 보드들도 디바이스마트(devicemart.co.kr)에 등록되어 있다.</p>
<p>자세 측정 자체에 관심이 없는 경우에는 이런 방법들을 그냥 가져다 쓰는 것이 당장의 문제를 해결하는 것에는 도움이 되겠으나, 만약 관련 부분에 대한 공부를 하는 경우에는 문제가 있다. 도대체 왜 각도 하나를 측정하자고 센서를 두 개나 사용해서 융합해야 하는가? 또, 왜 하필 그게 자이로 센서와 가속도 센서가 융합의 주류인가? 라는 의문을 자세 측정분야에 관심이 있다면 가져야 하지 않을까 생각한다.<br />
하긴 그렇다고 하더라도, 사실 어떻게 융합하는가에 대한 설명은 참으로 많지만, 왜? 융합하는가에 대한 설명은 상대적으로 그 분량이 작다. 그래서, 이번 기획은 두 센서를 융합해서 자세를 측정하는 방법 중 상보필터라는 것을 소개하고, 그 첫번째 시간대로 도대체 왜 센서를 융합할 수 밖에 없었는가에 대한 글을 적고자 한다. 각도를 측정하는 일반적인 방법과 센서들을 몇 개 나열하고 센서를 하나만 사용했을 때의 어려움에 대해 이야기하고자 한다.</p>
<p><strong><span style="color: #008000">2. 엔코더나 포텐셔미터를 이용한 자세 측정의 문제점</span></strong></p>
<p>엔코더나 포텐셔미터는 아마 가장 일반적으로 사용되는 각도 측정 장치일 것이다. 그러나 이와 같은 센서들은 고정점 대비 상대적인 각도를 측정한다. 그로 인해 공중에 떠 있거나, 혹은 고정빔을 설치할 수 없는 곳에서는 자세를 측정하는데 문제가 있다.</p>
<table align="center">
<tbody>
<tr>
<td>
<div id="attachment_3969" class="wp-caption alignnone" style="width: 375px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang001.jpg" rel="lightbox[3930]"><img class=" wp-image-3969   " alt="그림1. 포텐셔미터(좌)와 엔코더(우)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang001-620x254.jpg" width="365" height="150" /></a><p class="wp-caption-text">그림1. 포텐셔미터(좌)와 엔코더(우)</p></div></td>
<td>
<div id="attachment_3960" class="wp-caption alignnone" style="width: 168px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang003.jpg" rel="lightbox[3930]"><img class=" wp-image-3960    " alt="그림2. 엔코더나 포텐셔미터의 자세측정에서의 한계" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang003.jpg" width="158" height="144" /></a><p class="wp-caption-text">그림2. 엔코더나 포텐셔미터의 자세측정에서의 한계</p></div></td>
</tr>
</tbody>
</table>
<p>그림2에서 보다시피 좌측의 그림처럼 엔코더 자체를 고정하고, 엔코더의 축을 회전해야만 각도가 측정되는 것이기 때문에, 그림2의 우측처럼 고정점이 없으면, 정확한 각도를 측정하기 어려워진다.</p>
<p><span style="color: #008000"><strong>3. 자이로 센서를 이용한 방법의 한계</strong></span></p>
<p>자이로 센서 또한 자세 측정에 많이 사용된다. 그러나 여기서 다루는 것은 실제 항공기나 선박에 장착되는 고가의 장비가 아니라 겨우 몇 만원대의 MEMS형 저가 자이로 센서이다. 이런 저가의 자이로 센서는 역시 한계를 가지게 된다.</p>
<div id="attachment_3961" class="wp-caption aligncenter" style="width: 385px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang004.jpg" rel="lightbox[3930]"><img class=" wp-image-3961  " alt="그림3. 실험장비" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang004.jpg" width="375" height="241" /></a><p class="wp-caption-text">그림3. 실험장비</p></div>
<p>먼저 기억해야 할 것은 자이로 센서는 각도를 출력으로 가지지 않는다는 것이다. 자이로 센서는 그 구현 원리상 각속도를 출력으로 가진다. 그래서 각도를 구하기 위해서는 당연히 자이로의 출력인 각속도를 적분해서 각도로 변환할 필요가 있다. 여기서 바로 문제가 생기게 된다.<br />
먼저 본 글 전체에 사용될 실험을 위한 장비가 그림3에 나타나있다. 흔히 진자시스템(Pendulum System)이라고 부르는 장비로 본래 목적은 아니지만, 이번 실험에는 아주 적합한 장비이다. 여기에 자이로센서와 다음 장에서 다룰 가속도 센서를 미리 연결하고, 참값과의 비교를 위해 엔코더 또한 장착했다. 센서들의 부착위치는 암(Arm)과 진자(Pendulum)가 만나는 곳이다.<br />
먼저 자이로 센서의 정확도를 확인하기 위해 자이로의 출력값인 각속도와 그래도 참값이라고 믿을 수 있는 엔코더의 각도를 차분한 각속도를 비교해 본다.</p>
<div id="attachment_3962" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang005.jpg" rel="lightbox[3930]"><img class=" wp-image-3962 " alt="그림4. 자이로의 출력(각속도)과 엔코더의 출력을 차분한 값과의 비교" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang005-620x397.jpg" width="434" height="278" /></a><p class="wp-caption-text">그림4. 자이로의 출력(각속도)과 엔코더의 출력을 차분한 값과의 비교</p></div>
<p>그림4에서 보듯이 완전히 일치시킬 수는 없지만, 어느 정도는 자이로의 출력과 엔코더의 차분치를 일치 시켰다. 이제 이 상태에서 자이로의 출력인 각속도를 적분해서 각도를 확인해보자.</p>
<div id="attachment_3963" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang006.jpg" rel="lightbox[3930]"><img class=" wp-image-3963 " alt="그림 5. 자이로센서의 출력을 적분한 각도와 엔코더와의 비교" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang006-620x397.jpg" width="434" height="278" /></a><p class="wp-caption-text">그림 5. 자이로센서의 출력을 적분한 각도와 엔코더와의 비교</p></div>
<p>참값이라고 가정할 수 있는 엔코더의 차분치(물론 오차는 있지만)와 일치시키는 작업을 하고 난 후의 적분치이지만, 역시 한쪽으로 흐르는 현상이 있다. 이 드리프트(Drift)라고 부르는 적분 과정에서 생기는 오차는 적분이라는 과정을 수행하는 경우 항상 존재할 수 있는 상황이다. 아무리 온도보정을 많이 하고, 또 정교한 필터링을 한다고 해도, 결국 자이로 센서만 사용하는 경우는 어쩔 수 없이 나타나는 현상이다.<br />
자이로 센서의 출력이 각속도이고, 그래서 각도를 얻기 위해서는 어쩔 수 없이 적분이라는 과정을 거쳐야 한다. 그리고, 그림5에서 보듯이 자이로의 출력에서 미세한 오차가 있다면, 결국 그것이 누적되고 또 누적되면서 적분한 결과인 각도는 한 쪽으로 흐르게 되는 현상이 발생하고, 이것이 자이로 센서 하나만 사용해서 자세를 측정할 수 없는 한계가 된다.</p>
<p><strong><span style="color: #008000">4. 기울기 센서를 이용한 방법의 한계</span></strong></p>
<p>MEMS형 센서는 아니지만, 기울기 센서라는 것도 엄연히 존재한다. 너무 많은 종류의 기울기 센서들이 있기 때문에 역시 MEMS형 자이로 센서와 비슷한 가격대의 기울기 센서라고 한정짓도록 하자. 기울기 센서는 그럼 왜 안되는 걸까. 역시 그림3의 장비에서 자이로와 같은 위치에 기울기 센서를 장착하고 측정한 결과를 보자.</p>
<div id="attachment_3964" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang007.jpg" rel="lightbox[3930]"><img class=" wp-image-3964 " alt="그림6. 기울기센서의 결과" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang007-620x395.jpg" width="434" height="277" /></a><p class="wp-caption-text">그림6. 기울기센서의 결과</p></div>
<p>그림6에서 보이듯이 기울기센서도 이름처럼 그렇게 좋은 결과를 가져오지는 못한다. 기울기 센서는 일반적으로 유체성분이 센서 안에 밀폐되어있고, 적절한 점도를 가진 그 유체의 기울어지는 정도를 전압으로 환산해서 기울어진 각도를 측정하게 된다. 그런데 그릇에 물을 채워놓고 빠르게 기울이면, 유체는 신기하게도 가장 변화속도가 빠른 지점에서 물 자신이 기울어지는 속도보다 더 기울게 되는 현상이 있다. 이 현상이 기울기 센서에서도 발생하게 되는데, 그것이 그림6에 잘 나타나 있다.<br />
그래서 기울기 센서는 내부의 유체가 안정화되는 시간이 필요하다. 이게 바로 기울기 센서의 응답속도를 느리게 만드는 요인이 되며, 대략 몇 백 ms정도의 시간이 필요하다. 센서와 같은 장비를 처음 만지는 학생들의 경우 이 응답속도라는 단어를 혼돈하게 되는데, 응답속도가 100ms라는 것이 참 값이 100ms후에 나온다는 의미가 아님을 알아야한다. 저렇게 유체가 안정화되는데 시간이 필요한 경우 빠르게 움직여야하는 시스템이라면 제대로 된 자세 측정은 어렵다고 봐야한다.</p>
<p><span style="color: #008000"><strong>5. 가속도 센서를 이용한 방법의 한계</strong></span></p>
<p>이제 마지막으로 또 각도를 측정하는 센서 중에서 많이 사용되는 것 중에 가속도 센서가 있다. 가속도를 측정한다는 의미의 이름이 붙은 이 센서로 어떻게 각도를 측정하는가? 정답은 간단한 삼각함수에 있다.</p>
<div id="attachment_3965" class="wp-caption aligncenter" style="width: 282px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang008.jpg" rel="lightbox[3930]"><img class=" wp-image-3965 " alt="그림7. 가속도 센서에서 각도를 구하는 원리" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang008.jpg" width="272" height="295" /></a><p class="wp-caption-text">그림7. 가속도 센서에서 각도를 구하는 원리</p></div>
<p>한 면만 놓고 쉽게 설명을 하면, 그림7에서 보듯이 가속도 센서의 두 축의 값을 읽어서 간단히 Arctan를 이용하면,<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang011.jpg" rel="lightbox[3930]"><img class="size-full wp-image-3968 aligncenter" alt="11scsang011" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang011.jpg" width="159" height="84" /></a><br />
이렇게 각도를 구할 수 있다.<br />
이 간단한 방법은 사실 정말 편하고 유용하다. 자이로 센서처럼 적분으로 인한 오차의 누적현상이 없고, 기울기 센서처럼 느린 응답속도로 인한 문제도 없다. 그림3의 장비에서 암(Arm)을 고정하고 진자(Pendulum)만 움직여서 얻은 결과를 보자.</p>
<div id="attachment_3966" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang009.jpg" rel="lightbox[3930]"><img class=" wp-image-3966 " alt="그림8. 가속도 센서를 이용한 각도 측정" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang009-620x397.jpg" width="434" height="278" /></a><p class="wp-caption-text">그림8. 가속도 센서를 이용한 각도 측정</p></div>
<p>그림 8을 보면 정말 결과가 좋다는 것을 알 수 있다. 그럼 아주 손쉽게 각도- 즉 자세를 측정할 수 있을 것 같지만, 사실 그렇지 않다. 그림8의 결과를 얻은 실험은 암(Arm)을 고정했다. 이것이 가속도 센서의 한계인데,</p>
<div id="attachment_3967" class="wp-caption aligncenter" style="width: 369px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang010.jpg" rel="lightbox[3930]"><img class=" wp-image-3967 " alt="그림 9. 가속도 센서를 이용해 각도를 측정할 때의 문제점" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang010.jpg" width="359" height="317" /></a><p class="wp-caption-text">그림 9. 가속도 센서를 이용해 각도를 측정할 때의 문제점</p></div>
<p>바로 그림7처럼 회전 각도가 발생하는 그 중심에 가속도센서가 위치하지 못하고, 그림9처럼 회전 중심축에서 멀어져서 회전하는 경우 문제가 발생한다. 센서의 이름이 가속도 센서라는 사실에 주목해야 하는데, 그림9와 같은 상황에서는 접선, 법선 방향의 가속도 성분이 가속도 센서에 같이 인가가 되면서, 그림8과 같은 실험을 수행하게 되면 결과가 이상해진다.</p>
<div id="attachment_3959" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang002.jpg" rel="lightbox[3930]"><img class=" wp-image-3959 " alt="그림 10. 가속도 센서를 이용한 각도측정의 한계" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11scsang002-620x381.jpg" width="434" height="267" /></a><p class="wp-caption-text">그림 10. 가속도 센서를 이용한 각도측정의 한계</p></div>
<p>바로 그림10처럼 그 결과가 안좋아지게 된다. 이는 가속도 센서에 회전 각도를 검출하는데 필요한 성분에 더해서 접선, 법선 방향의 가속도 성분이 인가되면서 그렇게 된 것이다.</p>
<p><span style="color: #008000"><strong>6. 결론</strong></span></p>
<p>본 글에서 단일 센서만 사용했을 때, 자세 측정에서 어떤 문제가 발생하는지 확인해 보았다. 엔코더와 같은 센서들은 고정점이 필요하고, 자이로 센서는 적분에서의 오차가, 기울기 센서는 느린 응답특성이, 가속도 센서는 회전 중심축과 센서의 중심이 맞아야한다는 문제가 있음을 확인했다.<br />
이제 다음에는 이와 같은 문제들로 인해 많이들 사용하는 센서의 융합에서 상보필터를 소개하고, 그 원리와 사용방법에 대해 다루고자 한다.</p>
<p><font style="font-size:8pt"><br />
■ 본 글은 2011년 2월 필자의 학위논문 중 일부를 발췌 후 잡지의 의도에 맞게 재정리한 것임을 미리 밝힙니다.</font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/3930/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[11호]GPS 자동차를 만들어 보자!-1</title>
		<link>http://www.ntrexgo.com/archives/5040</link>
		<comments>http://www.ntrexgo.com/archives/5040#comments</comments>
		<pubDate>Sat, 25 Feb 2012 07:13:01 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[11호]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[자동차]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=5040</guid>
		<description><![CDATA[디바이스마트 매거진 11호 &#124; 최근 GPS 위성 신호가 민간에 공개된 이후 그 활용도가 사회적으로 증가하고 있고 발전 가능성이 무궁무진해서 나도 한번쯤 GPS를 활용한 작품을 만들어보고 싶었다. GPS 자동차의 개발 목적은 작품을 만들면서 마이크로프로세서와 GPS를 심도 있게 공부하고 그것을 구현해 내는 것이다.]]></description>
				<content:encoded><![CDATA[<h2><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038.jpg" rel="lightbox[5040]"><img class=" wp-image-5111 alignleft" alt="11FGPS038" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038-300x230.jpg" width="185" height="142" /></a><strong><span style="color: #666699">GPS 자동차를 만들어 보자! -1</span></strong></h2>
<p>&nbsp;</p>
<p style="text-align: right">글 | 유한대 김경수(neocima3255@naver.com) 外</p>
<p><span style="text-decoration: underline"><strong>※ 상기 내용은 2010년에 진행된 유한대학과의 산학연 졸업 작품지원 프로젝트에 일환으로 작성되어진 원고임을 밝힙니다.</strong></span></p>
<p>&nbsp;</p>
<p><b><span style="color: #005557">1. 서론</span></b></p>
<p class="중간제목"><span class="가제목"><span style="color: #008e37"><strong>가. 개발동기 및 목적</strong></span></span></p>
<p class="중간제목">최근 GPS 위성 신호가 민간에 공개된 이후 그 활용도가 사회적으로 증가하고 있고 발전 가능성이 무궁무진해서 나도 한번쯤 GPS를 활용한 작품을 만들어보고 싶었다. GPS 자동차의 개발 목적은 작품을 만들면서 마이크로프로세서와 GPS를 심도 있게 공부하고 그것을 구현해 내는 것이다.</p>
<p><span class="중간제목"><span class="가제목"><span style="color: #008e37"><strong>나. 과제 해결 방안 및 과정</strong></span></span></span></p>
<p><span style="color: #47be80">1) 과제해결방안</span></p>
<p>GPS 자동차를 구성하고 있는 부품들에 대해서 충분히 공부를 하고 이해를 해서 활용할 줄 알아야 한다. 작품을 만들기전 단계별로 계획을 세우고 그 계획대로 조금씩 작품을 완성해 나간다. 우선 기본적으로 우리 조가 구상하고 있는 GPS 자동차는 지그비 모듈과 지그비 조정기를 활용해서 조정기로 수동 조작을 할수 있고, GPS 모듈을 이용하여 GPS 위성데이터를 수신해서 ATMEGA128을 통해 데이터를 필터링 하고 그 필터링한 데이터값을 이용해서 지정된 좌표로 모터를 구동해서 이동한다. 1단계로는 DC모터와 모터드라이버, ATMEGA128을 통해서 DC모터를 구동하고 지그비와 지그비 조정기를 사용해서 수동 조작을 하는 RC카 만들기이다. 2단계로는 차체에 GPS 모듈을 장착해서 GPS 데이터를 GPS 자동차가 수신받고 그 수신받은 데이터를 ATMEGA128 프로세서를 통해서 필터링한 후 지그비 통신을 통해 PC로 그 값을 확인한다. 값을 확인할 때는 PC의 하이퍼 터미널을 통해서 값을 확인한다. 3단계로는 PC에서 프로그램을 통해 목표 좌표를 지정해서 지그비로 GPS 자동차에 데이터를 송신하면 GPS 자동차의 현재 좌표와 수신받은 목표 좌표로 이동거리와 방향을 설정하고 마그네틱 컴파스 센서(나침판 센서)로 방향을 잡고 목표 좌표만큼 DC모터를 구동한다. 4단계로는 GPS 자동차에 초음파 센서를 장착하여 장애물을 탐지하고 피하는 기능을 수행한다. 각 단계별로 작품을 완성하기 위해서는 단계별로 사용된 제품의 매뉴얼이나 데이터 시트를 완벽하게 숙지하고 작품을 만들기전 각 부품을 실습 구현해서 완벽하게 그 부품을 이해하고 활용해야 한다.</p>
<p dir="ltr"><span class="숫자제목"><span style="color: #47be80">2) 과정</span></span></p>
<p>가) ATMEGA128을 활용해서 DC모터를 구동.<br />
나) DC모터 드라이버를 활용해서 DC모터를 제어.<br />
다) 지그비 모듈을 이용해서 무선송신.<br />
라) 지그비와 지그비 조정기를 사용해서 통신.<br />
마) GPS 모듈을 사용해서 어떤 데이터가 들어오는지 확인.<br />
바) GPS 데이터를 PC의 하이퍼 터미널로 표현.<br />
사) GPS 데이터를 지그비 통신을 통해 PC로 전송.<br />
아) PC에서 수신받은 GPS 데이터를 확인하고 목표 좌표 데이터를 지그비로 통신.<br />
자) 나침판 센서를 통해서 데이터를 수신받고 수신받은 데이터를 하이퍼 터미널로 구현.<br />
차) 목표 거리만큼 프로그램을 통해 DC모터 제어를 통해 이동.<br />
카) 프로그램 제어를 통해 목표좌표로 GPS 자동차 구동.</p>
<p><span class="숫자제목"><span class="중간제목"><b><span style="color: #005557">2. 제품 제작 과정</span></b></span></span></p>
<p><span class="가제목"><span style="color: #008e37"><strong>가. GPS 자동차의 전원 회로 구성</strong></span></span><br />
GPS 자동차의 차체는 디바이스마트에서 판매하는 NT-Destroyer-I 라는 제품이다.<br />
차체에 12V DC 모터가 4개 내장되어 있다. DC모터 연결 선은 커넥터로 연결되어 있다.</p>
<p><span class="숫자제목"><span style="color: #47be80">1) 모터제어 하드웨어 구성</span></span></p>
<table style="border-collapse: collapse" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS003.jpg" rel="lightbox[5040]"><img class="alignnone  wp-image-5076" alt="11FGPS003" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS003-300x281.jpg" width="240" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS014.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5087" alt="11FGPS014" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS014-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td>1. 자동차의 차체 모습이다. 4개의 DC모터가 연결되어 있다.</td>
<td>2. 자동차의 차체 내부 모습이다.<br />
4개의 DC모터 선이 연결되어 커넥터에 연결되어 있다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS025.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5098" alt="11FGPS025" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS025-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS036.jpg" rel="lightbox[5040]"><img class="wp-image-5109 aligncenter" alt="11FGPS036" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS036-249x300.jpg" width="199" height="240" /></a></td>
</tr>
<tr>
<td>3. 차체에 드릴로 구멍을 뚫어서 서포터로 위에 기판을 고정한다.</td>
<td>4. 기판은 200 x 300 기판으로<br />
기판에 구멍을 뚫어서 차체와 서포터로 고정시킨다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS039.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5112" alt="11FGPS039" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS039-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS040.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5113" alt="11FGPS040" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS040-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">5,6. 자동차의 배터리는 11.1V 2200mA의 리튬 폴리머 배터리로 ATMEGA128의 전원과 모터드라이버의 전원을 각각 하나씩 공급한다.(ATMEGA128에 한 개, 모터 드라이버에 한 개 각각 전원 공급)</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS041.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5114" alt="11FGPS041" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS041-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS042.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5115" alt="11FGPS042" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS042-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">7,8. 기판에 ATmega128, 모터 드라이버를 기판에 드릴로 뚫은 후 서포터와 나사로 고정시킨다. ATmega128은 [(주)뉴티씨] ATMEGA128Pro (KD-128PRO-C) 제품으로 외부전원 12V 입력, 내부동작 5V 단일 전원을 사용하고 7805가 내장되어 있어 5V출력 단자가 많다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS043.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5116" alt="11FGPS043" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS043-300x185.jpg" width="300" height="185" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS004.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5077" alt="11FGPS004" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS004-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">9,10. 모터 드라이버는 [(주)뉴티씨]DC 모터 구동모듈 Dual 2A (AM-DC2-2D)로 두 개의 모터를 제어할 수 있고 최대 전류는 2A 구동 전압은 5V∼45V이다. 컨트롤 신호에 10핀 커넥터로 ATmega128의 PORTC에 연결되고 전원 공급 핀에 리튬폴리머 배터리가 연결된다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS005.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5078" alt="11FGPS005" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS005-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS006.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5079" alt="11FGPS006" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS006-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS007.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5080" alt="11FGPS007" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS007-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS008.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5081" alt="11FGPS008" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS008-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">11,12,13,14. 차체에 기판을 고정시킨다. 차체와 기판에 드릴로 구멍을 뚫고 서포터와 나사로 고정시킨다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS009.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5082" alt="11FGPS009" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS009-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS010.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5083" alt="11FGPS010" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS010-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">15,16. 기판에 배터리를 연결시킨다. 배터리 연결 선은 연장선으로 연장하여 기판의 커넥터에 그림과 같이 연결 시킨다. 모터 커넥터 역시 그림처럼 모터 드라이브에 연결 시킨다.</td>
</tr>
</tbody>
</table>
<p><span class="숫자제목"><span style="color: #47be80">2) 모터제어 소프트웨어 구성</span></span></p>
<p>모터 드라이브의 예제 소스를 이용하여 모터를 제어한다.<br />
모터 드라이버의 핵심 구동 소스는 다음과 같다. 컴파일러는 avr studio를 사용하였다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>#include</p>
<p>#define MOTOR_PORT PORTC //모터 포트 지정<br />
#define MOTOR_DDR DDRC //해당 포트 입출력 설정<br />
#define PWM1_IN (MOTOR_PORT&amp;0&#215;01)<br />
#define PWM1_ON (MOTOR_PORT|=0&#215;01)<br />
#define PWM1_OFF (MOTOR_PORT&amp;=0xFE)<br />
#define DIR1_ON (MOTOR_PORT|=0&#215;02)<br />
#define DIR1_OFF (MOTOR_PORT&amp;=0xFD)<br />
#define ENABLE1_OFF (MOTOR_PORT|=0&#215;04)<br />
#define ENABLE1_ON (MOTOR_PORT&amp;=0xFB)<br />
#define BREAK1_ON (MOTOR_PORT|=0&#215;08)<br />
#define BREAK1_OFF (MOTOR_PORT&amp;=0xF7)<br />
#define PWM2_IN (MOTOR_PORT&amp;0&#215;10)<br />
#define PWM2_ON (MOTOR_PORT|=0&#215;10)<br />
#define PWM2_OFF (MOTOR_PORT&amp;=0xEF)<br />
#define DIR2_ON (MOTOR_PORT|=0&#215;20)<br />
#define DIR2_OFF (MOTOR_PORT&amp;=0xDF)<br />
#define ENABLE2_ON (MOTOR_PORT|=0&#215;40)<br />
#define ENABLE2_OFF (MOTOR_PORT&amp;=0xBF)<br />
void delay (int d){<br />
int i;</p>
<p>for (i=0;1</p>
<p>}</p>
<p>void main (void)<br />
{<br />
MOTOR_DDR = 0xff;      // 모터포트 초기화</p>
<p>ENABLE1_ON;            // 모터 드라이브 enable</p>
<p>while(1){<br />
// 2초 동안 전진<br />
DIR1_ON;<br />
DIR2_ON;<br />
PWM1_ON;<br />
PWM2_ON;<br />
delay(2000);<br />
PWM1_OFF;<br />
PWM2_OFF;<br />
// 2초 동안 후진<br />
DIR1_OFF;<br />
DIR2_OFF;<br />
PWM1_ON;<br />
PWM2_ON;<br />
delay(2000);<br />
PWM1_OFF;<br />
PWM2_OFF;<br />
}<br />
}</p>
</div>
<p><span class="숫자제목"><span style="color: #47be80">3) ATMEGA128 프로그램 입력</span></span></p>
<p>컴파일러 AVR STUDIO로 프로그램을 입력 후 헥사 파일을 만들어서 자동차의 ATMEGA128에 프로그램을 입력하는 과정을 나타내었다.</p>
<table style="border-collapse: collapse" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS011.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5084" alt="11FGPS011" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS011-300x240.jpg" width="300" height="240" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS012.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5085" alt="11FGPS012" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS012-300x240.jpg" width="300" height="240" /></a></td>
</tr>
<tr>
<td>17. 프로그램을 시작하면 프로그램을 저장할 위치를 지정한다.</td>
<td>18. 컴파일러할 부품을 선택한다. GPS자동차의 경우 ATMEGA128로 선택한다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS013.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5086" alt="11FGPS013" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS013-300x240.jpg" width="300" height="240" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS015.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5088" alt="11FGPS015" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS015-300x240.jpg" width="300" height="240" /></a></td>
</tr>
<tr>
<td>19. 프로그램 작성 화면이다. 프로그램은 C언어로 작성하였다. 프로그램이 작성되면 F7키를 눌러서 에러가 없으면 HEX파일이 생성된다.</td>
<td>20. 생성된 HEX파일을 ATMEGA128모듈에 저장하는 화면이다. Flash부분에서 저장할 HEX파일을 선택하고 Program버튼을 누르면 저장된다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS016.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5089" alt="11FGPS016" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS016-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS017.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5090" alt="11FGPS017" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS017-300x240.jpg" width="300" height="240" /></a></td>
</tr>
<tr>
<td>21. ATMEGA128에 프로그램을 저장하기 위해 PC와 연결된 모습이다. USB를 통해서 연결된다.</td>
<td>22. 프로그램이 ATMEGA128로 성공적으로 저장이 되면 빨간 박스안처럼 OK가 나타나고 ATMEGA128에 프로그램이 저장된다.</td>
</tr>
</tbody>
</table>
<p><span class="가제목"><span style="color: #008e37"><strong>나. 지그비 조정기를 이용하여 GPS 자동차를 RC카 제어</strong></span></span></p>
<p>지그비 조정기는 로보블럭의 지그비 조정기를 사용하였다. GPS 자동차와 지그비 조정기가 서로 무선통신을 하기 위해 지그비 조정기에서 지원하는 지그비 모듈은 사용하지 않고 Xbee pro라는 지그비 모듈을 공통적으로 사용하였다. 지그비 조정기에는 버튼에 따라 20가지 코드값이 출력되어 ATmega128에서 코드를 분석, DC모터를 제어한다.</p>
<p><span class="숫자제목"><span style="color: #47be80">1) 지그비 하드웨어 구성</span></span></p>
<p>23. 지그비 조정기의 사진이다.24. AA전지를 두 개 연결하고 서포터를 연결하기 위한 구멍을 드릴로 뚫는다.</p>
<table style="border-collapse: collapse" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS018.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5091" alt="11FGPS018" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS018-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS019.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5092" alt="11FGPS019" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS019-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS020.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5093" alt="11FGPS020" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS020-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS021.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5094" alt="11FGPS021" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS021-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td>25. 드릴로 뚫은 구멍에 서포터를 고정한다.</td>
<td>26. 연결할 지그비 모듈을 PCB 변환기판에 연결하여 일반 기판에 고정시킨다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS022.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5095" alt="11FGPS022" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS022-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS023.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5096" alt="11FGPS023" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS023-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">27,28. 지그비 모듈을 지그비 조정기에 설치한 모습이다. 일반 기판에도 구멍을 뚫어 서포터로 고정한다</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS024.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5097" alt="11FGPS024" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS024-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS026.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5099" alt="11FGPS026" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS026-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">29,30. 지그비 모듈은 Xbee pro라는 모듈로 3.3V에서 동작을 하고 무선 통신 최대 거리 1.6km에 2mm 핀 간격을 가진 모델이다. 자동차에 설치된 기판은 2.5mm 기판이므로 2mm 핀간격을 2.5mm 기판에 부착하기 위해 간단한 PCB를 제작하여 GPS 자동차에 설치하였다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS027.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5100" alt="11FGPS027" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS027-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS028.jpg" rel="lightbox[5040]"><img class="alignnone size-medium wp-image-5101" alt="11FGPS028" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS028-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td colspan="2">31,32. PC에도 똑같은 지그비 모듈인 Xbee pro를 사용하는데 PC와 지그비 모듈을 연결하기 위해 역시 지그비 인터페이스 보드가 필요하다. 지그비 인터페이스 보드는 usb연결로 usb케이블을 통해 연결된다.</td>
</tr>
<tr>
<td colspan="2" align="center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS029.jpg" rel="lightbox[5040]"><img class="alignnone size-full wp-image-5102" alt="11FGPS029" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS029.jpg" width="522" height="220" /></a></td>
</tr>
<tr>
<td colspan="2">33. 지그비가 통신을 하기 위해서는 3.3V의 전압이 인가되어야 한다. 하지만 ATMEGA128의 출력 전압은 5V라서 레귤레이터를 통해 5V를 3.3V로 전압을 바꿔줘야 한다. 필자는 레귤레이터를 LM-1117-3.3 LS라는 레귤레이터를 사용했다. 위 그림은 LM-1117의 데이터 시트이다.LM-1117을 Vin과 Vout 단자에 병렬로 캐패시터가 하나씩 필요하다는 것을 알 수 있다.</td>
</tr>
<tr>
<td colspan="2" align="center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS030.jpg" rel="lightbox[5040]"><img class="alignnone  wp-image-5103" alt="11FGPS030" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS030-620x465.jpg" width="496" height="372" /></a></td>
</tr>
<tr>
<td colspan="2">34. 실제 자동차에서 레귤레이터 회로를 구성한 모습. 위와 같이 회로를 구성하면 자동차의 지그비에 3.3V가 인가되어 지그비 통신이 가능하다. ATmega128과 지그비 통신은 UART1로 통신을 한다.</td>
</tr>
</tbody>
</table>
<p>아래 코드는 지그비 조정기의 버튼이 출력하는 코드를 나타낸 표이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2012/02/11FGPS056.jpg" rel="lightbox[5040]"><img class="alignnone  wp-image-5234" alt="11FGPS056" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11FGPS056-517x620.jpg" width="362" height="434" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #47be80">2) 지그비 소프트웨어 구성</span></p>
<p>아래 소스를 자동차의 ATmega128에 적용하면 버튼이 눌림에 따라 코드값을 지그비로 받아서 Switch, Case문으로 각 코드마다 구별하여 모터를 구동한다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>#include</p>
<p>#include</p>
<p>int putchar(int data);<br />
int getchar(void);<br />
int seg();<br />
#define MOTOR_PORT PORTC<br />
#define MOTOR_DDR DDRC<br />
#define PWM1_IN (MOTOR_PORT&amp;0&#215;01)<br />
#define PWM1_ON (MOTOR_PORT|=0&#215;01)<br />
#define PWM1_OFF (MOTOR_PORT&amp;=0xFE)<br />
#define DIR1_ON (MOTOR_PORT|=0&#215;02)<br />
#define DIR1_OFF (MOTOR_PORT&amp;=0xFD)<br />
#define ENABLE1_OFF (MOTOR_PORT|=0&#215;04)<br />
#define ENABLE1_ON (MOTOR_PORT&amp;=0xFB)<br />
#define BREAK1_ON (MOTOR_PORT|=0&#215;08)<br />
#define BREAK1_OFF (MOTOR_PORT&amp;=0xF7)<br />
#define PWM2_IN (MOTOR_PORT&amp;0&#215;10)<br />
#define PWM2_ON (MOTOR_PORT|=0&#215;10)<br />
#define PWM2_OFF (MOTOR_PORT&amp;=0xEF)<br />
#define DIR2_ON (MOTOR_PORT|=0&#215;20)<br />
#define DIR2_OFF (MOTOR_PORT&amp;=0xDF)<br />
#define ENABLE2_ON (MOTOR_PORT|=0&#215;40)<br />
#define ENABLE2_OFF (MOTOR_PORT&amp;=0xBF)<br />
void main (void)<br />
{<br />
MOTOR_DDR = 0xff; // 모터포트 초기화<br />
ENABLE1_ON;<br />
DDRE=0&#215;02; //UART1로 통신을 위한 입출력 설정</p>
<p>&nbsp;</p>
<p>UBRR1H=0; //UART1로 통신을 위한 초기 설정<br />
UBRR1L=103;<br />
UCSR1A = 0&#215;00;<br />
UCSR1B=0X18;<br />
UCSR1C = 0&#215;06;<br />
while(1){<br />
putchar(getchar()); //UART1로 데이터를 받아서 모터 구동<br />
}<br />
}<br />
int putchar(int data)<br />
{<br />
while(!(UCSR1A&amp;0X20));<br />
UDR1=data;<br />
seg(); //모터 구동 함수<br />
}<br />
int getchar(void)<br />
{<br />
while(!(UCSR1A&amp;0X80));<br />
return UDR1;<br />
}<br />
int seg() //모터 구동 함수<br />
{<br />
switch(UDR1)<br />
{<br />
case 0&#215;01: BREAK1_OFF; // 전진<br />
DIR1_ON;<br />
DIR2_ON;<br />
PWM1_ON;</p>
<p>PWM2_ON;</p>
<p>delay(1000);<br />
BREAK1_ON;<br />
PWM1_OFF;<br />
PWM2_OFF;<br />
break;</p>
</div>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/archives/5258" target="_blank"><strong style="font-size: 13px;line-height: 19px">2부에서 계속 이어집니다.</strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/5040/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[11호]GPS 자동차를 만들어 보자!-2</title>
		<link>http://www.ntrexgo.com/archives/5258</link>
		<comments>http://www.ntrexgo.com/archives/5258#comments</comments>
		<pubDate>Sat, 25 Feb 2012 05:32:37 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[11호]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[자동차]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=5258</guid>
		<description><![CDATA[디바이스마트 매거진 11호 &#124; 최근 GPS 위성 신호가 민간에 공개된 이후 그 활용도가 사회적으로 증가하고 있고 발전 가능성이 무궁무진해서 나도 한번쯤 GPS를 활용한 작품을 만들어보고 싶었다. GPS 자동차의 개발 목적은 작품을 만들면서 마이크로프로세서와 GPS를 심도 있게 공부하고 그것을 구현해 내는 것이다.]]></description>
				<content:encoded><![CDATA[<h2><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038.jpg" rel="lightbox[5258]"><img class=" wp-image-5111 alignleft" alt="11FGPS038" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038-300x230.jpg" width="185" height="142" /></a><strong><span style="color: #666699">GPS 자동차를 만들어 보자!-2</span></strong></h2>
<p>&nbsp;</p>
<p style="text-align: right">글 | 유한대 김경수(neocima3255@naver.com) 外</p>
<p><span style="text-decoration: underline"><strong>※ 상기 내용은 2010년에 진행된 유한대학과의 산학연 졸업 작품지원 프로젝트에 일환으로 작성되어진 원고임을 밝힙니다.</strong></span></p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/archives/5040" target="_blank">1부 보러가기</a></p>
<p><strong><span style="color: #008080">다. 지그비 무선 통신을 통해 PC의 하이퍼 터미널로 GPS 데이터 값을 확인</span></strong></p>
<p>GPS 데이터를 받기위해 사용한 GPS 모듈은 유아이구즈의 UIGGUB02-ROO1이라는 모델이다. 이 GPS 모듈은 안테나 일체형으로 USB로 PC와 연결이 가능해 간단하게 PC로 GPS 데이터를 확인할 수 있고 UART을 통해 간편하게 GPS 데이터를 받아 올수 있다. 아래 그림은 GPS 데이터의 연결 핀과 자동차에 GPS 모듈을 설치한 모습이다.</p>
<table>
<tbody>
<tr>
<td><img class="alignnone  wp-image-5264" alt="11FGPS059" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS059-620x156.jpg" width="312" height="79" /></td>
<td><img class="alignnone  wp-image-5235" alt="11FGPS057" src="http://www.ntrexgo.com/wp-content/uploads/2012/02/11FGPS057-620x240.jpg" width="260" height="101" /></td>
</tr>
</tbody>
</table>
<p><img class="alignnone  wp-image-5263" alt="11FGPS058" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS058-620x335.jpg" width="321" height="174" /></p>
<p>GPS 모듈은 자동차의 ATMEGA128의 UART0에 연결되어 있어 전원이 켜지면 지속적으로 위성으로부터 GPS 데이터를 받아 ATMEGA128로 저장 시킨다.</p>
<p><span style="color: #339966">1) 지그비 소프트웨어 구성</span><br />
GPS 모듈을 연결 했으면 이제 UART0통신으로 GPS 데이터를 ATMEGA128에 받아와야 한다. 아래의 소스는 GPS 데이터를 이제 UART0통신으로 ATMEGA128에 저장해 GPS 데이터를 지그비로 PC에 송신해 하이퍼 터미널로 확인하는 소스이다. GPS모듈은 UART0통신을 지그비는 UART1통신을 각각 한다.<br />
위 소스를 자동차의 ATMEGA128에 입력하면 지속적으로 GPS 데이터를 수신 받아서 지그비를 통해 PC로 GPS 데이터를 송신한다. GPS 모듈과 지그비 모듈은 모두 9600 보레이트의 통신 속도로 통신을 한다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>#include</p>
<p>#include</p>
<p>void main (void)<br />
{</p>
<p>DDRE = 0&#215;02; //통신 초기화 설정<br />
PORTE = 0&#215;00;<br />
DDRD = 0&#215;08;<br />
PORTD = 0&#215;00;<br />
usart0_init();<br />
usart1_init();</p>
<p>while(1)<br />
{<br />
put_char1(get_char0());<br />
//GPS 데이터를 usart0통신으로 받아서 지그비로 usart1 통신으로 PC에 GPS 데이터를 송신한다.<br />
}<br />
}<br />
void usart0_init(void) // usart0통신 설정<br />
{<br />
UBRR0H = 0;<br />
UBRR0L = 103;</p>
<p>UCSR0A = 0&#215;00;<br />
UCSR0B = 0&#215;18;<br />
UCSR0C = 0&#215;06;<br />
}<br />
void usart1_init(void) // usart1통신 설정<br />
{<br />
UBRR1H = 0;<br />
UBRR1L = 103;<br />
UCSR1A = 0&#215;00;<br />
UCSR1B = 0&#215;18;<br />
UCSR1C = 0&#215;06;<br />
}<br />
unsigned char get_char0(void)<br />
{<br />
while((UCSR0A &amp; 0&#215;80) == 0&#215;00);<br />
return UDR0;<br />
}<br />
void put_char0(unsigned char gps)<br />
{<br />
while((UCSR0A &amp; 0&#215;20) == 0&#215;00);<br />
UDR0 = gps;<br />
}<br />
unsigned char get_char1(void)<br />
{<br />
while((UCSR1A &amp; 0&#215;80) == 0&#215;00);<br />
return UDR1;<br />
}</p>
<p>void put_char1(unsigned char xbee)<br />
{<br />
while((UCSR1A &amp; 0&#215;20) == 0&#215;00);<br />
UDR1 = xbee;<br />
}<br />
void delay (int d){<br />
int i;<br />
for (i=0;i</p>
<p>}</p>
</div>
<p>&nbsp;</p>
<table style="border-collapse: collapse" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS031.jpg" rel="lightbox[5258]"><img class="alignnone size-medium wp-image-5104" alt="11FGPS031" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS031-300x240.jpg" width="300" height="240" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS032.jpg" rel="lightbox[5258]"><img class="alignnone size-medium wp-image-5105" alt="11FGPS032" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS032-300x211.jpg" width="300" height="211" /></a></td>
</tr>
<tr>
<td>35. 시작 → 모든 프로그램 → 보조프로그램 → 통신 → 하이퍼 터미널 순으로 프로그램을 실행한다.</td>
<td>36. 하이퍼 터미널의 이름을 입력한다.</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS033.jpg" rel="lightbox[5258]"><img class="alignnone size-medium wp-image-5106" alt="11FGPS033" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS033-300x211.jpg" width="300" height="211" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS034.jpg" rel="lightbox[5258]"><img class="alignnone size-medium wp-image-5107" alt="11FGPS034" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS034-300x211.jpg" width="300" height="211" /></a></td>
</tr>
<tr>
<td>37. ATMEGA128이 연결된 포트를 지정한다.</td>
<td>38. 포트의 등록정보를 위와 같이 설정한다.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong><span style="color: #008000"> 라. GPS 파싱</span></strong></p>
<p><span style="color: #33cccc">2) 실제 GPS 데이터 확인 과정</span></p>
<p>GPS 데이터를 수신했으면 수신받은 GPS 데이터에서 내가 필요한 정보만 따로 저장을 해야 한다. GPS 데이터에서 필요한 정보만 저장하는 것을 ‘GPS 파싱’이라고 한다. 아래 그림은 통신 프로그램을 통해 GPS 데이터가 파싱되어 나타내는 것을 확인할수 있다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS052.jpg" rel="lightbox[5258]"><img class="alignnone size-large wp-image-5125" alt="11FGPS052" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS052-620x396.jpg" width="620" height="396" /></a></p>
<p>GPS 자동차에서 필요한 데이터는 ‘$GPRMC’라는 문장에서 나오는데 이 문장을 분석하면,<br />
$GPRMC,155720.00.A,3729.18282,N,12649.27524,E,0.754,322.10,071010,,,A*69</p>
<p>155720 : 현재 시간<br />
A : 데이터의 신용정도<br />
3729.18282 : 위도<br />
12649.27524 : 경도</p>
<p>여기에서 위도 : 3729.18282 와 경도 : 12649.27524 의 데이터를 파싱하여 따로 변수에 저장해야 하는 것이다. 또한 위 데이터는 좌표 정보가 ddmm.mmmm 형식으로 되어 있다.<br />
여기서 dd는 경, 위도의 도(degree)단위를 말하고 크기는 0 ∼ 360도로 나타낸다. mm은 분(minute)을 말한다. 60분은 1도에 해당하며 .mmmm은 분(min)의 소수점이하 수치로서 10진법이 적용된다. 이 데이터를 GPS 항법 계산에 사용하려면 ddmm.mmmm 형식의 좌표를 dd.dddd형식의 십진법 좌표로 변환 하여야 한다. 여기서 변환법은 dd + mm.mmmm/60을 하면 dd.dddd형식의 십진법 좌표로 변환된다. 위의 좌표를 대입해 보면 위도 경도가 ddmm.mmmm 형식 3729.18282 , 12649.27524 이면 이것을 dd.dddd형식으로 변환하기 위해 위도 : 37+29.18282/60 , 경도 126+49.27524/60을 해주면 된다. 위의 식을 적용하면 위도 : 37.48638033 , 경도 : 126.821254 값이 된다. 이 값을 구글 어스에 넣어 보면 현재 위치를 지도상으로 표시할 수 있다.<br />
다음 그림은 구글 어스를 통해 dd.dddd형식 좌표를 지도상으로 확인한 그림이다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS002.jpg" rel="lightbox[5258]"><img class="alignnone size-large wp-image-5075" alt="11FGPS002" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS002-620x395.jpg" width="620" height="395" /></a></p>
<p><span style="color: #33cccc">1) GPS 파싱 소프트웨어 구성</span><br />
다음 소스에서는 GPS 데이터를 파싱하여 위도, 경도를 따로 추출하고 추출된 위도 경도 값을 dd.dddd 형식으로 변환하여 그 값을 지그비를 통해 PC의 하이퍼 터미널로 확인하는 소스 중 일부이다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt;<br />
#include<br />
#include<br />
#include</p>
<p>unsigned char GPSflag=0; // 데이터 파싱에서 쓰이는 변수,$로 시작할 때 1저장<br />
unsigned char GPScnt=0; // data parsing 할 때 사용<br />
unsigned char GPSDATA[100]; // GPS receiver부터 받은 모든 정보 저장할 변수<br />
unsigned char time[15]; // Time 정보 저장할 변수<br />
unsigned char lat2[10]; // 위도 정보 저장(mm.mmmm)<br />
unsigned char lon2[10]; // 경도 정보 저장(mm.mmmm)<br />
unsigned char lat1[5]; // 위도 정보 저장(dd)<br />
unsigned char lon1[5]; // 경도 정보 저장(dd)<br />
double latitude=0; // dd.dddd로 변환된 위도값 저장<br />
double longitude=0; // dd.dddd로 변환된 경도값 저장</p>
<p>// 1us 딜레이<br />
void delay_us(unsigned char time_us)<br />
{<br />
register unsigned char i;<br />
for(i=0; i&lt;time_us; i++) {<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
}<br />
}</p>
<p>//1ms 딜레이<br />
void delay_ms(unsigned int time_ms) {<br />
register unsigned int i;<br />
for(i=0; i&lt;time_ms; i++) {<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
}<br />
}</p>
<p>void usart0_init(void) //usart0 통신 설정 gps 데이터가 들어올때 인터럽트 발생<br />
{<br />
UBRR0H = 0;<br />
UBRR0L = 103;</p>
<p>UCSR0A = 0&#215;00;<br />
UCSR0B = 0&#215;98;<br />
UCSR0C = 0&#215;06;<br />
}<br />
</div>
위 소스를 자동차에 입력하고 자동차의 ATmega128에서 GPS 데이터가 지속적으로 들어오면 인터럽트가 발생해서 GPS 데이터를 파싱하고 위도, 경도 변수에 위도, 경도값을 저장한다. 저장된 위도, 경도값을 1초마다 지그비를 통하여 무선 송신하면 PC의 하이퍼 터미널을 통해 dd.dddd값으로 변환된 위도, 경도값만 확인 할 수 있다. 아래 그림은 실제 GPS 자동차에서 GPS 데이터를 파싱한 값을 하이퍼터미널로 확인한 그림이다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS045.jpg" rel="lightbox[5258]"><img class="alignnone size-large wp-image-5118" alt="11FGPS045" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS045-620x431.jpg" width="620" height="431" /></a></p>
<p><strong><span style="color: #008000">마. 추출된 위도, 경도값을 이용하여 수식을 통해 목표 좌표까지 거리, 방향각 값을 계산</span></strong><br />
GPS 데이터에서 추출된 위도, 경도값으로 목표 위도, 경도값까지의 이동거리, 방향각을 구하려면 우선 위도, 경도 값을 라디안 각도로 변환해야 한다. 위도나 경도는 지구 중심을 기반으로 하는 각도이기 때문에 라디안 각도로 변환할 수가 있는 것이다. 위도와 경도를 라디안 값으로 변환하는 식은 dd.dddd형식의 좌표를 57.2957795(1라디안에 해당하는 각도; 180/π)으로 나누거나 (π/180)을 곱하면 라디안 각도로 변환할 수 있다.</p>
<p><span style="color: #33cccc">1) 위도와 경도의 라디안 값을 구하는 식</span><br />
가) 위도 * (3.141592/180) = 라디안 위도값<br />
나) 경도 * (3.141592/180) = 라디안 경도값</p>
<p><span style="color: #33cccc">2) 목표까지의 라디안 거리 값을 구하는 공식</span><br />
가) 라디안 거리값 = acos(sin(현재 라디안 위도)*sin(목표 라디안 위도)+cos(현재 라디안 위도)*cos(목표 라디안 위도)*cos(현재 라디안 경도-목표 라디안 경도));</p>
<p><span style="color: #33cccc">3) 실제 M단위로 된 거리값을 구하는 계산식</span><br />
가) 실제 거리값(M) = 라디안 거리값 * 3437.7387 * 1852</p>
<p><span style="color: #33cccc">4) 목표 방위각을 구하는 계산식</span><br />
가) 라디안 방위각 = acos((sin(목표 라디안 위도) &#8211; sin(현재 라디안 위도) x cos(라디안 거리)) / (cos(현재 라디안 위도) x sin(라디안 거리)))</p>
<p><span style="color: #33cccc">5) 라디안 방위각 값을 항법에 적용할 방위각 값을 변환하는 공식</span><br />
가) 실제 방위각 = 라디안 방위각 * (180 / 3.141592)</p>
<p><span style="color: #33cccc">6) 만약 현재 경도가 목표 경도보다 값이 크다면 실제 방위각 값을 구하는 공식</span><br />
가) 실제 방위각 = 360 &#8211; (라디안 방위각 * (180 /3.141592))</p>
<p>위의 공식들을 사용하여 GPS 자동차는 목표 좌표까지 이동할 거리, 방위각을 계산하여 목표 방위각만큼 방향을 틀고 이동할 거리만큼 모터를 움직이면 원하는 좌표로 GPS 자동차를 무인 조정할 수 있는 것이다. 다음은 실제 좌표를 위의 공식들에 대입해서 목표 좌표로 이동할 거리와 방위각이 정확히 나오는지 구글 어스를 통해 확인한다. 현재 좌표를 현재위도 : 37.48638033 현재경도 : 126.821254 으로 설정하고 목표 좌표를‘목표위도 : 37.48738033 목표경도 : 126.822254’으로 설정하고 구글 어스를 통해 이동할 거리와 방위각을 구하면 아래 그림과 같다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS046.jpg" rel="lightbox[5258]"><img class="alignnone size-large wp-image-5119" alt="11FGPS046" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS046-620x321.jpg" width="620" height="321" /></a></p>
<p>이동할 거리는 141.85미터 , 방위각은 38.43도이다. 이제 위의 공식을 통해 계산하면,</p>
<p>현재 라디안 위도 = 37.48638033*(3.141592/180)<br />
= 0.6542606253<br />
현재 라디안 경도 = 126.821254*(3.141592/180)<br />
= 2.213447983<br />
목표 라디안 위도 = 37.48738033*(3.141592/180)<br />
= 0.6542780786<br />
목표 라디안 경도 = 126.822254*(3.141592/180)<br />
= 2.213465437<br />
라디안 거리 = acos(sin(0.6542606253) * sin(0.6542780786)<br />
+ cos(0.6542606253) * cos(0.6542780786) *<br />
cos(2.213447983 &#8211; 2.213465437))<br />
= 0.00002228070345<br />
실제 거리 = 0.00002228070345 * 3437.7387 * 1852<br />
= 141.854378(M)<br />
라디안 방위각=acos((sin(0.6542780786) &#8211; sin(0.6542606253)<br />
* cos(0.00002228070345)) / (cos(0.6542606253)<br />
* sin(0.00002228070345))) = 0.6707747395<br />
실제 방위각 = (0.6707747395 * (180 / 3.141592))<br />
= 38.43256957</p>
<p>7) 지그비를 통해 PC의 하이퍼 터미널로 표현하는 소스 중 일부이다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt; //인터럽트 헤더파일 선언<br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;math.h&gt; // 수함 함수 헤더파일 선언</p>
<p>unsigned char GPSflag=0; // 데이터 파싱에서 쓰이는 변수, $로 시작할 때 1저장<br />
unsigned char GPScnt=0; // data parsing 할 때 사용<br />
unsigned char GPSDATA[100]; // GPS receiver부터 받은 모든 정보 저장할 변수<br />
unsigned char time[15]; // Time 정보 저장할 변수<br />
unsigned char lat2[10];<br />
unsigned char lon2[10];<br />
unsigned char lat1[5];<br />
unsigned char lon1[5];</p>
<p>double latitude=0; //dd.dddd로 변환된 위도<br />
double longitude=0; //dd.dddd로 변환된 경도<br />
double d_latitude=37.48738033; // 목표 위도<br />
double d_longitude=126.822254; // 목표 경도<br />
double Cur_Lat_radian=0; // 현재 라디안 위도<br />
double Cur_Lon_radian=0; // 현재 라디안 경도<br />
double Dest_Lat_radian=0; // 목표 라디안 위도<br />
double Dest_Lon_radian=0; // 목표 라디안 경도<br />
double radian_distance=0; // 라디안 거리<br />
double radian_bearing=0; // 라디안 방위각<br />
double true_bearing=0; // 실제 방위각<br />
double distance=0; // 실제 거리</p>
<p>// 1us 딜레이<br />
void delay_us(unsigned char time_us)<br />
{<br />
register unsigned char i;<br />
for(i=0; i&lt;time_us; i++) {<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
}<br />
}</p>
<p>//1ms 딜레이<br />
void delay_ms(unsigned int time_ms) {<br />
register unsigned int i;<br />
for(i=0; i&lt;time_ms; i++) {<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
}<br />
}</p>
<p>void usart0_init(void)<br />
{<br />
UBRR0H = 0;<br />
UBRR0L = 103;</p>
<p>UCSR0A = 0&#215;00;<br />
UCSR0B = 0&#215;18;<br />
UCSR0C = 0&#215;06;<br />
}</p>
<p>void usart1_init(void)<br />
{<br />
UBRR1H = 0;<br />
UBRR1L = 103;<br />
UCSR1A = 0&#215;00;<br />
</div>
<p style="text-align: right">※ 전체 소스는 www.devicezine.co.kr에서 확인할 수 있다.</p>
<p><span style="color: #33cccc">8) 실제 이동할 거리, 방위각을 하이퍼 터미널로 나타낸 그림</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS060.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5281" alt="11FGPS060" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS060-620x295.jpg" width="496" height="236" /></a></p>
<p>&nbsp;</p>
<p><strong><span style="color: #008000">바. 마그네틱 컴파스 센서(나침판 센서)를 사용하여 GPS 자동차의 현재 방위각을 구한다.</span></strong></p>
<p>마그네틱 컴파스센서(나침판 센서)는 모델명이 CMPS03이며 진북 방향을 기준으로 현재 방위각 값을 지속적으로 출력한다. CMPS03의 그림과 핀번호는 다음과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS047.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5120" alt="11FGPS047" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS047-620x288.jpg" width="434" height="202" /></a><br />
GPS 자동차의 ATMEGA128과 연결해야 될 핀은 1,2,3,9번 핀이다. 1,9번핀은 전원 핀이고 2,3번 핀은 TWI통신 핀(I2C 통신)으로 CMPS03은 I2C통신을 통해 ATMEGA128과 통신을 하면서 현재 방위각 값을 출력한다. GPS 자동차와 CPMS03의 설치는 아래 그림과 같다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS035.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5108" alt="11FGPS035" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS035-620x465.jpg" width="268" height="201" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS037.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5110" alt="11FGPS037" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS037-620x465.jpg" width="268" height="201" /></a></td>
</tr>
</tbody>
</table>
<p>TWI통신을 할때는 통신하는 핀 SCL과 SDA핀에 각각 풀업 저항을 해줘야 한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS001.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5074" alt="11FGPS001" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS001-620x281.jpg" width="434" height="197" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">1) 지그비를 통해 방위각을 하이퍼 터미널로 확인하는 소스 중 일부이다.</span></p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;util/delay.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;avr/interrupt.h&gt;</p>
<p>unsigned char s[21];</p>
<p>void i2c_transmit(char,char,char); //TWI 통신 함수 선언<br />
char i2c_read(char,char); //TWI 통신 함수 선언</p>
<p>char i2c_read(char address, char reg) { //TWI 통신 함수<br />
char read_data = 0;</p>
<p>TWCR = 0xA4; // send a start bit on i2c bus<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address; // load address of i2c device<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = reg; // send register number to read from<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit</p>
<p>TWCR = 0xA4; // send repeated start bit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address+1; // transmit address of i2c device with readbit set<br />
TWCR = 0xC4; // clear transmit interupt flag<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWCR = 0&#215;84; // transmit, nack (last byte request)<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
read_data = TWDR; // and grab the target data<br />
TWCR = 0&#215;94; // send a stop bit on i2c bus<br />
return read_data;</p>
<p>}</p>
<p>void i2c_transmit(char address, char reg, char data) { //TWI 통신 함수<br />
TWCR = 0xA4; // send a start bit on i2c bus<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address; // load address of i2c device<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = reg;<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = data;<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWCR = 0&#215;94; // stop bit<br />
}</p>
<p>void usart0_init(void)<br />
{<br />
UBRR0H = 0;<br />
UBRR0L = 103;</p>
<p>UCSR0A = 0&#215;00;<br />
UCSR0B = 0&#215;18;<br />
UCSR0C = 0&#215;06;<br />
}</p>
<p>void usart1_init(void)<br />
{<br />
UBRR1H = 0;<br />
UBRR1L = 103;</p>
<p>UCSR1A = 0&#215;00;<br />
UCSR1B = 0&#215;18;<br />
UCSR1C = 0&#215;06;<br />
}</p>
<p><span style="font-size: 13px;line-height: 19px"></div></span></p>
<p>위 소스를 실제 GPS 자동차에 적용하여 방위각을 하이퍼 터미널로 확인하면 다음과 같다. 끝의 한자리는 소수점 자리를 나타낸다(ex : 3565 : 356.5도)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS044.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5117" alt="11FGPS044" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS044-620x385.jpg" width="397" height="246" /></a></p>
<p><strong><span style="color: #008000">사. 방위각의 비교와 모터를 구동하여 목표 좌표로 GPS 자동차를 이동</span></strong><br />
마지막 단계로 CMPS03에서 추출된 현재 방위각과 GPS 거리계산 공식으로 나온 방위각이 일치하도록 모터를 돌려주고 GPS 거리 계산 공식으로 나온 이동거리가 1보다 작을때까지 모터를 직진하면 GPS 자동차는 목표 좌표로 이동하게 된다.<br />
GPS 자동차는 좌회전 하면 현재 방위각이 작아지고 우회전을 하면 현재 방위각 값이 커진다. 따라서 현재 방위각이 목표 방위각 보다 크면 좌회전, 현재 방위각이 목표 방위각보다 작으면 우회전을 시키고 현재 방위각과 목표 방위각이 일치하면 이동거리만큼 직진해서 목표 좌표로 이동하면 된다.</p>
<p><span style="color: #33cccc">1) 목표 좌표를 입력하면 목표 좌표로 GPS 자동차가 무인제어하는 소스</span><br />
다음 소스는 CMPS03의 방위각을 TWI통신을 통해 수신, GPS 데이터를 통해 이동 거리와 방위각을 구하고 현재 방위각과 목표 방위각을 비교하여 방향을 잡은 후 목표 이동 거리만큼 모터를 직진하고 목표 이동거리로 이동하면 멈추는 소스이다.</p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">목표 좌표를 입력하면 목표 좌표로 GPS 자동차가 무인제어하는 소스</h3><div class="symple-toggle-container">
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;math.h&gt;</p>
<p>unsigned char GPSflag=0; // 데이터 파싱에서 쓰이는 변수, $로 시작 할 때 1저장할꺼임<br />
unsigned char GPScnt=0; // data parsing 할 때 사용<br />
unsigned char GPSDATA[100]; // GPS receiver부터 받은 모든 정보 저장할 변수<br />
unsigned char time[15]; // Time 정보 저장할 변수<br />
unsigned char lat2[10];<br />
unsigned char lon2[10];<br />
unsigned char lat1[5];<br />
unsigned char lon1[5];</p>
<p>double latitude=0;<br />
double longitude=0;<br />
double d_latitude=37.488499;<br />
double d_longitude=126.821250;<br />
double radian_distance=0;<br />
double radian_bearing=0;<br />
double distance=0;<br />
double rad_distance=0;<br />
double dis_lat=0;<br />
double dis_lon=0;<br />
double dis=0;<br />
double bea=0;<br />
double true_bea=0;<br />
unsigned char exam=0;</p>
<p>#define MOTOR_PORT PORTC<br />
#define MOTOR_DDR DDRC<br />
#define PWM1_IN (MOTOR_PORT&amp;0&#215;01)<br />
#define PWM1_ON (MOTOR_PORT|=0&#215;01)<br />
#define PWM1_OFF (MOTOR_PORT&amp;=0xFE)<br />
#define DIR1_ON (MOTOR_PORT|=0&#215;02)<br />
#define DIR1_OFF (MOTOR_PORT&amp;=0xFD)<br />
#define ENABLE1_OFF (MOTOR_PORT|=0&#215;04)<br />
#define ENABLE1_ON (MOTOR_PORT&amp;=0xFB)<br />
#define BREAK1_ON (MOTOR_PORT|=0&#215;08)<br />
#define BREAK1_OFF (MOTOR_PORT&amp;=0xF7)<br />
#define PWM2_IN (MOTOR_PORT&amp;0&#215;10)<br />
#define PWM2_ON (MOTOR_PORT|=0&#215;10)<br />
#define PWM2_OFF (MOTOR_PORT&amp;=0xEF)<br />
#define DIR2_ON (MOTOR_PORT|=0&#215;20)<br />
#define DIR2_OFF (MOTOR_PORT&amp;=0xDF)<br />
#define ENABLE2_ON (MOTOR_PORT|=0&#215;40)<br />
#define ENABLE2_OFF (MOTOR_PORT&amp;=0xBF)</p>
<p>void i2c_transmit(char,char,char);<br />
char i2c_read(char,char);</p>
<p>// 1us 딜레이<br />
void delay_us(unsigned char time_us)<br />
{<br />
register unsigned char i;<br />
for(i=0; i&lt;time_us; i++) {<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
asm volatile(“PUSH R0”);<br />
asm volatile(“POP R0”);<br />
}<br />
}</p>
<p>//1ms 딜레이<br />
void delay_ms(unsigned int time_ms) {<br />
register unsigned int i;<br />
for(i=0; i&lt;time_ms; i++) {<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
delay_us(250);<br />
}<br />
}<br />
char i2c_read(char address, char reg) { //TWI 통신 함수<br />
char read_data = 0;</p>
<p>TWCR = 0xA4; // send a start bit on i2c bus<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address; // load address of i2c device<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = reg; // send register number to read from<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit</p>
<p>TWCR = 0xA4; // send repeated start bit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address+1; // transmit address of i2c device with readbit set<br />
TWCR = 0xC4; // clear transmit interupt flag<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWCR = 0&#215;84; // transmit, nack (last byte request)<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
read_data = TWDR; // and grab the target data<br />
TWCR = 0&#215;94; // send a stop bit on i2c bus<br />
return read_data;</p>
<p>}</p>
<p>void i2c_transmit(char address, char reg, char data) { //TWI 통신 함수<br />
TWCR = 0xA4; // send a start bit on i2c bus<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = address; // load address of i2c device<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = reg;<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWDR = data;<br />
TWCR = 0&#215;84; // transmit<br />
while(!(TWCR &amp; 0&#215;80)); // wait for confirmation of transmit<br />
TWCR = 0&#215;94; // stop bit<br />
}</p>
<p>void parsing(void)<br />
{<br />
unsigned char temp=6; // time position<br />
unsigned char temp1=0;<br />
unsigned char temp3=20; // latitude position<br />
unsigned char temp4=0;<br />
unsigned char temp5=34; // longitude position<br />
unsigned char temp6=0;<br />
unsigned char temp7=18; // latitude position<br />
unsigned char temp8=0;<br />
unsigned char temp9=31; // longitude position<br />
unsigned char temp10=0;<br />
int i;</p>
<p>if(GPSflag)<br />
{<br />
if(GPSDATA[0]==‘G’)<br />
{<br />
if(GPSDATA[2]==‘R’ &amp;&amp; GPSDATA[3]==‘M’)<br />
{<br />
while(GPSDATA[temp]!=‘,’)<br />
{<br />
time[temp1]=GPSDATA[temp];<br />
temp++;<br />
temp1++;<br />
}<br />
while(GPSDATA[temp3]!=‘,’)<br />
{<br />
lat2[temp4]=GPSDATA[temp3];<br />
temp3++;<br />
temp4++;<br />
}<br />
while(GPSDATA[temp5]!=‘,’)<br />
{<br />
lon2[temp6]=GPSDATA[temp5];<br />
temp5++;<br />
temp6++;<br />
}<br />
for(i=0; i&lt;2; i++)<br />
{<br />
lat1[temp8]=GPSDATA[temp7];<br />
temp7++;<br />
temp8++;<br />
}<br />
for(i=0; i&lt;3; i++)<br />
{<br />
lon1[temp10]=GPSDATA[temp9];<br />
temp9++;<br />
temp10++;<br />
}<br />
}<br />
}<br />
}<br />
}</p>
<p>void way_point(void)<br />
{<br />
latitude = (atoi(lat1)+(atof(lat2)/60));<br />
longitude = (atoi(lon1)+(atof(lon2)/60));</p>
<p>dis_lat=69.1*(d_latitude-latitude);<br />
dis_lon=69.1*(d_longitude-longitude)*cos(latitude*3.141592/180);<br />
// pi = 3.141592<br />
rad_distance=sqrt(dis_lat*dis_lat+dis_lon*dis_lon);<br />
distance=rad_distance*1610; //1.61-&gt;1610 =&gt;km를 m단위로 계산</p>
<p>dis=distance/6366690.2;<br />
bea = acos(((sin(d_latitude*3.141592/180)-sin(latitude*3.141592/<br />
180) *cos(dis)) / (cos(latitude*3.141592/180)*sin(dis))));</p>
<p>if(sin(d_longitude-longitude)&lt;0)<br />
{<br />
true_bea = 3600 &#8211; bea*(180/3.141592) * 10;<br />
}<br />
else<br />
{<br />
true_bea = bea * (180/3.141592) * 10;<br />
}<br />
}</p>
<p>// 메인함수의 시작<br />
int main(){<br />
unsigned int angle;</p>
<p>DDRE = 0&#215;02;<br />
PORTE = 0&#215;00;<br />
DDRD = 0&#215;08;<br />
PORTD = 0&#215;00;<br />
usart0_init();<br />
usart1_init();<br />
fdevopen(put_char1,0);<br />
MOTOR_DDR = 0xff; // 모터포트 초기화<br />
ENABLE1_ON;</p>
<p>TWBR = 72;<br />
TWSR = 0&#215;00;<br />
TWCR = 0&#215;04;<br />
delay_ms(1000);</p>
<p>asm(“SEI”); // SREG 의 global interrupt enable 1로 set</p>
<p>while(1) { // 목표 좌표로 모터 제어 시작<br />
while(exam!=1)<br />
{<br />
angle = i2c_read(0xC0,2) &lt;&lt;8;// read cmps03 angle, high byte angle += i2c_read(0xC0,3);<br />
way_point();</p>
<p>BREAK1_ON; // STOP<br />
PWM1_OFF;<br />
PWM2_OFF;<br />
if(angle &gt; true_bea+100) //현재 방위각이 목표 방위각 보다 크면<br />
{<br />
BREAK1_OFF; // 좌회전<br />
DIR1_ON;<br />
DIR2_OFF;<br />
PWM1_ON;<br />
PWM2_ON;<br />
}</p>
<p>else if(angle &lt; true_bea-100) // 현재 방위각이 목표 방위각보다 작으면<br />
{<br />
BREAK1_OFF; // 우회전<br />
DIR1_OFF;<br />
DIR2_ON;<br />
PWM1_ON;<br />
PWM2_ON;<br />
}<br />
else if(true_bea-100 &gt; angle &lt; true_bea+100) // 현재 방위각과 목표 방위각이 같으면<br />
{<br />
exam = 1;<br />
}<br />
}<br />
while(exam!=0)<br />
{<br />
angle = i2c_read(0xC0,2) &lt;&lt;8; // read cmps03 angle, high byte<br />
angle += i2c_read(0xC0,3);<br />
way_point();</p>
<p>if(angle &gt; true_bea+100)<br />
{<br />
exam = 0;<br />
}</p>
<p>else if(angle &lt; true_bea-100)<br />
{<br />
exam = 0;<br />
}</p>
<p>else if(distance &gt; 1) //목표 이동거리가 1보다 크면<br />
{<br />
BREAK1_OFF; // 전진<br />
DIR1_ON;<br />
DIR2_ON;<br />
PWM1_ON;<br />
PWM2_ON;<br />
}</p>
<p>else if(distance &lt; 1) //목표 이동거리가 1보다 작으면<br />
{<br />
BREAK1_ON; // STOP<br />
PWM1_OFF;<br />
PWM2_OFF;<br />
}<br />
}<br />
}<br />
return 0;<br />
}</p>
<p>SIGNAL(SIG_USART0_RECV)<br />
{<br />
asm(“CLI”);<br />
unsigned char ch;<br />
ch = UDR0; // 수신된 데이터를 ch 변수에 저장합니다.<br />
if(ch==’$’) // 수신된 캐릭터가 $ 이면 한줄의 시작이므로<br />
{<br />
GPSflag=1;<br />
GPScnt=0; // 데이터파싱을 위한 카운트 변수도 0으로 초기화<br />
}else{<br />
GPSDATA[GPScnt]=ch; // $가 아니리면 GPSDATA에 계속 저장<br />
if(GPSDATA[GPScnt]==0x0A &amp;&amp; GPSDATA[GPScnt-1]==0x0D)<br />
{<br />
parsing();<br />
way_point();<br />
GPSflag=0;<br />
}<br />
GPScnt++;<br />
}<br />
asm(“SEI”;<br />
}</p>
<p><span style="font-size: 13px;line-height: 19px"></div></div></span></p>
<p><span style="font-size: 13px;line-height: 19px">마지막 소스에서 보면 GPS 거리 계산 공식이 전에 설명한 소스와 약간 다를 것이다. 이유는 전의 GPS 거리 계산 소스는 현재 AVR STUDIO 컴파일러에서는 정밀한 계산이 불가능하여 현재 좌표와 목표 좌표가 가까울때 계산을 정확히 하지 못하기 때문이다. 그 이유는 AVR STUDIO는 실수형 변수 double이 4 바이트로 C 컴파일러는 비주얼 C++보다 성능이 떨어진다.(비주얼 C++ 컴파일러는 실수형 변수 double이 8 바이트로 GPS 거리계산 공식을 정확하게 계산한다.) 전의 GPS 거리 계산 공식은 정밀한 계산이 필요한데(예를 들어 0.999999994 를 AVR STUDIO는 실수형 변수를 최대 4 바이트밖에 인식하지 못해 1로 인식) AVR STUDIO 컴파일러는 그 계산을 정확히 하지 못한다.</span></p>
<p>후에 필자는 마지막 소스에서와 같이 다른 공식을 찾았고 AVR STUDIO 컴파일러에서도 정상적으로 목표이동거리와 방위각을 계산할 수 있었다. 또 목표 방위각으로 모터를 돌릴때 IF문에 true_bea(목표 방위각)에 +-100을 해준 이유는 +-100의 오차를 주지 않으면 모터가 정밀하게 움직이지 못하여 방향을 못잡아서이다. 위의 소스처럼 오차범위를 주면 자동차는 목표 방위각으로 방향을 틀때 헤매지 않고 바로 방향을 잡을 수 있을 것이다.(방위각의 오차는 조금 있을 것이다.)</p>
<p><strong><span style="color: #003366">3. 제작 후기</span></strong></p>
<p>이번 GPS 자동차를 제작하면서 정말 많은 것을 배울 수 있었다. 사실 이번 졸업 프로젝트를 하기 전까지는 GPS라는게 뭔지도 몰랐지만 이번 프로젝트를 통해서 GPS의 원리, 응용, 항법에 대해서 자세히 알 수 있었고 혼자서는 감히 엄두도 못낼 가격의 자동차를 만들 수 있게 되었다.<br />
디바이스마트에서 아낌없이 부품을 지원해준 덕분에 많은 소자와 센서, 부품들을 다뤄볼 수 있었고 많은 것을 공부할 수 있었다. 아직 GPS 자동차는 완성된 것이 아니다. 시간이 조금 더 주어 진다면 LAB VIEW로 프로그램 작성을 해서 노트북으로 실시간 GPS 자동차의 모든 상태를 지그비를 통해서 볼 수 있고 노트북에서 목표 좌표를 지정해서 실시간으로 GPS 자동차를 무인제어할 수 있도록 할 것이다. 또 초음파 센서를 장착해서 4방위의 장애물을 감지하고 GPS 자동차 무인 제어시 초음파 센서를 통해 장애물을 회피할 수 있도록 하는것이 최종 목표이다.<br />
아낌없는 지원을 해 줘서 이런 좋은 기회를 갖게 해준 디바이스마트에 감사하고 이번 프로젝트를 하는 동안 많은 도움을 주신 유한대 김진선 교수님께 감사의 뜻을 전하고 싶습니다. 지금까지 보고서를 읽어주셔서 감사합니다. 만약 이 보고서에 틀린 점이 있다면 많은 지적 부탁드립니다.</p>
<p><strong><span style="color: #008000">가. 최종 완성 작품</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5111" alt="11FGPS038" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS038-620x475.jpg" width="347" height="266" /></a></p>
<p><strong><span style="color: #008000">나. GPS자동차 동영상</span></strong></p>
<p><strong></strong><a href="http://cafe.naver.com/carroty.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=116671" target="_blank">동영상보러가기</a></p>
<p><strong><span style="color: #008000"> 다. 부품 목록</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS061.jpg" rel="lightbox[5258]"><img class="alignnone  wp-image-5319" alt="11FGPS061" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/11FGPS061-601x620.jpg" width="354" height="365" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/5258/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
