SPARK MAX Smart Motion Beta - Firmware Release v1.1.26

SPARK MAX Smart Motion Beta - Firmware Release v1.1.26

Due to the number of new features added to the SPARK MAX software for the next release, the initial release will be a beta. We are working on additional documentation for the new modes added. During this time things are subject to change, however this will be kept to a minimum. Details are also reflected on the beta section of our site.

REV Smart Motion Trapezoidal Motion Profiling is now available on board the SPARK MAX. This feature combines the built in velocity PID controller with user defined constraints to provide easy and smooth motion for mechanisms such as elevators and arms, all on-board the SPARK MAX.

Voltage Compensation Add even more repeatability to your auton by using the built in voltage compensation mode. With this mode, you can now set a nominal voltage used to compensate the voltage output by the controller.

Built-in PID controller improvements Set max integral values, filter noisy derivative terms, pre-load the sensor position, and more.

Check out the release notes for a complete list of firmware changes and improvements, and as always, you can track our development on our public Trello board.


SPARK MAX Firmware

roboRIO API Offline Files

LabVIEW Installer

Online API Installer Link

Release Notes


  • Adds new Smart Motion mode utilizing trapezoidal motion profiling
  • Improvements to velocity decoding for low speeds and associated PID control loops requiring control at low speeds
  • Improvements to gate driver fault handling
  • Adds voltage compensation mode
  • Adds ability to set the stored sensor position
  • Adds ability to set the max PID integral accumulator value to prevent integral windup
  • Adds ability to set the PID I accumulator value
  • Adds filter function to PID derivative value
  • Adds closed loop current control
  • Adds closed loop ramp rate separate from open loop
  • Adds ability to follow Phoenix 4.11 motor controllers
    • Note: The ability of this feature depends on the firmware of the Phoenix controllers, and is not controlled by REV. We will do our best to build this functionality, but this is not an officially supported feature.
  • Adds ability to set a unit conversion for both velocity and position units
  • Adds ability to reset to factory defaults
  • Improvements to smart current limits
  • Improvements to current data sent over CAN
  • Improvements to internal settings table implementation
  • Calling the constructor no longer resets the encoder count, this must be done manually by running CANEncoder.setPosition()

Note: Upgrades to this firmware version will clear most parameters flashed into the controller except for CAN ID, Motor Type, Sensor Type, Idle Mode, Input Deadband


  • Improvements to setInverted()
  • New API calls for new firmware features
  • Better error message in Java when CAN is not connected
  • Doc updates are in progress

Special Thanks

We appreciate the assistance from the community for feedback, contributing and testing these new features, specifically a huge thank you to Team 195 CyberKnights


Is there a list of the defaults for the new parameters anywhere?

Great update guys, and thanks for fixing “Follow” mode for Phoenix controllers.

Is there documentation available for “Smart Motion”?
I assume the implementation is similar to “Motion Magic”?

Also, one suggestion for a feature in the software configuration tool (if it doesn’t already exist): Save/Load Configs. Might come in handy when flashing devices, or when swapping out a controller if one burns out (for some reason) or something.

Looks like it’s still in process

One thing that seems different immediately is that Smart Motion closes the loop on velocity. It’s been a while but I’m pretty sure that the Talon SRX’s motion magic feedback loop acts on position.

I’d be curious as to why this is, as most use cases for motion magic / smart motion would be to get from point A to B smoothly.

I have not yet looked at the smart motion implementation but can you change the control mode as you can with the MAX PID loop?

1 Like

So the Smart Motion use case is exactly as you describe, and closes the loop around position. The process to configure the controller uses a tuned velocity PID loop, and a max acceleration/velocity to run the motion profile around position.

We’re still working on documentation, but there are examples available for Java, LabVIEW (in the ‘Examples’ palette), and C++.

The interface is the same as before, to run Smart Motion after its configured, you simply call SetReferece(ControlType.kSmartMotion, setpoint) and to switch back to say, velocity mode, you can then run SetReferece(ControlType.kVelocity, setpoint)

This is definitely on our near-term plan for the GUI, and if you look at the source you’ll see that most of the structure exists for it.

Isn’t “velocity PID” by definition closing the loop on velocity as the setpoint? I’m a bit confused.

I think what will is talking about is both afaik the talon and the spark max use velocity pid internally when you call motion magic or smart motion. The input to both motion magic and smart motion is position, and it will internally figure out a trapezoidal motion profile and feed those velocities to get to your position with the requirements you configured into a velocity pid.

1 Like

My understanding of how the Talon SRX’s Motion Magic works is a bit different. I believe position PID along with a velocity FF is used to maintain the position and velocity of the active trajectory point.

The reason I ask is because position PID and velocity PID are two fundamentally different ways of controlling a system. Both have been proven to work well in FRC applications, but I think it’s important for a team to understand what they’re working with.

I looked back and realized I said this earlier—it probably didn’t convey what I intended. Under the assumption that Smart Motion uses velocity PID, I am curious as to what drove REV’s decision to implement Smart Motion differently from Motion Magic given the exact same use case.

The current docs in CANPIDController.h suggest that the CANPIDController methods are not affected by the position/velocity conversion factors. Is this correct?

The units mentioned in SetSmartMotionMaxAccel seem to not make sense. I presume it’s meant to be in RPM.s⁻²?

Also, correct me if I’m wrong, but it seems that the CANEncoder::SetPosition and CANPIDController::SetIAccum methods do not reflect the inverted state, even though the GetPosition and GetIAccum methods do. This wasn’t intended, right?

If you visit the Spark Max Example Git, there are both C++ and Java annotated examples with sample shuffleboard setups.

This actually isn’t correct. It is - see below

Talon Motion Magic is actually trapezoidal motion profiling overlaid atop a velocity PID.

When you provide the PIDF terms in the ctre world, you’re providing the tuning parameters for the velocity PID under the hood, then cruise velocity and Max acceleration provide the parameters for the trapezoidal motion profiling.

The motion profiling takes a position setpoint and error in - calculates a motion profile that fits your parameters to achieve that, and then feeds that motion profile as inputs into the velocity PID.

1 Like

Where are you getting this information? Unless I am severely mistaken, or the implementation has changed in the last year, this is simply not true. The TalonSRX Motion Magic implementation is as such:

Max velocity and acceleration parameters are used to generate the trapezoidal profile (as you said)
kP, kI, and kD are used to close the loop on position for each profile point
kF is multiplied by the velocity reference at each profile point to approximate the needed output for the given velocity.

To repeat: Motion Magic is closing the loop on position, and using velocity feedforward to assist.


This is my understanding as well and consistent with the motion profiling implementation on the talon. The documentation says that the same PIDF parameters are used for motion magic as motion profiling.

Anyways, don’t want to derail this thread too much. More curious about the spark max and what went into the decision to use velocity PID.

The units are RPM/s. You don’t have an s^2 because RPM is already a measure of velocity.

1 Like

It appears you’re right.

I’ll admit with the somewhat sparse documentation I was conjecturing a fair amount.

We ran an experiment to investigate though, and it does appear that the talon motion magic implementation is either filtering or projecting ahead a few frames a desired position, and filling that into a position based PID, while using the velocity setpoint from its trapezoidal profile to drive the F gain.

We used the following configuration to run a motion magic setup with only P and no F gain:

TalonSRX.config_kP(0, .01); 
TalonSRX.config_kI(0, 0);
TalonSRX.config_kD(0, 0);
TalonSRX.config_kF(0, 0);

TalonSRX.set(ControlMode.MotionMagic, 409600000);

Running on a 775 with a 10:1 gearbox and an integrated versa encoder and observed that the duty cycle isn’t proportional to either the overall position setpoint or the desired velocity setpoint - but seems to be a projection of the desired position based on your profile performance parameters, thus allowing even a purely position based P loop to cap out at the cruise velocity

Based on that it does sound different than the rev implementation based on the API and patch notes.

Ran an analogous test on the SparkMax with the units rectified to match the TalonSRX native units.

It does appear that as described above the SparkMax is using the motion profile to drive a velocity PID - my test used a P value that was insufficient to attain cruise velocity, and you can see it stabilizing below the desired trapezoid.

As is tuning a SparkMax Smart Motion control loop would seem to lend itself more to tuning a velocity PID and then adding Smart Motion.

It still reacts to position error at the low end, but only by driving a velocity error which in turn drives the velocity loop.

CANPIDController pidC = SparkMax.getPIDController();
pidC.setOutputRange(-1, 1);
pidC.setP(0.00012, 0);
pidC.setI(0, 0);
pidC.setD(0, 0);
pidC.setFF(0, 0);
pidC.setSmartMotionMaxVelocity(3000 / 4096.0 * 600 * 10, 0);
pidC.setSmartMotionMaxAccel(2000 / 4096.0 * 600 * 10, 0);

pidC.setReference(100000, ControlType.kSmartMotion, 0, 0);


Thanks for doing these tests! They very nicely demonstrate the difference in behavior between the Talon SRX and the Spark Max, and I think they will be helpful for teams who are considering using Smart Motion.

I’m guessing the pause at the beginning of the Talon SRX test is some combination of deadbanding (output below 4% is zerored) and stiction in the gearbox (seems like the velocity only picks up after 7% output?).

I believe the position PID for Motion Magic is on the active trajectory point’s position setpoint, not the overall goal position. AKA where the robot should be at that point in time according to the motion profile.

If you could rerun the test and also record the trajectory position setpoint (getActiveTrajectoryPosition()) and closed loop error (getClosedLoopError()), that may shed some more light on what the Talon SRX is doing internally.

Where exactly is the position loop closed in this arrangement? Are there cascaded PID controllers, or is the motion profile being re-generated on the fly from the sensed position?

1 Like