Skip to the content
PCBKitNew board
2 layers88.6 × 69.9 mmExpressionController, the printed circuit board in 3D

ExpressionController

amonbenson/expad

A four-jack USB MIDI adapter for expression and sustain pedals, built on a Raspberry Pi Pico 2 W. It works out what is plugged into each jack - whichever contact a pedal's wiper is on, and whether it is a potentiometer…

Size
88.6 × 69.9 mm
Copper layers
2
Thickness
1.58 mm
Parts
147
Nets
158
Pads
562
Tracks, vias
1,136, 299
Pours
8
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
8 Aug 2026
Updated
14 Oct 2026

Overview

ExpressionController is an open-source printed circuit board by amonbenson, from the amonbenson/expad repository on GitHub, published under the MIT licence. It is a 2-layer board of 88.6 × 69.9 mm with 147 parts on 158 nets, routed with 1,136 tracks and 299 vias.

It is built around the 74AHCT1G125SE, AD7718BRZ and 74HC595DRG, with the ADP7142AUJZ-2.5-R7, ADP7142AUJZ-3.3-R7 and ADP7142AUJZ-5.0-R7 among its other parts. Its parts include 53 capacitors, 41 resistors, 18 ICs, 7 diodes and 5 connectors. It belongs with the RP2040 boards of this library.

Main components

11

README

README.md

expad - Expression Adapter

A four-jack USB MIDI adapter for expression and sustain pedals, built on a Raspberry Pi Pico 2 W. It works out what is plugged into each jack - whichever contact a pedal's wiper is on, and whether it is a potentiometer, a switch or a two-wire rheostat - and sends every pedal's position as a MIDI control change, ~190 times per second. A WiFi access point serves a web interface for watching the jacks and changing the settings live.

Hardware

The PCB is the KiCad project in hardware/. Each jack's tip, ring and sleeve (plus the tip's switch contact, for plug detection) can be switched to a shared 1 kΩ pull-up to the 2.5 V reference or a 1 kΩ pull-down, and is read back by one of two AD7718 24-bit ADCs. The four WS2812B LEDs below the jacks glow a dim white while a plug is in but no known pedal is behind it. A recognised pedal is announced for a second in its own color - purple for an expression pedal, lime for a footswitch, yellow for a rheostat - after which the LED shows the value it sends, from dark red at 0 through red, orange and yellow to white at 127. They run off a linear regulator, so the firmware caps them at ~4% brightness.

Supported pedals

PedalCableShown asValue
Expression pedal (potentiometer), wiper on tip or ringstereo (TRS)Trackingwiper position, counting up away from the sleeve
Sustain pedal / footswitchmono (TS) or stereoSwitch100% closed, 0% open
Two-wire (rheostat) expression pedalmono or stereoRheostatresistance against the nearest standard value (10k, 25k, 50k ...)
Anything else (dual footswitches, other wirings)Other pedalnone

Pedals are recognised within ~0.1 s of being plugged in, and unplugging is noticed just as fast.

  • A normally-closed sustain pedal, or an expression pedal wired the other way round, needs Invert.
  • A rheostat pedal on a mono cable first reads as a potentiometer at rest, until its resistance has changed by a fifth.
  • A potentiometer pedal needs a stereo cable: with a mono one, most pedals short their ring to the sleeve, which leaves a resistance that rises and falls again over the travel.
  • A mono cable with nothing at the other end reads as a released switch.

Using it

  1. Plug the Pico into a computer over USB. It shows up as a USB MIDI device; by default the first two jacks send CC 11 (Expression) and the last two CC 1 (Modulation), all on MIDI channel 1.
  2. Join the WiFi network Expression Adapter (password: the one it was built with, see below). Phones, tablets and computers open the interface by themselves as the network's sign-in page; otherwise open http://192.168.4.1.
  3. Per jack, set the MIDI channel and controller, Invert, and the Range: move the pedal to one end and press Min, to the other and press Max, so its travel covers the full MIDI range. Drive bends the response against a pedal's nonlinear track: centered is linear, turning it right makes the value rise early in the travel, left late (double-click resets it). Wiper only matters for pedals whose wiper is on the ring or sleeve and that rest on an end stop when plugged in; Auto handles the common wirings. The LED slider sets the brightness.

The topology panel on the right draws the selected jack's measured network.

Setup

Needs Rust, Node.js (see engines in web/package.json) for the web interface, and a debug probe (e.g. a Raspberry Pi Debug Probe) on the Pico's SWD pins.

bash
rustup target add thumbv8m.main-none-eabihf
cargo install probe-rs-tools --locked
cp .env.example .env   # then set EXPAD_WIFI_PASSWORD (8-63 characters)

Building and flashing

bash
cargo run --bin expression_controller   # build, flash and show the log
cargo run --bin expression_controller --features no-wifi   # the same with the radio off
cargo build --no-default-features       # without the web interface (no Node.js needed)

The other programs in src/bin/ test parts of the board:

ProgramWhat it does
detect_pin_mappingchecks every contact's switches and ADC input against the wiring table (unplug all jacks)
captureholds every contact in one state and logs every ADC input, for noise measurements
adc_characterizationcompares ADC filter rates and SPI settings on a pedal in jack 1
potentiometerreads a pedal in jack 1 and shows its position on the LEDs
rainbowLED strip test
midi_loopbackechoes every USB MIDI message back to the host
web_interfacethe web interface with made-up data

Development

bash
cargo test -p expad-topology --target x86_64-pc-windows-msvc   # solver tests, on your host triple
cargo fmt
cargo clippy --all-features
cd web && npm run dev:mock   # web interface against a simulated device, no hardware needed

AGENTS.md describes the repository in detail, and docs/fast-tracking.md the measurements and design behind the pedal detection.

General TODOs

  • missing standard trait implementations for all types (Debug, Default, Clone, Copy, PartialEq, Eq, etc.)
  • missing with_field builder methods for all config structs
  • thiserror (nostd) or similar better error handling

Parts

147
QtyValueFootprintReferences
24100nCapacitor_SMD:C_0805_2012MetricC11, C13, C16, C18, C20, C39, C40, C41, C42, C47, C48, C49, C50, C51, C52, C53 +8
1710kResistor_SMD:R_0805_2012MetricR15, R16, R17, R18, R23, R24, R25, R26, R31, R32, R33, R34, R39, R40, R41, R42 +1
1610nCapacitor_SMD:C_0805_2012MetricC23, C24, C25, C26, C27, C28, C29, C30, C31, C32, C33, C34, C35, C36, C37, C38
15TestPointTestPoint:TestPoint_THTPad_D1.5mm_Drill0.7mmTP1, TP2, TP3, TP4, TP5, TP6, TP7, TP8, TP9, TP10, TP11, TP12, TP13, TP14, TP15
1247Resistor_SMD:R_0805_2012MetricR3, R4, R5, R6, R7, R8, R9, R10, R46, R47, R48, R49
81k 0.1%Resistor_SMD:R_0805_2012MetricR50, R51, R52, R53, R54, R55, R56, R57
8TMUX1511PWRPackage_SO:TSSOP-14_4.4x5mm_P0.65mmU15, U16, U17, U18, U19, U20, U21, U22
418pCapacitor_SMD:C_0805_2012MetricC14, C15, C21, C22
474HC595DRPackage_SO:SOIC-16_3.9x9.9mm_P1.27mmU6, U8, U10, U12
4AudioJackJack_6.35mm_Neutrik_NMJ6HFD4_Horizontal:Jack_6.35mm_Neutrik_NMJ6HFD4_HorizontalJ2, J3, J4, J5
4WS2812BLED_SMD:LED_WS2812B_PLCC4_5.0x5.0mm_P3.2mmD4, D5, D6, D7
310uCapacitor_SMD:C_0805_2012MetricC2, C10, C17
32.2uCapacitor_SMD:C_0805_2012MetricC4, C6, C8
3SolderJumper_2_OpenJumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mmJP1, JP2, JP3
20Resistor_SMD:R_0805_2012MetricR44, R45
232.768kHzMS1V-T1K:MS1V-T1KY1, Y2
24.7uCapacitor_SMD:C_0805_2012MetricC3, C5
2AD7718BRZPackage_SO:SOIC-28W_7.5x17.9mm_P1.27mmU4, U5
1100kResistor_SMD:R_0805_2012MetricR1
1220Resistor_SMD:R_0805_2012MetricR43
147uCapacitor_SMD:CP_Elec_6.3x5.8C1
174AHCT1G125Package_TO_SOT_SMD:SOT-353_SC-70-5U14
1ADP7142AUJZ-2.5Package_TO_SOT_SMD:TSOT-23-5U3
1ADP7142AUJZ-3.3Package_TO_SOT_SMD:TSOT-23-5U1
1ADP7142AUJZ-5.0Package_TO_SOT_SMD:TSOT-23-5U2
1BZX84C15-7-FPackage_TO_SOT_SMD:SOT-23D2
1BarrelJackConnector_BarrelJack:BarrelJack_CUI_PJ-102AH_HorizontalJ1
1DMP3099L-7Package_TO_SOT_SMD:SOT-23Q1
1MF-MSMF050-2Fuse:Fuse_1812_4532MetricF1
1PMEG6010ELRDiode_SMD:Nexperia_CFP3_SOD-123WD3
1RaspberryPi_PicoPico_2W_with_Header:Pico_2W_with_HeaderA1
1SMBJ15CADiode_SMD:D_SMBD1

Questions

How big is the ExpressionController PCB?

It measures 88.6 × 69.9 mm and has 2 copper layers, 1.58 mm thick.

What parts does the ExpressionController use?

147 parts, built around the 74AHCT1G125SE, AD7718BRZ, 74HC595DRG and ADP7142AUJZ-2.5-R7. 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 ExpressionController KiCad files?

From the amonbenson/expad repository on GitHub, at the commit this page was made from: the board is hardware/ExpressionController.kicad_pcb and its schematic hardware/AnalogFrontend.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the ExpressionController 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

  • 4 layers49.4 × 111.4 mmEeg hardware v1, the printed circuit board in 3D

    Eeg hardware v1

    es-ude/eeg-hardware

    Repo of the Custom Hardware Design Files of the EEG-based Gaming Controller

    412 partsMIT
  • 2 layers48.8 × 18.5 mmCurmea, the printed circuit board in 3D

    Curmea

    Ledger-Donjon/curmea

    To analyze the power consumption of a component, it is common to measure the current going to the ground by placing a small resistor and measuring the voltage across it.

    30 parts2LGPL-3.0
  • 2 layers177.8 × 82.6 mmBaku, the printed circuit board in 3D

    Baku

    Demonpore-sys/baku

    49 parts
  • 4 layers145 × 73 mmDashboard, the printed circuit board in 3D

    Dashboard

    broncoracing/dashboard

    BR23 Dashboard PCB/Firmware

    284 parts
  • 2 layers160 × 120 mmSTM, the printed circuit board in 3D

    STM

    jherkenhoff/STM

    DIY scanning tunneling microscope (STM)

    307 parts88
  • 4 layers300 × 270 mmTbox, the printed circuit board in 3D

    Tbox

    charlieh0tel/ee_stuff

    440 partsBSD-3-Clause
  • 2 layers78 × 62.5 mmScr23-sens to can, the printed circuit board in 3D

    Scr23-sens to can

    m888r/scr23-analog-to-can

    USC Racing 2023 FSAE Car Analog/Digital to CAN module

    62 parts