현관문에 모니터를 만들어 보자

by 하민정 | 2017-01-04 16:17
gsm iot monitor 모니터 스마트홈 아두이노 알림 프로토쉴드 현관문

재료

  • 아두이노 GSM 쉴드 V2 1개
  • 아두이노 프로토 쉴드 1개
  • 아두이노 우노 1개
  • 점퍼 와이어 1개


이 프로젝트를 통해서는 최대 두 개의 현관 문을 LCD 화면을 통해서 모니터 및 관리 할 수 있습니다. 

또한 문이 열림의 상태에서 '완전히 열려지지 않았거나' 혹은 '너무 오랫동안 문이 열려진 경우'

작동 이상으로 간주되어 알람이 울리게 됩니다.이 알람은 SMS를 통해서도 전달 받을 수 있습니다.


보안상의 이유로 하나의 핸드폰만 사용하는 것으로 이 프로젝트를 진행했고,

핸드폰을 이용해서도 문을 열거나 닫을 수 있습니다. 


cf > 문의 상태를 확인하기 위해서 프로젝트에서 문과 가까운 곳에 '자기장 스위치'를 두어 사용하지만, 이것은 사용자에 따라 '마이크로 스위치'로 변경하여 사용하여도 무방합니다. 




- 프로토 쉴드가 브래드 보드를 대신해서 위와 같이 사용이 됩니다.

아두이노 우노, GSM 쉴드, 그리고 프로토 쉴드를 사용해 위와 같이 만들 수 있습니다. 




- LCD 스크린은 문이 열려져 있는지 닫혀져 있는지에 대한 상태를 확인할 수 있습니다.

문이 열리면 그 때부터 문이 열려진 시간 만큼을 측정하여 얼마동안 현관문이 열려져 있었는지 또한

확인할 수 있습니다. 


                                        


                                        - 문을 제어하기 위해서 릴레이 모듈을 사용합니다. 


                                         


                                      -  LCD에 시간을 표시하기 위해서 I2C 클럭 모듈을 사용합니다. 




- 프로토쉴드의 윗 부분은 위와같이 구성합니다. 




- 프로토 쉴드의 아랫부분은 위와 같이 구성합니다. 


Step 1. 준비물 


- 아두이노 우노 

- 아두이노 GSM 쉴드 V2 

- 아두이노 프로토 쉴드 

- 점퍼 와이어 


Step 2. 하드웨어 연결 방법 



1) 아두이노의 디지털 2번 핀과 3번 핀에 GSM 쉴드를 연결합니다.

2) 문을 닫기 위한 핀은 8번과 9번에 연결합니다.

3) 1번 문의 Upper sensor와 Lower sensor는 (A0, D14) , ( A1, D15) 에 연결,

4) 2번 문의 Upper sensor와 Lower sensor 는 ( A2, D16), (A3, D17) 에 연결합니다.

5) rtc 클럭은 (A4, D18) 와 ( A5, D16) 에 연결합니다. 


Step 3. 코드 


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
//Library for LCD
#include <LiquidCrystal_I2C.h>
//Library for Clock
#include <Wire.h>
#include "RTClib.h"
//Library for GSM
#include <SoftwareSerial.h>
#include <SerialGSM.h>
DS1307 rtc;
SerialGSM cell(2,3);
// initialize the library with the i2c adress and chars and lines
LiquidCrystal_I2C lcd(0x3F,20,4);
const byte Doors = 2;//number of doors to manage
const byte Lines = 2;//number of lines on the lcd
const byte Chars = 16;//number of characters on the lcd
const long int ClosingTrigger = 60000;//time before an alarm is triggered
const long int ClosingTime = 20000;//time needed to close the door !!Measure this time for your door!!
static const uint8_t PinsIn[] = {14,15,16,17};//Array of pins used to minitor the doors
static const uint8_t PinsOut[] = {8,9};//Array of pins used to control the doors
char GSMNum[13]="+XXXXXXXXXXX";  // telephone number to send sms
String ValidAction;//used to check if incomming sms is valid
String PrevMessage01;//used to move the LCD message one line
String PrevMessage02;//used to move the LCD message one line
String PrevMessage03;//used to move the LCD message one line
byte PrevLine = 1; //previous used line on the LCD
byte UpperSensor[Doors];
byte PrevUpperSensor[Doors];
byte LowerSensor[Doors];
byte PrevLowerSensor[Doors];
char DoorState[Doors];//M=movement, O=open, C=Closed
byte x=0;//for loop trough number of doors. We start at 0 because list numbering starts at 0
byte DoorToActivate;//door that has to be activated extracted from SMS
long int StartMillis[Doors];//remember the starttime of the not closed timer
bool TimerStarted[Doors];//remember if the not closed timer has been started for a given door
bool SMSsend[Doors];//remember if a SMS has been send
 
cs


총 5개의 라이브러리를 참조합니다.

먼저, LCD를 제어하기 위한 라이브러리로 <LiquidCrystal_I2C.h> 라이브러리를 

시간 측정을 위해 <Wire.h> 그리고 <RTClib.h> 

GSM 쉴드를 사용하기 위해서 <SoftwareSerial.h> 그리고 <SerialGSM.h> 라이브러리를

참조합니다. 


LiquidCrystal_I2C 라이브러리를 우리가 사용하고자 하는 목적으로 초기화 시키기 위해서

I2C 의 주소와 우리가 사용할 글자 수 그리고 줄 수를 이용해 초기화 시켜줍니다. 


1
2
// initialize the library with the i2c adress and chars and lines
LiquidCrystal_I2C lcd(0x3F,20,4);
cs


cf>  편의를 위하여 각각을 상수화 시켜서 사용합니다 

: 시간을 측정하기 위해 사용하는 I2C DS1307은 < rtc > 라는 변수

  관리할 현관 문의 수<Doors>

  LCD에 보여져야 할 라인의 수 <Lines>

  LCD에 보여져야 할 글자 수 <Chars>

  현관 문이 열렸을 때 부터 시작해서 '얼마동안 열려져 있는지'를 측정하기 위해서 StartMillis 라는 변    수명으로 각각의 문이 열린 시간을 기록해 놓습니다.

  만약 문이 닫혀지지 않는다면 <TimerStarted> 라는 변수에 '문이 열렸던 시간'을 저장해 놓습니다.

  사용자의 sms로 알람이 보내졌다면 <SMSsend>에 기록이 됩니다


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
void setup() {
//start LCD
lcd.init();
lcd.backlight();
// Print a message to the LCD.
lcdmessage("LCD Booted", 1);
// init clock
  Wire.begin();
  rtc.begin();
 
if (! rtc.isrunning()) {
lcdmessage("RTC is NOT running!", 1);
// following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
 
//loop trough the inputs. 2 inputs for each door
  for(byte y=0;y<2*Doors;y++)
  {
   pinMode(PinsIn[y],INPUT);
  }
//loop trough the outputs. 1 output for each door
//reset timers voor each door
 for(byte y=0;y<Doors;y++)
 {
   pinMode(PinsOut[y],OUTPUT);
//In order to work with a relay module HIGH is Normal Open   
   digitalWrite(PinsOut[y], HIGH);
   StartMillis[y]=0;
   TimerStarted[y]=0;
   SMSsend[y]=0;
 }
Serial.begin(9600);
 
//setup GSM shield  
cell.begin(9600);
//for debug  cell.Verbose(true);
lcdmessage("Booting GSM", 1);
cell.Boot(); 
cell.FwdSMS2Serial();
cell.DeleteAllSMS();
lcdmessage("GSM Booted", 1);
}
 
cs


LiquidCrystal_I2C 라는 라이브러리의 내장 함수를 통해서 LCD를 초기화 시킵니다.

이때 시간을 측정하는 모듈인 rtc도 RTClib.h 라이브러리의 내장 함수를 통해서 초기화 시킵니다.


만약 rtc가 작동하지 못한다면, 수행하지 않고 수행 에러 <RTC is NOT running> 가 표시됩니다.

GSM 쉴드 역시 같이 초기화를 진행하는데, 이때 제대로 수행 되었다면 <Booting GSM>가 표시됩니다. 


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
void loop() {
  if (x < Doors)
    { 
//check uppersensors and compare to previous state
      PrevUpperSensor[x] = UpperSensor[x];
      UpperSensor[x] = digitalRead(PinsIn[(2*x)]);
      if (!(PrevUpperSensor[x] == UpperSensor[x]))
        {
          MakeMessage(x, 'U');
        }
//check lowersensors and compare to previous state
      PrevLowerSensor[x] = LowerSensor[x];
      LowerSensor[x] = digitalRead(PinsIn[(2*x)+1]);
      if (!(PrevLowerSensor[x] == LowerSensor[x]))
        {
          MakeMessage(x, 'L');
        }
//Start timer if door not closed else reset timers
      if (!(DoorState[x] == 'C'))
        {
          CheckTimer(x);
        }
       else
        {
          TimerStarted[x] = 0;
          StartMillis[x]=0;
          SMSsend[x]=0;
        }
      x= x+1;
    }
  else
    {
      x=0;//reset doornumber in order to restart the checking cycle
    }
//process incomming SMS messages
  if (cell.ReceiveSMS())
    {
//check if number is valid
      String SMSSender=cell.Sender();
      SMSSender.remove(12);
      String ValidSender=GSMNum;        
        if (SMSSender == ValidSender)
          {
//retrieve DoorToActivate from SMSMessage
      String SMSMessage=cell.Message();
            lcdmessage(SMSMessage, 1);
            SMSMessage.remove(1);
            DoorToActivate=SMSMessage.toInt();
            
            switch (DoorState[DoorToActivate-1])
              {
                case 'C':
                  ValidAction="Open";
                break;
                
                case 'O':
                  ValidAction="Close";
                break;
              }
            
            SMSMessage=cell.Message();
            SMSMessage.substring(2);
            if (SMSMessage.substring(2) == ValidAction)
            {
              ActivateDoor(DoorToActivate);
            }
            else
            {
              lcdmessage("No Valid action", 10);
            }
//delete all SMS messages
            cell.DeleteAllSMS();
            SMSsend[DoorToActivate-1]=0;
          }
        else
          {
            lcdmessage("Wrong number", 10);
          }
   } 
}
 
cs


처음 설정을 setup 에서 마친 뒤,

반복적으로 문의 열고 닫힘을 감지하기 위해서 이를 loop 문에서 대기하게 됩니다.


⓵ 1번 문과 2번 문을 반복적으로 확인하면서 감지하는데,

각 문 당 uppser sensor와 lower sensor 두 개를 검사하면서 각 문의 열고 닫힘을 감지하게 됩니다.

문 하나의 upper sensor와 lower sensor가 모두 'U' 이거나 모두 'L'일때 '열림' 과 '닫힘'을

LCD에  'C' 와 'D' 로 표시하게 됩니다. 


⓶ 문이 닫히지 않은 경우엔 'C'라는 글자로 표현하여 표시되고,

만약 열린 상태라면 CheckTimer 라는 함수를 통해 계속해서 시간이 측정되게 되고,

닫히게 된다면, TimerStarted 변수와 StartMillis 라는 변수가 모두 초기화 되어 문의 열림을 측정한 값들이 모두 초기화(=0) 됩니다. 


⓷ 휴대폰을 하나 설정하여 그 핸드폰을 통해서 문의 열고 닫힘을 감지하기 위한 기능을 수행합니다.

먼저, SMS가 도착했다면, 이것이 우리가 검토해야 할 유효한 번호인지 아닌지를 먼저 검사한 뒤,

유효하다면 그 다음에 요청한 일을 수행하도록 합니다.


⓸ 'C'라면 문의 열림 기능을 수행하도록 하고, 'D' 라면 문의 닫힘 기능을 수행하도록 합니다. 


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
void MakeMessage(byte door, char location)
{
  String message = "D";
  message.concat(door+1);
  switch (location)
  {
    case 'U':
      if (PrevUpperSensor[door] < UpperSensor[door])
        {
          message.concat(" = O ");
          DoorState[door]='O';
        }
      else
        {
          message.concat(" > C ");
          DoorState[door]='M';
        }
      break;
    
    case 'L':
      if (PrevLowerSensor[door] < LowerSensor[door])
        {
          message.concat(" = C ");
          DoorState[door]='C';
        }
      else
        {
          message.concat(" > O ");
          DoorState[door]='M';
        }
      break;
  }
  DateTime now = rtc.now();
  char buf[100];
  strncpy(buf,"hh:mm:ss\0",100);
  message.concat(now.format(buf));
  lcdmessage(message, 1);
}
 
cs


이 함수는 사용자의 SMS를 통해서 문의 열고 닫힘을 진행하는데 있어서

'열림->닫힘' 이 되는 경우나 '닫힘->열림' 이 되는 경우와 같이 상태가 바뀌어야 하는 경우

수행 해야 할 기능을 진행 하는 함수입니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CheckTimer(byte door)
{
   if (TimerStarted[door] == 0)
     {
         TimerStarted[door]=1;
         StartMillis[door]=millis();
     }
   else
     {
         if ((millis()-StartMillis[door] > ClosingTrigger) && (SMSsend[door] == 0))
           {
             Warning(door);
// Wait till door normally should be closed
             delay (ClosingTime);
           }
      }
}
 
cs


이 함수에서 문이 열리기 시작해서 ~ 사용자의 휴대폰으로 알림이 되기까지 기능을 수행하게 됩니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
void Warning(byte door)
{
//create the message
  char txtMsg[100];
  String SMSMessage = "Door ";
  SMSMessage.concat(door+1);
  SMSMessage.concat(" is not closed.");
  SMSMessage.toCharArray(txtMsg,100);
//send the message
  sendSMS(GSMNum, txtMsg);
  SMSsend[door]=1;
}
 
cs


Warning 함수에서 메시지를 생성하고 이것을 SMS로 보내기 위한 기능을 수행합니다.

문이 제대로 닫히지 않은 경우엔 <Door is not closed> 라는 메시지가 SMS로 전송이 되게 됩니다. 


1
2
3
4
5
6
7
8
9
10
11
12
void ActivateDoor(byte door)
{
    Serial.print("Digital out to low : ");
    Serial.println(PinsOut[door-1]);
    String Message = "Activate D";
    Message.concat(door);
    lcdmessage(Message, 1);
    digitalWrite(PinsOut[door-1], LOW);
    delay(2000);
    digitalWrite(PinsOut[door-1], HIGH);
}
 
cs


ActivateDoor 함수는 문의 열림과 닫힘을 수행시키기 위한 함수로,

HIGH 상태인 경우엔 작동하지 않지만, LOW 상태로 되면 문이 작동하게 됩니다. 


다음은 전체 코드 입니다. 

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
/*
Pin configuration
D0
D1
D2      GSM
D3      GSM
D4      
D5      
D6      
D7      
D8      close door1
D9      close door2
D10
D11     
D12     
D13
A0 D14  Upper door1
A1 D15  Lower door1
A2 D16  Upper door2
A3 D17  Lower door2
A4 D18  clock
A5 D19  clock
 
*/
//Library for LCD
#include <LiquidCrystal_I2C.h>
//Library for Clock
#include <Wire.h>
#include "RTClib.h"
//Library for GSM
#include <SoftwareSerial.h>
#include <SerialGSM.h>
 
DS1307 rtc;
 
SerialGSM cell(2,3);
 
// initialize the library with the i2c adress and chars and lines
LiquidCrystal_I2C lcd(0x3F,20,4);
 
const byte Doors = 2;//number of doors to manage
const byte Lines = 2;//number of lines on the lcd
const byte Chars = 16;//number of characters on the lcd
const long int ClosingTrigger = 60000;//time before an alarm is triggered
const long int ClosingTime = 20000;//time needed to close the door !!Measure this time for your door!!
static const uint8_t PinsIn[] = {14,15,16,17};//Array of pins used to minitor the doors
static const uint8_t PinsOut[] = {8,9};//Array of pins used to control the doors
char GSMNum[13]="+XXXXXXXXXXX";  // telephone number to send sms
String ValidAction;//used to check if incomming sms is valid
String PrevMessage01;//used to move the LCD message one line
String PrevMessage02;//used to move the LCD message one line
String PrevMessage03;//used to move the LCD message one line
byte PrevLine = 1; //previous used line on the LCD
byte UpperSensor[Doors];
byte PrevUpperSensor[Doors];
byte LowerSensor[Doors];
byte PrevLowerSensor[Doors];
char DoorState[Doors];//M=movement, O=open, C=Closed
byte x=0;//for loop trough number of doors. We start at 0 because list numbering starts at 0
byte DoorToActivate;//door that has to be activated extracted from SMS
long int StartMillis[Doors];//remember the starttime of the not closed timer
bool TimerStarted[Doors];//remember if the not closed timer has been started for a given door
bool SMSsend[Doors];//remember if a SMS has been send
 
 
void setup() {
//start LCD
lcd.init();
lcd.backlight();
// Print a message to the LCD.
lcdmessage("LCD Booted", 1);
// init clock
  Wire.begin();
  rtc.begin();
 
if (! rtc.isrunning()) {
lcdmessage("RTC is NOT running!", 1);
// following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
 
//loop trough the inputs. 2 inputs for each door
  for(byte y=0;y<2*Doors;y++)
  {
   pinMode(PinsIn[y],INPUT);
  }
//loop trough the outputs. 1 output for each door
//reset timers voor each door
 for(byte y=0;y<Doors;y++)
 {
   pinMode(PinsOut[y],OUTPUT);
//In order to work with a relay module HIGH is Normal Open   
   digitalWrite(PinsOut[y], HIGH);
   StartMillis[y]=0;
   TimerStarted[y]=0;
   SMSsend[y]=0;
 }
Serial.begin(9600);
 
//setup GSM shield  
cell.begin(9600);
//for debug  cell.Verbose(true);
lcdmessage("Booting GSM", 1);
cell.Boot(); 
cell.FwdSMS2Serial();
cell.DeleteAllSMS();
lcdmessage("GSM Booted", 1);
}
 
void loop() {
  if (x < Doors)
    { 
//check uppersensors and compare to previous state
      PrevUpperSensor[x] = UpperSensor[x];
      UpperSensor[x] = digitalRead(PinsIn[(2*x)]);
      if (!(PrevUpperSensor[x] == UpperSensor[x]))
        {
          MakeMessage(x, 'U');
        }
//check lowersensors and compare to previous state
      PrevLowerSensor[x] = LowerSensor[x];
      LowerSensor[x] = digitalRead(PinsIn[(2*x)+1]);
      if (!(PrevLowerSensor[x] == LowerSensor[x]))
        {
          MakeMessage(x, 'L');
        }
//Start timer if door not closed else reset timers
      if (!(DoorState[x] == 'C'))
        {
          CheckTimer(x);
        }
       else
        {
          TimerStarted[x] = 0;
          StartMillis[x]=0;
          SMSsend[x]=0;
        }
      x= x+1;
    }
  else
    {
      x=0;//reset doornumber in order to restart the checking cycle
    }
//process incomming SMS messages
  if (cell.ReceiveSMS())
    {
//check if number is valid
      String SMSSender=cell.Sender();
      SMSSender.remove(12);
      String ValidSender=GSMNum;        
        if (SMSSender == ValidSender)
          {
//retrieve DoorToActivate from SMSMessage
      String SMSMessage=cell.Message();
            lcdmessage(SMSMessage, 1);
            SMSMessage.remove(1);
            DoorToActivate=SMSMessage.toInt();
            
            switch (DoorState[DoorToActivate-1])
              {
                case 'C':
                  ValidAction="Open";
                break;
                
                case 'O':
                  ValidAction="Close";
                break;
              }
            
            SMSMessage=cell.Message();
            SMSMessage.substring(2);
            if (SMSMessage.substring(2) == ValidAction)
            {
              ActivateDoor(DoorToActivate);
            }
            else
            {
              lcdmessage("No Valid action", 10);
            }
//delete all SMS messages
            cell.DeleteAllSMS();
            SMSsend[DoorToActivate-1]=0;
          }
        else
          {
            lcdmessage("Wrong number", 10);
          }
   } 
}
 
//make message for logging if doorstate has changed.
void MakeMessage(byte door, char location)
{
  String message = "D";
  message.concat(door+1);
  switch (location)
  {
    case 'U':
      if (PrevUpperSensor[door] < UpperSensor[door])
        {
          message.concat(" = O ");
          DoorState[door]='O';
        }
      else
        {
          message.concat(" > C ");
          DoorState[door]='M';
        }
      break;
    
    case 'L':
      if (PrevLowerSensor[door] < LowerSensor[door])
        {
          message.concat(" = C ");
          DoorState[door]='C';
        }
      else
        {
          message.concat(" > O ");
          DoorState[door]='M';
        }
      break;
  }
  DateTime now = rtc.now();
  char buf[100];
  strncpy(buf,"hh:mm:ss\0",100);
  message.concat(now.format(buf));
  lcdmessage(message, 1);
}
 
//Check if timer has started for a door and if trigger has been reached, then send SMS
void CheckTimer(byte door)
{
   if (TimerStarted[door] == 0)
     {
         TimerStarted[door]=1;
         StartMillis[door]=millis();
     }
   else
     {
         if ((millis()-StartMillis[door] > ClosingTrigger) && (SMSsend[door] == 0))
           {
             Warning(door);
// Wait till door normally should be closed
             delay (ClosingTime);
           }
      }
}
 
//Creates a message and sends it by SMS
void Warning(byte door)
{
//create the message
  char txtMsg[100];
  String SMSMessage = "Door ";
  SMSMessage.concat(door+1);
  SMSMessage.concat(" is not closed.");
  SMSMessage.toCharArray(txtMsg,100);
//send the message
  sendSMS(GSMNum, txtMsg);
  SMSsend[door]=1;
}
 
//Sends a SMS message to a number
void sendSMS(char num[13], char msg[100])
{
  cell.DeleteAllSMS();
  cell.Rcpt(num);
  lcdmessage(msg, 1);
  cell.Message(msg);
  cell.SendSMS();
}
 
//Activate a door in order to close or open. Action is always the same.
//HIGH is normal mode LOW is activated state
void ActivateDoor(byte door)
{
    Serial.print("Digital out to low : ");
    Serial.println(PinsOut[door-1]);
    String Message = "Activate D";
    Message.concat(door);
    lcdmessage(Message, 1);
    digitalWrite(PinsOut[door-1], LOW);
    delay(2000);
    digitalWrite(PinsOut[door-1], HIGH);
}
 
//shows a message on the LCD screen
void lcdmessage(String message, byte visible)
{
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print(PrevMessage03);
 lcd.setCursor(0,1);
 lcd.print(PrevMessage02);
 lcd.setCursor(0,2);
 lcd.print(PrevMessage01);
 lcd.setCursor(0,3);
 lcd.print(message);
 PrevMessage03 = PrevMessage02;
 PrevMessage02 = PrevMessage01;
 PrevMessage01 = message;
 delay(visible*1000);  
}
 
cs


댓글 1

MADE BY