BeatCanvas - a BLE MIDI Controller
by rjrishabh2409 in Circuits > Audio
257 Views, 4 Favorites, 0 Comments
BeatCanvas - a BLE MIDI Controller
BeatCanvas is a custom ESP32-based Bluetooth MIDI controller designed to work seamlessly with apps like Koala Sampler.
It features 8 velocity-style pads, 2 analog knobs, and an 8×8 WS2812 LED matrix that displays vibrant animations and visual feedback.
It sends MIDI Note and Control Change messages over BLE, allowing you to trigger samples, control effects, or manipulate synth parameters wirelessly.
Why I made it:
I built BeatCanvas to combine tactile music control with visual expression.
Most small MIDI controllers are functional but lack personality — I wanted something that feels alive, where each beat and movement is accompanied by dynamic color and motion.
BeatCanvas turns sound performance into a visual art form, creating a bridge between music and light.
Supplies
ESP32 Dev Module
2 Potentiometer Knobs
2x4 Touch Keypad
8x8 WS2812 LED Matrix
Jumper Wires
Wiring
Power safety
- Use an external 5V power supply for the LED matrix if you plan on >50% brightness.
- Connect all grounds together: ESP32 GND ↔ LED matrix GND ↔ power supply GND.
WS2812 (matrix)
- VCC (5V) → external 5V supply
- GND → common ground
- DIN (data) → ESP32 GPIO 23 (or any digital pin NOT 34–39)
- Put 1000 μF capacitor across 5V and GND at the LED input.
- Put 330 Ω resistor in series on the data line (between ESP32 pin and DIN).
Potentiometers (2)
- Pot outer pins → 3.3V and GND (NOT 5V; ESP32 ADC max is 3.3V)
- Pot wiper (middle) → ADC pins:
- Pot1 → GPIO 34
- Pot2 → GPIO 33
- Note: use ADC1 pins (32–39 are ADC but 34–39 are input-only — they’re fine for pots).
Buttons (8)
- Connect one side of each switch to an ESP32 digital pin:
- {13, 14, 15, 5, 22, 18, 19, 21} (as in your code)
- Other side of each switch → GND.
- In code use pinMode(pin, INPUT_PULLUP) so switch is active LOW.
ESP32 USB
- Use USB only for programming and serial debugging. Powering many LEDs from USB is unstable — use external 5V.
Libraries to install (Arduino IDE)
Open Library Manager (Sketch → Include Library → Manage Libraries) and install:
- Adafruit NeoPixel (for WS2812 control)
- BLEMIDI_Transport and BLEMIDI_ESP32 GitHub - lathoub/Arduino-BLE-MIDI: MIDI over Bluetooth Low Energy (BLE-MIDI) 1.0 for Arduino
Also ensure Arduino board manager has ESP32 platform installed.
CODE
#include <BLEMIDI_Transport.h>
#include <hardware/BLEMIDI_ESP32.h>
#include <Adafruit_NeoPixel.h>
BLEMIDI_CREATE_INSTANCE("ESP32_KOALA_CTRL", MIDI)
// ---- CONFIG ----
const int potPin = 34; // potentiometer pin (ADC1 channel)
// Button pins (adjust these as per your wiring)
const int buttonPins[8] = {13, 14, 15, 5, 22, 18, 19, 21};
// MIDI note numbers for each pad
int midiNotes[8] = {36, 38, 42, 46, 49, 51, 45, 47};
// (Kick, Snare, HiHat Closed, HiHat Open, Crash, Ride, Tom1, Tom2)
int lastPotValue = -1;
bool padState[8] = {0}; // track button state
// ---- WS2812 LED CONFIG ----
#define LED_PIN 23 // Data pin for WS2812 LEDs
#define NUM_LEDS 64 // 8x8 matrix (or adjust if using a strip)
#define BRIGHTNESS 3 // 0–255 brightness
Adafruit_NeoPixel leds(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// ---- Rainbow animation variables ----
uint16_t rainbowOffset = 0;
// ---- SETUP ----
void setup() {
Serial.begin(115200);
MIDI.begin();
// Configure button pins with internal pull-ups
for (int i = 0; i < 8; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
// Initialize LED matrix
leds.begin();
leds.setBrightness(BRIGHTNESS);
leds.show(); // Initialize all pixels to 'off'
Serial.println("ESP32 MIDI Controller with Rainbow Animation Ready!");
}
// ---- MAIN LOOP ----
void loop() {
handlePot();
handleButtons();
rainbowAnimation(10); // continuous rainbow effect (non-blocking)
delay(5);
}
// ---- POTENTIOMETER HANDLER ----
void handlePot() {
int potValue = analogRead(potPin); // 0-4095
int ccValue = map(potValue, 0, 4095, 0, 127); // scale to 0-127
if (ccValue != lastPotValue) {
MIDI.sendControlChange(21, ccValue, 1); // CC 21 on channel 1
Serial.print("Pot: ");
Serial.println(ccValue);
lastPotValue = ccValue;
}
}
// ---- BUTTON HANDLER ----
void handleButtons() {
for (int i = 0; i < 8; i++) {
int val = digitalRead(buttonPins[i]);
if (val == LOW && !padState[i]) {
MIDI.sendNoteOn(midiNotes[i], 127, 1);
Serial.print("Pad ");
Serial.print(i);
Serial.println(" Note On");
padState[i] = true;
}
else if (val == HIGH && padState[i]) {
MIDI.sendNoteOff(midiNotes[i], 0, 1);
Serial.print("Pad ");
Serial.print(i);
Serial.println(" Note Off");
padState[i] = false;
}
}
}
// ---- RAINBOW ANIMATION ----
void rainbowAnimation(uint8_t wait) {
for (int i = 0; i < leds.numPixels(); i++) {
int pixelHue = rainbowOffset + (i * 65536L / leds.numPixels());
leds.setPixelColor(i, leds.gamma32(leds.ColorHSV(pixelHue)));
}
leds.show();
rainbowOffset += 256; // Move rainbow forward
delay(wait);
}
Upload & Test Steps
- Open Arduino IDE, select correct ESP32 board & COM port.
- Install libraries listed above.
- Paste the sketch attached in the project and upload.
- Open Serial Monitor at 115200 to see debug prints.
- With your 5V supply connected to the LEDs and common ground:
- Verify the rainbow animation runs.
- Turn the potentiometer and watch Serial print CC21 values.
- Press pads and watch Note On / Note Off print; pair BLE MIDI on your phone/computer and select device "BeatCanvas".
- In Koala Sampler (or other DAW), connect to the BLE MIDI device and use MIDI Map option:
- Move pot → assign CC 21 to desired parameter
- Press pads → assign notes to pads/sounds
Conclusion
BeatCanvas merges music control and visual art into one compact device.
Built on the ESP32’s BLE MIDI capability, it bridges tactile performance with colorful feedback, giving musicians both functionality and expression.
The project demonstrates how affordable components — buttons, potentiometers, and addressable LEDs — can be combined through Arduino to build a wireless MIDI controller that feels personal, creative, and alive.
Ultimately, BeatCanvas isn’t just a tool — it’s an instrument that lets you paint sound with light. 🎶🌈