Skip to the content
PCBKitNew board
2 layers68.1 × 30.3 mmFinalMidiGuitar, the printed circuit board in 3D

FinalMidiGuitar

Alejo-end/midiguitar

A time-of-flight distance sensor embedded in a Squier Mustang electric guitar, turning hand gestures into MIDI messages for controlling effects in Max/MSP, Ableton, or any MIDI host.

Size
68.1 × 30.3 mm
Copper layers
2
Thickness
1.6 mm
Parts
51
Nets
16
Pads
94
Tracks, vias
354, 0
Pours
1
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
1 Apr 2026
Updated
3 Nov 2026

Overview

FinalMidiGuitar is an open-source printed circuit board by Alejo-end, from the Alejo-end/midiguitar repository on GitHub. It is a 2-layer board of 68.1 × 30.3 mm with 51 parts on 16 nets, routed with 354 tracks and 0 vias.

It is built around the SN74LVC1T45DBVRE4. Its parts include 3 capacitors, 3 connectors, 2 switches, 1 resistor and 1 IC.

Main components

1

README

README.md

MIDI Guitar

A time-of-flight distance sensor embedded in a Squier Mustang electric guitar, turning hand gestures into MIDI messages for controlling effects in Max/MSP, Ableton, or any MIDI host.

How it works

Wave your hand over the VL53L1X sensor mounted near the pickups. The firmware converts distance and hand speed into MIDI CC and pitch bend messages, sent over USB or Bluetooth LE. A rotary encoder navigates a 4-page OLED menu; a bypass button mutes output; a DIP switch selects the default transport.

MIDI output

MessageDefault CCSourceUse case
CCCC20Hand distanceContinuous modulation (wah, filter, delay)
CCCC21Hand velocitySpeed-based effects (resonance, attack)
Pitch Bend--Hand distance14-bit smooth pitch shifting

MIDI channel, CC numbers, distance range, and response curve are all adjustable at runtime via the Settings page. Changes persist across power cycles (saved to flash).

Hardware

ComponentPartPurpose
MCUSeeed XIAO ESP32-S3USB-OTG + BLE 5.0
SensorVL53L1X (or VL53L4CD)I2C time-of-flight, 10-500mm
DisplaySSD1306 128x64 OLED4-page Elektron-style UI
EncoderRotary w/ push buttonPage navigation + parameter control
LED ring16x WS2812B NeoPixelColor-coded distance bar + animations
Bypass btnMomentary push buttonMute MIDI output
Edit btnMomentary push buttonToggle edit mode on Settings page
Transport SWSPDT slide switchUSB / BLE default at boot
Pickup SW (x2)SPDT slide switchesNeck / Bridge on/off (analog, not GPIO)
BatteryLiPo (optional)Charges via XIAO built-in circuit

Wiring

GPIO pinout

FunctionXIAO PinGPIONotes
I2C SDAD45Shared: OLED + VL53L1X
I2C SCLD56Shared: OLED + VL53L1X
NeoPixel DIND1216-LED ring, data in
Transport SWD23DIP switch, INPUT_PULLUP
Bypass buttonD34Momentary, INPUT_PULLUP
Encoder AD87Quadrature channel A
Encoder BD98Quadrature channel B
Encoder pushD109Encoder built-in button
VL53L1X XSHUTD643Sensor reset/address set
Edit buttonD744Momentary, INPUT_PULLUP

I2C bus (400kHz)

DeviceAddress
SSD1306 OLED0x3C
VL53L1X0x30 (remapped from 0x29 via XSHUT)

Button wiring

All buttons use the internal pullup resistor (INPUT_PULLUP). No external resistor required:

text
GPIO pin ──── ┤ ├ ──── GND
             button

Firmware versions

Four versions in code/, each building on the last:

VersionFolderDescription
v1tof_midi/Minimal: distance to CC20 over USB
v2tof_midi_v2/Adds velocity CC, pitch bend, BLE, NeoPixel bar
v3tof_midi_v3/Adds OLED display
v4tof_midi_v4/Full UI: encoder menu, settings page, NVS persistence, animations

v4 features

  • 4-page OLED UI (Elektron Digitakt-inspired)
  • Rotary encoder navigation with long-press bypass
  • Runtime-adjustable settings saved to flash (NVS)
  • NeoPixel gradient arc with velocity pulse and mode-change wipe
  • Bypass breathing animation and BLE connection flash
  • Synchronized OLED + NeoPixel startup animation
  • Sensor error recovery (retries, graceful degradation)
  • OLED screensaver after 60s inactivity
  • Hardware watchdog (5s auto-reset on hang)
  • DIP switch live-read (no reboot needed)
  • Toast overlay notifications on setting changes

User interface

Controls

InputAction
Encoder rotateAdjust setting on current page
Encoder short-press (<500ms)Next page
Encoder long-press (>500ms)Toggle bypass (mute)
Bypass buttonToggle bypass (mute)
Edit buttonEnter/exit edit mode on Settings page
Transport DIP switchSet default transport (read at boot + live)

OLED pages

Navigate pages with encoder push. The active page is shown by a tall white block in the page indicator bar at the bottom; inactive pages show thin dashes.

Page 1 -- Live

Real-time sensor data. Encoder rotation adjusts LED brightness.

text
┌────────────────────────────────────────┐
│▌USB▐ ▌CC▐ Ch1              ▌MUTE▐     │
│────────────────────────────────────────│
│DST ▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓ ░ ░ ░ ░    102  │
│────────────────────────────────────────│
│VEL ▓▓▓ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░    38  │
│────────────────────────────────────────│
│CC20  CC21                  245mm       │
│────────────────────────────────────────│
│▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ░ ░ ░ ░ ░ ░ ░   │
│              █ _ _ _                   │
└────────────────────────────────────────┘
  • Status bar: Transport badge, mode badge, channel, BLE indicator, mute/error badge
  • DST/BND bar: Segmented distance bar + numeric value
  • VEL bar: Segmented velocity bar + numeric value
  • Info row: CC numbers (or bend value) + raw distance in mm
  • Activity meter: Full-width segmented bar with quarter-mark ticks
  • When muted: bars show diagonal stripes, meter shows dashed outline
Page 2 -- Transport

Select MIDI output. Encoder rotation cycles USB / BLE / Both.

text
┌────────────────────────────────────────┐
│█████████████████████████████████████████│
│█       OUTPUT                        █│
│█████████████████████████████████████████│
│ ╭────────╮  ╭────────╮  ╭────────╮    │
│ │  USB   │  │███BLE██│  │  BOTH  │    │
│ │  icon  │  │██icon██│  │  icon  │    │
│ │        │  │████████│  │        │    │
│ ╰────────╯  ╰████████╯  ╰────────╯    │
│              _ █ _ _                   │
└────────────────────────────────────────┘
Page 3 -- Mode

Select CC or Pitch Bend mode. Encoder rotation toggles.

text
┌────────────────────────────────────────┐
│█████████████████████████████████████████│
│█       MODE                          █│
│█████████████████████████████████████████│
│ ╭──────────────────╮ ╭──────────────╮  │
│ │██ staircase ████ │ │   arrows     │  │
│ │██ waveform █████ │ │   ↑ ─── ↓   │  │
│ │█████████CC██████ │ │    BEND      │  │
│ ╰██████████████████╯ ╰──────────────╯  │
│              _ _ █ _                   │
└────────────────────────────────────────┘
Page 4 -- Settings

Editable parameter list. Encoder rotation moves cursor. Press edit button to enter edit mode (value blinks with < > arrows), rotate to change value, press edit button again to confirm. Settings auto-save to flash 2 seconds after the last change.

text
┌────────────────────────────────────────┐
│█████████████████████████████████████████│
│█   SETTINGS                    EDIT  █│
│█████████████████████████████████████████│
│ CC Dist                           20  │
│ CC Vel                            21  │
│█Curve████████████████████████<LIN>████│
│ LED Brt                           40  │
│ Invert                           OFF  │
│              _ _ _ █                   │
└────────────────────────────────────────┘
SettingRangeDefaultDescription
MIDI Ch1--161MIDI channel for all output
CC Dist0--12720CC number for distance
CC Vel0--12721CC number for velocity
Dist Min5--200 mm10Sensor near threshold
Dist Max100--1000 mm500Sensor far threshold
CurveLIN / LOG / EXPLINResponse curve shape
LED Brt5--25540NeoPixel ring brightness
InvertOFF / ONOFFFlip distance mapping (closer = higher value)

Toast notifications

Brief centered overlay messages appear for 500ms on any page when settings change:

EventToast text
Bypass onMUTED
Bypass offACTIVE
Transport changeUSB / BLE / BOTH
Mode changeCC / BEND
Sensor failureNO SENSOR

NeoPixel ring

16-LED WS2812B ring with color-coded animations:

StateAnimationColor
USB + CC modeGradient arc (bright tip, dim tail)Green
USB + Pitch BendGradient arcPurple
BLE + CC modeGradient arcBlue
BLE + Pitch BendGradient arcCyan
USB+BLE + CCGradient arcTeal
USB+BLE + PBGradient arcViolet
Bypassed (muted)Sine-wave breathingAmber
BLE scanningTwo-LED chase spinnerBlue
BLE connectedFull ring flash (200ms)Blue
Mode/transport changeClockwise wipe (150ms)New mode color
High velocity (>100)Leading LED flashWhite
Sensor errorAlternating blinkRed

Startup sequence

The OLED and NeoPixel ring play a coordinated 4-phase boot animation:

  1. Line sweep -- horizontal line draws across OLED center; single LED spins around ring
  2. Box expand -- rounded rectangle grows from center line; ring fills outward with gradient
  3. Typewriter -- "M I D I G U I T A R" types in character by character; ring pulses gently
  4. Fade out -- black bars close from top and bottom; ring fades to black

Sensor processing

text
VL53L1X raw distance (mm)
    │
    ▼
EMA smoothing (alpha = 0.2)
    │
    ▼
Normalize to 0.0--1.0 (distMin → distMax range)
    │
    ▼
Apply curve (linear / log / exp)
    │
    ▼
Optional invert (1.0 - value)
    │
    ├──► CC mode:  scale to 0--127, send CC
    └──► PB mode:  scale to 0--16383, send Pitch Bend

Velocity = |delta EMA| per poll cycle
    deadzone: < 2mm → 0
    cap: 30mm → 127

Reliability

  • Sensor recovery: If VL53L1X fails to initialize, retries 3 times before falling back to display-only mode (OLED and ring still work, MIDI is disabled). An ERR badge appears on the Live page.
  • Watchdog: 5-second hardware watchdog timer auto-resets the ESP32 on hang.
  • Screensaver: OLED blanks after 60 seconds of inactivity. Wakes on encoder, button, or sensor movement.
  • Flash persistence: Settings saved to ESP32 NVS with 2-second write debounce to prevent flash wear from rapid encoder scrolling.
  • DIP live-read: Transport DIP switch is polled every 200ms in the main loop -- no reboot needed to change transport.

Building

Arduino IDE

  1. Board: XIAO_ESP32S3
  2. USB Mode: USB-OTG (TinyUSB)
  3. Install libraries:
    • SparkFun VL53L1X
    • Adafruit NeoPixel
    • Adafruit SSD1306
    • Adafruit GFX
  4. Upload

Arduino CLI

bash
arduino-cli compile -b esp32:esp32:XIAO_ESP32S3 \
  --build-property "build.extra_flags=-DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0" \
  code/tof_midi_v4/

arduino-cli upload -b esp32:esp32:XIAO_ESP32S3 -p /dev/cu.usbmodem* \
  code/tof_midi_v4/

PCB

KiCad 9 project files in the root directory (midiguitar.kicad_sch, midiguitar.kicad_pcb). See HARDWARE.md for the full hardware specification and PCB_BUILD_PLAN.md for the build guide with BOM.

Parts

51
QtyValueFootprintReferences
18, , , , , , , , , , , , , , , +2
2100nFPCM_fab:C_1206C1, C2
1100uFPCM_fab:C_1206C3
1330PCM_fab:R_1206R1
1BTNPCM_fab:Button_Omron_B3SN_6.0x6.0mmSW1
1Module_XIAO_Generic_SocketSMDPCM_fab:Module_XIAO_Generic_SocketSMDM1
1NeoPixelPCM_fab:PinHeader_01x04_P2.54mm_Vertical_THT_D1mmJ1
1NeoPixelPCM_fab:PinHeader_01x03_P2.54mm_Vertical_THT_D1mmJ3
1Oled Displayfootprints:Display_128x64_096_I2CJ4
1PEC12R-4015F-S0024PEC12R-4015F-S0024:XDCR_PEC12R-4015F-S0024S1
1SN74LVC1T45DBVRfootprints:DBV0006A_NU1

The 29 most common of 51 parts.

Questions

How big is the FinalMidiGuitar PCB?

It measures 68.1 × 30.3 mm and has 2 copper layers, 1.6 mm thick.

What parts does the FinalMidiGuitar use?

51 parts, built around the SN74LVC1T45DBVRE4. 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 FinalMidiGuitar KiCad files?

From the Alejo-end/midiguitar repository on GitHub, at the commit this page was made from: the board is finalMidiGuitar/finalMidiGuitar.kicad_pcb and its schematic finalMidiGuitar/finalMidiGuitar.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the FinalMidiGuitar design in my own project?

Its repository states no licence, so its author keeps all rights: ask Alejo-end before reusing the design.

Similar boards

  • 4 layers100 × 77.4 mmWasca, the printed circuit board in 3D

    Wasca

    hitomi2500/wasca

    Sega Saturn multipurporse cartridge

    145 parts80MIT
  • 2 layers66 × 59 mmMicroPicoDrive, the printed circuit board in 3D

    MicroPicoDrive

    gusmanb/micropicodrive

    Internal microdrive replacement for the Sinclair QL

    16 parts29MIT
  • 4 layers65 × 56.5 mmHashat, the printed circuit board in 3D

    Hashat

    skot/hashat

    A Bitcoin ASIC mining HAT for Raspberry Pi

    109 parts27
  • 2 layers63.1 × 56.1 mmMicroPicoDrive, the printed circuit board in 3D

    MicroPicoDrive

    Silveriomrs/micropicodrive

    Internal Microdrive replacement for the Sinclair QL

    31 parts7MIT
  • 2 layers66 × 59 mmMicroPicoDrive, the printed circuit board in 3D

    MicroPicoDrive

    arleybls/micropicodrive-ng-hardware

    KiCad hardware design for an internal Microdrive replacement for the Sinclair QL. The device emulates a Microdrive cartridge drive using a Raspberry Pi Pico (RP2040) and stores data on a microSD card, fitting in the…

    21 parts2MIT
  • 2 layers34.2 × 63.7 mmGb link usb, the printed circuit board in 3D

    Gb link usb

    hazy2go/gb-link-usb

    Game Boy (DMG) link port to USB-C PC adapter: printer emulation, PC link, online link play. Sister project of the WiFi Game Boy cart.

    59 parts2
  • 2 layers100 × 15 mmCellLight, the printed circuit board in 3D

    CellLight

    humanHardDrive/CellLight

    A shameless copy of the NanoLeaf light

    30 parts2MIT
  • 6 layers101.8 × 80.5 mmSN-64, the printed circuit board in 3D

    SN-64

    FantomZap/SN-64

    Snes games on the n64 or m64

    410 parts1