---
description: Programming Motors
---

# Motors and Encoders

DC Motors in FTC are used for movement of large mechanisms and can be used for fast and continuous rotation, or precise movement for things like an arm. It is very important to learn how to efficiently program motors.&#x20;

## Motor Initialization

The first step in using a motor is to initialize it as a variable in the code. This is done through the use of an object named **hardwareMap** that is used for easy initialization of FTC Objects.

```java
DcMotor driveMotor;       

driveMotor = hardwareMap.get(DcMotor.class, "Drive Motor");  
```

In this example, first the `driveMotor` variable is created through the use of the `DcMotor` object. Then the **hardwareMap** is used to initialize and name the motor, this should be the same name used in the configuration of the Motor on the phone.&#x20;

### DcMotor Setup Usage

There are many methods that for the DcMotor that can be used before the motor is powered to change how it behaves when it runs.

### Set Direction

```java
driveMotor.setDirection(DcMotor.Direction.Forward);
driveMotor.setDirection(DcMotor.Direction.Reverse);
```

&#x20; `setDirection` is used to change the way a motor rotates when it is set to power. set     Direction should be used on drive train motors to ensure that all motors are spinning the same direction when sent to an equal power.&#x20;

## Motor Encoders

In the realm of FTC robotics, motors connected to an encoder serve as advanced motors with an extra ability: they can communicate to the robot how much they've rotated and at what speed. Imagine you're steering a remote-control car, and you want it to travel a particular distance or turn a specific angle. Regular motors might get close, but they can't give you exact control. Encoder motors, on the other hand, offer precision.

An encoder is typically connected via a special wire that is connected to the motor. This device keeps track of rotations, and each complete rotation is divided into smaller parts called ticks. Think of a tick as a tiny mark on a ruler that measures how much the motor has turned. For instance, a motor may measure 100 ticks for every rotation of the motor shaft.&#x20;

FTC teams harness the power of these encoder motors to program their robots with accurate movements. When the robot's wheels turn, the encoders count the ticks. So, if the robot's wheel turns 100 ticks, the robot knows it has moved a specific distance. It's akin to the robot reading its own mini-map that shows exactly where it is.

On the other hand, the motor's velocity is also measured by the encoder through the number of ticks per second the motor is traveling.&#x20;

### Run Mode

```java
driveMotor.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
driveMotor.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
driveMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER);
driveMotor.setMode(DcMotor.RunMode.RUN_TO_POSITION);
```

#### RUN WITHOUT ENCODER

This mode causes a motor to not use the plugged in encoder values to do things like control its position or speed.

#### RUN USING ENCODER

This causes the motor to use a motor encoder(if plugged in), to help control its position or speed. When a motor is set to `RUN_USING_ENCODER` it automatically uses the encoder to help keep the motor consistently running at any speed set to the motor.&#x20;

#### STOP AND RESET ENCODER

This will reset the encoder tick value the motor has to 0. It will ensure that the encoder ticks are consistent per each run, and causes the motor to work as expected each run. If using the encoder ticks as a measurement, `STOP_AND_RESET_ENCODER` should be used at the beginning of your code.&#x20;

#### RUN TO POSITION

Run To Position is a very useful mode for motors. It allows for a motor to run to a specific target tick value that is set, and the motor will go that position and hold it. It uses an in-built PID Control Loop to accomplish this.

{% hint style="info" %}
### Note

In some cases, RUN\_TO\_POSITION, might not be the best method for moving a motor to a position, and it can be better to create and use a custom PID loop in some cases. Instructions for a custom PID Loop can be found here.&#x20;
{% endhint %}

### Moving a Motor to a Position Using Encoders

To move a motor to a target encoder position(given in ticks), we will first be introducing two more commands. `setTargetPosition()` takes in a tick value for the motor that becomes its target position. `setPower()` sets a \[-1,1] value for the motor speed to run at. A power below 0 runs the motor in the opposite direction. &#x20;

```java
TARGET_TICK_VALUE = 600;      
driveMotor.setTargetPosition(TARGET_TICK_VALUE);    //Sets Target Tick Position
driveMotor.setMode(DcMotor.RunMode.RUN_TO_POSITION); 
driveMotor.setPower(1);           //Sets Motor to go to position at 1 power.
```

In the example the motor is set to run to a target position of 600 ticks, the amount of rotations this is will depend on the ticks per rotation of that specific motor. After setting the target position the motor is set to the `RUN_TO_POSITION` mode, then set to a power of 1, or full power, to run to its target position.

{% hint style="info" %}
When using RUN\_TO\_POSITION, the power should not ever be negated as the motor will go towards whatever direction the tick count is. If the motor needs to go in the opposite direction, use a negative tick count
{% endhint %}

### Finding Motor Position

When using encoders, there is a useful method that can be used to find the motors position in encoder ticks.

```java
int position;
position = motor.getCurrentPosition();
```

{% hint style="info" %}
### Ticks Per Rotation

We recommend looking up the webpage of whatever motor you are using and finding the ticks per revolution, the value counted by the encoder per rotation. This can help you in terms of calculating how far you want to turn your mechanisms.&#x20;
{% endhint %}

### Velocity Control

When setting the motor to RUN\_USING\_ENCODER mode, setting power to a motor causes it to move at a constant velocity rather than an actual power, this means that a motor connected to an encoder will be less resistant to battery fluctuations when compared to a motor that is not connected to an encoder.&#x20;

Alternatively, you can specify the exact ticks per second the motor should be spinning at:

```java
((DcMotorEx)motor).setVelocity(ticksPerSecond); 
```

## Motor Class

Here is a convenient motor class that contains shortcuts to most of the methods listed above.&#x20;

```java
package org.firstinspires.ftc.teamcode.Utils;

import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.DcMotorEx;
import com.qualcomm.robotcore.hardware.DcMotorSimple;
import com.qualcomm.robotcore.hardware.HardwareMap;
import com.qualcomm.robotcore.hardware.PIDFCoefficients;

public class Motor {
  DcMotor motor;
  int multiplier = 1;

  public Motor(HardwareMap hardwareMap, String name) {
    this.motor = hardwareMap.dcMotor.get(name);
    motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);

    try {
      resetEncoder(true);
    } catch (Exception e) {
      noEncoder();
    }
  }

  public Motor(HardwareMap hardwareMap, String name, boolean useEncoder) {
    this.motor = hardwareMap.dcMotor.get(name);
    motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);

    try {
      resetEncoder(useEncoder);
    } catch (Exception e) {

    }
  }

  public void setDirection(DcMotorSimple.Direction d) {
    motor.setDirection(d);
  }

  public DcMotorSimple.Direction getDir() {
    return motor.getDirection();
  }

  public void coast() {
    motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT);
  }

  public void negateEncoder() {
    multiplier = -1;
  }

  public int encoderReading() {
    return motor.getCurrentPosition() * multiplier;
  }

  public void setPower(double power) {
    this.motor.setPower(power);
  }

  public double getPower() {
    return this.motor.getPower();
  }

  public void resetEncoder(boolean useEncoder) {
    this.motor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER);

    if (useEncoder) {
      useEncoder();
    } else {
      noEncoder();
    }
  }

  public void setFloat() {
    this.motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT);
  }

  public void noEncoder() {
    this.motor.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
  }

  public void flip() {
    this.motor.setDirection(DcMotorSimple.Direction.REVERSE);
  }

  public void useEncoder() {
    this.motor.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
  }

  public void setTarget(double target) {
    this.motor.setTargetPosition((int) target);
  }

  public void setPid(double p, double i, double d, double f) {
    this.retMotorEx()
        .setPIDFCoefficients(DcMotor.RunMode.RUN_USING_ENCODER, new PIDFCoefficients(p, i, d, f));
  }

  public void toPosition() {
    this.motor.setMode(DcMotor.RunMode.RUN_TO_POSITION);
  }

  public boolean isBusy() {
    return this.motor.isBusy();
  }

  public DcMotorEx retMotorEx() {
    return (DcMotorEx) motor;
  }
}
```

{% hint style="success" %}
### EXERCISE
{% endhint %}

{% tabs %}
{% tab title="Task" %}
First, initialize a new motor that has a variable name of **arm**, but has a configuration name of **armMotor**. Then, reverse the motor from its current direction. After that, set the motor to run using an encoder. Next, move the motor to a position of 950 ticks at 70% speed.
{% endtab %}

{% tab title="Solution" %}
```java
DcMotor arm;
TARGET_TICK_POSITION = 950;
arm = hardwareMap.get(DcMotor.class,"armMotor");

arm.setMode(DcMotor.RunMode.RUN_USING_ENCODER);

arm.setTargetPosition(TARGET_TICK_POSITION);
arm.setMode(DcMotor.RunMode.RUN_TO_POSITION);
arm.setPower(0.7);
```
{% endtab %}
{% endtabs %}

###
