BeatCanvas – a BLE MIDI Controller : 5 Steps (with Pictures)

CODE

#include

#include

#include

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 // 8×8 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);

}

Read more here: Source link

BeatCanvas – a BLE MIDI Controller : 5 Steps (with Pictures)

CODE

#include

#include

#include

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 // 8×8 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);

}

Read more here: Source link