Mega and USB - Serial Midi

Hello - I've written some code on the Teensy and converted it to work on the Mega. I need two outputs for my Midi data - USB and Serial. Both work great on the Teensy. On the Mega the serial works just great, however the USB doesn't seem to be doing anything.

I know the code is sloppy at best (I'm new at this), but it works. However, do I need to use different commands to send Midi to the USB port? Any suggestions would be great. Here's my code:

#include <Bounce2.h>
#include <MIDI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

MIDI_CREATE_DEFAULT_INSTANCE();

const int NUM_OF_BUTTONS = 12;
const int MIDI_CHAN = 1;
const int DEBOUNCE_TIME = 40;

Bounce buttons[NUM_OF_BUTTONS + 1] =
{
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
  Bounce(),
};

const int MIDI_MODE_NOTES = 0;
const int MIDI_MODE_CCS = 1;
int midiMode = MIDI_MODE_NOTES;

const int MIDI_NOTE_NUMS[NUM_OF_BUTTONS] = {89, 90, 91, 92, 93, 94, 95, 96, 1, 3, 5, 7};
const int MIDI_NOTE_VELS[NUM_OF_BUTTONS] = {110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110};
const int MIDI_CC_NUMS[NUM_OF_BUTTONS] = {89, 90, 91, 92, 93, 94, 95, 96, 1, 3, 5, 7};
const int MIDI_CC_VALS[NUM_OF_BUTTONS] = {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127};

bool running = false;
bool toggle_state[NUM_OF_BUTTONS] = {false, false, false, false, false, false, false, false, false, false, false, false};
bool pc_sent[NUM_OF_BUTTONS] = {false, false, false, false, false, false, false, false, false, false, false, false};

LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup()
{
  lcd.init();
  Wire.begin();
  lcd.backlight();
  Serial.begin(9600); // Initialize the Serial monitor

  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize MIDI

  for (int i = 0; i < NUM_OF_BUTTONS + 1; i++)
  {
    pinMode(i, INPUT_PULLUP);
    buttons[i].attach(i);
    buttons[i].interval(DEBOUNCE_TIME);
  }
  lcd.begin(20, 4);
  lcd.print("CC and PC Buttons");
  Serial3.begin(31250);
}

void loop()
{
  for (int i = 0; i < NUM_OF_BUTTONS; i++)
  {
    buttons[i].update();
  }

  for (int i = 0; i < NUM_OF_BUTTONS; i++)
  {
    if (buttons[i].fell())
    {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Button: ");
        lcd.print(i + 1);
        lcd.print(" pressed");

      if (i == 8 || i == 9 || i == 10 || i == 11) // Buttons 9, 10, 11, 12
      {
        if (!pc_sent[i])
        {
          pc_sent[i] = true;
          sendProgramChange(MIDI_NOTE_NUMS[i], i);
          Serial3.write(0x90 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_NOTE_NUMS[i]);
          Serial3.write(0xB0 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_CC_NUMS[i]);
          lcd.clear();
          lcd.setCursor(1, 0);
          lcd.print("PC ");
          lcd.print(i + 1);
          lcd.print(" Value ");
          lcd.print (MIDI_NOTE_NUMS[i]);
        }
      }
      else // Buttons 1, 2, 3, 4 ,5, 6, 7, 8
      {
        toggle_state[i] = !toggle_state[i];
        if (toggle_state[i])
        {
          lcd.clear();
          lcd.setCursor(0, 1);
          lcd.print("CC Btn");
          lcd.print(i + 1);
          lcd.print(" ");
          lcd.print(" Value On");
          lcd.print(MIDI_NOTE_NUMS[i]);

          // Send MIDI message through USB
          MIDI.sendNoteOn(MIDI_NOTE_NUMS[i], MIDI_NOTE_VELS[i], MIDI_CHAN);
          MIDI.sendControlChange(MIDI_CC_NUMS[i], MIDI_CC_VALS[i], MIDI_CHAN);

          // Send MIDI message through Serial port
          Serial3.write(0x90 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_NOTE_NUMS[i]);
          Serial3.write(MIDI_NOTE_VELS[i]);
          Serial3.write(0xB0 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_CC_NUMS[i]);
          Serial3.write(MIDI_CC_VALS[i]);
        }
        else
        {
          lcd.clear();
          lcd.setCursor(0, 2);
          lcd.print("CC Btn");
          lcd.print(i + 1);
          lcd.print(" ");
          lcd.print(" Value Off");
          lcd.print(MIDI_NOTE_NUMS[i]);

          // Send MIDI message through USB
          MIDI.sendNoteOff(MIDI_NOTE_NUMS[i], MIDI_NOTE_VELS[i], MIDI_CHAN);
          MIDI.sendControlChange(MIDI_CC_NUMS[i], 0, MIDI_CHAN);

          // Send MIDI message through Serial port
          Serial3.write(0x80 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_NOTE_NUMS[i]);
          Serial3.write(MIDI_NOTE_VELS[i]);
          Serial3.write(0xB0 | (MIDI_CHAN - 1));
          Serial3.write(MIDI_CC_NUMS[i]);
          Serial3.write(0);
        }
      }
    }
    else if (buttons[i].rose())
    {
      if (i == 0 || i == 1 || i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8 || i == 9 || i == 10 || i == 11) // Buttons 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
      {
        pc_sent[i] = false;
      }
    }
  }
}

void sendProgramChange(int pc, int i)
{
  lcd.setCursor(3, 0);
  lcd.print("PC ");
  lcd.print(i + 1);
  lcd.print(" pressed");

  // Send MIDI message through USB
  MIDI.sendProgramChange(pc, MIDI_CHAN);

  // Send MIDI message through Serial port
  Serial3.write(0xC0 | (MIDI_CHAN - 1));
  Serial3.write(pc);
}


I don't found USB using in your code at all

Also, If you use default MIDI settings as this:

it will be an error to initialize Serial manually:

Use USBMIDI - Arduino Reference

Thanks, I’ll give it a shot.

I’m not getting compiler errors. Thankfully!

Unlike the Teensy, the Arduino Mega does not support MIDI over USB natively. See Control Surface: MIDI over USB

Thanks.

Why oh why did I ditch the Teensy for the Mega!?

So, and I’m new to this so please forgive me…..

I need to use a new library, with its particular code (which I know nothing about), create a new script, make sure it works (except of course the simultaneous.midi serial and usb output as I can’t test because it won’t send midi via the usb output), flash new firmware on my Mega, and the hope I did everything correctly?

All I wanted to do was add some more control buttons and associated led’s…..

Did I get this right?

You don't need a different library, but there are many different libraries available, using a library is often easier than writing everything from scratch.
But you do need to understand the hardware limitations of the Mega, and understand how you can use custom firmware for the secondary microcontroller to do MIDI over USB.

For true MIDI over USB, you will need a library, because you shouldn't be writing all of the USB code and descriptors from scratch. For Teensy, this library is included in the Teensyduino core.

What are you mean as "MIDI over USB" ? From the Arduino side, the USB connection is nothing more than yet another Serial interface.
If you talk about the support of the work with USB hardware - this does not apply to arduino Mega at all, whether you use the library or not, because the Mega mcu does not have native USB support.

Correct to both the above.

I want to send midi signals via USB and Serial at the same time. In order to do this, I have to use a flash a new firmware which allows another chip on the Mega to send midi via USB. In addition to the firmware, I need a new library (Control_Surface) that has been developed specifically to allow this.

Its a very complex process as I described above and being new to the process, its very complex for me.

You don't need to use the Control Surface library, you can use any MIDI library.

So go back to the Teensy. Why keep beating your head against the wall?

1 Like

Do I still need to flash the Mega with the custom firmware.

Yes.

If you want MIDI over USB, you need a microcontroller with USB hardware. The ATmega2560 does not include this, so you cannot use it for that purpose without hacks like V-USB. The secondary ATmzga16U2 does include USB hardware in the chip (connected to the Mega's USB port), so you can program that chip to show up as a MIDI device rather than a virtual serial port/modem.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.