Lamprey Absolute Encoder with Spark Max

Hello. We are trying to use Lamprey Absolute Encoders with Spark Max motor controllers and NEO motors. We’re having issues with getting values from getPosition. The value sometimes gets smaller and it changes inconsistently. With getVelocity, it switches between positive and negative.

I’ve looked at past threads for the Lamprey encoder. They talk about removing wires when used with the Talon SRX. There isn’t much info for the Spark Max and all I could find was nonspecific and mentioned having issues and using breakout boards. We currently have the encoder directly connected to the data port on the Spark Max with the provided cable. We’ve also set the Spark Max to use the alternate encoder at 1024 counts per revolution. What should we do to make the Lamprey encoder work correctly with the Spark Max?

We have been using the Lamprey connected to the Spark Max in similar manner with the Tx/Rx lines cut, except in analog mode. It seems like it works, except for a Spark Max feature that averages samples that it reports, which sometimes produces a value 180° away from 0°/360° on the sensor boundary.

1 Like

Take a look at my posts on this thread: Hollow Bore Absolute Encoder by 221 Robotic Systems - #70 by SndMndBdy

They likely explain the issues you are seeing.

The Encoder sends position data to the SparkMax via an analog voltage from 0-3.3V, proportional to the angle of the magnet. The SparkMax averages the last few values it sees from the encoder, which generally works fine, but when you make a full rotation, the voltage flips from 3.3V to 0V, and the SparkMax briefly averages this to be 1.65V (which is totally wrong… it’s the complete opposite direction).

I don’t believe that Rev has updated the software to give you an option to not average the readings.

As an alternative, you can read the analog voltage from the encoder on the RoboRio.

1 Like

Thanks for the reply.

From the thread you linked:

From what I can tell, the only way to connect a Lamprey Encoder to a SparkMax is to run the 10-pin ribbon cable from the encoder to the SparkMax, remove the necessary lines as described above, and then wire the analog output of the encoder to the analog input on the alternate encoder input on the SparkMax (using the breakout board or directly).

By removing the necessary lines, are you just referring to the Tx and Rx lines? And when you say to wire the analog output on the encoder to the analog input on the Spark Max, I checked the pin outs of the Lamprey and Spark Max and both have analog output/input on pin 3, so why would we need a breakout board?

You don’t need a breakout. You should be able to just cut lines 5 and 7 and connect the Lamprey straight to the Spark Max.

1 Like

I have cut the Tx and Rx lines (5 and 7). However, I am still having issues. The getPosition value starts around 1 and very slowly rises in value, inconsistently. When you turn the part with the magnet in one direction getPosition slowly decreases in value, and if you turn it the other direction, getposition increases in value more quickly. When you stop turning the part with the magnet, getPosition continues to rise. The value of getVelocity randomly fluctuates between -1 and 3 while the part is at rest. We tested two encoders and both had these issues.

SPARK MAX Data Port (Alternate Encoder Mode):

There are folks here how have used (and developed) these parts, so my 2¢ isn’t worth much.

It looks as though you want pins 2, 10, and 3 connected straight through, leaving 7 pins which need to be considered. Also, the averaging behavior described above could certainly cause issues. Anyhow, pins 5, 7, and 9 are used on the SPARK MAX for the encoder built-into the NEO, which means pin 7 (Tx out from Lamprey) needs to be cut for sure. Pin 5 is an input, so cutting it is probably optional. Pin 9 might be an input as well? Pin 1 looks questionable to me – it’s 3.3V out from SPARK MAX and “reset” on the Lamprey – if it’s an active low reset, it’s probably OK (this seems to be the case, based on the experience others have reported).

This leaves pins 4, 6, and 8. These are all inputs on the SPARK MAX. I think these are probably OK, but the Lamprey will drive some of these. I think an important thing is you need to set the SPARK MAX up to use the analog input, and NOT to use the alternate A/B/I inputs. If you haven’t done so, try this. The theory here is that the signals on some of these lines are causing the digital encoder inputs to see strange things.

If I were doing this, I think I’d just run pins 2, 3, and 10 – either by cutting the cable and only splicing these lines or by doing back-to-back breakouts. But, first try the analog encoder thing.

I agree with nuttle. To keep things simple, start by reading the analog voltage input on the SparkMax, rather than the getPosition or getVelocity methods. I have a feeling those are based off of the quadrature encoder inputs, which the Lamprey doesn’t provide. On the analog input, you should see it rise from 0V to 3.3V as you rotate the magnet. (That is, if the light on your encoder is blue. If it is orange, then it’s outputting 0-5V. You can triple click the button to switch between the options)

Also, did you do the basic calibration procedure for the Lamprey, and see the status light on it at least turn red while calibrating?

We are doing the same thing as well right now. We have a home grown swerve module and started with a SparkMax connected to a NEO brushless with a Lamprey encoder.
We have the connected the Lamprey to the SparkMax via the Analog input on the data port.

But we are coming to the conclusion that unless REV changes the SparkMax firmware to allow reading the raw value from the analog input this cannot be the combination we use.

The averaging the SparkMax does on the analog input makes it useless, in the long run, for using as the controller for rotating the wheel. The point of the Lamprey is to get the initial angle of the wheel at startup (and possible for recalibration while running) but because of the averaging the value cannot be trusted.

Sure there are work arounds and other stuff you could do to deal with it but I’d rather not introduce unnecessary complexity to the code just to compensate for a shortcoming in the motor controller.

So we are using it right now for initial testing of the mechanical setup and the code but unless REV can tell us they are going to add a feature to the SparkMax we are going to move away from them and the NEO for production.

I’ve emailed their tech support asking about adding the feature but they haven’t responded.

1 Like

If you just need an initial position, the averaging may not be a deal-breaker. At start-of-match, the robot is just sitting there, the encoder will send whatever voltage, and this voltage should be fixed (or only varying by a small amount). There could be a corner case where the wheel is right on the border between min and max, but hysteresis should cover even this case. So, things should be steady enough to record the initial position. Not ideal, but likely workable…

1 Like

Unless that initial point is close to zero, which also happens to be close to 3.3, which in the world of the Spark Max also happens to be 1.65 through averaging. It might not happen every time, but happening once is enough to make it bad. We want to also use it to reset our heading if we encounter enough drift to warrant it, but the same issue pops up in that use case too.

I’d probably hook the encoder up to the roboRIO, using the digital PWM absolute position and DutyCycleEncoder. One could also do this with the analog absolute position and an analog input.

Either way, this gets you absolute position without the averaging. The controller will use the built-in encoder on the NEO for commutation, and can use it for position control. This leaves it to software (on the roboRIO) to do any integration of the two sensors, and you have to decide if you want to try to incorporate the SPARK MAX position control, or just have the roboRIO manage things totally.

Yes, we looked at that option. It makes for some unfortunate wire runs and makes swapping a module more of a challenge. In the end we will either do that, or swap to a brushed motor and a talon, or bail on the lamprey and go with another option for zeroing.

One nice thing about only needing three wires, to a single digital (or analog, depending) input on the roboRIO, is that PWM cables work here. You just need to make a splice near the encoder, then you are on easy-to-make/easy-to-run PWM-style cable. You probably will want a lot of heat shrink on the splice. Or, get one of the little 10-pin breakout boards and use that to transition to PWM-style cable. It’s also pretty easy to make a three-wire quick disconnect, there are even inline PWM quick disconnects.

Also, the “kAnalogAverageDepth” “Number of samples in moving average of velocity.” configuration parameter might be worth fiddling.