/* * LCD Alarm Clock with Temperature * * Arduino powered alarm clock that shows the time and temperature * Alarm can be set. Alarm creates tone at piezo and flashes LED * * Settings controlled with two buttons: * - button 1: set time * - button 1: cycle hr/min/24hr * - button 2: increment * - button 2: set alarm * - button 1: cycle hr/min/on-off * - button 2: increment * * pin configuration outlined in comments below * * To do: adjust to handle millis() rollover * ... I've got about 50 days * * Mark Ruff, Jan 2015 */ #include // GLOBALS // ARDUINO PINS const int button1 = 6; // push buttons const int button2 = 7; const int tempPin = A0; // temperature monitor const int alarmPin = 8; // piezo const int alarmLedPin = 13; // LED // LCD // moved pin 11->10 and 3->9 to avoid interference from tone() LiquidCrystal lcd(12,10,5,4,9,2); // Byte blocks for additional icons to display in lcd // loading in setup() byte alarmIcon[8] = { B00100, B01110, B01110, B01110, B11111, B00100, B00000, }; byte heartIcon[8] = { B00000, B01010, B11111, B11111, B11111, B01110, B00100, }; byte noteIcon[8] = { B00100, B00110, B00101, B00101, B00100, B11100, B11100, }; // TIME SETTINGS // Set time - adjustment relative to millis() unsigned long int setMillis = 0; // (60 * hours + minutes)*60000 int hour24 = false; // 24 hour time // For setting the time // - 0 = not settingm time // - 1 = setting Hours // - 2 = setting Minutes // - 3 = setting am/pm int setTimeMode; int adjustedHour; int adjustedMinute; // ALARM SETTINGS bool alarmOn = false; int alarmHour = 0; int alarmMinute = 0; // For setting the alarm (mode similar to setTime Mode int setAlarmMode; // frequencies (notes) used by the alarm int notes[] = {261, 294, 329, 349, 392, 440, 493, 523}; // BUTTON SETTINGS // Held button: current state HIGH and prev state HIGH // Pressed button: current state LOW and prev state HIGH // - Pressed is really released button // Pressed time is used to vary the speed when incrementing // the time or alarm int button1State = LOW; int button2State = LOW; int prevButton1State = LOW; int prevButton2State = LOW; bool button1Pressed = false; bool button1Held = false; bool button2Pressed = false; bool button2Held = false; int button1PressedTime = 0; int button2PressedTime = 0; void setup() { // pins pinMode(button1, INPUT); pinMode(button2, INPUT); pinMode(tempPin, INPUT); pinMode(alarmPin, OUTPUT); pinMode(alarmLedPin, OUTPUT); digitalWrite(alarmLedPin, LOW); // lcd lcd.begin(16,2 ); // three characters (defined above) lcd.createChar(0, alarmIcon); lcd.createChar(1, heartIcon); lcd.createChar(2, noteIcon); // print the welcome message welcomeMessage(); // write the temperature, because we don't do it every loop writeTemp(); } void loop() { // capture button presses // HELD = while button depressed // PRESSED = after release (reading falling edge) button1State = digitalRead(button1); button2State = digitalRead(button2); if(button1State == HIGH && prevButton1State == HIGH ) { button1Held = true; button1Pressed = false; if (button1PressedTime == 0) { button1PressedTime = millis(); } } else if (button1State == LOW && prevButton1State == HIGH ) { button1Pressed = true; button1Held = false; button1PressedTime = 0; } else { button1Pressed = false; button1Held = false; } if(button2State == HIGH && prevButton2State == HIGH ) { button2Held = true; button2Pressed = false; if ( button2PressedTime == 0 ) { button2PressedTime = millis(); } } else if (button2State == LOW && prevButton2State == HIGH ) { button2Pressed = true; button2Held = false; button2PressedTime = 0; } else { button2Pressed = false; button2Held = false; } prevButton1State = button1State; prevButton2State = button2State; // Setting the time? if (setTimeMode > 0) { setTime(); } // Or setting the alarm? else if (setAlarmMode > 0 ) { setAlarm(); } // Otherwise just display the time & temperature else { int hours = getHour(); int minutes = getMinute(); int seconds = getSeconds(); // BUTTON 1 PRESS // Change the time if ( button1Pressed ) { setTimeMode = 1; adjustedHour = hours; adjustedMinute = minutes; } // BUTTON 2 PRESS if ( button2Pressed ) { setAlarmMode = 1; adjustedHour = alarmHour; adjustedMinute = alarmMinute; } // DISPLAY THE TIME displayTime(hours, minutes, seconds); // DISPLAY ALARM ICON (if on) if ( alarmOn ) { lcd.print(" "); lcd.write( byte(0) ); // this is our alarm icon } else { lcd.print(" "); } // DISPLAY THE TEMPERATURE // only refresh every 10s if ( millis() % 10000 < 200 ) { writeTemp(); } // Set off alarms if set on and time if ( alarmOn && hours == alarmHour && minutes == alarmMinute ) { alarm(); } } } // Calculate hours / minutes / seconds since Arduino reset // Used to calcuate time int getHour() { return ((millis()+setMillis)/3600000)%24; } int getMinute() { return ((millis()+setMillis)/60000)%60; } int getSeconds() { return (millis()/1000)%60; } // Displays the time void displayTime(int hours, int minutes, int seconds) { // is it morning bool am = hours < 12; // HOURS lcd.setCursor(0,0); // first handle 24 hour time if( hour24 ) { if ( hours < 10 ) { lcd.print(" "); } lcd.print(hours); } // otherwise am/pm else { hours = am ? hours : hours - 12; if ( hours == 0 ) { lcd.print("12"); } else if ( hours < 10 ) { lcd.print( " " ); lcd.print(hours); } else { lcd.print(hours); } } // FlASHING COLON if ( seconds % 2 == 0 ) { lcd.print(":"); } else { lcd.print(" "); } // MINUTES if ( minutes < 10 ) { lcd.print("0"); } lcd.print(minutes); // AM/PM if ( !hour24 ) { if ( am ) { lcd.print("am"); } else { lcd.print("pm"); } } else { lcd.print (" "); } } // Print a welcome message // Two lines, top line first, bottom line scrolling in with top // line scrolling out. void welcomeMessage() { char topMessage[] = " Ruffian Clock"; // bottom message split so I can put a heart in char bottomMessageLeft[] = "I "; char bottomMessageRight[] = " Arduino!"; // Write top welcome message lcd.setCursor(0,0); lcd.print(topMessage); delay(2500); // Write bottom welcome message lcd.setCursor(16,1); lcd.autoscroll(); for ( int i = 0 ; bottomMessageLeft[i] != '\0' ; i++ ) { lcd.print(bottomMessageLeft[i]); delay(500); } // print the heart lcd.write(byte(1)); delay(500); for ( int i = 0 ; bottomMessageRight[i] != '\0' ; i++ ) { lcd.print(bottomMessageRight[i]); delay(500); } lcd.noAutoscroll(); lcd.clear(); } void setTime() { bool am = adjustedHour < 12; bool flash = (millis() % 1500 ) < 250; // display the clock // flash the digits (HH or MM) being changed // display the time lcd.setCursor(0,0); if( flash && setTimeMode == 1 && !button2Held && ! button2Pressed) { lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if (hour24) { if ( adjustedHour < 10 ) { lcd.print(" "); } lcd.print(adjustedHour); } else { if (!am) { if ( adjustedHour == 12 ) { lcd.print("12"); } else { if ( adjustedHour -12 < 10 ) { lcd.print(" "); } lcd.print(adjustedHour - 12); } } else { if ( adjustedHour == 0 ) { lcd.print("12"); } else { if ( adjustedHour < 10 ) { lcd.print(" "); } lcd.print(adjustedHour); } } } } lcd.print(":"); if( flash && setTimeMode == 2 && !button2Held ) { lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if (adjustedMinute < 10 ) { lcd.print("0"); } lcd.print(adjustedMinute); } // am/pm - don't flash if( flash && setTimeMode == 3 && !button2Held ) { lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if ( hour24 ) { lcd.print(" "); } else { if ( am ) { lcd.print("am"); } else { lcd.print("pm"); } } } // Button 2 Pressed // this increments the hours/minutes if ( button2Held ) { int delayFactor = millis() - button2PressedTime; if ( delayFactor < 2000 ) { delay(200); } if (delayFactor < 4000) { delay(100); } delay(50); if (setTimeMode == 1) { adjustedHour = ( adjustedHour + 1 ) % 24; } else if (setTimeMode == 2 ){ adjustedMinute = ( adjustedMinute + 1 ) % 60; } } if ( button2Pressed && setTimeMode == 3 ) { hour24 = !hour24; } // Button 1 Pressed // This cycles through Hours / Minutes / Finished if ( button1Pressed ) { setTimeMode = (setTimeMode +1 ) % 4; if (setTimeMode == 0) { setMillis = (((adjustedHour * 60 + adjustedMinute ) * 60000) - millis()) % 86400000; lcd.clear(); writeTemp(); } } } void setAlarm() { bool am = adjustedHour < 12; bool flash = (millis() % 1500 ) < 300; // display the clock // flash the digits (HH or MM) being changed // display the time lcd.setCursor(0,0); if( flash && setAlarmMode == 1 && !button2Held && ! button2Pressed) { lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if (hour24) { if ( adjustedHour < 10 ) { lcd.print(" "); } lcd.print(adjustedHour); } else { if (!am) { if ( adjustedHour == 12 ) { lcd.print("12"); } else { if ( adjustedHour -12 < 10 ) { lcd.print(" "); } lcd.print(adjustedHour - 12); } } else { if ( adjustedHour == 0 ) { lcd.print("12"); } else { if ( adjustedHour < 10 ) { lcd.print(" "); } lcd.print(adjustedHour); } } } } lcd.print(":"); if( flash && setAlarmMode == 2 && !button2Held ) { lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if (adjustedMinute < 10 ) { lcd.print("0"); } lcd.print(adjustedMinute); } // am/pm - not changing here if ( hour24 ) { lcd.print(" "); } else { if ( am ) { lcd.print("am"); } else { lcd.print("pm"); } } if( flash && setAlarmMode == 3 && !button2Held ) { lcd.print(" "); lcd.print((char)95); lcd.print((char)95); lcd.print((char)95); // flash when setting } else { if ( alarmOn ) { lcd.print(" on "); } else { lcd.print(" off"); } } // Button 2 Pressed // this increments the hours/minutes if ( button2Held ) { int delayFactor = millis() - button2PressedTime; if ( delayFactor < 2000 ) { delay(200); } if (delayFactor < 4000) { delay(100); } delay(50); if (setTimeMode == 1) { adjustedHour = ( adjustedHour + 1 ) % 24; } if (setAlarmMode == 1) { adjustedHour = ( adjustedHour + 1 ) % 24; } else if (setAlarmMode == 2 ){ adjustedMinute = ( adjustedMinute + 1 ) % 60; } } if ( button2Pressed && setAlarmMode == 3 ) { alarmOn = !alarmOn; } // Button 1 Pressed // This cycles through Hours / Minutes / Finished if ( button1Pressed ) { setAlarmMode = (setAlarmMode +1 ) % 4; if (setAlarmMode == 0) { alarmHour = adjustedHour; alarmMinute = adjustedMinute; lcd.clear(); writeTemp(); } } delay(100); } // Set off the alarm, combination of: // - tone // - LED flashing // - note icon on LCD void alarm() { // draw the note icon on the LCD lcd.setCursor(9,0); lcd.write(byte(2)); // play the little tune (uses frequencies in notes[]) // flash the LED at the same time for ( int i = 0 ; i < 4 ; i++ ) { tone(alarmPin,notes[i],200); digitalWrite(alarmLedPin,LOW); delay(200); tone(alarmPin,notes[i+2],200); digitalWrite(alarmLedPin,HIGH); delay(200); } tone(alarmPin,notes[6],600); for (int i = 0 ; i < 6 ; i++ ) { digitalWrite(alarmLedPin,LOW); delay(50); digitalWrite(alarmLedPin,HIGH); delay(50); } for(int i = 3 ; i >= 0 ; i-- ) { tone(alarmPin,notes[i],200); lcd.setCursor(9,0); lcd.write(byte(2)); delay(100); // flash the note icon a little lcd.setCursor(9,0); lcd.write(" "); delay(100); } // turn off alarm, clear LCD, turn off LED alarmOn = false; digitalWrite(alarmLedPin,LOW); lcd.clear(); // write the temp (because there might be a delay) writeTemp(); } // write the temperature on the bottom line of the LCD void writeTemp() { // get the sensor value int tempSensorVal = analogRead(tempPin); // convert the sensor reading to voltage float voltage = (tempSensorVal/1024.0) * 5.0; // convert voltage to temperature float temperature = (voltage - 0.5) * 100; lcd.setCursor(0,1); lcd.print(temperature); lcd.setCursor(4,1); lcd.print((char)223); // degrees symbol lcd.print("C"); }