Garbage in my MIDI

I’ve breadboarded a MIDI in circuit with a Nano and am running a sketch that listens for MIDI messages and prints them out. It uses SoftwareSerial for MIDI so it can write diagnostics to the serial monitor with hardware serial. Or it can be set up to use hardware serial for MIDI and write no diagnostics; it flashes an LED when it sees a MIDI message of the type or types I specify.

And I’m getting garbage.

I’m using this for MIDI In:

The worse problem is with the Arturia Keystep. If I just play keys manually it does fine. But if I put it in arp mode and hold down one key to get a single-note “arpeggio”, I get this (where “Clock tick” means it’s seen 24 Clock messages):

08:55:59.308 -> ControlChange d1 54 d2 127
08:55:59.341 -> Type = 250 d1 0 d2 0
08:55:59.375 -> Clock tick
08:55:59.507 -> ControlChange d1 54 d2 0
08:56:01.296 -> Clock tick
08:56:02.291 -> NoteOn MIDI note 31 channel 1 velocity 128
08:56:02.358 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:03.319 -> Clock tick
08:56:03.319 -> Type = 255 d1 0 d2 0
08:56:04.280 -> NoteOn MIDI note 74 channel 1 velocity 128
08:56:04.347 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:05.307 -> Clock tick
08:56:06.302 -> NoteOn MIDI note 41 channel 1 velocity 128
08:56:06.335 -> Type = 255 d1 0 d2 0
08:56:07.296 -> Clock tick
08:56:07.328 -> NoteOn MIDI note 74 channel 1 velocity 144
08:56:08.289 -> NoteOn MIDI note 41 channel 1 velocity 128
08:56:08.323 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:09.284 -> Clock tick
08:56:09.317 -> Type = 255 d1 0 d2 0
08:56:10.278 -> NoteOn MIDI note 74 channel 1 velocity 128
08:56:10.345 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:11.307 -> Clock tick
08:56:12.301 -> NoteOn MIDI note 61 channel 1 velocity 128
08:56:12.334 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:13.296 -> Clock tick
08:56:14.290 -> NoteOn MIDI note 41 channel 1 velocity 128
08:56:14.356 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:15.317 -> Clock tick
08:56:15.317 -> Type = 255 d1 0 d2 0
08:56:16.282 -> NoteOn MIDI note 74 channel 1 velocity 128
08:56:16.349 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:17.309 -> Clock tick
08:56:17.309 -> Type = 255 d1 0 d2 0
08:56:18.303 -> NoteOn MIDI note 74 channel 1 velocity 128
08:56:18.337 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:19.298 -> Clock tick
08:56:20.294 -> NoteOn MIDI note 41 channel 1 velocity 128
08:56:20.327 -> NoteOn MIDI note 74 channel 1 velocity 64
08:56:21.287 -> Clock tick

I get pairs of note events per 24 Clock events mostly, as expected, but they’re both NoteOn instead of one on and one off, and the note is usually the correct one, 74, but not always. There also are a lot of System Reset messages (Type 255). Occasionally also there are some random Control Change messages.

Is the Keystep really doing this? I don’t think so, because if I plug it into my Mother-32 all I hear is the same note over and over, on and off, as expected.

This occurs even at the lowest tempo, somewhere around 40 beats per minute.

With another keyboard, my M-Audio MIDI keyboard, plugged in, if I press a key and then do nothing (not touching the keyboard), I get:

08:42:37.362 -> ControlChange d1 93 d2 76
08:42:37.495 -> NoteOn MIDI note 56 channel 1 velocity 47  // key was pressed
08:42:37.627 -> NoteOff MIDI note 56 channel 1
08:43:33.648 -> ControlChange d1 93 d2 70
08:43:33.682 -> ControlChange d1 93 d2 67
08:43:33.715 -> ControlChange d1 93 d2 63
08:43:33.748 -> ControlChange d1 93 d2 60
08:43:33.781 -> ControlChange d1 93 d2 58
08:43:33.815 -> ControlChange d1 93 d2 57
08:43:33.848 -> ControlChange d1 93 d2 56
08:43:33.848 -> ControlChange d1 93 d2 55
08:43:37.891 -> ControlChange d1 93 d2 60
08:43:37.924 -> ControlChange d1 93 d2 62
08:43:37.957 -> ControlChange d1 93 d2 65
08:43:37.990 -> ControlChange d1 93 d2 69
08:43:38.024 -> ControlChange d1 101 d2 93
08:43:38.057 -> ControlChange d1 72 d2 93
08:43:38.057 -> ControlChange d1 73 d2 93
08:43:38.090 -> ControlChange d1 74 d2 93
08:43:39.383 -> ControlChange d1 75 d2 176
08:43:39.416 -> ControlChange d1 93 d2 76
08:43:57.145 -> ControlChange d1 93 d2 77
08:45:23.243 -> ControlChange d1 93 d2 78

At intervals of roughly once a minute, one or more Control Change messages. Almost always with a 93 as either the first or the second data byte.

Note that this keyboard does send Active Sense messages (which my sketch sees but doesn’t print out). I’m thinking these may be somehow corrupted Active Sense messages.

With diagnostic messages turned off and using hardware serial to listen to the MIDI, the LED lights up about once a minute, so I infer the same thing is happening. Therefore this does not appear to be a Software Serial issue or to do with serial output bogging things down.

I have the same issues using an H11L1 optoisolator (different pinout and pullup resistor). I’ve changed the MIDI cable, no change. I’ve tried two Nanos, both clones from Tayda, one brand new, no change.

I’m out of ideas. Do you have any?

Here’s the sketch:

/*
  Listen for MIDI messages (on soft serial pin) and write
  diagnostics (on hard serial)

  CC0 Rich Holmes Feb 2020
*/

#define DO_PRINT 1  // Print events (requires software serial)
#define HSERIAL 0  // 1 for hardware serial, 0 for software

#define TELL_NOTEON     1
#define TELL_NOTEOFF    1
#define TELL_PITCHBEND  1
#define TELL_CC         1
#define TELL_CLOCK     24 // Every nth clock
#define TELL_OTHER      1
#define TELL_ACTIVE     0 // Every nth active sense

#define LED_TELL 10

#include <MIDI.h>

#if HSERIAL==1
MIDI_CREATE_DEFAULT_INSTANCE();
#else
#define MIDI_RX 6 // <--- connect the optocoupler to this pin
#define MIDI_TX 7

unsigned long led_time = 0;

#include <SoftwareSerial.h>
SoftwareSerial midiSerial(MIDI_RX, MIDI_TX);
MIDI_CREATE_INSTANCE(SoftwareSerial, midiSerial, MIDI);
#endif

void setup()
{
#if HSERIAL==0
  Serial.begin(9600);
#endif

  MIDI.begin(MIDI_CHANNEL_OMNI);

  pinMode(LED_TELL, OUTPUT);
  digitalWrite(LED_TELL, LOW);
  led_time = 0;
}

void loop()
{
  int type, noteMsg, velocity, channel, d1, d2, led_on;
  static unsigned int clock_count = 0;
  static unsigned int active_count = 0;

  if (led_time > 0 && millis() - led_time > 300)
    {
      digitalWrite(LED_TELL, LOW);
      led_time = 0;
    }

  led_on = 0;
  if (MIDI.read()) {
    byte type = MIDI.getType();
    switch (type) {
    case midi::NoteOn:
#if TELL_NOTEON>0       
      led_on = 1;
#if DO_PRINT > 0
      noteMsg = MIDI.getData1();
      channel = MIDI.getChannel();
      velocity = MIDI.getData2();
      Serial.print ("NoteOn");
      Serial.print (" MIDI note ");
      Serial.print (noteMsg+21);
      Serial.print (" channel ");
      Serial.print (channel);  
      Serial.print (" velocity ");
      Serial.println (velocity);  
#endif
#endif
      break;

    case midi::NoteOff:
#if TELL_NOTEOFF>0      
      led_on = 1;
#if DO_PRINT > 0
      noteMsg = MIDI.getData1();
      channel = MIDI.getChannel();
      Serial.print ("NoteOff");
      Serial.print (" MIDI note ");
      Serial.print (noteMsg+21);
      Serial.print (" channel ");
      Serial.println (channel);  
#endif
#endif
      break;

    case midi::PitchBend:
#if TELL_PITCHBEND>0
      led_on = 1;
#if DO_PRINT > 0
      d1 = MIDI.getData1();
      d2 = MIDI.getData2(); // d2 from 0 to 127, mid point = 64
      Serial.print ("PitchBend");
      Serial.print (" d1 ");
      Serial.print (d1);
      Serial.print (" d2 ");
      Serial.println (d2);  
#endif
#endif
      break;

    case midi::ControlChange:
#if TELL_CC     
      led_on = 1;
#if DO_PRINT > 0
      d1 = MIDI.getData1();
      d2 = MIDI.getData2(); // From 0 to 127
      Serial.print ("ControlChange");
      Serial.print (" d1 ");
      Serial.print (d1);
      Serial.print (" d2 ");
      Serial.println (d2);  
#endif
#endif
      break;

    case midi::Clock:
#if TELL_CLOCK>0
      led_on = 1;
#if DO_PRINT > 0
      if (clock_count == 0)
        Serial.println ("Clock tick");
      clock_count++;
      if (clock_count == TELL_CLOCK)
        clock_count = 0;
#endif
#endif
      break;

    case midi::ActiveSensing:
#if TELL_ACTIVE>0
      led_on = 1;
#if DO_PRINT > 0
      if (active_count == 0)
        Serial.println ("ActiveSensing");
      active_count++;
      if (active_count == TELL_CLOCK)
        active_count = 0;
#endif
#endif
      break;
      

    default:
#if TELL_OTHER>0        
      led_on = 1;
#if DO_PRINT > 0
      d1 = MIDI.getData1();
      d2 = MIDI.getData2();
      Serial.print ("Type = ");
      Serial.print (type);
      Serial.print (" d1 ");
      Serial.print (d1);
      Serial.print (" d2 ");
      Serial.println (d2);  
#endif
#endif
    }
    if (led_on > 0)
      {    digitalWrite(LED_TELL, HIGH);
        led_time = millis();
      }
  }
}
1 Like

I believe soft serial has limitations as eluded to here… ( post 2 )

2 Likes

can you send debug to an I2C LCD?

1 Like

Right, but LED evidence is at least some of the same is happening with hard serial.

Good idea, got one around somewhere

Yes, hardware serial is the way to go, I’ve had little issue with the midi interface I built and I had to build an amplifier on the optocoupler because I used some random one from my junk box!

Some midi devices send noteOn vel 0 instead of noteOff messages and iirc the key step is one of those devices, so that explains the double note on.

Finally after a long long effort got the OLED kind of working enough to establish that with hard serial, the Keystep does appear to be producing correct NoteOn/NoteOff (not double NoteOn) pairs. So I think soft serial is most of the problem. There was still the indication I had before of stray CC messages with the M_Audio keyboard but who knows, maybe that keyboard is flaky.

2 Likes

Them OLED ones are a bit of a bit more complex than the plain LCD’s

Good to know it’s worked and provided the evidence :slight_smile:

Yeah, I can barely get any sensible behavior out of the OLED. I don’t know if this Adafruit library is inherently flaky or if between it and the MIDI library there’s too little memory to function correctly or what. I suspect the latter. Is there a better/smaller OLED library?

I may have to bite the bullet and go Teensy.

Before you go off to teensy land, try reducing the refresh rate of your screen by only updating the screen every x cycles. Just make a counter var, and skip update logic unless it’s time.

It’s not timing, it’s memory use, I think. Anyway, I don’t touch the OLED except when a new MIDI message comes in.

I wasnt suggesting it was timing. I was suggesting you might be constantly refreshing the screen state, which would eat into your performance.

What OLED you running? A code update since adding the OLED would be helpful.

I’ve never had much luck with the oled adafruit library. U8glib and u8g2 take a bit of trial to figure out configuration wise, but I’ve found them to be much better.

2 Likes

Yeah, the U8’s are the ones I tried.

THANK YOU! That is SO much better:

2 Likes

Excelent, a nice adition to the module :slight_smile:

I just plugged in the M-Audio keyboard (using hardware serial) and sure enough it’s spewing a bunch of CC 93 xx messages and occasionally CC 5 xx. No idea why. They come and go.

ControlChange d1 93 d2 76

I’m a bit puzzled by your debugging output – isn’t 0xDn channel pressure/aftertouch (2 bytes), rather than control change (which is 0xBn, and followed by 2 bytes, not 3).

(I usually just ignore any MIDI commands I don’t care about, so no idea what my keyboards output when they’re not doing useful things :smiley:)

1 Like
    case midi::ControlChange:
#if TELL_CC     
      led_on = 1;
      d1 = MIDI.getData1();
      d2 = MIDI.getData2(); // From 0 to 127
#if OLED>0
      u8x8log.print("CC   ");
      u8x8log.print(d1);
      u8x8log.print(" ");
      u8x8log.print(d2);
      u8x8log.print("\n");
#endif
#if DO_PRINT > 0
      Serial.print ("ControlChange");
      Serial.print (" d1 ");
      Serial.print (d1);
      Serial.print (" d2 ");
      Serial.println (d2);  
#endif
#endif
      break;

It saw midi::ControlChange, and then subsequent calls to getData1 and getData2 returned 93 and 76. That’s all I know.

Oh, I see… d1 and d2 are not hex values, they’re just labels for the first and second data bytes.

Oh, so none of the four hex bytes were hex bytes? Sneaky :slight_smile:

According to the MIDI spec, 93 (0x5D) is effects 3 depth, which seems a bit random to me, but then I’m not an M Audio keyboard.

(What keyboard is this? I flipped through the manual for a random one (CODE 25/49/61), and it seems virtually any knob, button or key on it can be configured to output arbitrary CC commands.)