Skip to content

Controlling Motors

Controlling your motors is an essential part of FRC Robotics. It's not just about setting a power and leaving it; you'll often need to dynamically control motors based on sensors, user input, or pre-defined conditions. In this lesson, we will explore some of the advanced controls available in WPILib.

Understanding Motor Controllers

In FRC Robotics, motor controllers are the interfaces that allow us to electronically control the motors. Various types of motor controllers are used in FRC, each with their own unique properties and methods of control. Some common examples include the SparkMax, Talon, and Victor motor controllers.

WPILib has classes to represent these motor controllers, such as SparkMax, Talon, Victor, etc. To use a motor controller in your code, you instantiate the corresponding class and use its methods to control the motor.

Example

Here is a basic example of how to use a SparkMax motor controller to control a motor:

import edu.wpi.first.wpilibj.TimedRobot;
import com.revrobotics.CANSparkMax;

public class Robot extends TimedRobot {
    private CANSparkMax motor;

    @Override
    public void robotInit() {
        motor = new CANSparkMax(1, MotorType.kBrushless); // SparkMax is flashed to CAN id 1
    }

    @Override
    public void teleopPeriodic() {
        motor.set(0.5); // Set the motor to half power
    }
}

In the robotInit method, we initialize a new SparkMax motor controller on CAN id 1. Then, in teleopPeriodic, we set the power of the motor to 0.5, which is half power.

Control a Motor with a Joystick

In many robots, you'll want to use a joystick to control the motor. In the teleopPeriodic() method, the joystick's Y-axis value is continually read and directly set as the output for the motor controller. As controller.getY(Hand.kLeft) returns a value between -1 and 1 (representing the full range of the joystick), the motor speed varies from full reverse (-1), to stop (0), to full forward (+1) corresponding to the movement of the joystick.

Here's how to do this:

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.XboxController;
import com.revrobotics.CANSparkMax;

public class Robot extends TimedRobot {
    private CANSparkMax motor;
    private XboxController controller;

    @Override
    public void robotInit() {
        motor = new CANSparkMax(1, MotorType.kBrushless);
        controller = new XboxController(0); // Controller in USB port 0
    }

    @Override
    public void teleopPeriodic() {
        motor.set(controller.getY(Hand.kLeft)); // Control motor power with left joystick Y-axis
    }
}

This results in a straightforward one-to-one control system where the position of the joystick directly influences the speed and direction of the motor.

Inverting Motor Direction

In many robotic systems, especially those with multiple motor assemblies like a drivetrain, there might be a requirement for one motor to mirror or "follow" the actions of another. This is typically done to ensure synchronized operation of multiple motors for executing coordinated tasks.

motor.setInverted(true); // Inverts the direction of the motor

Create a Follower Motor

In many robotic systems, especially those with multiple motor assemblies like a drivetrain, there might be a requirement for one motor to mirror or "follow" the actions of another. This is typically done to ensure synchronized operation of multiple motors for executing coordinated tasks.

In the example given below, a second motor, followerMotor, is declared and set to follow the motor. The follower motor is also a SPARK MAX motor controller, connected through the CAN bus on port 2.

Once followerMotor.follow(motor) is called, the followerMotor will now mirror the actions of motor. So, if motor's speed is set to 0.5, the followerMotor will also run at a speed of 0.5. If motor's direction changes, the followerMotor will change its direction as well. The follower motor's operation is now entirely dependent on the leading motor unless otherwise specified.

CANSparkMax followerMotor = new CANSparkMax(2, MotorType.kBrushless);
followerMotor.follow(motor); // followerMotor will now mirror the actions of motor

Stop Motor with Limit Switch

A limit switch halts a motor when it reaches a specified limit. This can be crucial in preventing mechanical damage or undesired behavior. Upon the switch's trigger, the software stops the motor, ensuring controlled movement.

DigitalInput limitSwitch = new DigitalInput(0); // Limit switch plugged into DIO port 0

@Override
public void teleopPeriodic() {
    if (limitSwitch.get()) { // If limit switch is triggered
        motor.stopMotor(); // Stop the motor
    } else {
        motor.set(0.5); // Otherwise, set motor to half power
    }
}

The limitSwitch.get() function returns a boolean value that indicates the state of the limit switch. If the switch is pressed (i.e., the limit has been reached), it returns true. If the switch is not pressed (i.e., the limit has not been reached), it returns false. The return value of this function can be used to conditionally control the motor, stopping it when the limit is reached.

Reading from the Hall Sensor Encoder

A Hall sensor encoder is a device typically attached to a motor, providing real-time position feedback by detecting changes in magnetic fields. This ability to precisely measure the motor's position is crucial for tasks that require fine control and accurate movements. For instance, a robot arm that needs to move to specific locations would benefit from a Hall sensor encoder. The line double position = motor.getEncoder().getPosition(); fetches the motor's current position, which can then be output or utilized within the program for responsive control.

double position = motor.getEncoder().getPosition(); // Get current position of motor
System.out.println("Motor Position: " + position);

Tasks

  1. Explore SparkMax motor controller: Start a new robot project as you've learned before. Instantiate a SparkMax motor controller and write a simple program that sets its speed to half power in the teleoperated mode. Test this program in the simulator to ensure the motor is working correctly.

  2. Control a motor with a joystick: Expand your program to control the SparkMax motor with a joystick. Map the Y-axis of the joystick to the power of the motor. Observe how the motor's speed and direction change with the joystick's movement in the simulator.

  3. Invert motor direction: Experiment with the setInverted method. Write a program where the motor direction is inverted after a certain time or based on a button press on the joystick. Observe the behavior in the simulator.

  4. Create a follower motor: Extend your robot setup to include a second motor. Use the follow method to make the second motor follow the first one. Observe how the follower motor mirrors the actions of the leading motor in the simulator.

  5. Implement a limit switch: Use a digital input to simulate a limit switch in your code. Program the motor to stop when the limit switch is triggered and run otherwise. Test your setup in the simulator.

  6. Read from a Hall Sensor Encoder: Use the getEncoder and getPosition methods to read the position of the motor. Print this value to the console in your robot program and observe how it changes as you run the motor.

Additional Resources

WPILib Motor Control Documentation

REV Robotics SPARK MAX Software Resources

REV Robotics SPARK MAX Examples