Lesson 6.5: Build a Non-Blocking Timer for Parallel Mechanism Control
Technical Context
"Blocking" code (using sleep() or empty while loops) prevents a robot from performing parallel tasks. A responsive robot may need to drive toward a target while simultaneously raising a lift. A non-blocking timer loop lets the program check time, sensors, and encoders in the same loop cycle, so independent mechanisms can continue updating.
How Non-Blocking Timing Lets Mechanisms Work Together
This lesson uses the SDK's ElapsedTime utility. Calling new ElapsedTime() creates a timer and starts it immediately; calling reset() establishes a new zero point when an action begins. The loop can then check seconds() or milliseconds() without pausing other code.
This pattern is commonly used for state-machine transitions and parallel mechanism control.
Annotated Code
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.util.ElapsedTime;
@TeleOp(name="Parallel_Control_Demo")
public class ParallelControlDemo extends LinearOpMode {
// The constructor starts the timer; reset it when the timed action begins.
private final ElapsedTime liftTimer = new ElapsedTime();
@Override
public void runOpMode() {
DcMotor driveMotor = hardwareMap.get(DcMotor.class, "drive");
DcMotor liftMotor = hardwareMap.get(DcMotor.class, "lift");
waitForStart();
liftTimer.reset();
while (opModeIsActive()) {
// Action 1: Drive can continue responding on each loop cycle
driveMotor.setPower(-gamepad1.left_stick_y);
// Action 2: Lift only runs if the timer window is still open
if (liftTimer.seconds() < 2.0) {
liftMotor.setPower(1.0);
} else {
liftMotor.setPower(0.0);
}
telemetry.addData("Lift Time", "%.2f s", liftTimer.seconds());
telemetry.update();
}
}
}
Competition Code in the Wild
Murray Bridge Bunyips' BunyipsLib wraps a function in a reusable periodic scheduler. Its field initialization also shows the complete new ElapsedTime() expression:
private final ElapsedTime timer = new ElapsedTime();
@Override
public void run() {
if (!init) {
timer.reset();
init = true;
}
if (intervalMs <= 0 || timer.milliseconds() >= intervalMs) {
function.run();
timer.reset();
}
}
Nothing in run() waits. Repeated calls check the deadline, run the function when due, reset the timer, and return. Excerpted from BunyipsLib's Periodic.java at a pinned commit under the MIT License.
Fill-in-the-Blank Practice
- Using
sleep()is discouraged because it__________the entire program thread from updating other hardware. - A
__________timer loop is necessary to allow parallel mechanism control. - To trigger an event after 5 seconds without stopping the robot, call
reset()when the event begins and compare__________against5.0.
Show answers
- blocks
- non-blocking
timer.seconds()(wheretimeris anElapsedTimeinstance)
Simulator Practice
Use the simulator below to practice running one mechanism on a timer while another still responds every loop cycle.
Ready to move on?
Only mark complete if you genuinely understand the material. Your progress will be saved in this browser.
Stuck on this lesson?
Ask about anything on this page. It can see which lesson you have open and which part you are reading.