let two steppers run at different speeds at the same time with arduino Mega

I want to run 2 stepper motors at 2 different speeds at the same time. I also want to use a timer so I can do other things ‘at the same time’. I think I need to adjust the Timer interrupt in such a way that the speeds are perfectly aligned. The code below is what I have tried so far. The program does what it should do with some interval numbers. But with others, it doesn’t do what it should and stops every time. After stopping it will run again for a while and then stop again at some point. I hope somebody can help with another idea to solve this problem or improve my program.
I use:
Arduino Mega 2560, CNC Shield, drv8825, 0.9° stepper NEMA17

#define ENABLE         8

#define DIR_X          5
#define STEP_X         2
#define DIR_Y          6
#define STEP_Y         3

#define STEP_HIGH_X       PORTE |=  0b00010000; //digitalWrite(2, HIGH);
#define STEP_LOW_X        PORTE &= ~0b00010000; //digitalWrite(2, LOW);
#define STEP_HIGH_Y       PORTE |=  0b00100000; //digitalWrite(3, HIGH);
#define STEP_LOW_Y        PORTE &= ~0b00100000; //digitalWrite(3, LOW);

#define TIMER1_INTERRUPTS_ON    TIMSK1 |=  (1 << OCIE1A);
#define TIMER1_INTERRUPTS_OFF   TIMSK1 &= ~(1 << OCIE1A);

int IntervalX = 300;
int IntervalY = 600;
int IntervalCounterX = 0;
int IntervalCounterY = 0;
int StartInterval;
int NextMotorToTurn;

void setup() {
  NextMotorToTurn = 0;
  StartInterval = 25;
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = StartInterval;                             
  TCCR1B |= (1 << WGM12);
  TCCR1B |= ((1 << CS11) | (1 << CS10));
  interrupts();
  Serial.begin(1000000);
  Serial.setTimeout(50);

  pinMode(DIR_X, OUTPUT);
  pinMode(STEP_X, OUTPUT);
  pinMode(DIR_Y, OUTPUT);
  pinMode(STEP_Y, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  
  digitalWrite(ENABLE, LOW);
}

void StepX() {
  STEP_HIGH_X
  STEP_LOW_X
}
void StepY() {
  STEP_HIGH_Y
  STEP_LOW_Y
}

void SetNextInterval() {
  IntervalCounterY += OCR1A;
  IntervalCounterX += OCR1A;

  switch(NextMotorToTurn) {
    case 0:
      IntervalCounterX = 0;
      break;
    case 1:
      IntervalCounterY = 0;
      break;
    case 2:
      IntervalCounterX = 0;
      IntervalCounterY = 0;
      break;  
  }
  if (IntervalX - IntervalCounterX == IntervalY - IntervalCounterY) {
    OCR1A = IntervalX - IntervalCounterX;
    NextMotorToTurn = 2;
  }
  else if (IntervalX - IntervalCounterX < IntervalY - IntervalCounterY) {
    OCR1A = IntervalX - IntervalCounterX;
    NextMotorToTurn = 0;
  }
  else if (IntervalX - IntervalCounterX > IntervalY - IntervalCounterY) {
    OCR1A = IntervalY - IntervalCounterY;
    NextMotorToTurn = 1;
  }
}

ISR(TIMER1_COMPA_vect) {
  switch(NextMotorToTurn) {
    case 0:
      StepX();
      break;
    case 1:
      StepY();
      break;
    case 2:
      StepX();
      StepY();
      break;  
  }
  SetNextInterval();
}

void loop() {
  TIMER1_INTERRUPTS_ON

}

It's not easy to figure out what a program does when it relies on register settings - it would be a big help if you decribe in English how it is intended to work.

You say you want the motors to run at different speeds at the same time but you have not said how those speeds relate to each other or whether the two motors need to start and stop at the same time even though they move different numbers of steps.

I have been working on a program to move 4 stepper motors for a small CNC mill with a 4th axis. I use a Timer to produce a "tick" at a regular interval and the speeds of each motor are determined by the number of "ticks" between steps - which, in my case, is calculated by a Python program on my PC. This means the Timer just needs to produce "ticks" at a single frequency. (It's a while since I wrote the code so I'm a little hazy).

...R

I want to make a coordinated movement. But to keep it easy, I would like to run the 2 motors at a different speed, not depending on the number of steps (just infinite running). This by an ISR (Timer1 interrupt). I have an interval for the 1st motor and an interval for the 2nd motor. e.g. 200 and the 2nd 300. The first motor should then step every 200 ticks and the 2nd every 300. The program I made should calculate the next interval (OCR1A) and set it so that these 2 motors run correctly. The 200 and the 300 should be completely independent and I would also like to change through the process. This can be any number such as 523 and 268 (random numbers). I hope this makes it a bit clearer.

You've got 4 16-bit timers at your disposal in the 2560. Can you tie the first motor to Timer1 and the 2nd to, say, Timer3? Set up with the same prescalers and the same clock source they will tick at the same rate and be in sync.

Or do you need to stick with a single timer?

tedjones:
I have an interval for the 1st motor and an interval for the 2nd motor. e.g. 200 and the 2nd 300. The first motor should then step every 200 ticks and the 2nd every 300.

Get your ISR to increment a variable by (say) 10 every tick. The use code like this in the ISR

void myISR() {
   counter += 10;

   if (counter >= motor1Count ) {
     // step motor1
     motor1Count += 200;
   }
   if (counter >= motor2Count ) {
     // step motor2
     motor2Count += 300;
   } 
}

That way a single timer frequency can drive both motors at different speeds.

...R

Thank you for your answers. The idea of Blackfin is what I found out myself and what I use now. But this idea wouldn’t work if I used 2 more motors. But the idea of Robin2 is pretty smart of its own. This would not be a problem but the problem is that my intervals are not always a multiple of 10. This would give a wrong execution.

tedjones:
This would not be a problem but the problem is that my intervals are not always a multiple of 10. This would give a wrong execution.

Choose the increment number so that the fastest motor steps correctly. There may be small timing irregularities for the slower motors but it may not be possible to avoid that. In theory you could increment by 1 but that may be impractical if it would require too frequent interrupts.

You have to make sure that the interrupts do not repeat faster than the time taken by the code in the interrupt when it has the maximum amount of work to do.

...R