Hey all I found myself in need of a product that would convert 5pin MIDI into midi over USB to control my Hotone Ampero Mini from a midi controller that sends program change messages over a 5pin MIDI DIN cable connected to the arduino uno.
I found these instructions and library http://cyfrowogitarowo.pl/wp-content/uploads/2014/04/MIDI-USB-HOST-DIY-tutorial.pdf as to not reinvent the wheel. I've got it working but it has 1 quirk.
It only works if the Arduino is powered (at least when it starts) by a usb port on my computer. if the arduino is off, and I power it on from say, a 9v battery or other power source on the barrel jack, it won't function (at least not that I can tell from watching my ampero not change patches when I send it program change messages from a midi controller).
If I power on the arduino from a usb port on my PC, then plug in a barrel jack power supply, then unplug the USB to my computer, the unit functions just as it should, so it only seems to matter what power supply is used when the arduino first starts, leading me to think it's something with a serial connection that's made on startup.
I've done arduino projects before but it's always been my code instead of someone elses, and I'm not really familiar with this library, nor did I find my answer trying to dig through documentation on it. I'm sure that's a failure on my part. Hoping one of you can help me spot the problem. Exact code I'm using is straight from the library example "bidirectional_converter" from USB Host Shield Library 2.0
If anyone has the time to help me out I'd really appreciate it! Thanks in advance!
/*
*******************************************************************************
* Legacy Serial MIDI and USB Host bidirectional converter
* Copyright (C) 2013-2021 Yuuichi Akagawa
*
* for use with Arduino MIDI library
* https://github.com/FortySevenEffects/arduino_midi_library/
*
* Note:
* - If you want use with Leonardo, you must choose Arduino MIDI library v4.0 or higher.
* - This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <MIDI.h>
#include <usbh_midi.h>
#include <usbhub.h>
//Arduino MIDI library v4.2 compatibility
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif
// Set to 1 if you want to wait for the Serial MIDI transmission to complete.
// For more information, see https://github.com/felis/USB_Host_Shield_2.0/issues/570
#define ENABLE_MIDI_SERIAL_FLUSH 0
//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////
USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
//If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE
#ifdef USBH_MIDI_SYSEX_ENABLE
//SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
Midi.SendSysEx(sysexmsg, sizeofsysex);
}
#endif
void setup()
{
MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.turnThruOff();
#ifdef USBH_MIDI_SYSEX_ENABLE
MIDI.setHandleSystemExclusive(handle_sysex);
#endif
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
uint8_t msg[4];
Usb.Task();
if ( Midi ) {
MIDI_poll();
if (MIDI.read()) {
msg[0] = MIDI.getType();
switch (msg[0]) {
case midi::ActiveSensing :
break;
case midi::SystemExclusive :
//SysEx is handled by event.
break;
default :
// If this is a channel messages, set the channel number.
if( msg[0] < 0xf0 ){
// The getchannel() returns 1-16, but the MIDI status byte starts at 0.
msg[0] |= MIDI.getChannel() - 1;
}
msg[1] = MIDI.getData1();
msg[2] = MIDI.getData2();
Midi.SendData(msg, 0);
break;
}
}
}
}
// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
uint8_t size;
#ifdef USBH_MIDI_SYSEX_ENABLE
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
uint8_t rcode = 0; //return code
uint16_t rcvd;
uint8_t readPtr = 0;
rcode = Midi.RecvData( &rcvd, recvBuf);
//data check
if (rcode != 0) return;
if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
return ;
}
uint8_t *p = recvBuf;
while (readPtr < MIDI_EVENT_PACKET_SIZE) {
if (*p == 0 && *(p + 1) == 0) break; //data end
uint8_t outbuf[3];
uint8_t rc = Midi.extractSysExData(p, outbuf);
if ( rc == 0 ) {
p++;
size = Midi.lookupMsgSize(*p);
_MIDI_SERIAL_PORT.write(p, size);
p += 3;
} else {
_MIDI_SERIAL_PORT.write(outbuf, rc);
p += 4;
}
#if ENABLE_MIDI_SERIAL_FLUSH
_MIDI_SERIAL_PORT.flush();
#endif
readPtr += 4;
}
#else
uint8_t outBuf[3];
do {
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
//MIDI Output
_MIDI_SERIAL_PORT.write(outBuf, size);
#if ENABLE_MIDI_SERIAL_FLUSH
_MIDI_SERIAL_PORT.flush();
#endif
}
} while (size > 0);
#endif
}