무아스 LED 벽시계의 IR 리모콘을 아두이노로 구현
하드웨어개조/아두이노(Arduino) / 2026. 8. 3. 16:25
잃어버린 IR 리모콘을 다시 구현하는 과정을 이미 정리한 적이 있었으나,
이번에 AI의 도움을 받아서, 확실하게 모든 리모콘 기능을 구현하였습니다.
IR 송신부 회로는 아래와 같이 구성하면 되는데,
아두이노 우노 또는 나노를 사용하고, 나중에 코드에서도 설명되겠지만, IR 송신핀은 코드와 맞춰서 사용한다.
아래 그림에는 D9로 되어 있지만, 실제 이후 코드에서는 D12를 사용하였다.
그리고, 사용한 IRed가 SI3317-H 이지만, 다른 제품을 사용한다면, R1 저항 33오옴을 적절하게 바꿔야만 한다.

만약 IRed를 SI5315-DS로 바꿔서 사용하려면, R1 저항을 68오옴으로 교체해야만 한다.
데이터시트상에서 체크한 내용이
순방향 전류 IF 정격입니다. 앞서 드린 33Ω은 SI3317-H의 IF = 100mA를 전제로 계산한 값입니다.
IF 정격R1 값비고
| 100mA | 33Ω, 1/4W | 그대로 사용 |
| 50mA | 68Ω, 1/4W | 저항만 교체 |

그래서, 위의 조작법을 보고, SW1~SW8을 원래 리모콘 배치 그대로 매핑했습니다.
스위치 짧게 길게 (0.7초)
| SW1 ⏻ | 전원 | – |
| SW2 ↻ | 화면 전환 | 디스플레이 모드 설정 |
| SW3 ☀ | 자동밝기 ON/OFF | 페이드 인/아웃 ON/OFF |
| SW4 🔔 | 알람 ON/OFF | – |
| SW5 🕐 | (확정 / OK) | 시간설정 |
| SW6 ⏰ | 알람시간 확인 | 알람시간 설정 |
| SW7 + | 밝기 올림 / 숫자 올림 | 연속 증가 |
| SW8 - | 밝기 내림 / 숫자 내림 | 연속 감소 |
아두이노 코드 .ino 파일은 다음과 같습니다.
---------------------------------------------------------------------------------------------------------------
/*
* 무아스 퓨어 슬림 LED 벽시계 IR 리모콘
* 8버튼 · 짧게/길게 누름 / 아두이노 나노·우노 공통
*/
#define DISABLE_CODE_FOR_RECEIVER
#define IR_SEND_PIN 12
#include <IRremote.hpp>
#define HOLD_MS 700 // 700ms = 0.7초, 이 시간 이상 누르면 '길게'
#define LONG_REPS 24 // 길게 1회성 명령용 (SW2·3·5·6)
#define MAX_REPEAT 200 // 연속 증감 상한 (약 22초), 숫자 수정시에 연속된 증감을 위해,
const uint8_t NKEYS = 8;
const uint8_t keyPins[NKEYS] = {2, 3, 4, 5, 6, 7, 8, 9}; // 아두이노에 연결된 키들을 연결하는 곳은 D2~D9 까지 8개의 키에 각각 매핑, 그리고 GND 가 하나 더 꽂아져야 하겠지요!
// SW1 SW2 SW3 SW4 SW5 SW6 SW7 SW8
const uint8_t shortCmd[NKEYS]={0x1C, 0x40, 0x08, 0x44, 0x5E, 0x4A, 0x18, 0x52}; // 키에 할당되는 코드 값
const bool hasLong[NKEYS] ={false,true, true, false,true, true, true, true}; // 길게 누르는 키의 존재 여부
// SW7, SW8만 연속 반복
const bool holdRepeat[NKEYS] = {false,false,false,false,false,false,true,true};
const char* names[NKEYS] = {
"POWER", "DISPLAY", "AUTO BRIGHT", "ALARM",
"CLOCK", "ALARM TIME", "UP +", "DOWN -"
};
bool stable[NKEYS], raw[NKEYS];
uint32_t lastChange[NKEYS];
const uint16_t DEBOUNCE_MS = 25;
void setup() {
Serial.begin(115200);
for (uint8_t i = 0; i < NKEYS; i++) {
pinMode(keyPins[i], INPUT_PULLUP);
stable[i] = raw[i] = true;
lastChange[i] = 0;
}
pinMode(LED_BUILTIN, OUTPUT);
IrSender.begin(DISABLE_LED_FEEDBACK);
Serial.println(F("--- Mooas remote ready (8 buttons) ---"));
}
// 눌린 채 유지되는지 확인 (디바운스 포함)
bool held(uint8_t i) {
return (digitalRead(keyPins[i]) == LOW);
}
void fire(uint8_t i, bool isLong) {
digitalWrite(LED_BUILTIN, HIGH);
if (isLong && holdRepeat[i]) {
IrSender.sendNEC(0x00, shortCmd[i], 0); // 첫 프레임
uint16_t n = 0;
uint8_t miss = 0;
while (n < MAX_REPEAT) { // 뗄 때까지 반복
delay(n == 0 ? 42 : 98);
if (!held(i)) { if (++miss >= 3) break; }
else miss = 0;
IrSender.sendNECRepeat();
n++;
}
Serial.print(F(" (repeat ")); Serial.print(n); Serial.print(F(")"));
} else {
IrSender.sendNEC(0x00, shortCmd[i], isLong ? LONG_REPS : 0);
}
digitalWrite(LED_BUILTIN, LOW);
Serial.print(F("SW")); Serial.print(i + 1);
Serial.print(F(" ")); Serial.print(names[i]);
Serial.println(isLong ? F(" [LONG]") : F(" [short]"));
}
void loop() {
uint32_t now = millis();
for (uint8_t i = 0; i < NKEYS; i++) {
bool r = digitalRead(keyPins[i]);
if (r != raw[i]) { raw[i] = r; lastChange[i] = now; }
if ((now - lastChange[i]) < DEBOUNCE_MS || stable[i] == r) continue;
stable[i] = r;
if (r != LOW) continue; // 뗀 것은 무시
if (!hasLong[i]) { // 길게가 없으면 즉시 전송
fire(i, false);
} else {
uint32_t t0 = now;
uint8_t miss = 0;
while (millis() - t0 < HOLD_MS) { // 계속 누르고 있나 관찰
if (!held(i)) { if (++miss >= 3) break; }
else miss = 0;
delay(10);
}
fire(i, (millis() - t0) >= HOLD_MS);
}
uint8_t rel = 0; // 손 뗄 때까지 대기
while (rel < 5) {
if (!held(i)) rel++; else rel = 0;
delay(10);
}
stable[i] = raw[i] = true;
lastChange[i] = millis();
}
}
리모콘을 만들기 위한 긴 여정은 이제 여기서 끝마친다!

