Zero Power Behavior: BRAKE vs FLOAT
When you call setPower(0), you might expect the motor to stop immediately. In reality, the motor has two completely different behaviors depending on how you have configured it -- and choosing the wrong one for your mechanism can lead to anything from jerky driving to a slow arm crashing down under its own weight.
What Happens When You Set Power to Zero?
FLOAT (Coast)
In FLOAT mode, the motor controller disconnects the motor terminals from the drive circuit. The motor is effectively unpowered and spins freely under inertia. This is called coasting.
Think of it like taking your foot off the gas in a car on a flat road -- the car slows down gradually due to friction, not because anything is actively stopping it.
BRAKE
In BRAKE mode, the motor controller short-circuits the motor terminals. This causes the motor's own back-EMF to oppose any further rotation. The motor resists being turned and decelerates much more sharply.
Think of it like engine braking on a steep downhill -- the drivetrain actively works against forward motion.
Setting Zero Power Behavior
motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT);
Set this property during init(), before waitForStart(). You only need to set it once -- the setting persists until you change it.
When to Use BRAKE
Use BRAKE whenever you want the mechanism to hold its position when the driver releases the control:
- Lifts and arms: Without braking, gravity will slowly backdrive the motor and the arm will drop.
- Precise stopping in autonomous: BRAKE gives you a more consistent stopping position because the motor resists rolling past the target.
- Any mechanism where backdriving is dangerous: If a motor coasting backwards could damage a game element or the robot, use BRAKE.
When to Use FLOAT
Use FLOAT when abrupt stopping would cause problems:
- Drive wheels between bursts: When coasting is acceptable and you want the robot to slow gradually, FLOAT feels smoother.
- Mechanisms with hard stops: If the mechanism is against a physical stop, BRAKE forces can stress the gearbox unnecessarily.
- High-speed mechanisms that coast safely: A spinning flywheel that needs to spin down naturally.
Motor Direction Configuration
Most drivetrains need to reverse one side of the robot so that positive power drives both wheels forward. Without this, the left and right motors spin in opposite directions when given the same power command.
motor.setDirection(DcMotor.Direction.REVERSE); // Flip the motor
motor.setDirection(DcMotor.Direction.FORWARD); // Default
For a standard mecanum drivetrain, the left-side motors are typically reversed:
frontLeft.setDirection(DcMotor.Direction.REVERSE);
backLeft.setDirection(DcMotor.Direction.REVERSE);
Best Practice: Configure Everything in init()
Hardware configuration should happen in init(), before waitForStart(). This keeps your setup logic in one place and ensures the robot is always in the correct state when loop() or the main autonomous sequence begins.
@Override
public void runOpMode() {
// Get motors from hardware map
DcMotor frontLeft = hardwareMap.get(DcMotor.class, "frontLeft");
DcMotor frontRight = hardwareMap.get(DcMotor.class, "frontRight");
DcMotor backLeft = hardwareMap.get(DcMotor.class, "backLeft");
DcMotor backRight = hardwareMap.get(DcMotor.class, "backRight");
// Set directions -- left side reversed for forward motion
frontLeft.setDirection(DcMotor.Direction.REVERSE);
backLeft.setDirection(DcMotor.Direction.REVERSE);
frontRight.setDirection(DcMotor.Direction.FORWARD);
backRight.setDirection(DcMotor.Direction.FORWARD);
// Set all motors to BRAKE
frontLeft.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
frontRight.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
backLeft.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
backRight.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
// Set run mode
frontLeft.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
frontRight.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
backLeft.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
backRight.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);
telemetry.addData("Status", "Initialized");
telemetry.update();
waitForStart();
// Main teleop loop
while (opModeIsActive()) {
double forward = -gamepad1.left_stick_y;
double strafe = gamepad1.left_stick_x;
double rotation = gamepad1.right_stick_x;
double fl = forward - strafe - rotation;
double fr = forward + strafe + rotation;
double bl = forward + strafe - rotation;
double br = forward - strafe + rotation;
// Normalize
double max = Math.max(Math.abs(fl),
Math.max(Math.abs(fr),
Math.max(Math.abs(bl), Math.abs(br))));
if (max > 1.0) {
fl /= max;
fr /= max;
bl /= max;
br /= max;
}
frontLeft.setPower(fl);
frontRight.setPower(fr);
backLeft.setPower(bl);
backRight.setPower(br);
}
}
Summary
| Setting | Motor at Zero Power | Best For |
|---|---|---|
FLOAT | Coasts freely | Drive wheels, spin-down mechanisms |
BRAKE | Actively resists rotation | Lifts, arms, precise autonomous stops |
Your Exercise
Configure a 4-motor mecanum drivetrain. In init(): retrieve all four motors from hardwareMap, set the left motors (frontLeft and backLeft) to Direction.REVERSE, and set all four motors to ZeroPowerBehavior.BRAKE. Then implement a teleop while loop that reads gamepad1.left_stick_y and gamepad1.right_stick_x to drive the robot.