2 * fuzzy_alarm_clock arduino sketch
3 * copyright (C) 2011 Elena Grandi, Diego Roversi
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <RealTimeClockDS1307.h>
23 // minutes of "dawn" before alarm
25 // "dawn" + "daylight"
27 // "dawn" + "daylight" + blue blinding light
30 // number of available alarms; max 10 for storage in the DS1307 ram
44 int st = 0; // alarm status (minutes from alarm - TIN)
45 char alarms[NALARMS][5]; // alarm settings
46 char cmin; // current minute
47 signed char a = -1; // current alarm
48 bool dbg = false; // print debug informations
49 bool ringing = false; // sound the alarm
50 bool pressed = false; // stop button status
53 int freq[] = { 255, 192, 128, 96, 64, 96, 128, 192, 255 }; // frequencies for the alarm
65 TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
66 TCCR2B = _BV(WGM22) | _BV(CS22);
68 attachInterrupt(IINT, button_pressed, HIGH);
70 analogWrite(RPIN,128);
71 digitalWrite(YPIN,LOW);
72 digitalWrite(BPIN,LOW);
74 // if the RTC is already running read alarms and status,
75 // otherwise set everything to a sane default
76 if ( RTC.readData(0x00) >> 7 ) {
77 for ( int i = 0 ; i < NALARMS ; i ++ ) {
78 for ( int j = 0; j < 5 ; j ++ ) {
86 st = RTC.readData(0x08);
87 a = RTC.readData(0x09);
88 cmin = RTC.readData(0x0a);
89 // This only works if the arduino had no power for a
90 // "short" time. This is by design. :D
93 st = st + (RTC.getMinutes() - cmin) % 60;
94 cmin = RTC.getMinutes();
97 for ( int i = 0; i < NALARMS ; i ++ ) {
98 for ( int j = 0; j < 5 ; j ++ ) {
99 alarms[i][j] = RTC.readData(0x0b + i*5 + j);
108 // read commands from serial
111 // read time, check alarms
116 Serial.print("st: ");
117 Serial.print(st,DEC);
118 Serial.print(", a: ");
120 Serial.print(", cmin: ");
121 Serial.print(cmin,DEC);
122 Serial.print(", ringing: ");
123 Serial.print(ringing);
124 Serial.print(", pressed: ");
125 Serial.println(pressed);
128 // act on status: LEDs and buzzer
133 if ( RTC.getSeconds() < 5 ) {
146 // wait about till the next second
153 RTC.writeData(0x08,st);
154 RTC.writeData(0x09,a);
155 RTC.writeData(0x0a,cmin);
159 if ( RTC.readData(0x00) >> 7 ) {
162 for ( int i = 0; i < NALARMS ; i ++ ) {
163 // we can skip checking the hour/minute field
164 for ( int j = 0; j < 3 ; j ++ ) {
165 if ( alarms[i][j] != 0 ) {
173 // ****** Serial interface management *************************************** //
175 void check_serial() {
176 int rec = Serial.read();
206 int i = s_read_dig();
207 for ( int j = 0; j < 5 ; j++) {
208 alarms[i][j] = s_read_2hex();
210 for ( int j = 0; j < 5 ; j++ ) {
211 RTC.writeData(0x0b + i*5 + j,alarms[i][j]);
213 Serial.print("Alarm ");
215 Serial.println(" set.");
221 RTC.setYear(s_read_2dig());
222 RTC.setMonth(s_read_2dig());
223 RTC.setDate(s_read_2dig());
224 RTC.setDayOfWeek(s_read_dig());
225 RTC.setHours(s_read_2dig());
226 RTC.setMinutes(s_read_2dig());
227 RTC.setSeconds(s_read_2dig());
229 Serial.print("Time set: ");
237 while ( rec == -1 ) {
245 n = s_read_dig() * 10;
246 n = n + s_read_dig();
253 while ( rec == -1 ) {
256 if ( rec >= 48 && rec < 58 ) {
258 } else if ( rec >= 65 && rec < 71 ) {
260 } else if ( rec >= 97 && rec < 103 ) {
269 n = s_read_hex() * 16;
270 n = n + s_read_hex();
274 void s_print_alarms() {
275 for ( int i = 0; i < NALARMS ; i++) {
278 for ( int j = 0; j < 5 ; j++) {
279 Serial.print(alarms[i][j],DEC);
286 void s_print_time() {
288 Serial.print(RTC.getYear(),DEC);
290 Serial.print(RTC.getMonth(),DEC);
292 Serial.print(RTC.getDate(),DEC);
294 Serial.print(RTC.getDayOfWeek(),DEC);
296 Serial.print(RTC.getHours(),DEC);
298 Serial.print(RTC.getMinutes(),DEC);
300 Serial.println(RTC.getSeconds(),DEC);
303 void s_toggle_debug() {
313 Serial.println("Testing LEDs");
314 digitalWrite(RPIN,HIGH);
315 digitalWrite(YPIN,HIGH);
316 digitalWrite(BPIN,HIGH);
318 digitalWrite(RPIN,HIGH);
319 digitalWrite(YPIN,LOW);
320 digitalWrite(BPIN,LOW);
324 void s_reset_alarms() {
325 for ( int i = 0 ; i < NALARMS ; i ++ ) {
326 for ( int j = 0; j < 5 ; j ++ ) {
336 void s_print_help() {
338 Serial.println(" a<s> - set an alarm");
339 Serial.println(" <s> is nhhhhhhhhhh");
340 Serial.println(" alarm ID");
341 Serial.println(" one bit (in hex) for day of week");
342 Serial.println(" hex values for month, day");
343 Serial.println(" hex values for hour, minutes");
344 Serial.println(" (relative to start-of-dawn time)");
345 Serial.println(" s<s> - set the clock");
346 Serial.println(" <s> is yymmgguHHMMSS");
347 Serial.println(" p - print the alarms");
348 Serial.println(" t - print the clock");
349 Serial.println(" d - toggle printing of debug informations");
350 Serial.println(" r - reset status and alarms");
351 Serial.println(" l - test LEDs");
352 Serial.println(" h - print this help");
355 void button_pressed() {
359 // ****** Time management *************************************************** //
361 // Set the current time
362 void set_time(int y,int m,int d, int w, int hh, int mm, int ss) {
377 int mm = RTC.getMinutes();
378 int hour = RTC.getHours();
379 int wday = RTC.getDayOfWeek();
380 int day = RTC.getDate();
381 int month = RTC.getMonth();
384 for ( int i = 0; i < NALARMS ; i ++ ) {
386 if ( ( alarms[i][0] & ( 1 << (wday - 1) ) ) ||
387 (month == alarms[i][1] && day == alarms[i][2]) ) {
388 // this is alarm day!
389 if ( hour == alarms[i][3] && mm == alarms[i][4]) {
390 // this is alarm hour!
395 if ( ( alarms[i][0] & 128 ) == 0 ) {
396 // this alarm won't be repeated
397 alarms[i] = { 0,0,0,0,0 };
398 for ( int j = 0; j < 5 ; j++ ) {
399 RTC.writeData(0x0b + i*5 + j,0);
416 // ****** LED management **************************************************** //
419 if ( st > 0 && st <= TIN) {
420 int y = int(float(st*255)/TIN);
424 } else if ( st > TIN && st < TDAY ) {
426 analogWrite(YPIN,255);
428 } else if (st >= TDAY && st < TOUT) {
431 analogWrite(BPIN,255);
432 } else if (st == TOUT) {
444 analogWrite(RPIN,128);
449 analogWrite(YPIN,16);
450 analogWrite(BPIN,16);
459 pinMode(APIN1,OUTPUT);
460 for (int i=0; i<NFREQ ; i++) {
464 pinMode(APIN1,INPUT);
468 // vim: set filetype=c: