My assistive device is an alarm clock that requires the user to aim a nerf gun to a target attached to the clock to stop the alarm.

 

GIF of the project working at times x4 (I used my finger instead of the nerf gun to stop the alarm but it is the same mechanism)

I couldn’t attach the original video due to file size so I will attach a link: https://youtu.be/Qz9fStl4Iwg

Overview photo

 

Detail 1 of the wiring seen from the outside through the acrylic walls

Detail 2 of the buttons used to operate the clock and a buzzer on the right side wall

Detail 3 of the clock working as the claimed time matches the actual time (+ a close up of the LED at the center top)

Photo aiming at the target

Photo going through the target! (Bullseye!)

Process Images and Review

These are my initial ideation sketch of the project:

Sketch 1 of ideation

Sketch 2 of ideation

And this is a prototype cardboard version of the alarm box that I made:

Box Prototype made before making the laser cut acrylic body

My first decision point was when I started with four momentary buttons to set and control the alarm and the time. Of the four, two buttons increased and decreased the input numbers.

Using four momentary buttons for control

Although it was fine on the breadboard for the demonstration during the prototype stage, as I thought about putting four big buttons on a small container, I thought it made more sense that I convert the two + and – buttons to a single potentiometer. The time range was mapped to the potentiometer and that way it did not require holding down multiple buttons at once.

Another decision point was when I decided to make a moving target instead of a static one. I attached the target to a motor that moves between 0 to 90 degrees back and forth.

A failed attempt at getting the motor working with the clock (the motor works separately though)

However, when I was trying to combine my two codes together I realized that because my motor code involved multiple “delay” code, the time would stop to rotate the target and resume again, which does not make a very useful clock. Although, I know how to fix this problem because we learned how to create a timer system using millis() instead of using multiple delay()s, I just could not finish editing the code in time.

Discussion

After the critique, I noticed that I received a lot of comment regarding how to confirm my state of consciousness. One of the comments I received during the critique was to make some variation in the alarm sound in order to avoid my brain from gradually dismissing the same sound. I believed that this addition could be a great next step of the project. Because I originally planned on having a moving target, maybe I could have a set of tunes and the target will move differently everyday in sync with the tune. Although that sound quite challenging, I believe this addition would definitely wake me up.

Another comment mentioned having to hit a target twice with some gap in between the first hit and the second hit. This feature I feel like is more feasible because inside the alarm setting function I just need to make it also go off a minute afterwards. Although I don’t think I should add both features at once because then I would have to be a pro shooter, I think it would be interesting to have different “modes” and I could maybe choose between either of them depending on the occasion.

In self-reflection, I am satisfied with how the project turned out because my goal was to just make it work, and it works! Well, sort of. It has its flaws–like the motor not working properly–and I wouldn’t say it is too user friendly either because it requires both hands and you need to keep your fingers pressed; however, my main personal goal was to have the big components working and making this image in my head come true in the real world, so during the given time I believe I did the best I could and it looks quite pretty too, so I am happy. 🙂

During the process, I feel like I already knew my limitations from the start. Wiring the parts together I could sort out by looking at the diagrams and past circuits we made in class but the actual coding was my biggest pain.

I only have very rudimentary coding knowledge so a lot of my code was done with the help of the internet, which I cited. Therefore, most of the time I was trying to understand the different dynamics of the code and incorporate IR sensors into the system. Because my alarm clock already had a “kill”  condition where if it senses the kill button being pressed it turns off the alarm, I did not think it would be difficult replacing that condition with the IR sensor reading “broken”.

However, I came across a surprising obstacle: even if the Arduino reads the broken sensor the alarm will still go on because the time would still be the same. As in, if the timer was set to 20:00 and it goes off at 20:00 I would hit the bullseye at 20:00:15 and it would read the “broken” sensor but still buzz on because a full minute has not passed. I don’t think it would not have been a problem if I could also set the seconds. Eventually, the problem was fixed by creating a boolean variable and more dedicated functions.

On the other hand, I enjoyed piecing the parts of the physical box together. Although I got a lot of help from Zach to make the fusion file, I enjoyed screwing in little tiny screws perfectly into the cut holes on the acrylic board. It was a nice rest between the hard coding and struggles to actually get the system working.

As stressful as it was, it was also enjoyable to make because I have been thinking about this sort of odd house furniture for a while, so I definitely want to build another iteration of this project. As I mentioned in the beginning, I want to include different modes of alarm where I can choose in between settings to give myself a variety in waking myself up. Hopefully in the 2.0 version, I would get the motor working, and I also want to give the alarm some life and make it print out “:> you failed!” or “∠( ᐛ 」∠)_ are you awake now?” messages as the alarm is going off.

Technical information

Block Diagram (motor included)

 

Schematic (motor included)

/*
  Title: Shoot! What time is it?
  Creator: Sarah Yun
  This is a code for an assistive device, which is an alarm clock using a RTC that requires the user to aim a nerf gun to a target attached to the clock to stop the alarm by shooting in between two IR sensors to break their connection.

  Pin mapping:
  Digital-
  ~3 : servo motor
  ~6 : Hour button
  ~9 : Min button
  ~10 : buzzer
  13 : LED
  Analog-
  A0 : potentiometer
  A4 : SDA (lcd, rtc)
  A5 : SCL (lcd, rtc)

  >>resources/credit
  1. Alarm_Clock by Tittiamo (Tiziano Bianchettin): https://create.arduino.cc/projecthub/tittiamo68/alarm-clock-f61bad
  2. IR Breakbeam Sensors: https://learn.adafruit.com/ir-breakbeam-sensors/arduino
  3. RTC: https://create.arduino.cc/projecthub/MisterBotBreak/how-to-use-a-real-time-clock-module-ds3231-bc90fe
  4. potentiometer: https://docs.arduino.cc/built-in-examples/basics/AnalogReadSerial
  5. Zach's coding hint for boolean variable and reference to https://www.ict.ru.ac.za/resources/thinksharply/thinksharply/conditionals.html

*/
//------------------------------------------
//************libraries**************//
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

//************************************//
LiquidCrystal_I2C lcd(0x27, 20, 4); // Display  I2C 20 x 4
RTC_DS1307 RTC;

//************Button*****************//
int P1 = 6; // Button SET MENU'
int P2 = 9; // SWITCH Alarm

//**************Alarm***************//
#define SENSORPIN 4 //IR
#define buzzer 10 //goes off
#define LED 13 //goes on
#define pot A0 //+ and -

//************Variables**************//
int hourupg;
int minupg;
int yearupg;
int monthupg;
int dayupg;
int menu = 0;
int setAll = 0;
int sensorState = 0, lastState = 0;
int timeH;
int timeM;
int potVal = 0;
uint8_t alarmHours = 0, alarmMinutes = 0;
bool alarmOn = false;
float count = 0;


void setup() {
  lcd.init();
  lcd.backlight();
  lcd.clear();
  pinMode(pot, INPUT);
  pinMode(SENSORPIN, INPUT);
  digitalWrite(SENSORPIN, HIGH);

  pinMode(P1, INPUT_PULLUP);
  pinMode(P2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  pinMode(buzzer, OUTPUT);
  printAllOff();
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();

  //****check if clock is working****//
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__)); // Set the date and time at compile time
  }

  RTC.adjust(DateTime(__DATE__, __TIME__)); //resets time
  int menu = 0;
  count = 0;
}

void loop() {
  sensorState = digitalRead(SENSORPIN);

  if (digitalRead(P1) == LOW) {
    menu = menu + 1;
  }
  if ((digitalRead(P1) == LOW) && (digitalRead(P2) == LOW)) {
    DisplaySetHourAll();
    DisplaySetMinuteAll();
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print("ALARM");
    lcd.setCursor(5, 1);
    lcd.print(alarmHours, DEC);
    lcd.print(":");
    lcd.print(alarmMinutes, DEC);
    delay(1000);
    lcd.clear();
  }
  if (menu == 0) {
    DisplayDateTime();
    checkTime();
    Alarm();
  }
  if (menu == 1) {
    StoreAgg();
    delay(500);
    menu = 0;
  }
  if (menu == 2) {
    DisplayEnd();
  }

  delay(100);
  lastState = sensorState;
  Serial.println(count);
}

//****current time****//
void DisplayDateTime () {
  //time
  DateTime now = RTC.now();
  lcd.setCursor(0, 2);
  lcd.print("Time : ");
  if (now.hour() <= 9) {
    lcd.print("0");
  }
  lcd.print(now.hour(), DEC);
  hourupg = now.hour();
  lcd.print(":");
  if (now.minute() <= 9) {
    lcd.print("0");
  }
  lcd.print(now.minute(), DEC);
  minupg = now.minute();
  lcd.print(":");
  if (now.second() <= 9) {
    lcd.print("0");
  }
  lcd.print(now.second(), DEC);

  //date
  lcd.setCursor(0, 1);
  lcd.print("Date : ");
  if (now.month() <= 9) {
    lcd.print("0");
  }
  lcd.print(now.month(), DEC);
  monthupg = now.month();
  lcd.print("/");
  if (now.day() <= 9)
  {
    lcd.print("0");
  }
  lcd.print(now.day(), DEC);
  dayupg = now.day();
  lcd.print("/");
  lcd.print(now.year(), DEC);
  yearupg = now.year();

  //day
  char DOW[][10] = {"Sunday   ", "Monday   ", "Tuesday  ", "Wednesday", "Thursday ", "Friday   ", "Saturday "};
  lcd.setCursor(0, 0);
  lcd.print("Day  : ");
  lcd.print(DOW[now.dayOfTheWeek()]);
}

//****Variable saving****//
void StoreAgg() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SAVING IN");
  lcd.setCursor(0, 1);
  lcd.print("PROGRESS");
  RTC.adjust(DateTime(yearupg, monthupg, dayupg, hourupg, minupg, 0));
  delay(200);
}

// Setting the alarm minutes
void DisplaySetHourAll() {
  while (digitalRead(P1) == LOW) {
    Serial.println("Displayset Hour is happening!");
    lcd.clear();
    potVal = analogRead(pot);
    timeH = map(potVal, 0, 1023, 0, 24);
    alarmHours = timeH;

    lcd.setCursor(0, 0);
    lcd.print("Set HOUR Alarm:");
    lcd.setCursor(0, 1);
    lcd.print(alarmHours, DEC);
    delay(200);
  }
  delay(200);
}

void DisplaySetMinuteAll() {
  while (digitalRead(P2) == LOW) {
    lcd.clear();
    potVal = analogRead(pot);
    timeM = map(potVal, 0, 1023, 0, 60);
    alarmMinutes = timeM;

    lcd.setCursor(0, 0);
    lcd.print("Set MIN. Alarm:");
    lcd.setCursor(0, 1);
    lcd.print(alarmMinutes, DEC);
    delay(200);
  }
  delay(200);
}

void DisplayEnd() {
  lcd.clear();
  lcd.setCursor(1, 1);
  lcd.print("'HEY, YOU UP NOW?'");
  //  lcd.setCursor(9, 2);
  //  lcd.print("_ .");
  lcd.setCursor(7, 2);
  lcd.print("|'w')?");
  delay(200);
}

//****Alarm On****//
void printAllOn() {
  Serial.println("print all on on");
  lcd.setCursor(0, 3);
  lcd.print("Alarm: ");
  if (alarmHours <= 9) {
    lcd.print("0");
  }
  lcd.print(alarmHours, DEC);
  lcd.print(":");
  if (alarmMinutes <= 9) {
    lcd.print("0");
  }
  lcd.print(alarmMinutes, DEC);
}

//****Alarm Off****//
void printAllOff() {
  lcd.setCursor(0, 3);
  lcd.print("Alarm: Off  ");
}

void checkTime() {
  printAllOn();
  DateTime now = RTC.now();
  if ((!sensorState && lastState))  {
    Serial.println("broken");
    alarmOn = false;
    count += 0.25;
  }
  else if (now.hour() == alarmHours && now.minute() == alarmMinutes &&  (count < 0.25)) {
    alarmOn = true;
  }
  if (digitalRead(P2) == LOW) {
    count = 0;
  }


}

void Alarm() {
  if (alarmOn == true) {
    lcd.noBacklight();
    DateTime now = RTC.now();
    digitalWrite(LED, HIGH);
    tone(buzzer, 880); //play the note "A5" (LA5)
    delay (300);
    tone(buzzer, 698); //play the note "F6" (FA5)
    lcd.backlight();
  }
  else if (alarmOn == false) {
    noTone (buzzer);
    digitalWrite(LED, LOW);
  }

}