앰비라이트는 ambient lighting의 약자로 티비를 위한 간접 조명 시스템을 뜻한다.


쉽게 말해 화면의 가장자리에 있는 영상의 색을 LED로 밝혀서 마치 화면이 확장된듯한 느낌을 주도록 하는 조명 시스템으로 보면 된다. 필립스에서 처음 개발되었으나, 오픈소스 하드웨어의 발달로 만드는 방법에 대한 자료가 많아 개인도 비교적 쉽게 DIY가 가능하여 직접 제작하는 사람들도 많다.


기본 구현 원리는 다음과 같다.

  • 실시간으로 티비 영상의 가장자리edge 검출
  • 해당 섹션의 평균 색상 추출
  • 섹션의 평균 색상을 LED로 표현





LED 스트랩 테스트





티비 뒷면에 부착전 동작 테스트




실제 티비에 적용된 앰비라이트




번외 - 음악 반응형 LED 라이트


[Development Environment]
Main Chip : ATMEGA 128
Bluetooth Module : FB155BC
Tool Chain : IAR AVR 4.12A
Downloader : AVR Studio 4
Serial Monitor : Tera Term 4.73

Android Application : Bluetooth Chat(on the web)



[개요]
블루투스를 이용하여 안드로이드폰과 AVR이 데이터를 주고 받을 수 있도록 하는 방법에 대해 알아보자.

[블루투스]
블루투스에는 각 용도에 맞게 여러가지 profile을 제공하는데,  몇개의 주요 프로파일은 다음과 같다.
A2DP - 일반적으로 블루투스 헤드셋으로 노래들을 때 사용
AVRCP - 재생, 정지, 다음곡 등의 조작을 할 때 사용
HFP - 핸즈프리용 프로파일
SPP(Serial Port Profile) - 시리얼 통신용 프로파일
이중에서 우리가 사용할 프로파일은 SPP이며 UART 프로토콜로 데이터를 주고 받는다.
(안드로이드에도 SPP가 지원되며, 아쉽게도 아이폰에서는 지원을 안한다고 한다.)

Firmtech의 FB155BC이며 아래와 같이 생겼다.




구동전압은 3.3V이므로 5V 환경에서 사용하려면 3.3V regulator가 필요하다.
블루투스 환경세팅을 위한 interface board를 따로 판매하지만, 가격이 비싸므로
직접 회로를 구성하여 환경세팅을 할수 있도록 할 것이다.(회로가 간단하다)
Interface는 UART로 되어있으므로 AVR에서 사용하기가 아주 쉽다.

우선 아래 회로도대로 땜질을 완료하도록 하자.



사실 블루투스를 사용만하려면 전원(VCC, GND)과 UART(RXD, TXD)만 연결하면 된다.
하지만 우린 블루투스의 Configuration Setting도 해야하고, 블루투스 연결이 잘되었는지 등의 상태도 봐야하니 위의 회로를 모두 구성하는 것이 좋다.


회로를 구성하였으면 땜질이 잘되었는지, 블루투스가 잘 동작하는지 테스트를 해봐야한다.
Bluetooth와 AVR의 통신을 위해 Bluetooth의 RXD, TXD는 UART1에 연결하였고,
Bluetooth에 들어오고 나가는 데이터를 눈으로 보기위해 UART0은 PC에 Serial Cable로 연결하도록 하자. 하이퍼터미널 등의 Serial Monitor 프로그램을 실행하여 연결 COM Port, Baud rate 및 기타 설정값들을 AVR의 UART Setting과 같이 맞춰놓자.(여기 소스에서는 9600bps를 사용하였다)
이제 전원을 켜도록 하자. Status에 연결된 LED가 깜빡이면 뭔가를 대기중이라는 뜻이다. 일단 반은 성공했다고 보면 된다.
이제 Configuration Mode로 진입하기 위해, 블루투스의 전원을 제거한 상태에서 Reset Switch를 누르고 전원을 넣도록 하자.
그럼 아까 띄워놓은 터미널창에 아래와 같은 메시지가 나올 것이다.

0 DEVICE NAME FB155v1.0a
1 AUTHENTICATION DISABLE
2 REMOTE BD ADDRESS 000000000000
3 CONNECTION MODE MODE4
4 UART CONFIG 9600bps 8-N-1
5 STATUS MESSAGE ENABLE
6 POWER SAVE MODE DISABLE
7 ROLE SLAVE

이것저것 입력해보고, 입력이 된다면 땜질은 제대로 된것으로 봐도 무방하다.

Setting을 하나하나 대강 살펴보면,
Device Name은 폰에서 블루투스 검색시에 표시되는 이름이다.
Authentication은 암호화 여부인데, 폰과 연결시에는 Enable시 안됐던것 같다. 일단은 Disable로 하자.
Authentication에 들어가면 PIN code라는 것이 있는데, 블루투스 연결시 PIN Code가 일치해야 연결이 되므로, 0000 등의 임의의 값으로 설정해주자.(폰에서 블루투스 장치를 찾은 후 연결시도시에 Pin Code를 물어보게 되는데, 이 때 입력한 값을 넣어줘야 한다)
Remote BD Address는 전에 연결했던 장치의 고유번호인데, 일단 pass하고,
Connection Mode는 Slave로 사용할 것이므로 신경쓸 필요없다.(1 또는 2로 해주자)
Uart Config는 AVR과 주고 받을 UART의 Setting이다. 역시 AVR의 Setting 값과 맞춰준다.
Role은 블루투스의 경우 누가 찾을지, 연결요청을 할지 Master/Slave로 구분을 한다.
여기서는 폰을 Master로 사용하고, BT Module을 Slave로 한다.
이제 AVR쪽 세팅은 끝났다.


[Android Application]
출처 및 소스

Android SDK Example - BluetoothChat
http://developer.android.com/resources/samples/BluetoothChat/index.html

BuletoothChat을 Base로 SPP 연결이 되도록 수정한 소스
http://blog.naver.com/free2824?Redirect=Log&logNo=60108857440

// 아두이노 사용, 버튼으로 제어
http://web.suapapa.net:8080/wordpress/?p=474





연결방법

기울기 센서 -> 서보제어
화면 드래그 -> 서보제어
휘도센서 -> 뭐 제어
phone과 avr간 가속도, 기울기 차이 비교...







[아이디어]
 우리가 어렸을 때 즐겨하던 숫자퍼즐을 실시간으로 표시되는 카메라 영상을 이용하여 맞출 수 있도록 구현한 작품이다.




[블럭 다이어그램]
CMOS Image Sensor에서 RAM에 이미지 데이터를 올리면(VHDL)
임의로 리맵핑한 메모리 어드레스의 데이터를 화면에 표시함(Verilog) 
FPGA : Spartan2 



[장치 구성]
방향키를 이용하여 퍼즐을 움직이고, Select키를 누르면 힌트를 볼 수 있다. 



[구현 영상]



개발 목적
 우리가 일반적으로 사용하는 휴대용 디스플레이어의 경우 소형화면을 채택하므로 이동 중에 볼 경우 화면이 흔들려 제대로 된 화면을 볼 수 없다. 이러한 불편을 해소하기 위해 이동 중에도 흔들림 없이 화면을 볼 수 있는 보정장치를 개발하게 되었다.

기본 구조
 가속도센서에서 움직임이 검출되면 움직임에 대한 가속도 값을 픽셀로 변환 후 해당되는 픽셀만큼 화면을 이동시켜 움직임을 보상한다.

Processor : ARM7(AT91SAM7S256)

LCD : 2.4" TFT-LCD(320X240)

Sensor : 3-Axis Acceleration Sensor


기본 원리



구현 영상

아래의 영상은 극적인 효과를 위해 보정 범위를 크게 했으나, 실제 응용엔 보정 값을 작게하여 미세한 움직임에 대해 보정하도록 하면 눈의 부담을 크게 줄여 줄 수 있을 것이다.

영상 뒷 부분의 그래프는 가속도 센서에서 나온 값을 필터링 한 결과를 보여준다.

- 녹색 : 필터링 되기 전의 센서 값 - 노이즈가 많이 발생함

- 연두색 : 노이즈 제거를 위한 이동 평균 필터 적용

- 하얀색 : 가속도 센서의 경우, 현재 센서의 기울어진 정도(pitch, yaw, roll)에 영향을 받기 때문에, 제대로 된 가속도 값을 얻기 위해 그 값을 필터링 한 결과.






포터블 도트매트릭스

우리는 전에 도트매트릭스를 이용한 전광판을 만들어 보았다.(도트매트릭스 전광판 참조)
 기존에 만든 전광판은 원래 짜여진 각본대로 출력하는 수동적인 바보티비에 불과했지만 이번엔 기울기센서를 추가하여 사용자의 입력에 따라 출력을 바꾸어주는 능동적인 디스플레이어를 만들어 보도록 하자.
 기본적인 하드웨어 구성은 다음과 같다.


기본적인 도트매트릭스 회로에 기울기센서 및 진동모터를 추가되었다.
 기울기센서는 현재 기울어진 각도에 따라 전압을 다르게 출력해준다. 그렇다면 역시 A/D Converter를 사용해야 한다는 얘기인데, 여기서는 기울기 센서를 두개 사용하여 X축 및 Y축에 대한 기울기 값으로 현재 기판이 기울어진 정도를 얻을 수 있게 구성하였다.
 ATMEGA128의 경우에는 기본적으로 A/D Converter가 포함되어 있기 때문에 따로 회로를 구성하지 않아도 된다, 기울기 센서에 기준전압만 넣어주고 기울기센서의 출력만 PF0/ADC0, PF1/ADC1에 연결하면 회로 구성은 끝. 참 쉽죠?

 기울기 센서를 통해 입력을 받을 수 있게 되면서 도트매트릭스가 할 수 있는 일은 무궁무진해졌다.
여기서는 아래와 같이 4가지 기능을 구현해 보았다.
- 지렁이 게임
- 길찾기 게임
- 사용자의 입력에 따라 글자 및 색상을 바꿔 표시할 수 있는 전광판  
- 현재 각도에 맞게 글자를 회전 시키는 회전 전광판

전광판



길찾기 


지렁이


 글자회전

 

 
 이번엔 도트매트릭스를 이용한 전광판을 만들어 보자.
요즘에 길거리에 LED를 사용한 광고판들이 많이 보인다. 각종 광고 및 안내 용도로, 단색, 3색, 5색, 256색까지 다양한 LED 전광판들을 어렵지 않게 볼 수 있다.
 지금까지는 아무 생각없이 보고 지나쳤지만 어떤 원리로 글자가 만들어지고 표시되는지 알아보도록 하자.
우리가 최종적으로 만들 것은 아래와 같은 전광판이다.



 도트매트릭스는 단지 LED 여러개를 미리 땜질하여 놓은 LED의 배열일 뿐이다.
위의 사진을 보면 세로로 LED가 16칸, 가로로 64칸이다(8X8 도트매트릭스 16개 사용). 각각의 LED는 녹색, 빨간색, 주황의 3색 LED이다.
 
주황색은 따로 주황색 LED가 있는 것이 아니라 녹색과 빨간색 LED를 같이 켜면 사람 눈에 주황색으로 보인다.
역시 사람 눈의 오점을 이용한 교묘한 수법. 멀리서 보면 주황색으로 보이지만 가까이서 본다면 녹색과 빨간색 LED가 보이는 것을 알 수 있다. 직접 확인해보고 싶다면 근처 전철역이나 버스 정류장에서 확인해 보도록 하자.
 같은 원리로 잉크젯 프린터가 있다. 잉크젯 프린터 역시 다양한 색을 나타내기 위해 3개의 색을 섞어서 표현하는 것이 아니라, 3개의 색을 적당히 뿌려서 사람눈에 적당히 원하는 색으로 보이게끔 눈속임할 뿐이다.

 그럼 이제 저 전광판을 만들기 위해 몇개의 I/O 포트가 필요한가를 계산해 보자.(LED를 켜보았다면 LED하나를 제어하기 위해 1개의 I/O 포트가 필요하다는 것을 알것이다.)
우선 하나의 도트매트릭스에 필요한 I/O Port만 계산해보면
 8X8 = 64개 이고, 각각 빨간색, 녹색 2개의 LED가 들어있으므로 도트매트릭스 하나당 128개의 I/O 포트가 필요하다!
그 도트매트릭스가 16개 있으므로 I/O포트가 총 128*16 = 2048개가 필요하다.
하지만 우린 I/O Port가 2000개나 되는 MPU를 구할 길이 없으므로 전광판 만드는 것을 포기하도록 하자.


 하지만 '아니, 그럼 너님은 어떻게 만들었는데?'라는 생각이 든다면 어떻게 만들었는지 같이 알아보도록 하자. 우리의 지혜로운 선조들은 돈을 아끼기 위한(I/O 포트가 곧 돈이다) 여러가지 기법을 개발해 놓았다.
 그 기법들을 알기 위해 아래 링크를 참조하도록 한다.

디코더 및 래치의 원리

그럼 이제 도트매트릭스의 원리를 알게 되었으니, 실제로 전광판을 만들어 보도록 하자.
도트매트릭스는 연결해야 하는 포트가 많은 만큼 회로 구성 및 땜질에 있어서 상당한 노가다를 요구한다.
그렇기 때문에 실제로 회로를 땜질전 회로가 제대로 동작하는지 확인이 필요하다.


 위에서 구성한 회로는 래치회로가 제대로 동작하는지 확인하기 위한 회로이다.  디코더 및 트랜지스터 부분은 따로 테스트를 했기 때문에 여기서는 빠져있다.(디코더와 트랜지스터가 빠졌음에도 연결해야하는 선이 상당히 많은 것을 알 수 있다.)
 어쨌든 원하는데로 도트매트릭스가 잘 동작하는 것을 확인했으니 땜질을 하도록 한다.


 땜질 완료한 후에 테스트 해본 사진이다. 모든 래치를 enable상태로 놓고 포트에 0xFF 시그널을 주었으므로, 모든 LED가 들어와 주황색이 켜져야 한다. 위 사진에서 보면 RED LED 2개와 가로로 RED LED 한줄이 안들어 오는 것을 알 수 있는데, 불이 안들어오는 원인에는 도트매트릭스의 LED가 죽었거나, 땜질이 잘못되었을 경우이다. 우선 도트매트릭스가 나갔는지는 도트매트릭스를 교체해 보면 알 수 있고, 위와 같은 경우에는 회로도를 보거나 땜질한 부분을 직접 살펴보고 문제점을 금방 찾을 수 있다.
 그리고 사진에서 보면 알 수 있겠지만 도트매트릭스 별로 약간씩 밝기가 다른 것을 알 수 있다. 이는 회로의 문제가 아닌 도트매트릭스 자체의 문제이므로 도트매트릭스를 적절히 재배치하여 눈에 튀지 않게 구성하도록 하자.


 이제 어렵게 도트 회로를 완성하였으니, 실제 글자를 넣어주도록 하자.
지금 만든 도트매트릭스는 16X64개의 LED로 구성되어 있으므로 기본적으로 2byte짜리의 배열을 [84]개 만들어 놓고 원하는 글자를 해당 배열을 참조하여 실제 I/O포트에 값을 넣어주는 형태로 만들 수가 있다.(2byte는 16bit이므로 2byte의 배열을 84개 만들면 될 것이다.)
 일정시간단위로 해당 배열의 데이터를 이용하여 래치에 각각의 데이터를 넣어주고, 디코더 값을 증가시키는 역할을 하는 부분을 따로 만들면 실제 프로그래밍시에는 디코더와 래치를 신경쓰지 않고 해당 배열의 데이터만 바꾸는 작업으로 실제 표시되는 글자를 바꿀 수가 있게 될 것이다.

일반적으로 프로그램은 H/W를 직접적으로 접근하는 드라이버단과 그 위에서 드라이버단을 사용하는 어플리케이션단으로 나누어 짜는 방법이 있는데, 이렇게 역할별로 잘 분리하여 프로그램을 짤 경우 유지보수 측면에서 상당한 이득을 얻을 수 있게 된다. 위에서 보라색으로 표시한 부분을 드라이버단, 해당 배열에 데이터를 바꾸어주는 부분을 어플리케이션단으로 나누어서 프로그램 구조를 잡을 것이다. 이렇게 할 경우, 문제 발생시 어느쪽의 문제인지 파악하여 그 부분의 문제만 수정하게 되면 프로그램의 구조의 변경없이 수정을 쉽게 할 수 있을 것이다. 또한 H/W 변경시에도 어플리케이션단의 소스는 그대로 활용할 수 있게 된다.
 하지만 이렇게 나눌 경우 Main Application단에서 해당 배열에 값을 넣고 있는 중에 인터럽트가 걸리게 되면 문제가 발생할 소지가 있다. 이러한 경우에 대비하기 위해 배열의 값을 변경할 때에는 인터럽트가 걸리지 않도록 꺼주어야 한다.
(크리티컬 섹션이라고 하며, 이 구간은 짧을 수록 좋다. 자세한 내용은 OS의 크리티컬 섹션, 뮤텍스, 세마포어 등을 참조하도록 하자)


우선 일정시간단위로  래치에 각각의 데이터를 넣고 디코더 값을 바꿔주는 일을 해야하므로 타이머 인터럽트를 사용하도록 한다. 


 

위의 소스코드를 살펴보면 타이머 인터럽트 발생시 decorder의 sequence를 0에서 7까지의 범위로 증가시켜주고 displayArrayData()를 호출하여 gData[] Array의 데이터를 각각의 래치에 담는 작업을 한다.
이렇게 드라이버단을 만들어 놓은 후 main() 함수에서는 gData[]의 값만 바꿔주면 실제 도트매트릭스에 입력되는 데이터가 바뀌어 실제 도트매트릭스에 해당 값으로 불이 들어오게 된다.
(위의 소스에서는 GREEN에 해당하는 데이터만 처리하도록 되어있다. RED도 같은 원리로 제어할 수 있을 것이다.)

 이것을 이용하여 여러가지 효과를 주어 아래와 같은 전광판을 만들어 보도록 하자.





우선 도트매트릭스의 앞뒤 생김새를 살펴보면 아래와 같다.


 도트매트릭스는 LED를 연결하여 잘 배열하여 놓은 것으로 내부에는 아무 것도 없다. 정말 LED빼곤 아무것도 없다. 도트매트릭스 가격이 부담스럽다면 직접 LED를 한땀한땀 땜질하여 사용해도 무방하다.(하지만 땜질하다 보면 내가 이걸 왜 하고 있지..하는 생각이 2천번 정도 들 것이다.)
 사실 도트매트릭스 모듈 중에는 미리 땜질이 다 되어 있고, 안에 Driver Chip들을 내장해놓아서 데이터시트대로 신호만 주면 별 어려움 없이 전광판을 만들 수도 있는 것도 있다. 하지만 우리는 도트매트릭스의 원리를 알아야 하기 때문에 쌩(?)도트매트릭스를 사용하도록 한다.
 위 사진의 8X8 도트매트릭스 회로도를 보면 아래와 같다.


 회로도를 봐도 역시 LED밖에 없다. 나와있는 핀은 사진과 같이 24개이고, 그중 8개는 ROW라고 써있고 가로 줄 LED의 (+)극 끼리 쫘라락 연결해 놓았다(커먼 애노드). 그럼 이제 이 도트매트릭스를 켜기 위한 방법을 알아보기 위해 ROW1만 있다고 생각해보자. LED 8개 제어하는건 참 쉽다. (1, 1)의 GREEN LED를 켜기 위해선 ROW1에 5V를 주고, COL24번핀을 0V를 주면 된다. 23번핀을 0V를 주면 빨간색이 들어올 것이고, 23번과 24번핀이 모두 0V일 경우엔 GREEN과 RED가 모두 켜져 주황색으로 켜진것처럼 보일 것이다. 


 그럼 이제 (1, 1)과 (2, 2)를 동시에 켜보도록 하자. 어떻게 하면 될까? ROW1을 1로 놓고 COL24는 0으로 놓고, ROW2는 1로 놓고 COL21을 0으로 놓으면 될까? 회로도를 자세히 살펴 보면 LED의 (-)부분 역시 세로로 연결이 되어 있어서 왼쪽 구석의 LED 4개가 모두 들어오게 될 것이다.
그럼 어떻게 해야할까?  이번에도 사람의 눈을 교묘히 속여서 원하는 대로 LED를 켜도록 하자.(잔상돼지편 참조)
 즉, 한꺼번에 모든 LED를 켜는 것이 아니라, 한줄한줄 돌아가면서 한번씩 켜주는 것이 포인트이다.
ROW1 켜주고 원하는 24번 0V 넣어주고, ROW2 켜주고 21번 0V 넣어주고를 반복하면 (1, 1)과 (2, 2)에 불이 켜진 것처럼 보일 것이다. 전체 8줄을 다 켠다면 ROW1 ~ ROW8까지 반복하며 원하는 데이터를 넣어주면 된다.
 그럼 이 방법을 사용한다면 I/O포트는 몇개나 필요할까?
ROW에 8개 필요할 것이고, COLUMN에는 빨강, 녹색 각각 8개의 LED가 있으므로 16 + 8 = 24개의 PORT가 필요하고, 이런게 16개 있으므로 24*16 = 384개의 I/O포트가 필요하다. 아까 2000개에 비하면 많이 줄었지만 384개도 역시 많다. 그럼 더 줄여 보도록 하자.
 우선 ROW에 8개 필요한 것을 3개로 줄여보자. ROW에 사용하는 포트가 하는 일은 뭘까? 
처음엔 ROW1에 1주고, 두번째엔 ROW2 1주고, 세번째엔 ROW3에 1주고... ROW8에 1주고, 또 ROW1에 1주고...
위의 작업을 표로 나타내면 아래와 같다.


이러한 출력을 내주는 녀석을 디코더라고 한다. 디코더는 입력에 따라 한개의 출력을 선택하게끔 하는 회로인데, n개의 입력으로 2 ⁿ 개의 출력을 내줄 수 있다. 우리에게 필요한 출력은 ROW1~8까지 8개의 선택이므로, 2의 3승이 8이므로 입력이 3개만 필요한 것을 알 수 있다.
수학적으로 구해보려면 2 ⁿ  = 8 양변에 로그를 취하면.. n log 2 = log 8 = 3 log 2, 즉 n = 3이 된다.
이말인 즉슨, 3개의 입력만 있으면 우리가 원하는 8개의 출력을 내줄 수 있다는 말씀.
실제 우리가 실제로 사용할 디코더 74138의 진리표는 다음과 같다.


 여기서 H는 High 즉, 1을 나타내고 L은 Low, 0을 나타낸다. 위에 그림과 1과 0이 바뀌었는데 그 이유는 뒤에서 보도록 하자.

자, 그럼 이제 ROW를 제어하기 위한 포트도 줄였겠다, 가속도를 더 붙여 Column에 대한 포트도 줄여 보도록 하자.
래치라는 것을 들어보았는가? 래치는 이전의 데이터를 저장할 수 있는 일종의 메모리 회로이다. 이 메모리 기능을 이용하여 우리의 사리사욕을 채워보자.


위 표는 래치 74573의 Function Table이다(라고 적혀있다). LE(Latch Enable을 보면 High일 경우, 입력(D)가 그대로 출력으로 나가고 LE가 Low일 경우에는 출력이 Q0로 되어있다. 즉, LE가 Low일 경우에는 뭘 입력으로 넣어도 상관없이 이전에 넣었던 내용만 출력한다라는 뜻이다. 래치의 이러한 특성을 이용하면, 포트의 사용을 획기적으로 줄일 수가 있다.
 자세한 설명은 회로도를 보면서 하도록 하자.



우선은 위에 74138 디코더가 보인다. 디코더 출력(OUTx)부분 핀에 보면 빨간버블이 붙어있는데 이는 0이 활성화 상태라는 뜻이다. 아까 위에서 살펴봤던 디코더의 진리표가 출력이 반대로 되어 있었던 이유이기도 하다. 
 디코더에서 나온 신호는 PNP형 트랜지스터의 입력으로 들어간다. 위 회로에서 PNP TR은 스위치로 사용되고, 입력이 0일때 도트매트릭스의 COMMON단에 VCC전압을 공급하여 주는 역할을 한다. 즉, 디코더의 입력 ABC에 신호를 순차적으로 주게되면 도트매트릭스의 COM1~8에 차례로 VCC 전원을 공급하여, 도트매트릭스의 한줄한줄을 순차적으로 스캔할 수 있도록 해준다.
 그 다음으로, 래치회로를 살펴보도록 하자. 래치는 우리가 입력한 데이터를 저장하기 위한 용도로 사용한다. LE(Latch Enable)을 1로 주고 래치에 원하는 신호를 준 후에, LE를 0으로 주면, 래치 입력(Dn) 신호에 상관없이 래치의 출력(Qn)에는 이전에 입력한 값만 나타나게 된다. 래치의 이러한 특성을 이용하여 GREEN과 RED에 각각 다른 값을 넣어줄 수가 있다.
 RED 데이터를 넣어주기 위해 두 래치의 LE를 1로 셋해주고 RED에 해당하는 데이터를 넣어주고, 오른쪽 래치의 LE를 0으로 해주고, 다시 GREEN에 해당하는 데이터를 넣어주면 GREEN과 RED에서는 각각 저장된 데이터가 출력되게 될 것이다.
이것이 I/O Port하나로 RED와 GREEN LED를 제어할 수 있게 하는 원리이다.
 이 회로를 여러개의 도트매트릭스에 대해  확장을 하면, 하나의 포트로 모든 도트매트릭스의 RED와 GREEN 포트에 신호를 넣어줄 수가 있게 된다.

이 원리를 이용하여 도트매트릭스에 글자를 넣어보자.
 


 위 이미지는 래치를 이용하여 각각의 도트에 데이터를 넣는 그림이다. 위에서는 3색에 대한 Latch는 고려하지 않았지만 같은 원리로 RED/GREEN에 대한 Latch에 데이터를 넣어놓을 수가 있을 것이다.
 이런 식으로 각각의 래치에 데이터를 저장하고, 디코더를 이용해 한줄한줄을 차례로 표시해준다.


위의 작업을 빠른속도로 반복하게 되면 실제 눈에 보이는 이미지는 아래와 같을 것이다.


 이러한 원리로 도트매트릭스를 적은 포트로 제어할 수 있게 된다. 도트매트릭스가 더 추가한다고 해도 실제 추가해야할 I/O포트는 LE신호를 제어할 한핀 뿐이므로 포트 갯수에 대한 부담없이(물론 땜질의 부담은 증가하겠지만..) 도트매트릭스를 추가할 수가 있을 것이다.


 제일 처음 만들어 봤던 작품이다. 일종의 RC카라고 생각하면 된다.
이름은 축구로봇이지만 축구를 위해 추가된 기능은, 본체 앞에 ']'자 모양의 철프레임을 달아 놓은게 전부이다.
그럼 슛은 어떻게 하느냐? 공을 밀어서 드리블하여, 그대로 밀어넣으면 된다.
원래는 슛을 할 수 있도록 설계하려 했지만, 뭔가 마땅한게 없어서 금방 접었다.


 기본적으로 컨트롤러에서 사용자의 조작을 RF 모듈을 이용하여 본체로 보내주면, 본체에서는 그 값을 연산하여 적당히 모터를 제어하여 움직이도록 한다.


전체적인 블럭다이어그램은 아래와 같다.


 가변저항과 연결된 볼펜꼬다리(!)를 통해 A/D Converter로 전압값이 들어가면 A/D Converter는 그 전압값을 프로세서가 알아먹을 수 있는 디지털 신호로 변환하며 프로세서로 보내준다.
 프로세서는 컨버팅된 디지털값을 UART로 RF-Module의 송신단으로 보내면 RF-Module은 알아서 그 값을 무선으로 쏴주고, 수신단의 RF-Module에서 알아서 그 신호를 받아서 본체의 프로세서에게 UART로 전송해준다.
 그 후 본체 프로세서가 컨트롤러부터 보내진 값을 해석하여 실질적으로 모터에 신호를 줌으로써 움직일 수 있게 한다.

이 과정을 자세히 알아보기 위해 컨트롤러 부분부터 살펴보도록 하자.
주요 부품은 다음과 같다.
- MCU(8051),  7-Segment, 가변저항, A/D Converter(ADC0809), RF 송신모듈(RX2TX2)



우선 컨트롤러의 기본 회로도를 보면 다음과 같다.


왼쪽부분이 A/D converter이고 오른쪽이 마이크로 프로세서이다.
왼쪽의 ADC를 살펴보면 IN0/IN1이라는 부분이 있는데, 이 부분에서 현재의 전압값을 읽어들인다.
ADC는 말그대로 Analog로 출력되는 전압값을, 프로세서가 알아먹을 수 있도록 Digital로 변환해 주는 녀석이다.
(변환하는 원리는 비교기를 이용한다. 비교기는 기준전압에 대해 입력된 값이 높으면 1, 낮으면 0을 출력해주는데 비교를 많이 할수록 정밀한 값을 얻어낼 수 있다.)

 볼펜 꼬다리에 연결된 것이 가변저항인데, 가변저항으로 전압값을 조절해주는 원리는 키르히호프의 전압분배의 법칙이다.
 저항이 직렬로 두개 이상 연결되어 있을 경우, 각 저항에 걸리는 전압은 저항값에 비례한다. 즉, 저항이 클수록 그 저항에 걸리는 전압이 높아진다는 얘기.
위의 회로도에서 가변저항 부분은 실제로는 아래와 같은 구조로 되어있다.

이 회로에서 전압분배 법칙에 따르면 Vout = Vin * ( R2/(R1+R2) ) 이 된다.
예를 들어서 Vin이 5V이고, R1과 R2가 10kΩ으로 같다면 Vout에 걸리는 전압은 2.5V가 되는 것이고,
R1 = 0, R2= 10KΩ이라면 5V의 전압이 모두 R2에만(Vout) 걸린다는 얘기이다.
위의 원리로 가변저항을 돌리게 되면 R1, R2의 저항값이 바뀌어 ADC로 들어가는 Vout값을 변화시킨다.

 가변저항들에 걸린 전압값을 ADC의 입력부분에 연결하였다. ADC0809는 8-channel Converter로 8개의 입력을 가질 수가 있도록 되어있다. 가변저항을 8개 사용할 수 있다는 얘기이다.
 이렇게 연결된 여러 입력을 선택하기 위한 A0~2까지 채널 셀렉션 포트가 있는데, 여기서는 가변저항을 두개만 사용하므로 A0은 GPIO포트에 연결하고 A1 및 A2는 그라운드에 연결하였다.(8개 모두 사용하려면 A0~2포트를 모두 프로세서의 GPIO에 연결하여 원하는 채널을 선택할 수 있게 해야한다.)
 IN0을 사용하기 위해 A0이 물린 포트를 0으로 설정해놓고, Start Port를 1로 셋하면 ADC는 현재 물려있는 1번 채널(IN0) 을 열심히 변환한 후에 컨버팅 작업이 끝나면 ADC는 '나 컨버팅 끝났다'는 의미로 EOC(End Of Convertion) Port에 1을 셋해준다.
 EOC가 셋된 후, 프로세서에선 '알았다. 내가 데이터를 가져가겠다'는 의미로 OE(Output Enable) 포트를 1로 셋해주면 ADC는 컨버팅된 디지털 데이터를 D0~7포트로 뿌려주고, 실제 가변저항에 걸린 전압값이 0x00~0xFF의 디지털 값으로 나타나게된다.
 이러한 과정은 Datasheet에 나와있다. 어떤 칩 또는 모듈 등을 사용할 때, 그 모듈이 어떻게 동작이 되는지는 Datasheet에 나와 있다. Datasheet를 꼭 참고하도록 하자.



 EOC port는 7414에 연결이 되어있는데 7414는 인버터(NOT Gate)이다. A에 1이 들어오면 Y에 0을 출력해주고, A에 0이 들어오면 1을 출력해준다. 7414를 사용한 이유는 EOC를 프로세서의 외부인터럽트(INT0)에 연결해서 사용하는데, 8051의 외부인터럽트는 Low Level Edge에서 동작(INT0위에 줄이 그어져있으면, 얘는 0일때 뭔가를 처리한다는 의미이다.) 하므로 EOC에서 1이라는 신호가 들어왔을 때 외부인터럽트가 걸릴 수 있도록 7414를 연결하였다.


자, 이제 힘들게 아날로그 전압을 A/D 컨버팅하여 디지털 신호로 변환하였다.

컨트롤러에서 변환된 신호를 RF module로 보내주기만 하면 임무는 끝난다.
내가 사용한 RF module은 TX2RX2모듈로 433MHz의  단방향 모듈이다. 한쪽에서는 보내기만 하고, 다른 한쪽에서는 받기만 할 수 있다.
 TX2TX2 RF 모듈은 UART를 이용하여 인터페이스를 한다.

RF 회로도는 아래와 같다.


회로도가 간단한만큼 사용하기도 참 쉽다.
송신부에서 원하는 신호를 보내려면 UART의 TXD로 보내주면 되고, 수신부에서는 RXD에서 읽어오면 된다.
나머지 무선 통신 관련하여서는 RF모듈이 알아서 다 해주므로, 회로만 저렇게 구성해주고, RF 모듈은 잊어버리도록 한다. 일반적인 UART 통신을 하듯이 사용하면 되는 거다.
 안테나의 경우 데이터시트를 참고하면 헬리컬, 루프, 휩 안테나를 이용할 수 있다고 되어있는데, 여기서는 17Cm 휩안테나를 연결하였다. 뭐, 안테나를 돈주고 살 수도 있겠지만, 굵은 전선을 사용해도 통신이 잘되었으므로 그냥 전선으로 땜질해 연결해 버렸다.

실제로도, RF Module이 있는 것과 UART 통신을 직접적으로 하는 것의 프로그램코드는 똑같다. 전에 이거 만들다가 RF모듈 하나가 죽어서 갑자기 모듈을 구할 수가 없었을 때, 동일한 프로그램 소스를 이용하여, 컨트롤러와 본체의 RX, TX만크로스로 직접 연결하여 구동시킨 적이 있다. 인터페이스가 같다는건 내가 실제로 그 모듈을 사용해보지 않았어도 사용할 수 있다는 얘기나 마찬가지이다. UART를 사용할 줄 알면 UART를 인터페이스로 하고 있는 블루투스 모듈이나 지그비 모듈 등도 사용방법이 모두 같을 것이고, A/D 컨버터를 사용할 줄 안다면, 출력이 전압으로 나오는 가속도 센서, 기울기 센서, 조도센서 등의 모든 센서의 사용방법이 같다는 얘기이다. 하나를 알면 열을 안다는 말씀.



이제 본체 부분에 대해 알아보자.
본체는 구성이 훨씬 간단하다.


 본체에서는 컨트롤러부에서 보내온 데이터를 받아서 모터를 구동하게 되는 역할을 한다.
ADC에서 나온 값에 따라 속도 및 방향을 정해서 모터를 돌리면 끝.

 이 로봇에는 구동할 수 있는 모드가 2개 있다.(아까 회로의 외부인터럽트 스위치를 이용해 모드를 결정한다.)
첫번째 모드는 일반적인 RC카와 같은 원리로, 왼쪽 볼펜뚜껑은 속도, 오른쪽 볼펜뚜껑은 방향을 제어할 수 있는 모드이고
두번째 모드는 왼쪽뚜껑이 왼쪽 바퀴, 오른쪽은 오른쪽 바퀴를 구동시키도록 제어할 수 있는 모드이다.
조정을 하기 위해선 RC카와 같은 첫번째 모드가 좋겠지만, 방향을 전환하는 점에 있어 한계가 있다.
두번째 모드로 플레이를 하게 되면 처음에는 조작이 어렵지만, 제자리에서 돌 수 있는, 선회 등의 고급스킬(?)이 가능하기 때문에 두번째 모드를 추천한다...지만 지금은 장기기증으로 인해 세상 어디에도 없다..


그럼 이러한 원리를 이용하여 재미있는 RC카를 만들어 보도록 하자.

 
이번에는 사람 눈을 교묘히 속여 적은 수의 LED로 간지나는 전광판을 만들어 보자.

 아래 사진은 잔상효과를 이용하여 글자를 표시해주는 잔상돼지이다. 의도한바는 아니지만 만들다 보니 돼지처럼 만들어져 잔상돼지라는 이름이 붙었
다. 도트매트릭스의 원리를 간단히 응용하면 스테핑모터와 LED 8개와 나무젓가락만으로도 훌륭한 전광판을 만들 수가 있다.
 동영상이 있었으면 이해가 쉬웠을 것이나, 아쉽게도 남은건 아래 흐리멍텅한 사진 하나 밖에 없다. 이 돼지도 역시 다음 작품을 위해 바로 분해되었다.



 그럼 이 돼지가 어떻게 글자를 표시할 수가 있을까? 이해를 돕기 위해 급조해 만든 GIF 이미지를 통해 원리를 알아보자.

                   

 먼저 아래쪽에 파란색으로 동그랗게 된 부분이 스테핑모터이다. 모터가 회전하면서 그 위에 나무젓가락에 붙어있는 8개의 빨간색 LED가 불규칙적으로 깜빡이는 것을 알 수 있다. 하지만 이렇게 천천히 돌아서는 정말 LED가 무작위로 깜빡이는 것으로 밖에 안보일 것이다.
 그럼 조금 더 빨리 움직여보자.

 어떤가? 이번엔 잘 보이는가? 만약에 잘보인다면 모니터를 바꿀 때가 된것이다. 어서 모니터를 새것으로 교체하고 다시 보도록 하자. 
 여전히 눈만 아프고 보일 생각을 안한다. 잔상효과로 인해 글자를 표시하고 싶다면, 우리눈에 잔상이 없어지는 시간을 주어선 안된다. 일단 GIF 이미지론 더이상 빨리 돌릴수가 없는 관계로 인위적으로 잔상을 넣어서 돌려보자. 

  무언가 글자가 보이는가? 뭐 그다지 멋지게 나타나진 않지만, 글자가 나타나긴 한다. 사실 실제로 LED를 이용하여 만들어보면 기대보다 뛰어난 퀄리티로 표시될 것이다.(동영상이 없어서 참 아쉽다.)

 사람눈에 잔상이 남는 시간은 대략 1/16초라고 한다. 하지만 내 눈으로 테스트해봤을 때는 1초에 2~3번 정도만 왕복해도 글자가 잘 보였으므로 빛이 강할 수록 눈에 잔상이 더 오래 남는 듯하다. 사실 더 빨리 돌리고 싶어도 스테핑모터의 특성상 급가속을 하다보면 탈조가 나게되므로, 탈조가 나지 않는 선에서 최대한 빠른 속도로 돌려 주는 것이 관건이다.

 위의 방법 말고도 모터를 뺑뺑 돌려서 잔상을 얻어내는 방법도 있다. 하지만 모터가 뺑뺑 돌아가는 구조라면 선이 꼬이기 때문에 모터부와 LED부분을 분리해서 만들어야 하며, 모터와 LED의 씽크를 맞추어 줘야 한다.
 씽크가 안맞을 경우에는 글자가 항상 제자리에 표시되지 않고 돌아가기 때문에 의도한 효과를 내기 힘들 것이다.
씽크를 맞춰주는 방법에는 모터는 모터대로 돌도록 놔두고(보통 DC모터를 사용한다), 적외선센서 등을 이용하여 한바퀴 도는 시간을 계산하여 LED에 표시해주는 방법이 있겠다.
 다른 방법이 있다면, 가속도 센서를 이용하는 것도 있겠다. 위에서 적외선센서 대신 가속도 센서를 사용하거나, 아예 모터를 빼버리고 손으로 흔들어서 가속도값에 맞게 글자를 표시해주도록 만드는 것도 괜찮을 것이다.


그럼 이제 원리를 알았으니, 만드는 일만 남았다.
사실 원리만 이해하면 만드는 것은 일도 아니다.(MCU를 이용하여 LED를 켤줄 알고, 스테핑모터를 돌릴줄 안다면 말이다.)
회로도를 살펴보도록 하자.
  


 우선 마이크로 프로세서의 회로도이다. 프로세서는 흔히 사용하는(사용했던?) 8051을 사용하였다. 오른쪽에 외부인터럽트와 연결된 스위치가 보인다. 본인은 쇼를 위한 모드 세팅과 글자 선택 등의 기능에 사용했으므로 안넣어도 무방하다.


 그 다음은 LED회로도이다. LED 8개를 VCC-330Ω저항-PORT0에 각각 연결하였다. 기본 LED 회로도이므로 별 것 없다.
PORT0의 값을 0으로 넣어주면 전류가 흘러 LED가 켜지는 회로이다.


 다음은 스테핑모터의 회로도이다. 보통 모터의 경우엔 전류를 효과적이고 안정적으로 제어하기 위해 프로세서의 I/O Port에 바로 물리지 않고, 모터드라이버를 통해 제어하게 된다. 스테핑 모터도 역시 드라이버를 사용해야하는데 여기서는 SLA7026이라는 드라이버를 사용하였다. 스텝모터는 INA, INB에 일정한 시퀀스대로 시그널을 주면 그 시그널에 맞게 한스텝, 한스텝 움직이게 된다. 스텝모터의 이러한 특성으로 인해 잔상 LED를 만들기에 적합하다.(한스텝 움직이고 LED 시그널 바꾸고 하면 되기 때문에 모터와 LED간의 싱크를 맞추기에 편하다.)

그럼 이제 소스코드를 살펴 보도록 하자. 사실 해줄일이 별로 없기 때문에 프로그램도 간단하다.

우선 LED를 구동할 신호 Data 배열이다.


unsigned char code micro[48] = 
{
   0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xFF , 0xFF 
 , 0xE0 , 0x78 , 0xE0 , 0xFF , 0xFF , 0x00 , 0x00 , 0xFF 
 , 0xFF , 0x00 , 0x00 , 0x7E , 0xFF , 0xC3 , 0xC3 , 0xC3 
 , 0xC3 , 0x00 , 0x00 , 0xFF , 0xFF , 0xD0 , 0xD0 , 0xFF 
 , 0x6F , 0x00 , 0x00 , 0x7E , 0xFF , 0xC3 , 0xC3 , 0xFF 
 , 0x7E , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 
};



 위 배열에는 'MICRO'라는 글자가 들어가있다. 얼핏 보기에도 MICRO라는 글자가 보인다..면 당신은 공학용 계산기이다. 어서 공학용 계산을 수행하도록 하자. 비록 직관적으로 어떤 글자인지 안보이더라도, 저게 왜 MICRO라는 글자가 되는지는 알아야 한다. 잘 모르겠다면 공학용 계산기로 위의 16진수를 2진수로 변환해보면 알수도 있을 것이다.(사실.. 알아야한다.)
 배열을 만들때는 직접 한땀한땀 2진수에 대입하여 만들어도 되지만, 우린 도구를 쓸줄 아는 진보된 인간이기 때문에 원하는 글자 또는 그림을 Hexa 형태로 변환해주는 font editor와 같은 툴을 사용하도록 하자.

툴을 이용하여 배열을 만들었으면 이제 할일은 배열 값을 이용해 LED한번 켜주고 모터한번 돌려 주고를 반복하면 끝이다.
  

while(1)
{
	if(motorSequence == CW)
	{
		MotorForward();
		P0 = micro[index++]
		if(index > 48)
			motorSequence = CCW;
	}
	else
	{
		MotorBackward();
		P0 = micro[index--]
		if( index < 0 )
			motorSequence = CW;
	}
	delay();
}


  위에서 말로 써놓은걸 프로그램으로 짜보면 위와 같이 나올 것이다. 간단하지 않은가? 너무 간단해서 허무할 지경이다.
모터를 제어하는 부분은 따로 포스팅할 예정이므로, 일단은 MotorForward()시 시계방향으로 한칸, MotorBackward()시 반시계 방법으로 한칸 움직인다고만 이해해두자.

 사실 위 소스코드를 실제로 돌려본다면 의도하지 않게 글자가 반전되어 표시가 될 것이다. 왜 그런지 생각해보고 제대로 디스플레이 될 수 있도록 수정해보자.
 

전원을 안정적으로 공급하자. 전원부의 원리에 대해 알아보자.
-레귤레이터, 캐패시터(콘덴서 충전시간), 디커플링. 3.3v regulator

우리가 일반적으로 사용하는 소자, 칩 등에는 사용 가능한 전압 범위가 있다.
우리가 사용할 메인 칩(마이크로 프로세서)은 DC 전압을 전원으로 사용하는데, 보통 5V, 3.3V등의 사용전압이 정해져있다.
(뭐 5v짜리 칩에 3.3v를 공급해도 기본적인 동작은 한다. 1과 0을 구분짓는 기준전압이 3.3v이하이기 때문에...)
어떤 외부 혹은 내부의 요인으로 인해 전압이 높아진다면 어떨까?
칩이 죽어버리고 말 것이다. 칩이 죽으면 내 마음은 어떨까? 가격이야 둘째치고 소켓없이 바로 기판에 땜질을 했다면 같이 죽고 싶을 것이다. 이러한 사고를 미연에 방지하고, 안정적인 전원을 공급하기 위해 보통 레귤레이터라고 하는 소자를 사용하게 된다.


5V를 얻기 위해 흔히 사용하는 레귤레이터인 7805는 위의 그림과 같이 생겼으며, 보통 열이 많이 발생하기 때문에 오른쪽 그림과 같이 방열판을 달아주기도 한다.
 7805에 열이 많이 발생하는 이유는 입력 전원을 5V로 낮추기 위해 5V 이상의 전원은 열로써 소모하기 때문이다.
예를 들어, 8V의 전원을 공급하면 3번 출력포트로 5V가 나오고 나머지 3V에 대한 에너지는 열로써 소모시킨다. 입력전압이 높을수록 레귤레이터는 더욱 뜨거워지고, 그만큼 열로 손실되는 전력이 많아진다는 얘기(뭐 난방기기로 쓰려면 상관없다)
하지만 어떤 요인에 의해 전압이 휘청되는 부분을 레귤레이터에서 잡아주어 칩에 안정적인 전원을 공급하기 위해선 꼭 달아주어야 한다.(내가 죽어도 칩, 너만큼은 내가 구해주겠다. 레귤레이터의 역할이다.)

7805의 이름은 7~8V정도 입력하면 5V가 잘 나온다는 뜻이라고 생각하자.
(원래는 78은 플러스전압, 79는 마이너스전압, 뒤에 두자리수는 출력 전압을 나타내지만 그러려니 하고 넘어간다.)

7805 역시 다리가 세개 밖에 되지 않아 회로 구성이 상당히 쉽다. 1번은 입력전원, 2번은 그라운드, 3번은 출력전원이다.


상기 회로도에서 캐패시터는 디커플링의 용도로 사용된다.
캐패시터는 무엇일까.? 쉽게 말해 배터리이다. 작은 배터리. 캐패시터(콘덴서)의 종류에는 전해콘덴서와 세라믹콘덴서가 있다. 전해콘덴서는 디커플링 용도로 사용하고, 세라믹콘덴서 역시.. 디커플링 용도로 사용할 것이다.
일단 디커플링란, 쉽게 말해 노이즈 필터링이라고 보면 된다.
그럼 차이가 뭐냐? 전해콘덴서는 (세라믹콘덴서에 비해)용량이 크고, 세라믹 콘덴서는 용량이 작다. 그니깐 세라믹 콘덴서가 더 고주파스러운 노이즈를 필터링 한다는 얘기다.

 역시 전원이 불안정한 경우를 대비해 사용한 것인데, 레귤레이터는 입력 전압이 높아지는 것을 막아주는 역할을 한다. 그렇다면 반대로 전압이 떨어진다면 어떨까? 칩에 공급되는 전압이 적정수준보다 낮다면 역시 정상적인 동작을 보장하지 못하는데. 순간적으로 전압이 떨어지는 경우를 대비해 충전해 놓았다가 떨어질 때, 전압을 보상해주는 보조배터리의 역할을 하는 것이다.
그럼 보조배터리는 용량이 무조건 크면 좋겠네, 하는 생각을 하는 사람들도 있겠지만 그렇지 않다.
용량 큰 캐패시터가 회로에 많다면, 전원을 공급하는 순간에 충전을 해야하기 때문에 실질적으로 정상적인 전원을 사용할 수 있게 되는 시간을 더뎌진다. 또한 전원을 차단하였을 경우에도 충전된 캐패시터가 모두 방전되어야 하므로 반응속도가 늦어진다고 할 수 있다.(하이/로우패스 필터의 위상이 늦어지는 예..등은 나중에 센서의 노이즈 제거에서 보도록 하자.)
 용도는 교류성분을 제거하고, 전압강하시에 전력을 보충 해준다.

오른쪽 끝의 LED는 전원이 제대로 공급되는지 확인하기 위한 용도로 달아주었다. 다른 칩등에 5V의 전압을 공급해주기위해서 7805의 OUTPUT인 3번 핀과 연결하면 된다.

캐패시터의 충방전 시간.

캐패시터 참고 사이트
http://ghebook.blogspot.com/2011/06/capacitor.html



7805는 위에 알아봤듯이, 5V이외의 전압은 열로 소모하기 때문에 전원을 많이 소모하게된다. 
그렇기 때문에 배터리를 사용한다거나 할 경우, 에너지의 효율을 높일 수 있도록 남는 전원을 피드백시켜 주는 레귤레이터가 있는데, 그것이 바로 LM2575이다.