Send Midi Clock Issue

Hello! Best regards from Chile, hope you can help me to understand this...

i will try to think and write in english, please excuse me.

Well i'm trying to develope a MIDI tap tempo device. The main goal is to detect the time between button presses and from that estimate the frequency that MIDI message 0xF8 should be sent.

I'm using interrupts and TIMER1. I understand that when I increase the prescaler value, the 'resolutión' decrease... So i've read on the forum that it's a good advice to use de lower prescaler value that is possible. So i'm using 8 as prescaler. If i use the 1024 prescaler... The same compare match register value works for several BPM values.

i'm using this formula to calculate the value of the compare match register with which interrupts are triggered.

So, 120BPM value equals to a 2Hz frequency, then the compare match register value is 41666,625. When i use this value it works pretty well! The BPM values goes from 119.5 to 120.56.

But when I try it with a high frequency, like 290 BPM (that is 4.8333Hz or actually other frequencies that are float), the compare match register value calculated is "17242,52". But then, the BPM loose accuracy. The BPM values goes from 288.5 to 291.5.

This happens because the 24 MIDI messages are not send on a consistent frequency. The intervals are not being respected as in this an example. When the interval isn't respected I understand that the BPM value increases or decreases.

I know that the variation is small, could be negligent either but i would like to know first, why this happens, and then...is there a way to fine tune this value... I´m using arduino Uno/Nano. Should i go for a more powerfull board like the STM32 with a faster core clock?

Later i would like to make a device that stores BPM values and when user press a button, the device send the MIDI clock to a slave device...But the idea is that the slave device detects "290" no 289 or 291. Something like this:

By the way... Is there a chance that this issue is due to the fact that i'm using a software to create a virtual midi port and 'hearing' the serial wreited midi message by another sotware (metronome)?

I dont have a physic device to try this ...

Here is my code:

boolean toggle1 = 0;

void setup() {

  Serial.begin(96000);
  //set pins as outputs
  cli();//stop interrupts
  //set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 17242; //Using the formula to acchieve 290BPM
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 8 prescaler
    TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei();//allow interrupts

  //Stop Timer
  TCCR1B &= 0B11111000;

  //Start Timer
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
    TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

}//end setup
ISR(TIMER1_COMPA_vect) { //timer1 interrupt 1Hz toggles pin 13 (LED)
  //generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
  Serial.write(0xF8);
}


void loop() {
  //do other things here
}

Thanks,thanks so much! I really want to understand and improve this!

1 Like

By the way... i'm using Hairless as serial midi bridge and "MIDIClock" to recieve the midi clock time. I just bought a metronome with MIDI IN, I hope to test how the code works. I will make the corresponding report.

This happens because the 24 MIDI messages are not send on a consistent frequency. The intervals are not being respected as in this an example. When the interval isn't respected I understand that the BPM value increases or decreases.

the frequency at which they are sent is not ruling the received BPM that is converted etc.. most midi-sync receivers take the 24th and calculate from there, (some just calculate back to the time before at any given time) other midi messages are passed as well and the line can get a little clogged, but midi sync accounts for that. Many DAW's fluctuate a lot also when they are sending sync to each other, and since we are taking milliseconds here it is not something that will be disturbing to the ear (in fact it humanizes the whole thing a bit)

But when I try it with a high frequency, like 290 BPM (that is 4.8333Hz or actually other frequencies that are float), the compare match register value calculated is "17242,52". But then, the BPM loose accuracy. The BPM values goes from 288.5 to 291.5.

I thought you were making a "midi sync tapper", can you tap that fast ? that accurately ?Serial.begin(96000);is this your midi-port ? then that is not the correct baud-rate.
Anyway, as long as all you want to send is the midi-sync, then using a timer & interrupt is totally cool, but if you start sending different midi commands as well, you will actually be better of using millis() and the modulo off elapsed time and a counter(for sync's sent per beat), since you don't want any multi-byte commands to accidentally get broken up. Don't worry about the accurate frequency of the sync commands being sent the receiving end will anyway take an average over some period of time.
Most DAW's don't go into sync unless the transmitter send a 'play' or 'record' command btw.

Deva_Rishi:
since you don't want any multi-byte commands to accidentally get broken up.

I don't think this is a problem, since Real-Time events are allowed to be interjected between normal messages without problems:

Real Time messages can be sent at any time and may be inserted anywhere in a MIDI data stream, including between Status and Data bytes of any other MIDI messages. Giving Real-Time messages high priority allows synchronization to be maintained while other operations are being carried out.

Pieter

Wow..thanks so much for your comments!

When i look at this, https://www.youtube.com/watch?v=S1zvAt58WW8 i'm amazed by the accuracy of the device and I wonder how this could be achieved ... Probably it has not been made using arduino or maybe it is.

the frequency at which they are sent is not ruling the received BPM that is converted etc.. most midi-sync receivers take the 24th and calculate from there, (some just calculate back to the time before at any given time) other midi messages are passed as well and the line can get a little clogged, but midi sync accounts for that. Many DAW's fluctuate a lot also when they are sending sync to each other, and since we are taking milliseconds here it is not something that will be disturbing to the ear (in fact it humanizes the whole thing a bit)

From that, could I send only two time messages? is there a way or a MIDI message that could be sent to work with less than the 24 messages?

On the other hand, I bought used, the same metronome that is compared in the video. When it arrives i think it's a programming matter to test wich way is more o less accurate (using Millis() or Interruptions).

Or... maybe there is another way to make this more accurate?

I thought you were making a "midi sync tapper", can you tap that fast ? that accurately ?

Yes! But if you look at the video, user can store BPM values and use them as "Memory presets". I dont have the real product to test it but, I imagine that if the user stores a 290 BPM value, the reciever decive should mark the same BPM value... I'mean that's the idea, besides the tap mode... that could be said that "hides" or "justify" the BPM value inaccuracy

I know... its a +-1 BPM... But hope you can understand the idea and even a -+1 Variation in studio could be crucial.

is this your midi-port ? then that is not the correct baud-rate.

That's correct... But Hairless doesn't work with that baud rate. So i will test it with the metronome.

Most DAW's don't go into sync unless the transmitter send a 'play' or 'record' command btw.

But maybe... if you send a "play" message... a sequence will start!? or this message work as a "Start hearing time messages"? Also... I'm working this mainly with guitar pedals, delay units.

Thank's so much for your help! Have a Good Day!

From that, could I send only two time messages? is there a way or a MIDI message that could be sent to work with less than the 24 messages?

There is Midi-timecode which is supported in some DAW's but not easy to program that.

But maybe... if you send a "play" message... a sequence will start!? or this message work as a "Start hearing time messages"? Also... I'm working this mainly with guitar pedals, delay units.

well using midi-sync i mainly use it either on 'Guitar-Rig' -where i want to sync the delays in my presets- or in 'Ableton' where i actually want the loop player started for the same reason though i may not have any clips running at the time.
either way the DAW's & plugins i use require that play is pressed before they sync to midi-sync messages

I know... its a +-1 BPM... But hope you can understand the idea and even a -+1 Variation in studio could be crucial.

Nope, we are taking about less than 0.5% that is not crucial in this digital age, for sure not with a delay (though usually i use software-delays) just do the math. 290 bpm is 1/(290/6)= 0.206896 s per beat (say nearly 207 ms 291bpm is 1/(291/60)= 0.206185567s let's say 206 ms a studio engineer would not bother even to do a latency compensation for that little, and for sure not for an analog instrument.

When i look at this, https://www.youtube.com/watch?v=S1zvAt58WW8 i'm amazed by the accuracy of the device and I wonder how this could be achieved ... Probably it has not been made using arduino or maybe it is.

yes it's pretty good i think i got this accurate (receiving on Guitar-Rig) the main thing to keep in mind is that you go for 24 'syncs' per beat, so you calculate the length of the beat, divide that by 24, fire 23 sync with that length, and then fire the 24th exactly when you want it (you could use a compare with micros if you want and have nothing better to do) in fact hold the time from the last bpm change and make the 24th, 48th, 72nd etc sync accurate from that point. you lose accuracy because you make the steps to be calculated to small.

PieterP:
I don't think this is a problem, since Real-Time events are allowed to be interjected between normal messages without problems:
Pieter

if you are using the midi library then i think it does take care of that, if you send the midi commands as Serial data as the OP does then you should prevent that from happening somehow (if you plan to send anything else) if you send the 'sync' from an interrupt routine.