tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.19k stars 134 forks source link

ESP32 <-> ESP32 BLEMidi connectivity #936

Open shelson opened 1 year ago

shelson commented 1 year ago

I may be holding/reading things wrong but I haven't found anything in the code/docs about this. I'm building the following:

<Midi Controller with knobs/buttons w/ESP32 running control-surface, BLEMidi Interface> ---- (BLEMidi) ---- <Small box with ESP32 and 5 pin DIN socket purely piping midi between BLEMidi and HardwareSerialMidi>

The first bit (the controller) has been super easy and thanks so much for the cool library etc - if I pair it to my mac and run up a DAW I can play notes etc. The second bit - the box with the pipes - again it works perfectly if I connect my laptop to it. However the bit I'm stuck on is - can I make the two ESP32's talk to each other? I had a hunt through the code and I can see there's stuff about advertising and accepting connections, but not so much intiating them, which I'm guessing currently is the job of my mac when I hit the "connect" button. I'm guessing there's also some kind of identification thing - which BLEmidi.setName() is dealing with - and in my case I would want the devices to find each other - or the client find the server if that terminology even works here.

If there is a way to do this currently I would love to know how - and if not and you have some pointers I'm more than happy to work on a PR to see if I can't make it work - it's been a super interesting project and I'm happy to muck in vs just demanding features :)

Thanks!

Codewise I'm using https://github.com/tttapa/Control-Surface/blob/main/examples/1.%20MIDI%20Output/2.%20Buttons%20%26%20Switches/1.%20Momentary%20Push%20Buttons/NoteButton/NoteButton.ino for the client but with BluetoothMIDI_Interface and https://tttapa.github.io/Control-Surface-doc/Doxygen/d0/dc4/MIDI_Pipes-Routing_8ino-example.html for the second box - nothing at all special right now.

shelson commented 1 year ago

Just stumbled across https://github.com/max22-/ESP32-BLE-MIDI/tree/master which appears to do server/client and server discovery from the client - I might see if I can't bend that to be used in control-surface maybe vs reinventing the wheel?

shelson commented 1 year ago

I got this working - so the concept works - I would love to use the pipe functionality vs callbacks for everything though..

#include <Arduino.h>
#include <BLEMidi.h>
#include <HardwareSerial.h>
#include <MIDI.h>

HardwareSerial MidiSerialPort(2);
MIDI_CREATE_INSTANCE(HardwareSerial, MidiSerialPort, serialMidi);

void onNoteOn(uint8_t channel, uint8_t note, uint8_t velocity, uint16_t timestamp)
{
  serialMidi.sendNoteOn(note, velocity, 1);
  Serial.printf("Note on : channel %d, note %d, velocity %d (timestamp %dms)\n", channel, note, velocity, timestamp);
}

void onNoteOff(uint8_t channel, uint8_t note, uint8_t velocity, uint16_t timestamp)
{
  serialMidi.sendNoteOff(note, velocity, 1);
  Serial.printf("Note off : channel %d, note %d, velocity %d (timestamp %dms)\n", channel, note, velocity, timestamp);
}

void onAfterTouchPoly(uint8_t channel, uint8_t note, uint8_t pressure, uint16_t timestamp)
{
  Serial.printf("Polyphonic after touch : channel %d, note %d, pressure %d (timestamp %dms)\n", channel, note, pressure, timestamp);
}

void onControlChange(uint8_t channel, uint8_t controller, uint8_t value, uint16_t timestamp)
{
    Serial.printf("Control change : channel %d, controller %d, value %d (timestamp %dms)\n", channel, controller, value, timestamp);
}

void onProgramChange(uint8_t channel, uint8_t program, uint16_t timestamp)
{
    Serial.printf("Program change : channel %d, program %d (timestamp %dms)\n", channel, program, timestamp);
}

void onAfterTouch(uint8_t channel, uint8_t pressure, uint16_t timestamp)
{
    Serial.printf("After touch : channel %d, pressure %d (timestamp %dms)\n", channel, pressure, timestamp);
}

void onPitchbend(uint8_t channel, uint16_t value, uint16_t timestamp)
{
    Serial.printf("Pitch bend : channel %d, value %d (timestamp %dms)\n", channel, value, timestamp);
}

void setup() {
    Serial.begin(115200);
    Serial.println("Initializing bluetooth");
    BLEMidiClient.begin("MidiBridgeThing"); // "Midi client" is the name you want to give to the ESP32
    BLEMidiClient.setNoteOnCallback(onNoteOn);
    BLEMidiClient.setNoteOffCallback(onNoteOff);
    BLEMidiClient.setAfterTouchPolyCallback(onAfterTouchPoly);
    BLEMidiClient.setControlChangeCallback(onControlChange);
    BLEMidiClient.setProgramChangeCallback(onProgramChange);
    BLEMidiClient.setAfterTouchCallback(onAfterTouch);
    BLEMidiClient.setPitchBendCallback(onPitchbend);

    BLEMidiClient.enableDebugging();  // Uncomment to see debugging messages from the library
    serialMidi.begin();

}

void loop() {
    if(!BLEMidiClient.isConnected()) {
        // If we are not already connected, we try te connect to the first BLE Midi device we find
        int nDevices = BLEMidiClient.scan();
        if(nDevices > 0) {
            if(BLEMidiClient.connect(0))
                Serial.println("Connection established");
            else {
                Serial.println("Connection failed");
                delay(3000);    // We wait 3s before attempting a new connection
            }
        }
    }
}