diff --git a/toothbrush-timer.ino b/toothbrush-timer.ino index 1216a1d..7da3b0f 100644 --- a/toothbrush-timer.ino +++ b/toothbrush-timer.ino @@ -32,7 +32,45 @@ void drawStar(int x, int y) { } // ------------------------------------------------------------ -// Celebration animation with glow + sparkles +// Draw a cat face (fits same 28px circle as smiley) +// ------------------------------------------------------------ +void drawCatFace(int cx, int cy) { + // Head outline + display.drawCircle(cx, cy, 14, SSD1306_WHITE); + + // Ears + display.drawLine(cx - 10, cy - 8, cx - 4, cy - 16, SSD1306_WHITE); + display.drawLine(cx - 4, cy - 16, cx - 2, cy - 8, SSD1306_WHITE); + + display.drawLine(cx + 10, cy - 8, cx + 4, cy - 16, SSD1306_WHITE); + display.drawLine(cx + 4, cy - 16, cx + 2, cy - 8, SSD1306_WHITE); + + // Eyes + display.fillCircle(cx - 6, cy - 3, 2, SSD1306_WHITE); + display.fillCircle(cx + 6, cy - 3, 2, SSD1306_WHITE); + + // Nose + display.drawPixel(cx, cy + 1, SSD1306_WHITE); + display.drawPixel(cx - 1, cy + 2, SSD1306_WHITE); + display.drawPixel(cx + 1, cy + 2, SSD1306_WHITE); + + // Mouth + display.drawPixel(cx - 2, cy + 4, SSD1306_WHITE); + display.drawPixel(cx - 3, cy + 5, SSD1306_WHITE); + + display.drawPixel(cx + 2, cy + 4, SSD1306_WHITE); + display.drawPixel(cx + 3, cy + 5, SSD1306_WHITE); + + // Whiskers + display.drawLine(cx - 6, cy + 2, cx - 14, cy + 1, SSD1306_WHITE); + display.drawLine(cx - 6, cy + 4, cx - 14, cy + 5, SSD1306_WHITE); + + display.drawLine(cx + 6, cy + 2, cx + 14, cy + 1, SSD1306_WHITE); + display.drawLine(cx + 6, cy + 4, cx + 14, cy + 5, SSD1306_WHITE); +} + +// ------------------------------------------------------------ +// Celebration animation with glow + sparkles (Smiley) // ------------------------------------------------------------ void showSmiley() { int cx = 64; @@ -40,13 +78,12 @@ void showSmiley() { unsigned long startTime = millis(); - // --- 1. Sparkle burst at the start --- + // --- Sparkle burst --- for (int burst = 0; burst < 12; burst++) { display.clearDisplay(); int sx, sy, dx, dy, dist; - // Keep sparkles OUTSIDE the face radius do { sx = random(0, 128); sy = random(0, 32); @@ -63,25 +100,21 @@ void showSmiley() { delay(60); } - // --- 2. Main 15-second animation --- + // --- Main animation --- while (millis() - startTime < 15000) { display.clearDisplay(); - // Pulsing glow radius float t = (millis() - startTime) * 0.008; int pulse = 2 + (sin(t) * 3); - // Glow ring display.drawCircle(cx, cy, 14 + pulse, SSD1306_WHITE); - - // Face outline display.drawCircle(cx, cy, 14, SSD1306_WHITE); // Eyes display.fillCircle(cx - 6, cy - 4, 2, SSD1306_WHITE); display.fillCircle(cx + 6, cy - 4, 2, SSD1306_WHITE); - // Smile (correct orientation) + // Smile for (int angle = 20; angle <= 160; angle += 5) { float rad = angle * 0.0174533; int x = cx + cos(rad) * 10; @@ -89,7 +122,7 @@ void showSmiley() { display.drawPixel(x, y, SSD1306_WHITE); } - // --- Twinkling sparkles (outside the face) --- + // Sparkles for (int i = 0; i < 5; i++) { int sx, sy, dx, dy, dist; @@ -101,7 +134,75 @@ void showSmiley() { dy = sy - cy; dist = sqrt(dx * dx + dy * dy); - } while (dist < 22); // keep sparkles OUTSIDE the face + glow + } while (dist < 22); + + drawStar(sx, sy); + } + + display.display(); + delay(120); + } + + display.clearDisplay(); + display.display(); + display.ssd1306_command(SSD1306_DISPLAYOFF); +} + +// ------------------------------------------------------------ +// Celebration animation with glow + sparkles (Cat) +// ------------------------------------------------------------ +void showCat() { + int cx = 64; + int cy = 16; + + unsigned long startTime = millis(); + + // --- Sparkle burst --- + for (int burst = 0; burst < 12; burst++) { + display.clearDisplay(); + + int sx, sy, dx, dy, dist; + + do { + sx = random(0, 128); + sy = random(0, 32); + + dx = sx - cx; + dy = sy - cy; + dist = sqrt(dx * dx + dy * dy); + + } while (dist < 22); + + drawStar(sx, sy); + + display.display(); + delay(60); + } + + // --- Main animation --- + while (millis() - startTime < 15000) { + display.clearDisplay(); + + float t = (millis() - startTime) * 0.008; + int pulse = 2 + (sin(t) * 3); + + display.drawCircle(cx, cy, 14 + pulse, SSD1306_WHITE); + + drawCatFace(cx, cy); + + // Sparkles + for (int i = 0; i < 5; i++) { + int sx, sy, dx, dy, dist; + + do { + sx = random(0, 128); + sy = random(0, 32); + + dx = sx - cx; + dy = sy - cy; + dist = sqrt(dx * dx + dy * dy); + + } while (dist < 22); drawStar(sx, sy); } @@ -110,7 +211,6 @@ void showSmiley() { delay(120); } - // Turn off the display after animation display.clearDisplay(); display.display(); display.ssd1306_command(SSD1306_DISPLAYOFF); @@ -122,17 +222,13 @@ void showSmiley() { void drawTimer() { display.clearDisplay(); - // Bar dimensions int barHeight = 32; int barWidth = 96; - // Map remaining seconds to bar width int currentWidth = map(remaining, 0, 90, 0, barWidth); - // Draw bar left → right display.fillRect(0, 0, currentWidth, barHeight, SSD1306_WHITE); - // Digits on the right display.setTextSize(2); display.setTextColor(SSD1306_WHITE); @@ -154,46 +250,48 @@ void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); - display.setRotation(0); // horizontal + display.setRotation(0); display.display(); + + randomSeed(analogRead(A0)); // for random celebration } // ------------------------------------------------------------ // Main loop // ------------------------------------------------------------ void loop() { - // Start timer on button press if (!running && digitalRead(buttonPin) == LOW) { remaining = 90; running = true; display.ssd1306_command(SSD1306_DISPLAYON); - - delay(200); // debounce + delay(200); } if (running) { unsigned long now = millis(); - // Update once per second if (now - lastUpdate >= 1000) { lastUpdate = now; remaining--; - // Final 5-second countdown beeps (higher pitch) if (remaining > 0 && remaining <= 5) { - tone(buzzerPin, 3000, 150); // 3 kHz beep + tone(buzzerPin, 3000, 150); } - // Regular 10-second interval beeps else if (remaining > 0 && remaining % 10 == 0) { - tone(buzzerPin, 2000, 150); // 2 kHz beep + tone(buzzerPin, 2000, 150); } if (remaining <= 0) { running = false; - showSmiley(); + + // Random celebration + if (random(0, 2) == 0) + showSmiley(); + else + showCat(); } } drawTimer(); } -} +} \ No newline at end of file