아두이노:IR 송수신
둘러보기로 이동
검색으로 이동
아두이노 관련 정보를 모으기 위한 틀. 틀:아두이노
- 아두이노:개요
- 아두이노:하드웨어
- 아두이노:코드
- 아두이노:핀 사용
- 아두이노:시리얼 통신
- 아두이노:편의함수
- 센서 사용
- 아두이노:LCD 사용
- 아두이노:스위치 사용
- 아두이노:릴레이
- 통신 관련, 정보 교환
- 아두이노:해결되지 않은 다양한 의문들
- 수업용 간단 실습
- 아두이노 모터 출력
- 미완문서
- 분류:아두이노 프로젝트
개요[편집 | 원본 편집]
적외선 리모컨 신호를 받아들이고 반대로 적외선 신호를 내보내는 과정에 대하여.
- 중심 표준은 없지만, 38kHz가 일반적. NEC 프로토콜이 38kHz를 사용한다. 너무 낮으면 주변광의 노이즈를 받게 되고, 전송 속도가 느리며, 너무 높으면 비싸지고, 회로 설계에 따라 신호 감쇠/손실될 수 있다.
NEC 규약[편집 | 원본 편집]
- 기본적으로 시작 신호와 끝 신호를 주고 시작하며(송신기에서 9ms ‘HIGH’ + 4.5ms ‘LOW’ 신호 → 데이터 시작 신호),
- 오염을 염두에 둔다. 예컨대 값이 0xCC33FF00인 경우. 00이 주소값, 33이 명령값이다. CC는 33에 대한 반전값, FF는 주소에 대한 반전값이다. 반전값을 두어 데이터 전송에 문제가 없는지 확인한다. 즉, 의미가 있는 것은 00과 33 부분. 나머지는 검증용이다.
하드웨어[편집 | 원본 편집]
IR 수신기[편집 | 원본 편집]
| 종류 | 설명 | 비고 |
|---|---|---|
| VS1838B | 중심주파수: 38 kHz (표준 TV/가전 리모컨 대부분) | 구조 링크 |
| KY-022 | VS1838B에 기판 단 것.(머리부분에 1838이라 각인되어 있다)
기판에 축전기랑 저항 달려있어서 노이즈를 줄인다. |
|
| TSOP38238 | 수신거리가 12m정도로 위보다 조금 짧지만, 노이즈에 강함. |
IR 송신기[편집 | 원본 편집]
리모컨 앞에 달린 둥그런 그것.
| 종류 | 설명 | 비고 |
|---|---|---|
| 적외선 LED | ||
| KY-005 | 적외선 LED만 있어도 되지만, 편의사항 증진.
하지만, 신호가 별로 멀리 나가진 않는다; |
KY-022와 유사함. |
활동 예시[편집 | 원본 편집]
송신기 준비물[편집 | 원본 편집]
- 우노, 연결용 USB 선
- 송신모듈
- 암수 점퍼선 3개
수신기 준비물[편집 | 원본 편집]
- 우노, 연결용 USB 선
- 수신기 작동 확인용 리모컨
- 수신모듈
- 암수 점퍼선 3개
코드[편집 | 원본 편집]
수신 관련 코드[편집 | 원본 편집]
IRremote 라이브러리를 요한다. 라이브러리 매니저에서 받는 게 가장 편함.
#include <IRremote.h>
int RECV_PIN = 11;
void setup() {
Serial.begin(9600);
IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK); // 수신기 시작
Serial.println("수신기 준비!");
}
void loop() {
if (IrReceiver.decode()) {
if (IrReceiver.decodedIRData.protocol != NEC || IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
IrReceiver.resume();
return; // 리피트 신호 무시
}
// 정상 NEC 코드 처리
Serial.print("NEC 주소=0x"); Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(", 명령=0x"); Serial.print(IrReceiver.decodedIRData.command, HEX);
// raw값 보여주기.
unsigned long rawCode = IrReceiver.decodedIRData.decodedRawData;
Serial.print(", Raw값=0x"); Serial.println(rawCode, HEX);
IrReceiver.resume();
}
}
비고[편집 | 원본 편집]
종종 받은 값: 0x0이 뜨는 이유: 버튼이 눌린 채로 있음을 나타내는 경우.
송신 관련 코드[편집 | 원본 편집]
수신과 마찬가지로 IRremote 라이브러리를 요한다. 라이브러리 매니저에서 받는 게 가장 편함.
#include <IRremote.h>
// 송신 핀 (일반적으로 D3)
#define IR_SEND_PIN 3
void setup() {
Serial.begin(9600);
// 송신기 초기화 (LED 피드백 LED_BUILTIN 사용)
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK, LED_BUILTIN);
Serial.println("IR 송신기 준비 완료");
}
void loop() {
byte address = 0x00; // 00부터 FF까지 기입 가능.
byte command = 0x33; // 00부터 FF까지 기입 가능.
byte addressInv = address ^ 0xFF;
byte commandInv = command ^ 0xFF;
unsigned long necCode = ((unsigned long)commandInv << 24) |
((unsigned long)command << 16) |
((unsigned long)addressInv << 8) |
address;
Serial.print("송신 NEC 코드: 0x");
Serial.println(necCode, HEX);
IrSender.sendNECRaw(necCode, 32);
delay(5000);
}
비고[편집 | 원본 편집]
- 송신 핀은 PWM을 쓸 수 있는 핀에 꽂아야 한다.
더 해볼 만한 활동[편집 | 원본 편집]
- 오차의 원인은 무엇일까?
송수신 합친 코드[편집 | 원본 편집]
송신과 수신, 보드가 2개 필요한데, 하나로 합칠 수 있을까?
#include <IRremote.h>
#define RECV_PIN 2 // 수신기 핀
#define SEND_PIN 3 // 송신기 핀
unsigned long learnedCode = 0; // 학습된 코드 저장
void setup() {
Serial.begin(9600);
// 수신기 초기화
IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK);
// 송신기 초기화
IrSender.begin(SEND_PIN);
Serial.println("리모컨 버튼을 눌러 학습하세요...");
}
void loop() {
// ===== 1. 리모컨 수신 =====
if (IrReceiver.decode()) {
learnedCode = IrReceiver.decodedIRData.decodedRawData; // 학습
Serial.print("학습된 코드: 0x");
Serial.println(learnedCode, HEX);
IrReceiver.resume(); // 다음 신호 준비
}
// ===== 2. 시리얼 입력 확인 =====
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input == "send") {
if (learnedCode != 0) {
Serial.print("코드 송신 중: 0x");
Serial.println(learnedCode, HEX);
// NEC 프로토콜로 송신 (32비트 코드)
IrSender.sendNEC(learnedCode, 32);
} else {
Serial.println("아직 학습된 코드가 없습니다!");
}
}
}
}
의문 해결[편집 | 원본 편집]
송신 관련 코드에서 아래처럼 쓰는데 << 숫자의 의미는 무엇일까?
unsigned long necCode = ((unsigned long)commandInv << 24) |
((unsigned long)command << 16) |
((unsigned long)addressInv << 8) |
address;