Absolute Encoder Values Changing?

Hi,

So we’re using a Rev Through-Bore encoder on an arm on our robot, connected directly to the associated SPARK. We also have another Rev Encoder attached to a wrist, also connected to its associated SPARK.

When we shut off the robot and move around the arm and wrist, then turn on the robot in a new position, the arm’s encoder readings change, whereas the wrist’s encoder readings stay consistent.

To my knowledge, the wiring and whatnot is consistent between the two.

Is there anything we should look into to make the arm’s encoder readings stay consistent?

Thanks.

the arm’s encoder readings change, whereas the wrist’s encoder readings stay consistent.

When you say “change”, do you mean the value is different, which is expected? Or the value for one arm position is different than a value for that same position after a power cycle?

Yeah I mean the latter. The arm position at one point will be 0.3, for example, and after power cycling, the reading will be 0 at the same point.

I would bet that you’re applying an offset in code that is zeroing the value of the absolute encoder when you start up.

Is there a specific toggle/setting that does that? I don’t remember enabling that, if there is a setting for it.

Is there a way you could share some code for the encoder? It may make it easier to identify if there’s some configuration being set.

1 Like

It’ll look something like this: FRC78_2024/src/main/java/frc/robot/subsystems/Wrist.java at main · frc78/FRC78_2024 · GitHub

package frc.robot.subsystems;

import frc.robot.Constants;
import frc.robot.RobotContainer;

import com.revrobotics.AbsoluteEncoder;
import com.revrobotics.CANSparkMax;
import com.revrobotics.RelativeEncoder;
import com.revrobotics.SparkMaxAlternateEncoder;
import com.revrobotics.CANSparkLowLevel.MotorType;
import com.revrobotics.SparkAbsoluteEncoder.Type;

import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

import com.revrobotics.SparkPIDController;

public class ArmSubsystem extends SubsystemBase{
public static CANSparkMax leftArm;
public static CANSparkMax rightArm;

public static AbsoluteEncoder armEncoder;
public double encoDiff;
public static double armspeed;
public double encoValue;


public ArmSubsystem() {
    leftArm = new CANSparkMax(Constants.DriveConstants.leftArmSpark, MotorType.kBrushless);
    
    rightArm = new CANSparkMax(Constants.DriveConstants.rightArmSpark, MotorType.kBrushless);
    
    armEncoder = rightArm.getAbsoluteEncoder(Type.kDutyCycle);

}

boolean runIta = false;

@Override
public void periodic() {
  SmartDashboard.putNumber("Arm position", armEncoder.getPosition()); //ALSO IFFY
  System.out.println("Arm position " + armEncoder.getPosition());


  encoValue=armEncoder.getPosition();
  encoDiff= 0.75 - armEncoder.getPosition();
  if (encoDiff<0)
  {encoDiff=encoDiff*-1;}
  
  
  if (encoDiff>=0.07 && runIta==true)
  {
    armspeed=Constants.DriveConstants.armVolts;
  }    
  else if(encoDiff<0.07 && runIta==true)
  {
    armspeed=Constants.DriveConstants.armVolts/1.5;
  }
  else if (encoDiff < 0.05 || runIta==false)
  {
    armspeed=0;
  }



  if (runIta){ // TESTING main


  if(encoValue>0.7 && encoValue<0.9){
      if(armspeed>0)
      {armspeed=armspeed*-1;}

    } else if (encoValue>0.73 && encoValue<0.95){
      if(armspeed<0)
      {armspeed=armspeed*-1;}
    } 
     else {
      runIta = !runIta;
      setArm(armspeed);
    }
  
  }

}

@Override
public void simulationPeriodic() {
  // This method will be called once per scheduler run during simulation
}

public void setArm(double v) {

if(v !=0)
{
leftArm.setVoltage(vConstants.DriveConstants.armVolts);
rightArm.setVoltage(-v
Constants.DriveConstants.armVolts);
}
else
{
leftArm.stopMotor();
rightArm.stopMotor();
}
}

public void setWrist(double d) {
    // TODO Auto-generated method stub
    throw new UnsupportedOperationException("Unimplemented method 'setWrist'");
}

}

Ah. I don’t believe we used that method.

You could try resetting the spark max to default settings, in case it has a setting stored in its flash memory that is messing things up

You can reset in code with

leftArm.restoreFactoryDefaults();
rightArm.restoreFactoryDefaults();

Or do it via the rev hardware client

Hmm ok. We’ll try that when we get a chance, thanks!

We spent about a week debugging an issue very similar to this in build season with the REV absolute encoder not maintaining it’s “absoluteness”. Was very frustrating and ended up ditching the encoder completely due to it’s poor performance. .getAbsoluteEncoder would repeatedly give inconsistent values that were not “absolute” and seemed to somehow be related to boot time location of the pivot location. The encoder was also giving us erroneous values on startup, if we read values too quickly it would give a random number.

We tried swapping hardware, same issues. In 2023 we used the sensor in the exact same way and had no issues for multiple parts of our robot.

No clue why it was happening, but that poor experience, along with this moved us off of using that Rev through bore encoder again in the future.

Hmm, that’s interesting. I guess yeah it might just be a manufacturing issue. Sucks that it isn’t just a one-time issue.