Help with noisy velocity measurement

It sounds like something weird is going on, so I’d start at the bottom and work your way up. STM32HWEncoder inherits from the base Sensor class and does not override getVelocity, so it should be using the base class version. Try printing some stuff there, like this:

float Sensor::getVelocity() {
    // calculate sample time
    float Ts = (angle_prev_ts - vel_angle_prev_ts)*1e-6f;
    if (Ts < 0.0f) {    // handle micros() overflow - we need to reset vel_angle_prev_ts
        vel_angle_prev = angle_prev;
        vel_full_rotations = full_rotations;
        vel_angle_prev_ts = angle_prev_ts;
        return velocity;
    }
    if (Ts < min_elapsed_time) return velocity; // don't update velocity if deltaT is too small

    velocity = ( (float)(full_rotations - vel_full_rotations)*_2PI + (angle_prev - vel_angle_prev) ) / Ts;

static unsigned long lastPrintTime = millis();
if(abs(velocity) > 1 && millis() - lastPrintTime > 1000) {
  lastPrintTime = millis();
  Serial.print("full_rotations "); Serial.println(full_rotations);
  Serial.print("vel_full_rotations "); Serial.println(vel_full_rotations);
  Serial.print("angle_prev "); Serial.println(angle_prev);
  Serial.print("vel_angle_prev "); Serial.print(vel_angle_prev);
  Serial.print("Ts "); Serial.println(Ts);
  Serial.println();
}

    vel_angle_prev = angle_prev;
    vel_full_rotations = full_rotations;
    vel_angle_prev_ts = angle_prev_ts;
    return velocity;
}

That might give you a clue as to the nature of the values that result in bad velocity calculations.