Project Motivations and Abstract

Find yourself missing that 9am class or meeting because you hit that snooze button way too often? As college students, this is a daily predicament we face and is a common problem shared by working adults too. Oversleeping only adds to the daily stress of college by making our schedules even busier with the need to get in touch with teachers and get caught up on missed material. Research from health publications such as Everyday Health put forth several tips to boost daily productivity, of which are: making the snooze button harder to hit and getting out of bed to hit the alarm clock.

Well, be late no more for that morning class you’ve always dreaded with a system that incorporates all these principles! We present to you RunawayClock! an alarm clock system that runs away from you in real-time when the alarm sounds. Utilizing ultrasonic sensors, a car frame, a pushbutton, a buzzer, an LCD module and Bluetooth communication, the RunawayClock! makes hitting the snooze button a challenge. When the alarm rings, the device zips around on the floor and will back away from movement it senses, forcing the user to get out of bed and chase the device in order to turn it off. This unavoidable activity in the morning gets the user out of bed and moving in order to make the waking up process a one time ordeal.

The RunawayClock! system features 2 subsytems: Car Alarm / Evasion System, and Time Display / Alarm Setting System.

Marketing Viability of our Product

With a mature alarm clock market that has gained robust foundations through time, we needed to devise a product that revolutionized the way we wake up. The demand for alarm clocks is certain. In today's age where smartphones are ubiquitous, alarm clocks still find their existence in households for both practical and psychological reasons. Coupled with research in boosting productivity and techniques in waking up, we created a product that would tailor to details such as these while offering the functionality of an alarm clock. Users, be it college students, working adults, or just about anyone who has not yet attained the luxury of not needing to wake up, will find great use in our product. For future development purposes, we can carry out the production of the car frame in-house, such that the cost of our product can be minimized. Such cost savings can be passed on to consumers and even be useful when we intend to penetrate the market by setting a price lower than that of competitors.

Project Goals

Create an alarm clock that would solve the common problem of oversleeping traditional alarms. Make the snooze button less accessible and force the user to get out of bed and get moving in the morning in order to turn off the alarm.

Technical Details and Approach

Car Alarm / Evasion System

First, we worked on the subsystem of the ultrasonic sensors. To ensure these were working, we used basic ultrasonic sensor code from Arduino and modified it to work for four sensors. We then printed the distance reading from each sensor to the serial monitor so we could see if things were working. Once we got consistent readings from the sensors, we determined thresholds for the sensors which, when crossed, would set the motors of the Zumo shield into motion. In order to make this module avoid the user, we set up a series of conditional statements in the code so that the car would move opposite the user’s approach.

Time Display / Alarm Setting System (LCD)

Next, we built the other part of the project by attaching an LCD shield to another Arduino. This piece is the alarm clock base, which we used to display the time and set the alarm. We used the Time library of Arduino with a Processing program in order to sync the internet time of the computer to the Arduino. The time is displayed on the first row and the alarm time is displayed on the second row once both programs are running. In order to set off the alarm, we checked if the alarm time and the clock time were equal, and then sent a signal to the Arduino on the Zumo shield via Bluetooth. As we only wanted the alarm to be triggered once for each time the set alarm equaled the current time, we sent the one-character String “A” once. This ensured that the Boolean value used in the software to determine if the alarm should be going off or not would only change once until the alarm was turned off by the user.

Interfacing both Systems to make the RunawayClock!

Once we got the alarm to cooperate with the clock, we incorporated a pushbutton into the circuit on the Zumo car to act as an off button. Of course, an alarm clock would be useless without sound, so we also added a buzzer to the circuit. When the button is pressed, the Boolean value mentioned above is reverted to false, and the motors and buzzer turn off. The alarm can be set to a different time, and will go off without having to reset any of the hardware.

Our Accomplishments

Ultimately, we were able to achieve what we set out to do and created the RunawayClock! that truly ran away from the user when the alarm sounds. Although we encountered numerous challenges along the way, we did not compromise on any of the product features we had planned from the start.

Challenges Encountered

There were a few issues we struggled with over the course of this project. The wiring of the Car Alarm / Evasion System was challenging, as the breadboard on top became increasingly cluttered as we added more subsystems over time. We had to exercise caution when planning how the circuitry should be like, as the wires sometimes introduced too much tension with neighboring wires and caused connection breaks as we ran tests. Thus, by drawing out the entirety of the circuitry of our system, we resolved this issue by optimizing the placement of our subsystems. We also had a rather hard time with the Bluetooth setup simply because we found them to be unreliable for our project. We would often have to restart the receiver and transmitter in order to get the alarm to work, even if we hadn’t changed any software or hardware. As for the coding side, writing the programs for both of our systems was equally challenging in both cases, as we gave careful thought into the implementation of respective details. For instance, in our Time Display / Alarm Setting System, we designed the alarm setting function such that the seconds, minutes, and hours values will roll over appropriately as we increased the desired alarm time. For the alarm car, we were concerned with interfacing the ultrasonic sensors, Bluetooth, and car motors with our code, which proved far more challenging as we were ambitious in crafting the many cases of movement we wanted our product to feature.

Link to Promotional Video

https://youtu.be/IsMUTFTlkkE

Alternate Link to Final Video

https://www.dropbox.com/s/40nes3kcbaltigx/RunawayClock%20Final%20Video.mp4?dl=0

Code for Car Alarm / Evasion System

/* alarm_car_code.ino *   *  A program that waits for a signal from the alarm clock module via bluetooth *  If the certain signal is received, the buzzer makes noise and the car will move away from objects it detects with ultrasonic sensors *    *  */

#include <ZumoMotors.h>
#include <SoftwareSerial.h>

// create objects for Bluetooth serial and motors of Zumo shield
SoftwareSerial BTSerial(A3, A1); // TX RX
ZumoMotors motors;

int trigRear = 4; // attach every other pin except 0, 8, 10 (reserved by arduino or zumo shield) to trigs
int trigLeft = 6;
int trigRight = 12;
int trigFront = 2;
int echoRear = 5; //attach every other pin except 1, 7, 9 (reserved by arduino or zumo shield) to echos
int echoLeft = 11;
int echoRight = 13;
int echoFront = 3;

// set buzzer and button pins
int button = A0;
int buzzer = A4;

// boolean to tell alarm whether to go off or not
boolean alarmOn = false;

// establish variables for duration of the ping,
// and the distance result in cm:
long duration, distance, cmRear, cmFront, cmLeft, cmRight;


void setup() {

pinMode(button, INPUT);
pinMode(buzzer, OUTPUT);
BTSerial.begin(9600); // initialize Bluetooth communication
Serial.begin(9600);
Serial.print("Rear - Left - Right - Front");
Serial.println();

}

void loop()
{

  if (BTSerial.available()) {
    char inChar = (char) BTSerial.read();
    if (inChar == 'A') {
      Serial.println('A');
      alarmOn = true;
    }
  }


  if (digitalRead(button) == HIGH) {
    alarmOn = false;

  }

  // should the alarm be going off
  if (alarmOn == true) {

    // if so, set off buzzer
    tone(buzzer, 3000, 1000);

    // read distances from the four sensors
    SonarSensor(trigRear, echoRear);
    cmRear = distance;
    SonarSensor(trigLeft, echoLeft);
    cmLeft = distance;
    SonarSensor(trigRight, echoRight);
    cmRight = distance;
    SonarSensor(trigFront, echoFront);
    cmFront = distance;

    // check the cases and set the motor speeds accordingly
    if (cmRear < 50 && cmLeft < 50) {
      motors.setLeftSpeed(200);
      motors.setRightSpeed(300);
    }
    else if (cmRear < 50 && cmRight < 50) {
      motors.setLeftSpeed(300);
      motors.setRightSpeed(200);
    }
    else if (cmFront < 50 && cmLeft < 50) {
      motors.setLeftSpeed(-200);
      motors.setRightSpeed(-300);
    }
    else if (cmFront < 50 && cmRight < 50) {
      motors.setLeftSpeed(-300);
      motors.setRightSpeed(-200);
    }
    else if (cmRear < 50) {
      motors.setLeftSpeed(200);
      motors.setRightSpeed(200);
    }
    else if (cmRight < 50) {
      motors.setLeftSpeed(300);
      motors.setRightSpeed(500);
    }
    else if (cmLeft < 50) {
      motors.setRightSpeed(300);
      motors.setLeftSpeed(500);
    }
    else if (cmFront < 50) {
      motors.setLeftSpeed(-200);
      motors.setRightSpeed(-200);
    }
    else {
      motors.setLeftSpeed(30);
      motors.setRightSpeed(30);
    }
    Serial.print(cmRear);
    Serial.print(" - ");
    Serial.print(cmLeft);
    Serial.print(" - ");
    Serial.print(cmRight);
    Serial.print(" - ");
    Serial.print(cmFront);
    Serial.println();
    }
  else {
    motors.setLeftSpeed(0);
    motors.setRightSpeed(0);
  }
  delay(100);

}
void SonarSensor(int trig, int echo) {
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(trig, OUTPUT);
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(5);
digitalWrite(trig, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echo,INPUT);
duration = pulseIn(echo, HIGH);
distance = microsecondsToCentimeters(duration);

}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PI...
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

Code for Time Display / Alarm Setting System

/*  * AlarmClock_code.ino * code that uses TimeSerial code from Time library in conjunction with Bluetooth and LCD screen to make an alarm clock * When alarm time is the same as clock time, program sends a signal to alarm car via Bluetooth  * * Used in combination with a Processing program (SyncArduinoClock) to sync time on LCD to internet time of computer *  * Some of this code is adapted from the TimeSerial function of the Time library of Arduino.  */ 

#include <TimeLib.h>
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

#define TIME_HEADER  "T"   // Header tag for serial time sync message
#define TIME_REQUEST  7    // ASCII bell character requests a time sync message 

LiquidCrystal lcd(8,9,4,5,6,7);   // initalize the lcd
SoftwareSerial BTSerial(2,3);   //intialize the Bluetooth Serial for communication between 

// create strings which will be used to print times to LCD 
String hr;
String mint;
String sec;
String ahr;
String amint;
String asec;

// create integers to store the values of time for alarm
int hrAlarm;
int mintAlarm;
int secAlarm;

int readkey;    // int to store value received from A0
int j;        // counter variable for setting alarm
boolean setAlarm = false;   // boolean to check if user is setting alarm or not

void setup()  {
  BTSerial.begin(9600);
  Serial.begin(9600);
  while (!Serial) ; // Needed for Leonardo only
  pinMode(13, OUTPUT);
  setSyncProvider( requestSync);  //set function to call when sync required
  Serial.println("Waiting for sync message");
  lcd.begin(16, 2); // start the LCD
}

void loop(){

  readkey = analogRead(0); // check to see which button is being pressed based on varying input on A0
  if (readkey > 650 && readkey < 850) { //button select
    setAlarm = !setAlarm;   // turn alarm setting mode on/off
  }
  if (setAlarm == true) {     
    lcd.blink();    // blink so user knows the alarm can be set    
      readkey = analogRead(0);    // re-read A0 to determine 
      if (readkey < 50) { // button right
        if (j == 6) j = 0;
        j += 1;          
      }
      else if (readkey < 250) { //button up
        // check cases based on where the "cursor" would be
        if (j == 0) {
          hrAlarm += 10;          
        }
        else if (j == 1) {
          hrAlarm++;
        }
        else if (j == 2) {
          mintAlarm += 10;
        }
        else if(j == 3) {
          mintAlarm++;
        }
        else if(j == 4) {
          secAlarm += 10;
        }
        else {
          secAlarm++;
        }
      }
      else if (readkey < 450) { //button down
        // check cases based on where the "cursor" would be
        if (j == 0) {
          hrAlarm -= 10;          
        }
        else if (j == 1) {
          hrAlarm--;
        }
        else if (j == 2) {
          mintAlarm -= 10;
        }
        else if(j == 3) {
          mintAlarm--;
        }
        else if(j == 4) {
          secAlarm -= 10;
        }
        else {
          secAlarm--;
        }
      }
      else if (readkey < 650) { // button left
        if (j == -1) j = 5;
        j--;         
      }

  }
  else {
    lcd.noBlink(); // turn off blink to let user know the alarm isn't being set anymore
  }
  if (Serial.available()) {
    processSyncMessage();
  }
  if (timeStatus()!= timeNotSet) {
    digitalClockDisplay();  
  }
  if (timeStatus() == timeSet) {
    lcd.clear();
    // if the hours/minutes/seconds are in single digits, add a 0 in front for aesthetic reasons (00:00:00 vs 0:0:0)

    if (hour() < 10) {
      hr = "0" + (String) hour(); 
    }
    else {
      hr = (String) hour();
    }
    if (minute() < 10) {
      mint = "0" + (String) minute();
    }
    else {
      mint = (String) minute();
    }
    if (second() < 10) {
      sec = "0" + (String) second();
    }
    else {
      sec = (String) second();
    }
    // do the same for alarm values, but also ensure that going over 24 for hours and over 60 for minutes/seconds resets the counter to 0
    if (hrAlarm < 10) {
      ahr = "0" + (String) hrAlarm; 
    }
    else if (hrAlarm > 24) {
      ahr = "00";
      hrAlarm = 0;
    }
    else {
      ahr = (String) hrAlarm;
    }
    if (mintAlarm < 10) {
      amint = "0" + (String) mintAlarm;
    }
    else if (mintAlarm > 60) {
      amint = "00";
      mintAlarm = 0;
    }
    else {
      amint = (String) mintAlarm;
    }
    if (secAlarm < 10) {
      asec = "0" + (String) secAlarm;
    }
    else if (secAlarm > 60) {
      asec = "00";
      secAlarm = 0;
    }
    else {
      asec = (String) secAlarm;
    }
    // check to see if the alarm time is the same as the clock time
    if (hrAlarm == hour() && mintAlarm == minute() && secAlarm == second()) {
      // if the two times are equal, send the one-character String "A" over bluetooth
      BTSerial.println("A");
    }
    lcd.print("Time: " + hr + ":" + mint + ":" + sec);  // print time to screen
    lcd.setCursor(0, 1);    // go to the next line of the lcd screen
    lcd.print("Alarm: " + ahr + ":" + amint + ":" + asec);  // print the alarm time to screen
  } 
  delay(1000);
}

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(); 
}

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 processSyncMessage() {
  unsigned long pctime;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
       setTime(pctime); // Sync Arduino clock to the time received on the serial port
     }
  }
}

time_t requestSync()
{
  Serial.write(TIME_REQUEST);  
  return 0; // the time will be sent later in response to serial mesg
}

Supplementary Code for Time Display / Alarm Setting System

/**
 * SyncArduinoClock. 
 *
 * portIndex must be set to the port connected to the Arduino
 * 
 * The current time is sent in response to request message from Arduino 
 * or by clicking the display window 
 *
 * The time message is 11 ASCII text characters; a header (the letter 'T')
 * followed by the ten digit system time (unix time)
 */


import processing.serial.*;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;

public static final short portIndex = 0;  // select the com port, 0 is the first port
public static final String TIME_HEADER = "T"; //header for arduino serial time message 
public static final char TIME_REQUEST = 7;  // ASCII bell character 
public static final char LF = 10;     // ASCII linefeed
public static final char CR = 13;     // ASCII linefeed
Serial myPort;     // Create object from Serial class

void setup() {  
  size(200, 200);
  println(Serial.list());
  println(" Connecting to -> " + Serial.list()[portIndex]);
  myPort = new Serial(this,Serial.list()[portIndex], 9600);
  println(getTimeNow());
}

void draw()
{
  textSize(20);
  textAlign(CENTER);
  fill(0);
  text("Click to send\nTime Sync", 0, 75, 200, 175);
  if ( myPort.available() > 0) {  // If data is available,
    char val = char(myPort.read());         // read it and store it in val
    if(val == TIME_REQUEST){
       long t = getTimeNow();
       sendTimeMessage(TIME_HEADER, t);   
    }
    else
    { 
       if(val == LF)
           ; //igonore
       else if(val == CR)           
         println();
       else  
         print(val); // echo everying but time request
    }
  }  
}

void mousePressed() {  
  sendTimeMessage( TIME_HEADER, getTimeNow());   
}


void sendTimeMessage(String header, long time) {  
  String timeStr = String.valueOf(time);  
  myPort.write(header);  // send header and time to arduino
  myPort.write(timeStr); 
  myPort.write('\n');  
}

long getTimeNow(){
  // java time is in ms, we want secs    
  Date d = new Date();
  Calendar cal = new GregorianCalendar();
  long current = d.getTime()/1000;
  long timezone = cal.get(cal.ZONE_OFFSET)/1000;
  long daylight = cal.get(cal.DST_OFFSET)/1000;
  return current + timezone + daylight; 
}

Built With

Share this project:

Updates