Last Updated or created 2025-09-07
Two versions of a mini monitor
A version using a Arduino and a Midi shield (Yellow wires are for display)
D0 (RX) is used for the Midi IN signal.
Above a Teensy 4.0 version. This one uses MIDI over USB.
Next to add: Rotary encoders, to select a CC Channel and display values graphically
CODE for Teensy version
#include <U8g2lib.h> #include <Wire.h> #include <MIDIUSB.h> // Teensy's built-in USB MIDI // SH1106 128x64 I2C constructor U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); void setup() { u8g2.begin(); u8g2.clearBuffer(); u8g2.setFont(u8g2_font_6x12_tf); u8g2.drawStr(0,12,"MIDI Monitor Ready"); u8g2.sendBuffer(); } void loop() { // Check for incoming MIDI while (usbMIDI.read()) { u8g2.clearBuffer(); u8g2.setFont(u8g2_font_6x12_tf); u8g2.drawStr(0,12,"MIDI Monitor Ready"); u8g2.sendBuffer(); byte type = usbMIDI.getType(); byte channel = usbMIDI.getChannel(); byte data1 = usbMIDI.getData1(); byte data2 = usbMIDI.getData2(); int y = 24; if (type == usbMIDI.NoteOn && data2 > 0) { u8g2.setCursor(0, y); u8g2.print("Note ON "); // pad u8g2.setCursor(0, y+12); u8g2.printf("Ch:%-3d", channel); // pad width 3 u8g2.setCursor(0, y+24); u8g2.printf("Note:%-3d", data1); u8g2.setCursor(0, y+36); u8g2.printf("Vel:%-3d", data2); } else if (type == usbMIDI.NoteOff || (type == usbMIDI.NoteOn && data2 == 0)) { u8g2.setCursor(0, y); u8g2.print("Note OFF "); // pad u8g2.setCursor(0, y+12); u8g2.printf("Ch:%-3d", channel); u8g2.setCursor(0, y+24); u8g2.printf("Note:%-3d", data1); } else if (type == usbMIDI.ControlChange) { u8g2.setCursor(0, y); u8g2.print("Control Chg "); u8g2.setCursor(0, y+12); u8g2.printf("Ch:%-3d", channel); u8g2.setCursor(0, y+24); u8g2.printf("CC#:%-3d", data1); u8g2.setCursor(0, y+36); u8g2.printf("Val:%-3d", data2); } else { u8g2.setCursor(0, y); u8g2.print("Other MIDI "); u8g2.setCursor(0, y+12); u8g2.printf("Type:%-3d", type); } u8g2.sendBuffer(); } }
CODE for Arduino plus shield
#include <U8g2lib.h> #include <Wire.h> #include <MIDI.h> // FortySevenEffects MIDI library // SH1106 128x64 I2C (page buffer, low RAM) U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // MIDI on hardware Serial (RX=D0) MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI); char line[12]; // small buffer for formatting void setup() { u8g2.begin(); u8g2.setFont(u8g2_font_6x12_tf); // proportional font, small size // Initial message u8g2.firstPage(); do { u8g2.setCursor(0, 12); u8g2.print("MIDI Monitor Ready"); } while (u8g2.nextPage()); MIDI.begin(MIDI_CHANNEL_OMNI); // listen to all channels } void loop() { if (MIDI.read()) { byte type = MIDI.getType(); byte channel = MIDI.getChannel(); byte data1 = MIDI.getData1(); byte data2 = MIDI.getData2(); // Page buffer redraw u8g2.firstPage(); do { // Title u8g2.setCursor(0, 12); u8g2.print("MIDI Monitor"); int y = 24; // start lower down if (type == midi::NoteOn && data2 > 0) { u8g2.setCursor(0, y); u8g2.print("Note ON "); snprintf(line, sizeof(line), "Ch:%-3d", channel); u8g2.setCursor(0, y+12); u8g2.print(line);32 snprintf(line, sizeof(line), "Note:%-3d", data1); u8g2.setCursor(0, y+24); u8g2.print(line); snprintf(line, sizeof(line), "Vel:%-3d", data2); u8g2.setCursor(0, y+36); u8g2.print(line); } else if (type == midi::NoteOff || (type == midi::NoteOn && data2 == 0)) { u8g2.setCursor(0, y); u8g2.print("Note OFF "); snprintf(line, sizeof(line), "Ch:%-3d", channel); u8g2.setCursor(0, y+12); u8g2.print(line); snprintf(line, sizeof(line), "Note:%-3d", data1); u8g2.setCursor(0, y+24); u8g2.print(line); } else if (type == midi::ControlChange) { u8g2.setCursor(0, y); u8g2.print("Control Chg"); snprintf(line, sizeof(line), "Ch:%-3d", channel); u8g2.setCursor(0, y+12); u8g2.print(line); snprintf(line, sizeof(line), "CC#:%-3d", data1); u8g2.setCursor(0, y+24); u8g2.print(line); snprintf(line, sizeof(line), "Val:%-3d", data2); u8g2.setCursor(0, y+36); u8g2.print(line); } else { u8g2.setCursor(0, y); u8g2.print("Other MIDI"); snprintf(line, sizeof(line), "Type:%-3d", type); u8g2.setCursor(0, y+12); u8g2.print(line); } } while (u8g2.nextPage()); } }