F1 Cockpit-Inspired Digital OLED Clock With ESP32

by gokux in Circuits > Gadgets

195 Views, 1 Favorites, 0 Comments

F1 Cockpit-Inspired Digital OLED Clock With ESP32

DSC04519.JPG
DSC04491.JPG

Formula 1 has long stood for top-tier technolоgy, accuracy, and design. The driver's steering whеel ‍display, compact, data-rich, and designed fоr both functionality and style, is one of the mоst recog‍nizable parts of modern F1 cars.

For thіs project, I decided to design and construct аn F1-inspired ‍digital clock that embodies the sаme high-performance appearance. This clock, whіch uses a microcont‍roller, an OLED display, and СAD-designed components, is more than just a tіmepiece. It has real-tim‍e NTP synchronization fоr accuracy, a unique UI inspired by F1 dashboаrds, and a form factor that ca‍n be changed with 3D-рrinted or CNC-milled housings.

This project shоws a multidisciplinary strategy‍ that combines еlectronics, embedded programming, and CAD desіgn. It emphasizes how modern prototypi‍ng tools сan incorporate fandom into functional design, аnd it illustrates how professional processe‍s, frоm circuit integration to 3D modeling, can be usеd in creative, fandom-driven projects.

Supplies

parts .jpg
  1. SeeedStudio XIAO ESP32C3
  2. 2.42inch OLED
  3. Multiperpus glue
  4. Super Glue

Designing in Fusion 360

Screenshot 2025-08-18 150010.png

I utilised Fusion 360 to plan and design my project, which required careful space optimisation. I needed to fit all the parts into the smallest form factor possible while ensuring practicality, including sufficient space for wiring and easy assembly. First, I imported all 3d models of the parts and tried different configurations by placing the parts in various positions. Once I found the optimal configurations, I built the enclosure around them. All design files are provided below

Then I 3d printed the main body in black PLA / also resin printed the F1 car model using my Elegoo Saturn 4 ultra

Flashing Code to XIAO ESP32C3

I always like to upload the code to the microcontroller before assembly. I am using Arduino IDE for flashing the code. follow these tutorials for setting up IDE for Seeed Studio XIAO ESP32C3 and learn more about this board

Make sure to install all required libraries into Arduino IDE

How to set your wifi password

We need an internal connection to get time data from NTP servers. so we need to connect this clock to your wifi network. you can enter your wifi credentials on 46,47 lines

const char* ssid     = "ssid";
const char* password = "password";

How to set your time zone

The time zone is configured using your GMT offset in seconds. My GMT offset is GMT +5:30, now we need to convert it into seconds which is 19800sec. Just google it for easy conversion

You can enter your GMT offset in seconds in line 65 of the code

NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800, 0);

The complete code

#include <WiFi.h>
#include <SPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/Org_01.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// WiFi credentials
const char* ssid = "NG(3110)"; // your WiFi SSID
const char* password = "80898089"; // your WiFi password
// OLED display SPI pins
#define OLED_MOSI D10
#define OLED_CLK D8
#define OLED_DC D6
#define OLED_CS D7
#define OLED_RESET D5
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
// NTP client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800, 0); // 19800 = IST offset (UTC+5:30)
static const unsigned char PROGMEM image_Layer_25_bits[] = {0x01,0x0e,0x07,0x03,0x81,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x07,0x03,0x81
,0xc2,0x00,0x03,0x1f,0x0f,0x87,0xc3,0xe1,0xf0,0xf8,0x7c,0x3e,0x11,0x08,0x84,0x42,0x23,0x00,0x07,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc
,0xfe,0x7f,0x20,0x90,0x48,0x24,0x13,0x80,0x0f,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0xfe,0x7f,0x20,0x90,0x48,0x24,0x13,0xc0,0x07,0x3f
,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0xfe,0x7f,0x20,0x90,0x48,0x24,0x13,0x80,0x03,0x1f,0x0f,0x87,0xc3,0xe1,0xf0,0xf8,0x7c,0x3e,0x11,0x08
,0x84,0x42,0x23,0x00,0x01,0x0e,0x07,0x03,0x81,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x07,0x03,0x81,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf0,0x41,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x9c,0x80
,0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x04,0xe4,0xbe,0x80,0x7f,0xff,0xff,0xff,0xf7,0x00,0x01,0xdf,0xff,0xff
,0xff,0xfc,0x05,0xf4,0xbe,0x80,0x80,0x00,0x00,0x00,0x03,0x00,0x01,0x80,0x00,0x00,0x00,0x02,0x05,0xf4,0xbe,0x81,0x00,0x00,0x00,0x00
,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x05,0xf4,0x9c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0xe4
,0x41,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x08,0x3e,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x21,0xf0,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x20,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00
,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00};
void setup() {
Serial.begin(115200);
// Initialize OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
// Initialize time client
timeClient.begin();
}
void loop() {
// Update time from NTP server
timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
time_t rawTime = epochTime;
struct tm *ptm = gmtime(&rawTime);
int monthDay = ptm->tm_mday;
int currentMonth = ptm->tm_mon + 1;
int currentYear = ptm->tm_year + 1900;
int currentHour = ptm->tm_hour;
int currentMinute = ptm->tm_min;
// Convert time to 12-hour format
String period = "AM";
if (currentHour >= 12) {
period = "PM";
if (currentHour > 12) {
currentHour -= 12;
}
} else if (currentHour == 0) {
currentHour = 12;
}
// Make strings for time and date
char timeStr[6];
snprintf(timeStr, sizeof(timeStr), "%02d:%02d", currentHour, currentMinute);
char dateStr[11];
snprintf(dateStr, sizeof(dateStr), "%02d.%02d.%04d", monthDay, currentMonth, currentYear);
// Display data on OLED
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Time (centered X)
display.setFont(&Org_01);
display.setTextSize(5);
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(timeStr, 0, 0, &x1, &y1, &w, &h);
int timeX = (SCREEN_WIDTH - w) / 2;
display.setCursor(timeX, 35);
display.print(timeStr);
// AM/PM (don’t move)
display.setTextSize(1);
display.setCursor(59, 48);
display.print(period);
// Date (centered X)
display.setTextSize(2);
display.getTextBounds(dateStr, 0, 0, &x1, &y1, &w, &h);
int dateX = (SCREEN_WIDTH - w) / 2;
display.setCursor(dateX, 60);
display.print(dateStr);
// Bitmap
display.drawBitmap(1, 2, image_Layer_25_bits, 126, 62, 1);
display.display();
delay(1000);
}


Wiring and Assembly

biwtmap.jpg

Here is the wiring diagram for this build. We are using a 2.42-inch OLED screen for displaying everything, so let start the assembly

1.Use super glue to attach the display holder to the base.

2.Place the OLED display module into the display holder and melt the plastic standoff to secure the OLED display.

3. Attach the XIAO antenna to the base.

4. Attach the XIAO ESP32C3 to the 3D-printed slot using glue.

5. Connect the antenna cable to the XIAO.

6. Complete the wiring according to the provided wiring diagram.

7 . Finally, apply some glue to the side and secure the back caps.

We are done with our build


Final Thought

DSC04519.JPG

This project demonstrates how fandom can be transformed into functional design through modern tools and prototyping methods. By merging electronics, CAD design, and programming, the F1-Inspired Digital Clock brings the aesthetic of a Formula 1 cockpit into an everyday object.

Beyond being a timepiece, it represents the intersection of creativity and engineering—showing how a passion for motorsport can drive technical exploration. The modular design also leaves room for customisation: users can adapt the UI, housing, or even add features such as alarms, animations, or team-specific themes.

Whether used as a personal desk accessory, a learning project in embedded systems, or as inspiration for further product design, this build highlights how fandom can fuel innovation.