Spark Max Encoder setPositionConversionFactor Not Doing Anything

I am trying to set the spark max encoder conversion factor in my code with sparkMax.getEncoder().setPositionConversionFactor(conversionFactor);
but it doesn’t seem to be working. The encoder output is not converted and the spark max telemetry tab shows the encoder position conversion factor field set to 1. Any ideas or suggestions?
This is where the conversion is supposed to happen

3512 noticed conversion factors were broken in that manner as well in early 2020. We ended up applying the conversion factor to the result of the encoder getter manually. The whole issue became moot when we stopped using on-motor-controller PID.

The conversion factor is sent as a “parameter” over CAN rather than stored on the robot code side. Assuming the conversion factor is actually making it to the SparkMax firmware, it seems likely the SparkMax firmware isn’t applying it.

1 Like

@Nick_Coussens, can you pass this along to the electron wizards(developers)?

Try this, if you haven’t already. The performance will likely be comparable or better, and the code overhead is waaaay less.

Better PID even if I’m using the neo’s built in encoders through the spark max?

Using the built-in encoder has mixed results. I’d recommend plugging in a separate encoder to the Spark Max’s data port instead, then reducing the “moving average depth”.

2 Likes

Probably comparable in that case; you’ll do better to use an external encoder per @calcmogul’s post above.

@Will_Toth found that removing the call to burnflash() or delaying it by 1 second with thread.sleep(1000) fixed the issue. I removed burnflash() which fixed the steer encoder conversion factor but left the drive encoder conversion factor still broken.

For reference, the file at the time of initial post is here https://github.com/FRC5892/2021-Nightlight-Summer-of-Swerve/commit/136b59720f563316b326fcc10c68d6c72d7973bb#diff-1432cb0f5b8ee7c0c2911293c77c0fb676a0fd7cffe2f7a41e30348d29c05d29

@NoahAndrews @Will_Toth any idea why the drive motor encoder conversion factor won’t stick?

We have a theory, that we’re actively working on proving. If it is correct, we’ll fix it before next season.

Do you have any for right now solutions other than doing the conversion in a getter function?

I’d recommend using Thread.sleep() before calling burnFlash(). You can probably shorten the amount quite a lot too. I would think 200ms is typically still way more than you need, though that’s going to depend on the amount of traffic on the CAN bus.

I completely removed burnflash. Steer motor encoder conversion works but drive motor encoder conversion still does not. Any quick fixes?

Here is the relevant version of the code as of this post https://github.com/FRC5892/2021-Nightlight-Summer-of-Swerve/blob/ea26171a1de73aabe1d95b5540dd8036d482259c/src/main/java/frc/robot/subsystems/SwerveModule.java

Interesting, I missed the part where you said that.

What happens if you use the REV Hardware Client to burn the desired setting to flash?

The conversion factor sticks and works

I was trying to add Thread.sleep(500); in between the defining of the two motors to see if that helped anything (the first motor defined is the one that is still having issues) but caught an interruptedexception error at compile

public CANSparkMax configuredCANSparkMax(int ID) {
		CANSparkMax sparkMax = new SparkMaxWrapper(ID, MotorType.kBrushless);
		sparkMax.restoreFactoryDefaults();
		sparkMax.setInverted(false);
		sparkMax.setIdleMode(IdleMode.kBrake);
		sparkMax.setSmartCurrentLimit(60);
        **thread.sleep(500);**
		return sparkMax;
	}

public SwerveModule(int driveMotorID, int turnMotorID, int lampreyID) {
		driveMotor = configuredCANSparkMax(driveMotorID);
		driveEncoder = driveMotor.getEncoder();
		driveEncoder.setPositionConversionFactor(Constants.kSwerveDriveTrain.kDrive.kEncoderConversionFactor);
		driveEncoder.setVelocityConversionFactor(Constants.kSwerveDriveTrain.kDrive.kEncoderConversionFactor / 60);

		drivePIDController = driveMotor.getPIDController();
		drivePIDController.setP(Constants.kSwerveDriveTrain.kDrive.kP);
		drivePIDController.setI(Constants.kSwerveDriveTrain.kDrive.kI);
		drivePIDController.setD(Constants.kSwerveDriveTrain.kDrive.kD);
		steerLampreyEncoder = new DutyCycleEncoder(lampreyID);
		steerMotor = configuredCANSparkMax(turnMotorID);
		steerEncoder = steerMotor.getEncoder();
		steerEncoder.setPositionConversionFactor(Constants.kSwerveDriveTrain.kSteer.kEncoderConversionFactor);
		// steerEncoder.setVelocityConversionFactor(Constants.kSwerveDriveTrain.kSteer.kEncoderConversionFactor / 60);

		// commented out until lampreys are hooked up
		// steerMotor.getEncoder()
		// .setPosition(steerLampreyEncoder.get());
		steerPIDController = steerMotor.getPIDController();
		steerPIDController.setP(Constants.kSwerveDriveTrain.kDrive.kP);
		steerPIDController.setI(Constants.kSwerveDriveTrain.kDrive.kI);
		steerPIDController.setD(Constants.kSwerveDriveTrain.kDrive.kD);
	}

Maybe a bit late, but I had problems if I set the conversion factors after burning flash. Unless I reviewed it incorrectly, it appears you do the same thing. It did work correctly when I moved the burn flash statements after the conversion factor setters.

Here is my code after fixing that issue for reference:

1 Like

Never too late! I’ll give that a try!