Introduction: Rise and Shine! - Arduino LDR Alarm Clock

This instructable was created in fulfillment of the project requirement of the MakeCourse at the University of South Florida (www.makecourse.com).

Theory of Operation

This alarm clock is designed to let you rise with the sun. When the light from outside is detected by our photo-resistor, it will then activate a servo, with a hammer attached to it. The hammer will turn 60 degrees and strike the bell twice to wake you up.

On the off chance that it is a gloomy and cloudy morning, the Arduino Code will calculate a sunrise time based on your latitude and longitude. If there is no light detected and it is 10 minutes past the calculated sunrise time, the Arduino will then set off the alarm (triggering the servo to hit the bell).

The LCD monitor can also display any message of your choice when the alarm is going off.

Step 1: Materials Needed

  • Arduino Uno
  • Jumper Wires
  • Long sized Breadboard
  • Micro Servo Motor (https://www.adafruit.com/product/169)
  • Servo Attachments
  • A photoresistor (referred to as an LDR, a light dependent resistor)
  • A bell that can be mounted (I bought mine on Amazon for $9.99 http://www.amazon.com/Wheel-Brass-Handbell-Dinner-...)
  • A 3-D Printed Hammer
    • You're welcome to use any hammer, however, I designed mine in AutoDesk Inventor as part of my project requirements. I have attached the .stl file below if anyone else would like to use it in their projects! I just printed it white and painted it with regular acrylic paint!
  • LCD (This project was made using an LCD with a YwRobot Arduino LCM1602 IIC V1 module)
  • DS1307 RTC (http://www.amazon.com/JBtek%C2%AE-DS1307-AT24C32-m...)
    (Normally these don't come with pins soldered on, so you will have to do the soldering** if you get the same one I did)
    • Soldering Iron **Only if you have to!**
    • Header Pins **Only if you have to!**
  • Super Glue
  • Electrical Tape
  • Enclosure box with screws

Step 2: Wiring / Circuit Setup

Above is a Fritzing diagram I have made to more clearly portray the circuit setup, it is quite simple and straightforward.

  • Servo to pin 9
  • LDR to pin A0 with a 10k ohm Resistor
  • GND to GND
  • Power to 5V

The following four pins must be connected using the two I2C ports on the Arduino, you must also add a 10k ohm resistor to each.

  • RTC- SDA to A4
  • RTC- SCL to A5
  • LCD- SDA to A4
  • LCD- SCL to A5

Step 3: Software: Libraries

The following links will take you to the .zip file with the source code:

Arduino Code In addition to the code ("sketch" in Arduino parlance) you will also need to install the following libraries (links provided below):

Time https://github.com/PaulStoffregen/Time

TimeLord http://www.swfltek.com/arduino/timelord.html

Wire http://arduino.cc/en/reference/wire (Probably already installed by default)

DS1307RTC http://www.pjrc.com/teensy/td_libs_DS1307RTC.html

LiquidCrystal_I2C (This library to be used with LCD with a YwRobot Arduino LCM1602 IIC V1 module attached. I have also included this library in a file below.)

Step 4: Software: Setting Up the RTC

Now, before we can use the RTC (real time clock), we need to set its time. We can do this manually using the example sketch provided in the DS1307RTC library (File --> Examples --> DS1307RTC --> SetTime). I would recommend running this sketch first simply because it would help you get accurate readings and give you a good starting point!

Step 5: Software: the Code

/************************************************************************************************************
 * Sunrise Alarm Clock by Bhavika Shah                              MakeCourse Spring 2016
 * 
 * When the LDR detects the sunrise, it will cause the servo(hammer attached) to turn 50 degrees
 * and hit a bell, as a wake up alarm. As a backup the code will calculate the sunrise time for the location 
 * of the clock using latitude and longitude coordinates, and activate the alarm in case there is no sunrise 
 * detected. This project also includes an RTC module that will keep time in case of power outage.
 ***********************************************************************************************************/
#include <Wire.h>
#include <Servo.h>
#include <TimeLib.h>                          //works in conjunction with DS1307RTC.h
#include <TimeLord.h>                         //contains sunrise calculations
#include <DS1307RTC.h>                        //RTC library
#include <LiquidCrystal_I2C.h>                //library to be used with LCD with a YwRobot Arduino LCM1602 IIC V1 module attached
#define DS1307_ADDRESS 0x68                   //RTC address
LiquidCrystal_I2C lcd(0x27,20,4); //Set the LCD address to 0x27 for a 16 chars and 2 line display Servo myservo; //Make a servo object int pos = 50; //Setting a servo position at 50 degrees int lightPin = A0; //Connect LDR to pin A0 int threshold = 500; //You set the light threshold to a value const int TIMEZONE = -5; //Set your time zone; mine is EST const float LATITUDE = 27.9506; //Set your latitude and longitude; mine are for Tampa, FL const float LONGITUDE = -82.4572; int wake = 0; // bool flag = 1; //Here, we have a boolean flag that will change when we perform our wakeup actions int sunriseMin; //minute of that days calculated sunrise to be used for comparison</p><p>void setup(){ void digitalClockDisplay(); //digital clock display of the time void printDigits(); //utility function for digital clock display: prints preceding colon and leading 0 void sunriseCalc(); //calculate sunrise void actionAM(); //function to perform wake up actions void checkPM(); //for debugging void lowLight(); //function to display sensor value if it is less than the threshold Serial.begin(9600); //begin serial communcation pinMode(13, OUTPUT); myservo.attach(9); //servo attached to pin 9 lcd.init(); //initialise the lcd lcd.backlight(); //turning on the LCD backlight setSyncProvider(RTC.get); //function to get the time from the RTC if(timeStatus()!= timeSet){ Serial.println("Unable to sync with the RTC"); } else { Serial.println("RTC has set the system time"); digitalClockDisplay(); } sunriseCalc(); }</p><p>void loop(){ if(wake = 0){ if (isAM()){ Serial.println("isAM true"); wake = 1; //if it's morning 'wake' will change from 0 to 1 flag = 0; //we will also change the flag variable to 0 Serial.println("First if is running"); //debugging Serial.print("flag: "); //for debugging Serial.println(flag); //for debugging } } if(wake = 1 && flag == 0) { //Because wake is 1, and flag is 0 , and we can begin light detection digitalClockDisplay(); //consistent readout of the the current time flag = 1; //We will change flag to 1 because the wakeup actions are being performed Serial.println(analogRead(lightPin)); //readout of the current light being detected if(analogRead(lightPin) > threshold){ //if the light detected is greater than our threshold: actionAM(); //perform wake up actions Serial.println("Second if is running"); //debugging } else{ flag = 0; printDigits(minute()); //debugging Serial.println(); //If no light is detected to perform wake up actions, we will check to see if current time has not passed sunriseMin + 10 if (sunriseMin < minute()){ //if the current minute value is greater than the sunrise minute value actionAM(); //perform wake up actions flag = 1; Serial.println("sunrise min is lower than current min"); //debug to let us know that the loop has gone through this statement } lowLight(); //if there is no light, we will check } delay(1000); } if (isPM()){ checkPM(); } } /**************************************************** FUNCTIONS ****************************************************/ void sunriseCalc(){ TimeLord tardis; tardis.TimeZone(-4 * 60); // tell TimeLord what timezone your RTC is synchronized to. You can ignore DST tardis.Position( LATITUDE, LONGITUDE ); // tell TimeLord where in the world we are byte today[] = { 0, 0, 12, 6, 4, 2016 }; // store today's date (at noon) in an array for TimeLord to use if (tardis.SunRise(today)){ // if the sun will rise today (it might not, in the [ant]arctic) Serial.print("Sunrise: "); Serial.print((int) today[tl_hour]); Serial.print(":"); Serial.print((int) today[tl_minute]); Serial.print(" AM"); Serial.println(); sunriseMin = (int) today[tl_minute] + 10; //storing the value of the sunrise time + 10 Serial.print("sunriseMin: "); Serial.println(sunriseMin); } } void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print("/"); Serial.print(month()); Serial.print("/"); Serial.print(year()); Serial.println(); delay(200); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } void actionAM(){ //function that contains all actions to be performed when it is time to get up! digitalWrite(13, HIGH); //turns the onboard LED on Serial.println("High"); //we print the status of the amount of light detected lcd.setCursor(3,0); //setting the cursor position lcd.print("Wake up Bee"); //printing a wake up message! lcd.setCursor(2,1); lcd.print("It's Sunrise!"); lcd.setCursor(0,2); //servo actions for (pos = 0; pos <= 50; pos += 1) { // goes from 0 degrees to 50 degrees in steps of 1 degree myservo.write(pos); delay(5); } for (pos = 50; pos >= 0; pos -= 1) { // goes from 50 degrees to 0 degrees myservo.write(pos); delay(5); } for (pos = 0; pos <= 50; pos += 1) { //0--->50 repeat myservo.write(pos); delay(5); } for (pos = 50; pos >= 0; pos -= 1) { //50--->0 repeat myservo.write(pos); delay(5); } } void checkPM(){ //function that returns a statement on the serial monitor if it is PM; used for debugging lcd.noDisplay(); //turning off the display on the LCD to conserve power Serial.println("isPM() True"); digitalClockDisplay(); Serial.println(analogRead(lightPin)); //readout of the current light being detected delay(1000); } void lowLight(){ //if the light detected is less than the threshold, we will print it on the serial monitor to keep track of it Serial.println(analogRead(lightPin)); //readout of the current light being detected digitalWrite(13, LOW); Serial.println("Low"); myservo.write(0); //return servo to 0 degrees }

Step 6: Setting Up!

To ensure that my project followed guidelines, I was given an enclosure box that you see in the photos. I had to hide all of my wiring in there.

For the power supply, I drilled a hole on the side of my enclosure box (as shown in the first photo), and kept widening it until my power supply cable fit through just perfectly.

Secondly, for the LDR, I drilled a small hold on the top panel so that the LDR may receive the most amount of sunlight (shown in the second photo)

I then measured the insides of the enclosure box, so that I could laser cut a lid for it out of Birch wood. I chose to laser cut because I wanted the holes for my servo motor head and the LCD to be absolutely perfect (third - fourth photos).

After that, I mounted by bell to the top of the lid, making sure that the bolt I was using didn't affect any of the internal components. I have also attached a photo of the internal components.

Step 7: Credits and Final Video!

Attached is my final video for my project! Please feel free to leave any comments, questions or suggestions for improvement! (There is always room for improvement!)

-------------------------------------------------------------------------------------------------------------------------------------------------

The Arduino open-source platform leverages the work of many talented developers that contribute libraries and example code. I've used code from many sources in this project and would like to credit them here (my apologies in advance if I forgot anyone):

- The "Timelord" library http://www.swfltek.com/arduino/timelord.html was crucial for sunrise/sunset calculations

- Jack Christensen's excellent high-tech night light article was a source of many of the ideas in the code: http://adventuresinarduinoland.blogspot.com/2012/...

- The fascinating Arduino chicken coup project: http://adventuresinarduinoland.blogspot.com/2012/...

-Dr. Rudy Schlaf and Dr. Michael Celestin from University of South Florida's Engineering Department, for the support, knowledge and continuous encouragement!

And everyone who contributes to the wonderful Arduino world!

First Time Author Contest 2016

Runner Up in the
First Time Author Contest 2016

Sensors Contest 2016

Runner Up in the
Sensors Contest 2016

3D Printing Contest 2016

Participated in the
3D Printing Contest 2016