Zeroing encoder during PID closed loop position control

We are using NEO brushless motors with SPARK MAX motor controllers. We have a rotating mechanism and are planning to use closed loop position control (via CANPIDController) to rotate it to specific positions.

However, our mechanism rotates freely and we may want it to spin arbitrarily far in either direction. To simplify calculations and limit the encoder values to a reasonable range we’d like to zero the encoder when the mechanism reaches a full revolution. That way the positions we specify can be within the range of a single revolution (or two, since we’ll need to specify a reference position >1 revolution if we want to spin past that point).

Is it safe for us to reset the encoder position using CANEncoder.setPosition() while also controlling position with PID, if we update our reference value at the same time? Otherwise, are we likely to run into limitations of encoder max/min values or accuracy if we spin the motor constantly in one direction?

I would zero to the offset from full rotation when you stop turning. It’s probably safe if your mech won’t move if you turn off the Pid, to briefly turn it off, rezero and update setpoint. Don’t rezero during the pid control, you will probably get unpredictable results.

Though you don’t have to solve the problem this way, I usually conceptualize it like this:

There are actually two numbers you care about:

  1. The position you want to end up at
  2. The rotation you’ll use to get there.

1 can be bound to the range 0-360 for convenience sake. However, I’ve found its usually easier to keep 2 more continuous - don’t wrap the range.

This is because the mechanism is continuous.

Let a transition from the 350 degree position to the 10 degree position be represented by a rotation to 370 degrees. That is different than a rotation to 10 degrees - on goes left, the other goes right. One takes much longer than the other. The two end at the same spot, but are not equivalent. Good code shouldn’t force the mechanism to take the long route.

I’d recommend creating a class to wrapper the spark max controller. Have your class accept the 0-360 command input as you want, and return the 0-360 position as you’d like to see it. On the inside of the class, translate that to and from the Spark Max’s continuous reference frame. In effect, you’ll be creating a very simple, 1-D pathplanner.

Rezeroing during PID control can be done. D and I terms will likely need to be reset or ignored for that loop. It requires something more than the standard , vanilla PID controller. Though the REV guys are awesome, I wouldn’t bank on the fact they’ve accounted for all your team’s assumptions.

2 Likes

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.