Raspberry pi

5편 적외선 리모콘 (IR Remote Controller) + TV 스피커리시버 연동

[혜안] 2017. 4. 19. 23:31
728x90

[Raspberry pi] - 1편 적외선 리모콘 (IR Remote Controller)

[Raspberry pi] - 2편 적외선 리모콘 (IR Remote Controller)

[Raspberry pi] - 3편 적외선 리모콘 (IR Remote Controller) + 음성인식

[Raspberry pi] - 4편 적외선 리모콘 (IR Remote Controller) + 음성인식 개선

[Raspberry pi] - 5편 적외선 리모콘 (IR Remote Controller) + TV 스피커리시버 연동



몇달 전만 해도 라즈베리파이(Raspberry Pi)는 거실 TV 옆에서 KODI 미디어 서버 역할을 충실히 수행하고 있었다.

잘 쓰던 라즈베리파이를 좀 더 잘써보겠다고 서재방으로 들여놓고, 실제로 몇가지 기능을 구현하여 사용을 하고 있지만..

아무래도 라즈베리파이(Raspberry Pi)는 미디어 서버일 때에 그 활용도가 가장 높은 것 같다.

사실 이 고민의 시작은 스마트 TV의 허접한 DLNA 기능 때문이다.

NAS에서 DLNA 기능을 켜면 TV에서 컨텐츠를 볼 수는 있지만, 윈도우 탐색기보다 못한 수준이다.

게다가 새로운 컨텐츠를 넣어도 즉각 반영되지 않는다.


그리하여 지난 몇주 간 만들어 놓은 홈 서버의 기능을 그대로 유지하면서 미디어 서버 역할도 할 수 있는 방법을 고민하고 있다.



라즈베리파이2 활용 기능 목표

1. 홈 서버

  - 스마트콘센트 제어

  - 주방TV 제어

2. 미디어 서버

 - KODI 또는 PLEX 서버

3. 리모콘 포워딩

 - TV 의 전원, 볼륨 신호를 스피커 리시버로 재전송


1번 기능은 만들었고,

2번은 KODI로 활용했었고, PLEX 적용이 가능한지 테스트가 필요하다. (성능이 나올지)

3번은 주방TV 제어 때 사용한 IR 송수신 모듈을 응용하면 가능하다.


3번 기능은 스마트콘센트(Smart Plug) 1편에서 얘기한 CEC 혼선에 대한 해결책이다.

[Raspberry pi] - 1편 스마트 콘센트? Smart Plug!


TV를 켜면 스피커도 켜지고, TV볼륨을 올리면 스피커 볼륨이 올라가야 한다.



우선 TV 리모콘 신호를 홈씨어터로 재전송하도록 리모콘을 등록하자.

리모콘 등록은 이미 주방TV 리모콘 등록에서 해봤고, 과정 동일하다.

[Raspberry pi] - 1편 적외선 리모콘 (IR Remote Controller)


lirc.org 사이트에 이미 등록된 리모콘 conf 파일이 있지 않을까 싶었지만, 

없었다.


등록할 리모콘은 아래 두개, TV리모콘 (좌측), 홈씨어터 리모콘(우측)

스피커 연동이므로 등록할 버튼은 4개

전원, 볼륨업, 볼륨다운, 음소거


적외선 송수신 모듈을 붙이고, 수신 준비 (거금들인 돋보기 달린 더미집게가 조수이다)


1편에 비해서는 훨씬 수월하게 등록작업을 완료했다.


아래는 새로 등록한 conf 파일


스피커리시버 리모콘


begin remote
name AH59-01778Q
bits 16
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100

header 4502 4426
one 571 1650
zero 571 535
ptrail 573
pre_data_bits 16
pre_data 0xC2CA
gap 107772
min_repeat 7
# suppress_repeat 7
# uncomment to suppress unwanted repeats
toggle_bit_mask 0x0

begin codes
POWER 0x807F
VOLUMEUP 0xCC33
VOLUMEDOWN 0xDC23
MUTE 0x9C63
end codes end remote


TV 리모콘

begin remote

name BN59-01198P
bits 16
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100

header 4523 4486
one 531 1707
zero 531 589
ptrail 533
pre_data_bits 16
pre_data 0xE0E0
gap 107885
min_repeat 3
# suppress_repeat 3
# uncomment to suppress unwanted repeats
toggle_bit_mask 0x0

begin codes
POWER 0x40BF
VOLUMEUP 0xE01F
VOLUMEDOWN 0xD02F
MUTE 0xF00F
end codes
end remote


그리고 lircd.conf에 include 추가

include "/etc/lirc/dm-2901.conf"
include "/etc/lirc/BN59-01198P.conf"
include "/etc/lirc/AH59-01778Q.conf"

이로써 1편에서 추가한 주방TV와 총 세개의 리모콘이 등록되었다.


여기서 잠깐,

새로산 모니터 자랑!

LG 울트라와이드 29um58

그동안 조막만한 노트북으로 이창저창 닫았다 열었다 짜증이나서 구매했다.

PIP도 지원이 되서 두개의 HDMI 입력을 분할해서 보여주는 기능이 있지만, 우분투 드라이버는 없단다. ㅜㅜ


그래도 창 세개 동시에 봐가며 작업하는게 넘나 편하다.


이제 node.js 수정

언제나 느끼지만 node.js는 너무 편하다.

추가된 코드는 아래가 전부

lirc_node.addListener(function(data){
l("Received " + data.remote + " " + data.key);

if(data.remote == 'BN59-01198P') {
sendSignal('AH59-01778Q', data.key, null, 0);
} });

내용은 당연히 TV 리모콘에서 받은 신호를, 홈씨어터 리모콘으로 보내라....

pseudo code 쓰는 기분이다.


사실 node.js 에도 많은 개선이 있었다.

글로 담기에는 너무 많아서 나중에 여유가 되는대로 차근히 포스팅할 계획이다.

위에 보이는 l function도 winston 모듈을 도입하면서 로깅을 단순화 한 것이다.


테스트


테스트를 위해 라즈베리파이(Raspberry Pi)가 오랜만에 거실에 나왔다.

빵판과 전선을 주렁주렁 달고... ㅋㅋ

아래 화면 가운데에 IR 송신기가 보인다. 그리고 뒤편에 신호를 받을 스피커 리시버

아래는 스피커볼륨과 KODI를 한 리모콘으로 조종하는 영상이다.

TV와 우측의 홈씨어터 리시버의 파란 LED를 보면 리모콘 신호에 따라 전원, 볼륨업, 볼륨다운, MUTE 실행이 되는걸 볼 수 있다.

볼륨 업/다운은 한번 수신 시 2~3 칸씩 조절된다.


목표한대로 라즈비안에 KODI를 설치해서 TV와 CEC 연동을 한다. 

즉, TV 리모콘 하나로 스피커 볼륨을 조절하고, KODI를 조정한다는게 핵심!



내용추가


주말에 적용한 위 기능을 쓰던 중 몇 가지 문제점이 발견되었다.

1. 신호를 한번 누락하면 홈씨어터와 TV 전원이 서로 반대가 된다. 즉, 전원 신호는 절대로 놓치면 안된다.

2. 볼륨 신호를 라즈베리파이가 너무 과도하게 보내서 한칸 씩 세밀한 조정이 안된다. 단순히 몇차례 보내는 신호를 한번만 보내면 될 줄 알았는데, 한번만 보내도 몇칸씩 조절된다.



1번 문제는 일단 TV 신호를 잘 Detect 하게만 하면 홈씨어터 쪽으로 수차례 보내주면 된다. 수신부와 발신부의 각도를 좀 더 조절해도 큰 문제는 없는 듯...

2번은 신호의 세밀한 조정을 위해 lirc 코딩과 config 옵션을 찾아보았다. 생각보다 너무 많은 옵션에 당황하긴 했지만, 눈에 들어오는 몇가지 옵션이 있었다.


repeat <prepeat> <srepeat>

A pulse and space that replaces everything between leading pulse and the trailing pulse, whenever a signal is repeated. The foot is not sent, and the header is not sent unless the REPEAT_HEADER flag is present.

..........................

repeat_gap <repeat_gap length>

A gap immediately following the trailing pulse, and preceding a repetition of the same code that's due to a the same press of the button.

min_repeat <minimum number of repetitions>

The minimum times a signal is repeated when sent. Note that 0 means the signal is sent only once. Not used when receiving.


더 자세한 건 아래 출처에서 참조하자.

http://www.lirc.org/html/lircd.conf.html


현재 홈씨어터 리모콘 설정을 보니 min_repeat 이 7로 셋팅되어 있었다.

min_repeat  0 으로 해보니 한칸씩 움직이긴 한다... 그런데 잘 안움직인다.

그래서 1만 줬는데 볼륨이 간헐적으로 두칸씩 움직인다..

일단 min_repeat  0 으로 하고, 코딩으로 해결하기로....


※ lirc 를 재시작하니 forever restart 해도 lirc 모듈이 먹통이다. 명시적으로 forever stop, start를 해주어야 한다.


코딩에서 사용한 send_once function 대신, send_start, send_stop으로 미세조정 돌입.


무수한 시험 결과 솔루션은 아래와 같다.

var hold = false;

function holdListen() {
hold = true;
}

function releaseListen() {
hold = false;
}

lirc_node.addListener(function(data){
l("Recv " + data.remote + " " + data.key);

if(data.remote == 'BN59-01198P') {
if(data.key == 'POWER')
sendSignal('AH59-01778Q', data.key, null, 3);
else {
if(hold == true){
l('holdListen!');
return;
}
holdListen();
sendSignal_msec('AH59-01778Q', data.key, null, 300);
setTimeout(releaseListen, 300);
}
}
});

var sendSignal = function(name, sig, res, cnt){
for(var i=0; i<cnt; i++){
lirc_node.irsend.send_once(name, sig);
}
lirc_node.irsend.send_once(name, sig);

l("Sent " + name + " " + sig + " " + (cnt+1));

if(res != null)
res.send([{result:'ok'}]);
};

var stopSignal = function() {
lirc_node.irsend.send_stop();
}

var sendSignal_msec = function(name, sig, res, msec){
lirc_node.irsend.send_start(name, sig);
l("Sent for " + msec + "msec");
setTimeout(stopSignal, msec);

if(res != null)
res.send([{result:'ok'}]);
}

역시 코드가 길어지고, 시간도 오래 걸렸다.

2:8의 법칙이라고,,,

제품을 만드는데 총 100일이  걸린다면,

80%의 기능을 만드는데 20일이 걸리고,

나머지 20%를 완성하는데에 80일이 걸린다고 했다.

진리인듯...

728x90