-
Notifications
You must be signed in to change notification settings - Fork 0
/
alarme_ifrn.ino
284 lines (229 loc) · 7.85 KB
/
alarme_ifrn.ino
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
/*
Relógio, Calendário e controle de alarme de aulas para o IFRN - Pau dos Ferros
Autor: Diego Cirilo
Data: 18/01/2013
Pinos utilizados:
* RTC - SDA - SCL(AN4, AN5)
* SW1(da placa) - PIN0
* SW2(eu botei) - PIN6
* LED2(azul - PIN2
* RELE1 - PIN7
* RELE2 - PIN8
* JUMPER1 - PIN9
* LED1(verm) - PIN10
* BUZZER - PIN13
* LCD RS - PIN12
* LCD Enable - PIN11
* LCD D4 - PIN5
* LCD D5 - PIN4
* LCD D6 - PIN3
* LCD D7 - PIN2
*/
// biblioteca do display
#include <LiquidCrystal.h>
// biblioteca do I2C(para comunicar com o RTC)
#include <Wire.h>
// inicializa o display com os pinos em questão(mencionados acima)
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// aliases para os pinos
#define SW1 0
#define SW2 6
#define LED2 1
#define RELE1 7
#define RELE2 8
#define JUMPER1 9
#define LED1 10
#define BUZZER 13
// endereço de comunicação com o RTC
#define DS1307_ADDRESS 0x68
//byte zero "de verdade"
byte zero = 0x00;
// variável para temporização
long timer01=0;
// variáveis para os valores de tempo. weekDay é o dia da semana de dom a sab, 1-7.
byte second, minute, hour, weekDay, monthDay, month, year, checkday=0;
// tempo de toque longo(horario de intervalo)
byte tempoLongo=4;
// tempo de toque curto(entre aulas sem intervalo)
byte tempoCurto=2;
// variáveis booleanas para alguns controles no código
bool toggle=false, firstpass=true;
// loop de inicialização, padrão do arduino.
void setup() {
// setando os pinos de saída
pinMode(BUZZER, OUTPUT);
pinMode(RELE1, OUTPUT);
pinMode(RELE2, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
// e os pinos de entrada. notar que eles tem um pull-up de 10k,
// logo eles são lidos normalmente como HIGH, e se o botão é
// pressionado, vai para LOW.
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
pinMode(JUMPER1, INPUT);
// Inicializar a interface I2C - RTC
Wire.begin();
// setando o número de colunas e linhas do display, no caso 8x2
lcd.begin(8, 2);
}
// converte de decimal para BCD. utilizado já que o RTC trabalha com dígitos BCD
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
// converte de BCD para decimal. utilizado já que o RTC trabalha com dígitos BCD
byte bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
// atualiza a data e hora no RTC.
void setDateTime(){
byte second = 0; //0-59
byte minute = 20; //0-59
byte hour = 9; //0-23
byte weekDay = 2; //1-7
byte monthDay = 25; //1-31
byte month = 2; //1-12
byte year = 13; //0-99
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); // vai p/ registro 0, onde ficam os segundos. leia o datasheet do DS1307
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
Wire.write(decToBcd(monthDay));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(zero); //volta p/ registro 0 que é o canto certo
Wire.endTransmission();
}
void resetDateTime(){
second=0;
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); // vai p/ registro 0, onde ficam os segundos. leia o datasheet do DS1307
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
Wire.write(decToBcd(monthDay));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(zero); //volta p/ registro 0 que é o canto certo
Wire.endTransmission();
}
// lê a data do RTC e escreve nas variáveis globais de data, hora, etc
void getDate(){
// vai p/ registro 0, dos segundos... p/ garantir
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);
Wire.endTransmission();
// pede 7 bytes ao RTC
Wire.requestFrom(DS1307_ADDRESS, 7);
// os 7 bytes de resposta.
second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0b111111); //formato 24hrs
weekDay = bcdToDec(Wire.read()); //1-7 -> domingo - sábado
monthDay = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
}
// atualiza o display, escrevendo as variáveis em questão.
void printDate(byte second_f, byte minute_f, byte hour_f, byte weekDay_f, byte monthDay_f, byte month_f, byte year_f){
// imprime a data no formato dd/mm/aa e a hora na segunda linha, no formato hh:mm:ss
lcd.setCursor(0, 0); //posicionando o cursor na posição 0 da primeira linha(0)
if(monthDay<10){
lcd.print(0); // necessário no caso do dia só ter um dígito, ele imprime um zero antes para manter o espaçamento correto.
}
lcd.print(monthDay);
lcd.print("/");
if(month<10){
lcd.print(0); // mesmo caso do dia, e idem para todos os outros items.
}
lcd.print(month);
lcd.print("/");
if(year<10){
lcd.print(0);
}
lcd.print(year);
lcd.setCursor(0, 1); // posicionando o cursor na posição 0 da segunda linha(1).
if(hour<10){
lcd.print(0);
}
lcd.print(hour);
lcd.print(":");
if(minute<10){
lcd.print(0);
}
lcd.print(minute);
lcd.print(":");
if(second<10){
lcd.print(0);
}
lcd.print(second);
}
// seletor dos momentos de tocar, retorna true se tiver na hora!
bool timeToStudy(){
byte jumper=digitalRead(JUMPER1);
// se não for domingo(0) nem sábado(6) ou se jumper tiver HIGH(passa por cima de sábados e domingos, no caso de sábado letivo)
// verifica pelas horas se toca 3s(intervalos e inicio/fim) ou 1s(entre aulas)
if((weekDay!=1 && weekDay!=7) || jumper==HIGH){
// toque de tempoLongo s para 07h00m, 12h00m, 13h00m, 18h00m, 19h00m
if((hour==7 || hour==12 || hour==13 || hour==18 || hour==19) && minute==0 && (second>=0 && second<=tempoLongo))
return true;
// toque de tempoLongo s para 8h30m, 10h30m, 14h30m, 16h30m, 20h30m
if((hour==8 || hour==10 || hour==14 || hour==16 || hour==20) && minute==30 && (second>=0 && second<=tempoLongo))
return true;
// toque de tempoLongo s para 08h50m, 14h50m
if((hour==8 || hour==14) && minute==50 && (second>=0 && second<=tempoLongo))
return true;
// toque de tempoLongo s para 10h20m, 16h20m
if((hour==10 || hour==16) && minute==20 && (second>=0 && second<=tempoLongo))
return true;
// toque de tempoLongo s para 20h40m, 22h10m
if(((hour==20 && minute==40) || (hour==22 && minute==10)) && (second>=0 && second<=tempoLongo))
return true;
// toque de tempoCurto s para 07h45m, 13h45m, 19h45
if((hour==7 || hour==13 || hour==19) && minute==45 && (second>=0 && second<=tempoCurto))
return true;
// toque de tempoCurto s para 09h35, 15h35m
if((hour==9 || hour==15) && minute==35 && (second>=0 && second<=tempoCurto))
return true;
// toque de tempoCurto s para 11h15m, 17h15m
if((hour==11 || hour==17) && minute==15 && (second>=0 && second<=tempoCurto))
return true;
// toque de tempoCurto s para 21h25m
if(hour==21 && minute==25 && (second>=0 && second<=tempoCurto))
return true;
} else{
return false;
}
return false;
}
// loop principal do arduino, é padrão. a ação acontece aqui. tipo um "main" do C.
void loop() {
// atraso de 100ms para diminuir a frequência de acesso ao RTC, atualização do display, etc.
// ninguém está desesperado, e teoricamente ainda diminui o consumo.
delay(100);
// Lê a data do RTC e escreve nas variáveis globais lá.
getDate();
if ((hour==6) && (minute==0) && (second==30) && (checkday!=weekDay)){
checkday = weekDay;
resetDateTime();
}
//teste
if(digitalRead(SW1)==LOW){
setDateTime();
}
// Escreve a data no display
printDate(second, minute, hour, weekDay, monthDay, month, year);
// chama timeToStudy para saber se ta na hora de tocar, se tiver, toca!
if(timeToStudy()){
digitalWrite(RELE1, HIGH); // relé que controla a sirene
digitalWrite(LED1, HIGH); // led1 só p/ visualização
digitalWrite(BUZZER, HIGH); // buzzer da placa, idem.
} else{
digitalWrite(LED1, LOW);
digitalWrite(RELE1, LOW);
digitalWrite(BUZZER, LOW);
}
}