[tutorial] AlarmClock

AlarmClock Tutorial from codebender on Vimeo.

This is a tutorial on how to build an alarm clock. This alarm clock will have its basis on an LCD Keypad shield and a DS1307 Real Time Clock module.

project_zps835c09c9

So… an alarm clock. This is the schematic.

schematic_zpse07cf686

Now, what do we want from a alarm clock? Well, we want it to show date and time, that’s what the RTC module offers. Then we want an alarm, and the ability to turn the alarm on and off, set the alarm time, see the alarm time, and have a snooze function. That’s basically it.

So, we want a device that has to process and maintain information, as well as handle its hardware. It has to do quite a few things and manage to coordinate them in real time.

I tried to start from here and build the clock. The steps I had to go through were to get the data from the RTC module, display them on the LCD screen, and look for user input for which I’d like to have an immediate response. But we can’t just throw these inside a loop and get done. There are hardware restrictions, like the refresh rate of the LCD screen. There are also logical considerations, like that there is no need to update time more frequent than once per second. Also, we can’t pause the Arduino and wait for a second, since we expect user input at any time. And then try to add menus and let the user navigate, and blah blah blah… you get the idea. Things can get really complicated very quickly, and that’s when you start doing all sorts of hacks and tricks to make the clock appear functional. I did that myself as an experiment and the result was at the very least poor.

So, what do we do? We have to stop, before we put our hands on the keyboard, and think about the problem at a higher level. We have to somehow organize things, view the problem as a system, anticipate and design appropriately.

And this is the result of such a process… a state diagram.

fsm_zps1b423811

Our clock has to do various things. We’ll try to divide those into categories that we will call states. When the clock is in a state, it does something specific… its operation is well defined. And then we expect things to happen that will change the state of the system and cause it to do something different.

To sum up, we have a system that can be in different states, and then we have events that make the system transition to another state.

So, we sit down, we think about the problem, and we come up with something like the diagram above. Let’s look at what this diagram says.

We start at the show time state. Here, the date and time appear on the screen. By pressing the RIGHT button, we change state, the alarm turns on and also an ALARM indication appears on the screen. By pressing the RIGHT button again, we turn off the alarm and move back to the show time state. From either the show time or the show time alarm on state, by pressing the LEFT button, we move on to the show alarm time state whose operation is self explanatory. After 3 seconds, a time out occurs, and we go back to the state we came from. From the same two states, by pressing the SELECT button, we transfer to the set alarm hours state where we get to set the hours part of the alarm time. If we don’t press any of the UP or DOWN buttons within 5 seconds, a time out happens and the process cancels. If we press the SELECT button, we move on to set the minutes part of the alarm time. Again, after 5 seconds of inactivity the process cancels. If we hit SELECT, the alarm time gets updated, the alarm turns on, and we go to the show time alarm on state. From that state, if the alarm time has come, we transition to the buzzer on state where a buzzer starts ringing. From there, if we hit either UP or DOWN, the buzzer turns off, 10 minutes are added to the alarm time, and we move back to the show time alarm on state. On the other hand, if we hit SELECT or LEFT, the buzzer goes off along with the alarm setting, and we transfer back to the show time state. Any button, at any state, that’s not mentioned, has no effect on the states of the system.

And we are done. Now, we put this diagram beside us and start coding.

There are two main parts in this implementation. The loop function where the current state is recognized and the proper function is called to handle whatever needs to be done, and then we check for button presses and if a valid button is pressed, a state transition is performed. The second part is the transition function that gets an event and performs the appropriate state transition along with any necessary variable updates. This is the control part of the system. The rest of the functions handle the hardware. You can watch an example of the alarm’s performance in the video.

So, this is it. We start from a diagram and we end up with an implementation. But the very best part of this approach, and the beauty of it, is that the system is totally expandable with minor or zero code changes. You can add any features you want to the current design, and you won’t have to worry a bit about what the rest of the implementation does.

Finally, there is one more issue that is out of the specification. This is the setting of the current date and time. If you need to set the date and time on the RTC module, uncomment line 96 in the code, upload the example to your Arduino, then comment the line back, and upload the code again. Now, the time is saved on the RTC module that is backed with a battery, and even if the power goes down and later the Arduino resets, you won’t have to set the time again… the RTC module will keep running.

RTCRAMRead example


One last bonus note. The code makes use of the RTClib library from Jeelab. This library doesn’t support a neat feature there is on the DS1307 RTC module. This is the 56 byte RAM. So next, follows an example that demonstrates how to interface this RAM space. Read the example’s description for more details.

That’s all folks. We hope you enjoy this project, and if you have any comments or suggestions you can contact us at girder [at] codebender [dot] cc


Sounds are from freesound.org. Schematics were based on Fritzing.

22 Comments

  1. Priya Rai

    26 Feb 2016 10:57:00

    Hi Nick

    This is an excellent project as I’ve set it up and it works well. I wish to extend the function of the program so that 15 minutes before the alarm sounds that a LED will illuminate. Would you be able to help me with coding this?

    • Nick Lamprianidis

      27 Feb 2016 14:33:29

      Hi,

      This shouldn’t be too difficult. You just have to set the time at which the led turns on and then check if that time is met. The simplest way to do this is to create a functionality that is dependent on the alarm, so that you don’t modify the state machine.

      • At the end of the setAlarmMinutes function, inside the if ( !timeOut ) { ... } control block, do the necessary computation to create the ledHours:ledMinutes time.
      • Then, at the beginning of the checkAlarmTime function, check if the time is met, if ( now.hour() == ledHours && now.minute() == ledMinutes ) digitalWrite(LED, HIGH);.
      • At last, inside the transition function, at the BUZZER_ON case, inside the second if block, add digitalWrite(LED, LOW);.

      I hope this helps,
      Nick

  2. Gill

    02 Mar 2016 09:21:13

    hi Nick
    this is a very helpful project but could be this done using arduino uno and I want to do this in a breadboard instead of PIC could you help me doa schematic for this thanks in advance

  3. Gabriel Belo

    04 Apr 2016 07:35:26

    Hello,
    How could be this changed, to have also separate days for alarm?
    Like one time alarm, weekdays alarm.

    Thank you!

  4. Gerhard

    09 May 2016 14:12:31

    How difficult would it be to a days to this sketch with multiple alarms, for different days?

    • Nick Lamprianidis

      09 May 2016 21:28:11

      It wouldn’t be that hard. You’d have to add one more state before “set alarm hour” to pick the day, and later also check for the day when checking the alarm time.

  5. Viorel

    10 May 2016 13:27:18

    Hello!
    How do I can set the clock and date?
    Thank you.

  6. WAN FARHANAH BINTI WAN ENGAH A13MB0209

    12 May 2016 05:52:37

    hello!why I cant download the lcdkeypad library?

    • Nick Lamprianidis

      14 May 2016 18:41:57

      Here is the page for the lcdkeypad library.

      • WAN FARHANAH BINTI WAN ENGAH A13MB0209

        17 May 2016 04:06:01

        hye nick! I have downloaded the library lcd keypad. when I run your coding, my push buttons were not same as yours since the value of each button is different. ex: your buttonSELECT become my buttonLEFT. I cant change the value at LCD KEYPAD library, since it has error compiling of Arduino board. can u help me?

  7. Juho

    12 May 2016 11:57:10

    Hello,

    How difficult would it be to modify this code for a DIY Keypad shield and to use a I2C 8×2 LCD?

    Having in mind that I don’t have much experience in coding but I do understand some of it. Writing however is a different matter.

    Thanks

    • Nick Lamprianidis

      14 May 2016 18:56:20

      If you don’t have experience, I wouldn’t recommend building your own keypad. At this point, it’s best to find a standard solution and then study how it works.
      You can connect any keypad and lcd you like. The good thing about using standard products is that they normally come with libraries that make it easy to use them without knowing how they actually work.
      All you would have to do is replace the libraries I am currently using and call the appropriate functions from those libraries, wherever necessary in the code. It shouldn’t be that hard since you won’t be modifying the logic of the program.

      • Juho

        17 May 2016 11:21:05

        The keypad you are using is fairly simple. Just a couple of switches with resistors to form a voltage divider for the ADC. The display on the shield is also generic. The schematic for it is also available and building a DIY version is not rocket science. I have built one and tested all the parts. The button ADC values are exactly as specified in the LCDKeypad library.

        However I can’t seem to get this code working. I have used all the correct (hopefully!) libraries you have referenced here, though there seems to be a ton of different LiquidCrystal libraries i have found surfing the web. Atmel Studio is happy with the code,

        but the screen is blank. If I press select i will occasionally see some strange characters. The lcd is fine since i’m able to print text to the lcd but in your code the lcd turns blank when it is supposed to start showing the date and time… I see that the display is trying to do something but i can’t make it out. The contrast is set to max.

        At the moment i’m using a 8×2 parallel display.

        • Nick Lamprianidis

          20 May 2016 13:22:30

          The LiquidCrystal library is the usual one that’s present in the standard arduino libraries.

          Please look at the constructor of the LCDKeypad class, here. It creates an instance of the LiquidCrystal class. Make sure that the pins you are using match the pins that appear in the library.

  8. Oliver

    18 May 2016 05:43:23

    Hi Nick, when I use your code, it is shown that ‘class DateTime’ has no member named ‘dayOfWeek’, what does this mean and how can I fix it? Thanks.

    • Juho

      18 May 2016 11:02:34

      I ran in to the same issue. Sometimes Arduino IDE let me compile it and sometimes it didn’t. It helped if I deleted the contents of my Temp folder in AppData. Then I was able to compile it in a few cases… it seems that this function doesn’t exist in the RTClib library, instead there is a reference to “dayOfTheWeek()” in that library… I compiled it both with the newest Arduino IDE and also Atmel Studio 7 without any issues when I changed the function name. Whether it works or not, I can’t tell, since I wasn’t able to see anything on my LCD using that code.

      • KIT

        20 May 2016 21:57:00

        I´ve had the same problem, and others following,
        I only had the rtclib.h
        after I´ve downloaded rtclib.zip unzipped and put it to the libraries folder
        wow, it works

    • Nick Lamprianidis

      20 May 2016 13:17:51

      The function at line 192 has changed from dayOfWeek to dayOfTheWeek. So, please make this change in your code. I’ll update the example soon.

      • KIT

        20 May 2016 22:25:46

        (aduino 1.6.8)
        with the rtclib folder( incl RTClib.cpp (and others)) it works with dayOfWeek
        before I tried it with dayOfTheWeek, it doesn´t !

        https://github.com/adafruit/RTClib

        I am very new in Arduino programming,but now I get it working

  9. Pooja Rao

    18 Sep 2016 12:56:20

    Hi Nick, the 3rd pin of my shield is not available for use so I tried using the 2nd pin. As soon as I dumped the code on the board, the buzzer was continuously buzzing even when there was no alarm. I can’t figure out what to do.

    • Nick Lamprianidis

      19 Sep 2016 22:13:23

      Hi Pooja. You need to use a PWM pin and update the #define BUZZER_PIN 3 line such that it has the number of the pin you chose. For the available PWM pins on your board, please consult the manufacturer’s page. For example, Arduino UNO supports PWM on pins 3, 5, 6, 9, 10, and 11. Please take care not to choose one of the pins used by the LCD.

  10. Jestina

    24 Oct 2016 08:01:06

    Hi,
    I tried implementing this circuit. But as soon as I connect the buzzer to the arduino (to pin 3), it keeps beeping even though I haven’t set an alarm

Leave a Comment

Stay tuned:

* we promise that we won´t spam you, never.