RLD 3: REV - TEAM1771/Crash-Course GitHub Wiki

NOTE: We do not use REV devices nearly as much as we used to, I recommend skipping this section unless you know you'll be working with REV motor controllers

The REV Library

REV is a popular vendor that makes lots of parts for FRC. In addition to mechanical parts, they manufacture electronics, including motors and motor controllers. The REV library allows us to communicate with, configure, and control these motor controllers (called SparkMaxs) through robot code.

Including REVLib

To include REVLib in a file, use #include <rev/, followed by the header file that contains the part of the library that you wish to use.

SparkMax

REV's SparkMax is a motor controller, which basically means it controls how much power to provide to the motor. In addition, it takes encoder (sensor) values from the motor and sends them to the RoboRio. This allows us to see the speed, position, temperature, etc. of the motor.

Including the CANSparkMax library

To use SparkMaxs in your code, make sure to use #include <rev/CANSparkMax.h>

Everything to do with REV is in the "rev::" namespace.

Making a SparkMax instance

To make a SparkMax variable (instance of the rev::CANSparkMax class), use the constructor.

The constructor takes in an int for the CAN ID of the SparkMax (this is the "address" of the motor controller on the robot's network), and then a MotorType to know if the motor is brushed or brushless (two different motor technology; most motors are brushless nowadays).

The easiest way to figure out something like this by yourself is to simply hover over things in VSCode (or press "ctrl" + "t") because it will give suggestions from the REVLib documentation.

rev::CANSparkMaxLowLevel::MotorType may look scary, but it is actually very easy to figure out. You can simply paste that from the constructors function definition (this appears when you start typing rev::CANSparkMax spark_max = rev::CANSparkMax() and hover your cursor inside the parentheses), and after that you can press "ctrl" + "t" to see what options are given (in this case, kBrushed and kBrushless). This happens a lot when using vendor libraries like REV and CTRE.

Here's a GIF for demonstration

This kind of information can also be found on the REVLib API docs

rev::CANSparkMax upper = rev::CANSparkMax(6, rev::CANSparkMaxLowLevel::MotorType::kBrushed);
rev::CANSparkMax upper{8, rev::CANSparkMaxLowLevel::MotorType::kBrushless};

Customizing settings

Customizing settings (such as PID tuning, current and output limits, and position limits (to avoid exceeding range of motion)) can be done either through the REV Hardware Client or through code.

The Hardware Client is recommended for quick on-the-fly customizations while tuning, but it is then recommended you hard-code the settings through code so that the settings persist even if motor controller needs to be swapped. You never know when a controller might die and lose its settings.

In code, settings relating to the motor itself can be set using functions on the CANSparkMax object

static rev::CANSparkMax pivot{
    PIVOT::CAN_ID,
    rev::CANSparkMaxLowLevel::MotorType::kBrushless};

void Intake::init()
{
    pivot.SetSmartCurrentLimit(40); // restricts the amount of current (in amps) that the motor can use
    pivot.SetClosedLoopRampRate(0.2); // limits how fast the motor can apply power (eliminates very hard jerks)
}

PID tuning settings need to be applied to the PIDController object

static auto pivot_pid = pivot.GetPIDController();

void Intake::init()
{
    pivot_pid.SetP(0.02);
    pivot_pid.SetOutputRange(-0.5, 0.5); // restricts the amount of power the motor can apply (slows it down)
}

Encoder settings need to be applied to the SparkMaxRelativeEncoder object

static auto pivot_encoder = pivot.GetEncoder();

void Intake::init()
{
    // PIVOT DEG PER MOTOR ROTATION is a factor determined through math that accounts for various
    // gearing ratios between the motor and the actual system (intake pivot) it controls

    // By calculating this value, we can just tell the motor to go to 0deg or 90deg without needing to worry about gear ratios.
    pivot_encoder.SetPositionConversionFactor(PIVOT::PIVOT_DEG_PER_MOTOR_ROTATION.value());
}

To save the settings between reboots, "burn" them to the "flash" (memory) on the controller

pivot.burnFlash();

These are just a few examples of settings you can apply. Check the REV docs for more.

Running a SparkMax's motor

The simplest way to actually run a motor hooked up to a SparkMax is using the .Set() function. This is a WPILib function that is implemented across all motor controllers.

The idea is very simple: the function takes in an int value between -1 and 1, with -1 being -100% speed and 1 being 100% speed.

Advanced Functionality

More advanced control of a SparkMax's motor (targeting a position or velocity) can be done using the PIDController variable in code.

rev::CANSparkMax spark_max{1, rev::CANSparkMaxLowLevel::MotorType::kBrushless};
rev::SparkMaxPIDController pid = spark_max.GetPIDController();

Once you have obtained the PIDController object, you can use the .SetReference(double value, rev::ControlType ctrl) function to set your target.

ControlType can be Position, Velocity, or even Voltage, Current or Duty Cycle. SmartMotion and SmartVelocity are designed for smoother control with acceleration limits, however they have issues and can be unreliable.

Documentation

Just like WPILib, REV has 2 libraries.

  • The main documentation is a very detailed resource explaining SparkMaxs and utilizing them with REV Client (a GUI app for tuning/testing REV stuff), but doesn't really go into using SparkMaxs in code.

  • REV also has API documentation that you can access in WPILib by hovering over things from REV's library, such as function arguments. This is great to see what each function does, how to use the constructors, etc.