3/4 view of the Glasses Wipe device. Shows main front interface with LCD and side with buzzer and wipe count reset button.
This device reminds Richard to clean his glasses in the mornings at either 9 or 10 am, based on what time button he presses. This device also starts a timer as he cleans his glasses to ensure he is cleaning them for long enough to remove all smudges. The time is started when he opens the lid of the box to grab a glasses wipe and goes off every time he opened the lid, regardless of time of day. This device also tracks when he is running low on glasses wipes, which will cause a light to turn on. When he restocks his wipes, he can reset the wipe counter.
Richard wakes up at 8:55 AM to get ready for the day. His glasses sit on his nightstand and he picks them up, heading to the bathroom to begin his morning routine. He puts his glasses on the counter and works through his morning routine a buzzing goes off on his Glasses Wipe Box device at 9 AM, reminding him to clean his glasses. He opens the lid and a 2-minute timer begins. He pulls out a wipe from the box and begins wiping. Because he is timed to wipe for 2 minutes, his glasses will be quite clean for the day. After the 2-minute timer is completed, he throws the wipe away. He notices that the low wipe indicator light has turned on, which means he should make sure he has a replacement box soon.
Richard brings home a box of wipes from the store a few days later. The next day is Saturday so he sets his morning reminder for 10 AM the night before. He goes to grab a wipe from his box Saturday morning and notices it is the last one. He cleans his glasses for 2 minutes as the timer goes, and when it ends he goes to check if he has new wipes. Thankfully, he remembered to buy a new box a few days ago because of the low wipe count light so now he replaces the wipes in the box and presses the wipe count reset button so that the device knows he has put in a new box of wipes.
Front view of device
Semi top view of device showing lid and interface
Up close view of LCD and front buttons.
Up close view of the buzzer and reset wipe count button
In this video, I show how the alarm time can be set. Once the alarm goes off, the box is then opened to grab a glasses wipe which begins a one minute timer to ensure enough time is spent on cleaning the pair of glasses.
In this video, I show how the alarm time can be changed by a press of the front two buttons, and how the wipe count can be reset by the press of a button located on the side of the box. In addition, the timer functionality is demonstrated when the box is opened to grab a glasses wipe from inside.
For this first prototype, we wanted to test the motion of opening the box with a lid. This option takes up less counter space as it opens up but we were unsure if this motion was comfortable for Richard. Additionally, we are testing a lower LCD placement in this version with the button panel in front (not shown in this photo but we made one button panel that we could move around to ask Richard if he wanted the interface on the front/side/top).
With this prototype, we wanted to test the drawer/pulling motion and the higher placement of the buttons. The movable button panel is in this photo; we showed it to Richard on the top and side of this box. We also wanted to test a higher LCD placement to see if higher is better for when he is standing at his counter.
With this part we wanted to test if having the drawer in this open shape would have the wipes more accessible and visible. Later we realized that Richard would prefer to keep the wipes in the original box so this open shape would not have done much.
Unfortunately we didn't get a video of Richard testing the prototypes, but pictured below are moments from the interview.
We showed Richard our devices to give him an idea of how the final device might work electronically and then tested each of our cardboard prototypes (not pictured here). From this interview, we decided to go with the first prototype and got an idea what kinds of parts and functions we should include.
Going in to the meeting with Richard, we all somewhat prefered the prototype featuring the drawer mechanism and higher interface. To us, it seemed easier and the arrangement of the button interface and LCD seemed like it would offer a more comfortable way to interact with the device and also a more nuanced form. However, when we were actually discussing with Richard he expressed his interest in prioritizing ease and simplicity above all. He also mentioned that the sliding drawer mechanic required him to pull the full weight of the wipe box as opposed to simply flipping a lid. All this lead us to pursue the simpler box design in future iterations. In addition to our prototypes, we also asked Richard what type of part he'd like to use (buttons of various sizes vs. switches). Although it was pointed out to us that switched would've simplified the process by allowing him to toggle between options, Richard stated his preference for buttons as it required less force so we went in that direction instead. Finally, we offered Richard the option to simply dump the wipes into the box, but he said he usually keeps the wipes stored inside their original box so, not wanting to interrupt his routine, we opted to construct the box around the form of the original container the lens wipes arrive in.
Initial breadboard testing of the proximity sensor. We started our with breadboarding all our electrical components.
The graveyard of 4 failed box iterations. Issues arose with fitting electronics into holes or amount of space left by inner walls that hide the electronics, so we are very glad we decided to start physical fabrication very early!
We wanted to hide the wiring of electronic components inside the box since the wipes would also be inside the box. This is the inner wall that would cover the back of the LCD. In this iterations we did not leave enough space for the LCD to fit well, so we ended up remaking the fusion model.
We had a panel running across the whole box so we could hide the bulk of the electronic components underneath.
We accidentally put the LCD upside down, but this was an easy fix! We had much bigger issues with poor connections on the LCD so we ended up soldering to the LCD and using screw pins on the ardunio.
laying out all of our soldered electronic components with our final box iteration (with hinges installed).
Some of our main struggles with the process were the physical aspects. As mentioned above, we had several iterations of the laser-cut box. Part of this was because we had to make sure everything was labelled and fit into the proper places. Sometimes there wasn't enough space to fit the LCD, or too much room for buttons, etc. Exporting the dxf files between Fusion, Illustrator, and CorelDraw was also a little challenging to maintain the proper scaling, making sure the text and holes were properly vectorized/rasterized, and everything fit together correctly. As far as the wiring, we had a few little errors along the way with the IR proximity sensore breaking (twice), falsely advertized momentary push buttons that were actually latching, and faulty connectuons to the LCD. However, we eventually got everything to work together which left us with the challenge of fitting all the hardware into the physical form. This was a difficult and delicate process, but eventually we were able to bring the project together!
Major Critques
During the final crit, people mostly liked the fabrication fidelity of our device and understood why certain things were created the way they were, especially after we explained Richard's preferences. We also received some insightful suggestions and concerns:
"Can the times on your device be adjusted for daylight savings?"
Almost every crit group brought up this concern, which shows the importance of having feedback because no one in our team ever thought of this throughout this whole process. Since we are using the Realtime clock library, we aren't entirely sure if the library itself accounts for daylight savings, but if it doesn't, this is definitely something we should be accounting for in the future. One possible way we could do this is to simply have a switch for daylight savings that Richard can flip when it starts or ends.
What if Richard wants to clean his glasses elsewhere? Can you make this portable?
This is a very valid concern in most cases and definitely something we could explore in next steps! After our multiple interviews/meetings with Richard he's told us and shown us that he is organized in his life and his schedules, so he felt that the device just in his bathroom would be fine. Since he goes to the bathroom everyday to do his morning routine, having this device stay in the bathroom will work as a reminder as he always goes to the bathroom in the morning. Additionally, he told us that he always keeps his wipes in the original packaging which is a box of 75 and quite large, so it would be challenging to make anything of that size portable.
Having just a light indicator for low wipe count doesn't really provide a lot of information, you could use something like a progress bar instead.
We liked this suggestion and it’s something we would want to explore in next steps. Just having a low wipes light does feel intangible and black-boxy so a progress bar would do a lot better in showing the gradual decrease while also being vague enough to account for possible counting errors. We never wanted to provide a remaining wipes count because we didn’t want to be off by a few wipes, but a progress bar also doesn’t have to be too specific!
The sound stopping by itself after a few seconds may not be an effective reminder by itself, you could have something that stays on until he opens the box in order to remind him even if he misses the alarm.
This is also a great suggestion, as requiring an action from Richard to end a reminder is much more effective than our device ending the reminder itself. We thought about this in our initial ideations but thought having two lights could be confusing, however, if we label and arrange the interface well, adding the reminder light would be useful!
Working with Richard, Takeaways/What to differently
Working with Richard was a great experience and it was surprising how difficult it was for us to find a problem in his life to address during the initial stages of our project. Richard has a very active and enriched life, and even regarding more physical actions, he seems to be very competent in almost all day-to-day motions so the problem we ended up addressing was not even related to his physical disability at all. Even though it was hard for us to find a problem space, it was really cool to see how independent and thriving he was at a relatively young age and he even started giving us job/internship advice during our first interview!
Richard was very clear with us about what he wanted so our process was quite smooth after we landed on an idea within our project scope, so there isn’t much we would do differently in the fabrication/prototyping process. If we could redo the first interview, we would try to scope our project a bit better to him initially so we would not have needed a second interview, but the second interview was also a great opportunity to show him our lab space and what we were working with.
// Richard's Glasses Wipe Box
// Team Peanuts - Kyla, Jennie, Cody
// The following code is used to remind Richard to clean his glasses each morning and keeps track of the remaining number of wipes in his box.
// When the box is opened, the counter subtracts from the number of wipes and a 1 minute timer begins to help Richard clean his glasses for a sufficient amount of time.
// In addition, the box has an LED that will light up when the number of wipes reaches a critical level, to remind Richard to replace his wipes box soon.
// Pins Used: Function:
// 6 Wired to an LED to illuminate when wipes count is low
// 9 Wired to a buzzer for alarm sound
// 11 Wired to a button to set alarm time
// 12 Wired to a button to set another alarm time
// 13 Wired to a button to reset wipes count
//Libraries were used for the buzzer, LCD, and Real-Time Clock
#include <toneAC.h> // for Buzzer
#include <Wire.h> // for I2C communication
#include <LiquidCrystal_I2C.h> // for LCD
#include <RTClib.h> // for RTC
LiquidCrystal_I2C lcd(0x27, 16, 2); // create LCD with I2C address 0x27, 16 characters per line, 2 lines
RTC_DS3231 rtc; // create rtc for the DS3231 RTC module, address is fixed at 0x68
const int timePin1 = 11; //Button pin used for Setting Time 1
const int timePin2 = 12; //Button pin used for Setting Time 2
const int resetWipes = 13; //Button pin used to reset wipes
const int redLED = 6; //Pin to control "Low Wipes" indicator
const int buzzer1 = 9; //Pin to control Buzzer
int currentWipes = 75;
int wipesCount = 75; //Number of Wipes per box
int alarmHour = 9; //Default Alarm Time
int alarmMinute = 0;
int buzzerTime = 3; //Time that the alarm goes off for
float previousVoltage = 0;
/*
function to update RTC time using user input
*/
void updateRTC() {
lcd.clear(); // clear LCD display
lcd.setCursor(0, 0);
lcd.print("Edit Mode...");
// ask user to enter new date and time
const char txt[6][15] = { "year [4-digit]", "month [1~12]", "day [1~31]",
"hours [0~23]", "minutes [0~59]", "seconds [0~59]" };
String str = "";
long newDate[6];
while (Serial.available()) {
Serial.read(); // clear serial buffer
}
for (int i = 0; i < 6; i++) {
Serial.print("Enter ");
Serial.print(txt[i]);
Serial.print(": ");
while (!Serial.available()) {
; // wait for user input
}
str = Serial.readString(); // read user input
newDate[i] = str.toInt(); // convert user input to number and save to array
Serial.println(newDate[i]); // show user input
}
// update RTC
rtc.adjust(DateTime(newDate[0], newDate[1], newDate[2], newDate[3], newDate[4], newDate[5]));
Serial.println("RTC Updated!");
}
/*
function to update LCD text
*/
void updateLCD() {
// get time and date from RTC and save in variables
DateTime rtcTime = rtc.now();
int ss = rtcTime.second();
int mm = rtcTime.minute();
int hh = rtcTime.twelveHour();
int DD = rtcTime.dayOfTheWeek();
int dd = rtcTime.day();
int MM = rtcTime.month();
int yyyy = rtcTime.year();
// move LCD cursor to upper-left position
lcd.setCursor(0, 0);
lcd.print("Alarm Time:");
if (alarmHour < 10) {
lcd.print(" ");
}
lcd.print(alarmHour);
lcd.print(":");
lcd.print("0");
lcd.print(alarmMinute);
// move LCD cursor to lower-left position
lcd.setCursor(0, 1);
// print time in 12H format
if (hh < 10) lcd.print("0");
// if current time is alarm time, activate buzzer
if (!rtcTime.isPM()) {
if (hh == alarmHour) {
if (mm == alarmMinute) {
if (ss < buzzerTime) {
toneAC(2500, 9);
} else {
toneAC(0);
}
}
}
}
lcd.print(hh);
lcd.print(':');
if (mm < 10) lcd.print("0");
lcd.print(mm);
lcd.print(':');
if (ss < 10) lcd.print("0");
lcd.print(ss);
if (rtcTime.isPM()) lcd.print(" PM"); // print AM/PM indication
else lcd.print(" AM");
}
void setup() {
Serial.begin(9600); // initialize serial
lcd.init(); // initialize lcd
lcd.backlight(); // switch-on lcd backlight
rtc.begin(); // initialize rtc
pinMode(timePin1, INPUT_PULLUP);
pinMode(timePin2, INPUT_PULLUP);
pinMode(resetWipes, INPUT_PULLUP);
pinMode(redLED, OUTPUT);
}
void loop() {
updateLCD(); // update LCD text
if (Serial.available()) {
char input = Serial.read();
if (input == 'u') updateRTC(); // update RTC time
}
//Time buttons
if (digitalRead(timePin1) == LOW) {
alarmHour = 9;
alarmMinute = 0;
}
if (digitalRead(timePin2) == LOW) {
alarmHour = 10;
alarmMinute = 0;
}
//if resest button pressed, reset wipe counter
if (digitalRead(resetWipes) == LOW) {
wipesCount = 75;
}
//if low on wipes, red LED on
if (wipesCount <= 15) {
digitalWrite(redLED, HIGH);
} else {
digitalWrite(redLED, LOW);
}
// if proximity is triggered, wipes count -1, 1 minute timer starts
currentWipes = wipesCount;
checkProximity();
//If box isn't already open, start timer
if (currentWipes != wipesCount) {
startTimer();
toneAC(2500, 9);
delay(2000);
toneAC(0);
}
}
//Checks to see if box is opened from a closed state
void checkProximity() {
int sensorValue = analogRead(A0);
//convert analog read to voltage
float voltage = sensorValue * (5.0 / 1023.0);
if (voltage >= 4) {
if (previousVoltage == 0) { //Checks to see if box was closed before being opened
wipesCount--;
previousVoltage = voltage;
}
} else {
previousVoltage = 0;
}
}
//One Minute Timer to Clean Glasses
void startTimer() {
lcd.clear();
int s = 0;
while (s < 60) {
lcd.setCursor(6, 0);
lcd.print("0");
lcd.print(':');
if (s < 10) {
lcd.print("0");
lcd.print(s);
} else {
lcd.print(s);
}
delay(1000);
s++;
}
}