1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <IRremote.h>                 // IR Remote (ver 2.5.0) 라이브러리 사용
#include <Servo.h>                    // Servo 라이브러리 사용
#include <U8glib.h>                   // OLED 디스플레이 라이브러리 사용
 
#define IR_PIN      2                 // IR 수신 센서 Pin 번호
#define SERVO_PIN   3                 // 서보모터 Pin 번호
#define BUZZER_PIN  4                 // 피에조 부저 Pin 번호
 
#define EFFECT_WAKE_UP    1           // 부저 효과음 - 입력 활성화
#define EFFECT_UNLOCK     2           // 잠금해제
#define EFFECT_KEY_ERR    3           // 키 오류
#define EFFECT_INPUT_NUM  4           // 키 입력
 
// 객체 선언
IRrecv ir(IR_PIN);
Servo servo;
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);
 
// IR 리모컨 신호 리스트
long irSignalList[] = {
  167124451672876516732845,
  1673845516750695167568151672417516718055,
  1674304516716015167262151673488516730805,
};
 
// IR 신호별 문자 리스트
String irCharList[] = {
  "OK""*""#",
  "1""2""3""4""5""6""7""8""9""0",
};
 
 
bool isWakeup, isLock;            // 입력 활성화, 잠금 상태 값
String receiveStr = "";           // IR 신호 문자 값
String inputStr = "";             // 입력 키 값
long inputTime;                   // 입력 동작 시간
long timeOut = 1000 * 10;         // 입력 종료 시간
 
String unlockStr = "2021";        // 잠금해제 키 값
 
void setup() {
  Serial.begin(115200);
  u8g.begin();                                // OLED 모듈 활성화
  servo.attach(SERVO_PIN, 0180);            // 서보 모터 초기화
 
  pinMode(BUZZER_PIN, OUTPUT);                // 부저 모듈 Pin 모드 설정
 
  servo.write(0);                             // 서보모터 초기 각도 제어
  ir.enableIRIn();                            // IR 수신 활성화
 
  showLockState();                            // 잠금상태 OLED 출력
}
 
void loop() {
  irReceiver();                               // IR 신호 수신
  setLockStatus();                            // 잠금 상태 설정
 
  // 입력 가능 시간 체크
  if (isWakeup && millis() - inputTime > timeOut) {           // 입력이 활성화된 상태에서 지정 시간만큼 시간이 지나면
    isWakeup = false;                                               // 입력 비활성화 상태로 전환
    inputStr = "";                                                  // 입력 키 정보 초기화
    showLockState();                                                // 잠금상태 OLED 출력
  }
  delay(50);
}
 
// 잠금 상태 설정 함수
void setLockStatus() {
  if (receiveStr != "") {                                 // 지정된 문자에 대한 IR 신호 수신 시,
    if (receiveStr.equals("*")) {                                     // "*" 문자 수신 시, 입력 활성화 설정                        
      isWakeup = !isWakeup;                                                     // 입력 활성화 상태 변경
      inputStr = "";                                                            // 입력 키 정보 초기화              
      isWakeup ? showInputNumber() : showLockState();                           // 활성화 상태에 따른 OLED 정보 출력
      soundEffect(EFFECT_WAKE_UP);                                              // 입력 활성화 효과음 출력
      
    } else if (receiveStr.equals("#"&& isLock) {                    // "#" 문자 수신 및 잠금해제 상태 시, 잠금 설정    
      servo.write(0);                                                           // 서보 모터 각도 초기화
      isLock = isWakeup = false;                                                // 잠금 상태, 입력 비활성화 상태 설정
      showLockState();                                                          // 잠금상태 OLED 출력
      
    } else if (isWakeup) {                                            // 입력 활성화 상태 시,
      inputStr += receiveStr;                                                   // 입력 키 정보에 IR 신호 문자 추가
      showInputNumber();                                                        // 입력 키 정보 OLED 출력
      soundEffect(EFFECT_INPUT_NUM);                                            // 키 입력 효과음 출력
      
      if (inputStr.length() == 4) {                                             // 4자리 키 정보 입력 시,
        delay(300);
        if (inputStr.equals(unlockStr)) {                                               // 잠금해제 키 정보와 일치할 경우,
          isLock = true;                                                                      // 잠금 해제 상태로 설정
          isWakeup = false;                                                                   // 입력 비활성화 설정
          soundEffect(EFFECT_UNLOCK);                                                         // 잠금 해제 효과음 출력
          showLockState();                                                                    // 잠금상태 OLED 출력
          servo.write(180);                                                                   // 서보 모터 각도 제어
          
        } else {                                                                        // 잠금해제 키 정보와 불일치할 경우,
          inputStr = "";                                                                      // 입력 키 정보 초기화
          soundEffect(EFFECT_KEY_ERR);                                                        // 키 오류 효과음 출력
          showInputNumber();                                                                  // 입력 키 정보 OLED 출력
        }
      }
    }
    inputTime = millis();                                    // 입력 시작 시간 초기화
    receiveStr = "";                                         // IR 수신 문자 초기화
  }
}
 
// 입력 키 정보 OLED 출력 함수
void showInputNumber() {
  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_unifont);                            // 폰트 설정
    u8g.undoScale();                                          // 폰트 스케일 초기화
    u8g.drawStr(1416"INPUT NUMBER");                      // 텍스트(Title) 출력
    u8g.setScale2x2();                                        // 폰트 스케일 증가
    String showNum = "";
    for (int i = 0; i < inputStr.length(); i++) {                         // 입력 키 문자열 길이만큼 반복문 실행
      showNum += i > 0 ? " " + String(inputStr[i]) : inputStr[i];             // 첫번째 문자 이후부터 공백 " " 추가 
    }
    u8g.drawStr(326, showNum.c_str());                      // 입력 키 정보 출력
  } while ( u8g.nextPage() );
}
 
// 잠금 상태 정보 OLED 출력 함수
void showLockState() {
  u8g.firstPage();
  do {
 
    u8g.setFont(u8g_font_unifont);                            // 폰트 설정
    u8g.undoScale();                                          // 폰트 스케일 초기화
    u8g.drawStr(3816"IR LOCK");                           // 텍스트(Title) 출력
    u8g.setScale2x2();                                        // 폰트 스케일 증가
    if (isLock) {                                             // 잠금 상태에 따른 텍스트 출력
      u8g.drawStr(1626"OPEN");
    } else {
      u8g.drawStr(1226"CLOSE");
    }
  } while ( u8g.nextPage() );
}
 
// IR 신호 수신 함수
void irReceiver() {
  decode_results res;
  if (ir.decode(&res))                                          // IR 신호 수신 시,
  {
    if (res.decode_type == 3 && res.bits == 32) {                        // 지정 IR 타입 및 크기(32Bit)의 신호 수신 시,
      int irPos = -1;
      for (int i = 0; i < sizeof(irSignalList); i++) {                   // IR 리모컨 신호 리스트에서 해당 신호의 인덱스 검출
        if (res.value == irSignalList[i]) {
          irPos = i;
          break;
        }
      }
      receiveStr = irPos != -1 ? irCharList[irPos] : "";                 // IR 신호 리스트의 인덱스 기준 IR 문자 호출 및 저장 
    }
    ir.resume();                                                // IR 신호 수신 대기
  }
}
 
// 피에조 부저 효과음 출력 함수
void soundEffect(int type) {
  if (type == EFFECT_WAKE_UP) {                                 // 입력 활성화 효과음
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
    delay(50);
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
  } else if (type == EFFECT_UNLOCK) {                           // 잠금 해제 효과음
    digitalWrite(BUZZER_PIN, HIGH);
    delay(300);
    digitalWrite(BUZZER_PIN, LOW);
    delay(50);
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
    delay(50);
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
  } else if (type == EFFECT_KEY_ERR) {                           // 입력 키 오류 효과음
    digitalWrite(BUZZER_PIN, HIGH);
    delay(500);
    digitalWrite(BUZZER_PIN, LOW);
  } else {                                                       // 키 입력 효과음
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
  }
}
cs

+ Recent posts