ALIVE SERVER MONITOR OLED VERSION
Arduino Sketch - SSD1306 0.96" OLED Display
KEY FEATURES
Non-Blocking Ping
Scans one server per loop - scrolling never pauses
Scrolling Status Display
Animated "ServerName ALIVE" when all OK
LED Alerts
Blue always ON, Red flashes on server down
Cyberpunk Yellow/Blue UI
Optimized for dual-color OLED displays
DISPLAY PREVIEW
SSD1306 128x64 (2x scale)
BLUE (OK)
RED (ALERT)
TOGGLE SERVERS
Ready - Click RUN BOOT SEQUENCE
OLED vs ROUND LCD COMPARISON
| Feature | SSD1306 OLED | GC9A01 Round LCD |
|---|---|---|
| Resolution | 128 x 64 | 240 x 240 |
| Colors | Monochrome | 65K Colors |
| Interface | I2C (4 wires) | SPI (8 wires) |
| Size | 0.96" diagonal | 1.28" diameter |
| Power | ~20mA (varies by content) | ~30mA (backlight) |
| Best For | Compact builds, text display | Visual dashboards, graphics |
ARDUINO SKETCH
AliveOLED.ino
/* * Server Status Dashboard - "ALIVE" (OLED Version) * ESP32-S3 Super Mini + SSD1306 0.96" OLED + Status LEDs * * Uses I2C for simple 4-wire connection * Blue LED: Always ON (power indicator) * Red LED: Flashing when any server is down */ #include <WiFi.h> #include <ESP32Ping.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> // ============== CONFIGURATION ============== // WiFi credentials const char* WIFI_SSID = "YOUR_WIFI_SSID"; const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; // Server list - add your servers here (IP addresses or hostnames) const char* servers[] = { "1.1.1.1", // Server 1 "1.1.1.1", // Server 2 "1.1.1.1", // Server 3 "1.1.1.1", // Server 4 "1.1.1.1" // Server 5 }; const int NUM_SERVERS = sizeof(servers) / sizeof(servers[0]); // Optional: Friendly names for display (keep short for OLED) const char* serverNames[] = { "Server1", "Server2", "Server3", "Server4", "Server5" }; // Check interval (milliseconds) const unsigned long CHECK_INTERVAL = 30000; // 30 seconds // ============== PIN DEFINITIONS ============== // I2C for SSD1306 OLED #define OLED_SDA 8 #define OLED_SCL 9 // Status LEDs #define LED_BLUE 5 #define LED_RED 10 // ============== DISPLAY SETTINGS ============== #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 // No reset pin #define OLED_ADDR 0x3C // I2C address (try 0x3D if this doesn't work) // Create display object Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // ============== STATUS TRACKING ============== bool serverStatus[NUM_SERVERS]; bool allServersUp = true; unsigned long lastCheck = 0; unsigned long lastBlink = 0; bool redLedState = false; // Non-blocking scan state int scanIndex = -1; // -1 = not scanning, 0+ = server being checked bool scanInProgress = false; // Scrolling display int scrollX = 128; // Start from right edge int currentScrollServer = 0; // Which server is scrolling unsigned long lastScroll = 0; // ============== SETUP ============== void setup() { Serial.begin(115200); delay(100); Serial.println("\n=== ALIVE - Server Status Dashboard (OLED) ==="); // Initialize LED pins pinMode(LED_BLUE, OUTPUT); pinMode(LED_RED, OUTPUT); digitalWrite(LED_BLUE, LOW); digitalWrite(LED_RED, LOW); // Initialize I2C with custom pins Wire.begin(OLED_SDA, OLED_SCL); // Initialize OLED display if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { Serial.println("SSD1306 allocation failed!"); // Flash both LEDs to indicate error while (1) { digitalWrite(LED_BLUE, HIGH); digitalWrite(LED_RED, HIGH); delay(200); digitalWrite(LED_BLUE, LOW); digitalWrite(LED_RED, LOW); delay(200); } } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); // Show startup screen drawStartupScreen(); // Connect to WiFi connectWiFi(); // Initial server check checkAllServers(); updateDisplay(); } // ============== MAIN LOOP ============== void loop() { // Maintain WiFi connection if (WiFi.status() != WL_CONNECTED) { connectWiFi(); } // Start a new scan cycle periodically if (!scanInProgress && millis() - lastCheck >= CHECK_INTERVAL) { startScan(); } // If scan in progress, check one server per loop iteration if (scanInProgress) { checkNextServer(); } // Continuous display update (scrolling when OK, blinking when alert) updateDisplay(); // Handle LED states updateLEDs(); delay(50); } // ============== STARTUP SCREEN ============== void drawStartupScreen() { display.clearDisplay(); // === YELLOW ZONE (y=0-15) - Title bar === display.fillRect(0, 0, 128, 15, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(35, 4); display.print("BOOTING..."); display.setTextColor(SSD1306_WHITE); // === BLUE ZONE (y=16-63) - Content === // Cyberpunk angular corners in blue zone display.drawLine(0, 16, 15, 16, SSD1306_WHITE); display.drawLine(0, 16, 0, 26, SSD1306_WHITE); display.drawLine(112, 16, 127, 16, SSD1306_WHITE); display.drawLine(127, 16, 127, 26, SSD1306_WHITE); display.drawLine(0, 63, 15, 63, SSD1306_WHITE); display.drawLine(0, 53, 0, 63, SSD1306_WHITE); display.drawLine(112, 63, 127, 63, SSD1306_WHITE); display.drawLine(127, 53, 127, 63, SSD1306_WHITE); // Title display.setTextSize(2); display.setCursor(34, 24); display.print("ALIVE"); // Underline accent display.drawFastHLine(34, 41, 60, SSD1306_WHITE); display.drawFastHLine(36, 43, 56, SSD1306_WHITE); // Subtitle display.setTextSize(1); display.setCursor(22, 50); display.print(">> SYS_MONITOR"); display.display(); delay(500); } // ============== WiFi CONNECTION ============== void connectWiFi() { display.clearDisplay(); // === YELLOW ZONE (y=0-15) === display.fillRect(0, 0, 128, 15, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(25, 4); display.print("NET_CONNECT"); display.setTextColor(SSD1306_WHITE); // === BLUE ZONE (y=16-63) === display.setCursor(10, 24); display.print("SSID: "); display.print(WIFI_SSID); display.display(); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); int attempts = 0; display.setCursor(10, 42); display.print("["); while (WiFi.status() != WL_CONNECTED && attempts < 30) { delay(500); Serial.print("."); display.print("="); display.display(); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi connected!"); Serial.print("IP: "); Serial.println(WiFi.localIP()); display.clearDisplay(); // === YELLOW ZONE === display.fillRect(0, 0, 128, 15, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(25, 4); display.print("LINK_ACTIVE"); display.setTextColor(SSD1306_WHITE); // === BLUE ZONE === display.setCursor(45, 24); display.print("NODE:"); display.setCursor(25, 36); display.print(WiFi.localIP()); display.setCursor(45, 52); display.print("[OK]"); display.display(); delay(750); } else { Serial.println("\nWiFi failed!"); display.clearDisplay(); // === YELLOW ZONE === display.fillRect(0, 0, 128, 15, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(25, 4); display.print("LINK_FAILED"); display.setTextColor(SSD1306_WHITE); // === BLUE ZONE === display.setCursor(30, 35); display.print(">> RETRY..."); display.display(); delay(1000); } } // ============== NON-BLOCKING SERVER CHECK ============== void startScan() { Serial.println("\n--- Starting server scan ---"); scanInProgress = true; scanIndex = 0; allServersUp = true; } void checkNextServer() { if (scanIndex >= NUM_SERVERS) { // Scan complete scanInProgress = false; lastCheck = millis(); Serial.print("Scan complete. All up: "); Serial.println(allServersUp ? "YES" : "NO"); return; } Serial.print("Pinging "); Serial.print(servers[scanIndex]); Serial.print("... "); bool success = Ping.ping(servers[scanIndex], 1); serverStatus[scanIndex] = success; if (success) { Serial.println("OK"); } else { Serial.println("FAILED"); allServersUp = false; } scanIndex++; } // Initial blocking check at startup void checkAllServers() { Serial.println("\n--- Initial server check ---"); allServersUp = true; for (int i = 0; i < NUM_SERVERS; i++) { Serial.print("Pinging "); Serial.print(servers[i]); Serial.print("... "); bool success = Ping.ping(servers[i], 2); serverStatus[i] = success; if (success) { Serial.println("OK"); } else { Serial.println("FAILED"); allServersUp = false; } } lastCheck = millis(); } // ============== UPDATE DISPLAY ============== void updateDisplay() { display.clearDisplay(); if (allServersUp) { // === ALL SERVERS UP - Scrolling display === // === YELLOW ZONE (y=0-15) - Header === display.fillRect(0, 0, 120, 14, SSD1306_WHITE); display.fillTriangle(120, 0, 120, 14, 127, 0, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(4, 4); display.print("ALIVE"); display.setCursor(50, 4); if (scanInProgress) { display.print("[SCAN "); display.print(scanIndex + 1); display.print("/"); display.print(NUM_SERVERS); display.print("]"); } else { display.print("[NOMINAL]"); } display.setTextColor(SSD1306_WHITE); // === BLUE ZONE (y=16-63) - Scrolling server name === // Build scroll text: "ServerName ALIVE" String scrollText = String(serverNames[currentScrollServer]) + " ALIVE"; int textWidth = scrollText.length() * 12; // Size 2 = ~12px per char // Draw scrolling text - centered vertically in blue zone display.setTextSize(2); display.setTextWrap(false); // Prevent text wrapping display.setCursor(scrollX, 32); display.print(scrollText); // Update scroll position if (millis() - lastScroll > 30) { scrollX -= 3; // Scroll speed lastScroll = millis(); // When text is fully off screen, move to next server if (scrollX < -textWidth) { scrollX = 128; currentScrollServer++; if (currentScrollServer >= NUM_SERVERS) { currentScrollServer = 0; } } } // === Bottom status with blinking chevrons === display.setTextSize(1); // Blinking pattern: alternates every 300ms int blinkPhase = (millis() / 300) % 2; // Outer chevrons if (blinkPhase == 0) { display.setCursor(10, 56); display.print(">"); display.setCursor(111, 56); display.print("<"); } // Inner chevrons if (blinkPhase == 1) { display.setCursor(16, 56); display.print(">"); display.setCursor(105, 56); display.print("<"); } // Static text display.setCursor(25, 56); display.print("System Active"); } else { // === SERVER DOWN - Warning display === // Find first down server int downIndex = -1; for (int i = 0; i < NUM_SERVERS; i++) { if (!serverStatus[i]) { downIndex = i; break; } } // Blinking effect using millis bool blinkOn = (millis() / 300) % 2 == 0; // === YELLOW ZONE - Blinking WARNING === if (blinkOn) { display.fillRect(0, 0, 128, 15, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); display.setTextSize(1); display.setCursor(40, 4); display.print("WARNING"); display.setTextColor(SSD1306_WHITE); } // === BLUE ZONE - Flashing server info === if (blinkOn && downIndex >= 0) { display.setTextSize(1); display.setCursor(45, 24); display.print("[DEAD]"); display.setTextSize(2); display.setCursor(10, 36); display.print(serverNames[downIndex]); display.setTextSize(1); display.setCursor(25, 54); display.print(servers[downIndex]); } } display.display(); } // ============== UPDATE LEDs ============== void updateLEDs() { // Blue always on digitalWrite(LED_BLUE, HIGH); if (allServersUp) { // All OK: Red off digitalWrite(LED_RED, LOW); redLedState = false; } else { // Problem: Red flashing if (millis() - lastBlink >= 500) { redLedState = !redLedState; digitalWrite(LED_RED, redLedState ? HIGH : LOW); lastBlink = millis(); } } }
SETUP INSTRUCTIONS
- WiFi: Replace
YOUR_WIFI_SSIDandYOUR_WIFI_PASSWORDwith your WiFi credentials. - Servers: Edit the
servers[]array to add your server IP addresses or hostnames. - Server Names: Keep names short (4-8 chars) for the compact OLED display.
- I2C Address: Default is
0x3C. If display doesn't work, try0x3D. - Libraries: Install via Arduino Library Manager:
Adafruit GFX LibraryAdafruit SSD1306ESP32Pingby Matteo Dainese
- Board: Select "ESP32S3 Dev Module" in Arduino IDE.
- LEDs: GPIO 5 (Blue - always ON) and GPIO 10 (Red - flashes on alert).
- Display: Uses cyberpunk yellow/blue zone layout for dual-color OLEDs. Features scrolling server names when all OK.
I2C TROUBLESHOOTING
- Display not working? Run an I2C scanner sketch to find your display's address.
- Common addresses:
0x3C(most common) or0x3D(some modules). - No display output? Check wiring: SDA to GPIO 8, SCL to GPIO 9, VCC to 3.3V, GND to GND.
- Flickering? Add 4.7K pull-up resistors on SDA and SCL lines (some modules have them built-in).
- Dual-color OLED: Top ~16 rows display yellow, bottom rows display blue. Code is optimized for this layout.
I2C SCANNER (OPTIONAL)
I2C_Scanner.ino/* * I2C Scanner - Find your OLED address * Upload this if display doesn't work to find correct address */ #include <Wire.h> #define OLED_SDA 8 #define OLED_SCL 9 void setup() { Serial.begin(115200); delay(2000); Serial.println("\nI2C Scanner"); Wire.begin(OLED_SDA, OLED_SCL); } void loop() { byte error, address; int nDevices = 0; Serial.println("Scanning..."); for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); nDevices++; } } if (nDevices == 0) { Serial.println("No I2C devices found!"); } delay(5000); }
ARDUINO PROJECT SETUP
- Create Project Folder: Create a folder named
ALIVE_OLEDin your Arduino sketches directory (usuallyDocuments/Arduino/) - Main Sketch: Save the code as
ALIVE_OLED.ino- filename MUST match folder name - Single File Project: This project uses only one .ino file - no additional .h files required
- Optional: Save the I2C Scanner as a separate sketch for troubleshooting
ALIVE_OLED/ └── ALIVE_OLED.ino // Complete sketch (copy the main code above) I2C_Scanner/ // Optional - for troubleshooting └── I2C_Scanner.ino
COMPONENTS NEEDED
| ESP32-S3 Super Mini | Main microcontroller | AliExpress |
| SSD1306 OLED Display | 128x64 0.96" I2C (dual-color yellow/blue recommended) | Amazon |
| Blue LED (5mm) | Status indicator - always ON when running | Amazon |
| Red LED (5mm) | Alert indicator - flashes when server down | Amazon |
| 330Ω Resistors (x2) | Current limiting for LEDs | Amazon |
| Dupont Wires | For connections (F-F for OLED) | Amazon |
WIRING DIAGRAM
| SSD1306 OLED | ESP32-S3 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SDA | GPIO 8 |
| SCL | GPIO 9 |
| Status LEDs | ESP32-S3 |
|---|---|
| Blue LED (+) → 330Ω | GPIO 5 |
| Red LED (+) → 330Ω | GPIO 10 |
| Both LED (-) | GND |
Note: Only 4 wires needed for OLED (I2C is simpler than SPI displays).
REQUIRED LIBRARIES
Install via Arduino Library Manager (Sketch → Include Library → Manage Libraries):
| Adafruit GFX Library | Graphics primitives |
| Adafruit SSD1306 | OLED display driver |
| ESP32Ping | by Matteo Craciunescu - ICMP ping |
Note: ESP32Ping may need manual install from GitHub if not found in Library Manager.
ARDUINO IDE 3.x BOARD SETTINGS
| Board | ESP32S3 Dev Module |
| USB CDC On Boot | Enabled |
| Flash Size | 4MB (32Mb) |
| Partition Scheme | Default 4MB with spiffs |
| Upload Speed | 921600 |
ESP32 Board URL: Add this in File → Preferences → Additional Board Manager URLs:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
TROUBLESHOOTING
- Upload fails / Guru Meditation Error: Hold BOOT button while clicking Upload, release after "Connecting..." appears.
- OLED shows nothing: Run I2C Scanner to find correct address. Try 0x3C or 0x3D.
- I2C Scanner finds no devices: Check wiring - SDA to GPIO 8, SCL to GPIO 9, VCC to 3.3V.
- Display flickers: Add 4.7K pull-up resistors on SDA and SCL (some modules have built-in).
- WiFi won't connect: Double-check SSID and password. ESP32 only supports 2.4GHz networks.
- All servers show DOWN: Verify server IPs are correct. Check if firewall blocks ICMP ping.
- LEDs not working: Check LED polarity (long leg = positive). Verify resistors connected.
- Serial Monitor empty: Set baud rate to 115200. Enable "USB CDC On Boot" in board settings.
BUILD CHECKLIST
- □ Install Arduino IDE 3.x
- □ Add ESP32 board package URL and install ESP32 boards
- □ Install required libraries: Adafruit GFX, Adafruit SSD1306, ESP32Ping
- □ Create project folder:
ALIVE_OLED/ - □ Copy sketch as
ALIVE_OLED.ino - □ Edit code: Set WiFi SSID and password
- □ Edit code: Add your server IPs to
servers[]array - □ Edit code: Set short names in
serverNames[]array (4-8 chars) - □ Wire SSD1306 OLED to ESP32-S3 (4 wires: VCC, GND, SDA, SCL)
- □ Wire status LEDs with 330Ω resistors
- □ Connect ESP32-S3 via USB-C
- □ Select ESP32S3 Dev Module and correct COM port
- □ Upload sketch (hold BOOT if needed)
- □ Check Serial Monitor for WiFi connection
- □ Verify scrolling server names on display - Done!