Robot pianista · MIDI · ESP32 · WiFi / USB Serial · Impresión 3D

Un robot que toca
el piano de verdad

A robot that plays
a real piano

Servos controlados por ESP32 (por WiFi o USB Serial), piezas impresas en 3D, LEDs sincronizados con cada nota y un secuenciador MIDI web con análisis armónico e interpretación expresiva que lo orquesta todo desde el navegador.

ESP32-driven servos (over WiFi or USB Serial), 3D-printed parts, LEDs synced to every note and a web MIDI sequencer with harmonic analysis and expressive interpretation that orchestrates it all from the browser.

Impresión 3D — 7 piezas STL ↗ Instagram ↗ Open Source ↗ Web Serial API ↗ MIDI.js ↗ ESP32 docs ↗ PCA9685 guide ↗


Tres cosas que ningún otro secuenciador web combina

Three things no other web sequencer combines

⚙️

Control de hardware real

Real hardware control

Envía comandos en tiempo real a servos y motores conectados a un ESP32 por dos canales a elegir: WebSocket sobre WiFi o USB Serial (Web Serial API). Sincronización beat-by-beat con corrección de drift y configuración de la red WiFi desde la propia app.

Sends real-time commands to servos and motors connected to an ESP32 over two selectable channels: WebSocket over WiFi or USB Serial (Web Serial API). Beat-by-beat sync with drift correction and WiFi setup straight from the app.

🎹

Secuenciador MIDI completo

Full MIDI sequencer

Grid con arrastrar y soltar, carril de velocidades, 128 instrumentos GM, importación y exportación de archivos .mid estándar compatibles con cualquier DAW.

Drag-and-drop grid, velocity lane, 128 GM instruments, standard .mid import and export compatible with any DAW.

🧠

Análisis armónico en tiempo real

Real-time harmonic analysis

Detección automática de tonalidad (Krumhansl-Kessler), acordes con Tonal.js, heat map 4D y análisis de cadencias mientras compones.

Automatic key detection (Krumhansl-Kessler), chords with Tonal.js, 4D heat map and cadence analysis as you compose.

Interfaz del secuenciador PianoRoll

🎵 Interpretar🎵 Interpret

Pinta cada nota por relevancia (azul relleno → rojo clave) y ajusta la firma expresiva: velocity y duración se reescriben en el grid. Reversible con Ctrl+Z.

Colours every note by relevance (blue fill → red key) and tunes the expressive signature: velocity and duration are rewritten into the grid. Undo with Ctrl+Z.

Motor Map avanzadoAdvanced Motor Map

Asigna notas MIDI a servos con Vmín/Vmáx por motor, mute, tecla de teclado, golpe de prueba e import/export JSON del mapa.

Map MIDI notes to servos with per-motor Vmin/Vmax, mute, keyboard key, test hit and JSON import/export of the map.

Escala y transposiciónScale & transpose

Transpone ±1 / ±12 semitonos al vuelo, con opción de reproducir solo las notas que tienen motor asignado.

Transpose ±1 / ±12 semitones on the fly, with an option to play only notes that have a motor assigned.

🤖 Comprimir a motores🤖 Compress to motors

Colapsa las notas a las octavas de los motores configurados en el Motor Map, resolviendo colisiones por atención del heat map.

Collapses notes onto the octaves of the motors set in the Motor Map, resolving collisions by heat-map attention.

A→B y fragmentosA→B & fragments

Loop A→B marcando en la regla, y copiar / pegar / borrar fragmentos con recolocación por flechas.

A→B loop by marking on the ruler, plus copy / paste / delete fragments with arrow-key repositioning.

♩ Mapa de tempo♩ Tempo map

Puntos de BPM editables directamente en la regla: acelerandos y ritardandos por sección.

BPM points editable right on the ruler: accelerandos and ritardandos per section.

LEDs SynthesiaSynthesia LEDs

Tira WS2812B que replica el color exacto de cada nota en el editor, con anticipación tipo Synthesia y encendido de todas las notas, tengan motor o no.

WS2812B strip mirroring each note's exact colour in the editor, with Synthesia lookahead and lighting for every note, motor-mapped or not.

Multipestaña + MinimapMulti-tab + Minimap

Varios proyectos abiertos con deshacer independiente por pestaña y vista panorámica con scrub rápido.

Multiple projects open with per-tab undo, plus a full-project overview with quick scrub.

Importación MMLMML Import

Pega notación MML directamente y aparece en el grid.

Paste MML notation directly and it populates the grid.

AudioContext SchedulerAudioContext Scheduler

100 ms de lookahead para timing sample-accurate. Sin jitter por setInterval.

100 ms lookahead for sample-accurate timing. No setInterval jitter.

Export .mid Tipo 1Type 1 .mid export

Genera archivos .mid estándar con mapa de tempo y transposición, compatibles con Ableton, Logic, MuseScore o Cubase.

Generates standard .mid files with tempo map and transposition, compatible with Ableton, Logic, MuseScore or Cubase.

Sin instalaciónZero install

Funciona en Chrome, Edge y Opera. Sin npm, sin Electron, sin plugins.

Works in Chrome, Edge and Opera. No npm, no Electron, no plugins.


No solo secuencia notas: las entiende y las interpreta

It doesn't just sequence notes — it understands and interprets them

Motor armónico en tiempo real fusionado con una capa de interpretación que vuelca expresión sobre la velocidad y la duración de cada nota antes de tocar.

A real-time harmonic engine fused with an interpretation layer that pours expression onto each note's velocity and duration before it plays.

Panel Interpretar de PianoRoll con notas coloreadas por relevancia
  • 🔑

    Tonalidad automática

    Automatic key

    Detección de tonalidad con el algoritmo Krumhansl-Kessler mientras compones.

    Key detection via the Krumhansl-Kessler algorithm as you compose.

  • 🎶

    Acordes y cadencias

    Chords & cadences

    Identificación de acordes con Tonal.js y análisis de cadencias, con panel para reproducirlos y hacer loop.

    Chord identification with Tonal.js and cadence analysis, with a panel to play and loop them.

  • 🔥

    Heat map 4D

    4D heat map

    Mapa de calor que pondera la atención de cada nota y guía la compresión a motores y la interpretación.

    A heat map that weighs each note's attention and drives motor compression and interpretation.

  • 🎵

    Interpretación expresiva

    Expressive interpretation

    La capa «escuchar antes de tocar» fusiona heat map, armonía y frases para reescribir velocity y duración. Reversible con Ctrl+Z.

    The "listen before you play" layer fuses heat map, harmony and phrasing to rewrite velocity and duration. Undo with Ctrl+Z.

Cada tecla se ilumina al ritmo de la música

Every key lights up to the beat of the music

Una tira WS2812B cromática (C1–B5) muestra en tiempo real lo que suena, sincronizada con el audio del navegador. Se encienden todas las notas, tengan servo asignado o no, con el mismo color que tienen en el editor.

A chromatic WS2812B strip (C1–B5) shows what's playing in real time, synced with the browser audio. Every note lights up — servo-mapped or not — in the same colour it has in the editor.

1:1
Color del editor
Editor colour
60
LEDs · C1–B5
LEDs · C1–B5
Sync
con el audio
with the audio

Cada LED copia el color exacto de su nota en el editor: por octava con brillo según la fuerza del golpe, o los colores de relevancia (azul→rojo) cuando la vista de interpretación está activa. Además, anticipación tipo Synthesia: el LED se enciende unos milisegundos antes del golpe.

Every LED mirrors its note's exact colour in the editor: by octave with brightness tied to hit strength, or the relevance colours (blue→red) when the interpretation view is active. Plus Synthesia-style lookahead: the LED lights a few milliseconds before the hit.


Conecta y configura el ESP32 sin salir del navegador

Connect and set up the ESP32 without leaving the browser

Elige el canal en la barra de herramientas (grupo ESP32) y conecta. La red WiFi del robot se configura desde la propia app, por WiFi o por cable.

Pick the channel in the toolbar (ESP32 group) and connect. The robot's WiFi network is set up from the app itself, over WiFi or over the cable.

📶 WiFi (WebSocket)WiFi (WebSocket)

El ESP32 y tu ordenador comparten red. Escribes la IP del ESP32 (por defecto 192.168.4.1 en su modo AP) y conectas por WebSocket. Ideal para tocar sin cables.

The ESP32 and your computer share a network. You type the ESP32's IP (default 192.168.4.1 in AP mode) and connect over WebSocket. Great for cable-free playing.

WebSocket · puerto 81

🔌 Serie (USB)Serial (USB)

Conexión directa por cable USB con la Web Serial API de Chrome/Edge. No necesitas red: útil para el primer arranque y para configurar la WiFi por cable.

Direct USB-cable connection via Chrome/Edge's Web Serial API. No network needed: handy for first boot and for setting up WiFi over the cable.

Web Serial API

Cómo se configura la WiFi del ESP32

How to set up the ESP32's WiFi

Abre Log en la barra de herramientas: dentro tienes los botones + WiFi y ⟳ Reset WiFi. Funcionan por los dos canales.

Open Log in the toolbar: inside you'll find the + WiFi and ⟳ Reset WiFi buttons. They work over both channels.

Primer arranque = AP

First boot = AP

Sin red guardada, el ESP32 crea el punto de acceso abierto midiGrid-Setup en 192.168.4.1.

With no saved network, the ESP32 creates the open access point midiGrid-Setup at 192.168.4.1.

Abre el Log → + WiFi

Open Log → + WiFi

Pulsa + WiFi e introduce el nombre de la red (SSID) y la contraseña.

Click + WiFi and enter the network name (SSID) and password.

Guarda y reinicia

Save & reboot

El ESP32 guarda las credenciales en memoria (NVS) y se reinicia para conectarse a tu red.

The ESP32 stores the credentials in memory (NVS) and reboots to join your network.

Toma su IP

Gets its IP

Si conecta, adopta una IP de tu red (mírala en el Log/monitor serie). Si falla, vuelve al AP.

On success it takes an IP from your network (check the Log/serial monitor). On failure it falls back to the AP.

Dos caminos para el mismo botón: Two paths, same button: en modo WiFi la app envía la configuración por HTTP al AP 192.168.4.1; en modo Serie la manda por el cable USB con el comando W ssid|pass; (y el reset con R;), sin necesidad de conectarte antes a la red del robot. in WiFi mode the app sends the config over HTTP to the AP 192.168.4.1; in Serial mode it sends it over the USB cable with the W ssid|pass; command (and reset with R;), with no need to join the robot's network first.

Conexionado del ESP32

ESP32 wiring

Dos controladoras PCA9685 en buses I2C independientes (por eso ambas usan la dirección 0x40 sin puentes de soldadura) y la tira de LEDs por un GPIO dedicado. El firmware las detecta automáticamente al arrancar con un escaneo I2C.

Two PCA9685 drivers on independent I2C buses (which is why both use address 0x40 with no solder jumpers) and the LED strip on a dedicated GPIO. The firmware auto-detects them at boot via an I2C scan.

ComponentePines ESP32Detalle
PCA9685 #1 — motores 0–15SDA GPIO 21 · SCL GPIO 22Bus I2C 0 · dirección 0x40
PCA9685 #2 — motores 16–31SDA GPIO 16 · SCL GPIO 17Bus I2C 1 · dirección 0x40
Tira LEDs WS2812B (60)DATA GPIO 5Orden de color GRB
Alimentación5 V / GNDServos por el terminal V+ de cada PCA · GND común con el ESP32
ComponentESP32 pinsDetail
PCA9685 #1 — motors 0–15SDA GPIO 21 · SCL GPIO 22I2C bus 0 · address 0x40
PCA9685 #2 — motors 16–31SDA GPIO 16 · SCL GPIO 17I2C bus 1 · address 0x40
WS2812B LED strip (60)DATA GPIO 5GRB colour order
Power5 V / GNDServos via each PCA's V+ terminal · common GND with the ESP32
Ventana de Log del ESP32 con los botones para configurar la WiFi

Escúchalo tocar

Hear it play

El robot tocando una secuencia compuesta en PianoRoll y enviada al ESP32 en tiempo real.

The robot playing a sequence composed in PianoRoll and sent to the ESP32 in real time.


¿Quieres uno? ¿Tienes preguntas?

Want one? Got questions?

Escríbeme por WhatsApp — respondo en menos de 24 h. Puedo fabricar una unidad, resolver dudas técnicas o hablar de colaboraciones.

Message me on WhatsApp — I reply within 24 h. I can build a unit, answer technical questions or discuss collaborations.

Escríbeme por WhatsAppMessage me on WhatsApp

portab76@gmail.com