sending midi data without delay.

hi everyone,

today i feel like a real noob, i am at one of those points where my brain just wont work. please can you guys help me!

i am making a midi master clock generator,

midi needs to be sent 24 times per quater note, so i did a calculation, first beat - second beat / 24

that gives me the interval i need in microseconds,

but i am using a for loop, loop 24 times, and inside the loop is just send midi data, delay for calculated time.

i am going to have a go at putting in some code now:

   if (oldTick != tick) {
     pTimeout = millis();
     
     switch (tick){
       case 1:
       tickTime1 = micros();
       calculatedTime = ((tickTime1-tickTime4)/24);
       break;
       case 2:
       tickTime2 = micros();
       calculatedTime = ((tickTime2-tickTime1)/24);
       break;
       case 3:
       tickTime3 = micros();
       calculatedTime = ((tickTime3-tickTime2)/24);
       break;
       case 4:
       tickTime4 = micros();
       calculatedTime = ((tickTime4-tickTime3)/24);
       break;
     }
      
     if ((tick == 1)&&(play == true)) Serial.print(midi_start, BYTE);
     

     for (int i = 0; i < 24; i++) {
       Serial.print(midi_clock, BYTE);
       delayMicroseconds(calculatedTime);
     }

but this doesn’t work, the delay slows down the rest of the code, causing the stored micros() values to get further and further apart until the midi signal times out.

if i replace the output of my code to just serial print to the debug window it is perfectly in time just not divided by 24, it is coming in at the BPM speed, if i add the divide by 24 code everything falls appart.

help, this is driving me mad! i am so close i am sure!

The delay and delayMicroseconds functions make the Arduino twiddle it’s thumbs until the specified time has passed. Using the millis and micros functions and some calculations, you are determining when the next output needs to occur.

Instead of using delayMicroseconds, just set a flag for when the next action needs to occur. In each pass through loop, see if it’s time to take that action (using millis() or micros()) and reset the time for the next action.

Look at the BlinkWithoutDelay example.

hi and thanks for the reply. i had a look at the blink without delay thing. i am not so sure how to work out a time for it to check against,

i am not so sure how to work out a time for it to check against,

You are setting pTimeout and tickTimeN in the snippet of code you posted, as well as calculating calculatedTime.

Those variables must mean something to you.

We'd need to see all of your code to help you more.

sorry, you are right, that was a lame reply, i was just checking the sensors and i managed to break them so a am a bit frustrated at the moment. i waited 3 weeks for them to arrive and now they are broken…

anyway here is the whole code.

int pinBPM1Input = 0; 
int pinBPM2Input = 1; 
int pinBPM3Input = 2; 
int pinBPM4Input = 3; 

int tick = 0;
int oldTick = 0;
int play = false;
int long pTimeout = 0;
int long calculatedTime = 0;
int long tickTime1 = 0;
int long tickTime2 = 0;
int long tickTime3 = 0;
int long tickTime4 = 0;

byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;

 void setup() {
 Serial.begin(9600);
  
  pinMode(pinBPM1Input,INPUT);
  pinMode(pinBPM2Input,INPUT);
  pinMode(pinBPM3Input,INPUT);
  pinMode(pinBPM4Input,INPUT);
 }

void loop() {
  oldTick = tick; 
  if (analogRead(pinBPM1Input)>6) tick = 1;
   else { 
     if (analogRead(pinBPM2Input)>6) tick = 2;
        else {  
          if (analogRead(pinBPM3Input)>6) tick = 3;   
            else {  
              if (analogRead(pinBPM4Input)>6) {
                  tick = 4;
                  if (play = false) play = true;
                  }
                else{ 
                  if (millis() > (pTimeout+1000)) {
                    tick = 0;
                    tickTime1 = 0;
                    tickTime2 = 0;
                    tickTime3 = 0;
                    tickTime4 = 0;
                    if (play) {
                      play = false;
             //         Serial.print(midi_stop, BYTE);
                    }
                  }
                 }
             }
         }
     }
      int a = analogRead(pinBPM1Input);          
   if (oldTick != tick) {
     pTimeout = millis();
     switch (tick){
       case 1:
       tickTime1 = micros();
       calculatedTime = ((tickTime1-tickTime4)/24);
       break;
       case 2:
       tickTime2 = micros();
       calculatedTime = ((tickTime2-tickTime1)/24);
       break;
       case 3:
       tickTime3 = micros();
       calculatedTime = ((tickTime3-tickTime2)/24);
       break;
       case 4:
       tickTime4 = micros();
       calculatedTime = ((tickTime4-tickTime3)/24);
       break;
     }
      
     if ((tick == 1)&&(play == true)) Serial.print(midi_start, BYTE);
     for (int i = 0; i < 24; i++) {
       Serial.print(midi_clock, BYTE);
       delayMicroseconds(calculatedTime);
     }
   }
}