Update MIDI Breadboard Instrument project page with GitHub repo link, breadboard photos, ESP32 pinout, and 16-track playlist
This commit is contained in:
parent
b107575b11
commit
d9127ac7d9
6 changed files with 116 additions and 55 deletions
BIN
assets/images/MIDI_FIRST.jpg
Normal file
BIN
assets/images/MIDI_FIRST.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 MiB |
BIN
assets/images/MIDI_SECOND.jpg
Normal file
BIN
assets/images/MIDI_SECOND.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
BIN
assets/images/MIDI_THIRD.jpg
Normal file
BIN
assets/images/MIDI_THIRD.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 MiB |
|
|
@ -116,6 +116,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<a class="btn btn-secondary" href="projects/midi-breadboard-instrument.html">Project Notes</a>
|
<a class="btn btn-secondary" href="projects/midi-breadboard-instrument.html">Project Notes</a>
|
||||||
|
<a class="btn btn-secondary" href="https://github.com/ertunc-ozbay/midi-breadboard-instrument" rel="noopener noreferrer">GitHub Repo</a>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -134,24 +134,25 @@
|
||||||
|
|
||||||
<p><strong>Confirmed components & tools:</strong></p>
|
<p><strong>Confirmed components & tools:</strong></p>
|
||||||
<ul class="tag-list" aria-label="Confirmed components for MIDI Breadboard Instrument">
|
<ul class="tag-list" aria-label="Confirmed components for MIDI Breadboard Instrument">
|
||||||
<li><span class="tag">MIDI-to-C Conversion Script</span></li>
|
<li><span class="tag">ESP32 Dual-Core (ESP-IDF v5.2.2)</span></li>
|
||||||
<li><span class="tag">C Code Output</span></li>
|
<li><span class="tag">Python RLE MIDI-to-C Compiler</span></li>
|
||||||
<li><span class="tag">2x Active Buzzers</span></li>
|
<li><span class="tag">16-Track Flash Symphony</span></li>
|
||||||
<li><span class="tag">1x Passive Buzzer</span></li>
|
<li><span class="tag">2x Active Buzzers (Kick/Hat)</span></li>
|
||||||
<li><span class="tag">1x Rotary Encoder</span></li>
|
<li><span class="tag">1x Passive Buzzer (LEDC PWM)</span></li>
|
||||||
<li><span class="tag">1.3" AMOLED Screen</span></li>
|
<li><span class="tag">1x Rotary Encoder (PCNT)</span></li>
|
||||||
<li><span class="tag">2x Buttons</span></li>
|
<li><span class="tag">1.3" SPI OLED (30 FPS)</span></li>
|
||||||
<li><span class="tag">2x LEDs</span></li>
|
<li><span class="tag">2x Buttons & 2x LEDs</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="project-notes">
|
<div class="project-notes">
|
||||||
<p><strong>What I am currently learning:</strong> Translating musical MIDI data into C code arrays and coordinating buzzers, a display, and physical user inputs on a breadboard.</p>
|
<p><strong>What I am currently learning:</strong> RLE compression of fragmented MIDI events into C struct arrays, acoustic transposition (+2 octaves) for passive piezo resonance, and Dual-Core FreeRTOS IPC between Core 0 (30 FPS OLED UI) and Core 1 (microsecond audio engine).</p>
|
||||||
<p><strong>Next step:</strong> Recording build notes, refining the MIDI-to-C conversion workflow, and documenting the breadboard setup.</p>
|
<p><strong>Next step:</strong> Migrating the dual-breadboard prototype onto a soldered perfboard or custom KiCad PCB.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<a class="btn btn-primary" href="midi-breadboard-instrument.html">Read Project Page</a>
|
<a class="btn btn-primary" href="midi-breadboard-instrument.html">Read Project Page</a>
|
||||||
|
<a class="btn btn-secondary" href="https://github.com/ertunc-ozbay/midi-breadboard-instrument" rel="noopener noreferrer">GitHub Repository</a>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>MIDI Breadboard Instrument — Projects — Ertunç Özbay</title>
|
<title>MIDI Breadboard Instrument (Desk Rave & 16-Track Symphony) — Projects — Ertunç Özbay</title>
|
||||||
<meta name="description" content="Project notes for the MIDI Breadboard Instrument by Ertunç Özbay: playing MIDI melodies via C code on a breadboard with buzzers, a 1.3-inch AMOLED display, and rotary encoder.">
|
<meta name="description" content="Project notes for the MIDI Breadboard Instrument (Desk Rave & 16-Track Symphony Controller) by Ertunç Özbay: Dual-Core ESP32 synthesizer in ESP-IDF v5.2.2 with RLE Python MIDI-to-C compiler, 30 FPS SPI OLED visualizer, rotary encoder, and triple-buzzer acoustic stage.">
|
||||||
<link rel="icon" type="image/svg+xml" href="../assets/images/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="../assets/images/favicon.svg">
|
||||||
<link rel="stylesheet" href="../assets/css/style.css">
|
<link rel="stylesheet" href="../assets/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
@ -48,102 +48,161 @@
|
||||||
<article>
|
<article>
|
||||||
<header class="workshop-hero">
|
<header class="workshop-hero">
|
||||||
<div class="card-meta">
|
<div class="card-meta">
|
||||||
<span class="badge badge-experimental">Status: In progress / Experimental</span>
|
<span class="badge badge-experimental">Status: Active Breadboard Prototype</span>
|
||||||
<span>Project 03 // Breadboard Hardware, C Code & Music</span>
|
<span>Project 03 // ESP32, ESP-IDF C99, FreeRTOS & Python RLE Tooling</span>
|
||||||
</div>
|
</div>
|
||||||
<h1>MIDI Breadboard Instrument</h1>
|
<h1>MIDI Breadboard Instrument — Desk Rave & 16-Track Symphony Controller</h1>
|
||||||
<p class="hero-lead">
|
<p class="hero-lead">
|
||||||
A breadboard-based project that plays MIDI melodies by converting MIDI data into C code for the device.
|
A standalone, dual-core ESP32 MIDI synthesizer, drum sequencer, and 30 FPS SPI OLED visualizer written in ESP-IDF v5.2.2 (C99 / FreeRTOS), powered by a custom Run-Length Encoding (RLE) Python MIDI-to-C compiler.
|
||||||
</p>
|
</p>
|
||||||
<p class="reading-width">
|
<p class="reading-width">
|
||||||
The hardware currently includes two active buzzers, one passive buzzer, a rotary encoder, a 1.3-inch AMOLED display, two buttons, and two LEDs.
|
What started as making a passive piezo buzzer squeak evolved into a full 16-track embedded music box with live kick/hi-hat drum transients, hardware PCNT quadrature rotary controls for real-time tempo and volume scaling, and dual-core FreeRTOS task isolation.
|
||||||
</p>
|
</p>
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
|
<a class="btn btn-primary" href="https://github.com/ertunc-ozbay/midi-breadboard-instrument" rel="noopener noreferrer">View GitHub Repository</a>
|
||||||
<a class="btn btn-secondary" href="index.html">All Projects</a>
|
<a class="btn btn-secondary" href="index.html">All Projects</a>
|
||||||
<a class="btn btn-secondary" href="../lab.html">See Lab Experiments</a>
|
<a class="btn btn-secondary" href="../lab.html">See Lab Experiments</a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<figure class="schematic-frame" aria-label="MIDI Breadboard Instrument Component Diagram">
|
<figure class="schematic-frame" aria-label="MIDI Breadboard Instrument Component Diagram">
|
||||||
<img src="../assets/images/midi-breadboard-layout.svg" alt="Block diagram of the MIDI Breadboard Instrument showing the MIDI conversion script producing C code for the breadboard system, connected to two active buzzers, one passive buzzer, a 1.3-inch AMOLED screen, one rotary encoder, two buttons, and two LEDs." width="760" height="320">
|
<img src="../assets/images/midi-breadboard-layout.svg" alt="Block diagram of the MIDI Breadboard Instrument showing the MIDI conversion script producing C code for the breadboard system, connected to two active buzzers, one passive buzzer, a 1.3-inch SPI OLED screen, one rotary encoder, two buttons, and two LEDs." width="760" height="320">
|
||||||
<figcaption class="schematic-caption">
|
<figcaption class="schematic-caption">
|
||||||
Confirmed software-to-hardware workflow and component list for the MIDI Breadboard Instrument.
|
Software-to-hardware pipeline: Python RLE MIDI compiler (<code>midi_to_c.py</code>) generating flash-resident <code>SequenceStep</code> struct arrays for the dual-core ESP32 breadboard synthesizer.
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
<section class="section-block" aria-labelledby="p3-gallery">
|
||||||
|
<span class="section-label">01 // Hardware Build Gallery</span>
|
||||||
|
<h2 id="p3-gallery">Breadboard Prototype Photos</h2>
|
||||||
|
<div class="card-grid">
|
||||||
|
<figure class="card" style="margin:0;">
|
||||||
|
<img src="../assets/images/MIDI_FIRST.jpg" alt="Full dual-breadboard overview of the ESP32 MIDI Breadboard Instrument" style="width:100%; height:auto; border-radius:6px; margin-bottom:0.75rem;">
|
||||||
|
<figcaption>
|
||||||
|
<strong>Full Breadboard Layout:</strong> Dual-breadboard build featuring the ESP32 DevKit, 1.3" 7-pin SPI OLED display, KY-040 rotary encoder, tactile buttons, passive melody piezo, and dual active drum buzzers.
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure class="card" style="margin:0;">
|
||||||
|
<img src="../assets/images/MIDI_SECOND.jpg" alt="Active 1.3-inch SPI OLED visualizer running at 30 FPS on the breadboard" style="width:100%; height:auto; border-radius:6px; margin-bottom:0.75rem;">
|
||||||
|
<figcaption>
|
||||||
|
<strong>30 FPS Live OLED Visualizer:</strong> Custom 5×7 font renderer displaying track code (<code>WHISP</code>), rotary mode (<code>SPD</code> / <code>VOL</code>), kick/hi-hat drum boxes, and dynamic frequency bars.
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure class="card" style="margin:0;">
|
||||||
|
<img src="../assets/images/MIDI_THIRD.jpg" alt="Close-up of the rotary encoder, tactile buttons, LEDs, and three buzzers" style="width:100%; height:auto; border-radius:6px; margin-bottom:0.75rem;">
|
||||||
|
<figcaption>
|
||||||
|
<strong>Controls & Acoustic Stage:</strong> Close-up of the rotary encoder, Play/Pause and Next Track buttons, green/red drum LEDs, and the 3-buzzer audio stage.
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="section-block reading-width" aria-labelledby="p3-overview">
|
<section class="section-block reading-width" aria-labelledby="p3-overview">
|
||||||
<span class="section-label">01 // Overview</span>
|
<span class="section-label">02 // Engineering Challenges Solved</span>
|
||||||
<h2 id="p3-overview">Combining Hardware, Software, and Creativity</h2>
|
<h2 id="p3-overview">From a Squeaking Buzzer to a Dual-Core Synthesizer</h2>
|
||||||
<p>
|
<p>
|
||||||
This project represents the kind of work I enjoy most: combining hardware, software, music, experimentation, and creativity in a practical and unusual system on a breadboard.
|
Pushing a bare-metal breadboard setup to play recognizable, energetic multi-track music required solving several real embedded systems challenges:
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
To get melodies onto the hardware, I wrote a script that converts MIDI data into C code for the device. That generated C code drives the breadboard setup to play MIDI sounds while providing physical controls and visual feedback.
|
|
||||||
</p>
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>The Strobe-Light Bug & RLE Compression (<code>midi_to_c.py</code>):</strong> Raw MIDI files often slice sustained notes into microscopic fragments, causing the LEDs and OLED UI to strobe at 30+ Hz while wasting flash memory. We built a custom Python Run-Length Encoding (RLE) compressor using <code>mido</code> that merges contiguous identical pitch/drum states into solid <code>SequenceStep</code> blocks and routes bass/percussion channels to dedicated drum triggers.</li>
|
||||||
|
<li><strong>Acoustic Hardware Limits (+2 Octave Transposition):</strong> Passive piezo buzzers physically struggle to resonate at low bass frequencies. Tracks with deep basslines like <em>Seven Nation Army</em> were transposed up two full octaves so the piezo disc resonates clearly while the active buzzers carry the rhythmic punch.</li>
|
||||||
|
<li><strong>Dual-Core FreeRTOS Lockless IPC:</strong> Core 0 runs <code>oled_visualizer_task</code> (30 FPS SPI DMA framebuffer engine) and <code>button_task</code> (debounced input polling), while Core 1 exclusively runs <code>buzzer_sequence_task</code> for microsecond-accurate LEDC PWM pitch generation and hardware PCNT rotary encoder scaling.</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="section-block reading-width" aria-labelledby="p3-components">
|
<section class="section-block reading-width" aria-labelledby="p3-components">
|
||||||
<span class="section-label">02 // Confirmed Hardware & Software</span>
|
<span class="section-label">03 // Confirmed Hardware & Pinout</span>
|
||||||
<h2 id="p3-components">Confirmed Components on the Breadboard</h2>
|
<h2 id="p3-components">ESP32 Pinout & Architecture Specifications</h2>
|
||||||
<table class="spec-table">
|
<table class="spec-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Component / Layer</th>
|
<th scope="col">Component / Peripheral</th>
|
||||||
<th scope="col">Confirmed Specification</th>
|
<th scope="col">ESP32 Pin / Interface</th>
|
||||||
|
<th scope="col">Function</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Conversion Workflow</strong></td>
|
<td><strong>Microcontroller</strong></td>
|
||||||
<td>Custom script that converts MIDI data into C code for the device</td>
|
<td>ESP32 (Dual-Core Xtensa @ 160 MHz)</td>
|
||||||
|
<td>ESP-IDF v5.2.2 + FreeRTOS dual-core execution</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Device Code Output</strong></td>
|
<td><strong>Rotary Encoder CLK / DT</strong></td>
|
||||||
<td>C code</td>
|
<td><code>GPIO 32</code> / <code>GPIO 33</code></td>
|
||||||
|
<td>Hardware PCNT quadrature tracking (1000 ns glitch filter)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Active Sound Components</strong></td>
|
<td><strong>Rotary Encoder SW</strong></td>
|
||||||
<td>2 × Active buzzers</td>
|
<td><code>GPIO 16</code> (Active Low)</td>
|
||||||
|
<td>Toggles knob & OLED HUD between Speed (<code>0.2x–3.0x</code>) and Volume (<code>0%–100%</code>)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Passive Sound Component</strong></td>
|
<td><strong>Pause / Next Buttons</strong></td>
|
||||||
<td>1 × Passive buzzer</td>
|
<td><code>GPIO 13</code> / <code>GPIO 14</code> (Active Low)</td>
|
||||||
|
<td>Play/Pause toggle and 16-track playlist cycling</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Display</strong></td>
|
<td><strong>Passive Buzzer (Melody)</strong></td>
|
||||||
<td>1 × 1.3-inch AMOLED screen</td>
|
<td><code>GPIO 25</code> (LEDC 13-bit PWM)</td>
|
||||||
|
<td>Main melody synthesizer driven by hardware LEDC Timer 0</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Rotational Input</strong></td>
|
<td><strong>Active Buzzer 1 & 2 (Drums)</strong></td>
|
||||||
<td>1 × Rotary encoder</td>
|
<td><code>GPIO 26</code> (Kick) / <code>GPIO 27</code> (Hi-Hat)</td>
|
||||||
|
<td>Physical percussion transients on drum steps</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Push Inputs</strong></td>
|
<td><strong>Kick & Hi-Hat LEDs</strong></td>
|
||||||
<td>2 × Buttons</td>
|
<td><code>GPIO 21</code> (Kick) / <code>GPIO 22</code> (Hi-Hat)</td>
|
||||||
|
<td>Visual beat indicators synchronized to drum hits</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Visual Indicators</strong></td>
|
<td><strong>1.3" 7-Pin SPI OLED</strong></td>
|
||||||
<td>2 × LEDs</td>
|
<td><code>CS: 5, DC: 2, RES: 4, MOSI: 23, SCK: 18</code></td>
|
||||||
</tr>
|
<td>10 MHz SPI2 display running custom 30 FPS visualizer on Core 0</td>
|
||||||
<tr>
|
|
||||||
<td><strong>Additional Circuit Details</strong></td>
|
|
||||||
<td>Details will be documented as the project develops.</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="section-block reading-width" aria-labelledby="p3-playlist">
|
||||||
|
<span class="section-label">04 // Flash Memory Playlist</span>
|
||||||
|
<h2 id="p3-playlist">The 16-Track Symphony</h2>
|
||||||
|
<p>
|
||||||
|
All 16 tracks are stored in ESP32 flash memory as <code>SequenceStep</code> arrays featuring <code>frequency</code>, <code>duration</code>, <code>kick_drum</code>, and <code>hi_hat</code> triggers:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li><strong>Careless Whisper</strong> (Extended Club Edit)</li>
|
||||||
|
<li><strong>Take On Me</strong> (EDM Build-up Edition)</li>
|
||||||
|
<li><strong>Never Gonna Give You Up / Rickroll</strong> (Double Chorus)</li>
|
||||||
|
<li><strong>Can't Help Falling In Love</strong> (Wedding Mix)</li>
|
||||||
|
<li><strong>Gimme! Gimme! Gimme!</strong> (Midnight Rave)</li>
|
||||||
|
<li><strong>Für Elise</strong> (Beethoven Trance)</li>
|
||||||
|
<li><strong>Symphony No. 40</strong> (Mozart Intense Strings)</li>
|
||||||
|
<li><strong>Super Mario Bros.</strong> (Main Theme)</li>
|
||||||
|
<li><strong>Pirates of the Caribbean 1</strong> (He's a Pirate)</li>
|
||||||
|
<li><strong>Pirates of the Caribbean 2</strong> (The Black Pearl)</li>
|
||||||
|
<li><strong>Rondo Alla Turca</strong> (Mozart)</li>
|
||||||
|
<li><strong>Tetris</strong> (Korobeiniki)</li>
|
||||||
|
<li><strong>Sonic the Hedgehog</strong> (Green Hill Zone)</li>
|
||||||
|
<li><strong>Castlevania</strong> (Vampire Killer)</li>
|
||||||
|
<li><strong>Seven Nation Army</strong> (Transposed +2 Octaves for piezo resonance)</li>
|
||||||
|
<li><strong>Mega Man 2</strong> (Dr. Wily Stage)</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="section-block reading-width" aria-labelledby="p3-learning">
|
<section class="section-block reading-width" aria-labelledby="p3-learning">
|
||||||
<span class="section-label">03 // Workshop Notes</span>
|
<span class="section-label">05 // Workshop Notes & Next Steps</span>
|
||||||
<h2 id="p3-learning">What I Am Currently Learning & Next Steps</h2>
|
<h2 id="p3-learning">Current State & Roadmap</h2>
|
||||||
<div class="callout-box">
|
<div class="callout-box">
|
||||||
<span class="callout-title">What I Am Currently Learning</span>
|
<span class="callout-title">Current State</span>
|
||||||
<p>
|
<p>
|
||||||
How data conversion scripts bridge file formats (like MIDI) into low-level C structures, and how multiple physical outputs (two active buzzers, one passive buzzer, two LEDs, and a 1.3-inch AMOLED screen) can be coordinated alongside user inputs (a rotary encoder and two buttons).
|
The firmware is rock-solid on the breadboard: the rotary encoder dynamically scales volume and tempo via lockless IPC variables, all 16 tracks play from flash memory, and the 1.3" SPI OLED renders real-time frequency bars and drum hits at 30 FPS.
|
||||||
</p>
|
</p>
|
||||||
<span class="callout-title">Next Step</span>
|
<span class="callout-title">Next Steps</span>
|
||||||
<p style="margin-bottom:0;">
|
<p style="margin-bottom:0;">
|
||||||
Documenting how the MIDI-to-C conversion script formats note events and adding further hardware notes as the breadboard prototype evolves.
|
Migrating the dual-breadboard circuit onto a soldered perfboard or custom KiCad PCB, and optionally re-integrating a WS2812B addressable RGB strip when expanding the enclosure.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue