Internet Alarm Clock

Overview

This project is an expansion of the NTP client cookbook example. The internet alarm clock first establishes an ethernet connection then conducts an automatic network timesync. Once established the current time will display on the LCD. The timezone can be adjusted to the current timezone or an alarm time can be set through the use of three hardwired pushbuttons. The alarm flashes 4 LED when triggered and stops when the time changes or though the use of any pushbuttons.

Functionality

The internet alarm clock contains 5 menus and uses three hardwired push buttons to navigate those menus
Menu PushButton
1. Default - Current time 1. Menu Select
2. Timezone 2. Add
3. Alarm hour 3. Subtract
4. Alarm Minute
5. Alarm Set

Options

  1. Default - Display the current time immediately upon completion of timesync.
  2. Timezone - Displays the current timezone. Timezone can be changed +12 hours or -12 hours.
  3. Alarm Hour - Displays the alarm hour to be set, can be incremented or decremented.
  4. Alarm Minute - Displays the alarm minute to be set, can be incremented or decremented.
  5. Alarm Set - Turns the alarm on or off.
  1. Menu Select -  Cycles through the five menus.
  2. Add - Increments a value in the corresponding menu.
  3. Subtract - Decrements a value in the corresponding menu.

Connections

Ethernet
mbed adapter
TD+
p1
TD- p2
RD+ p7
RD- p8
Text LCD Display
mbed LCD mbed LCD mbed LCD mbed LCD
GND 0V RS P5 D0 D4 P7
VCC 5V RW 0V D1 D5 P8
VO {1k Ohm } - 0V E P6 D2 D6 P9
D3 D7 P10

 

Pushbutton

The hardwired pushbuttons were implemented as pull-up networks with 1k Ohm resistors. Menu - p23, Add - p22,  Subtract - p21.

Code

Main.h

#include "mbed.h"
#include "EthernetNetIf.h"
#include "NTPClient.h"
#include "TextLCD.h"

/****************** Class Global Declartions **********************/
EthernetNetIf eth; 
NTPClient ntp;
TextLCD lcd(p5, p6, p7, p8, p9, p10);
InterruptIn statechange(p23);
InterruptIn plus(p22);
InterruptIn minus(p21);
Ticker ring;
BusOut led(LED1, LED2, LED3, LED4);
/******************************************************************/
/***************** Standard Global Declartions ********************/

int menu = 0;           // Holds the current menu information 
int timezone = 0;       // Timezone is configured as UTC + timezone - 12
bool alarmstate = false;// Determines whether the alarm is set or not
bool ringflag = false;  // Determines if alarm is ringing
bool snooze = false;    // True if the alarm has been turned off by a button
struct tm *cTime;       // Stucture that holds the current time
int ahour;              // Value that holds alarm hour
int amin;               // Value that holds alarm minute
/******************************************************************/
/*********************** Function Declartions *********************/
void print_lcd();
void print_time(int, int);
void print_menu();
void change_menu();
void button_press(int);
void push_plus();
void push_minus();
void alarm_ring();
void alarm_snooze();
void alarm_check();
/******************************************************************/

Main.cpp

#include "main.h"

/*******************************************************************
 * Print_lcd
 *
 * This function clears the LCD, then either prints 1. the alarm time
 * or 2. the current time and alarm clock menu state.
 ******************************************************************/
void print_lcd()
{
    lcd.cls();
    /* Menu options 2 and above deal with the alarm */
    if (menu > 1)
        print_time(ahour, amin);
    else
        print_time(cTime->tm_hour, cTime->tm_min);
    print_menu();
}

/******************************************************************
 * Print_time
 *
 * This function takes an hour(in 24hr time) and a minute and
 * prints the correct format to the lcd.
 *****************************************************************/
void print_time(int hour, int minute)
{
    /* Variable tmphr is 24 hour time adjusted for timezone */
    int tmphr = hour + timezone;
    while (tmphr < 0)
        tmphr += 24;
    tmphr %= 24;
    
    /* Variable printhr is 12 hour time for printing */
    int printhr = tmphr % 12;
    if (printhr == 0)
        printhr += 12;
    lcd.printf("%2d:%02d ", printhr, minute);
    
    /* tmphr allows for checking of AM/PM */
    if ((tmphr > 11) && (tmphr < 24))
        lcd.printf("PM\n");
    else
        lcd.printf("AM\n");
}    

/*******************************************************************
 * Print_menu
 *
 * This function prints the menu state of the alarm clock to the LCD. 
 * The menu options are 1. Viewing current time 2.  Setting Timezone
 * 3. Setting alarm hour 4. Setting alarm minute 5. Toggling alarm
 ******************************************************************/
void print_menu()
{
    switch (menu){
        case 0:
            break;
        case 1: 
            lcd.printf("TZ is (UTC) %+d\n", timezone);  
            break;
        case 2: 
            lcd.printf("Set Alarm Hour\n");
            break;
        case 3: 
            lcd.printf("Set Alarm Min\n");
            break;
        case 4: 
            lcd.printf("Alarm is ");
            if (alarmstate == false)
                lcd.printf("Off\n");
            else
                lcd.printf("On\n");
            break;
        default:
            lcd.printf("Invalid menu %d\n", menu);
            break;
    }
}

/******************************************************************
 * Change_menu
 *
 * This function uses a dedicated pushbutton that changes the menu. 
 * The state variable, menu, gives the user the ability to cycle 
 * through the 5 alarm clock menus.
 *****************************************************************/
void change_menu()
{
    alarm_snooze();
    menu = (menu + 1) % 5;
    print_lcd();
}

/******************************************************************
 * Push_plus
 *
 * This function  uses a dedicated pushbutton to only increment or
 * "Add" the value of variables of an alarm clock i.e. minute, hour,
 * time zone
 *****************************************************************/
void push_plus()
{
    alarm_snooze();
    button_press(1);
}

/******************************************************************
 * Push_minus
 *
 * This function  uses a dedicated pushbutton to only decrement 
 * or "Subtract" the value of variables of an alarm clock
 * i.e. minute, hour, time zone
 *****************************************************************/
void push_minus()
{
    alarm_snooze();
    button_press(-1);
}

/******************************************************************
 * Button_press
 *
 * This function performs an action based on which menu item is 
 * currently selected. It is called whenever the "Add" or 
 * "Subtract" button is pressed.
 *****************************************************************/
void button_press(int input)
{
    switch (menu)
    {
        case 0: 
            break;
        case 1:
            timezone += 12;      
            timezone += input;
            while (timezone < 0)
                timezone += 24;
            timezone %= 24;
            timezone -= 12;
            break;
        case 2:
            ahour += input;
            while (ahour < 0)
                ahour += 24;
            ahour %= 24;
            break;
        case 3: 
            amin += input;                  
            while (amin < 0)
                amin += 60;
            amin %= 60;
            break;
        case 4: 
            alarmstate = !alarmstate;       // Turn alarm on/off
            break;
        default:
            lcd.printf("Invalid state %d\n", menu);
            break;
    }
    print_lcd();
}

/******************************************************************
 * Alarm_ring
 *
 * This function rings the alarm by flashing the leds
 *****************************************************************/
 void alarm_ring()
 {
    if (led == 0x0F)
        led = 0;
    else
        led = (led << 1) | 1;
 }
 
/******************************************************************
 * Alarm_snooze
 *
 * This function turns off the alarm
 *****************************************************************/
void alarm_snooze()
{
    if (ringflag == true) {
        ringflag = false;
        snooze = true;
        ring.detach();
        led = 0;
    }
}

/******************************************************************
 * Alarm_check
 *
 * This function compares the alarm time vs the current time. Once 
 * alarm time and real time match it begins ringing the alarm. 
 * Once the times differ then it turns off the alarm.
 *****************************************************************/
void alarm_check()
{
    if ((cTime->tm_min == amin) && (cTime->tm_hour == ahour)) {
        if ((alarmstate == true) && (ringflag == false) && (snooze == false)) { 
            ringflag = true;
            ring.attach(&alarm_ring, .5); // Set up a Ticker for the alarm,
                             // calls alarm_ring every .5 seconds until stopped
        }
    }
    else {
        alarm_snooze();
        snooze = false;
    }
}

int main() {

    /* Set up Ethernet */
    lcd.cls();
    lcd.printf("Setting up Eth\n");
    EthernetErr ethErr = eth.setup();
    if (ethErr) {
        lcd.cls();
        lcd.printf("Error with Eth\nNum: %d", ethErr);
        return -1;
    }
    
    
    /* Set up NTP */
    lcd.printf("Setting up NTP\n");
    Host server(IpAddr(), 123, "0.uk.pool.ntp.org");
    ntp.setTime(server);
    
    /* Initialize all the interrupts for each of the pushbuttons */
    statechange.rise(&change_menu);
    plus.rise(&push_plus);
    minus.rise(&push_minus);
    
    /* Temporary variables for control loop */
    time_t rtc_time = time(NULL);
    int minute = -1;
    
    /* Initialize alarm time */
    ahour = 0;
    amin = 0;

    /* Main control loop */
    while(1)
    {
        /* Update current time */
        rtc_time = time(NULL);
        cTime = localtime(&rtc_time);
        
        /* Only redraw the lcd display if anything changes */
        if (cTime->tm_min != minute) {
            minute = cTime->tm_min;
            print_lcd();
            
            /* Update time from NTP server if it's midnight UTC */
            if ((cTime->tm_min == 0) && (cTime->tm_hour == 0)) {
                Host server(IpAddr(), 123, "0.north-america.pool.ntp.org");
                ntp.setTime(server);
            }
        }
        
        /* Check to see if the alarm should be started/stopped */
        alarm_check();
    }
    return 0;
}


0 comments

You need to log in to post a comment