Building a MIDI Beat Indicator

I am new to Arduino - built one board several years ago using someone else's code. Now trying to build a MIDI Beat Indicator that takes the MIDI out from my Drum Machine to a remote display that I can see from my organ bench. Using UNO R3 with a MIDI shield. I found the code example and with one correction it compiled. However, it isn't doing anything. Should blink the built in LED. Am I missing something?

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

// Define MIDI input and LED pin
#define MIDI_IN_PIN 2  // Example: Use digital pin 2 for MIDI input
#define LED_PIN 13     // Example: Use digital pin 13 for the LED

// MIDI variables
byte midi_clock = 0xf8;
int clock_counter = 0;
bool running = false;

// Function to handle incoming MIDI clock messages
void handleClock() {
  if (running) {
    clock_counter++;
    if (clock_counter >= 24) { // MIDI clock sends 24 pulses per quarter note
      clock_counter = 0;
      digitalWrite(LED_PIN, HIGH); // Turn LED on
      delayMicroseconds(50); // Short pulse for visibility
      digitalWrite(LED_PIN, LOW); // Turn LED off
    }
  }
}

// Function to handle incoming MIDI Start message
void handleStart() {
  running = true;
  clock_counter = 0;
}

// Function to handle incoming MIDI Stop message
void handleStop() {
  running = false;
}

// Function to handle incoming MIDI Continue message
void handleContinue() {
  running = true;
}

void setup() {
  // Initialize MIDI
  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.setHandleClock(handleClock);
  MIDI.setHandleStart(handleStart);
  MIDI.setHandleStop(handleStop);
  MIDI.setHandleContinue(handleContinue);

  // Set LED pin as output
  pinMode(LED_PIN, OUTPUT);

  // Optional: Set up serial communication for debugging
  Serial.begin(115200);
}

void loop() {
  MIDI.read(); // Check for incoming MIDI messages
}

Check the documentation for your MIDI shield — many shields route MIDI input to digital pin 4 (not pin 2 as your code assumes).

The MIDI shield did not come with documentation. I tried changing to 4 and it still did not work.

I tried changing to pin 0 (RX) based on looking at the circuit on the shield, and because RX made sense. Still did not work. If the shield is working, shouldn't the RX light flash with the MIDI Clock (24 times per beat)?

Solved it. I needed to change the serial rate to 31250. And the RX light does not appear to be flashing. But the LED does flash with the beat.

The next phase of this project is to light up one of four LEDS, depending on the beat. I'm assuming 4/4 rhythm (for the musicians here). I want one light to appear on Beat 1, another on Beat 2, etc, and then start over. I assume I need a variable (Beat?) and increment it by one until I reach 4 and then reset. So, what is the best logic to use? If/Else or Switch/Case? Thoughts. Again, new at Arduino.

// currentBeat 1 to 4

switch ( currentBeat ) {
  case 0: // fall through to start
  case 1:
    // beat 4 off, beat 1 on
    digitalWrite(beat4LEDpin, LOW);
    digitalWrite(beat1LEDpin, HIGH);
    currentBeat = 2;
    break;
  case 2:
    // beat 1 off, beat 2 on
    digitalWrite(beat1LEDpin, LOW);
    digitalWrite(beat2LEDpin, HIGH);
    currentBeat = 3;
    break;
  case 3:
    // beat 2 off, beat 3 on
    digitalWrite(beat2LEDpin, LOW);
    digitalWrite(beat3LEDpin, HIGH);
    currentBeat = 4;
    break;
  case 4:
    // beat 3 off, beat 4 on
    digitalWrite(beat3LEDpin, LOW);
    digitalWrite(beat4LEDpin, HIGH);
    currentBeat = 1;
    break;
}

You will have to define what the beatXLEDpin variables actual pin numbers will be.

@damuehlbauer - can you even see this? Just curious:

 delayMicroseconds(50); // Short pulse for visibility

Using the build in LED on an UNO I can see a tiny pop of light, no way would it be useful from more than a few feet away, and certainly not if there were other LEDs competing for attention.

I kept increasing the on time; for these old eyes, 10 milliseconds (200 times longer) was just starting to be useful.

Now I don't know where you are going with this sketch, or how much you want or need to learn as you go, but the usual recommendation when a programmer moves from doing one thing to doing the same kind of thing N times is that it is time to take a break and learn about arrays and loops and functions.

You will def see them in competent code you read and borrow or steal.

Start here or google for your preferred learning choice:

https://docs.arduino.cc/language-reference/en/variables/data-types/array/

Also, loops go well with arrays, so maybe

https://docs.arduino.cc/language-reference/en/structure/control-structure/for/

The clue is the appearance or reliance on variables that are made distinct by appending an increasing letter or number, led1, led2, led3 &c. One array variable can hold them all and allows you to refer to them by number, called an index. The index expression can be an integer variable or computed number, whatever. Flexible.

Using arrays and loops (and functions) results in compact code which is easier to write, read, fix and enhance. All completely worth any time and struggle. Here's simple sketch that runs a few LEDs.

Here's simple sketch that runs a few LEDs. Just to show some of the syntax in action and a few tricks. Note: get accustomed to numbering N things bot 1 .. N, rather 0 .. (N - 1). It is the way of C/C++. In real code if it is necessary for the humans, the printed number can be a white lie!

const byte ledPin[4] = {5, 4, 3, 2};

void setup() {
  Serial.begin(115200);
  Serial.println("\nHi Mom!\n");

  for (int ii = 0; ii < 4; ii++) {
    pinMode(ledPin[ii], OUTPUT);
    digitalWrite(ledPin[ii], LOW);
  }
}

int beatCount;

void loop() {
  digitalWrite(ledPin[beatCount], LOW);

  beatCount++;
  if (beatCount == 4) beatCount = 0;

  digitalWrite(ledPin[beatCount], HIGH);

  Serial.print("and the beat is ");
  Serial.println(beatCount + 1);       // a white-ish lie!
  
  delay(777);
}

You may also like to try the wokwi simulator - here's that code along with a few LEDs lashed up to show the possibilities:

HTH

a7

I was able to get this to work using the code from blh64. The second was interesting (and I'm sure more efficient). Just beyond my skill set at this point.

My next question is more cosmetic. The MIDI shield does not align the IN and OUT ports with the power and USB ports on the Arduino board. I assume the USB port is too high. But I need to put this in a case and I'm wondering if anyone has suggestions. I wound up breadboarding it during development, so I know which pins I need to connect where, but I need something that will be fairly sturdy when assembled. Thoughts? Examples?

Appreciate everyone's help!

Completed the unit and it works as planned.

Please post the complete sketch you ended up with.

TIA

a7

Here is the code that is current installed and working. I’m new at this, so I’m sure there are improvements possible.

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

// Define MIDI input and LED pin
#define MIDI_IN_PIN 0  // Example: changed to pin 0 RX based on PCB circuit
#define beat1LEDpin 4
#define beat2LEDpin 5
#define beat3LEDpin 6
#define beat4LEDpin 7

int currentBeat = 1;

// MIDI variables
byte midi_clock = 0xf8;
int clock_counter = 0;
bool running = false;

// Function to handle incoming MIDI clock messages
void handleClock() {
  if (running) {
    clock_counter++;
    if (clock_counter >= 24) {  // MIDI clock sends 24 pulses per quarter note
      clock_counter = 0;

      // Currentbeat 1 to 4

      switch (currentBeat) {
        case 0:  // fall through to start
        case 1:
          // beat 4 off, beat 1 on
          digitalWrite(beat4LEDpin, LOW);
          digitalWrite(beat1LEDpin, HIGH);
          currentBeat = 2;
          break;
        case 2:
          // beat 1 off, beat 2 on
          digitalWrite(beat1LEDpin, LOW);
          digitalWrite(beat2LEDpin, HIGH);
          currentBeat = 3;
          break;
        case 3:
          // beat 2 off, beat 3 on
          digitalWrite(beat2LEDpin, LOW);
          digitalWrite(beat3LEDpin, HIGH);
          currentBeat = 4;
          break;
        case 4:
          // beat 3 off, beat 4 on
          digitalWrite(beat3LEDpin, LOW);
          digitalWrite(beat4LEDpin, HIGH);
          currentBeat = 1;
          break;
      }
    }
  }
}

// Function to handle incoming MIDI Start message
void handleStart() {
  running = true;
  clock_counter = 23; //start on beat #1 and light LED 1
}

// Function to handle incoming MIDI Stop message
void handleStop() {
  running = false;
  digitalWrite(beat1LEDpin, LOW); //make sure all four LEDs are off after stop
  digitalWrite(beat2LEDpin, LOW);
  digitalWrite(beat3LEDpin, LOW);
  digitalWrite(beat4LEDpin, LOW);
  currentBeat = 1;
}

// Function to handle incoming MIDI Continue message
void handleContinue() {
  running = true;
}

void setup() {
  // Initialize MIDI
  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.setHandleClock(handleClock);
  MIDI.setHandleStart(handleStart);
  MIDI.setHandleStop(handleStop);
  MIDI.setHandleContinue(handleContinue);

  // Set LED pin as output
  pinMode(beat1LEDpin, OUTPUT);
  pinMode(beat2LEDpin, OUTPUT);
  pinMode(beat3LEDpin, OUTPUT);
  pinMode(beat4LEDpin, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  // Set up serial communication for debugging
  Serial.begin(31250);
}

void loop() {
  MIDI.read();  // Check for incoming MIDI messages
}