Before you start coding, make sure you understand the basics of your codebase.
Your robot code is split into three main files:
| File | Purpose | Can You Edit? |
|---|---|---|
main.cpp | Hardware setup, driver control, main program flow | YES - Most of your work happens here |
1790Autonomous.h | Autonomous routines and mode selection | YES - Add and edit autonomous modes |
1790Common.h | Helper functions, status display, combos | MOSTLY NO - Only add motor externs when adding new motors |
Open main.cpp and find these sections:
This is where all motors and sensors are defined. Currently set up:
Currently three modes: Disabled, Near Score, Far Score. You'll add more here.
This is where button presses control the robot. Default controls:
main.cpp hardware sectionusercontrol() function1790Autonomous.hAfter making changes:
Your code follows a specific flow. Understanding this helps you know where to add new features.
1. Robot Powers On
↓
2. main() runs → Sets up competition callbacks
↓
3. pre_auton() runs ONCE
- Calibrates IMU (required for accurate turns)
- Sets up optical sensor
- Displays status on controller
↓
4. Wait for Competition Switch or Field Control
↓
5a. AUTONOMOUS MODE 5b. DRIVER CONTROL MODE
- Runs for 15 seconds - Runs for 1:45
- Uses runSelectedAutonMode() - Uses usercontrol() loop
- No driver input allowed - Reads joysticks/buttons every 20ms
- Pre-programmed movements - Responds to driver commands
↓ ↓
6. Match Ends → All motors stop
When you add a new motor, you need TWO things:
// In main.cpp - DECLARE the motor (creates it)
motor catapultMotor = motor(PORT10, ratio18_1, false);
// In 1790Common.h - EXTERN the motor (lets other files use it)
extern motor catapultMotor;
Think of it like this: Declaration says "this motor exists," extern says "other files can use this motor."
When multiple motors do the same job, group them:
// Individual motors
motor leftIntakeMotor = motor(PORT9, ratio6_1, false);
motor rightIntakeMotor = motor(PORT3, ratio6_1, false);
// Group them for easier control
motor_group intakeMotors = motor_group(leftIntakeMotor, rightIntakeMotor);
// Now control both at once
intakeMotors.spin(forward); // Both motors spin forward
This is critical for status monitoring. Every motor MUST be added here:
std::vector<MotorInfo> allMotors = {
{&leftFrontMotor, 1},
{&leftRearMotor, 15},
// ... add every motor with its port number
};
This lets your code automatically check for disconnected or overheating motors.
| What You're Adding | Where It Goes | File |
|---|---|---|
| New motor/sensor hardware | Hardware setup section (~line 40) | main.cpp |
| Motor externs | STUDENT EDIT HERE section (~line 18) | 1790Common.h |
| Driver button controls | Inside usercontrol() loop (~line 130) | main.cpp |
| New autonomous routine | Add function after runFarScoreAuton() | 1790Autonomous.h |
| New autonomous mode name | autonModeNames array (~line 92) | main.cpp |
Motors are the core of your robot. Here's how to add new ones for mechanisms like lifts, catapults, or conveyors.
// Add after intakeMotors section (around line 50)
motor conveyorMotor = motor(PORT10, ratio18_1, false); // 18:1 for torque
// Add to allMotors vector for monitoring
std::vector<MotorInfo> allMotors = {
{&leftFrontMotor, 1},
{&leftRearMotor, 15},
{&rightFrontMotor, 8},
{&rightRearMotor, 19},
{&leftIntakeMotor, 9},
{&rightIntakeMotor, 3},
{&conveyorMotor, 10}, // ADD THIS LINE
};
// In STUDENT EDIT HERE section (around line 18)
extern motor leftFrontMotor;
extern motor leftRearMotor;
extern motor_group leftDriveMotors;
extern motor rightFrontMotor;
extern motor rightRearMotor;
extern motor_group rightDriveMotors;
extern motor leftIntakeMotor;
extern motor rightIntakeMotor;
extern motor_group intakeMotors;
extern motor conveyorMotor; // ADD THIS LINE
// In main.cpp, inside usercontrol() while loop (around line 140)
// Set default velocity after motor declaration
conveyorMotor.setVelocity(60, percent); // Slower for control
conveyorMotor.setStopping(hold); // Hold position when stopped
// Button control example - Up/Down on D-pad
if (ControllerDriver.ButtonUp.pressing()) {
conveyorMotor.spin(forward, 60, percent); // Move blocks up
} else if (ControllerDriver.ButtonDown.pressing()) {
conveyorMotor.spin(reverse, 40, percent); // Reverse if needed
} else {
conveyorMotor.stop(hold); // Hold position
}
// In 1790Autonomous.h, inside an auton function
void runNearScoreAuton() {
Brain.Screen.print("Running Near Score");
// Drive to goal
smartDrive.driveFor(forward, 24, inches);
// Run conveyor to score
conveyorMotor.spinFor(forward, 2.0, seconds); // Score for 2 seconds
// Back away
smartDrive.driveFor(reverse, 12, inches);
}
For scoring in the Center Goal's upper section, you might need a lift:
// In main.cpp - Declare all lift motors
motor leftLiftFront = motor(PORT11, ratio18_1, true); // Reversed
motor leftLiftRear = motor(PORT12, ratio18_1, true);
motor rightLiftFront = motor(PORT13, ratio18_1, false);
motor rightLiftRear = motor(PORT14, ratio18_1, false);
// Group for synchronized control
motor_group liftMotors = motor_group(leftLiftFront, leftLiftRear,
rightLiftFront, rightLiftRear);
// Add all four to allMotors vector
{&leftLiftFront, 11}, {&leftLiftRear, 12},
{&rightLiftFront, 13}, {&rightLiftRear, 14},
// In 1790Common.h - Add externs
extern motor leftLiftFront;
extern motor leftLiftRear;
extern motor rightLiftFront;
extern motor rightLiftRear;
extern motor_group liftMotors;
// In usercontrol() - Control with left shoulder buttons
liftMotors.setStopping(hold); // IMPORTANT: Hold prevents lift from falling
liftMotors.setVelocity(50, percent); // Slower for heavy lifts
if (ControllerDriver.ButtonL1.pressing()) {
liftMotors.spin(forward); // Lift up
} else if (ControllerDriver.ButtonL2.pressing()) {
liftMotors.spin(reverse); // Lift down
} else {
liftMotors.stop(hold); // Hold position (prevents drop)
}
coast: Motor spins freely (good for intakes)brake: Motor resists motion (good for drivetrains)hold: Motor actively maintains position (REQUIRED for lifts/arms)Official Docs: vex::motor • motor_group
Digital outputs control pneumatics, LEDs, or relays. They're simple on/off devices.
// In main.cpp - Declare pneumatic solenoid
digital_out blockDescoreArm = digital_out(PORT21, false); // Starts open (false)
// In 1790Common.h - Add extern
extern digital_out blockDescoreArm;
// In usercontrol() - Toggle with X button
static bool clampClosed = false;
static bool prevXState = false;
if (ControllerDriver.ButtonX.pressing() && !prevXState) {
clampClosed = !clampClosed; // Toggle state
blockDescoreArm.set(clampClosed); // true = close, false = open
// Haptic feedback for driver
if (clampClosed) {
ControllerDriver.rumble(".."); // Short rumble = closed
} else {
ControllerDriver.rumble("."); // Single pulse = open
}
}
prevXState = ControllerDriver.ButtonX.pressing(); // Track for next loop
Official Docs: vex::digital_out
| Control | Action | Code Name |
|---|---|---|
| Left Stick Y | Forward / Backward | Axis3 |
| Right Stick X | Turn (Arcade) | Axis1 |
| R1 | Intake IN (hold) | ButtonR1 |
| L2 | Intake OUT (hold) | ButtonL2 |
| R2 (press) | Toggle continuous intake | ButtonR2 |
Useful for precise positioning near Goals:
// Add this in usercontrol() loop
static bool precisionMode = false;
if (ControllerDriver.ButtonLeft.pressing()) {
precisionMode = true;
smartDrive.setDriveVelocity(40, percent); // Half speed
smartDrive.setTurnVelocity(40, percent);
} else {
precisionMode = false;
smartDrive.setDriveVelocity(80, percent); // Full speed
smartDrive.setTurnVelocity(80, percent);
}
Stop intake automatically when Block is detected:
// In usercontrol() - replaces basic R1 control
if (ControllerDriver.ButtonR1.pressing()) {
intakeMotors.spin(forward);
// Stop automatically when a team-color Block is fully loaded (wait up to 5 sec)
if (isTeamColorDetected(5000)) {
intakeMotors.stop(); // Block loaded – stop intake
ControllerDriver.rumble("."); // Success feedback
}
} else if (ControllerDriver.ButtonL2.pressing()) {
intakeMotors.spin(reverse); // Manual outtake
} else {
intakeMotors.stop();
}
Official Docs: smartdrive::arcade
Before every match, you'll select which autonomous routine to run, your alliance color, and starting position.
Use these button combinations on the driver controller:
| Combo | Action | Display Updates |
|---|---|---|
| Up + X | Cycle autonomous mode | "NEAR" → "FAR" → "OFF" |
| Right + Y | Toggle alliance color | "RED" ↔ "BLUE" |
| Down + B | Toggle starting side | "LEFT" ↔ "RIGHT" |
The controller screen shows your current settings:
Line 1: NEAR | RED | LEFT
^^^^ ^^^ ^^^^
Mode Color Side
After making any selection changes, wait 5 seconds. The robot automatically recalibrates the IMU (inertial sensor) to ensure accurate turns. You'll see "WAIT: Calibrating IMU" on the brain screen.
Autonomous is 15 seconds of pre-programmed movement. This section shows you how to create and modify autonomous routines.
Your code has three modes by default:
Let's add a "Park Only" mode for safe points:
// In main.cpp, around line 90
const int numberOfAutonModes = 4; // Changed from 3 to 4
// In main.cpp, around line 93
std::string autonModeNames[numberOfAutonModes] = {
"Disabled",
"Near Score",
"Far Score",
"Park Only" // ADD THIS
};
// Add forward declaration at top (around line 18)
void runNearScoreAuton();
void runFarScoreAuton();
void runParkOnlyAuton(); // ADD THIS
// Add case in switch statement (around line 33)
void runSelectedAutonMode() {
switch (selectedAutonMode) {
case 0:
Brain.Screen.print("Auton Disabled");
wait(15000, msec);
break;
case 1:
runNearScoreAuton();
break;
case 2:
runFarScoreAuton();
break;
case 3: // ADD THIS CASE
runParkOnlyAuton();
break;
default:
Brain.Screen.print("Unknown Auton");
wait(15000, msec);
break;
}
smartDrive.stop();
}
// Add function definition at bottom of file
void runParkOnlyAuton() {
Brain.Screen.print("Park Only");
smartDrive.setDriveVelocity(60, percent);
// Drive straight to Park Zone
smartDrive.driveFor(forward, 48, inches);
// Done - robot is parked
}
Here's a more advanced autonomous that scores multiple Blocks:
void runMultiScoreAuton() {
Brain.Screen.print("Multi-Score Routine");
smartDrive.setDriveVelocity(70, percent);
smartDrive.setTurnVelocity(50, percent);
// 1. Grab pre-loaded Block
intakeMotors.spinFor(forward, 0.5, seconds);
// 2. Drive to nearest Goal
smartDrive.driveFor(forward, 30, inches);
// 3. Turn to face Goal (mirrored for side/color)
smartDrive.turnFor(rightTurnDirection(), 45, degrees);
// 4. Score Block
intakeMotors.spinFor(reverse, 1.0, seconds); // Outtake
// 5. Back up to grab another Block
smartDrive.driveFor(reverse, 20, inches);
// 6. Turn toward second Block
smartDrive.turnFor(leftTurnDirection(), 90, degrees);
// 7. Drive and intake
intakeMotors.spin(forward); // Start intake
smartDrive.driveFor(forward, 24, inches);
wait(500, msec); // Let Block settle
intakeMotors.stop();
// 8. Return to Goal and score again
smartDrive.turnFor(rightTurnDirection(), 90, degrees);
smartDrive.driveFor(forward, 20, inches);
intakeMotors.spinFor(reverse, 1.0, seconds);
// 9. Park
smartDrive.driveFor(reverse, 10, inches);
}
rightTurnDirection() and leftTurnDirection() so your auton works from both sidesSmartDrive uses the inertial sensor for accurate straight lines and turns. This is essential for reliable autonomous.
// Drive 24 inches forward
smartDrive.driveFor(forward, 24, inches);
// Drive 18 inches backward
smartDrive.driveFor(reverse, 18, inches);
// Drive 2 feet forward (same as 24 inches)
smartDrive.driveFor(forward, 2, feet);
// Turn 90 degrees right
smartDrive.turnFor(right, 90, degrees);
// Turn 45 degrees left
smartDrive.turnFor(left, 45, degrees);
// Turn 180 degrees to reverse direction
smartDrive.turnFor(right, 180, degrees);
// Slower for precision near Goals
smartDrive.setDriveVelocity(40, percent);
smartDrive.driveFor(forward, 6, inches); // Careful approach
// Faster for crossing field
smartDrive.setDriveVelocity(90, percent);
smartDrive.driveFor(forward, 48, inches); // Speed run
Sometimes you want to do something WHILE driving:
// Start driving (doesn't wait)
smartDrive.drive(forward, 80, percent);
// Spin intake while driving
intakeMotors.spin(forward);
wait(2000, msec); // Drive and intake for 2 seconds
// Stop both
smartDrive.stop();
intakeMotors.stop();
Use these helper functions so your auton works from any starting position:
// Always turns "right" relative to your starting position
smartDrive.turnFor(rightTurnDirection(), 90, degrees);
// Always turns "left" relative to your starting position
smartDrive.turnFor(leftTurnDirection(), 45, degrees);
These functions automatically flip the turn direction based on:
If your robot doesn't drive straight or turn accurately:
// In main.cpp, around line 60 - measure YOUR robot
double wheelDiameter = 3.25; // Measure wheel size in inches
double wheelBase = 12.25; // Distance between left/right wheels
double trackWidth = 12.25; // Distance between front/rear wheels
smartDrive.driveFor(forward, 48, inches);wheelDiameterOfficial Docs: vex::smartdrive
The optical sensor detects colors - useful for identifying team vs opponent Blocks.
Your code has helper functions in 1790Common.h:
// Returns true if sensor sees your alliance's color
if (isTeamColorDetected()) {
// Do something with team Block
intakeMotors.spin(forward);
}
// Or wait up to 1 second for team color
if (isTeamColorDetected(1000)) {
Brain.Screen.print("Found team Block!");
}
// Returns true if sensor sees opponent's color
if (isOpponentColorDetected()) {
// Reject opponent Block
intakeMotors.spin(reverse);
wait(500, msec);
intakeMotors.stop();
}
// In usercontrol() - replace basic R1 control
if (ControllerDriver.ButtonR1.pressing()) {
intakeMotors.spin(forward);
// Check for opponent Block
if (isOpponentColorDetected()) {
// Reject opponent Block
intakeMotors.spin(reverse, 100, percent);
wait(500, msec); // Reverse for 0.5 seconds
ControllerDriver.rumble("- -"); // Alert driver
}
// Check for team Block loaded
if (isTeamColorDetected()) {
intakeMotors.stop(); // Stop when loaded
ControllerDriver.rumble("."); // Single pulse = success
}
} else {
intakeMotors.stop();
}
void runSmartScoreAuton() {
Brain.Screen.print("Smart Score Routine");
// Approach Block area
smartDrive.driveFor(forward, 24, inches);
// Start intake and look for team color
intakeMotors.spin(forward);
if (isTeamColorDetected(2000)) { // Wait up to 2 seconds
// Found team Block - keep it
wait(500, msec); // Let it settle
intakeMotors.stop();
// Drive to Goal and score
smartDrive.driveFor(forward, 30, inches);
intakeMotors.spinFor(reverse, 1.0, seconds);
} else {
// Didn't find team Block - abort
intakeMotors.stop();
Brain.Screen.print("No team Block found");
}
}
The sensor measures "hue" - a number from 0-359 representing color:
// Get raw hue value
double hue = opticalSensor.hue();
Brain.Screen.print("Hue: %.1f", hue);
// Check if object is close enough
if (opticalSensor.isNearObject()) {
Brain.Screen.print("Object detected");
}
Official Docs: vex::optical
When something goes wrong, start here. Most issues have quick fixes.
Cause: You forgot to add the extern in 1790Common.h
Fix: Add extern motor motorName; in the STUDENT EDIT section of 1790Common.h
Cause: You declared the same motor twice, or didn't match main.cpp and 1790Common.h
Fix: Check that motor names are identical in both files. Check spelling.
Cause: You added a mode name but didn't increase numberOfAutonModes
Fix: Count your mode names and update the number. If you have 4 names, use const int numberOfAutonModes = 4;
Cause: Inertial sensor not connected or wrong port
Fix: Check port 16 wiring. IMU must be firmly clicked in. Try different cable.
Cause: Motors overheating from stalling or high load
Fix:
Cause: Motor unplugged or bad connection
Fix: Reconnect motors on listed ports. Check for damaged cables.
Cause: Motors reversed incorrectly
Fix: In main.cpp, flip the true/false on left or right motors:
// If robot veers right, try reversing left motors
motor leftFrontMotor = motor(PORT1, ratio6_1, true); // Change to true
motor leftRearMotor = motor(PORT15, ratio6_1, true);
Cause: Incorrect wheel diameter setting
Fix: Measure your wheel and update in main.cpp:
double wheelDiameter = 3.25; // Your actual wheel size
Test by commanding 48 inches and measuring. Adjust diameter until accurate.
Cause: IMU not calibrated or wheelBase/trackWidth wrong
Fix:
Cause: Speed too low, wrong direction, or mechanical issue
Fix:
intakeMotors.spin(forward) should pull Blocks inintakeMotors.setVelocity(100, percent);Cause: Too far from object, light not on, or ambient lighting
Fix:
// Ensure light is on (should be in pre_auton)
opticalSensor.setLight(ledState::on);
opticalSensor.setLightPower(100, percent);
// Check if object is near
if (opticalSensor.isNearObject()) {
Brain.Screen.print("Object detected at %.1f hue", opticalSensor.hue());
}
Position sensor 1-2 inches from where Blocks pass.
Cause: Already connected to field control
Fix: Disconnect from field, change settings, wait for IMU calibration, reconnect
Possible causes:
Causes: Too many motors, motors stalling, battery old
Fix:
If you're stuck: