Midi filtertering of stop start messages

Ok I think I figured it out.
By changing "clk=0;" to clk=23; in both places!
It appears now to start bang on time.

I was just about to post

There is nothing fundamentally different between the first start and a stop/start

So now, your very first start will be 1 tick too soon. You could also change it to this

    if ((data == midi_clock) && (play_flag == 1)) {
      if (clk == 0) digitalWrite(tempoled, HIGH);
      if (clk == 7) digitalWrite(tempoled, LOW);  // this should light it up for 25% of the time
      clk = (clk+1) % 24;
      Serial.write(midi_clock); // send midi clock to out... Provides tempo!
    }

which reduces the amount of times digitalWrite() is actually called and then leave all your clk=0 statements

You guys got it sussed. The increment comes to at the begining of the if statement, it probably should come at the end and then you can reset it to '0' It must have been a little early before as well

if ((data == midi_clock) && (play_flag == 1)) {      
      if (clk / 6) digitalWrite(tempoled, LOW);  // this should light it up for 25% of the time
      else digitalWrite(tempoled, HIGH);
      Serial.write(midi_clock); // send midi clock to out... Provides tempo!
      clk++;
      clk = clk % 24;                                 // 24 clock messages per beat
    }

and i actually think that it should be like this for continue, you don't reset the clock it is 'continue' after all

    if (data == midi_continue) { // if midi in continue
      Serial.write(midi_continue); // send midi out continue
      play_flag = 1;
      // clk=0; don't reset the clock for continue
    }

I wasn't sure what that was supposed to do.. more of a pause/un-pause or more of a no-op.

It continues after 'stop' from the point where it stopped.
We should probably turn the led off when it receives a 'stop' as well.

A million thanks to you both for the generous help!

Yes, I realise I have been under the illusion the led was turning off with each stop. I will take a bash at that!

I wonder if I could ask you both once again for your help?

I want to send a midi note to a module to indicate audibly the tempo along with the LED. I have tried adding this but I'm afraid the coding won't compile correctly.

   else if ((data == midi_clock) && (play_flag == 1)) {
      if (clk / 2) digitalWrite(tempoled, LOW); //digitalWrite(tempoled, LOW);  // percentage of lit time
      MIDI.sendNoteOn(60, 127, 1);
      else digitalWrite(tempoled, HIGH); //digitalWrite(tempoled, HIGH);
      digitalWrite(tempoled, HIGH);
      MIDI.sendNoteOn(60, 0, 1);
      Serial.write(midi_clock); // send midi clock to out... Provides tempo!
      clk++;
      clk = clk % 24;
    }
  }
}

What do I need to alter in the code please?

Your if/else statement does not contain { or } so only one statement is being executed with those which means your sendNoteOn() function is being called every time. You need to go back to when the led is only toggled at the correct time, not every time

    if ((data == midi_clock) && (play_flag == 1)) {
      if (clk == 0) {
        digitalWrite(tempoled, HIGH);
        // insert note here
      }
      if (clk == 7) {
        digitalWrite(tempoled, LOW);  // this should light it up for 25% of the time
        // insert note here
      }
      clk = (clk+1) % 24;
      Serial.write(midi_clock); // send midi clock to out... Provides tempo!
    }
1 Like

Totally ! Also send the noteOn when you turn the LED on and send noteOff when you turn the LED off. It's perfect just like that.

1 Like

That's fantastic! That's much clearer to me now and easier to add any extras I may need down the line! I've added in some extra code as I wanted to use GM midi to access some percussion sounds from a synth chip to create a metronome triggered by the sequencer or master clock. Below is my updated code for anyone who may need it. Thanks immensely blh64 and Deva_Rishi for your time and help!

#define drumchan           9

// general midi drum notes
#define note_snaredrum    37 // rimshot!


// MIDI clock as per Little Scale
byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;
byte midi_continue = 0xfb;

static uint8_t clk = 0;


// Variables
int tempoled = 13;
int play_flag = 0;
byte data;


// Setup
void setup() {
  Serial.begin(31250);
  pinMode(tempoled, OUTPUT);
}


// Program
void loop() {

  if (Serial.available() > 0) {
    data = Serial.read();

    if (data == midi_start) { // if midi in start
      Serial.write(midi_start); // send midi out start
      play_flag = 1;
      clk = 0;
    }

    if (data == midi_continue) { // if midi in continue
      Serial.write(midi_continue); // send midi out continue

      play_flag = 1;
    }

    if (data == midi_stop) { // if midi in stop
      Serial.write(midi_stop); // send midi out stop
      digitalWrite(tempoled, LOW);
      play_flag = 0;
    }



    if ((data == midi_clock) && (play_flag == 1)) {
      if (clk == 0) {
        digitalWrite(tempoled, HIGH);
        noteOn(drumchan,  note_snaredrum, 100);
      }
      if (clk == 7) {
        digitalWrite(tempoled, LOW);  // this should light it up for 25% of the time
        noteOff(drumchan,  note_snaredrum, 0);
      }
      clk = (clk + 1) % 24;
      Serial.write(midi_clock); // send midi clock to out... Provides tempo!
    }
  }
}
// Send a MIDI note-on message.  Like pressing a piano key
// channel ranges from 0-15
void noteOn(byte channel, byte note, byte velocity) {
  midiMsg( (0x90 | channel), note, velocity);
}

// Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte velocity) {
  midiMsg( (0x80 | channel), note, velocity);
}

// Send a general MIDI message
void midiMsg(byte cmd, byte data1, byte data2) {
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

:slightly_smiling_face: