This program allows the user to set the time from the serial terminal on power on. Thereafter the clock will run as the real time clock. The user is able to set the alarm time using the joystick. Down button is used to increase the time and center button is used to set. The alarm will sound when the alarm time and actual time are equal. Right button of joystick is used to stop the alarm. The alarm will stop automatically after specified duration (hard coded) if the stop button is not pressed.

Dependencies:   C12832_lcd DebounceInterrupts mbed-rtos mbed USBDevice

GOAL:

To implement a simple alarm clock using MBED Application borad LPC1768.

USER CONTROLS

  • USB interface to set the clock initially. This is required only when the board is powered ON.
  • Joystick down button to increase the hrs/mins.
  • Joystick center button to toggle between hrs and min.
  • Joystick right button to stop the alarm.
  • LCD to display the actual time and the alarm time.

DETAILS

  • Thread compare_time is used to compare the actual time and the alarm time set by the user.
  • Thread update_lcd is used to display the actual time and the alarm time set by the user on the LCD.
  • Main thread is used to initiate threads to update LCD and thread to compare timings.
  • A ticker is used to update the actual time every second.

TESTING

  • User Level Testing
Test ItemDescriptionStatus
USB ConnectionVerify if the device is recognized as USB Serial Device even when connected to a USB hubPASS
Verify the set time is displayed on the LCDPASS
Set time updateVerify the Set time is updated every second.PASS
Setting the Alarm timeVerify the alarm time is getting updated on the LCD as the time increase button is pressedPASS
Sounding the AlarmVerify the alarm and the alarm LED (LED2)are turned ON when the actual time and the set time are equalPASS
Stopping the AlarmWhen the alarm is ON and the user presses the right button of the joystick the alarm should turn OFF and the Alarm LED LED2 should be OFF.PASS
If the User does not press the alarm stop button within a minute the alarm should turn OFFPASS
  • Product Level Testing
Test ItemDescriptionStatus
ProgrammingVerify mbed is detected as Mass Storage Device and is programmed by the hostPASS
USBVerify the power consumed by the USB device. Current drawn is 160mA. Power is 800mW.Satisfies the USB specification
Normal Working (After the time is set)After setting the time remove the USB.(Be sure to connect the external supply before removing the USB)The clock works satisfactorily on the external power supply.
Key DebounceVerify that there is no debounce on any of the joystick keys.PASS

Import programRTOS_Alarm_Clock

This program allows the user to set the time from the serial terminal on power on. Thereafter the clock will run as the real time clock. The user is able to set the alarm time using the joystick. Down button is used to increase the time and center button is used to set. The alarm will sound when the alarm time and actual time are equal. Right button of joystick is used to stop the alarm. The alarm will stop automatically after specified duration (hard coded) if the stop button is not pressed.

main.cpp

/*****************************************************************************/
/*      Main program for the implementation of RTOS_ALARM Clock              */
/*Function: To sound an alarm when the actual time is equal to alarm time    */
/*Features: USB access to set the time                                       */
/*          User can set the time with the joystick                          */
/*          Audio Visual alarm available                                     */
/*          Alarm turns OFF automaticaaly after 1 min if not turned OFF      */
/*Author:   Bhakti Kulkarni                                                  */
/*Date:     03/25/2014                                                       */
/*****************************************************************************/

#include "mbed.h"
#include "C12832_lcd.h"
#include "DebouncedIn.h"
#include "DebouncedInterrupt.h"
#include "rtos.h"
#include "USBSerial.h"

#define INTERRUPT
#define HR 1
#define MIN 0
#define DURATION 1
#define MAX_HRS 24
#define MAX_MINS 60
#define MAX_SECS 60

C12832_LCD lcd;
USBSerial serial;

DebouncedInterrupt increase(p12);                     //Switch to increase time
DebouncedInterrupt select(p14);         //Switch to toggle between hrs and mins
Mutex M_lcd;                            //Mutex for LCD
DebouncedIn stop_alarm(p16);            //Switch to stop the alarm
Ticker update_time;                     //Ticker to update actual time
DigitalOut wake_up(LED2);               //Visual alarm LED
PwmOut speaker(p26);                    //Speaker for audible alarm

/*Global variables for mins and hrs*/
int hrs;
int mins;
int hrs_set = MAX_HRS;
int mins_set = MAX_MINS;
int sec_set = 0;
bool selection= HR;            //Signal to indicate the hrs/mins to be changed

/*****************************************************************************/
/*                     ISR for increasing the time                           */
/*Function: This routine checks the value of selection signal.               */
/*          If selection value - HR it updates hrs and if selection = MIN    */
/*          it updates the minute value. It also checks for the maximum      */
/*          value of hrs and mins and reset appropriate variable             */
/*****************************************************************************/
void increase_time()
{
    if (selection == HR)
    { 
      if (hrs < MAX_HRS)
         hrs ++;
      else
         hrs = 0;
    }
    else
    {
        if (mins < MAX_MINS)
           mins ++;
         else{
           mins = 0;
           if (hrs < MAX_HRS)
            hrs++;
           else
             hrs = 0;
        }
     }
}
/*****************************************************************************/

/*****************************************************************************/
/*                          ISR to update selection                          */
/*Function: Allows the user to toggle between the hours and minutes          */
/*****************************************************************************/
void select_time()
{
    selection = !selection;
}
/*****************************************************************************/

/*****************************************************************************/
/*                        Thread to update LCD                               */
/*Function: This thread updates the LCD with the actual and the alarm time   */
/*****************************************************************************/
void update_lcd(void const *args)
{
    M_lcd.lock();                                       //Mutex to lock the LCD
    lcd.cls();
    lcd.locate(0,20);
    while(1) {
        lcd.cls();
        lcd.locate(0,0);
        lcd.printf("Actual-hh:mm:sec %02d:%02d:%02d",hrs_set,mins_set,sec_set);
        lcd.locate(0,10);
        lcd.printf("Alarm-hh:mm:sec %02d:%02d:%02d",hrs,mins,0);
        M_lcd.unlock();  
        Thread::wait(25);
    }
}
/*****************************************************************************/

/*****************************************************************************/
/*                   Ticker function to update the actual time               */
/*This function is called every second. It increments no. of seconds         */
/*Also checks for max secs, mins and hours and accordingly adjusts other     */
/*variables.                                                                 */
/*****************************************************************************/
void time_update()
{
    sec_set++;
    if (sec_set == MAX_MINS)
    {
        mins_set++;
        sec_set = 0;
    }
    if (mins_set == MAX_MINS)
    {
        hrs_set++;
        mins_set = 0;
    }
    if (hrs_set == MAX_HRS)
    {
        hrs_set = 0;
        mins_set = 0;
        sec_set = 0;
    }
}
/*****************************************************************************/

/*****************************************************************************/
/*                        Function to sound the alarm                        */
/*This function is called when the alarm time = actual time                  */
/*It sounds the alarm till alarm_stop button is pressed | 1 min is ellapsed  */
/*The variable frequency and beat rate of the PWM decide the tone of alarm   */
/*****************************************************************************/
void alarm_on()
{
    float frequency[]={659,554,659,554,440,494,554,587,494,659,554,440};
    float beat[]={1,1,1,1,1,0.5,0.5,1,1,1,1,2}; //beat array
    while (!stop_alarm && !(hrs_set == hrs && mins_set == mins+DURATION)) {
        wake_up = 1;
        for (int i=0;i<=11;i++) {
            speaker.period(1/(2*frequency[i])); // set PWM period
            speaker=0.5; // set duty cycle
            wait(0.4*beat[i]); // hold for beat period
        }
    }
    wake_up =0;                                       //Turn OFF visual alarm
    speaker = 0.0;                                     //Turn OFF audio alarm
}
/*****************************************************************************/

/*****************************************************************************/
/*                    Thread for time Comparison                             */
/*This thread comapres the actual and the alarm time and calls the alarm     */
/*function when both the timings are equal. It also reset the alarm time     */
/*after the alarm is turned OFF(either by user or after a minute is ellapsed)*/
/*****************************************************************************/
void sound_alarm(void const *args)
{
    while (true){
    if ((hrs == hrs_set && mins_set == mins && sec_set == 0) )
    {
        alarm_on();
        hrs = 0;
        mins = 0;
    }
    Thread::wait(50);
    }
}
/*****************************************************************************/

/*****************************************************************************/
/*                               Main Thread                                 */
/*Initializes all the threads and the USB inerface.                          */
/*This thread makes a blocking call to set the time. In this application     */
/*blocking call is used since the actual time is necessary parameter for the */
/*alarm clock. Without the time alarm clock has no function to do.           */
/*****************************************************************************/
int main() {
    char ch;
    increase.attach(&increase_time);
    select.attach(&select_time);
    Thread compare_time (sound_alarm,NULL,osPriorityAboveNormal);
    Thread lcd_display(update_lcd,NULL,  osPriorityAboveNormal);
    serial.printf("\r\n");
    serial.scanf("%c",&ch);
    serial.printf("Set the hours\r\n");
    do{
        serial.scanf("%d",&hrs_set);
        if (hrs_set > MAX_HRS)
            serial.printf("Enter Valid hours\r\n");
    }while (hrs_set > MAX_HRS);              //error checking for hours entered
    serial.printf("Set mins\r\n");
    do
    {
        serial.scanf("%d",&mins_set);
        if (mins_set > MAX_MINS)
            serial.printf("Enter Valid minutes\r\n");
    }while (mins_set > MAX_MINS);          //error checking for minutes entered
    update_time.attach(&time_update,1);
    while(1)
    {
        Thread::wait(1000);
    }
}

.

Committer:
bhakti08
Date:
Mon Mar 24 18:05:58 2014 +0000
Revision:
0:cdc96a6032be
Initial Creation of the rtos alarm clock

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bhakti08 0:cdc96a6032be 1 #include "DebouncedIn.h"
bhakti08 0:cdc96a6032be 2 #include "mbed.h"
bhakti08 0:cdc96a6032be 3
bhakti08 0:cdc96a6032be 4 /*
bhakti08 0:cdc96a6032be 5 * Constructor
bhakti08 0:cdc96a6032be 6 */
bhakti08 0:cdc96a6032be 7 DebouncedIn::DebouncedIn(PinName in)
bhakti08 0:cdc96a6032be 8 : _in(in) {
bhakti08 0:cdc96a6032be 9
bhakti08 0:cdc96a6032be 10 // reset all the flags and counters
bhakti08 0:cdc96a6032be 11 _samples = 0;
bhakti08 0:cdc96a6032be 12 _output = 0;
bhakti08 0:cdc96a6032be 13 _output_last = 0;
bhakti08 0:cdc96a6032be 14 _rising_flag = 0;
bhakti08 0:cdc96a6032be 15 _falling_flag = 0;
bhakti08 0:cdc96a6032be 16 _state_counter = 0;
bhakti08 0:cdc96a6032be 17
bhakti08 0:cdc96a6032be 18 // Attach ticker
bhakti08 0:cdc96a6032be 19 _ticker.attach(this, &DebouncedIn::_sample, 0.005);
bhakti08 0:cdc96a6032be 20 }
bhakti08 0:cdc96a6032be 21
bhakti08 0:cdc96a6032be 22 void DebouncedIn::_sample() {
bhakti08 0:cdc96a6032be 23
bhakti08 0:cdc96a6032be 24 // take a sample
bhakti08 0:cdc96a6032be 25 _samples = _samples >> 1; // shift left
bhakti08 0:cdc96a6032be 26
bhakti08 0:cdc96a6032be 27 if (_in) {
bhakti08 0:cdc96a6032be 28 _samples |= 0x80;
bhakti08 0:cdc96a6032be 29 }
bhakti08 0:cdc96a6032be 30
bhakti08 0:cdc96a6032be 31 // examine the sample window, look for steady state
bhakti08 0:cdc96a6032be 32 if (_samples == 0x00) {
bhakti08 0:cdc96a6032be 33 _output = 0;
bhakti08 0:cdc96a6032be 34 }
bhakti08 0:cdc96a6032be 35 else if (_samples == 0xFF) {
bhakti08 0:cdc96a6032be 36 _output = 1;
bhakti08 0:cdc96a6032be 37 }
bhakti08 0:cdc96a6032be 38
bhakti08 0:cdc96a6032be 39
bhakti08 0:cdc96a6032be 40 // Rising edge detection
bhakti08 0:cdc96a6032be 41 if ((_output == 1) && (_output_last == 0)) {
bhakti08 0:cdc96a6032be 42 _rising_flag++;
bhakti08 0:cdc96a6032be 43 _state_counter = 0;
bhakti08 0:cdc96a6032be 44 }
bhakti08 0:cdc96a6032be 45
bhakti08 0:cdc96a6032be 46 // Falling edge detection
bhakti08 0:cdc96a6032be 47 else if ((_output == 0) && (_output_last == 1)) {
bhakti08 0:cdc96a6032be 48 _falling_flag++;
bhakti08 0:cdc96a6032be 49 _state_counter = 0;
bhakti08 0:cdc96a6032be 50 }
bhakti08 0:cdc96a6032be 51
bhakti08 0:cdc96a6032be 52 // steady state
bhakti08 0:cdc96a6032be 53 else {
bhakti08 0:cdc96a6032be 54 _state_counter++;
bhakti08 0:cdc96a6032be 55 }
bhakti08 0:cdc96a6032be 56
bhakti08 0:cdc96a6032be 57 // update the output
bhakti08 0:cdc96a6032be 58 _output_last = _output;
bhakti08 0:cdc96a6032be 59
bhakti08 0:cdc96a6032be 60 }
bhakti08 0:cdc96a6032be 61
bhakti08 0:cdc96a6032be 62
bhakti08 0:cdc96a6032be 63
bhakti08 0:cdc96a6032be 64 // return number of rising edges
bhakti08 0:cdc96a6032be 65 int DebouncedIn::rising(void) {
bhakti08 0:cdc96a6032be 66 int return_value = _rising_flag;
bhakti08 0:cdc96a6032be 67 _rising_flag = 0;
bhakti08 0:cdc96a6032be 68 return(return_value);
bhakti08 0:cdc96a6032be 69 }
bhakti08 0:cdc96a6032be 70
bhakti08 0:cdc96a6032be 71 // return number of falling edges
bhakti08 0:cdc96a6032be 72 int DebouncedIn::falling(void) {
bhakti08 0:cdc96a6032be 73 int return_value = _falling_flag;
bhakti08 0:cdc96a6032be 74 _falling_flag = 0;
bhakti08 0:cdc96a6032be 75 return(return_value);
bhakti08 0:cdc96a6032be 76 }
bhakti08 0:cdc96a6032be 77
bhakti08 0:cdc96a6032be 78 // return number of ticsk we've bene steady for
bhakti08 0:cdc96a6032be 79 int DebouncedIn::steady(void) {
bhakti08 0:cdc96a6032be 80 return(_state_counter);
bhakti08 0:cdc96a6032be 81 }
bhakti08 0:cdc96a6032be 82
bhakti08 0:cdc96a6032be 83 // return the debounced status
bhakti08 0:cdc96a6032be 84 int DebouncedIn::read(void) {
bhakti08 0:cdc96a6032be 85 return(_output);
bhakti08 0:cdc96a6032be 86 }
bhakti08 0:cdc96a6032be 87
bhakti08 0:cdc96a6032be 88 // shorthand for read()
bhakti08 0:cdc96a6032be 89 DebouncedIn::operator int() {
bhakti08 0:cdc96a6032be 90 return read();
bhakti08 0:cdc96a6032be 91 }
bhakti08 0:cdc96a6032be 92
bhakti08 0:cdc96a6032be 93