Last Updated or created 2025-10-21
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());
}
}
