During initialization, after "Init" is pressed on the Driver Hub but BEFORE "Play" is pressed, there are a few things we can set up for our code.
First are our motor settings. One of the drivetrain motors must be reversed to prevent spinning in a circle. For the 2026-27 Starter Bot, the rightDrive motor is reversed. Then our flywheel need to be set to use the encoder since we will be using velocity.
Then we will set up our variables. There is only one variable in the default code, targetVelocity, which sets the velocity the flywheel will try to reach for launching pollen from near the field perimeter. If your team decides to change where you want to launch from, this variable can be updated here or an additional one can be added!
After play is pressed, the looping portion of the OpMode will begin. But first, the pollenServo will be set itself to the up position (1). This helps to ensure the extension is out of the way as the robot drives until the servo is activated.
The loop for the OpMode may appear pretty short, but this is thanks to the use of
intakeControls
This is the code used to control the Core Hex intake for the pollen.
pollenPoker
This is the code used to control the servo's position for poking pollen out of a flower
arcadeDrive
Telemetry allows us to receive information on the Driver Hub from the robot. The telemetry included provides a readout of the current velocity for the flywheel to help with troubleshooting and making adjustments to the code.


This is the code for driving the robot. Look here if you plan to change to Split Arcade, Mecanum, or Tank Drive
flywheelControls
This larger function contains the code for the flywheel system, including both manual controls and the auto sequence for launching pollen.



This year's Starter Bot program focuses on simplicity, providing a foundation for teams to then build upon in both TeleOp control and Auto. This walkthrough will begin with an overview of the configuration, wiring, and gamepad set up.
If your team is new to FTC, or in need of a review, we strongly recommend checking out our updated Hello Robot Programming Guide before diving in!
To begin, let's take a look at the configuration and actuators used in this year's design.
Before getting started with programming we needed to create a configuration file. Below is an overview of how the robot is configured for the TeleOp code to function as expected:
If the "Download" button is not visible, right click the file below and select "save link as". To put this configuration file on your robot, drag this file into the "FIRST" folder of your Control Hub's file system.
You will need to activate the configuration using the Driver Hub before proceeding.
The 2026-27 REV DUO FTC Starter Bot is designed to use arcade drive for the default. Check out our page for the split arcade drive version of the program.
In arcade drive, one joystick will control all movements of the drivetrain. For the example code, the left joystick controls the drivetrain freeing up the right hand to activate the various action buttons!
More information on programming gamepads for use with your robot can be found at .
Coming Soon!
The autonomous program for the 2026-27 Starter Bot has the robot move forward from the starting location then launch the preloaded Pollen into the Hive. An optional delay is available so that the robot can either start on the high end of the Hive or wait until after your alliance partner launches their preloads and shifts the goal on the other side!
During initialization, the robot will complete a few tasks in preparation for "Play" being pressed. Similarly to the TeleOp code, one of the drivetrain motors must be reversed and the flywheel motor told to use the encoder.
The targetVelocity variable is set to the same as in TeleOp, but another variable is created here. The autoTimer sets up our ElapsedTime timer that we will be using during the auto period!
What do you think of when you think of a timer? A stopwatch? Your phone? Maybe the timer on a microwave or oven? Timers commonly consist of two main categories: count up and count down. You can think about the differences of these two by a comparison like keeping track of how fast a runner did a 100m dash vs. needing to know how much longer our food should cook.
ElapsedTime is a count up timer. Registering the amount of time elapsed from the start of a set event, like the starting of a stopwatch. In this situation, it is the amount of time passed from when the timer is created or reset within the code.
At the very start of the auto OpMode, after "Play" is pressed, the pollenServo will move to it's 1 position if not already there.
Then there is a disabled block in the sample code.
This sleep call is available to force the OpMode to wait before beginning the code proper. During this time we don't want the robot to do anything so we'll tell it to sleep for 10 seconds then begin.
If your team's strategy is to wait on the low side of the Hive, with the intention of launching your preloads after your alliance partner has gone and shifted the Hive up, then enable this block! Be sure to check how long the sleep period should be to make sure there is enough time to execute the full auto.
The timer used for ElapsedTime begins as soon as the OpMode is initialized. Since it's hard to plan for how long it's been running, we'll first simply reset the timer before using it.
Next, we have a loop for the robot to move for 0.7 seconds to reposition from the wall.
How long the robot needs to move may vary per robot build. Be sure to test this and make adjustments for your final design!
Looking more closely at the loop, there are two checks. The loop while continue so long as BOTH are true. A check for if opModeIsActive, meaning if the "Play" has been pressed, should always be used with loops to ensure the OpMode executes properly and safely disables when needed!
The other check looks at if the autoTimer is still less than or equal to 0.7 seconds. Remember we just restarted the timer so it'll be at 0 when entering the loop!
During the loop, the robot will send -0.25 power to the drivetrain motors to move slowly away. Since the recommended orientation for starting is the robot sitting with the front side (intake) to the wall, the robot must back up or use negative power.
After the 0.7 seconds is over, the motors are told to go to 0 power to prevent any extra movement. At this point the robot is in place and ready to launch!
Before our next loop begins, we'll reset our timer again so it starts from 0 and is easier to make adjustments to the program.
Similar to the driving portion of the code, the loop will continue while the OpMode is active AND the timer is less than or equal to 15 seconds. Make sure to test this amount of time and adjusted it based on your robot and strategy!
Once the loop begins, the flywheel will turn on to get up to velocity.
Before feeding in game pieces, the robot will check if the flywheel's velocity is within a specified range of the targetVelocity, similar to the TeleOp code.
The range is larger than when running the TeleOp program, but it's recommended to do some testing with your final robot to adjust this range appropriately!
If the velocity is within range, then the servo feeder AND intake will begin moving game pieces into the flywheel shoot to be launched.
If the velocity is out of range, the servo feeder and intake will turn off. This may cause what appears to be "stuttering" or "rubberbanding" while the flywheel stabilizes to the correct velocity.
Once the 15 seconds for the flywheel portion of the code ends the program will stop!
This year's Starter Bot's default program uses Arcade Drive. While practicing with the robot, we found this more comfortable to handle alongside the flywheel and poker controls. Both forward/reverse and rotation are controlled on the left joystick.
Alterative options for drive style are available on our upgrades page. Test out different versions and see what works best for you!
Controlling the rotation of the intake, both for forward and reverse, is on the right side of the gamepad using the right bumper and right trigger. The right bumper intakes and moves the game pieces up to the feeder.
The right trigger pushes the game pieces back down and out of the robot. In code, this is set to RightTriggerPressed instead of the standard right trigger option. This is because the triggers on the gamepad typically provide a float input, but since we just need to know if it's pressed or not pressed here we can set it to simply check for that instead!
The cross and circle buttons on the gamepad control the servo's position. For both, "WasPressed" is used to prevent needing to continuing holding the button until the servo has reached position.
The largest function within the program is that for the flywheel control. Let's break it down!
At the beginning of the flywheelControls function is the manual control for the flywheel. When triangle is held, the flywheel will spin up to the targetVelocity BUT the feeder will not activate.
When square is held, the flywheel will spin in reverse near half power. This is intended to help with unsticking or repositioning game pieces if needed.
Next is the sequence for the flywheel and feeder to activate together. When the flywheel spins up to the targetVelocity while left bumper is held, the feeder will wait until the current velocity is within range before also turning on. This is intended to prevent game pieces feeding too early for more consistent launches!
It's recommended to take some time testing this on your specific robot and making adjustments to this range based on your team's preferred launch location and robot set up.
The feeder is controlled by a servo and intended to allow control of how the game pieces feed down into the flywheel.
Similar to the flywheel, there are manual controls for the servo feeder. When up on the dpad is pressed, the feed will move game pieces into the chute for the flywheel. When down on the dpad is pressed, the servo will spin in reverse pushing game pieces back into the intake. This is intended to help with unsticking or repositioning game pieces.
Lastly, if no button in the if/else statement is currently pressed then the flywheel motor and servo will be set to 0 power to be turned off.
Motor
0
REV Robotics Ultraplanetary HD Hex Motor
leftDrive
Motor
1
REV Robotics Ultraplanetary HD Hex Motor
rightDrive
Motor
2
leftDrive
UltraPlanetary Gearbox Kit and HD Hex Motor
Motor/Encoder Port 0
rightDrive
UltraPlanetary Gearbox Kit and HD Hex Motor
Left Joystick
Drivetrain control (Arcade Drive)
Left Bumper
Flywheel Sequence: Activates flywheel then feeder servo
Right Bumper






The OnBot Java version of the program is nearly identical to the Blocks version this year. Therefore the walkthrough for the Blocks version is applicable to the OnBot Java option.
Some extra spacing has been added for readability, but does not effect the 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.CRServo;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.DcMotorEx;
import com.qualcomm.robotcore.hardware.Servo;
@TeleOp
public class REVStarterBotJava2026 extends LinearOpMode {
private DcMotor intakeMotor;
private DcMotor flywheel;
private CRServo crServo;
private DcMotor rightDrive;
private Servo pollenServo;
private DcMotor leftDrive;
int targetVelocity;
/**
* The section below contains the iterative OpMode for the robot to operate so
* long as "Stop" has not been pressed OR communication to the Driver Station
* has not been lost.
*/
@Override
public void runOpMode() {
intakeMotor = hardwareMap.get(DcMotor.class, "intakeMotor");
flywheel = hardwareMap.get(DcMotor.class, "flywheel");
crServo = hardwareMap.get(CRServo.class, "crServo");
rightDrive = hardwareMap.get(DcMotor.class, "rightDrive");
pollenServo = hardwareMap.get(Servo.class, "pollenServo");
leftDrive = hardwareMap.get(DcMotor.class, "leftDrive");
// Setting up motors and variables
rightDrive.setDirection(DcMotor.Direction.REVERSE);
flywheel.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
targetVelocity = 1160;
waitForStart();
if (opModeIsActive()) {
// Ensures the servo is up. Runs once after "Play" is pressed.
pollenServo.setPosition(1);
// Loop for the OpMode containing the functions
while (opModeIsActive()) {
intakeControls();
pollenPoker();
arcadeDrive();
flywheelControls();
// Allows for velocity to be seen on the Driver Station
telemetry.addData("Flywheel Velocity", ((DcMotorEx) flywheel).getVelocity());
telemetry.update();
}
}
}
//Below are the individual functions, also called methods, for each system.
/**
* Intake Controls
* This function contains the controls for the intake system using the Core Hex.
*/
private void intakeControls() {
// Intake in and out
if (gamepad1.right_bumper) {
intakeMotor.setPower(1);
} else if (gamepad1.right_trigger_pressed) {
intakeMotor.setPower(-1);
} else {
intakeMotor.setPower(0);
}
}
/**
* Controls for the Pollen poking servo
* This function contains the code for the servo powered pollen poker on the front of the robot.
*/
private void pollenPoker() {
// Servo control for poking out pollen
if (gamepad1.crossWasPressed()) {
pollenServo.setPosition(0);
} else if (gamepad1.circleWasPressed()) {
pollenServo.setPosition(1);
}
}
/**
* Controls for Arcade Drive
* This function contains the code for the arcade drive controls.
*/
private void arcadeDrive() {
float x;
float y;
// Arcade Drive on left stick
x = gamepad1.left_stick_x;
y = -gamepad1.left_stick_y;
leftDrive.setPower(y + x);
rightDrive.setPower(y - x);
}
/**
* Controls for the flywheel - manual and auto sequence
* This function contains the controls for the flywheel system.
*/
private void flywheelControls() {
if (gamepad1.triangle) {
// Manual control for flywheel motor
((DcMotorEx) flywheel).setVelocity(targetVelocity);
} else if (gamepad1.square) {
// Reverse flywheel
flywheel.setPower(-0.55);
} else if (gamepad1.left_bumper) {
((DcMotorEx) flywheel).setVelocity(targetVelocity);
// Auto feed into flywheel if within a set velocity range
if (((DcMotorEx) flywheel).getVelocity() >= targetVelocity - 20 && ((DcMotorEx) flywheel).getVelocity() <= targetVelocity + 20) {
crServo.setPower(1);
}
} else if (gamepad1.dpad_up) {
// Manual control for feeder servo
crServo.setPower(1);
} else if (gamepad1.dpad_down) {
// Reverse feeder
crServo.setPower(-1);
} else {
// Turn off servo and motor when gamepad is not active
flywheel.setPower(0);
crServo.setPower(0);
}
}
}package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.hardware.CRServo;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.DcMotorEx;
import com.qualcomm.robotcore.hardware.Servo;
import com.qualcomm.robotcore.util.ElapsedTime;
@Autonomous
public class REVStarterBotJavaAuto2026 extends LinearOpMode {
private DcMotor rightDrive;
private DcMotor flywheel;
private Servo pollenServo;
private DcMotor leftDrive;
private CRServo crServo;
private DcMotor intakeMotor;
/**
* This autonomous code will have the robot drive away from the wall then
* launch preloaded pollen. An optional delay is available if your team chooses
* to start on the far side!
*/
@Override
public void runOpMode() {
int targetVelocity;
ElapsedTime autoTimer;
rightDrive = hardwareMap.get(DcMotor.class, "rightDrive");
flywheel = hardwareMap.get(DcMotor.class, "flywheel");
pollenServo = hardwareMap.get(Servo.class, "pollenServo");
leftDrive = hardwareMap.get(DcMotor.class, "leftDrive");
crServo = hardwareMap.get(CRServo.class, "crServo");
intakeMotor = hardwareMap.get(DcMotor.class, "intakeMotor");
// Put initialization blocks here.
rightDrive.setDirection(DcMotor.Direction.REVERSE);
flywheel.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
targetVelocity = 1160;
autoTimer = new ElapsedTime();
waitForStart();
if (opModeIsActive()) {
// Ensures the servo for the pollen poker is in the right position pointing up
pollenServo.setPosition(1);
// Enable the sleep call below (Line 51) to add a delay to the program starting
// The default delay is 10 seconds so be sure to adjust based on your strategy!
//sleep(10000);
// Robot drives forward 700 milliseconds to no longer touch the wall
autoTimer.reset();
while (autoTimer.milliseconds() <= 700 && opModeIsActive()) {
leftDrive.setPower(-0.25);
rightDrive.setPower(-0.25);
}
// Turn off drivetrain motors to prevent extra movement
leftDrive.setPower(0);
rightDrive.setPower(0);
// Flywheel begins launch sequence for the preloaded pollen
autoTimer.reset();
// The flywheel is set to spin for 15 seconds.
while (autoTimer.seconds() <= 15 && opModeIsActive()) {
((DcMotorEx) flywheel).setVelocity(targetVelocity);
// The flywheel must be within a specified range of the target velocity for the intake and feeder servo to activate!
if (((DcMotorEx) flywheel).getVelocity() >= targetVelocity - 50 && ((DcMotorEx) flywheel).getVelocity() <= targetVelocity + 50) {
crServo.setPower(1);
intakeMotor.setPower(1);
} else {
// If the velocity is not within range, the intake and feeder servo turn off to prevent early feeding
crServo.setPower(0);
intakeMotor.setPower(0);
}
}
}
}
}REV Robotics Core Hex Motor
intakeMotor
Motor
3
REV Robotics Ultraplanetary HD Hex Motor
flywheel
Servo
0
Continuous Servo
crServo
Servo
1
Servo
pollenServo
Motor/Encoder Port 1
intakeMotor
Core Hex Motor
Motor/Encoder Port 2
flywheel
UltraPlanetary Gearbox Kit and HD Hex Motor
Motor/Encoder Port 3
crServo
Smart Robot Servo - set to CR mode
Servo Port 0
pollenServo
Smart Robot Servo
Servo Port 1
Intakes pollen
Right Trigger
Outtakes pollen (reverses Core Hex Motor)
Dpad Up
Manual control for the servo feeder
Dpad Down
Manually reverses the servo feeder
Y/Triangle
Manually activates ONLY the flywheel to the target velocity
X/Square
Manually reverses the flywheel at half power
A/Cross
Moves pollen poker servo to preset down position
B/Circle
Moves pollen poker servo to preset up position














