Tamagotchi Cube
Interactive companion inspired by virtual pets and emotional caregiving
Tamagotchi Cube is an interactive companion device inspired by the nostalgic concept of virtual pets. Reimagined as a physical, cube-shaped object, it explores emotional bonding, care, and responsiveness through tangible interaction. By combining proximity sensing, RFID-based input, and expressive light behaviors, the project transforms the abstract idea of “care” into a visible, physical experience.
The cube possesses its own emotional states and personality. As users approach, it reacts to their presence, expressing awareness and anticipation through gentle changes in light. Over time, the cube develops needs, which the user must interpret and respond to. This dynamic creates a relationship built on observation, empathy, and repeated interaction.
Rather than relying on screens, Tamagotchi Cube communicates entirely through light and behavior. Emotions are expressed through color, brightness, and animated LED patterns, encouraging users to read subtle cues and engage intuitively. The project reflects on how humans form emotional attachments to simple systems and how care can be communicated through minimal, non-verbal feedback.
Process
Prototype design with 3D modeling with Solidwork
Figure Out the Material of Final Prototype
Interaction Concept
Users care for the cube by understanding its emotional state and responding appropriately.
The cube detects the user’s proximity and reacts as they approach
It displays an emotional state using color
The user inserts a specialized RFID chip representing a form of care
Correct care results in a joyful visual reward
Incorrect care prompts a warning response
Through repeated exchanges, the cube becomes a companion that rewards attentiveness and emotional awareness.
System Overview
The installation integrates sensors, RFID technology, and LED outputs controlled by a microcontroller.
Input
Time-of-Flight Distance Sensor (VL53L0X)
Detects the proximity of the user and initiates interactionRFID Reader (MFRC522)
Reads specialized care chips inserted into the cubeFood / Care / Activity chips (mapped to emotional needs)
Processing
Arduino Uno
Interprets distance and RFID data
Manages emotional state transitions
Controls LED brightness and animations
Output
NeoPixel LED Strip
Visualizes emotional states through color and motion
Smooth brightness transitions based on proximity
Emotional States
The cube communicates its internal state through color:
Pink (Neutral)
Default state when the user is nearby but interaction has not yet begunRed (Angry)
Indicates the cube needs attention or specific careGreen (Steady)
Calm and content, but still open to interactionRainbow (Happy)
Triggered when the user provides the correct care
A celebratory reward lasting approximately 20 seconds
Interaction Flow
Approach
The user approaches the cubeDistance sensor detects presence
Soft pink glow appears and increases in brightness
Emotional Expression
When the user is within close range (≈10 cm):The cube randomly selects an emotional state
Red (angry) or green (steady) is displayed
Care Action
The user interprets the cube’s emotionInserts an RFID care chip through the top opening
Response
Correct chip:
The cube enters a joyful rainbow animationIncorrect chip:
The cube blinks red three times, signaling a mismatch
Reset
The cube transitions into a new emotional state
Awaits the next interaction
-
#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <Adafruit_VL53L0X.h>
#define SS_PIN 10
#define RST_PIN 9
#define NEOPIXEL_PIN 7
#define NUM_PIXELS 40
#define TOTAL_PIXELS 80
MFRC522 rfid(SS_PIN, RST_PIN);
Adafruit_NeoPixel pixels(TOTAL_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
unsigned long lastEmotionChangeTime = 0;
const unsigned long EMOTION_CHANGE_INTERVAL = 10000; // Change emotion every 10 seconds
byte tagIds[][4] = {
{209, 221, 145, 73},
{193, 223, 145, 73},
{97, 220, 145, 73}
};
int currentEmotion = -1; // -1: Pink, 0: Angry, 1: Steady
byte* correctTag;
int currentBrightness = 1;
void setup() {
Serial.begin(115200);
SPI.begin();
rfid.PCD_Init();
pixels.begin();
pixels.setBrightness(currentBrightness);
setPink();
turnOffExtraLEDs();
pixels.show();
Wire.begin();
if (!lox.begin()) {
Serial.println(F("Failed to boot VL53L0X"));
while(1);
}
randomSeed(analogRead(0));
Serial.println("System initialized. Approach the VL53L0X sensor.");
}
void loop() {
long distance = measureDistance();
updateNeoPixelBasedOnDistance(distance);
if (distance <= 100) {
if (currentEmotion == -1 && millis() - lastEmotionChangeTime > EMOTION_CHANGE_INTERVAL) {
showRandomEmotion();
lastEmotionChangeTime = millis();
}
handleRFIDTag();
}
delay(100);
}
long measureDistance() {
VL53L0X_RangingMeasurementData_t measure;
lox.rangingTest(&measure, false);
if (measure.RangeStatus != 4) {
return measure.RangeMilliMeter;
} else {
return 2000; // Return a large value when out of range
}
}
void updateNeoPixelBasedOnDistance(long distance) {
if (distance <= 1000) {
int targetBrightness;
if (distance > 100) { // Pink color with increasing brightness
targetBrightness = map(distance, 1000, 100, 1, 255);
targetBrightness = constrain(targetBrightness, 1, 255);
currentEmotion = -1;
} else { // Full brightness when distance <= 100 mm (10 cm)
targetBrightness = 255;
if (currentEmotion == -1) {
showRandomEmotion();
}
}
// Smooth brightness transition
if (currentBrightness < targetBrightness) {
currentBrightness++;
} else if (currentBrightness > targetBrightness) {
currentBrightness--;
}
pixels.setBrightness(currentBrightness);
if (currentEmotion == -1) {
setPink();
}
pixels.show();
}
}
void showRandomEmotion() {
currentEmotion = random(2); // Only Angry (0) or Steady (1)
correctTag = tagIds[currentEmotion];
switch (currentEmotion) {
case 0:
setAngry();
break;
case 1:
setSteady();
break;
}
pixels.show();
Serial.println("New emotion displayed. Scan the correct RFID tag.");
}
void handleRFIDTag() {
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
if (checkTagMatch(rfid.uid.uidByte, correctTag)) {
Serial.println("Correct tag! Well done!");
setHappy(); // Set to happy state (rainbow effect for about 20 seconds)
showRandomEmotion(); // Show new random emotion after happy state
lastEmotionChangeTime = millis(); // Reset the timer
} else {
Serial.println("Wrong tag. Try again.");
blinkAngry();
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
void setPink() {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 20, 147)); // Deep pink
}
}
void setAngry() {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // Red for angry
}
}
void setSteady() {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // Green for steady
}
}
void setHappy() {
unsigned long startTime = millis();
while (millis() - startTime < 20000) { // Run for about 20 seconds
rainbowEffect();
}
}
void turnOffExtraLEDs() {
for (int i = NUM_PIXELS; i < TOTAL_PIXELS; i++) {
pixels.setPixelColor(i, 0, 0, 0);
}
}
bool checkTagMatch(byte* tagToCheck, byte* storedTag) {
for (byte i = 0; i < 4; i++) {
if (tagToCheck[i] != storedTag[i]) {
return false;
}
}
return true;
}
void blinkAngry() {
for (int j = 0; j < 3; j++) {
setAngry();
pixels.show();
delay(200);
pixels.clear();
pixels.show();
delay(200);
}
// Restore the current emotion
switch (currentEmotion) {
case 0:
setAngry();
break;
case 1:
setSteady();
break;
default:
setPink();
break;
}
pixels.show();
}
void rainbowEffect() {
static int j = 0;
for(int i = 0; i < NUM_PIXELS; i++) {
int pixelHue = (i 65536L / NUM_PIXELS + j 256) & 0xFFFF;
pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue)));
}
turnOffExtraLEDs();
pixels.show();
delay(50); // Slower, more gentle transition
j = (j + 1) % 256; // Slower color cycle
}
How will people engage with your project?
People engage with Tamagotchi Cube through curiosity and care. By approaching, observing, and responding to its emotional cues, users form a playful yet meaningful relationship with the object. The project encourages attentiveness and empathy, rewarding users who take the time to understand and respond to subtle signals.
Rather than demanding constant interaction, the cube invites gentle, intentional engagement—mirroring the way emotional bonds form in real relationships.
Designed by Luna Park. 2025