To-Do Timer

A large cardboard box, with a small LCD screen at the bottom, displaying numbers for times and alarms. a large Post It note is up near the top, between a speaker and three LEDs. On the right side, a red, a blue, and a yellow knob can be seen; on the right, a cord coming out of the box.

A top view of the device- the Post Its on the top are meant for the user to indicate their own To-Dos. The switches and knobs can be seen on the right side of the device, while at the back left the charging cord can be seen.

Description

This project helps me do small but important tasks on time- think doing the laundry, signing up for shifts for the next workweek, getting some work started for a long term project. Three timers can run at a time, and are set by turning knobs and started by flipping switches.

A large cardboard box, with "To Do" etched into it on the top, below which is a sheaf of Post Its for the user to write their To-Do's onto. On the left of the PostIts are three LEDs, on the right is a speaker. Further down, an LCD screen depicts three different times and alarms for the three different lights; these correspond to a set of knobs on the right side of the box. Below the LCD is a small post-it explaining how to read the LCD screen.

Here is the final project as a whole! The three knobs on the side each manage a corresponding time and alarm, and when the alarm runs out, trigger the speaker and associated LED across from the knob. The toggleable switches cannot be seen, but are underneath the knobs.

This image depicts the side of the box; there are three knobs, in red, blue, and yellow, above three toggleable switches. Post it notes to the left of them explain their use- the knobs change the times, while the switches start the timer.

The important side of the project- these knobs and levers are the only real way to interact with the timers. They correspond with the ones vertically next to them, and that line can be continued over the box to see which lights they turn on, too.

The side of the box with knobs and switches on it is displayed- someone is in the process of turning the yellow knob.

To change the times for any of the timers, you would need to turn one of the knobs- for example, changing the first alarm time would be done by turning the red knob; the yellow knob being turned in the picture changes the third timer.

The side of the box with knobs and switches is displayed- someone has just finished toggling the switch below the yellow knob to the 'on' position, their hand still on the switch.

After setting the time to the correct number of hours by turning the knob, it would then be necessary to flip the switch directly beneath it to the on position. Doing so would cause the timer to start counting down.

GusToDoTimer.MOV

In this video, I show how each knob can be turned to change the time displayed on the LCD and change what the alarm is set to; then, I show how flipping the switch starts the countdown (and how when the countdown hits 0, a light turns on and the speaker makes a beeping noise.) 

Process

An Arduino Uno attached to a breadboard, which is connecting both an LCD screen that is displaying "Wednesday" and "15:25:13". Behind the LCD, a Real Time Clock module can be seen plugged in.

This image is from the first attempt at wiring; it used the RTC to successfully upload the date and time of day to the Arduino, which connected it to the LCD screen. At this point I was just trying to make the RTC keep time correctly, and had not yet started on the timers.

An Arduino Uno is attached to a breadboard that further connects to three potentiometers and three togglable switches, which each lie around the nest of wires. An LCD Screen depicts the date, time, and time and alarms for three different alarms.

This image is after I had gotten the circuits working- It was not yet ready to be put into a case, but the LCD shows the date, time, and time and alarms for all three timers. 

A prototype of the case- Taped together rather than glued, I made this to try and determine whether the current holes I had installed would work or if I needed to remake them. After this process, I moved several of the holes around and remade several to be circular.

The inside of a half-built box, several holes in the cardboard are open, while nearer the base, one is filled with an LED, another has an LCD screen set into it. Against the right wall, a switch and a potentiometer are slotted into holes as well.

A view from the opposite side of the box of the previous picture- no wiring had been set up here, this was just trying to examine if the prototype would be able to hold all of the wiring and electronic hardware I needed to put in.

A partially built box made of cardboard can be seen with a pair of wires attached to one wall, while the top of the box and the two unattached sides can be seen lying nearby on the table. The top has a screwed on LCD screen and a circular hole with a speaker under it.

Here, I had started the process of putting together the final project- The charging cord, speaker, and the LCD screen are all attached, with the speaker taped on and the LCD and the charger both screwed on. This step was in preparation to fitting the wiring into the case for the device.

Process

Although I couldn't show it in the images, easily the most challenging piece of this project was working out how to use the Real Time Clock Module. Over the course of the prototyping and as I worked on designing my code and wiring, I tried several different RTC libraries before ultimately settling on the NeiroN Real Time Clock module library, which I found easiest to use. Further difficulties came in working out how to set the alarm- I decided to, so long as the switch was in the off position, repeatedly 'kick the can' down the road and reset the alarm to the current time plus x seconds multiplied by 36,000, the number of seconds in an hour.

Although my original plan was to attempt to use if-then statements or otherwise work with delaying some amount of time, it rapidly became clear that this could not work in a device that used multiple different alarms; and furthermore, the if-then statements rapidly became too complex to realistically work.

Discussion

When I started this project, my plan was to create a device that could store and run several different timers simultaneously, that I could set independently. My original plan included an LCD to list the To-Dos, as well as to show time remaining and to say at what time and day the timer would run out. As I went through the process of ideation, however, parts of this necessarily had to change. I went through several steps on figuring out how to set and change the alarms, I realized what limited space I had on the LCD screen and reduced what it would show to just depicting the alarm times and how much was left before they went off. Overall, I think that I succeeded in the spirit of what I was hoping to achieve, even though I didn't hit the exact target I aimed for.

Seeing as the end result does work as intended, I don't think I am likely to build a second iteration any time soon- but If I were, I would start with the wiring so that I could build the final box around it and be sure that everything would fit well. The final box design was very difficult for me- I did it last, which was necessary as precisely how the device worked changed several times, so it would not have been possible to build a casing first. However, doing so made it harder to fit everything into the box as I needed to . I learned a lot in this project about organizing my code, though; I started out with pretty kludgy code all over the page, but when with my professor's help it was cleaned up, I found it much easier to make important edits. However, I also discovered my limitations when trying to find a library I could use to manage the RTC; finding and understanding new libraries is not a strength of mine.

In the final critique, the general consensus is that the box worked well- the cardboard box and sticky notes were determined to be good choices, described as  "very cute," and a "brilliant design choice with sticky notes" that would "make me get work done for sure." I too have really come to enjoy the aesthetic of the cardboard box with sticky notes; it fits the concept of the final project well, and gives off the right feeling for a small, desk-situated to do list and timer. Another oft-repeated suggestion was to "make a way on the box to change the timers from hours to minutes, and back again to make for more versatility." I think this is a great idea; at present moment, I don't know how I might implement that, but were I to eventually make a second iteration I would definitely add some sort of button that could be pressed to toggle the hours/minutes mode on and off. Lastly, several people suggested "color coding the knobs and switches to the lights," advice which I was able to take immediately, and installed color coded knob caps over the potentiometers.

Technical information

/*


To-Do Timer


Takes in the turning of a potentiometer to set a time and the toggling of a switch to start a timer, which is done using a Real-Time Clock module and displayed on an LCD screen.


Code written for an Arduino Uno circuit board.


pin mapping:


Arduino pin | role | description

___________________________________________________________________

A0 input Reads potentiometer 1 value

A1 input Reads potentiometer 2 value

A2 input Reads potentiometer 3 value

4 input Reads switch 1 value

5 input Reads switch 2 value

6 input Reads switch 3 value

7 output turns on and off speaker

8 output Turns on and off LED 1

9 output Turns on and off LED 2

10 output Turns on and off LED 3

Code released to the public domain by the author, 03/22/2024

Gus Gamble, amgamble@andrew.cmu.edu


*/


//This section introduces libraries and sets up all the pins and longs/variables the rest of the code will be using, as well as starting the serial so that if attached to the computer, the values can be examined

//

#include <RTClib.h>

#include <Time.h>

DS3231 rtc;


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C screen(0x27, 20, 4);




char buf[20];


long alarm1 = 0;

long alarm2 = 0;

long alarm3 = 0;

long countdown1 = 0;

long countdown2 = 0;

long countdown3 = 0;

DateTime now;


unsigned long nextScreenUpdate;

const unsigned long screenUpdateInterval = 1000;


const int LIGHT1PIN = 8;

const int LIGHT2PIN = 9;

const int LIGHT3PIN = 10;


const int POT1PIN = A0;

const int POT2PIN = A1;

const int POT3PIN = A2;


const int TOGGLE1PIN = 4;

const int TOGGLE2PIN = 5;

const int TOGGLE3PIN = 6;


const int SPEAKERPIN = 7;


void setup() {

  Wire.begin();

  rtc.begin();

  now = rtc.now();


  screen.init();

  screen.backlight();

  screen.home();


  pinMode(POT1PIN, INPUT);

  pinMode(POT2PIN, INPUT);

  pinMode(POT3PIN, INPUT);


  pinMode(TOGGLE1PIN, INPUT);

  pinMode(TOGGLE2PIN, INPUT);

  pinMode(TOGGLE3PIN, INPUT);


  Serial.begin(9600);


  pinMode(LIGHT1PIN, OUTPUT);

  pinMode(LIGHT2PIN, OUTPUT);

  pinMode(LIGHT3PIN, OUTPUT);


  pinMode(SPEAKERPIN, OUTPUT);

}


void loop() {

//sets time value

  now = rtc.now();

//turns potentiometer values into 1-96 values, to represent hours

  int pot1Val = analogRead(POT1PIN);

  int time1 = map(pot1Val, 25, 1020, 1, 96);

  int pot2Val = analogRead(POT2PIN);

  int time2 = map(pot2Val, 25, 1020, 1, 96);

  int pot3Val = analogRead(POT3PIN);

  int time3 = map(pot3Val, 25, 1020, 1, 96);

//checks the switches

  int toggle1Val = digitalRead(TOGGLE1PIN);

  int toggle2Val = digitalRead(TOGGLE2PIN);

  int toggle3Val = digitalRead(TOGGLE3PIN);

//The actual work of the alarm- if the switch is off, the alarm1 time can be set by turning the potentiometer

//once the switch is on, the alrm1 time remains static

//when the current unix time is more than or equal to the alarm1 time, the alarm goes off

//each timer works the same way

//for a shorter timer, in order to test, comment out the *36000L- this will set the alarm time in seconds, rather than hours

  Serial.print(toggle1Val);

  if (toggle1Val == 0) {

    alarm1 = now.unixtime() + (time1*36000L);

  }

  if (now.unixtime() >= alarm1) {

    digitalWrite(LIGHT1PIN, HIGH);

    tone(7, 1500, 100);

  } else {

    digitalWrite(LIGHT1PIN, LOW);

  }


  if (alarm1 >= now.unixtime()) {

    countdown1 = (alarm1 - (now.unixtime() / 36000.0L));

  } else {

    countdown1 = 0;

  }


  Serial.print(toggle2Val);

  if (toggle2Val == 0) {

    alarm2 = now.unixtime() + (time2 * 36000L);

  }

  if (now.unixtime() >= alarm2) {

    digitalWrite(LIGHT2PIN, HIGH);

    tone(7, 1500, 100);

  } else {

    digitalWrite(LIGHT2PIN, LOW);

  }


  if (alarm2 >= now.unixtime()) {

    countdown2 = (alarm2 - now.unixtime()) / 36000.0L;

  } else {

    countdown2 = 0;

  }


  Serial.print(toggle3Val);

  if (toggle3Val == 0) {

    alarm3 = now.unixtime() + (time3) * 36000L;

  }

  if (now.unixtime() >= alarm3) {

    digitalWrite(LIGHT3PIN, HIGH);

    tone(7, 1500, 100);

  } else {

    digitalWrite(LIGHT3PIN, LOW);

  }


  if (alarm3 >= now.unixtime()) {

    countdown3 = (alarm3 - now.unixtime()) / 36000L;

  } else {

    countdown3 = 0;

  }




  if (millis() >= nextScreenUpdate) {

//writes to serial monitor

    Serial.println(now.tostr(buf));

    Serial.print("Unix Epoch time: ");

    Serial.println(now.unixtime());

    Serial.print("Time 1: ");

    Serial.println(time1);

    Serial.print("alarm1:");

    Serial.println(alarm1);

    Serial.print("Time 2: ");

    Serial.println(time2);

    Serial.print("alarm2:");

    Serial.println(alarm2);

    Serial.print("Time 3: ");

    Serial.println(time3);

    Serial.print("alarm3:");

    Serial.println(alarm3);

    Serial.println(now.tostr(buf));

//writes to LCD

    screen.clear();

    screen.setCursor(0, 0);

    screen.print("T1:");

    screen.print(time1);

    screen.print(" Alarm1:");

    screen.print(countdown1);

    screen.setCursor(0, 1);

    screen.print("T2:");

    screen.print(time2);

    screen.print(" Alarm2:");

    screen.print(countdown2);

    screen.setCursor(0, 2);

    screen.print("T3:");

    screen.print(time3);

    screen.print(" Alarm3:");

    screen.print(countdown3);

    screen.setCursor(0, 3);

    nextScreenUpdate += screenUpdateInterval;

  }

  delay(20);

}