diff --git a/src/content/docs/hardware/actuators/cr-servos.mdx b/src/content/docs/hardware/actuators/cr-servos.mdx
index f8035a0..b9125b0 100644
--- a/src/content/docs/hardware/actuators/cr-servos.mdx
+++ b/src/content/docs/hardware/actuators/cr-servos.mdx
@@ -17,18 +17,22 @@ There are two ways to construct a `NextCRServo`, depending on what you desire.
```kotlin
-val intakeServo = NextCRServo(RobotController.controlHub, 0) // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+val intakeServo = NextCRServo(RobotController.controlHub, 0)
-val intakeServo = NextCRServo("intakeServo") // Using your configuration name
+// Using a configuration name
+val intakeServo = NextCRServo("intakeServo")
```
```java
-NextCRServo intakeServo = new NextCRServo(RobotController.getControlHub(), 0); // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+NextCRServo intakeServo = new NextCRServo(RobotController.getControlHub(), 0);
-NextCRServo intakeServo = new NextCRServo("intakeServo"); // Using your configuration name
+// Using a configuration name
+NextCRServo intakeServo = new NextCRServo("intakeServo");
```
diff --git a/src/content/docs/hardware/actuators/feedback-servos.mdx b/src/content/docs/hardware/actuators/feedback-servos.mdx
index 8e83eda..22e35c6 100644
--- a/src/content/docs/hardware/actuators/feedback-servos.mdx
+++ b/src/content/docs/hardware/actuators/feedback-servos.mdx
@@ -19,23 +19,28 @@ All of these below are interchangeable with `NextFeedbackCRServo`.
```kotlin
-val armServo = NextFeedbackServo("armServo", AnalogFeedback(name = "armEncoder")) // By configuration name
+// By configuration name
+val armServo = NextFeedbackServo("armServo", NextAnalogInput("armEncoder"))
-val armServo = NextFeedbackServo(RobotController.expansionHub, 0, AnalogFeedback(name = "armEncoder")) // By Lynx Module and port
-
-val armServo = NextFeedbackServo(RobotController.expansionHub, 0, NextAnalogInput(RobotController.expansionHub, 0)) // Full LynxModule
+// By Lynx Module and port + NextAnalogInput
+val armServo = NextFeedbackServo(RobotController.expansionHub, 0, NextAnalogInput("armEncoder"))
+// Additionally, using a custom feedback method
+val armServo = NextFeedbackServo("armServo", AnalogFeedback(voltageSupplier = { /* custom method here */ } ))
```
```java
-NextFeedbackServo armServo = new NextFeedbackServo("armServo", new AnalogFeedback("armEncoder")); // By configuration name
+// By configuration name
+NextFeedbackServo armServo = new NextFeedbackServo("armServo", new NextAnalogInput("armEncoder"));
-NextFeedbackServo armServo = new NextFeedbackServo(RobotController.getExpansionHub(), 0, new AnalogFeedback("armEncoder")); // By Lynx Module and port
+ // By Lynx Module and port
+NextFeedbackServo armServo = new NextFeedbackServo(RobotController.getExpansionHub(), 0, new NextAnalogInput("armEncoder"));
-NextFeedbackServo armServo = new NextFeedbackServo(RobotController.getExpansionHub(), 0, new NextAnalogInput(RobotController.getExpansionHub(), 0)); // Full LynxModule
+// Additionally, using a custom feedback method
+NextFeedbackServo armServo = new NextFeedbackServo("armServo", new AnalogFeedback(() -> { /* custom method here */ };
```
diff --git a/src/content/docs/hardware/actuators/motors.mdx b/src/content/docs/hardware/actuators/motors.mdx
new file mode 100644
index 0000000..6814d82
--- /dev/null
+++ b/src/content/docs/hardware/actuators/motors.mdx
@@ -0,0 +1,224 @@
+---
+title: Motors
+description: Control motors with NextMotor
+sidebar:
+ order: 1
+---
+
+import { Tabs, TabItem } from '@astrojs/starlight/components';
+
+`NextMotor` is a lightweight wrapper around the standard FTC motor (`DcMotor` or `DcMotorEx`) that provides standard easy-to-use interface for throttling, voltage control, PIDS, and more
+
+## Creating a NextMotor
+There are two main ways to construct a `NextMotor`, depending on what you desire.
+
+
+
+```kotlin
+// By Lynx Module and port, recommended
+val intakeMotor = NextMotor(RobotController.controlHub, 0)
+
+// Using a configuration name
+val intakeMotor = NextMotor("intakeMotor")
+```
+
+
+```java
+// By Lynx Module and port, recommended
+NextMotor intakeMotor = new NextMotor(RobotController.getControlHub(), 0);
+
+// Using a configuration name
+NextMotor intakeMotor = new NextMotor("intakeMotor");
+```
+
+
+
+All constructors accept two optional parameters:
+
+| Parameter | Type | Default | Description |
+|---|---|---|---|
+| `anglePerCount` | `Angle` | 1.0 rad | The angle that a motor's shaft rotates by for every 'tick' or 'count'. Used for calculations that directly convert 'ticks' to the number of rotations the motor has spun. |
+| `cacheTolerance` | `Double` | `0.01` | Minimum change in `throttle` required before a new value is written to the motor. |
+
+## Usage
+### Throttle Control
+
+Throttle Control allows the motor to be throttled from -1.0 (reverse) to 1.0 (full power).
+The value represents a fraction of the robot's total voltage.
+
+
+
+```kotlin
+// Adjust 1.0 to be what value you would like it to be
+myMotor.throttle = 1.0
+```
+
+
+```java
+// Adjust 1.0 to be what value you would like it to be
+myMotor.setThrottle(1.0)
+```
+
+
+
+### Voltage Control
+
+Voltage Control allows the motor's power to be controlled more accurately and set to a specific voltage.
+
+
+
+```kotlin
+// This function takes in a 'Voltage'
+myMotor.voltage = 12.0.volts
+```
+
+
+```java
+// This function takes in a 'Voltage'
+myMotor.setVoltage(volts.of(12))
+```
+
+
+
+### Positional Control
+
+Positional control allows the motor's position to be controlled using a `PID` Controller
+
+You can change the default positional PID constants by doing:
+
+
+
+```kotlin
+myMotor.positionConstants.apply {
+ kP = 0.1
+}
+// Like kP, other positional PID constants include:
+// kP, kI, kD, kS, kV, kA, kG, kCos, kCosRatio
+```
+
+
+```java
+myMotor.getPositionConstants()
+ .withP(0.1)
+// Like kP, other positional PID constants include:
+// kP, kI, kD, kS, kV, kA, kG, kCos, kCosRatio
+```
+
+
+
+#### Relative Positional Control
+This moves the motor to the designated position **relative** to the position of the motor during the robot's startup.
+
+
+
+```kotlin
+// Increase the target to be your desired angle from the initial position
+myMotor.setPositionSetpoint(90.degrees)
+```
+
+
+```java
+// Increase the target to be your desired angle from the initial position
+myMotor.setPositionSetpoint(degrees.of(90))
+```
+
+
+
+#### Absolute Positional Control
+This makes the motor take the shortest path, regardless of rotations to an angle in the range [-180, 180] degrees.
+
+
+
+```kotlin
+// Increase the target to be your desired angle
+myMotor.setAbsolutePositionSetpoint(90.degrees)
+```
+
+
+```java
+// Increase the target to be your desired angle
+myMotor.setAbsolutePositionSetpoint(degrees.of(90))
+```
+
+
+
+### Velocity Control
+Similar to [Positional Control](#positional-control) velocity control allows the motor's velocity to be controlled using a `PID` Controller
+
+
+
+```kotlin
+// Increase the target to be your desired angular velocity
+myMotor.setVelocitySetpoint(30.degreesPerSecond)
+```
+
+
+```java
+// Increase the target to be your desired angular velocity
+myMotor.setVelocitySetpoint(DegreesPerSecond.of(30))
+```
+
+
+
+You can change the default velocity PID constants by doing:
+
+
+
+```kotlin
+myMotor.velocityConstants.apply {
+ kP = 0.1
+}
+// Like kP, other velocity PID constants include:
+// kP, kI, kD, kS, kV, kA
+```
+
+
+```java
+myMotor.getVelocityConstants()
+ .withP(0.1)
+// Like kP, other velocity PID constants include:
+// kP, kI, kD, kS, kV, kA
+```
+
+
+
+### Following other motors
+`NextMotor`'s have a helpful feature that allows one motor to 'follow' or mimic another motor.
+
+You can use this feature by doing:
+
+
+```kotlin
+myFollowerMotor.follow(myLeaderMotor)
+
+// Optional direction to specify whether it should follow in the same
+// or opposite direction.
+myFollowerMotor.follow(myLeaderMotor, Direction.REVERSE)
+```
+
+
+```java
+myFollowerMotor.follow(myLeaderMotor)
+
+// Optional direction to specify whether it should follow in the same
+// or opposite direction.
+myFollowerMotor.follow(myLeaderMotor, Direction.REVERSE)
+```
+
+
+
+### `Direction`
+You can set the `Direction` property of `NextMotor`'s to control the direction that the motor rotates in.
+
+| Direction Type | Description |
+|---|---|
+| Direction.FORWARD | The motor moves forward (Clockwise) |
+| Direction.REVERSE | The motor spins in the opposite direction (Counter-Clockwise) |
+
+### `ZeroPowerBehaviour`
+The `ZeroPowerBehaviour` property allows you to control how the motor reacts when it is given a `throttle` of 0
+
+| ZeroPowerBehaviour Type | Description |
+|---|---|
+| ZeroPowerBehaviour.BRAKE | Actively stops the motor when given a power of 0 |
+| ZeroPowerBehaviour.FLOAT | Allows the motor to naturally spin and eventually stop by itself |
\ No newline at end of file
diff --git a/src/content/docs/hardware/actuators/servos.mdx b/src/content/docs/hardware/actuators/servos.mdx
index 5dc7b68..4b4a5d0 100644
--- a/src/content/docs/hardware/actuators/servos.mdx
+++ b/src/content/docs/hardware/actuators/servos.mdx
@@ -11,24 +11,28 @@ import { Tabs, TabItem } from "@astrojs/starlight/components";
## Creating a NextServo
-There are three ways to construct a `NextServo`, depending on what you desire.
+There are two main ways to construct a `NextServo`, depending on what you desire.
```kotlin
-val armServo = NextServo(RobotController.controlHub, 0) // By Lynx Module and port, recommended
+ // By Lynx Module and port, recommended
+val armServo = NextServo(RobotController.controlHub, 0)
-val armServo = NextServo("armServo") // Using your configuration name
+// Using a configuration name
+val armServo = NextServo("armServo")
```
```java
-NextServo armServo = new NextServo(RobotController.getControlHub(), 0); // By Lynx Module and port, recommended
+ // By Lynx Module and port, recommended
+NextServo armServo = new NextServo(RobotController.getControlHub(), 0);
-NextServo armServo = new NextServo("armServo"); // Using your configuration name
+// Using a configuration name
+NextServo armServo = new NextServo("armServo");
```
diff --git a/src/content/docs/hardware/miscellaneous/husky-lens.mdx b/src/content/docs/hardware/miscellaneous/husky-lens.mdx
index 7ed71e7..7625eb7 100644
--- a/src/content/docs/hardware/miscellaneous/husky-lens.mdx
+++ b/src/content/docs/hardware/miscellaneous/husky-lens.mdx
@@ -17,14 +17,16 @@ Anything else not wrapped is accessible through `camera`.
```kotlin
-val huskyLens = NextHuskyLens("huskyLens") // Using your configuration name
+// Using your configuration name
+val huskyLens = NextHuskyLens("huskyLens")
```
```java
-NextHuskyLens huskyLens = new NextHuskyLens("huskyLens"); // Using your configuration name
+// Using your configuration name
+NextHuskyLens huskyLens = new NextHuskyLens("huskyLens");
```
diff --git a/src/content/docs/hardware/miscellaneous/limelights.mdx b/src/content/docs/hardware/miscellaneous/limelights.mdx
index f5635f5..0c2fbff 100644
--- a/src/content/docs/hardware/miscellaneous/limelights.mdx
+++ b/src/content/docs/hardware/miscellaneous/limelights.mdx
@@ -17,14 +17,16 @@ Any data that is not wrapped can be accessed through `camera`.
```kotlin
-val limelight = NextLimelight("limelight") // Using your configuration name
+// Using your configuration name
+val limelight = NextLimelight("limelight")
```
```java
-NextLimelight limelight = new NextLimelight("limelight"); // Using your configuration name
+// Using your configuration name
+NextLimelight limelight = new NextLimelight("limelight");
```
diff --git a/src/content/docs/hardware/miscellaneous/rgb-indicator.mdx b/src/content/docs/hardware/miscellaneous/rgb-indicator.mdx
index 038818c..b3a34b2 100644
--- a/src/content/docs/hardware/miscellaneous/rgb-indicator.mdx
+++ b/src/content/docs/hardware/miscellaneous/rgb-indicator.mdx
@@ -17,18 +17,22 @@ It extends [`NextServo`](/hardware/actuators/servos/), so everything from that c
```kotlin
-val indicator = NextRGBIndicator(RobotController.controlHub, 0) // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+val indicator = NextRGBIndicator(RobotController.controlHub, 0)
-val indicator = NextRGBIndicator("LED") // Using your configuration name
+// Using your configuration name
+val indicator = NextRGBIndicator("LED")
```
```java
-NextRGBIndicator indicator = new NextRGBIndicator(RobotController.getControlHub(), 0); // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+NextRGBIndicator indicator = new NextRGBIndicator(RobotController.getControlHub(), 0);
-NextRGBIndicator indicator = new NextRGBIndicator("LED"); // Using your configuration name
+// Using your configuration name
+NextRGBIndicator indicator = new NextRGBIndicator("LED");
```
diff --git a/src/content/docs/hardware/sensors/analog-inputs.mdx b/src/content/docs/hardware/sensors/analog-inputs.mdx
index 49f355d..931d3b7 100644
--- a/src/content/docs/hardware/sensors/analog-inputs.mdx
+++ b/src/content/docs/hardware/sensors/analog-inputs.mdx
@@ -17,18 +17,22 @@ It inherits from `AnalogFeedback`, so any `NextAnalogInput` can also be passed d
```kotlin
-val input = NextAnalogInput(RobotController.controlHub, 0) // By Lynx Module and channel, recommended
+// By Lynx Module and channel, recommended
+val input = NextAnalogInput(RobotController.controlHub, 0)
-val input = NextAnalogInput("armEncoder") // Using your configuration name
+// Using your configuration name
+val input = NextAnalogInput("armEncoder")
```
```java
-NextAnalogInput input = new NextAnalogInput(RobotController.getControlHub(), 0); // By Lynx Module and channel, recommended
+// By Lynx Module and channel, recommended
+NextAnalogInput input = new NextAnalogInput(RobotController.getControlHub(), 0);
-NextAnalogInput input = new NextAnalogInput("armEncoder"); // Using your configuration name
+// Using your configuration name
+NextAnalogInput input = new NextAnalogInput("armEncoder");
```
diff --git a/src/content/docs/hardware/sensors/color-sensor.mdx b/src/content/docs/hardware/sensors/color-sensor.mdx
index 4ebeead..f495b52 100644
--- a/src/content/docs/hardware/sensors/color-sensor.mdx
+++ b/src/content/docs/hardware/sensors/color-sensor.mdx
@@ -15,18 +15,22 @@ import { Tabs, TabItem } from "@astrojs/starlight/components";
```kotlin
-val sensor = NextColorDistanceSensor(RobotController.controlHub, 0) // By Lynx Module and I2C bus, recommended
+// By Lynx Module and I2C bus, recommended
+val sensor = NextColorDistanceSensor(RobotController.controlHub, 0)
-val sensor = NextColorDistanceSensor("colorSensor") // Using your configuration name
+// Using your configuration name
+val sensor = NextColorDistanceSensor("colorSensor")
```
```java
-NextColorDistanceSensor sensor = new NextColorDistanceSensor(RobotController.getControlHub(), 0); // By Lynx Module and I2C bus, recommended
+// By Lynx Module and I2C bus, recommended
+NextColorDistanceSensor sensor = new NextColorDistanceSensor(RobotController.getControlHub(), 0);
-NextColorDistanceSensor sensor = new NextColorDistanceSensor("colorSensor"); // Using your configuration name
+// Using your configuration name
+NextColorDistanceSensor sensor = new NextColorDistanceSensor("colorSensor");
```
diff --git a/src/content/docs/hardware/sensors/digital-sensor.mdx b/src/content/docs/hardware/sensors/digital-sensor.mdx
index 4027151..a6b7cc9 100644
--- a/src/content/docs/hardware/sensors/digital-sensor.mdx
+++ b/src/content/docs/hardware/sensors/digital-sensor.mdx
@@ -18,18 +18,22 @@ This wrapper handles that inversion for you, so `isTriggered` always means what
```kotlin
-val beamBreak = NextDigitalSensor(RobotController.controlHub, 0) // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+val beamBreak = NextDigitalSensor(RobotController.controlHub, 0)
-val beamBreak = NextDigitalSensor("beamBreak") // Using your configuration name
+// Using your configuration name
+val beamBreak = NextDigitalSensor("beamBreak")
```
```java
-NextDigitalSensor beamBreak = new NextDigitalSensor(RobotController.getControlHub(), 0); // By Lynx Module and port, recommended
+// By Lynx Module and port, recommended
+NextDigitalSensor beamBreak = new NextDigitalSensor(RobotController.getControlHub(), 0);
-NextDigitalSensor beamBreak = new NextDigitalSensor("beamBreak"); // Using your configuration name
+// Using your configuration name
+NextDigitalSensor beamBreak = new NextDigitalSensor("beamBreak");
```
diff --git a/src/content/docs/hardware/sensors/distance-sensor.mdx b/src/content/docs/hardware/sensors/distance-sensor.mdx
index 38745ce..0123452 100644
--- a/src/content/docs/hardware/sensors/distance-sensor.mdx
+++ b/src/content/docs/hardware/sensors/distance-sensor.mdx
@@ -15,18 +15,22 @@ import { Tabs, TabItem } from "@astrojs/starlight/components";
```kotlin
-val sensor = NextDistanceSensor(RobotController.controlHub, 0) // By Lynx Module and I2C bus, recommended
+// By Lynx Module and I2C bus, recommended
+val sensor = NextDistanceSensor(RobotController.controlHub, 0)
-val sensor = NextDistanceSensor("distanceSensor") // Using your configuration name
+// Using your configuration name
+val sensor = NextDistanceSensor("distanceSensor")
```
```java
-NextDistanceSensor sensor = new NextDistanceSensor(RobotController.getControlHub(), 0); // By Lynx Module and I2C bus, recommended
+// By Lynx Module and I2C bus, recommended
+NextDistanceSensor sensor = new NextDistanceSensor(RobotController.getControlHub(), 0);
-NextDistanceSensor sensor = new NextDistanceSensor("distanceSensor"); // Using your configuration name
+// Using your configuration name
+NextDistanceSensor sensor = new NextDistanceSensor("distanceSensor");
```
diff --git a/src/content/docs/hardware/sensors/imu.mdx b/src/content/docs/hardware/sensors/imu.mdx
index 757f24f..ae19e26 100644
--- a/src/content/docs/hardware/sensors/imu.mdx
+++ b/src/content/docs/hardware/sensors/imu.mdx
@@ -15,18 +15,22 @@ import { Tabs, TabItem } from "@astrojs/starlight/components";
```kotlin
-val imu = NextIMU() // Defaults to the configuration name "imu"
+// Defaults to the configuration name "imu"
+val imu = NextIMU()
-val imu = NextIMU("imu") // Using a custom configuration name
+// Using a custom configuration name
+val imu = NextIMU("imu")
```
```java
-NextIMU imu = new NextIMU(); // Defaults to the configuration name "imu"
+// Defaults to the configuration name "imu"
+NextIMU imu = new NextIMU();
-NextIMU imu = new NextIMU("imu"); // Using a custom configuration name
+// Using a custom configuration name
+NextIMU imu = new NextIMU("imu");
```
diff --git a/src/content/docs/hardware/sensors/pinpoint.mdx b/src/content/docs/hardware/sensors/pinpoint.mdx
index d1eb397..12cf17d 100644
--- a/src/content/docs/hardware/sensors/pinpoint.mdx
+++ b/src/content/docs/hardware/sensors/pinpoint.mdx
@@ -15,18 +15,22 @@ import { Tabs, TabItem } from "@astrojs/starlight/components";
```kotlin
-val pinpoint = NextPinpoint(RobotController.controlHub, 0) // By Lynx Module and I2C bus
+// By Lynx Module and I2C bus
+val pinpoint = NextPinpoint(RobotController.controlHub, 0)
-val pinpoint = NextPinpoint("pinpoint") // Using your configuration name
+// Using your configuration name
+val pinpoint = NextPinpoint("pinpoint")
```
```java
-NextPinpoint pinpoint = new NextPinpoint(RobotController.getControlHub(), 0); // By Lynx Module and I2C bus
+// By Lynx Module and I2C bus
+NextPinpoint pinpoint = new NextPinpoint(RobotController.getControlHub(), 0);
-NextPinpoint pinpoint = new NextPinpoint("pinpoint"); // Using your configuration name
+// Using your configuration name
+NextPinpoint pinpoint = new NextPinpoint("pinpoint");
```