#include #include #include #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 32 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Button and buzzer pins const int buttonPin = 7; const int buzzerPin = 8; unsigned long lastUpdate = 0; int remaining = 0; bool running = false; // ------------------------------------------------------------ // Draw a star-shaped sparkle // ------------------------------------------------------------ void drawStar(int x, int y) { display.drawPixel(x, y, SSD1306_WHITE); display.drawPixel(x - 1, y, SSD1306_WHITE); display.drawPixel(x + 1, y, SSD1306_WHITE); display.drawPixel(x, y - 1, SSD1306_WHITE); display.drawPixel(x, y + 1, SSD1306_WHITE); display.drawPixel(x - 1, y - 1, SSD1306_WHITE); display.drawPixel(x + 1, y - 1, SSD1306_WHITE); display.drawPixel(x - 1, y + 1, SSD1306_WHITE); display.drawPixel(x + 1, y + 1, SSD1306_WHITE); } // ------------------------------------------------------------ // 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; 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); 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 for (int angle = 20; angle <= 160; angle += 5) { float rad = angle * 0.0174533; int x = cx + cos(rad) * 10; int y = cy + sin(rad) * 10; display.drawPixel(x, y, SSD1306_WHITE); } // 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); } 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); } display.display(); delay(120); } display.clearDisplay(); display.display(); display.ssd1306_command(SSD1306_DISPLAYOFF); } // ------------------------------------------------------------ // Draw the horizontal countdown bar + digits // ------------------------------------------------------------ void drawTimer() { display.clearDisplay(); int barHeight = 32; int barWidth = 96; int currentWidth = map(remaining, 0, 90, 0, barWidth); display.fillRect(0, 0, currentWidth, barHeight, SSD1306_WHITE); display.setTextSize(2); display.setTextColor(SSD1306_WHITE); int digitX = 100; int digitY = 10; display.setCursor(digitX, digitY); display.print(remaining); display.display(); } // ------------------------------------------------------------ // Setup // ------------------------------------------------------------ void setup() { pinMode(buttonPin, INPUT_PULLUP); pinMode(buzzerPin, OUTPUT); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); display.setRotation(0); display.display(); randomSeed(analogRead(A0)); // for random celebration } // ------------------------------------------------------------ // Main loop // ------------------------------------------------------------ void loop() { if (!running && digitalRead(buttonPin) == LOW) { remaining = 90; running = true; display.ssd1306_command(SSD1306_DISPLAYON); delay(200); } if (running) { unsigned long now = millis(); if (now - lastUpdate >= 1000) { lastUpdate = now; remaining--; if (remaining > 0 && remaining <= 5) { tone(buzzerPin, 3000, 150); } else if (remaining > 0 && remaining % 10 == 0) { tone(buzzerPin, 2000, 150); } if (remaining <= 0) { running = false; // Random celebration if (random(0, 2) == 0) showSmiley(); else showCat(); } } drawTimer(); } }