다목적 기능의 만능시계 만들기

by 하민정 | 2017-01-03 18:51
iot 디지털시계 만능시계 스마트홈 아두이노 알람기능 타이머설정 하드웨어

재료

  • Real Time Clock (RTC) DS3231 1개
  • 분압계 1개
  • 점퍼케이블 (Male- Male), (Female-Female) 1개
  • Liquid Crystal Display 1602 1개
  • 저항 220옴 1개
  • 아두이노 우노 1개
  • 버저 1개
  • 버튼 4개

디지털 시계 이자, 온도측정도 가능하며, 알람 그리고 타이머의 기능까지 갖춘 '만능 시계'를 아두이노를 통해서 만들어 보자. 


Step 1. 준비물  


- 아두이노 우노 

- Real Time Clock ( RTC ) DS3231 

- Liquid Crystal Display 1602 

- 버저 

- 분압계 ( LCD 제어를 위함 ) 

- 저항 220옴 

- 점퍼케이블 ( Male-Male ) , ( Male-Female) 

- 버튼 4개 


첫번째 버튼을 통해서 Down 기능, 두번째 버튼을 통해서 Up 기능, 세번째 버튼을 통해서 타이머를 설정할 수 있고, 네번째 버튼을 통해서 알람을 설정할 수 있습니다. 



Step2. 하드웨어 연결방법 ( 회로도 ) 


4개의 버튼을 이용하게 됩니다. 버튼은 아두이노의 7번 핀에서 10번 핀까지에 연결시켜줍니다. LCD는 아두이노의 2번 핀에서 5번 핀까지에 연결시켜줍니다. LCD를 제어하기 위해, 분압계 역시 아두이노에 연결시켜줍니다. 



 Step3. 코드 


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
//다음의 라이브러리를 사용한다.
//크리스탈 LCD를 사용하기 위해 LiquidCrystal.h 의 라이브러리를 사용한다.
//실제로 Real Time Clock 를 제어하는 것은 아두이노에서 상당히 까다로우므로,
//DS3231.h 라는 라이브러리를 이용해 쉽게 이용할 수 있다.
#include <LiquidCrystal.h>      //  
#include <Button.h>             //  
#include <DS3231.h>             //  RTC
 
//buzzer 는 13번 핀에 연결한다.
int buzzer = 13;                                                //set  .   13
uint8_t hh = 0, mm = 0, ss = 0;                                 //set  ,, RTC
uint8_t timerMode = 0 ,setMode=0, setAlarm=0, alarmMode=0 ;     //set    
uint8_t alarmHH =0 ,alarmMM =0 ,alarmSS=0;                      //   
uint8_t timerhh=0, timermm=0, timerss =0;                       //   
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);                          // LCD 
DS3231 rtc(SDA,SCL);                                            // RTC
Time t;                                                         //    t
 
//다운 핀은 7번으로, 업 핀은 8번으로, 설정 핀은 9번, 알람 기능의 핀은 10번으로
//연결해 준다.
#define DN_PIN 7                                                  //set  pin
#define UP_PIN 8                                                  //set  pin
#define SET_PIN 9                                                 //set  
#define ALR_PIN 10                                                //set   
#define PULLUP true                                               //aktifkan  
#define INVERT true                                               //If invert ==true,HIGH=released,LOW=pressed
#define DEBOUNCE_MS 20                                            //state  react with button
#define REPEAT_FIRST 500                                          //state  untuk tekan berapa lama button
#define REPEAT_INCR 100                                           // increase kan number
 
//Declare push buttons
//버튼에 대한 설정은 button.h 의 라이브러리의 내장함수를 이용하여준다.
Button btnDN(DN_PIN, PULLUP, INVERT, DEBOUNCE_MS);                //set 1st button utk decrement
Button btnUP(UP_PIN, PULLUP, INVERT, DEBOUNCE_MS);                //set 2nd button utk increment
Button btnSET(SET_PIN, PULLUP, INVERT, DEBOUNCE_MS);              //set button utk function timer
Button btnALR(ALR_PIN, PULLUP, INVERT, DEBOUNCE_MS);              //set button utk function alarm
 
enum {WAIT, INCR, DECR};                                          //The possible states for the state machine
uint8_t STATE;                                                    //The current state machine state
int count;                                                        //The number that is adjusted
int lastCount = -1;                                               //Previous value of count (initialized to ensure it's different when the sketch starts)
unsigned long rpt = REPEAT_FIRST;                                 //A variable time that is used to drive the repeats for long presses
 
 
 
void setup() {
  
Serial.begin(9600);
lcd.begin(16,2);
pinMode(buzzer,OUTPUT);
rtc.begin();
lcd.setCursor(0,0);
lcd.print("Welcome Shaqib!");
delay(2000);
lcd.clear();
//rtc.setTime(12,24,00);
 
}
 
void loop() {
 
t=rtc.getTime();
hh=t.hour,DEC;
mm=t.min,DEC;
ss=t.sec,DEC;
 
btnSET.read();
btnUP.read();                             
btnDN.read();
btnALR.read();
 
if(setMode==0 && setAlarm==0 ){
tunjukJamTemp();
tunjukTimer();}
 
if(setMode!=0 && setAlarm==0 && alarmMode==0 ){delay(100);}
if(setMode==1 && setAlarm==0 && alarmMode==0 ){lcd.setCursor(7,1);lcd.print("  ");delay(100);tunjukJamTemp();tunjukTimer();}
if(setMode==2 && setAlarm==0 && alarmMode==0 ){lcd.setCursor(10,1);lcd.print("  ");delay(100);tunjukJamTemp();tunjukTimer();}
if(setMode==3 && setAlarm==0 && alarmMode==0 ){lcd.setCursor(13,1);lcd.print("  ");delay(100);tunjukJamTemp();tunjukTimer();}
if(setMode==4 && setAlarm==0 && alarmMode==0 ){tunjukJamTemp();tunjukTimer();stepDown();delay(1000);}
 
 
 
if(setMode==0 && setAlarm!=0 && alarmMode==0 ){delay(100);}
if(setMode==0 && setAlarm==2 && alarmMode==0 ){lcd.setCursor(0,0);lcd.print("  ");delay(100);    lcd.setCursor(0,0);
    if(alarmHH<10){lcd.print("0");}
    lcd.print(alarmHH);lcd.print(":");
    if(alarmMM<10){lcd.print("0");}
    lcd.print(alarmMM);lcd.print(":");
    if(alarmSS<10){lcd.print("0");}
    lcd.print(alarmSS);lcd.setCursor(0,1);
    lcd.print("Set Your Alarm");}
if(setMode==0 && setAlarm==3 && alarmMode==0 ){lcd.setCursor(3,0);lcd.print("  ");delay(100);    lcd.setCursor(0,0);
    if(alarmHH<10){lcd.print("0");}
    lcd.print(alarmHH);lcd.print(":");
    if(alarmMM<10){lcd.print("0");}
    lcd.print(alarmMM);lcd.print(":");
    if(alarmSS<10){lcd.print("0");}
    lcd.print(alarmSS);lcd.setCursor(0,1);
    lcd.print("Set Your Alarm");}
if(setMode==0 && setAlarm==4 && alarmMode==0 ){lcd.setCursor(6,0);lcd.print("  ");delay(100);    lcd.setCursor(0,0);
    if(alarmHH<10){lcd.print("0");}
    lcd.print(alarmHH);lcd.print(":");
    if(alarmMM<10){lcd.print("0");}
    lcd.print(alarmMM);lcd.print(":");
    if(alarmSS<10){lcd.print("0");}
    lcd.print(alarmSS);lcd.setCursor(0,1);
    lcd.print("Set Your Alarm");}
if(setMode==0 && setAlarm==5 && alarmMode==0 ){alarmMode=1;setAlarm=0;}
 
setupAlarm();
Alarm(alarmHH,alarmMM);
 
btnSET.read();
btnUP.read();                             
btnDN.read();
btnALR.read();

//출력을 현재의 상태에 따라서 다르게 해 준다.
//wait 라는 상태의 경우 설정 버튼이 눌린 경우, 알람 버튼이 눌린 경우, 다운
//버튼이 눌린 경우, 그리고 업 버튼이 눌린 경우 이러한 경우에 수행하도록 만든다.
//wait 이외에도 시계의 타이머를 증가시켜야 하는 경우, 감소시켜야 하는 경우를
//각각 나누어 상황에 따라 시계가 작동할 수 있도록 제시해 주었다.
switch (STATE) {
        
        case WAIT:                            
            if (btnSET.wasPressed())
               { setMode = setMode+1;}
            if (btnALR.wasPressed())
               { setAlarm = setAlarm+1;} 
            if (btnUP.wasPressed())
                STATE = INCR;
            else if (btnDN.wasPressed())
                STATE = DECR;
            else if (btnUP.wasReleased())    
                rpt = REPEAT_FIRST;
            else if (btnDN.wasReleased())
                rpt = REPEAT_FIRST;
            else if (btnUP.pressedFor(rpt)) {  
                rpt += REPEAT_INCR;            
                STATE = INCR;
            }
            else if (btnDN.pressedFor(rpt)) {
                rpt += REPEAT_INCR;
                STATE = DECR;
            }
            break;
 
        case INCR:                               
            if (setMode==1 && setAlarm==0 && alarmMode==0 && timerhh<23)timerhh=timerhh+1; 
            if (setMode==2 && setAlarm==0 && alarmMode==0 && timermm<59)timermm=timermm+1;
            if (setMode==3 && setAlarm==0 && alarmMode==0 && timerss<59)timerss=timerss+1;
            if (setMode==0 && setAlarm==2 && alarmMode==0 && alarmHH<23)alarmHH=alarmHH+1;
            if (setMode==0 && setAlarm==3 && alarmMode==0 && alarmMM<59)alarmMM=alarmMM+1;
            if (setMode==0 && setAlarm==4 && alarmMode==0 && alarmSS<59)alarmSS=alarmSS+1;
            STATE = WAIT;
            break;
 
        case DECR:                               
            if (setMode==1 && setAlarm==0 && alarmMode==0 && timerhh>0)timerhh=timerhh-1; 
            if (setMode==2 && setAlarm==0 && alarmMode==0 && timermm>0)timermm=timermm-1;
            if (setMode==3 && setAlarm==0 && alarmMode==0 && timerss>0)timerss=timerss-1;
            if (setMode==0 && setAlarm==2 && alarmMode==0 && alarmHH>0)alarmHH=alarmHH-1;
            if (setMode==0 && setAlarm==3 && alarmMode==0 && alarmMM>0)alarmMM=alarmMM-1;
            if (setMode==0 && setAlarm==4 && alarmMode==0 && alarmSS>0)alarmSS=alarmSS-1;
            STATE = WAIT;
            break;
    }
}
 
 void stepDown() {
 if (timerss > 0) {
 timerss -= 1;
 } else {
 if (timermm > 0) {
 timerss = 59;
 timermm -= 1;
 } else {
 if (timerhh > 0) {
 timerss = 59;
 timermm = 59;
 timerhh -= 1;
 } else {
  for(int i=0;i<30;i++){
lcd.setCursor(0,0);
lcd.print(rtc.getTimeStr());
lcd.setCursor(10,0);
lcd.print(rtc.getTemp());
lcd.print("C");
btnSET.read();
if(btnSET.wasPressed()){digitalWrite(buzzer,LOW);i=30;}else{
digitalWrite(buzzer,HIGH);
delay(500);
digitalWrite(buzzer,LOW);
delay(500);}
}
setMode=0;
 
  }
 }
 }
 }
 
void tunjukTimer(){
lcd.setCursor(0, 1);
 lcd.print("Timer:");
 lcd.print(" ");
 (timerhh < 10) ? lcd.print("0") : NULL;
 lcd.print(timerhh);
 lcd.print(":");
 (timermm < 10) ? lcd.print("0") : NULL;
 lcd.print(timermm);
 lcd.print(":");
 (timerss < 10) ? lcd.print("0") : NULL;
 lcd.print(timerss);
   }
 
void tunjukJamTemp(){
  lcd.setCursor(0,0);
lcd.print(rtc.getTimeStr());
lcd.setCursor(10,0);
lcd.print(rtc.getTemp());
lcd.print("C");
 
}
 
void Alarm(uint8_t alarmHH,uint8_t alarmMM){
  if(alarmMode==1 && alarmHH==hh && alarmMM==mm){
   for(int i=0;i<30;i++){
lcd.setCursor(0,0);
lcd.print(rtc.getTimeStr());
lcd.setCursor(10,0);
lcd.print(rtc.getTemp());
lcd.print("C");
lcd.setCursor(0, 1);
 lcd.print("Timer:");
 lcd.print(" ");
 (timerhh < 10) ? lcd.print("0") : NULL;
 lcd.print(timerhh);
 lcd.print(":");
 (timermm < 10) ? lcd.print("0") : NULL;
 lcd.print(timermm);
 lcd.print(":");
 (timerss < 10) ? lcd.print("0") : NULL;
 lcd.print(timerss);
 
btnALR.read();
if(btnALR.wasPressed()){digitalWrite(buzzer,LOW);i=30;}else{
digitalWrite(buzzer,HIGH);
delay(500);
digitalWrite(buzzer,LOW);
delay(500);}
    }
    alarmMode=0;
    setAlarm=0;
  }}
 
void setupAlarm(){
  if(setMode==0 && setAlarm==1 && alarmMode==0 ){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Set Your Alarm");
    lcd.setCursor(0,0);
    if(alarmHH<10){lcd.print("0");}
    lcd.print(alarmHH);lcd.print(":");
    if(alarmMM<10){lcd.print("0");}
    lcd.print(alarmMM);lcd.print(":");
    if(alarmSS<10){lcd.print("0");}
    lcd.print(alarmSS);
  }
}




코드는 다음의 라이브러리를 사용합니다. < LiquidCrystal.h, Button.h, DS3231.h > 크리스탈 LCD를 사용하기 위해 LiquidCrystal.h 의 라이브러리를 사용합니다. 실제로 Real Time Clock를 제어하는 것은 아두이노에서 상당히 까다로우므로 DS3231.h 라는 라이브러리를 이용해 보다 쉽게 제어할 수 있습니다.


버튼에 대한 설정은 Button.h 라는 라이브러리를 사용합니다.예를 들어, 설정해 놓은 특정 버튼을 Up 혹은 Down 시켜야 하는 경우 Button 에 내장되어 있는 함수인 btnDN 그리고 btnUP를 이용해서 제어할 수 있습니다. < Button btnDN(DN_PIN, PULLUP, INVERT, DEBOUNCE_MS); >


출력을 현재의 상태에 따라 다르게 구현하기 위해서 switch 문을 이용해 주었습니다. 먼저, wait 라는 상태에서 설정 버튼이 눌린 경우 < if (btnSET.wasPressed() ) >, 알람 버튼이 눌린 경우, 다운 버튼이 눌린 경우, 그리고 업 버튼이 눌린 경우 각각의 상황에 따라서 각기 다른 수행을 할 수 있도록 제시해 주었습니다. 



Step 4. 수행결과 



타이머를 설정한 뒤, 알람이 울리게 되면, 3번째 버튼을 눌러서 알람을 끕니다. 그렇지 않게 되면 알람은 10초동안 계속되게 됩니다. 이후 그 다음 알람을 다시 설정하기 위해서는 4번째 버튼을 눌러서 설정을 할 수 있게 됩니다. 


알람을 설정하고, 알람이 울리게 되면 이는 4번째 버튼을 눌러서 끌 수 있게 됩니다. 

댓글 0

MADE BY