Skip to the content
PCBKitNew board
2 layers68.5 × 70.5 mmAether, the printed circuit board in 3D

ESP32-Based Attitude Indicator Wireless Flight Instrumentation System

Size
68.5 × 70.5 mm
Copper layers
2
Thickness
1.6 mm
Parts
7
Nets
46
Pads
60
Tracks, vias
61, 0
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
8 Aug 2026
Updated
11 Aug 2026

Overview

Aether is an open-source printed circuit board by GavishtK, from the GavishtK/AeThEriON repository on GitHub, published under the MIT licence. It is a 2-layer board of 68.5 × 70.5 mm with 7 parts on 46 nets, routed with 61 tracks and 0 vias.

Its parts include 3 resistors, 1 IC, 1 diode and 1 connector. It belongs with the ESP32 boards of this library.

README

README.md

Aetherion PCB 3D Render

AETHERION AI

ESP32-Based Attitude Indicator & Wireless Flight Instrumentation System
Version MCU IMU License UI Tests

Real-time flight attitude indicator with a wireless OLED display and a full web-based analytics dashboard.

50 Hz telemetry | 25 FPS OLED | 60 FPS horizon | AI analysis | Flight recording & replay | SQLite-quality sensor diagnostics


Table of Contents

  1. Project Overview
  2. System Architecture
  3. Data Flow
  4. Telemetry Protocol
  5. Firmware
  6. Dashboard
  7. Screenshots
  8. PCB Design
  9. Hardware
  10. Quick Start
  11. Development
  12. UI Testing
  13. License

Overview [blocked]

AETHERION AI is a self-contained, open-source flight instrumentation system built on the ESP32. It combines:

  • Onboard OLED primary flight display (PFD) — 128×64 monochrome display rendered at 25 FPS
  • Wireless web dashboard — served directly from the ESP32 over Wi-Fi, accessed via any browser
  • Real-time attitude indicator — artificial horizon with pitch ladder, roll arc, aircraft symbol, and turn coordinator
  • Flight telemetry — 50 Hz broadcast of raw IMU data, computed attitude, and G-force over WebSocket
  • Flight recording & replay — client-side session storage (IndexedDB), CSV/JSON export, and seekable playback
  • AI-powered analysis — multi-model flight state classification (Random Forest, XGBoost, Neural Network, SVM)
  • Stability & control scoring — RMS deviation, oscillation analysis, correction rate, and pilot stability metrics
  • Sensor health diagnostics — saturation, noise, packet-loss, and data-quality analysis

The ESP32 runs in Access Point mode, creating its own Wi-Fi network so no router is required. The dashboard is stored on-board in LittleFS flash and served over HTTP, while telemetry is streamed over a WebSocket server at 50 Hz.


System Architecture [blocked]

Firmware Module Architecture

mermaid
graph LR
    subgraph "firmware/Aetherion"
        A[Aetherion.ino<br/>Main Entry]
        B[config.h<br/>Configuration]
        C[imu.cpp/h<br/>Sensor Driver<br/>MPU6050 + Madgwick]
        D[graphics.cpp/h<br/>OLED Rendering<br/>U8g2 / PFD]
        E[web.cpp/h<br/>HTTP + WS Server<br/>LittleFS]
        F[rgb.cpp/h<br/>LED Status]
    end

    A --> B
    A --> C
    A --> D
    A --> E
    A --> F
    C -->|IMUData| D
    C -->|IMUData| A
    D -->|drawPFD| A
    E -->|handleWebClient| A
    F -->|Status| A

Architecture Diagram (Image)

System Architecture Flowchart

Data Flow [blocked]

mermaid
sequenceDiagram
    participant ESP32 as ESP32
    participant IMU as MPU6050 (I2C)
    participant OLED as OLED Display
    participant Browser as Web Browser
    participant IndexedDB as IndexedDB (Local)

    loop Setup (one-time)
        ESP32->>IMU: Initialize (I2C 0x68)
        ESP32->>IMU: Calibrate (200 samples)
        ESP32->>OLED: Boot Screen → Loading → Ready
        ESP32->>ESP32: Create I2C Mutex
        ESP32->>ESP32: Create oledTask (FreeRTOS, 25 FPS)
        ESP32->>WiFi: softAP("Aetherion", "aetherion123")
        ESP32->>WS: WebSocket Server begin (port 81)
        ESP32->>HTTP: LittleFS mount + WebServer begin (port 80)
    end

    par oledTask (25 FPS, Core 0)
        loop every 40 ms
            oledTask->>IMU: xSemaphoreTake(i2cMutex)
            IMU->>oledTask: Read accel + gyro
            oledTask->>oledTask: Compute roll/pitch (atan2)
            oledTask->>OLED: drawPFD(roll, pitch, gForce)

Telemetry Packet Format

Every 20 ms (50 Hz), the ESP32 broadcasts a JSON packet:

json
{
  "t": 1543210,
  "roll": -4.23,
  "pitch": 2.15,
  "gForce": 1.02,
  "ax": 0.123,
  "ay": -0.045,
  "az": 9.782,
  "gx": 0.001,
  "gy": -0.003,
  "gz": 0.002
}
FieldTypeUnitDescription
tuint32msESP32 uptime (for clock sync)
rollfloatdegreesRoll angle (-180° to +180°)
pitchfloatdegreesPitch angle (-90° to +90°)
gForcefloatGResultant G-force (1.0 = level)
ax/ay/azfloatm/s²Accelerometer raw values
gx/gy/gzfloatrad/sGyroscope raw values

Firmware [blocked]

The ESP32 firmware is an Arduino sketch (Aetherion.ino) with modular C++ components.

File Structure

text
firmware/Aetherion/
├── Aetherion.ino      # Main entry point: setup() + loop()
├── config.h           # Pin assignments, WiFi creds, constants
├── imu.cpp            # MPU6050 driver + sensor fusion
├── imu.h              # IMU data structure + API
├── graphics.cpp       # OLED rendering (PFD, boot screen, loading)
├── graphics.h         # Graphics API declarations
├── web.cpp            # HTTP + WebSocket server (LittleFS)
├── web.h              # Web server API declarations
├── rgb.cpp            # RGB LED status indicator
├── rgb.h              # RGB LED API declarations
├── sync_dashboard.ps1 # Syncs dashboard files to LittleFS data/
└── data/              # Dashboard served from LittleFS
    ├── index.html
    ├── style.css
    └── js/
        ├── app.js           # Core app: WebSocket, render loop
        ├── horizon.js        # Canvas artificial horizon
        ├── graphs.js         # Live telemetry graphs
        ├── flight-state.js   # Rule-based state detection
        ├── recorder.js       # Flight recording + IndexedDB
        ├── analysis.js       # Replay, stability, ML panels
        └── settings.js       # Persistent settings (localStorage)

Key Features

FeatureDetails
IMU SensingMPU6050 accelerometer + gyroscope via I2C (400 kHz)
Attitude Calc.Roll/Pitch via atan2 with 200-sample static calibration offset
G-ForceResultant acceleration vector magnitude normalized to G
OLED Display128×64 SH1106, drawn at 25 FPS via dedicated FreeRTOS task
PFD ElementsPitch ladder, roll arc with tick marks, aircraft symbol, turn coord.
WiFiESP32 in AP mode — SSID Aetherion, password aetherion123
WebSocketBroadcasts JSON telemetry at 50 Hz (port 81)
HTTP ServerServes dashboard from LittleFS (port 80)
FreeRTOSoledTask on Core 0 at priority 1 with I2C mutex
RGB LEDRed (boot) → Purple (init) → Blue (connecting) → Green (ready)
I2C MutexSerializes access between main loop (IMU read) and oledTask (OLED draw)

Boot Sequence

mermaid
flowchart TD
    A[Power On] --> B[Serial Init 115200]
    B --> C[initDisplay + initRGB]
    C --> D[RGB Red: Boot Screen]
    D --> E[Delay 1500ms]
    E --> F[RGB Purple: Initializing]
    F --> G[initIMU]
    G --> H[calibrateIMU 200 samples]
    H --> I[Wire.setClock 400kHz]
    I --> J[WiFi.softAP]
    J --> K[WebSocket Server on :81]
    K --> L[initFileSystem + initWebServer]
    L --> M[RGB Purple: Loading Screen 0-96]
    M --> N[RGB Blue: Ready Screen]
    N --> O[Delay 1000ms]
    O --> P[RGB Green: Ready]
    P --> Q[Create I2C Mutex]
    Q --> R[Create oledTask FreeRTOS]
    R --> S[Main Loop: 50 Hz]

Dashboard [blocked]

The web dashboard is a single-page application (SPA) written in vanilla JavaScript with no external framework dependencies. It uses HTML5 Canvas for all rendering and IndexedDB for local session storage.

Architecture

mermaid
graph TB
    subgraph "Dashboard Modules"
        App[app.js<br/>Core Engine<br/>WebSocket, Render Loop]
        Horizon[horizon.js<br/>Artificial Horizon<br/>Canvas 2D]
        Graphs[graphs.js<br/>Live Telemetry Graphs<br/>Canvas 2D]
        FlightState[flight-state.js<br/>State Detection<br/>Rule-based]
        Recorder[recorder.js<br/>Flight Recorder<br/>IndexedDB]
        Analysis[analysis.js<br/>Replay + AI Analysis]
        Settings[settings.js<br/>Config + localStorage]
        Style[style.css<br/>Dark Theme UI]
    end

    App --> Horizon
    App --> Graphs
    App --> FlightState
    App --> Recorder
    App --> Analysis
    App --> Settings
    App --> Style
    App -->|WebSocket| ESP32[ESP32 Telemetry]
    Horizon -->|registerCallback horizon| App
    Graphs -->|registerCallback graph| App
    FlightState -->|registerCallback state| App
    Recorder -->|registerCallback packet+graph| App
    Analysis -->|loadSession| Recorder
    Settings -->|load/save| App

Render Loop Architecture

The dashboard uses a throttled multi-rate render loop driven by requestAnimationFrame:

ComponentRateTriggerDescription
Artificial Horizon60 FPSrequestAnimationFrameCanvas redraw, smooth attitude
Telemetry Readouts15 HzTime-based throttleText updates for accel/gyro/attitude
Live Graphs15 FPSTime-based throttleCanvas graph plots (roll/pitch/G/gyro)
Flight State10 HzTime-based throttleRule-based state detection
Diagnostics2 HzTime-based throttlePacket count, FPS, latency, uptime
Packet Callbacks50 HzOn every packetRecording data capture

Tab Navigation

The dashboard has four tabs:

  1. LIVE — Real-time attitude indicator, telemetry panel, live graphs, flight state, and status bar
  2. RECORD — Flight recording controls, session management, recording preview graph
  3. ANALYSIS — Flight replay, stability metrics, control analysis, sensor health, system performance, AI analysis panel
  4. SETTINGS — Connection configuration, telemetry settings, display options

Flight States

The rule-based flight state detector identifies these states:

StateColorTrigger Condition
LEVELGreenRoll < 30°, pitch < 8°, G within 0.5–1.8
TURNING LEFTCyanRoll < -30°
TURNING RIGHTCyanRoll > +30°
CLIMBINGAmberPitch > 15°
DESCENDINGAmberPitch < -15°
PITCH-UPOrangePitch > 8°
PITCH-DOWNOrangePitch < -8°
ROLLINGMagenta
RECOVERINGCyanRoll < 15° and trending toward level
UNSTABLERedG-force > 1.8 or < 0.5

AI Analysis Models

The Analysis tab supports four ML models for flight state classification:

ModelUse CaseAccuracy Estimate
Random ForestFast, robust baseline classification~92%
XGBoostGradient boosting, handles edge cases~94%
Neural NetworkDeep pattern recognition~90%
SVMLinear separability, low compute~88%

Stability Metrics

MetricDescription
Roll RMSRoot-mean-square roll deviation
Pitch RMSRoot-mean-square pitch deviation
Angular-rate RMSRMS of combined gyroscope rates (gx+gy+gz)
Roll PeakMaximum absolute roll
Pitch PeakMaximum absolute pitch
G-Force PeakMaximum G-force recorded
Stability ScoreComposite 0-100 score: 100 - weighted deviation penalties
Data QualitySensor health score factoring missing packets, saturation, noise

Control Analysis

MetricDescription
Roll ControlRMS-based quality rating (Good/Moderate/Fair/Poor)
Pitch ControlRMS-based quality rating
Correction RateFrequency of roll direction changes per second
OscillationStd dev of roll deltas (control stability)
RecoveryRMS of roll in final 20% of flight (settling quality)

Screenshots [blocked]

Dashboard — Live Tab

Real-time attitude indicator with artificial horizon, telemetry panel, live graphs, flight state, and status bar:

Dashboard Live Tab

Dashboard — Record Tab

Flight recording controls, session list, and recording preview graph:

Dashboard Record Tab

Dashboard — Analysis Tab

Flight replay, stability metrics, control analysis, sensor health, system performance, and AI analysis:

Dashboard Analysis Tab

Dashboard — Settings Tab

Connection settings (ESP32 IP, WebSocket port), telemetry configuration, and display options:

Dashboard Settings Tab

UI Test Screenshots

Automated Playwright test captures of all dashboard states:

Full Dashboard — Initial render of the complete dashboard:

UI Test: Full Dashboard

Panel Hover — 3D perspective transform on panel hover:

UI Test: Panel Hover

Record Tab — Recording interface with session list:

UI Test: Record Tab

Analysis Tab — Flight replay and analysis panels:

UI Test: Analysis Tab

Settings Tab — Configuration panels:

UI Test: Settings Tab

Live Tab (returned) — Back to live attitude display:

UI Test: Live Tab Returned

PCB Design [blocked]

KiCad project files for the Aetherion hardware. The PCB integrates all components on a single 2-layer board.

PCB View Gallery

Schematic — Complete circuit schematic:

PCB Schematic

PCB Layout (Routed) — Top-layer copper routing:

PCB Routed Layout

3D Render — Isometric 3D view of the assembled PCB:

PCB 3D Render

Circuit Diagram (Concept) — Conceptual circuit overview:

Circuit Diagram

PCB File Structure

text
pcb/
├── schematic/           # KiCad schematic files (.kicad_sch)
├── pcb-layout/          # KiCad PCB layout files (.kicad_pcb, .kicad_pro)
├── library/
│   ├── SSD1306-128x64_OLED.kicad_sym           # OLED symbol
│   ├── SSD1306.pretty/
│   │   └── 128x64OLED.kicad_mod               # OLED footprint
│   └── AeroGyro.pretty/
│       └── LED_D5.0mm-4_RGB_AeroGyro.kicad_mod.pretty/
│           └── LED_D5.0mm-4_RGB.kicad_mod     # RGB LED footprint
└── manufacturing/       # Gerber and drill files (for fabrication)

Design Features

FeatureDetails
Form FactorESP32 DevKit compatible
IMU Connector4-pin I2C header (SDA, SCL, VCC, GND) for MPU6050
OLED ConnectorI2C header (4-pin: SDA, SCL, VCC, GND) for 0.96" SSD1306 display
RGB LEDCommon cathode, 3-pin current-limited output
I2C Pull-ups4.7kΩ resistors on SDA and SCL
PowerUSB-C input with onboard 3.3V regulator
DimensionsCompact handheld form factor

Hardware [blocked]

Components

ComponentSpecification
MCUESP32 DevKit (dual-core, 240 MHz, 520 KB RAM)
IMUMPU6050 (3-axis accelerometer + 3-axis gyroscope)
Display0.96" OLED, 128×64 pixels, SSD1306/SH1106, I2C (0x3C)
RGB LEDCommon Cathode, 3-pin (Red: GPIO19, Green: GPIO18, Blue: GPIO17)
WiFi802.11 b/g/n, Access Point mode
I2C BusSDA: GPIO21, SCL: GPIO22, Clock: 400 kHz
WebSocketPort 81 — telemetry broadcast
HTTP ServerPort 80 — dashboard serving via LittleFS

Quick Start [blocked]

Prerequisites

  • Arduino IDE 2.0+ (or PlatformIO)
  • ESP32 board package (https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json)
  • Libraries: Adafruit MPU6050, Adafruit Unified Sensor, U8g2, ESP Async WebServer, LittleFS, WebSockets, WebServer

Setup Steps

  1. Install ESP32 board support in Arduino IDE:

    • File → Preferences → Additional Boards Manager URLs
    • Add: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
    • Tools → Board → Boards Manager → Install esp32
  2. Install required libraries via Library Manager:

    text
    Adafruit MPU6050
    Adafruit Unified Sensor
    U8g2 (by olikraus)
    LittleFS_esp32
    WebSockets
  3. Open the firmware:

    text
    firmware/Aetherion/Aetherion.ino
  4. Upload to ESP32 via Arduino IDE.

  5. Connect to Wi-Fi:

    • Network: Aetherion
    • Password: aetherion123
  6. Open the dashboard:

    • Navigate to http://192.168.4.1 in any browser

Syncing Dashboard Updates

When dashboard files are updated during development, sync them to the firmware's LittleFS data folder before uploading:

powershell
# From the firmware directory
.\Aetherion\sync_dashboard.ps1

Then upload via Arduino IDE: Tools → ESP32 Sketch Data Upload


Development [blocked]

Project Structure

text
Aetherion/
├── firmware/                    # ESP32 Arduino firmware
│   └── Aetherion/
│       ├── Aetherion.ino        # Main sketch
│       ├── config.h             # Configuration
│       ├── imu.cpp / imu.h      # IMU sensor driver
│       ├── graphics.cpp / graphics.h  # OLED rendering
│       ├── web.cpp / web.h      # HTTP/WebSocket server
│       ├── rgb.cpp / rgb.h      # RGB LED control
│       ├── sync_dashboard.ps1   # Dashboard sync script
│       └── data/                # Dashboard files (LittleFS)
├── dashboard/                   # Standalone web dashboard (dev)
│   ├── index.html
│   ├── style.css
│   └── js/
│       ├── app.js               # Core application
│       ├── horizon.js           # Artificial horizon
│       ├── graphs.js            # Flight graphs
│       ├── flight-state.js      # Flight state detection
│       ├── recorder.js          # Flight recording
│       ├── analysis.js          # AI analysis
│       └── settings.js          # Configuration
├── aetherion-ui-test/           # Playwright UI tests
│   ├── index.html               # Test UI (with GSAP + 3D animations)

Firmware Development

The firmware follows a modular architecture:

  1. Aetherion.ino — Orchestrates all modules in setup() and loop(). The main loop is intentionally lightweight: HTTP handling, WebSocket servicing, IMU reads (mutex-protected), and 50 Hz telemetry broadcast.
  2. imu.cpp — MPU6050 driver using Adafruit library. Performs 200-sample calibration on boot, computes roll/pitch via atan2, and calculates resultant G-force.
  3. graphics.cpp — U8g2-based OLED renderer. Draws a full PFD (Primary Flight Display) including pitch ladder, roll arc, aircraft symbol, battery indicator, and Wi-Fi icon.
  4. web.cpp — Serves dashboard files from LittleFS over HTTP and broadcasts telemetry over WebSocket (port 81).
  5. rgb.cpp — Simple RGB LED status indicator using direct GPIO control.

Dashboard Development

The dashboard is a vanilla JavaScript SPA with no framework dependencies. Key architectural decisions:

  • Decoupled architecture: WebSocket packet reception is completely separate from the render loop. Packets update a central AG state object; the render loop reads from it.
  • Throttled multi-rate rendering: Different UI components update at different rates to balance performance and responsiveness.
  • No external dependencies (in production firmware): The production dashboard uses zero external libraries. The aetherion-ui-test/ variant adds GSAP for 3D animation testing.

UI Testing [blocked]

The aetherion-ui-test/ directory contains an enhanced version of the dashboard with GSAP-powered 3D animations, used for visual testing.

Running Tests

bash
cd aetherion-ui-test
npm install playwright
node test-ui.js

The test script uses Playwright to:

  1. Load the dashboard HTML in a headless Chromium browser
  2. Capture screenshots of the full dashboard and each tab
  3. Test 3D panel hover effects
  4. Verify JavaScript module loading (GSAP, Animations, Horizon, etc.)
  5. Check for JavaScript errors
  6. Validate CSS perspective transforms

Test Screenshots

#ScreenshotTabDescription
101-full-dashboard.pngLiveFull dashboard initial render
202-panel-hover.pngLive3D perspective on panel hover
303-record-tab.pngRecordRecording interface
404-analysis-tab.pngAnalysisFlight replay + analysis panels
505-settings-tab.pngSettingsConfiguration panels
606-live-tab-returned.pngLiveReturn to live attitude display

License [blocked]

MIT License — see LICENSE for details.

Copyright (c) 2026 Aetherion

Parts

7
QtyValueFootprintReferences
3220Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR1, R2, R3
1ESP32-DEVKITC-32DESP32_DEVKITC_32D:MODULE_ESP32-DEVKITC-32DU1
1LED_RGBKLED_THT:LED_D5.0mm-4_RGBD1
1MPU6050Connector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_VerticalJ1
1SSD1306SSD1306:128x64OLEDBrd1

Questions

How big is the Aether PCB?

It measures 68.5 × 70.5 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Aether use?

7 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Aether KiCad files?

From the GavishtK/AeThEriON repository on GitHub, at the commit this page was made from: the board is pcb/pcb-layout/Aether.kicad_pcb and its schematic pcb/schematic/Aether.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Aether design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

Similar boards

  • 2 layersEncoder, the printed circuit board in 3D

    Encoder

    byrantech/laptop

    anyon_e, a highly integrated, high end, open source laptop. Attempt the impossible.

    7 parts4.3kMIT
  • 2 layers40 × 20 mmSensor smd, the printed circuit board in 3D

    Sensor smd

    scottbez1/splitflap

    DIY split-flap display

    7 parts4.2k
  • 2 layers19.8 × 30 mmZ limit, the printed circuit board in 3D

    Z limit

    opulo-inc/lumenpnp

    The LumenPnP is an open source pick and place machine.

    7 parts3.7k
  • 2 layers35.6 × 58.2 mmDisplay Carrier, the printed circuit board in 3D

    Display Carrier

    AxxAxx/AxxSolder

    STM32 Based soldering station for JBC cartridges, 9-24 VDC and USB-PD power

    7 parts1.7kGPL-3.0
  • 2 layers20.3 × 16.3 mmMap MPX, the printed circuit board in 3D

    Map MPX

    rusefi/rusefi

    rusefi - GPL internal combustion engine control unit

    7 parts1.2k
  • 2 layers26 × 44 mmCompact carrier board, the printed circuit board in 3D

    Compact carrier board

    jamro/tiny-engineer

    A small desktop robot that brings an AI coding assistant to life, physically acting out when it reads files, thinks, writes code, and finishes work.

    7 parts1.1k
  • 2 layers26.4 × 53.8 mmAtari pickup, the printed circuit board in 3D

    Atari pickup

    hoglet67/RGBtoHDMI

    Bare-metal Raspberry Pi project that provides pixel-perfect sampling of Retro Computer RGB/YUV video and conversion to HDMI

    7 parts1kGPL-3.0
  • 2 layersRj45 breakout, the printed circuit board in 3D

    Rj45 breakout

    rene-dev/stmbl

    AC Servo Driver for STM32F4

    7 parts990GPL-3.0