Talon CTRE encoder values

Hi

I want to absolutely nail down understanding our understanding of the numbers that come from the various ways of reading the encoder values for a CTRE encoder attached to a talon, so I am going to ask some possibly dumb questions.

  1. the encoder remembers its position across power cycling?

  2. talon.getSensorCollection().setPulseWidthPosition(0, 10) really sets the encoder to

    • 0, OR to
    • a number in the range 0 to 4096?
  3. how long does it take to actually set the encoder to 0? We seem to get different results depending how quickly we read.

  4. getPulseWidthPosition() returns the absolute number of ticks positive or negative from the zero point: +4096 for 1 rev forward, -4096 backwards

  5. getQuadraturePosition() returns the same number IF you have gone through the process of setting relative sensor to match absolute, as described here:
    https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/master/Java/PositionClosedLoop/src/org/usfirst/frc/team217/robot/Robot.java

  6. getSelectedSensorPosition() returns the value of the sensor that has been configured using talon.configSelectedFeedbackSensor()

however

  1. the SIGN of getSelectedSensorPosition() seems to be +ve if motor moving forward and -ve if moving back. Is this correct?

Apologies if these are dumb, but I really want to get this nailed down.

1 Like
  1. for relative encoding no, it’ll start out as zero when you power on. for absolute encoding I think so?

3.1 don’t know much about canbus, but I suspect like any network it is nondeterministic and depends on how much traffic there is

  1. … and your output shaft hasn’t rotated more than one revolution since you set the sensor. if it has it’ll go above or below ± 4096

  2. it needs to be, but it is not guaranteed depending on your configuration. if that is not the case you need to call setSensorPhase

I answered the ones that I am confident/mostly confident in the answer:

1. the encoder remembers its position across power cycling?
Yes and No? Relative encoders do not. Absolute encoders, because of the way they work, hold their position within one rotation (they work kind of like potentiometers)

3. how long does it take to actually set the encoder to 0? We seem to get different results depending on how quickly we read.
That should be effectively instantaneous. What you might be seeing is small changes in your encoder because those things are very sensitive.

3. getPulseWidthPosition() returns the absolute number of ticks positive or negative from the zero point: +4096 for 1 rev forward, -4096 backwards
Correct - ish. If you are using a quad encoder (vs an absolute) it sounds like it will be 4*4096:
“The Talon directly supports Quadrature Encoders. If Quadrature is selected, the decoding is done in 4x mode. This means that each pulse will correspond to four counts.” (Software Reference Manual, pg 46). When in doubt, test while printing the values to the screen.

5. getSelectedSensorPosition() returns the value of the sensor that has been configured using talon.configSelectedFeedbackSensor()

Sounds about right.

6. the SIGN of getSelectedSensorPosition() seems to be +ve if motor moving forward and -ve if moving back. Is this correct?
This is a tricky one to answer because it depends on how your sensor is plugged in and how its attached to your system. I always verify this experimentally by turning the system in the direction that I call “forward” and seeing if the ticks rise or fall.

Apologies if these are dumb, but I really want to get this nailed down.

None of these are dumb questions. Most questions (in general) are not dumb questions. Please always ask questions!

  1. -These API calls are not ones I frequently see. Can you describe what you’re using them to accomplish?

Minor note on phrasing here, I supect you already know this but just for clarity:

The position read in will increase when you move in one direction, and decrease when you move in the other direction. You choose which is which by selecting the sensor phase to match your physical system. To make PID algorithms on-board the Talon work properly, you must configure sensor phase such that positive control effort results in increasing sensor reading.

Thanks to both of you for the replies.

I should have noted that we are using the CTRE SRX Mag Encoder, which provides both quad and PW readings. I should also have noted that we are using Java, and the WPI_TalonSRX class.

  1. the SIGN of getSelectedSensorPosition() seems to be +ve if motor moving forward and -ve if moving back. Is this correct?
    This is a tricky one to answer because it depends on how your sensor is plugged in and how its attached to your system. I always verify this experimentally by turning the system in the direction that I call “forward” and seeing if the ticks rise or fall.

The reason for asking this is that the quad and PW readings go -ve if we go below the “zero” point (i.e. go backwards for a while) but the sign of the getSelectedSensorPosition() method seems to depend on motor direction, rather than position relative to “zero”.

Is that your understanding?

I’ll add to this with our experiences, plus a related question maybe someone can shed some light on.

We have an arm that rotates maybe a little over 90 degrees max. We have an SRX Mag encoder feeding directly into a Talon SRX for feedback. We have a switch that the arm hits when it is down to zero the selected (for us, relative) encoder position to zero, and we do this every time the switch is hit.

We were seeing inconsistent (random) values from the relative encoder on startup, which is really as expected. After some reading and searching through examples, we changed it to also zero the pulse width (absolute) encoder value every time, and on startup, seed the relative encoder value with the absolute encoder value. (Zeroing every time just meant we didn’t have to run any one-off code to set things up.)

This worked well and as expected on our practice robot, with no issues with random startup values for either. But at CIR last weekend on our competition robot, it seemed to not work - on each startup, the arm position encoder had random values, instead of the last value it had before turning the robot off. The values are always less than 1x CPR (4096). (We ended up adding a step to our auto to zero the arm position at the start.)

The main thing here is that: Setting the absolute encoder position (PW) seems to work as expected and hold that value over power cycles. However, why would this work on one robot and not the other?

In fact, we had swapped the talon used for this with the exact same one from the practice robot (we had put a pretty old one on the comp bot before bag), so at competition it was actually the exact same hardware we used when it worked, except for the actual encoder. So I don’t see this being a talon firmware version issue or similar.

Has anyone seen this before? I had assumed from reading and observing the practice robot that the absolute encoder position is held across power cycles. Is this not the case? Did we just get freakishly lucky with the encoder magnet placement on the practice robot?

We’ve had the exact issues Steve is describing on our lift as well. Any movement in a mechanism with the power off drifts the SRX absolute encoders values.

Interesting feedback.

We are considering adding a “findzero()” method to the elevator and arm in the robot init. Basic idea is to move up 100 ticks, then move down until hit limit.

Welcome any comments from any team that has done something similar, and how well it worked out - or if there is a better technique.

The time it takes for the zeroing to happen is not instantaneous, and not negligible either. There will be some delay, stemming from the time it takes to send out the CAN message (will be dependent on CAN bus load and the Talon CAN ID) and then Talon to then send a message back with a 0 encoder reading (the default Talon config sends the status frames at 20ms frequency). This was enough of an issue for us that we decided to handle the zeroing logic onboard instead.

Another option is issuing the zero command but not starting your movement until you get a zero position response (should only take a few ticks through).

The CTRE libraries actually already handle this if you set a large enough timeout in the zeroing call, but we decided it was easy enough to implement our own zeroing method.

While it really isn’t a lot of extra time (~20ms), one of our zeroing methods involves running against a hard stop at low voltage and sensing the stall condition with current draw, so minimizing the time spent stalling here was seen as a plus.

Our 2 TalonSRX drives and Mag encoders zero when the reverse Limit switches that are wired direct to the TalonSRX are made. If we feel the lift is off we command the lift down using controlMode.PercentVbuss at a safe speed. Two things happen when the switches are made. 1 The motors stop. 2 The encoders zero. Also when the motors are being commanded using controlMode.MotionMagic if by chance the switches are made again the system is re-zeroed.

Java: https://github.com/CrossTheRoadElec/Phoenix-Documentation#use-limit-switch-to-zero-position

A parameter value of "1" will enable the feature while a parameter of "0" will disable the feature. SubValue and Ordinal are not used for this config.

Java -

//Configure Talon to clear sensor position on Forward Limit
_talon.configSetParameter(ParamEnum.eClearPositionOnLimitF, 1, 0, 0, 10);

or

//Configure Talon to clear sensor position on Reverse  Limit
_talon.configSetParameter(ParamEnum.eClearPositionOnLimitR, 1, 0, 0, 10);

Another thing to note here in the difference between these methods. The value returned by these methods are all derived from different CAN messages sent by the Talon at different frequencies. getPulseWidthPosition() is from Pulse Width Status 8 (160ms). getQuadraturePosition() is from Quadrature Encoder Status 3 (160ms). getSelectedSensorPosition() is from Feedback0 Status 2 (20ms).

SetStatusFramePeriod() can be used to adjust these frequencies, but be wary of bus load when increasing these.

Thanks - very interesting. Three questions if you have time:

  1. when you say “zero” does that zero: the quadrature position, the pulsewidth position, or both?

  2. The Talon manual (section4.1) says this:

When a limit switch input is closed (is connected to ground) the Talon SRX will disable motor drive

We interpreted this to mean that the motor is disabled and manual intervention would be required. Is this correct?

  1. Is there any documentation on the ParamEnum values and how to use them, other than the enum listing here https://www.ctr-electronics.com/downloads/api/java/html/index.html?com/ctre/phoenix/ParamEnum.html?

Thank you - more useful info…

Do you know if there is any documentation on the StatusFrame enum?

There’s info in section 20 of the Talon SRX Software Reference Manual.

Enums for the different frames are here

The motor is disabled in that direction.

Documentation is not available for this feature, just note the ParamEnum.eClearPositionOnLimitF, #, 0, 0, 10) Only change the # 1=enabled 0=disabled. I assume the 10 is the time out.

Not 100% sure. Our get position returns 0 after the switches are closed.

getSelectedSensorPosition(0)

Our sensor is set up:

configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.kPIDLoopIdx, Constants.kTimeoutMs);

Thanks again. If the motor is disabled, how does it get re-enabled?

Thanks Rahilm - sorry I missed that