markruff icon

Arduino alarm clock and temp - final

markruff | PRO | 01/20/16 01:33:20 AM UTC | 0 ⭐ | 646 👁️ | Never ⏰ | []
C++ |

16.08 KB

|

None

|

0 👍

/

0 👎

 /*
 * 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
 * 
 * Adjustments:
 * - Fixed millis() rollover causing reset to 0:00. Now using
 *   millisSinceMidnight and reset to 0 each day at midnight
 * - Fixed bug resulting in clock slowing down over time due
 *   to modulus operation between call to millis() and subsequent
 *   setting of prevMillis = millis()
 * - Optimised by changing % operations to branching operations
 *   where possible
 * - fixed incremental speed change of hr/min etc
 *
 * Mark Ruff, Jan 2015
 */
 
#include <LiquidCrystal.h>
 
// 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
// millisSinceMidnight, used to calculate the time, updated
// using interval millis() - prevMillis each cycle
unsigned long int millisSinceMidnight = 0;
unsigned long int prevMillis = 0;
int interval; // used to store millis() - prevMillis
 
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;
 
// For the flashing colon :
int colonFrequency = 1000; // flash every 2 seconds
int colonTimer = 0;
bool colonOn = true;
 
// For blinking digits during time / alarm set
int blinkOnTime = 1000;
int blinkOffTime = 333;
int blinkTimer = 0;
bool blinkOn = true;
 
// for slowing increasing speed at which hrs/mins increment
// based on how long button held
int buttonPressedTimer = 0;
int speed1Max = 1500; // 2 seconds
int speed1Delay = 300;
int speed2Max = 3000; //
int speed2Delay = 150;
int speed3Delay = 75;
 
// 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};
 
// TEMPERATURE SETTINGS
// How often to update the temperature
int tempFrequency = 10000;
int tempTimer = 0;
 
// 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() {
 
  // Time keeping
  interval = millis() - prevMillis;
  prevMillis = millis();
 
  // 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;
  }
  else if (button1State == LOW && prevButton1State == HIGH ) {
    button1Pressed = true;
    button1Held = false;
    buttonPressedTimer = 0;
  }
  else {
    button1Pressed = false;
    button1Held = false;
  }
  
  if(button2State == HIGH && prevButton2State == HIGH ) {
    button2Held = true;
    button2Pressed = false;
  }
  else if (button2State == LOW && prevButton2State == HIGH ) {
    button2Pressed = true;
    button2Held = false;
    buttonPressedTimer = 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 {
    // Calculate hours / minutes / seconds since Arduino reset
    // Used to calcuate time
    int hours = (millisSinceMidnight/3600000)%24;
    int minutes = (millisSinceMidnight/60000)%60;
    int seconds = (millisSinceMidnight/1000)%60;
         
    // 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
    // update the timer, check if threshold reached, if so
    // write the temperature 
    tempTimer += interval;
    if (tempTimer > tempFrequency) {
      writeTemp();
      tempTimer = 0;
    }
 
    // Set off alarms if set on and time
    if ( alarmOn && 
         hours == alarmHour && minutes == alarmMinute ) {
      alarm();
    }
  }
 
  // Increment millisecond count from midnight
  // rollover if we've reached midnight
  millisSinceMidnight += interval;
  millisSinceMidnight = millisSinceMidnight % 86400000;
} 
 
// 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
  colonTimer += interval;
  if ( colonTimer > colonFrequency ) {
    colonTimer = 0;
    colonOn = !colonOn;
  }
  if (colonOn) {
    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(1000);
 
  // 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);    
  }
  delay(1000);
 
  lcd.noAutoscroll();
  lcd.clear();
}
 
void setTime() {
 
  bool am = adjustedHour < 12;
 
  // work out whether flashing digit is on or off
  blinkTimer += interval;
  if (blinkOn) {
    if (blinkTimer > blinkOnTime) {
      blinkOn = false;
      blinkTimer = 0;
    }
  }
  else {
    if (blinkTimer > blinkOffTime) {
      blinkOn = true;
      blinkTimer = 0;
    }
  }
 
  // display the clock
  // flash the digits (HH or MM) being changed
  // display the time
  lcd.setCursor(0,0);
  if( !blinkOn && setTimeMode == 1 && !button2Held && ! button2Pressed) {
    lcd.print("__"); // 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( !blinkOn && setTimeMode == 2 && !button2Held ) {
    lcd.print("__"); // flash when setting
  }
  else {
    if (adjustedMinute < 10 ) {
      lcd.print("0");
    }
    lcd.print(adjustedMinute);
  }
 
  // am/pm
  if( !blinkOn && setTimeMode == 3 && !button2Held ) {
    lcd.print("__"); // 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 ) {
    blinkOn = true;
    blinkTimer = 0;
 
    buttonPressedTimer += interval;
    if (buttonPressedTimer < speed1Max) {
      delay(speed1Delay);
    }
    else if (buttonPressedTimer < speed2Max) {
      delay(speed2Delay);
    }
    else {
      delay(speed3Delay);
    }
 
    if (setTimeMode == 1) {
      adjustedHour = adjustedHour + 1;
      if (adjustedHour == 24) adjustedHour = 0;
    }
 
    else if (setTimeMode == 2 ){
      adjustedMinute = adjustedMinute + 1;
      if (adjustedMinute == 60) adjustedMinute = 0;
    }
  }
  if ( button2Pressed && setTimeMode == 3 ) {
    blinkOn = true;
    blinkTimer = 0;
    hour24 = !hour24;
  }
 
  // Button 1 Pressed
  // This cycles through Hours / Minutes / Finished
  if ( button1Pressed ) {
    blinkOn = false;
    blinkTimer = 0;
    setTimeMode = setTimeMode +1;
    if (setTimeMode == 4) {
      setTimeMode = 0;
      millisSinceMidnight = 
        adjustedHour * 3600000 + adjustedMinute * 60000;
      lcd.clear();
      writeTemp();
    }
  }
}
 
void setAlarm() {
 
  bool am = adjustedHour < 12;
 
  // work out whether flashing digit is on or off
  blinkTimer += interval;
  if (blinkOn) {
    if (blinkTimer > blinkOnTime) {
      blinkOn = false;
      blinkTimer = 0;
    }
  }
  else {
    if (blinkTimer > blinkOffTime) {
      blinkOn = true;
      blinkTimer = 0;
    }
  }
 
  // display the clock
  // flash the digits (HH or MM) being changed
  // display the time
  lcd.setCursor(0,0);
  if( !blinkOn && setAlarmMode == 1 && !button2Held && ! button2Pressed) { 
    lcd.print("__"); // 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( !blinkOn && setAlarmMode == 2 && !button2Held ) {
    lcd.print("__"); // 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( !blinkOn && setAlarmMode == 3 && !button2Held ) {
    lcd.print(" ___"); // flash when setting
  }
  else {
    if ( alarmOn ) {
      lcd.print(" on ");
    }
    else {
      lcd.print(" off");
    }
  }
    
  // Button 2 Pressed
  // this increments the hours/minutes
  if ( button2Held ) {
    blinkOn = true;
    blinkTimer = 0;
 
 
    buttonPressedTimer += interval;
    if (buttonPressedTimer < speed1Max) {
      delay(speed1Delay);
    }
    else if (buttonPressedTimer < speed2Max) {
      delay(speed2Delay);
    }
    else {
      delay(speed3Delay);
    }
    
    if (setAlarmMode == 1) {
      adjustedHour = adjustedHour + 1;
      if (adjustedHour == 24) adjustedHour = 0;
    }
    else if (setAlarmMode == 2 ){
      adjustedMinute = adjustedMinute + 1;
      if ( adjustedMinute == 60 ) adjustedMinute = 0;
    }
  }
  if ( button2Pressed && setAlarmMode == 3 ) {
    blinkOn = true;
    blinkTimer = 0;
    alarmOn = !alarmOn;
  }
 
  // Button 1 Pressed
  // This cycles through Hours / Minutes / Finished
  if ( button1Pressed ) {
    blinkOn = false;
    blinkTimer = 0;    
    setAlarmMode = setAlarmMode + 1;
    if (setAlarmMode == 4) {
      setAlarmMode = 0;
      alarmHour = adjustedHour;
      alarmMinute = adjustedMinute;
      lcd.clear();
      writeTemp();
    }
  }
}
 
// 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");
}

Comments