FortySevenEffects / arduino_midi_library

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

Callback functions not working #264

Closed noahpin closed 2 years ago

noahpin commented 2 years ago

Hello, I am struggling to get Callbacks to work properly. I am using an Arduino Mega connected to my computer via USB. I also am using MocoLUFA for MIDI. I have subscribed to both Clock and NoteOn callbacks, and neither of them are being fired. I am also not seeing the RX light flash whenever anything occurs in my DAW. For that, i'm using the free version of Waveform.

My code is as follows:

#include <MIDI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <SPI.h>

#define sclk 13
#define mosi 11
#define cs   2
#define rst  4
#define dc   3

// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF

Adafruit_SSD1331 display = Adafruit_SSD1331(&SPI, cs, dc, rst);

MIDI_CREATE_DEFAULT_INSTANCE();
#define C3 48
int keys[12] = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
int pins[12] = {52, 22, 50, 24, 48, 46, 26, 44, 28, 42, 30, 40};
int stat[12] = {0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 };

void setup()
{
  MIDI.begin(MIDI_CHANNEL_OMNI);  
  display.begin();
  MIDI.setHandleNoteOn(hNoteOn);
  MIDI.setHandleClock(hClock);
  display.fillScreen(BLACK);
}

int a = 0;

void loop()
{
  for (int i = 0; i < 12; i++) {

    if (digitalRead(pins[i]) == HIGH)
    {
      if (stat[i] == 0) {
        MIDI.sendNoteOn(keys[i], 127, 1);
        stat[i] = 1;
      }
    }
    else {
      if (stat[i] == 1) {
        MIDI.sendNoteOff(keys[i], 0, 1);
        stat[i] = 0;
      }
    }
  }
  MIDI.read();
}
void hNoteOn(byte channel, byte note, byte velocity) {
  display.fillScreen(BLACK);
  display.setCursor(0, 5);
  display.setTextColor(RED);
  display.setTextSize(1);
  display.println(channel);
  display.setCursor(0, 20);
  display.println(note);
  display.setCursor(0, 40);
  display.println(velocity);
}
void hClock(){
}

Thanks in advance!

franky47 commented 2 years ago

The default way of using the MIDI library (via MIDI_CREATE_DEFAULT_INSTANCE) uses a serial transport, to use with MIDI DIN plugs.

Unfortunately, I don't think the Mega has native USB support, so you could use a bridge like HairlessMIDI.

lathoub commented 2 years ago

Correct, Arduino Mega has no MIDI USB capabilities (see here). And you will need to use the USB version of this library, using atmega32u4 based boards or ARM boards.

lathoub commented 2 years ago

I suggest to rename the title to "USB not working on Mega" and move to Discussion.

franky47 commented 2 years ago

I didn't realise @FakeDazon was using MocoLUFA, the issue is probably there if there is no TX activity detected.

@FakeDazon, can you try a minimal setup where you log the received raw serial data to your LCD ?

void setup() {
  Serial.begin(31250); // The baudrate used by MocoLUFA might be different than MIDI's
  display.begin();
}

void loop() {
  if (Serial.available()) {
    display.fillScreen(BLACK);
    display.setCursor(0, 5);
    display.setTextColor(RED);
    display.setTextSize(1);
    display.println(Serial.read());
  }
}
lathoub commented 2 years ago

Never heard on MocoLUFA before, I'm learning today, thanks! (and disregard my comment to rename the issue)

noahpin commented 2 years ago

I am now able to receive MIDI messages, the DAW was just not sending any due to a synthesizer being placed before the output. However, I notice that through the MIDI Library, whenever the Arduino receives a midi byte it sends that same byte back to the PC. And, I tried the barebones serial reading and displaying, and I was able to receive all the correct data without this send-back. How do I bypass the data being sent back to the daw? Because, if I place midi input and output on the same track, I get stuck in an infinite loop of sending and receiving. Thank you!

franky47 commented 2 years ago

Ah, that's the softThru feature, which is on by default on the Serial transport. Since that's what used under the hood, and the MIDI library doesn't know there's a USB behind, you'll have to turn it off manually:

void setup() {
  MIDI.begin();
  MIDI.turnThruOff();
}
noahpin commented 2 years ago

That solved it. Thank you!