최근에 코엑스에서 사물인터넷 전시회를 해서 다녀왔다. 

전시회에 나온 제품들을 보면서 놀라기도 놀라면서 아주 간단한 아이디어로 사물인터넷 제품들을 보며 많은 것을 느끼게 되었다.

그래서 전시회에 나온 제품들중 내가 비슷하게 흉내낼수 있는 것을 한번 만들어보자 라는 생각을 가지게 되었다.

첫번째는 IoT Door Lock 이다.

전시회에서 본 IoT 도어락은 카메라도 달려있어서 방문자를 기록하고, 모바일에서도 실시간으로 확인이 가능한 시스템이었다. 일반적인 가정집에서 궂이 왜 모바일로 방문자의 얼굴을 확인해야 하는지 좀 궁금했다. 출입보안이 엄격한 곳에서는 이러한 기능이 필요한것 같지만...

아무튼 대충 가격을 물어보니 5~60만원 수준인 것으로 설명을 해주셨는데...너무 비싸다. 요즘 아주 저렴한 도어락이 5만원 정도인 것을 감안하면 상당히 고가 인것을 알수 있었다. 

그래서 대충 IoT Smart Door Lock을 만들어 보았다. 아래 내용은 IoT Smart Door Lock를 만드는 과정을 설명해 보았다.


개요

일단 처음에 생각했던 구성은 도어락 기구물을 만들고 기구물을 모터를 제어해서 Lock/Unlock 기능을 구연하고, RFID 태그와 모바일을 통해서 도어락을 제어하는 것으로 생각을 했다.

뭐 모터를 제어하고 RFID나 모바일로 제어하는 것은 그렇게 어렵다고 생각하지 않았다. 하지만...기구물이 문제였다. 왜냐면 나는 3D 모델링을 거의 못하기 때문이다. 그래서 Thingiverse에서 찾아봐서 아주 좋은 도어락 기구물을 찾았다. 아래 URL이다.

http://www.thingiverse.com/thing:465349

위 사진과 같은 형태로 도어락을 구성할 계획을 가지고 진행 했다.


구성


기본적인 구성도는 위 그림처럼 될 것이다. 

구성되는 하드웨어는  아두이노 메가, 아두이노 이더넷 쉴드, RFID 모듈, 서보모터, 도어락 기구물 이 될것이고, Blynk 라는 앱을 통해서 모바일에서 도어락이 제어 될것이다. 


RFID

RFID(Radio-Frequency Identification)는 주파수를 이용해 ID를 식별하는 SYSTEM으로 일명 전자태그로 불린다. RFID 기술이란 전파를 이용해 먼 거리에서 정보를 인식하는 기술을 말한다. 여기에는 RFID 태그(이하 태그)와, RFID 판독기(이하 판독기)가 필요하다. 태그는 안테나와 집적 회로로 이루어지는데, 집적 회로 안에 정보를 기록하고 안테나를 통해 판독기에게 정보를 송신한다. 이 정보는 태그가 부착된 대상을 식별하는 데 이용된다. 쉽게 말해, 바코드와 비슷한 기능을 하는 것이다. RFID가 바코드 시스템과 다른 점은 빛을 이용해 판독하는 대신 전파를 이용한다는 것이다. 따라서 바코드 판독기처럼 짧은 거리에서만 작동하지 않고 먼 거리에서도 태그를 읽을 수 있으며, 심지어 사이에 있는 물체를 통과해서 정보를 수신할 수도 있다.

RFID는 사용하는 동력으로 분류할 수 있다. 오직 판독기의 동력만으로 칩의 정보를 읽고 통신하는 RFID를 수동형(Passive) RFID라 한다. 반수동형(Semi-passive) RFID란 태그에 건전지가 내장되어 있어 칩의 정보를 읽는 데는 그 동력을 사용하고, 통신에는 판독기의 동력을 사용하는 것을 말한다. 마지막으로 능동형(Active) RFID는 칩의 정보를 읽고 그 정보를 통신하는 데 모두 태그의 동력을 사용한다.

RFID를 동력 대신 통신에 사용하는 전파의 주파수로 구분하기도 한다. 낮은 주파수를 이용하는 RFID를 LFID(Low-Frequency IDentification)이라 하는데, 120~140 킬로헤르츠(kHz)의 전파를 쓴다. HFID(High-Frequency IDentification)는 13.56 메가헤르츠(MHz)를 사용하며, 그보다 한층 높은 주파수를 이용하는 장비인 UHFID(UltraHigh-Frequency IDentification)는 868 ~ 956 메가헤르츠 대역의 전파를 이용한다. 

위 내용은 위키백과에서 발췌한 내용이다. 자세한 내용은 아래 URL을 참고하길 바란다.

https://ko.wikipedia.org/wiki/RFID

쉽게 설명하면 우리가 자주사용하는 교통카드, 건물 출입카드, 하이패스 등이 RFID가 사용된 주요 예시이다.

위 사진이 우리가 일반적으로 사용하는 RFID 태그(버스카드)의 구조로 볼 수있다. 

버스카드를 예로 들면 우리가 버스카드 리더기(RFID 리더기) 에 버스카드(RFID 태그)를 가까이 대면 버스카드의 안테나에 자기장이 유도가 되어 전류가 흐르게 된다. 일반적인 트랜스의 원리로 보면된다. 전류가 흐르기 때문에 버스카드에 내장된 칩이 버스카드 리더기로 데이터를 전송하게 되는 것이다. 안테나에 전류가 유도 되어야 칩이 동작하기 때문에 버스카드와 버스카드 리더기는 근거리에 있어야 정보교환이 가능하다. 이러한 형태가 수동형 이다.

하이패스는 자동차에 장착된 하이패스 단말기와 톨게이트의 하이패스 리더기와 이러한 통신이 이루어진다. 차동차에 장착된 하이패스 단말기는 별도의 전원이 공급이 되어 동작을 하기 때문에 원거리에 있는 하이패스 리더기와 정보교환이 가능하다. 이러한 형태가 능동형 이다.

내가 사용한 RFID 리더기 모듈은 RFID-RC522 이다. SPI I/F를 이용해 통신이 가능하고 관련된 예제도 찾아보면 상당히 많다. 

아두이노 라이브러리는 아래 URL에서 다운받을수 있다.

https://github.com/miguelbalboa/rfid


Blynk

Blynk는 kickstarter에서 크라우드 펀등을 진행한 앱이고, 2014년 5월에 펀딩을 시작해 5500만원 정도의 금액을 확보하고, 2015년 1월부터 서비스를 시작한 시스템입니다. Blynk는 사용자가 앱을 통해서 손쉽게 IoT 디바이스를 원격에서 제어, 모니터링이 가능하다. 별도의 제어하는 코드 없이 앱에서 몇가시 설정만 해도 IoT 디바이스가 제어가 가능하다. 

나도 이번에 처음 사용해 봤는데 정말 편한 시스템인것 같다.

또 하나의 장점은 디바이스가 이더넷이 되지 않아도 PC와 USB로 연결만 되어 있다면 Blynk 앱에서 제어가 가능한 것이다.


자세한 내용은 아래 URL의 공식 홈페이지에서 확인해보길 바란다.

http://www.blynk.cc/


서보모터

서보모터는 이전에 작성한 글이 있기 때문에 그것을 대체하겠다. 

2016/07/05 - [IT / Development/Arduino] - Arduino로 Servo Motor를 제어해 보자.


회로

위 사진과 같이 회로를 구성해서 테스트를 진행하고 완성을 했다.


기구

http://www.thingiverse.com/thing:465349

위 URL에서 다운받은 것을 3D프린터로 인쇄해서 조립한 모습니다. 우드락으로 간이 문을 만들었다.

그리고 자동으로 문을 열고 닫을 수 있도록 해보았다. 문을 열고 닫는 기구의 아래 URL에서 다운 받았다.

http://www.thingiverse.com/thing:524593


Blynk 구성

Blynk App의 구성은 아래 사진과 같이 구성을 했다. 도어락의 상태를 표시해주는 LCD와 장금장치 On/OFF 버튼, 문 On/Off 버튼, 잠금장치와 문을 On/Off라는 버튼을 만들었다.


코드

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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <SPI.h>
#include <MFRC522.h>
#include <Ethernet2.h>
#include <BlynkSimpleEthernet2.h>
#include <Servo.h> 
 
/////////////////////////////////////////////
//////////// ***** Define ***** /////////////
//RC522 Pin define
#define RST_PIN         48
#define SS_PIN          53 
 
//Buzzer Pin define
#define BUZZER_PIN      49
 
//LED Pin define
#define R_LED        2
#define G_LED        3
#define B_LED        4
 
//Servo Pin define
#define USE_SERVO  2
#define DOOR_LOCK  0  //buffer numbering
#define AUTO_DOOR  1  //buffer numbering
#define OPEN 0
#define CLOSE 1
 
//for DOOR LOCK
#define DOOR_LOCK_PIN  5
#define DOOR_LOCK_OPEN_START 85   // DoorLock unlock start angle (0~180) (case by user)
#define DOOR_LOCK_OPEN_STOP 20  // DoorLock unlock stop angle (0~180) (case by user)
#define DOOR_LOCK_CLOSE_START  20  // DoorLock lock start angle (0~180) (case by user)
#define DOOR_LOCK_CLOSE_STOP  85  // DoorLock lock stop angle (0~180) (case by user)
 
//for AUTO DOOR
#define DOOR_PIN 6
#define DOOR_OPEN_START     150  // Door open start angle (0~180) (case by user)
#define DOOR_OPEN_STOP    35  // Door open stop angle (0~180) (case by user)
#define DOOR_CLOSE_START  35  // Door close start angle (0~180) (case by user)
#define DOOR_CLOSE_STOP  150  // Door close stop angle (0~180) (case by user)
 
//Tap Mode define
#define REGIT        0
#define UNREGIT        1
#define    UNTAP        2
 
 
/////////////////////////////////////////////
///////// ***** Declare class ***** /////////
Servo door_servo[USE_SERVO];  // create servo object to control a servo 
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
WidgetLCD lcd(V0);   //WigetLCD init
 
 
/////////////////////////////////////////////
//////// ***** Global variable ***** ////////
int pos;    // variable to store the servo position  
String strID = "";
char idQty = 2;
char tapMode;
unsigned char preTapMode = UNTAP;
static bool flag_locker_open_state = CLOSE;
static bool flag_door_open_state = OPEN;
 
 
/////////////////////////////////////////////
//////// ***** Const variable ***** /////////
const String registeredID[] = { "A2:08:43:6D",  "09:C6:8F:00" }; //Registered ID List
const char auth[] = "b3130de6c7bd4e80977566e52b0fae50"//Blynk auth token key
 
 
/////////////////////////////////////////////
///// ***** Main Fuction : setup ***** //////
void setup() {
    //RC522 SS Pin init
    pinMode(SS_PIN, OUTPUT);
    digitalWrite(SS_PIN, HIGH);
    //Buzzer Pin init
    pinMode(BUZZER_PIN, OUTPUT);
    digitalWrite(BUZZER_PIN, HIGH);
    //RGB LED Pin init
    pinMode(R_LED, OUTPUT);
    digitalWrite(R_LED, HIGH);
    pinMode(G_LED, OUTPUT);
    digitalWrite(G_LED, HIGH);
    pinMode(B_LED, OUTPUT);
    digitalWrite(B_LED, HIGH);
 
    Serial.begin(115200);        // Initialize serial communications with the PC
                                //while (!Serial);        // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    Serial.println("Hello Arduino!");
 
    Blynk.begin(auth);        //Blynk init
    while (Blynk.connect() == false);
    Serial.println("Conneced Blynk Server.");
    lcd.clear();
    lcd.print(10"IoT Door Lock!");
    lcd.print(21"Hello Blynk!");
 
    mfrc522.PCD_Init();        // Init MFRC522
 
                            // You must initialize DOOR_LOCK firstly and AUTO_DOOR secondly
    servo_init(DOOR_LOCK, DOOR_LOCK_PIN); // attaches the servo on pin to the servo object 
    servo_init(AUTO_DOOR, DOOR_PIN); // attaches the servo on pin to the servo object 
}
 
/////////////////////////////////////////////
////// ***** Main Fuction : loop ***** //////
void loop() {
    digitalWrite(B_LED, LOW);        //Blue LED On
    tapMode = readRFID_UID();        //Read UID of Card 
 
    if (!(tapMode == preTapMode))
    {
        Serial.println("Tap card.");
        preTapMode = tapMode;
 
        switch (tapMode)
        {
        case REGIT:            //Registered Card
            digitalWrite(B_LED, HIGH);    //Blue LED Off
            digitalWrite(G_LED, LOW);    //Green LED On
            Serial.println("Registered");
            lcd.clear();
            lcd.print(20"Registered.");
            lcd.print(31"Welcome!!");
            lcd.clear();
            lcd.print(20"Registered.");
            lcd.print(11"Open the Door!");
 
            locker_unlock();
            door_open();
            delay(5000); // for auto test
            door_close();
            locker_lock();
 
            digitalWrite(G_LED, HIGH);    //Green LED Off
            break;
 
        case UNREGIT:        //Unregistered Card
            digitalWrite(B_LED, HIGH);    //Blue LED Off
            digitalWrite(R_LED, LOW);    //Red LED On
            Serial.println("Unregistered.");
            lcd.clear();
            lcd.print(10"Unregistered.");
            lcd.print(31"Get out!!");
            delay(2000);
            buzzer_beep_beep();
            digitalWrite(R_LED, HIGH);    //Red LED Off
            break;
 
        case UNTAP:            //Untap the card
            digitalWrite(B_LED, LOW);    //Blue LED On
            Serial.println("Locked the Door");
            lcd.clear();
            lcd.print(10"IoT Door Lock!");
            lcd.print(11"Lock the Door!");
        }
    }
    Blynk.run();
}
 
 
 
/////////////////////////////////////////////
//////// ***** Define function ***** ////////
//Locker Control
BLYNK_WRITE(V1)
{
    buzzer_beep();
    //Lock
    if (param.asInt())    //HIGH
    {
        digitalWrite(R_LED, HIGH);    //RED LED Off
        locker_lock();
    }
    //Unlock
    else    //LOW
    {
        digitalWrite(R_LED, LOW);    //RED LED On
        locker_unlock();
    }
}
 
//Door Control
BLYNK_WRITE(V2)
{
    buzzer_beep();
    //Close
    if (param.asInt())    //HIGH
    {
        digitalWrite(G_LED, HIGH);    //Green LED Off
        door_close();
    }
    //Open
    else    //LOW
    {
        digitalWrite(G_LED, LOW);    //Green LED On
        door_open();
    }
}
 
//Locker Control
BLYNK_WRITE(V3)
{
    buzzer_beep();
    //Close Lock
    if (param.asInt())    //HIGH
    {
        door_close();
        locker_lock();
    }
    //Unlock Open
    else        //LOW
    {
        locker_unlock();
        door_open();
    }
}
 
//Read to RFID uid
char readRFID_UID()
{
    if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial())
    {
        return UNTAP;
    }
    buzzer_beep();
 
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
 
    strID = "";
    for (byte i = 0; i < 4; i++) {
        strID +=
            (mfrc522.uid.uidByte[i] < 0x10 ? "0" : ""+
            String(mfrc522.uid.uidByte[i], HEX) +
            (i != 3 ? ":" : "");
    }
    strID.toUpperCase();
 
    Serial.print("Tap card key: ");
    Serial.println(strID);
 
    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
 
    for (int i = 0; i < idQty; i++)
    {
        if (strID.equals(registeredID[i]))
        {
            Serial.println("Registered Card");
            return REGIT;
        }
        if (i == idQty - 1)
        {
            Serial.println("Unregistered Card");
            return UNREGIT;
        }
    }
}
 
// Buzzer Sound
void buzzer_beep()
{
    digitalWrite(BUZZER_PIN, LOW);
    delay(200);
    digitalWrite(BUZZER_PIN, HIGH);
}
// Warning
void buzzer_beep_beep()
{
    buzzer_beep();
    delay(500);
    buzzer_beep();
    delay(500);
    buzzer_beep();
    delay(500);
    buzzer_beep();
    delay(500);
}
 
 
// Servo initiaize
void servo_init(int door_sel, int pin)
{
    door_servo[door_sel].attach(pin);
 
    if (door_sel == DOOR_LOCK)
    {
        locker_unlock();
        flag_locker_open_state = OPEN;  // Set doorlock state
    }
    else
    {
        door_close();
        flag_door_open_state = CLOSE;  // Set door state
        locker_lock();
        flag_locker_open_state = CLOSE;
    }
}
 
// Function for door open
void door_open(void)
{
    if (flag_locker_open_state == OPEN)  // check doorlock state
    {
        if (flag_door_open_state == CLOSE)  // check door state
        {
            control_servo(AUTO_DOOR, OPEN, DOOR_OPEN_START, DOOR_OPEN_STOP);
            flag_door_open_state = OPEN;
            lcd.clear();    //blink
            lcd.print(10"IoT Door Lock!");    //blynk
            lcd.print(11"Open the Door!");    //blynk
        }
        else if (flag_door_open_state == OPEN)
        {
            lcd.clear();    //blink
            lcd.print(10"Already opend!");    //blynk
            lcd.print(01"Check your door!");    //blynk
        }
 
    }
    else if (flag_locker_open_state == CLOSE)
    {
        lcd.clear();    //blynk
        lcd.print(10"Locker is closed!");    //blynk
        lcd.print(01"Can't open door!");    //blynk
    }
}
 
// Function for door close
void door_close(void)
{
    if ((flag_locker_open_state == OPEN))
    {
        if (flag_door_open_state == OPEN)
        {
            control_servo(AUTO_DOOR, CLOSE, DOOR_CLOSE_START, DOOR_CLOSE_STOP);
            flag_door_open_state = CLOSE;
            lcd.clear();    //blynk
            lcd.print(10"IoT Door Lock!");    //blynk
            lcd.print(01"Close the Door!");    //blynk
        }
        else if (flag_door_open_state == CLOSE)
        {
            lcd.clear();    //blynk
            lcd.print(10"Already closed!");    //blynk
            lcd.print(01"Check your door!");    //blynk
        }
    }
    else if (flag_locker_open_state == CLOSE)
    {
        lcd.clear();    //blink
        lcd.print(10"Locker is closed!");    //blynk
        lcd.print(01"Can't close door!");    //bliynk
    }
}
 
// Function for doorlock unlock
void locker_unlock(void)
{
    if ((flag_locker_open_state == CLOSE))
    {
        control_servo(DOOR_LOCK, OPEN, DOOR_LOCK_OPEN_START, DOOR_LOCK_OPEN_STOP);
        flag_locker_open_state = OPEN;
        lcd.clear();    //blink
        lcd.print(10"IoT Door Lock!");    //blynk
        lcd.print(01"Unlock the Door!");    //blynk
    }
    else if ((flag_locker_open_state == OPEN))
    {
        lcd.clear();    //blynk
        lcd.print(10"Already opened!");    //blynk
        lcd.print(01"Check your locker!");    //blynk
    }
}
 
// Function for doorlock lock
void locker_lock(void)
{
    if ((flag_locker_open_state == OPEN))
    {
        control_servo(DOOR_LOCK, CLOSE, DOOR_LOCK_CLOSE_START, DOOR_LOCK_CLOSE_STOP);
        flag_locker_open_state = CLOSE;
        lcd.clear();    //blink
        lcd.print(10"IoT Door Lock!");    //blynk
        lcd.print(01"Lock the Door!");    //blynk
    }
    else if ((flag_locker_open_state == CLOSE))
    {
        lcd.clear();    //blynk
        lcd.print(10"Already closed!");    //blynk
        lcd.print(01"Check your locker!");    //blynk
    }
}
 
// Function for control servo angle
void control_servo(int door_sel, int dir, int st, int ed)
{
    if (dir == OPEN)
    {
        for (pos = st; pos >= ed; pos--)     // goes from 180 degrees to 0 degrees 
        {
            door_servo[door_sel].write(pos);              // tell servo to go to position in variable 'pos'
            delay(20);                       // wait for the servo to reach the position (20ms period)
        }
    }
    else
    {
        for (pos = st; pos <= ed; pos++)     // goes from 0 degrees to 180 degrees 
        {
            door_servo[door_sel].write(pos);              // tell servo to go to position in variable 'pos' 
            delay(20);                       // wait for the servo to reach the position (20ms period)
        }
    }
}
cs


동작 영상


저작자 표시 비영리 변경 금지
신고
  1. 2017.03.27 17:31 신고

    저 앱을 통해서 원거리 제어도 가능한가요?

    • Scott Jeong 2017.04.03 11:02 신고

      네 당연히 가능합니다. 별도의 네트워크 설정없이 가능합니다.

  2. khard 2017.05.01 17:05 신고

    제가 하려고 하는 프로젝트와 Blynk앱과의 연동 외에 유사점이 많아서 질문드립니다.
    blynk앱과의 연계되는 부분의 소스코드만 빼고 RFID와 서보 소스코드만 묶으려면 글쓴이님께서 제공해주신 소스코드 부분을 어떻게 편집하면 되나요??

  3. dinieloh 2017.09.13 08:51 신고

    위에 회로에서 이더넷 모듈이 안보이는데 혹시 회로에 이더넷 모듈도 넣어서 수정해 주실수 있나요?

+ Recent posts