ARM Cortex-M0 코어 LPCXpresso 테스트보드 개발환경을 열어보니 막강한 이클립스 기반 IDE를 보고 감탄을 하는것도 잠깐,,, 예제를 열어보고 소스 분석을 해보려하자 당황스럽네요

더이상 main()이 메인이 아이더군요,  이보다 먼저 SystemInit() 가 수행되어 칩세팅을 하는데, 이 파일은 CMSIS library에 포함되어있습니다. 기타 레지스터 설정이나 장치 제어명령도(LED 한개 On/off하는것 까지도) 모두 전용 함수를 제공하는듯 합니다. (물론 CMSIS Libray 사용할 경우에 얘기겠죠, 마치 안드로이드 프로그래밍 하는 분위기입니다.)

AVR펌웨어를 만들때는 대게 8bit 레지스터에 비트마스킹하여 비트 ON/OFF/Toggle 하는정도로 Peripherals(타이머,UART,ADC etc) 제어하는 방식을 주로 사용했었는데요, LPC는 32bit MCU라서 그런지 효율적? 접근을 위해 2~3단계(매크로까지치면 그이상)는 랩핑된 함수로 Peripherals 설정을 하는것 같습니다.  물론 특정 주소에 직접 값을 기입하는것도 가능하겠지만, 칩제조사(silicon vendor)와 무관하고, 다른 ARM core에서도 호환이 가능한 장치 설정 인터페이스를 이용(표준화)하여, 코드 호환성을 높인다는 전략에 따른듯 합니다.  이를 CMSIS라고 부르더군요.  역시나 8bit MCU와 32bit MCU 사이는  장벽이 있네요.  새로운일을 시도할때는 어렵고 쉽고를 떠나서 평소와 다른 새로운것이 나오면 멈칫 진행이 멈쳐버립니다. 정작 중요한건 이로 인해 지체되는 시간을 보상할 정도의 메리트가 있는지? 아닌가 합니다.

어쨌든 좋은 취지로 만들어진것 같으니 일단 대충이라도 어떤것인지 알고넘어가야 하겠습니다.
근데, 진짜문제는 처음사용자용 안내문 링크에도 비중있게 나와있지않은 내용이라,,  이곳 저곳 다니며 자료를 모아야 했습니다. 관련자료를 모아서 여기에 모아두겠습니다.




1.2008년 11월에 발표를 했나보네요
 발표기사 http://www.arm.com/about/newsroom/23722.php

2. 개발환경에 기본 포함된 CMSIS library 내부 폴더에 도움말 도움문서가 숨어? 있습니다.
(도움문서 분량을 보니, 아직도 개발중이라고 해야할듯 합니다. 버젼마다 폴더명이 좀 다르겠네요 제경우 LPC11xx입니다. )
PC폴더 위치예: lpcxpresso_3.5/Examples/NXP/LPC1000/LPC11xx/CMSISv1p30_LPC11xx/CMSISv1p30_LPC11xx/docs/CMSIS_Core.htm

3. CMSIS 기술소개 동영상 및 문서
http://www.doulos.com/knowhow/arm/CMSIS/index.php
http://www.onarm.com/

4.CodeRed사 LPCXpresso IDE 서포트페이지
http://support.code-red-tech.com/CodeRedWiki/Support4CMSIS


그림2. CMSIS 파트너사
제경우 AVR시리즈는 써봤는데 ARM은 처음입니다.
이제부터 ARM의 8,16bit MCU 대체품으로 설계된 32bit Cortex-M0코어가 적용된 NXP사의 LPC1114 공부를 시작하려합니다.

LPCXpresso 라고 불리는 본 개발플래폼은  3개의 회사(NXP, Embedded ARtist, CodeRed)가 파트너가되어 만들었는데요,
무슨, 삼총사인가요?  아마도 유럽 쪽 회사들끼리 뭉친것 같습니다.

정리하면,  NXP사에서 칩을,
Embedded Artist사는 테스트 보드를,
CodeRed사는 개발 IDE를 맡았습니다.

몇가지 정리해 보면,

1. LPCXpresso EVB(Evaluation Board)
약 4만원짜리(해외에선 '$30이하'라고 광고하더군요) 평가보드를 구입하면,  JTAG/SWD 인터페이스 디버깅 장비( LPC3154 칩 내장)와  테스트용 MUC만 달랑 달린 테스트 보드 일체형의 보드가 생깁니다. 정말 좋은건, 필요시 반을 뚜욱~ 잘라서 디버깅 전용장비로 사용할 수 있다는 점과, MCU보드측에는 외부 확장 보드 없이도 약간의 프로토타입 회로를 추가할 수 있는 부분을 제공하는 여백의 미까지 갖쳤다는 것입니다.

JTAG 디버거(LPC Link라고 불림)는 현재 아래와 같은 칩들을 지원합니다.
LPC11xx: All products supported
LPC13xx: All products supported
LPC17xx: LPC1751 LPC1752 LPC1754 LPC17561 LPC17581 LPC1764 LPC17651 LPC17661 LPC17671 LPC17681
LPC2xxx: LPC2109 LPC2134 LPC2142 LPC2362 LPC2929
LPC3xxx: LPC3130 LPC3250


사진1. JTAG 디버거 및 평가보드 일체형 개발보드


그림1. 테스트보드 여러 이용법


개발을 하려면 칩(개발보드)과 더불어 개발환경(컴파일러 , IDE 등)이 필요한데요, 위의 삼총사님들이 다 준비해 놨습니다.  128KB이내의 작은 코드만 필요하신경우 무료로 모든 기능의 사용이 가능한 개발환경이 그냥 생깁니다.
(참고로, 조금 큰 용량이 필요하신분들도 256KB까지는 256$, 512KB까지는 512$만 투자하면 된답니다.)


1. LPCXpresso IDE 개발환경 설치

CodeRed 사의 LPCXPresso 개발환경을 설치합니다.
이때 USB드라이버 및 디버깅 보드 드라이버 등등도 함께 설치됩니다.
CodeRed사에 등록하고  128KB내에서 자유로운 사용이 가능한 라이센스를 받았습니다.
조금 번거롭지만, 용량제한말고는 제약이 없고, JTAG 디버깅 기능까지 지원하므로 기분좋습니다.

2. NXP 포럼가입
AVR과 달리 카페나 국내 기술자료가 거의 없는것 같습니다.
다른 회사 제품들은 M3급 이상의 제품이 많이 나와서 카페도 있고 왕성한 커뮤니티가 이뤄지고 있는데요
NXP제품은 전무;;; 하네요..  좋은 사이트 있으면 알려주시길
따라서, 방법은 한가지뿐이네요  NXP사 포럼에 가입하여 안되는 영어지만 눈팅이라도 하면서 배우는 수밖에 없는듯 합니다.
물론 비장의 무기인 유저 메뉴얼이 있으니, 레지스터만 섭렵하면 되지 않을까 하는 생각이 듭니다.  아닐까요?

하지만, 평가보드 구입후 개발환경 설치하면서 처음시작하는 사람을 위한 안내 자료가 있는데요
정작 가장 중요하다고 생각되는 User Manual이 잘 안보이네요.. 
(후기.알고보니 IDE 우측 하단에 링크버튼을 누르면 자료모음링크에 나오네요)
레지스터 섭렵을 하려면 필수 자료아닐까합니다.  열심히 찾아서 아래에 첨부합니다.


첨부자료:

LPCXpresso 플래폼 소개 자료 ( 테스트보드, 개발환경 등)


LPC11xx 기술문서 요약형


LPC11xx 수백페이지짜리 진짜 기술문서(User Manual)







Cortex-M0는 ARM의 가장작은 Cortex processor입니다.
12,000여 게이트로 이뤄져 있으며, 기존의 8,16bit 프로세서들의 대체를 목표하고 있습니다.  가령, 터치스크린 제어기로 8051을 사용해온 고객들이 대화면 및 멀티터치의 적용시 한계에 다다른 상황을 대체할 수 있다고 합니다.








성능 및 사양 비교


ARM 프로젝터 메니져 왈:
M3가 1.25Dmips/MHz, ARM7TDMI가 0.7Dmips/MHz인것에 비해
M0가 0.9Dmips/MHz 성능을 갖고있답니다.

전력소비도 적어져서,
M3가 210uW/MHz,180nm공정의 M0는 85uW/MHz 를 소비하고,
효율은 M3:6Dmips/mW에 비해 10Dmips/mW을 갖습니다.

ARM의 첫번째 범용 MCU인 Cortex-M3보다 간단한 코어로 이뤄졌으며,
두 코어를 구체적으로 비교하면 43,000게이트를 12,000게이트로 줄였고,
하바드 구조대신 폰노이만 구조를 갖고있으며
240개의 인터럽트를 32개로, 256가지 인터럽트 우선순위를 4단계로 줄였답니다.
명령어셋은 32bit instrunction체계를 16bit instruction 쌍으로 변경하여
코드크기도 대폭 축소하였답니다.

개발툴
파트너사인 CodeRed는 GNU tools 활용으로 저렴한 개발환경을 기획하여
현재는 128K 용량제한내에서 무료사용이 가능한 개발환경을 배포한 상태입니다.


이상, 아래의 링크 기사를 요약 소개드렸고요
참고기사: http://www.electronicsweekly.com/Articles/2009/03/04/45584/arms-cortex-m0-processor-how-it-works.htm


저도 어제 처음으로 NXP사의 ARM Cortex-M0 용 평가 보드인 LPCXpresso 를 구하여 테스트를 시작하고 있습니다. 관련글
LPC1114가 들어있는 보드로 구했는데요, AVR대체품으로 적당하다는 생각이 드네요,
하지만 AVR과 ARM사이의 장벽을 넘는일은 그리 녹녹치 않아보입니다;;

기술자료: http://infocenter.arm.com/help/index.jsp


추가내용(DEC.15)
링크1: 저의 LPCXpresso 간단 사용기
링크2: BR님의 NXP의 ARM Cortex-M0 코어 칩 LPC1000시리즈와 LPC 평가보드 사용기:  $1대의 ARM Cortex-M0 MCU, NXP LPC1000 시리즈 2 ? LPCxpresso 데모 보드 사용기


목적
피사체의 위치와 피사체가 바라보는 방향을 실시간으로 계산하는 헤드트래킹을 구현하기로 함, 이를 위해 Wiimote 두개와 IRED 3개로 구성된 표식자(태그)를 사용하였습니다.

특징
일반적으로 알려진 헤드트래킹은 피사체의 2차원 or 3차원 공간 좌표값(x,y,z) 성분만을 계산할 수 있는 제한이 있습니다.
본 3광점 태그를 이용한 헤드트래킹은 피사체의 위치와 더불어 방향벡터(로컬좌표계)까지 완전하게 계산하낼 수 있으므로 좀더 다양하게 응용할 수 있습니다.

용도
헤드 트래킹의 용도는 광범위하나 여기서는 3D 스캐닝 작업시, 여러차례 나눠서 스캐닝하지 않고, 한번에 피사체의 전체를 스캐닝하는데 활용하는 것을 가정하였습니다.

결과
헤드트래킹은 구현완료 하였으나 3D 스캐너 관련 개발은 현재 보류된 상태입니다. (3D 스캐너 관련글 링크)
One Step Full Scanning 구현은 언제가 될지 모르지만 꼭 완성하고 싶네요, 여러분이 먼저 하시렵니까??;;


방법 소개

3광점 표식자
헤드트래킹을 구현하기위해선 피사체에 고정되어 있는 정점(Vertex) 좌표값이 적어도 3개가 필요합니다. 물론 단순히 피사체의 위치벡터만 구하는 경우라면 두개의 Wiimote로 한개의 정점 좌표값만 구해도 됩니다만 이경우 정점의 3차원 좌표(x,y,z)값만을 알 수 있고 피사체의 2축 회전성분을 알수가 없으며, 정점 좌표가 2개인 경우엔 위치파악 및 2축 중 1축 회전성분을 알수 있습니다. 결국 피사체에 고정되어 있는 3개의 정점을 알아야 완전한 위치와 방향 성분을 갖는 벡터값을 구해낼 수 있습니다.

Wiimote
위모트는 한번에 4개까지의 IRED(적외선LED)광점을 인식할 수 있는 기능이 있습니다. 특정파장(940nm)의 적외선에 반응하므로 너무 밝지 않은 실내라면 별도의 장비없이도 쓸만한 광점인식 장비로 사용할 수 있습니다.  피사체에 3개의 IRED를 고정시킨 후 실시간으로 두개의 Wiimote로 그 광점들의 좌표값을 측정하는것으로 피사체의 위치와 바라보는 방향을 구할 수 있게됩니다.

3개의 정점으로 정의되는 Local 좌표계 구하기
위모트를 사용해보신 분들이라면 광점 3개를 읽어들이는것은 어렵지 않게 할 수 있습니다만, 실제 이값을 가지고 피사체의 벡터(위치와 방향)성분을 구해내는건 약간의 벡터연산에 대한 이해가 필요합니다.  사실 고등학교때부터 배워온 벡터지만,,  막상 써먹으려니 막막하더군요,  어쨌든 간만에 벡터연산 공부좀 하고 해답을 구했습니다.  정리해놓고 보면 별거 아니네요.


이제 순서대로 정리를 해보도록 하겠습니다.


1단계. 3광점의 3차원 좌표값 구하기

Wiimote 2개로 광점 3개의 2차원 좌표값들을 구하고 이값으로  3차원 좌표값 P1, P2, P3을 구해놓습니다.  이와 관련된 내용은3D 포인트 트래킹 구현하기 글에 소개되어 있습니다. 이값은 웹캠이나 기타 다른 방식으로 구할 수 도 있습니다.

준비된 결과 값:  P1(x,y,z)  P2(x,y,z)  P3(x,y,z)

2단계. 문제정의

3개의 정점으로 구성된 Local 좌표계 구하기라고 목표를 정의했지만, 사실 애매한 표현입니다. 수학적으로 엄밀한 표현까지는 아니더라도 좀더 구체적인 정의가 필요합니다.  그림으로 표현하는게 가장 이해하기 쉬울듯 합니다. 정의 방법에 따라 무수히 다른 방식의 좌표계 정의를 내릴 수 있을텐데요, 여기선 단계적으로 손쉽게 이해하고 계산하기 쉬운 방식으로 정의하겠습니다.



그림. 로컬 좌표계와 P1,P2,P3 관계 정의도

3단계. 계산하기

우리가 구해야할 값은 위 그림에서 u1,u2,u3로 표현된 벡터값 입니다.  각각 Local좌표계의 x,y,z축에 해당하는 벡터입니다. 헤드 트래킹의 경우, 월드좌표계안에서 헤드의 위치와 방향을 바로 이 좌표계 정보로 표현 한다는 개념입니다.
아래의 수식은 실제로 Away3D라는 플래시 3D엔진에서 Number3D 자료형의 벡터연산 메소드(함수)를 이용하여 계산하는 예입니다.  벡터 빼기 연산은 sub() 로, 벡터 외적 연산은 cross() 로 표기됩니다.

  P1->P2 를 벡터A 로 정의합니다.
  P1->P3 을 벡터B 로 정의합니다.

A.sub( P1 , P2);
B.sub( P1 , P3);

  이제 위 정보로 u1,u2,u3를 구합니다. 이때 방향성분이 중요하고 크기(길이)는 중요치 않습니다.
  (참고로 위 그림에서 u벡터들의 길이는 실제값이 아니고 임의의 크기로 표현했음에 주의바랍니다.)
  여기선, 두 벡터를 외적(Cross Prduct)하면 서로 직교하는 제 3의 벡터를 구할 수 있다는 것을 응용합니다.
  첫번째 로컬 좌표축 성분 벡터인 u1은 A와 B의 벡터 합으로 정의하고
  두번째 로컬 좌표축 성분 벡터인 u2는 A와 B의 외적으로 정합니다.
  세번째 로컬 좌표축 성분 벡터인 u3는 u1과 u2의 외적으로 구합니다.

u1.add( A, B);
u2.cross( A, B);
u3.cross( u2,u1);

위 연산으로 벌써 결과가 구해졌습니다. 벡터연산 함수를 사용하면 뺄셈 2번, 덧셈 1번, 곱셈2번으로 끝나는 매우 간단한 연산입니다. 이렇게 구한 벡터 3개는 모두 나머지 두 벡터와 직교하는 벡터가 되며, 로컬좌표계의 3개의 축 정보로 사용할 수 있습니다. 보통 좌표계의 축벡터는 크기가 중요하지 않으므로, 아래와 같이 크기가 1인 단위벡터로 변환하는 연산(Normalize)을 해줍니다.  위 그림에서는 u1,u2,u3 벡터를 단위길이 벡터로 변환한 것이 ^u1, ^u2, ^u3 로 표현되었습니다.

u1.normalize();
u2.normalize();
u3.normalize();


결과값과 활용


여기서 구한  u1,u2,u3를 이용하여 로컬좌표계를 정의할 수 있고, 월드좌표계와 좌표계변환 연산등을 할 수 있습니다. 좌표계 변환은 행렬연산과 관련된 또다른 주제가 됩니다. 그 부분은 기회가 되면 Away3D같은 3D 엔진 예제와 함께 설명 드릴 예정입니다.  계획했던 연관 프로젝트 진행이 중단되어 아직 보여드릴 만한 응용예제가 없네요, 추후 예제가 생기면 추가하겠습니다. 아래의 이미지는 실제 헤드트래킹 과정을 기록해둔 동영상의 한장면을 캡쳐한 것입니다. 머리의 움직임에따라 우측에 보이는 화면속 삼각형(+로컬좌표축)의 위치와 방향이 변합니다.


사진. 헤드트래킹 장면 예

우측 부분에 월드 좌표축과 삼각형 위에 붙은 작은 좌표축(헤드의 로컬좌표축)이 희미하게나마 보입니다.

끝으로
헤드트래킹을 구현한지가 벌써 반년이 넘어버렸습니다. 그동안 정리는 뒤로 미루고 새로운 일을 벌리곤 했지만 지나보니 정리를 안해놓으니 남는게 없네요;;  앞으로라도 좀더 정리된 자료를 만드는 습관을 들여서 개인 프로젝트 히스토리 관리도 하고 약간이나마 공공지식에의 공언도 해야겠다는 생각이 듭니다.  그러나,,,오랜만에 그림 하나 그리는데 왜이리 힘든지요 ^^;;


관련링크

1. 외적(Cross Product)연산 : wikipedia
2. 1광점 트래킹하기 (3차원 좌표값 실시간추적)

목표
저렴한 비용으로 로봇이 말하고 노래하게 만들기위한 방법 소개

방법 소개
이미 MP3Play 보드나 칩이 시장에 많이 나와있습니다...  다만, 값이 비싸다는 문제가 있습니다. 직접 제작하거나 제작KIT를 사용하면 비용이 5~10만원이 넘어갑니다.  때문에 시중에 판매되고 있는 MP3Player의 개조하여 사용하는것을 고려해봤지만, 막상 개조하려해도 쉽지가 않습니다.

그러던 중 리모컨으로 제어되는 제품을 리모컨 신호를 송출하는 깔끔한 방법으로 제어한다는 아이디어가 떠올랐는데요,  이방법은 MP3Player 뿐만이 아니라, TV,에어콘 등등의 가전기기도 덤으로 제어하여 이용할 수 있는 가능성이 있으므로 여러모로 활용성이 좋은 아이디어인것 같아 소개드립니다.

여러분이 이미 로봇 제어기(MCU)를 갖고 계시다면, 필요한건 IRED 1개와 TR 1개, 저항 1~2개 뿐이고,  디지탈 출력핀 1개와 약간의 프로그램이 추가되면 됩니다.  여기선 이와 관련된 기본 이론 소개와 관련 자료를 첨부하도록 하겠습니다.

사진. MP3Player+Speaker 기기 분해 사진

스피커와 배터리까지 포함되어 있는데 가격은 배송비 포함하여 2만원이 안됩니다.

여기선 말하는 로봇 대신 음악재생을 제어하는 동영상을 보여드리겠습니다.

동영상. 제어신호 송출로 재생/중지 제어 하는 예


리모컨 프로토콜

기계들이 의사소통을 하기위한 약속된 규칙을 프로토콜이라고 하는데요, 리모컨(리모트컨트롤러)과 수신기는 서로 동일한 프로토콜을 사용하여야 합니다. 하지만 각 제조사 및 기기별로 다양한 프로토콜을 사용하므로 호환성에 문제가 많은게 현실입니다. 하지만, 최근에 사용되는 많은 전자기기들이 NEC 코드를 사용하는 것으로 알고 있습니다. 때문에 일단 NEC코드를 기준으로 소개시켜 드리겠습니다.


NEC 코드 전송 규약

아래의 자료는 실제 리모컨에 사용되고 있는 IR신호 송출칩 DataSheet에 기록된 다이어그램입니다.  (첨부파일 참조)

그림. 전송규약 파형 안내도

캐리어 신호
 우선 리모컨 신호의 캐리어 주파수인 38KHz 주기의 방형파를 생성해야합니다. (위 그림 하단부 참조)  이는 타이머/카운터를 이용하여 만들 수 있습니다. Duty는 약 1/3정도를 권장하고 있습니다만, 손쉽게 하려면 50%로도 가능합니다.

캐리어 신호를 On Off한다.
위에서 만든 캐리어 주파수 파형을 약속된 시간만큼 On Off 하는것으로 리모컨 신호를 송출할 수 있습니다.
이 출력값은 그대로 출력비트에 연결된 IRED 구동회로에 전달되어 적외선의 On Off 상태로 전환되어 송출됩니다.

전송규약에 맞쳐 On Off
이제 약속된 파형을 송출합니다. 송출신호는 크게 3가지로 부분으로 나눌 수 있습니다.


1.시작코드

9ms의 High, 4.5ms의 Low 신호로 코드의 시작을 알립니다. 위 그림(1)부분 참조

2.데이타 코드열
시작신호 이후부터 bit data 1은 2.25ms 폭의 신호로  bit 0은 1.125ms 폭의 신호로 송출됩니다. 위 그림(2)부분 참조
보통 16 data bits를 순서대로 보낸 후, 비트 반전한 정보를 다시한번 송출하는 것으로 마무리됩니다.
비트 반전후 전송하는 과정에 의해 오차도 줄일수 있고, bit data의 1과 0의수와 관계없이 항상 동일한 폭이 됩니다.

3.반복코드
만약 숫자 3 버튼을 누른상태를 유지한다면 리모컨은 숫자 3에 해당하는 코드를 송출한 뒤 그 다음 부터는 "반복코드"를 송출하게됩니다. 이러한 방법을 사용하는것은 3을 1회 누른것과 2회 누른것을 구분하기 위함인듯 합니다.
반복코드는 위 그림(3) 부분같은 형태입니다. 

캐리어주파수(38KHz)를 사용하는 이유는 노이즈 제거를 위한것입니다.  IR수신회로에는 저주파 차단회로가 들어있어서 특정 주파수(가령 38KHz)이하의 성분을 제거해버립니다. 이로인해 형광등이나 기타 주변광에 의한 오차발생 소지를 줄일 수 있습니다.



IRED(적외선LED) 드라이브 회로

우선, IR수신회로에서 사용하는 수광소자의 주파수를 확인하여 송출용 IRED의 주파수를 결정합니다. 보통 8xx ~9xx nm 파장의 IRED가 사용됩니다. 제경우 940nm IRED(Wii전자펜제작용)와 940nm용 IR수신기가 있습니다.  수신기에서 사용하는 주파수를 잘 모르더라도 가까운 거리에서 사용할 경우 큰 문제가 되지 않으므로 주변에서 구할 수있는 IRED를 우선 사용해보시기 바랍니다.  또 하나 확인할 것은 구동 전압입니다. 일반 LED(2V)와 달리 IRED는 보통 1.4V 정도에서 작동합니다.
가장 단순한 구동법으로 디지탈 출력핀에 직결하는 방법도 있습니다만, 10미터 정도의 거리에서도 작동되는 고출력 리모컨을 원한다면 트랜지스터 한개로 구동하는것을 추천드립니다. 가령, 아래의 회로는 실제 리모컨에 사용되는 회로의 예입니다. (첨부문서참조) 짧은 순간에 고주파로 송신하게 되므로 실제의 정격전압보다는 다소 높은 전압을 사용할 수 있습니다.  아래의 경우는 건전지로 3V정도의 전압을 사용하는 경우입니다.



그림. 리모콘 송출용 IRED 구동회로 예



리모컨 기기 코드 분석하기

리모컨 신호의 코드를 분석해주는 전용 기기도 있지만, 오실로스코프를 이용하면 직접 코드 프로토콜의 종류와 코드값을 알아낼 수 있습니다.  제가 참고한 NEC코드의 경우 코드 송출시 2바이트의 정보가 송신됩니다.  1바이트는 장치번호이고 나머지 1바이트가 명령 코드입니다. 따라서 총 16비트입니다만 위에서 언급했듯이 반전비트를 전송하므로 총 32비트 정보가 송출되게 됩니다.  코드 분석을 위해선 IR신호 수신기가 필요한데요, 전용의 리모컨 IR수신 모듈이나 IR 포토트랜지스터가 있으면 됩니다.  IR수신 모듈 사용법은 첨부된 자료를 보시면 나옵니다.  전원 핀 2개에 5V, GND 입력을 하면 나머지 핀에서 아래 사진과 같은 신호가(전압변화) 출력됩니다.

리모컨 송신 신호 파형 실제 예

아래의 사진은 제가 갖고있는 리모컨들의 파형을 오실로스코프로 캡쳐한 것입니다. 왼편 두개는 좀 오래된 VTR과 CDP용 리모컨이고, 우측 두개는 비교적 최신의 전자제품용으로 LCD모니터 및 MP3Player용 리모컨입니다. 보시는 바와 같이 왼쪽과 오른쪽이 시작파형이 다릅니다. 오른쪽의 두 리모컨이 최근 많이 사용되고있는 NEC 코드 파형입니다. 전송규약을 잘 이해한 후엔 어떤 리모컨용 수신기도 만들수 있게됩니다. 반대로 어떤 리모컨수신 기기도 제어할 수 있게됩니다.  본 파형을 잘 보고 2바이트 값을 알아내야 합니다. 그중 1바이트는 항상 같을 겁니다. 즉, 기기번호입니다.  가령 제가 갖고 있는 MP3P의경우 0x02 의 기기번호를 갖고 있습니다. 그리고 나머지 한 바이트가 명령 코드입니다.  가령 Play/Pause버튼의 경우 0x06 입니다. 이 값을 잘 정리해둔 뒤 리모컨 송출 코드로 발송하면 기기는 명령을 받은대로 작동하게 됩니다.  전용 리모컨 대신 직접 만들어낸 송출 신호에 의해 기기가 작동하게되면,,, 기분, 좋습니다. ^^



오실로스코프


안타깝게도 여러분이 오실로스코프가 없다면, 리모컨 코드를 알아내기가 좀 어려울 겁니다. 하지만 불가능한건 아니고, 보유하고계신 MCU로 샘플링하여 계산해 낼 수 는 있습니다.  하지만 본격적인 전자회로 공부를 하시려한다면 오실로스코프 구입을강력 추천합니다. 저도 구입하고 싶다는 생각만 갖고 몇년을 보냈는데, 막상 구입하고나서 너무도 유용하게 사용하고 있습니다.  사양에 욕심을 내자니 가격이 너무 높고,  저렴한 중고를 사려해도  구형 허큘리스 모니터 같이 생긴 녀석에게 신뢰가 가질 않았습니다.  그래서 제가 선택한것이 USB형 오실로스코프입니다. 40MHz 급의 새제품을 20~40만원 선에 구할 수 있습니다.  참고하세요~   



끝으로
초보분들에겐 부족한 내용일듯합니다. 하지만 아이디어와 힌트를 드렸으니 조금만 자료조사하고 노력하시면 좋은 결과물을 얻으실 수 있을겁니다.  재밌는 로봇 많이 만드시고,,, 더불어 제게도 알려주시면 감사하겠습니다.


참고자료
리모컨ic-SC6121.pdf
다운로드
IR수광모듈예.pdf
다운로드




내용추가
2011.July.26 
아래의 관련글 링크에 리모콘 신호 송수신 회로와  PC에서 키보드 입력으로 로봇을 제어하는 소스 예제를 포함한 글을 새로 등록하였습니다. 참고하세요

 

관련글 링크

 .IR무선 리모콘 송수신 회로로 로봇 제어하기

 

 

 



오늘은 이상한 녀석을 소개시켜 드리고자 합니다.



겉모습을 보자면 우편함을 뒤집어 놓은 것입니다만, 몇 가지 특이한 기술이 적용된 음악재생기 입니다.
사운드 카드를 통해 디지탈 신호를 전달하고 이를 해석하여 본래의 디지탈 신호를 복원하는 기술을 통해 로봇을 제어하는 것인데요, 쉽게 말하면 사운드 카드용 모뎀을 만들어서 로봇제어에 사용하는 예를 보여드리겠습니다.

모뎀이 뭐냐고요? 

글쎄요... 다시 설명하자면, 디지탈 신호를 전화선 같은 교류 음성 라인용으로 신호로 변환시킨 후, 수신측에서는 다시 이를 역변환하여 본래의 신호를 복원해주는 기기입니다. Modulator(변조) + DeModulator(복조)의 합성어라고 알고있습니다. 90년대 PC통신 문화를 지탱해왔다가 지금은 사라져버린 역사적인 기기랍니다. 자세한건 고글,네버,담,야호 등에게 물어보시기 바랍니다.

신호 전달 단계

디지탈신호 -> [사운드카드] -> 신호 포함된 사운드파형 -> [신호변환기] -> 디지탈신호 -> [임베디드 기기]

사운드카드와 신호변환기가 필요하며, 소프트웨어는 사운드 파형을 제어하여 디지탈 신호를 실어주는 프로그램과,
이 사운드 파형에서 디지탈 신호를 해석하는 프로그램이 필요합니다.


자 이제부터 사운드 통신을 우체통 뮤직 로봇 (MP3Play Robot)에 적용한 예를 보여드리겠습니다.




동영상. 뮤직로봇 작동만 하는 동영상

아래는 관련 기술을 설명하는 동영상입니다.  영상품질이 매우 안좋습니다. 양해바랍니다.

음악들려주는 우편함 로봇 동영상 시연 내용 정리

. 외형을 둘러보면 전원선과 사운드 통신선이 있습니다.
. 전원을 켜면 자동으로 음악이 재생되는 상태입니다.
. 현재는, 주변상황에 반응하지 않는 상태입니다.

. PC측 플래시 어플리케이션(리모컨제어기)을 실행합니다.
. 사운드 라인을 PC측 사운드 출력에 연결합니다.
. 플래시 어플내 버튼을 누르면 리모콘 제어가 가능합니다.

. 다음은 프로그래밍 환경(플래시 어플리케이션)을 뛰웁니다.
. 코드를 불러와서 컴파일하고 사운드카드를 통해 로봇으로 전송합니다.
. 이제부터는 로봇 내부의 센서와 버튼으로 작동가능합니다.

. 로봇의 양눈에 설치된 거리센서에 접근하면 프로그램된 기능이 수행됩니다.
. 현재는 재생/정지와 다음곡 듣기 기능이 프로그램되어 있습니다.
. 재생/정지가됩니다.
. Next 다음곡 재생하기가 됩니다.
. 버튼으로 트랙1번 재생도 가능합니다.

. 프로그램를 변경하여 전송하면 그에따라  다른 기능의 수행이 가능합니다.
. 제손이 너무 두꺼비 손 같네요 ㅡㅡ;;  양해바랍니다.



동영상. 세부 기술 소개 (사운드 통신 및 프로그래밍 기능)


응용 범위

플래시 및 기타 응용 프로그램에서의 임베디드기기 제어
MP3Player, Radio, PMP, Mobile Phone 등의 사운드출력가능한 모든기기에 적용 가능.


특장점

보통 로봇을 제어하거나 프로그래밍을 하려면,  시리얼 포트나 USB포트를 이용하게 됩니다. 이를 위해 별도의 하드웨어를 구입하거나 장착 및 설정하는 과정이 필요합니다.  사운드 통신선을 이용하면, 보셨듯이 사운드 출력 라인만 있으면 됩니다.
MP3Player나, 특히 휴대폰과 스마트폰에 응용이 가능합니다.  현재 안드로이드 폰에서 신호변환 출력이 정상 작동하는 것을 확인했습니다.  아이폰도 물론 가능합니다만,,, 제가 아이폰 개발환경이 없습니다 ;;;


제품화 아이디어 - Sound to Serial 변환기

Sound to Serial변환기란 시중에서 판매되고 있는 USB to Serial변환기와 유사한 용도로 사용할 수 있습니다. 차이점은 USB포트가 필요없으므로 사운드 출력이 가능한 모든 디지탈 기기에서 사용할 수 있다는 장점이 있습니다. 특히 모바일폰에 곧바로 적용 가능한 기술입니다. 가령 로봇제어에 3G네트웍이 필요할 경우, 로봇의 시리얼 포트와 휴대폰의 사운드출력 단자에 Sound to Serial 변환기를 꽂아주면 됩니다.  물론 적절한 프로그램이 구현되어야 합니다.  실용신안 등록까지 고려해본 기술입니다만, 상업적 가치는 글쎄요?? 입니다.  추가적으로 안드로이드폰으로 응용가능한 매우 재밌는 응용예가 있는데요, 어찌저찌해서 최신형 안드로이드폰이 생긴다면 그때 따로 보여드리도록 하겠습니다.


본 기술의 문제점

호환성: 대부분의 PC 사운드 카드에서 정상 작동하는데 간혹 사운드 음량이 너무 작거나, 기타 상황에 따라 인식이 안되는 경우가 있을수 있습니다. 하지만 이부분은 신호변환기를 보완하면 해결 될 수 있는 문제 같습니다.

속도: 보통 PC급 사운드 카드에서 지원하는 Sampling Rate이 44100Hz 이하이며,  이는 전송 데이타속도의 제한과 연계됩니다. 적은 값은 아니지만, 최근의 고속통신 디바이스들에 비하면 저속 통신만 지원 가능합니다.

단방향성: 현재 사운드 카드 출력 통신만(단방향) 개발했습니다.  하지만,  마이크 입력을 통해 반대 방향 입력도 가능합니다.




신호변환기

디지탈 신호를 사운드 파형으로 변환하고 사운드 신호에서 디지탈 신호로 변환해주는 회로를 간소화 하기 위한 기법을 사용하였으므로 신호변환을 위한 전자회로가 매우 단순합니다.  OPAmp와 저항 콘덴서 몇개면 가능합니다.  이보더 더 단순화 하여 트랜지스터 몇개로 구성하는 방법도 있습니다.  이정도 회로만으로도 MCU측에서 직접 해석 가능한 디지털 신호로 변환을 해줄 수 있습니다.  또는 신호변환기에 저사양 MCU를 장착하여 시리얼 통신 규약에 맞도록 변환시켜 줄 수 도 있는데, 그렇게 되면 바로 Sound to Serial 변환기가 됩니다.


변환기의 종류

Sound to TTL, Sound to Serial, USB Sound Card to TTL, USB Sound Card to Serial,,,
위와 같이 여러가지 용도별로 인터페이스 보드를 구성할 수 있습니다. 아래의 경우는 USB 사운드카드를 내장한 형태의 신혼변환기를 제작한 예입니다. 즉, PC에 내장된 사운드카드 대신 전용의 USB 사운드카드를 이용하는 예입니다.



사진. USB Sound Card to TTL 제작 예




목표
2대의 Wiimote를 이용하여 3D 공간에 위치한 광점(IRED)의 x,y,z 좌표값을 구한다.

본 기능은 다음의 경우에 응용할 수 있습니다.
1. 3D 스캐너 만들기
2. 헤드 트래킹(단순 위치 파악형 및 3광점 헤드 트래킹)
3. 3D 마우스

※ 3광점 헤드 트래킹:
3개의 IRED를 이용하면 단순히 위치를 파악하는것 뿐아니라 어느방향을 바라보는지도 알수 있습니다. 관련링크 참조

준비물
Wiimote 2개,  IRED(적외선LED) (참고링크2 참조) 
기타 Wiimote 사용을 위해 필요한 게이트웨이 SW 및 BT 장치 등.

Wiimote 설치 및 연동
Wiimote와 Flash를 연동하는 방법은  참고링크1.을 참고하시기 바랍니다. 

Wiimote로 측정 가능한 정보
wiimote에는 3축 가속센서, 여러개의 버튼이 포함되어있고, 내장된 적외선 카메라로 적외선 광점의 좌표값을 4개까지 인식할 수 있습니다. 물론 wiimote에서 출력해주는 좌표값은 카메라 스크린을 기준으로한 x,y 좌표(2D)좌료 값이므로 이것만으로는 3D좌표값을 구할수 없습니다. 하지만 wiimote를 2개 이상 사용한다면, 이 값들의 조합으로 3D 좌표값을 구해 낼 수 있습니다.
참고로 일반적인 WebCam으로도 가능합니다. 다만 wiimote를 사용하므로써 광점을 인식처리해주는 이미지 처리과정이 필요없고, wiimote의 기타 센서 기능을 함께 사용할 수 있으므로 목적에따라 선택하여 사용하면 됩니다.
아래의 이미지는 WiiFlash Server에서 기본 제공되는 데모 실행화면입니다. 버튼의 눌림상태와 각종 센서들의 수치값이 실시간으로 보여지는 것을 볼 수있습니다.




예제 소스
아래에 첨부된 소스는 Wiimote 2개( WA와 WB)를 이용하여  3차원공간상에 위치한 광점(ir Point)의 좌표값을 계산하는 예제 소스입니다. 저는 이를 기초로하여 3D 스캐너와 헤드트래킹을 구현했습니다. 좀더 고급 수학을 이용한 복잡한 방법이 있을듯 합니다만  저는 잘 모르고요, 제가 아는 범위의 단순한 삼각함수를 이용했습니다. 중.고등학교 과정의 수학이면 이해 가능할 듯 합니다.

package{
	import org.wiiflash.Wiimote;
	import org.wiiflash.events.ButtonEvent;
	import org.wiiflash.events.WiimoteEvent;
	import flash.events.*;
	import flash.display.*;
	import flash.text.TextField;
	
	public class PositionDetector extends Sprite{

		public const D2R:Number = Math.PI / 180;
		public const R2D:Number = 180 / Math.PI;
		// Calibration 수치
		public const IRX2DEG:Number = 41;
		public const IRY2DEG:Number = 32;
		private var L:Number = 500;				//500mm
		private var WA_LRCenterDeg:Number = 60;
		private var WA_UDCenterDeg:Number = 0;
		private var WB_LRCenterDeg:Number = 120;
		private var WB_UDCenterDeg:Number = 0;

		// p(x,y,z)산출 기본자료
		private var WAirx:Number;
		private var WAiry:Number;
		private var WBirx:Number;
		private var WBiry:Number;

		private var p1x:Number;
		private var p1y:Number;
		private var p1z:Number;

		// create a new Wiimote
		private var WA:Wiimote = new Wiimote();
		private var WB:Wiimote = new Wiimote();
				
		public function PositionDetector(){
			//ir value update EventListener 설정
			WA.addEventListener( Event.CONNECT, onWiimoteConnect );
			WA.addEventListener( IOErrorEvent.IO_ERROR, onWiimoteConnectError );
			WA.addEventListener( Event.CLOSE, onCloseConnection );
			WA.addEventListener( WiimoteEvent.UPDATE, WiimoteAUpdateHandler );
			WB.addEventListener( Event.CONNECT, onWiimoteConnect );
			WB.addEventListener( IOErrorEvent.IO_ERROR, onWiimoteConnectError );
			WB.addEventListener( Event.CLOSE, onCloseConnection );
			WB.addEventListener( WiimoteEvent.UPDATE, WiimoteBUpdateHandler );								
			WA.connect ();
			WB.connect ();
			Canvas2D.point.visible = false;
		}

		function onCloseConnection ( pEvent:Event ):void{
			trace("onClose: " + pEvent.target );
		}
		
		function onWiimoteConnectError ( pEvent:IOErrorEvent ):void{
			trace("onError: " + pEvent.target );
		}
		
		function onWiimoteConnect ( pEvent:Event ):void{
			trace( "Wiimote successfully connected: " + pEvent.target );
		}		

		public function WiimoteAUpdateHandler(pEvent:WiimoteEvent){
			if(pEvent.target.ir.p1){	
				WAirx = WA.ir.x1;
				WAiry = WA.ir.y1;
			}			
		}
		public function WiimoteBUpdateHandler(pEvent:WiimoteEvent){
			if(pEvent.target.ir.p1){	
				WBirx = WB.ir.x1;
				WBiry = WB.ir.y1;
				Canvas2D.point.visible = true;				
				CalcProcess();
			}else{
				Canvas2D.point.visible = false;
			}
		}
		public function CalcProcess(){
			//irx => WADeg => WAm(기울기)  , WBm도함께
			var WADeg:Number = WA_LRCenterDeg - ( WAirx - 0.5 ) * IRX2DEG;
			var WAm:Number = Math.tan( WADeg * D2R);
			trace( WADeg, WAm);
			var WBDeg:Number = WB_LRCenterDeg - ( WBirx - 0.5 ) * IRX2DEG;
			var WBm:Number = Math.tan( WBDeg * D2R);

			// 기울기를 알고있는 두 선분의 교점P(x,z) 구하기  
			// WA는 (0,0)  WB는 (L,0)을 지나는경우이며,  WA/WB 수평평면이 x/z 평면이다.
			p1x = ( -WBm * L ) / ( WAm - WBm ) ;
			p1z = WAm * p1x;

			// py구하기
			var Lxz:Number = Math.sqrt( p1x * p1x + p1z * p1z ) ;
			var WA_UDDeg:Number = WA_UDCenterDeg - ( WAiry - 0.5 ) * IRY2DEG;
			p1y = - Math.tan( WA_UDDeg *D2R ) * Lxz;

			// p(x,y,z)표시
			PointXYZ.text = "px = " + String(p1x);
			PointXYZ.text += "\npy = " + String(p1y);
			PointXYZ.text += "\npz = " + String(p1z);			
			
			var Lcan = Canvas2D.WB.x - Canvas2D.WA.x;
			Canvas2D.point.x = Canvas2D.WA.x + p1x  * Lcan / L;
			Canvas2D.point.y = Canvas2D.WA.y - p1z * Lcan / L;
		}
	}
}


예제 소스 설명

1. 장비 설치에 따른 수치 정의
측정하기 전에 WA와 WB의 world좌표상의 거리 L과  x축을 기준으로 한 회전각을 정의합니다.
좀더 노력하면 자동으로 Calibration하여 이값들을 구해낼 수 도 있으나, 본 예제는 기초적인 수학으로 3차원 자표값을 구해내는것을 목표로 하므로, 단순하게 직접 측정하여 기입하는 방식을 사용합니다.
 정의되야할 정보는 아래와 같습니다.

private var L:Number = 500;                           // WA와 WB 사이의 거리, 이경우 500mm
private var WA_LRCenterDeg:Number = 60;      // WA의 좌우 회전각 (Deg)
private var WA_UDCenterDeg:Number = 0;        // WA의 상하 회전각
private var WB_LRCenterDeg:Number = 120;     // WB의 좌우 회전각
private var WB_UDCenterDeg:Number = 0;        // WB의 좌우 회전각
public const IRX2DEG:Number = 41;                // Wiimote의 수평 화각이다.  (측정 값이며 오차있음)
public const IRY2DEG:Number = 32;                // Wiimote의 수직 화각이다.  (측정 값이며 오차있음)


그림1. Wiimote 설정치 참조도 (xz평면도)

2. 작동프로세스
Wiimote의 update 이벤트 발생시마다,  WA,WB모두에서 irPoint 가 발견될 경우에만 WA,WB의 irx,iry를 구한 뒤, p(x,y,z) 값  px,py,pz을 구합니다.


3. 실제 좌표값을 구하는 수학은 간단한 삼각함수를 이용합니다.  소스를 보시고 이해해 보시거나 직접 삼각함수로 연산을 해보시면 됩니다. 단, 한가지 알아둘 사항은 Wiimote에서 출력해주는 좌표값은 0~1 사이의 값이기 때문에 이값을 각도에 해당하는 값으로 변환해줘야 삼각함수 연산이 가능합니다.  이때문에 Wiimote의 화각정보를 미리 측정해 둬야하는데요, 가령 Wiimote의 좌우방향 화각이 30도라고 합시다.   이경우 광점이 가장 왼쪽경계에서 발견된다면  wiimote의 irx값은 0으로 출력됩니다.  그리고 만약 우측 경계부분에서 광점이 발견되면 irx의 값은 1이 됩니다.  또한 Wiimote 화각의 중심점에서 발견될 경우 이값은 정확이 0.5로 출력됩니다.

즉, 아래와 같이 변환될 수 있습니다.
 irx  0  0.25  0.5 0.75
1
중심기준 각도(deg)
 -15  -7.5 0
 7.5  15

실제 코드상에서는 아래와 같이 계산합니다.
var WADeg:Number = WA_LRCenterDeg - ( WAirx - 0.5 ) * IRX2DEG;


추가로, D2R 과 R2D 는 Deg각도 값과 Radian값을 변환해주는 상수 값입니다. 
Degree값을 Radian값으로 바꾸려면 D2R을 곱해주면 됩니다.  마찬가지로 Rad를 Deg로 변환하려면 R2D값을 곱해주면 됩니다.




동영상1. 3차원 좌표값 실시간 구하기


사진1. 설치예



웹캠으로 만드는 플래시 센서 박스(Flash Sensor Box) 입니다.


[사진1] 플래시 센서박스 - 뽀샤시 이미지


플래시는 현존 최고의 UI 구현용 개발환경 중 하나일 것입니다.
하지만, 모니터와 키보드, 그리고 마우스라는 인터페이스 요소의 한계가 분명히 존재합니다. 최근에는 기능이 보강되면서 웹캠등의 장치를 이용할 수 있게되었고, 소켓통신이 가능해지는 등 여러가지 외장 디바이스와 연동할 수 있는 방법이 생겨나게 되었습니다.

그럼에도,  조이스틱, 시리얼통신, 블루투스통신 등이 지원되지 않는것은 여전합니다. 특히 시리얼 통신은 디지탈 기기간의 데이타 통신을 위한 가장 기초적인 통신 수단임에도 지원되지 않고 있으므로 직접 제작한 장치와 플래시를 연동하려 할때 번거로운 단계를 거쳐야 하는 상황입니다.

즉, 시리얼 통신을 위해서 소켓통신을 해야하는 상황이고,  이를 위한 중계 프로그램(시리얼:소켓통신 변환)을 별도로 실행하고 부가적인 설정작업이 필요합니다. 뿐만 아니라 최근에는 시리얼포트가 아예 없는 PC나 노트북이 대부분인지라 USB to Serial 변환기를 구입해야합니다.

그뿐이 아닙니다. 센서 입력값을 처리해서 시리얼통신으로 보내주는 MCU(마이크로 컨트롤러 유닛:소형임베디드컴퓨터)가 필요합니다. 정리하면, 가령 직접 제작한 스위치 입력을 플래시에서 감지하기 위해서 아래의 절차와 구성품이 필요합니다.

MCU(AVR,PIC,Arm등의 소형 임베디드 컴퓨터)의 장치에 스위치를 연결하고,
스위치 작동값을 이 MCU가 감지한 결과를 시리얼 통신으로 PC에 전달하면,
PC에선 이를 게이트웨이 프로그램을 경유하여 소켓통신으로 플래시에 전달하고,
이를 감지하게 된다는 구조입니다.

스위치 한개 입력 받으려고, 중계소프트웨어, 중계소형컴퓨터, 중계시리얼변환기가 필요하다는 얘기입니다.
정밀한 제어가 아닌 미디어 아트나 실험적 외장디바이스의 연동을 위해서 사용되는 자원치고는 낭비가 많습니다.
미디어 아트를 제작하려는 많은 분들은 이런 번거로운 절차를 거쳐서야 비로소 아트를 시작할 수 있게됩니다.
때문에 아트 좀 하려고 전자공학을 공부해야 할 판입니다.

때문에 이를 개선 할 방법을 고안하다가 만들게 된 것중 하나가 플래시 센서박스입니다.(다른것도 있습니다)
본래 웹캠에서 캡쳐된 이미지를 실시간 영상처리하는 부분을 제작하다가 아이디어를 얻어서 만들게 되었는데요,
(참고적으로 요즘? 유행하고 있는 AR증강현실도 바로 웹캠을 응용하는 좋은 예 입니다.)

즉, 스위치 입력같은 외부 신호를 카메라 영상으로 캡쳐한 뒤 감지한다는 겁니다.

작동 원리는 매우 간단합니다.
센서나 스위치의 입력값에 해당하는 수치를 LED(발광다이오드)의 ON OFF나 밝기 정보로 변환하고
플래시는 웹캠에서 캡쳐한 이미지로 이를 감지한다는 것입니다.

이것으로 <THE END>. 끝입니다.

LED 켜고 끌 수 있는 정도의 전자회로 지식만으로 회로를 꾸밀 수 있습니다.
나머지는, 플래시 측에서 웹캠 이미지를 읽어서 약간의 해석작업을 해주면 됩니다.
이부분은 플래시 개발자 분들이라면 누구나 하실 수 있을겁니다.

최근 저가형 웹캠의 가격이 1만원 내외로 구매가 가능하므로, 여러용도로 활용하는데 부담이 없습니다.
게다가 아무리 사양이 떨어지는 웹캠이라도 35만화소 이상의 해상도를 갖고 있으므로
스위치 수십개 입력정도는 플래시에서 지원되는 어떤 범용 웹캠이라도 가능합니다.

장점
1. 시리얼통신 미사용 및 USB2Serial변환기 불필요
2. 게이트웨이 중계 프로그램 불필요.
3. MCU같은 별도의 컨트롤러 불필요
4. 100개 이상의 스위치 입력 가능  (이경우 일반 MCU로 구현하는것보다 비용도 절약되고 훨씬 수월합니다.)
5. 플래시 이벤트 지원 (프로그래머 입장에선 MouseDown 이벤트와 같은 방식으로 이용가능합니다.)

재료
: 웹캠까지 포함해서 재료비는 1~2만원 정도로 제작 가능합니다.

1. 웹캠
2. 스위치(or 센서)
3. LED보드: 회로기판에 필요한 수량의 LED를 장착합니다.
4. 센서박스: 속이 검은 박스를 구성합니다. 상자가 아니더라도 외부광을 차단할 수 있는 공간이면 됩니다.
 

작동 흐름도

1. 스위치나 센서가 On/ Off 됩니다.
2. 스위치나 센서 상태에 따라 LED가 On/Off 됩니다.
3. 암실에 설치된 웹캠에서 LED 이미지를 캡쳐합니다.
4. 캡쳐된 이미지를 해석하여 스위치나 센서의 On/Off 상태를 감지합니다.
5. 적절한 상태 변수값 변경 or 이벤트를 발생합니다.

구현 팁

1. 일반 LED들이 보통 2V정도의 전압에서 작동되므로 사용 전원에 따른 전류 제한용 저항이 필요하게됩니다.
 하지만 일부 특수 LED들은 1.5V건전지를 직결하여 작동하므로 저항없이 건전지 한개로 ON/OFF스위치 구현이 가능합니다.
 
2. 소수의 LED를 사용한다면, 각각의 간격을 충분히 넓혀서 서로간의 간섭을 없앨 수 있습니다.(빛이 너무 밝으면 번집니다.)
 하지만 수십개의 LED를 사용한다면 서로간의 간격을 넓히기 곤란하며, 또한 사용하는 건전지나 전원의 전압이 변동되면 ON되어 있는 LED 수량에 따라  밝기가 변하곤 할 수 있습니다.  이때는 정전류 회로를 이용하여 전압이나 다른 LED 작동상태에 무관하게 일정한 밝기를 유지할 수 있습니다.
 
 
응용분야

플래시를 이용하는 미디어 아트, 로보틱스, 게임 등


기타
당연한 얘기지만, 플래시가 아닌 다른 언어환경에서도 웹캠 이미지 캡쳐만 가능하다면 사용가능합니다.


실제 구현 사례

1단계. 범용 LED 드라이버 회로로 제작
센서박스 초기버전은 일반 LED를 트랜지스터 하나로 구동하는 회로로 구성을 하였습니다.
트랜지스터(C1815나 C536등의 범용 TR) 1개와 전류제한 저항을 사용하는 회로입니다.
Base 입력에 스위치를 연결하고,  Collector단에  저항과 LED를 연결하는 일반적인 LED 구동 회로 입니다.
하지만 개수가 여럿이 될때 문제가 발생하더군요;; 바로 LED 밝기가 사용되는 전력량에 따라 변한다는것 입니다.
이를 개선하는 방법이 정전류 구동회로입니다.

2단계. IRED와 정전류 구동회로로 제작

정전류 구동회로란 구동 전압이 다소 변화 하더라도 일정한 량의 전류 흐름을 유지하는 회로입니다.
즉, 주변 상황에 따른 LED밝기의 변화를 매우 작게 할 수 있는 고급 회로 입니다. 엄청 복잡한 회로 가 될 것 같은데요,,, 실은 전류 제한용 저항의 위치만 달라질 뿐 일반적인 LED 구동회로와 유사합니다.  즉, 저항은 Collector단에 연결하지 않고,  Emiter에 연결하게됩니다.

그리고, 제 경우 건전지 한개로 작동하기 위해 1.2~1.7V 에서 작동되는 IRED를 사용하였으며, 전류량은 LED한개당 1mA 이하로 유지하였습니다.  보통 LED 구동시 전류량이 20mA 안팍인데요, 이렇게 저전류를 사용하면 오히려 장점이 많습니다.  1.5V 전지 한개로 30개의 LED를 구동하여도 30mA가 안되므로 전력소모가 적습니다. 또한 빛의 밝기를 제한하므로 바로옆에 붙어있는 또다른 LED와의 빛 번짐 현상에 따른 간섭도 없어지게 됩니다.



사진2. 웹캠이 내장되어있고 USB라인을 컴퓨터에 연결한 뒤 스위치를 누르면 작동합니다.


사진3. 내부에는 LED 장착 보드가 있습니다.


사진3. 플래시에서 캡쳐된 이미지 예




동영상1. 각각의  LED의 영역을 설정해주는 화면




참고자료
웹캠 캡쳐 및 영상처리가 처음이신 분들을 위한 간단한 발광점 찾기 예제를 첨부하였습니다.  배경을 어둡게 한 상태에서 LED나 후레쉬를 이용하여 발광점의 인식을 확인해 보실 수 있습니다.

전자칠판으로 동물원 지키기 게임을~

보통 휴대폰 사이즈로 하던 게임을 대화면으로 해보시면 느낌이 또 다르답니다.

[전자칠판-후면방사형]
 투명 아크릴판에 반투명 기름종이를 붙였습니다. 프레임은 보시다시피 옻걸이 랍니다;;


관련링크1:

적외선펜 제작용 적외선 LED 팝니다.

관련링크2:

1000원짜리 비밀펜으로 적외선펜 만들기

관련링크3:

후면반사형 전자칠판 만들기

거리센서 테스트 2번째 이야기입니다.
종전방식은 그냥 거리에 따른 출력 전압변화를 전압계로 관측하는 정도 였습니다.
이번엔 조금 더 발전하여 아듀이노 보드에서 거리센서에서 출력해주는 전압을 받은 뒤, 시리얼 통신으로 PC에 전달하고,
PC측에서는 시리얼통신으로 전송받은 수치를 그래프로 표현해주는 serial Chart 라는 프로그램으로 시각화 하는 예제가 되겠습니다.

[거리센서+아듀이노+시리얼통신+시리얼챠트 = 실시간 거리센서 파형관찰 ]

[ 동영상. 거리센서 결과를 SerialChart로 관측하기 ]

아마도 아듀이노로 할 수 있는 가장 그럴듯한 초보적 예제중 하나일듯 합니다.

1. 아듀이노 : 거리센서 Pin 연결도

 거리센서  아듀이노 보드
 +  5V
 -  GND
 V out  Analog IN 0

2. 아듀이노 Sketch 소스코드

/**  * 기본포함된 예제인 AnalogInSerial를  PC측 SerialChart 프로그램에서 인식할수 있도록 한 줄 추가한 코드입니다.  */   void setup() {   Serial.begin(9600);  }    void loop() {   // read the analog input into a variable:    int analogValue = analogRead(0) /4;    // print the result:    Serial.print(analogValue);       Serial.println("");   //serialChart 프로그램에서 data 패킷 단위를 구분(0x0d 0x0a가 전달됨)해주기 위해 필요합니다.     // wait 10 milliseconds for the analog-to-digital converter    // to settle after the last reading:    delay(10);  } 

3. SerialChart 프로그램용 configuration 설정파일.
: 시리얼차트 프로그램은 입력받은 data를 configuration파일에 정의에따라 해석하여 그래프로 나타내줍니다.
아래의 예는 가장 간단하게 구성해본 예입니다. 더 다양한 설정이 가능하니 직접 해보시기 바랍니다.
 파일( 가령  imu_arduino.scc )에 아래의 내용을 적은 뒤 불러들이면 됩니다.
주의: COM3 같은 port 번호는 컴퓨터 설정마다 다른건 알고계시겠죠.. 자신의 설정에 맞게 수정해줍니다.

[_setup_]  port=COM3 baudrate=9600 width=700 height=500 background_color = white grid_h_origin = 100 grid_h_step = 1 grid_h_color = #EEE grid_h_origin_color = #CCC grid_v_origin = 0 grid_v_step = 0.5 grid_v_color = #EEE grid_v_origin_color = transparent  [_default_] min=0 max=255  [DistanceSensor] color=red 

 

 

[관련 블로그글]

거리센서 출력전압 관측

우편함 뮤직로봇 응용예제


[참고사이트]
시리얼챠트 프로그램 다운로드:
 

http://www.starlino.com/data/imu_kalman_arduino/SerialChart_01.zip

 

시리얼챠트 코드구글

 

Google Code Archive - Long-term storage for Google Code Project Hosting.

 

code.google.com

아듀이노 공식사이트:

http://arduino.cc

+ Recent posts