FortySevenEffects / arduino_midi_library

MIDI for Arduino
MIT License
1.56k stars 252 forks source link

ESP32-S3 Serial.read() infinite loop #315

Open cyberdevnet opened 1 year ago

cyberdevnet commented 1 year ago

Context

Please answer a few questions to help us understand your problem better and guide you to a solution:

Describe your problem (what does not work):

I'm trying to implement a Serial (DIN) communication to a working BLE Project, so far I can read every MIDI messages coming from my BLE Input device but calling MIDI_Serial.read(); creates an infinite loop where my ESP32 continuosly fires the callback functions. Should I call somewhere the end() method or my implementation is wrong?

Here the relevant code

#include "Arduino.h"
#include <MIDI.h>
#include <HardwareSerial.h>
#include "src/BLEMIDI/BLEMIDI_Transport.h"
#include "src/BLEMIDI/hardware/BLEMIDI_ESP32_NimBLE.h"
#include "src/midi/MidiIN.h"
#define RXD2 16
#define TXD2 17
BLEMIDI_CREATE_INSTANCE("MIDI_BLE_MEDUSA", MIDI)
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI_Serial);

void setup()
{
    Serial.begin(115200);                         // setup HW serial for debug communication
    Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2); // Serial2 (GPIO 16 & 17) for hardware-midi in/out
    MIDI.setHandleControlChange(handleControlChangeIN); // BLEMIDI CC Callback
    MIDI.setHandleProgramChange(handleProgramChangeIN); // BLEMIDI PC Callback
    MIDI.begin(MIDI_CHANNEL_OMNI);                      // Initiate BLEMIDI communications, listen to all channels
    MIDI_Serial.setHandleControlChange(handleControlChangeIN); // MIDI_Serial CC Callback
    MIDI_Serial.setHandleProgramChange(handleProgramChangeIN); // MIDI_Serial PC Callback
    MIDI_Serial.begin(MIDI_CHANNEL_OMNI);                      // Initiate MIDI_Serial communications, listen to all channels
}

void loop()
{
    if (BLE_isConnected && editSettings == 0)
    {
        MIDI.read();   // this works fine
    } 
    else if (Serial2.available() > 0 && editSettings == 0)
    {
        MIDI_Serial.read();  // this is being called in an infinite loop, it never stops receiving midi messages
    }
}
franky47 commented 1 year ago

There's a couple of things I can think of.

Based on this image:

We can see that the TX pin is 17, and RX is 18. Having set RX as 16 could be the problem, with incorrect data being read on that pin.

Another possibility is that calling MIDI_Serial.begin(MIDI_CHANNEL_OMNI) overrides your opening of the serial port on custom pins. For that, you could try using a custom Serial transport that calls begin with the correct pin assignments.

cyberdevnet commented 1 year ago

HI, thanks for pointing out the PINs, this was probably one of many error. I wasn't able to let the library work also with the custom transport (same infinite loop problem) instead I opted for the "old" serial method. I'm posting the working code just as reference if someone has the same problem

#include "Arduino.h"
#include <MIDI.h>
#include <HardwareSerial.h>
#include "src/BLEMIDI/BLEMIDI_Transport.h"
#include "src/BLEMIDI/hardware/BLEMIDI_ESP32_NimBLE.h"
#include "src/midi/MidiIN.h"
#define TXD2 17
#define RXD2 18
#define MIDI_PGM_CHANGE 192
#define MIDI_CTL_CHANGE 176

byte midiCommand;
byte statusByte;
byte midiChannel;

BLEMIDI_CREATE_INSTANCE("MIDI_BLE_MEDUSA", MIDI)
HardwareSerial MIDI_Serial(2);

void setup()
{
    Serial.begin(115200);                         // setup HW serial for debug communication

    MIDI.setHandleControlChange(handleControlChangeIN); // BLEMIDI CC Callback
    MIDI.setHandleProgramChange(handleProgramChangeIN); // BLEMIDI PC Callback
    MIDI.begin(MIDI_CHANNEL_OMNI);                      // Initiate BLEMIDI communications, listen to all channels

    MIDI_Serial.begin(31250, SERIAL_8N1, TXD2, RXD2); // setup MIDI_Serial for MIDI control
}

void loop()
{
    if (BLE_isConnected && editSettings == 0)
    {
        MIDI.read();   // this works fine
    } 
  else if (MIDI_Serial.available() > 1 && editSettings == 0)
  {

    // read MIDI byte
    statusByte = MIDI_Serial.read();

    // remove program info from status byte (only channel value left)
    midiChannel = statusByte & B00001111;
    // remove channel info from status byte (only program value left)
    midiCommand = statusByte & B11110000;

    switch (midiCommand)
    {                     // get the type of the message
    case MIDI_PGM_CHANGE: // if this is a program change command

        // do something

      break;

    case MIDI_CTL_CHANGE: // if this is a control change command

        // do something

      break;

    default:

      break;
    }
  }
}