Lower front view, drawer and storage detailing, device off
Front view, storage compartment + cup detection lights on
This device helps me track the steeping time of my tea in a quiet, ambient way, complementing the meditative nature of the practice. Designed with a simple and intuitive interface, it visually indicates the ideal steeping time for different tea types through a gentle color transition and a subtle light effect as an alarm.
Equipped with a force-sensitive resistor, the device detects when a full cup is placed on top, automatically initiating the steeping timer. To enhance its functionality and create a cohesive user experience, a built-in tea bag compartment is integrated into the front, ensuring convenience and ease of use.
2 minutes of steep time, mid green tone
Dark lighting wave pattern detail shot
Internal wiring, pieces are mounted in place so it is difficult to show the wiring more clearly than this. The green and white wire attach to the force resistor, and although it was not used in the final code, the thermistor can be seen soldered to the board.
Assembly shots of all components used, back port and how pieces are layered.
In this video, I demonstrate the operation of this smart tea steeping device, outlining its key features and functionality. The video begins by showcasing the built-in tea storage drawer and the process of initiating the device. The system detects the weight of the cup placed on top, recognizing when it is full and automatically starting the steeping timer.
As the tea brews, the device provides a visual timer through a dynamic lighting system. It begins with a default blue light and gradually transitions through different colors, each corresponding to the ideal steeping time for various tea types. After three minutes, the light turns green and a blinking circle activates as an alert, signaling the optimal steep time for green tea. This cycle continues—at five minutes, the light shifts to purple for black tea, and at seven minutes, it turns a soft pink for herbal teas.
Once the cup is lifted, the lights gently fade out as the device detects its absence. Additionally, to ensure energy efficiency, the device automatically powers down after 10 minutes, exceeding the recommended steeping time for any tea variety.
Form based prototype, visualizing the scale and feel of the device, and possibly how it might be assembled and where to place hardware inside.
Sandblasted glass for surface. Attaching leds to rim of glass to test effect, and testing early trials of color and light patterns using the force resistor as initial trigger.
Originally planned to use a thermistor to detect the heat of the cup through the glass, and therefore reflect the color in light in response to the color of the tea as an additional feature. I found that the thermistor did not work very well as the initial trigger, or as a data point to use for the timer as well. The temperature values were very weak and inconsistent, it also took to long to register the heat through the glass, making the timer wrong.
Before attaching the longer led strip later, I wanted to first see if I could get a light response based on the temperature sensed from the thermistor, and then later change these trigger values to fit the temperature of boiling water. I found this difficult to test using just body heat, and the temperature values did not really change even if I held it for a while.
For sake of accurate prototyping, I needed to test the thermistor using boiling temps, so I decided to solder and mount my circuit and test inside the base shell of my product. In case this did not work, I also attached the force resistor inside as a backup plan.
Final testing and adjusting of light response and weight scale to use based on cup used. This is the last step before polishing and painting the device.
During testing, I found that the force resistor worked better and more accurately for my intended purposes. As seen above I started to mount all the components inside the 3d print I made. In the future, I would like to leave a second port for the power as well. I did not compensate in the 3d print for excess material, and ended up having to sand down everything down by about 2 millimeters to try and fit as best as possible.
REFLECTING ON COMMENTS
Looking through most of the comments I received on this device, I would like to consider ways in which this can be more customizable for particular purposes and make the interface more clear. As once comment mentions, "there can definitely be more input methods for the type of tea (maybe not a button) such as dials", and another also mentions the use of buttons to select the tea type. While I personally do enjoy the interface of this device being more hidden and servicing in ambience, I do think it could benefit from a more clear distinction, maybe not buttons or sliders, but some way that shows the color meanings and tea types, a bit like a chart. Although a form of a slider could be nice, so that the alarms only happen once, instead of having to wait through 3 or less. Something else that stood out to me in the comments was this comment "I think you’ve built an infrastructure that is able to take on some more add-ons like temperature sensing and buttons to notify the type of tea to make it more customizable". This was actually something that I was considering, which is why I left the thermistor inside and wired in the end, so that I could always have the opportunity to to return to this idea, and include temp as a factor again. In this way, new possibilities like a way to let you know when your tea is cold, or even finding ways to incorporate a heating system can be included if temperature is known.
SELF - CRITIQUE
All in all, by the end of this project I personally felt very happy with the end product. While I did run into the wall a few times with the errors and issues I found with using the thermistor, I feel that this challenge ended up pushing me to find an alternative creative solution to measuring the time of steeping without knowing the temperature, but rather simply the presence of the cup. This was also great training to learn about 3d printing, and considering the measurements differently, in where laser cutting you need to consider the lost material, 3d printing needs to consider the gained and excess material. I enjoyed this a lot and will definitely continuously use this device myself.
LEARNED ABILITIED + LIMITATIONS
In working on this project, I found it to be quite challenging with my limited expertise in software. While I was working with a system that I thought was relatively simple, adjusting the timer as well as creating the patterns for the leds was quite challenging for me. Although, I did manage to find a few tutorials online about coding patterns for individually addressable leds, and also used chatGPT from time to time to help me implement this information as well as debug and help we write and understand the code. I do always enjoy the construction and designing of the form most enojoyable for me personally, and this was a good opportunity to take it lightly and design quickly and simply. In the end, I found that this ended creating a better form for my intentions anyways, although it is still a little bit large. I was surprised by how much I actually enjoy soldering, and found something satisfying about this process.
NEXT STEPS
As for future steps, I would like to find a way to include the temperature as a factor as well, and at least have it so that after your set time, the temperature will adjust the light color to notify you of when your tea is getting cold. Also considering a way to implement some form of customization of your tea, wether this could be totally analogue and use a slider system for adjustments, or even being creative about this and have it like placing a metal marble or peg down in a indent on the side to select the type of tea you are drinking, so that way the visual language is still consistent. I feel like there are multiple alterations that can be made to this design, and even making digital prototypes in 3d to showcase these alternatives could be a good way to visualize these different uses.
/*
Tea Steeping Timer with LED Indicator
This device helps track the steeping time for different types of tea using a quiet, ambient light effect instead of a loud alarm.
The LED color changes to indicate the steeping progress, and a final light effect signals when the tea is ready.
Pin Mapping:
___________________________________________________________________
Arduino Pin | Role | Description
------------|--------------|--------------------------------------------
6 | Output | Controls the WS2812 LED strip
A0 | Input | Reads force-sensitive resistor (FSR) to detect cup presence
Hardware:
- WS2812 LED strip (38 LEDs)
- Force Sensitive Resistor (FSR)
- Arduino-compatible board
Code uses the FastLED library for LED control.
Also uses ChatGPT for help in writing code and understanding code
Code released under MIT License by Isabel Fleck, 2025.
*/
#include <FastLED.h>
#define LED_PIN 6 // LED strip control pin
#define NUM_LEDS 38 // Total number of LEDs in the strip
#define FSR_PIN A0 // Force Sensitive Resistor (FSR) pin
CRGB leds[NUM_LEDS];
unsigned long startTime = 0;
bool cupPresent = false;
int trailSize = 6; // Number of LEDs in the rain effect
void setup() {
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
Serial.begin(9600);
Serial.println("System initialized. Waiting for cup...");
}
void loop() {
int fsrValue = analogRead(FSR_PIN);
Serial.print("FSR: "); Serial.print(fsrValue);
if (fsrValue > 170) { // Detect cup presence
if (!cupPresent) {
cupPresent = true;
startTime = millis(); // Start timer once
Serial.println(" | Cup detected! Timer started.");
}
unsigned long elapsed = millis() - startTime;
float progress = min((float)elapsed / 1000 * 0.01002, 6.01); // Scale progress to match timing
int minutes = (elapsed / 1000) / 60;
int seconds = (elapsed / 1000) % 60;
Serial.print(" | Time Elapsed: "); Serial.print(minutes);
Serial.print("m "); Serial.print(seconds);
Serial.print("s | Progress: "); Serial.println(progress);
if ((progress >= 1.80 && progress < 2.00) ||
(progress >= 3.01 && progress < 3.21) ||
(progress >= 4.20 && progress < 4.40)) {
rainEffect(progress);
} else if (progress >= 4.41 && progress <= 6.01) {
dimLEDs(progress);
} else {
updateLEDs(progress);
}
} else {
if (cupPresent) {
cupPresent = false;
Serial.println(" | Cup removed! LEDs fading out...");
fadeOutLEDs();
}
}
delay(50);
}
// Function to update LED colors smoothly over steeping progress
void updateLEDs(float progress) {
int r, g, b;
if (progress <= 1.80) {
gradualTransition(180, 220, 255, 166, 214, 8, progress / 1.80, r, g, b);
} else if (progress <= 3.01) {
gradualTransition(166, 214, 8, 165, 11, 94, (progress - 1.80) / (3.01 - 1.80), r, g, b);
} else if (progress <= 4.20) {
gradualTransition(165, 11, 94, 255, 90, 54, (progress - 3.01) / (4.20 - 3.01), r, g, b);
} else {
gradualTransition(255, 90, 54, 180, 220, 255, (progress - 4.20) / (6.01 - 4.20), r, g, b);
}
setLEDColor(r, g, b);
}
// Function to gradually transition between two colors
void gradualTransition(int r1, int g1, int b1, int r2, int g2, int b2, float transitionProgress, int &r, int &g, int &b) {
r = r1 + transitionProgress * (r2 - r1);
g = g1 + transitionProgress * (g2 - g1);
b = b1 + transitionProgress * (b2 - b1);
}
// Function to apply a color to all LEDs
void setLEDColor(int r, int g, int b) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(r, g, b);
}
FastLED.show();
}
// Creates a trailing rain effect at certain progress points
void rainEffect(float progress) {
static int position = 0;
FastLED.clear();
int r, g, b;
if (progress >= 1.80 && progress < 2.00) {
r = 166; g = 214; b = 8;
} else if (progress >= 3.01 && progress < 3.21) {
r = 165; g = 11; b = 94;
} else if (progress >= 4.20 && progress < 4.40) {
r = 255; g = 90; b = 54;
} else {
return;
}
for (int i = 0; i < trailSize; i++) {
int index = (position + i) % NUM_LEDS;
leds[index] = CRGB(r, g, b);
}
FastLED.show();
position = (position + 2) % NUM_LEDS;
delay(50);
}
// Function to gradually dim LEDs as steeping nears completion
void dimLEDs(float progress) {
float fadeAmount = 1 - ((progress - 4.41) / (6.01 - 4.41));
int r = 180 * fadeAmount;
int g = 220 * fadeAmount;
int b = 255 * fadeAmount;
setLEDColor(r, g, b);
}
// Function to fade out LEDs when the cup is removed
void fadeOutLEDs() {
for (int i = 255; i >= 0; i -= 10) {
fadeToBlackBy(leds, NUM_LEDS, 50);
FastLED.show();
delay(50);
}
FastLED.clear();
FastLED.show();
}