Arudino Uno Interrupts with FIT0450

In my Init, I connect the 2 and 3 interrupts each to different method

attachInterrupt(0, wheelSpeedRight, CHANGE);
attachInterrupt(1, wheelSpeedLeft, CHANGE);

The wheelSpeed methods are from

The "rpm" for the right engine logic is thus. The left engine code is identical except for the rpms variable.

  int Lstate = digitalRead(encoder0pinA);
  if((encoder0PinALast == LOW) && Lstate==HIGH)
  {
    int val = digitalRead(encoder0pinB);
    if(val == LOW && DirectionRight)
    {
      DirectionRight = false; //Reverse
    }
    else if(val == HIGH && !DirectionRight)
    {
      DirectionRight = true;  //Forward
    }
  }
  encoder0PinALast = Lstate;

  if(!DirectionRight)  rpmsRight++;
  else  rpmsRight--;

When both wheels are running, I hoped that both left and right rpm values would be calculated so I can compare them and adjust the wheel speeds so the car goes straight. However, when both motors are rotating only the first interrupt is invoked. The second only fires when I hold the right wheel still.

This is my first project and use of interrupts. I thought they would work like events in c# but instead it's like only the first interrupt will run unless the motor stalls and then the second one is called. But as soon as the first one is let free again, the second stops calling.

Is there a better way to synchronize engines?

and second one, should be short as possible

attachInterrupt(0, wheelSpeedRight, RAISING);
void wheelSpeedRight() {
  if (digitalRead(encoder0pinB))  rpmsRight++;
  else  rpmsRight--;
}

The datasheet for the FIT0450 says to pay attention to the direction. Why do you omit it?

void wheelSpeed()
{
int Lstate = digitalRead(encoder0pinA);
if((encoder0PinALast == LOW) && Lstate==HIGH)
{
int val = digitalRead(encoder0pinB);
if(val == LOW && Direction)
{
Direction = false; //Reverse
}
else if(val == HIGH && !Direction)
{
Direction = true; //Forward
}
}
encoder0PinALast = Lstate;
if(!Direction) duration++;
else duration--;
}

And how to you sample both motors to get pulses from each one?

Or more importantly, how to I get both motors to have the same wheel velocity? Right now, these commands use the same speed,

  analogWrite(A_1A, int(speed)); // right
  analogWrite(B_1B, int(speed)); // left

yet, I can see both wheels are not spinning the same. The right one is a bit faster so the car is always going in a circle.

No two motors are identical and what you mention above is usually the case. At a given speed, it is possible to empirically reduce one of the PWM values so that the motors run the same speed, but that won't work well if the motor loads change.

It is much easier just to count pulses when the vehicle is moving in one direction. If the right and left counts for a given period of time differ, adjust one of the PWM values to correct. Something like this:

right_PWM_value = left_PWM_value - scale*(left_count - right_count); //adjust scale to eliminate oscillations.

The Arduino Encoder library can read those encoders, but you need four interrupt-capable inputs to handle the two sets of A and B outputs. Which Arduino do you have?

These wheel encoders are a lot less work for the processor, as they encode the wheel speed rather than the motor shaft speed AND position: See Arduino Adventures: Using the SEN0038 wheel encoders, the Arduino, and interrupts

wheel_encoder

It can get by with two interrupt-capable pins, with one interrupt pin and one plain input per encoder:

https://www.pjrc.com/teensy/td_libs_Encoder.html

Theoretically and at low speeds, yes. But performance suffers if interrupts are not used on both channels, and I suspect it would skip counts at high speeds, considering that the encoder is on the motor shaft.

160rpm *(1920pulse/rev)/(60sec/min)= 5120pulse per sec

The library triggers on change, versus the OP's single edge, so it would indeed be twice the computational load. It would count twice/sec and there's two motors, so full speed would leave about 48us/interrupt, versus the OP's 96us/interrupt. Using a Mega with 4 interrupts for the encoder library would count at twice the rate again, leaving only 24us/interrupt. It still seems feasible, but overkill. I might have to check the limits.

A pair of wheel mounted 16 slot encoders triggering on RISING would need much less computation: 160RPM*16PPR/60SPM=42PPS for each wheel, or 11718us/interrupt.