Overview
For the final project, we have created an assistive device for our client, Don, who works in carpenting for the campus housing. To understand and support Don's work, we started with interviewing him regarding his day to day work as well as some of the routines that he has. Through interview, we have pin down an idea of building a device that will allow him to place on any surface and warn people about on going construction that he is working on.
This device is a small wooden sign that our client (Don) can hang on a door to communicate their status to anyone who approaches. The client selects one of three messages using buttons on the front — "Work in Progress", "Come Back in 5 Minutes/30 Minutes/2 Hours", or "Do Not Disturb", and the sign displays the message on a small screen accompanied by a colored LED strip. When someone walks up to the door, the sign automatically lights up, and the buzzer beeps to draw their attention to the message. When no one is nearby, the screen turns off to save power.
Front view of the completed device. The LCD screen sits at the top, three red panel-mount buttons in the middle allow the user to select status messages, and the PIR motion sensor at the bottom detects when someone approaches.
Side view of the device showing the LED strip mounted along the edge. The strip lights up in red, blue, or green depending on which status message is currently selected.
Back view of the device showing the perfboard with soldered electronics, a suction cup for attaching to smooth door surfaces, and the battery pack that powers the device.
Upper left view of the completed device. The boards sits at the top with hollow back for sound echoing, the suction cup holder that allows it to be slide in and out, and the a battery pack that allows the device to be turned on and off.
Front view of the completed device with power turned on next to a ruler showing size and proportion.
Back view of the complete device with power turned on next to a ruler showing size and proportion.
Demonstration of the three status buttons. Pressing the first button displays “Work in Progress” with a red LED strip. The second button cycles through time options with a blue LED strip. The third button displays “Do Not Disturb” with a green LED strip.
The second button cycles through three time options with each press: “Come back in 5 minutes”, "Come back in 30 minutes", and "Come back in 2 hours". allowing the worker to communicate a more specific return time.
When a student approaches the device, the PIR motion sensor detects their presence and automatically wakes the screen and LED strip, displaying the current status message. The screen turns off again after 10 seconds of no motion.
Don arrives at a female student's dorm room to fix a leaky faucet. He takes the sign out of his backpack and presses the 'Work in Progress' button. The LED strip lights up red and the screen displays the message. He hangs the device on the door handle.
There's no answer, so Don heads back to his workshop to grab a tool he forgot. He presses the time button (the button in the middle) twice, the screen now reads "Come back in 30 minutes". Judy (a student) walking down the hallway approaches the door. The buzzer beeps and LED strip lights up, and she sees the message and knows to wait.
When Don returns and finishes the job, he takes the device off the door and switches it off by unplugging the battery. He puts it back into his backpack, getting ready for the next room.
Prototype Phase
Through the prototype, we wish to seek answer in whether the device meets our client's need in portability, usability, and if the degree of it's feedback was noticeable enough.
Front view of the prototype, with holes you can see that will later on become insertions for the motion sensor and buttons
The back view of the prototype
The front view with a ruler next to it, as you can see, it is much smaller at this point as we have not thought about how large the electric components would be
Our prototype consists two parts. Part one is a wood house design with hardware parts in it for our clients to test portability and weight. The second part is the working hardware that allow us to show the mechanism in addition to making real time adjustments based on feedback to provide our client with instant response based on his feedback.
Process of cutting prototype case #1, the case ended up to be too big and too heavy so we changed the thickness of the board in addition to the design of the case.
The prototype hanging off a doorknob.
Wiring for the prototype, wiring includes: arduino board, breadboard, LCD screen, infrared light sensor and a LED light stripe.
Video demonstration of the prototype mechanism, when students approach, the LCD screen displays "Do Not Disturb" and the LED light stripe lights up.
Through prototyping, we were able to find answer to many of our main questions. Our main question is the portability of the design and if our client is satisfied with the features that we have included. Through feedback, we found the client’s preference carry method is his backpack. To make sure this requirement is satisfied, we redesigned the case to be flatter and lighter as well as the attachment style for better surface adaptability. The features satisfy Don's need, he have also made a request to add in sound notifications. We also realize through feedback that Don preferred simplicity over features.
During the critique and feedback session, we realized the power of sound in notification. We learned that for mechanics, sound cues are extremely crucial because their eyes and hands are full and occupied. For feedbacks that we ignored, if need to name one, we couldn't fulfill the suggestion for a more colorful body due to the weight constraints of available PLA materials, but we have made edits to the lights instead.
We were surprised that Don was so supportive of our process! We showed him some of our previous housing design and video of the previous failed mechanism during the feedback session. We were worried that it might make us look very untrustworthy because of our failures but Don was so supportive and told us he was surprised that we have went through so many rounds in such short amount of time. Learned that it is okay to show your struggles sometimes!
Process Towards Final Product
New updated mechanism with light design and interactive buttons for feature selection.
Various versions of the case, different thickness and interior design, printed with various kinds of PLA.
New attachment style and how it sits in the new case design. A suction cup that can be slide and fits within a holder.
Suction cup weight test and test for surface adaptability.
Redesigned to be thinner on the side with pressable buttons for simple mechanism.
Assembly phase, testing weight distribution within the case and minimize the amount of wires and hardware to keep weight minimal.
Took some of the wires apart to reorganize and remove non-essential wires and boards.
Finally in case with ideal even weight distribution. Organized wires with tape for now to do final soldering.
We made most design decisions during consulting hours with Don to make sure the device keeps with his needs. However, we still need to make some decisions independently to solve some smaller details, such as the placement of the suction cup on the back of the case and the color of the button. One major mistake, also a discovery for us, was the placement of the LED strip. In the beginning, we aimed to expose as much of the strip as possible to emphasize lighting as much as possible as central design feature. We later found that that partially enclosing the strip and creating a slide in slot will provide better protection and improve overall safety. A major breakthrough aka breakdown inconsistent light up timing between the LED and the LCD display after the device leaves sleep mode. We solved this by replacing both LED and LCD in addition to doing three rounds of code edits. Through this, we were able to end up with a working and consistent reaction feedback.
Gantt chart for Acadian Flycatchers Spring 2026
With the schedule, we were able to stay very consistent and on top of it. We did have some changes in tasks and responsibilities as we knew more about each other’s strength and time schedules. Since it was some small divergences that we have made we were able to still stay on top of the schedule. The reason why we were pretty successful at keeping up with our original goals was making sure communication was tight and we had point person for each of the parts. In addition, we were able to form a hand-down chain where if a team member’s work is not completed, it will directly impact the next person. Another big part is staying positive and supportive. Inspired by Don, we were very supportive of each other and cared for everyone’s schedule as we would jump in when someone is struggling.
Conclusions & Lessons Learned
During the final critique session, we were able to learn so much from the feedback from the faculty, staff, and other clients for other groups. We have categorized and organized our lessons into two primary categories: design/mechanism and client communication.
For the design/mechanism perspective, we have learned many things but there are some key points. First, we learned the psychological impact of color choices to our users. Our initial design idea was prioritized high visibility with the colors, so we selected bold and abrupt colors to attract attention. However, feedback was unfortunately not included in the form but there were discussions that colors already carry established meanings such as green often signaling safety or accessibility. By using these color for different purpose may cause conflict with intended functions. Second, feedbacks were consistently addressed the placement of the LED strip, example "The wires leaking out of the corner of the box are not great." . While our original design wanted maximum exposure to enhance visual impact, we received feedback suggesting a more inclusive design of the LED. By incorporating a slide-in design for the LED not only improved durability and safety but it will also help to improve user experience. Third, we reevaluated the size and orientation of the LCD screen based on the feedback "Bigger screen". We were limited and constrained by our initial vertical layout of the display area. However, if we jumped outside the box and shifted to a horizontal configuration it would better use the space and increase the visibility of the sign with a bigger LED.
For the feedback related to communication client communication, we recognized that our initial engagement lacked precision which result this product to be bigger than ideal: "Maybe a more simple device with less inputs could be easier to make smaller?". Unfortunately, we didn't find out until the last critique that we could eliminate even more features to make sure it is even smaller and simpler to use. However, if we were able to ask more precise questions and triple check on everything maybe we can eliminate features that take up too much space.
Through this process, one of the most significant takeaways was the importance of asking specific, scenario based questions. These questions encourage our client to reflect on real life situations instead of empty big words which helps us to target down questions and concerns. For future projects, if possible, we want to structure interviews into shorter and more focused sessions instead than a single longer conversation as it will give us more reflection time. Additionally, we also learned that silence during conversation, even though extremely awkward, can create time for reflection as well as more thoughtful responses and questions asking.
This project was a fun learning experience for us. While there are definitely areas for improvement, specifically in LED placement, LCD sizing, sound, and visual effects, we now know how and why these improvements are important. Additionally, we also learned that accepting, sharing challenges and avoiding formatted thinking are crucial to effective design thinking.
Block Diagram & Schematic
Code
/*
No Passing by Acadian Flycatchers
Created for 60-223 Final Project at Carnegie Mellon University
Designed for Don, a carpenter with Facilities Management Services (FMS)
Description:
This device allows a maintenance worker to display status messages
on an LCD screen when working in or near a room. Three buttons select
different messages ("Work in Progress", "Come back in X minutes/hours",
"Do Not Disturb"). An LED strip lights up in different colors to
reinforce each status. A PIR motion sensor wakes the screen when
someone approaches, and a buzzer beeps to alert them. The screen
turns off automatically after 10 seconds of no motion to save power.
Pin Mapping:
Pin 2 - Button 1: "Work in Progress"
Pin 3 - Button 2: "Come back in..." (cycles through 5min/30min/2hr)
Pin 4 - Button 3: "Do Not Disturb"
Pin 5 - LED strip data (WS2812B)
Pin 7 - PIR motion sensor output
Pin 8 - Active buzzer
SDA - LCD I2C data
SCL - LCD I2C clock
5V - LCD VCC, LED strip 5V, PIR VCC
GND - All grounds
Vin - Battery pack (6V, 4x AA)
Libraries used:
- LiquidCrystal_I2C by Frank de Brabender
- Adafruit NeoPixel by Adafruit Industries
https://github.com/adafruit/Adafruit_NeoPixel
License: CC BY-NC-SA 4.0
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_NeoPixel strip(30, 5, NEO_GRB + NEO_KHZ800);
const int btn1 = 2;
const int btn2 = 3;
const int btn3 = 4;
const int pirPin = 7;
const int buzzerPin = 8;
int currentMsg = 0; // currently selected message (0=none, 1-3=messages)
int lastMsg = -1; // tracks last displayed message to avoid redundant updates
int btn2State = 0; // tracks which time option btn2 is on (0=5min, 1=30min, 2=2hr)
unsigned long lastMotionTime = 0;
unsigned long buzzerStartTime = 0;
bool buzzerOn = false;
bool lastScreenOn = false;
const unsigned long keepOnDuration = 10000; // screen stays on for 10 seconds after motion
const unsigned long buzzerDuration = 2500; // buzzer beeps for 2.5 seconds
bool btn2LastState = HIGH; // for edge detection on btn2
void setStrip(uint32_t color) {
strip.fill(color);
strip.show();
}
// Print a row of text to the LCD, padded with spaces to clear old content
void printRow(int row, String text) {
lcd.setCursor(0, row);
while (text.length() < 16) text += " ";
lcd.print(text);
}
// Update LCD and LED strip based on selected message
void showMessage(int msg) {
// Set LED strip color first, then wait before updating LCD
// (NeoPixel disables interrupts briefly, which can disturb I2C)
switch(msg) {
case 0:
strip.clear();
strip.show();
break;
case 1:
setStrip(strip.Color(255, 0, 0)); // red = Work in Progress
break;
case 2:
setStrip(strip.Color(0, 0, 255)); // blue = Come back in...
break;
case 3:
setStrip(strip.Color(0, 255, 0)); // green = Do Not Disturb
break;
}
delay(100); // wait for strip to stabilize before I2C communication
switch(msg) {
case 0:
printRow(0, "Ready");
printRow(1, "");
break;
case 1:
printRow(0, "Work in Progress");
printRow(1, "");
break;
case 2:
printRow(0, "Come back in");
if (btn2State == 0) {
printRow(1, "5 minutes");
} else if (btn2State == 1) {
printRow(1, "30 minutes");
} else {
printRow(1, "2 hours");
}
break;
case 3:
printRow(0, "Do Not Disturb");
printRow(1, "");
break;
}
}
void setup() {
strip.begin();
strip.setBrightness(50);
strip.clear();
strip.show();
delay(100);
Wire.begin();
lcd.init();
lcd.backlight();
showMessage(0); // show "Ready" on startup
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
pinMode(btn3, INPUT_PULLUP);
pinMode(pirPin, INPUT);
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
}
void loop() {
// Update last motion time whenever PIR detects presence
if (digitalRead(pirPin) == HIGH) {
lastMotionTime = millis();
}
bool screenOn = (millis() - lastMotionTime < keepOnDuration);
// Trigger buzzer when screen wakes up and a message is active
if (screenOn && !lastScreenOn && currentMsg != 0) {
buzzerOn = true;
buzzerStartTime = millis();
digitalWrite(buzzerPin, HIGH);
}
lastScreenOn = screenOn;
// Turn off buzzer after duration
if (buzzerOn && millis() - buzzerStartTime >= buzzerDuration) {
buzzerOn = false;
digitalWrite(buzzerPin, LOW);
}
// btn2 cycles through time options on each press (edge detection)
bool btn2Current = digitalRead(btn2);
if (btn2Current == LOW && btn2LastState == HIGH) {
btn2State = (btn2State + 1) % 3;
currentMsg = 2;
lastMsg = -1; // force display refresh
}
btn2LastState = btn2Current;
if (screenOn) {
lcd.backlight();
if (digitalRead(btn1) == LOW) currentMsg = 1;
if (digitalRead(btn3) == LOW) currentMsg = 3;
// Only update display when message changes
if (currentMsg != lastMsg) {
showMessage(currentMsg);
lastMsg = currentMsg;
}
} else {
// Screen off when no motion detected
lcd.noBacklight();
strip.clear();
strip.show();
lastMsg = -1;
}
delay(100);
}