VEXCODE V5 · FULL GUIDE · INTERNAL

VEXcode V5 Guide

Configuration. Code. Calibration. The full workflow for building a competition-ready VEXcode V5 project from scratch. Companion to the architecture reference; use the Setup Guide instead if you just want to import an existing project.

CONTENTSWhat this guide covers

1Starting a new project — Empty template, save, defaults 2Configuring hardware — Devices wizard vs. Path B (manual) 3Understanding the code — the 9-section architecture 4Building, downloading, running — the workflow loop 5Calibration workflow — the practice-session order 6Common errors and fixes — lessons learned the hard way 7Using the dashboard — debugging with live sensor data 8Where to go next — adding subsystems, advanced toolchains 9Blocks vs Text — when to use which, graduation path 10Toolchain progression — Blocks → VEXcode V5 → VS Code

PART 1Starting a new project

  1. Open VEXcode V5 (the standalone IDE — Blocks + Text app, not VS Code)
  2. File → New Text Project → C++
  3. When asked for a template, pick Empty Project (or "Plain C++")
  4. File → Save As, give it a name like Clawbot-2822
  5. The IDE creates main.cpp, vex.h, and (depending on template) robot-config.h/cpp
⚠ Don't pick the "Clawbot Drivetrain" or "Drivetrain" template. Those auto-generate device configurations that conflict with the reference architecture. If you accidentally picked one, see Part 2's Path B section for how to recover.

PART 2Configuring hardware — two paths

VEXcode V5 has two ways to tell the brain about your motors and sensors. Pick one and stick with it — mixing them causes redefinition errors.

AspectPath A: Devices WizardPath B: Manual Code Declaration
HowOpen Devices panel → click + → configure graphicallyWrite motor LeftDrive = motor(PORT1, ratio18_1, false); in main.cpp
Auto-names motors?Yes — e.g., LeftDriveSmart, DrivetrainInertialNo — you name them
GUI port testingYes — click device in panel to testNo — write a test routine in code
Version-control friendlyHidden in project metadataYes — visible in main.cpp
Share across robotsTedious — recreate by clickingYes — paste Section 1
Recommended forSolo students, prototypingTeam projects, competition robots

Path A — Devices wizard step-by-step

The Devices button is in the top of the left sidebar. Click it to open the Devices panel. To add any device, click Add a Device, pick the device type, configure it, and click Done.

Add devices in this order for cleanest results:

  1. Controller — always first, gates everything else
  2. Drivetrain — if your robot has one (do this before adding individual motors so the wizard knows which ports are taken)
  3. Individual smart motors — arm, claw, intake, anything not in the Drivetrain
  4. Smart-port sensors — Distance, Optical, Vision / AI Vision
  5. 3-wire devices — Limit switches, potentiometers, bumpers

1. Adding a Controller

  1. Click Add a DeviceController
  2. Click Done (no other options to set)

Auto-generated code: controller Controller1 = controller(primary);

2. Adding an individual Smart Motor (arm, claw, intake)

  1. Click Add a DeviceMotor
  2. Select the port (1-21). Ports already used by other devices appear grayed out.
  3. Rename the motor (default is Motor1, Motor2, etc.). Use meaningful names like Arm, Claw, Intake.
  4. Pick the cartridge: Red (100 RPM) / Green (200 RPM) / Blue (600 RPM). Must match what's physically in the motor.
  5. Check Reversed if the motor spins the wrong direction (test in driver control; flip if backwards).
  6. Click Done

Auto-generated code: motor Arm = motor(PORT8, ratio36_1, false);

3. Adding a Drivetrain (2-motor or 4-motor)

Only one Drivetrain per project. Picks up ports for both motors plus the IMU in one step.

  1. Click Add a DeviceDrivetrain 2-Motor or Drivetrain 4-Motor
  2. Select the ports for the Left motors (e.g., port 1 for 2-motor; ports 1 and 2 for 4-motor)
  3. Select the ports for the Right motors (e.g., port 10; or 9 and 10)
  4. (Recommended) Click Inertial Sensor and select its port (e.g., 11). Required for IMU-corrected PID autons.
  5. Set Wheel Size (e.g., 4" for Clawbot), Gear Ratio (usually 1:1), and Gear Cartridge (must match physical motors)
  6. Click Done

Auto-generated code:

motor LeftDriveSmart  = motor(PORT1,  ratio18_1, false);
motor RightDriveSmart = motor(PORT10, ratio18_1, true);
inertial DrivetrainInertial = inertial(PORT11);
smartdrive Drivetrain = smartdrive(LeftDriveSmart, RightDriveSmart, 
                                    DrivetrainInertial, 319.19, 295, 40, mm, 1);
Memorize these names. The wizard auto-names everything: motors as LeftDriveSmart / RightDriveSmart, IMU as DrivetrainInertial, smartdrive as Drivetrain. You reference these exact names in your code's usercontrol (for arcade-drive mixing) and pre_auton (for IMU calibration). Spelling them wrong is the #1 cause of build errors when starting out.

4. Adding 3-wire devices (limit switch, potentiometer, bumper, gyro)

3-wire devices plug into the brain's ADI ports (labeled A-H). Same workflow regardless of device type.

  1. Click Add a Device3-Wire Devices
  2. Pick the specific device: Limit Switch, Bumper Switch, Potentiometer, Encoder, Line Tracker, etc.
  3. Select the 3-wire port (A-H). Ports already in use are grayed out.
  4. Rename to something meaningful: ArmTop, ArmBot, ArmPot, FrontBumper, etc.
  5. Click Done

Auto-generated code:

limit ArmTop = limit(Brain.ThreeWirePort.A);
limit ArmBot = limit(Brain.ThreeWirePort.B);
pot   ArmPot = pot(Brain.ThreeWirePort.C);
bumper FrontBumper = bumper(Brain.ThreeWirePort.D);

5. Adding smart-port sensors (Distance, Optical, Vision)

Smart-port sensors are simpler than 3-wire — just port assignment.

  1. Click Add a Device → pick from Distance, Optical, GPS, etc.
  2. Select the smart port (1-21). Avoid ports used by the Drivetrain or individual motors.
  3. Rename to something meaningful: BackDist, ClawOptical
  4. Click Done

Auto-generated code: distance BackDist = distance(PORT5); · optical ClawOptical = optical(PORT4);

6. Adding a V5 Vision Sensor (older) or AI Vision Sensor (new)

Vision sensors require an extra calibration step beyond just picking a port — you train them to recognize colors (and, for AI Vision, AprilTags and AI classifications).

⚠ AI Vision Sensor requires USB-C to computer. Before configuring color signatures, connect the AI Vision Sensor to your computer (not just the brain) with a USB-C cable. The configuration UI uses the live camera feed to let you select colors by clicking on the image.
  1. Click Add a DeviceVision Sensor or AI Vision Sensor
  2. Select the smart port
  3. (AI Vision only) Connect via USB-C to the computer when prompted
  4. The configuration window opens with the live camera feed
  5. Drag a box over a colored object to teach the sensor a Color Signature
  6. (Optional) Add 2+ signatures to create Color Codes (sequences of colors)
  7. (AI Vision only) Toggle AprilTag detection or AI Classifications on/off — no per-tag setup needed, the sensor detects all standard AprilTags
  8. Click Done

Auto-generated code (AI Vision with AprilTags enabled):

aivision AIVision1 = aivision(PORT7, aivision::ALL_AIOBJS,
                              aivision::ALL_TAGS);

See the Vision Sensor + AprilTags page for project ideas and integration patterns once vision is configured.

Editing or deleting devices

After a device is added:

Official VEX references (step-by-step with screenshots)

VEX publishes detailed walkthroughs with screenshots for each device type. Use those when you need the visual reference; come back here for what the wizard produces (the auto-generated names your code uses).

Path B — manual declaration in code

Don't want to type Section 1 by hand? The Code Generator is a wizard that asks about your robot (ports, sensors, mechanisms, controller mapping) and produces the Path B main.cpp for you to paste. Updates live as you change inputs.

Skip the Devices panel entirely. Put all hardware in Section 1 of your main.cpp:

controller Controller1 = controller(primary);

motor LeftDriveSmart  = motor(PORT1,  ratio18_1, false);
motor RightDriveSmart = motor(PORT10, ratio18_1, true);
inertial DrivetrainInertial = inertial(PORT11);

smartdrive Drivetrain = smartdrive(
    LeftDriveSmart, RightDriveSmart, DrivetrainInertial,
    319.19, 320, 40, mm, 1.0);

motor Arm  = motor(PORT8, ratio36_1, false);
motor Claw = motor(PORT3, ratio36_1, false);

limit ArmTop = limit(Brain.ThreeWirePort.A);
limit ArmBot = limit(Brain.ThreeWirePort.B);
pot   ArmPot = pot(Brain.ThreeWirePort.C);

competition Competition;

Motor cartridges — the right value matters

Cartridge codeColorFree-speed RPMBest for
ratio6_1BLUE600 RPMFast drive, intake rollers
ratio18_1GREEN200 RPMMost drives, lifts (stock Clawbot)
ratio36_1RED100 RPMHigh-torque mechanisms (arms, claws)
⚠ Cartridge mismatch is the #1 source of weird auton behavior. If your code says ratio6_1 (600 RPM) but you physically have green cartridges (200 RPM), PID drive distances will be 3x off. Pop a motor cap and check the actual cartridge color before tuning anything.

PART 3Understanding the code — the 9-section architecture

The reference projects organize main.cpp into 9 banner-commented sections. Each section has one job. To find any section, use Ctrl+F and search for SECTION N.

SectionWhat it does
1. HARDWAREMotor/sensor/pneumatic definitions. Only section to edit for port changes.
2. FORWARD DECLSFunction signatures so code can call functions defined later in the file
3-5. SUBSYSTEMSOne section per mechanism (arm, claw, lift, intake, etc.). Tunable constants at top, then init / control / auton API functions
6. DASHBOARD TASKBackground task printing live sensor values to the brain screen during operation
7. AUTONSDrive helpers (pid_drive, pid_turn) + per-auton routines
8. AUTON SELECTORBrain-screen menu — Up/Down cycle, A confirm
9. MAINpre_auton(), autonomous(), usercontrol(), main() — pure orchestration

The two-API pattern (every subsystem)

Every subsystem section exposes two parallel APIs — one for opcontrol, one for autons:

APIPurposeExample (arm)
OpcontrolCalled every usercontrol loop (~50×/sec). Reads buttons, drives motors.arm_control()
Auton APICalled once with target values. Drives motors to target.arm_set_power(80), arm_to_pot_angle(170)
InitCalled once in pre_auton(). Sets brake mode, tares encoder.arm_init()

PART 4Building, downloading, running

  1. Click Build (hammer icon at top, or Ctrl+F5 / Cmd+B). Output panel shows progress.
  2. Read errors top-to-bottom. The FIRST error is almost always the real problem — later errors are often cascading consequences. Fix #1, rebuild, re-read.
  3. Connect V5 brain via USB cable. Brain icon at top of VEXcode turns green when connected.
  4. Pick a slot from the dropdown if you don't want slot 1 (default).
  5. Click Download (arrow icon). Watch the progress bar — takes ~5 seconds.
  6. Press Run on the brain (or controller). The auton selector should appear on the brain screen.
  7. Use UP/DOWN on the controller to cycle autons, A to confirm. Dashboard appears after selection.
✓ Warnings are not errors. If the error count says Errors 0 and you see a yellow triangle ⚠ with a number, those are warnings. The build SUCCEEDED — you can download to the brain. Warnings flag things like unused variables, which don't affect runtime.

PART 5Calibration workflow

Calibration is a one-time-per-robot process. Do it in this order — each step assumes the previous one is correct.

StepWhat you do
1. Driver Control Sanity Push the joysticks. Verify drive direction. Test L1/L2 (arm up/down) and R1 (claw toggle). If anything is backwards — flip the reversed flag (true ↔ false) for the affected motor in Section 1.
2. Pot Preset Calibration (arm) Run the project, watch the brain dashboard. Move the arm by hand to each preset position, read the pot angle from the dashboard, update ARM_DOWN_DEG / ARM_MID_DEG / ARM_HIGH_DEG in Section 3. Rebuild + download.
3. Drive Distance (PID) Run Auton 1 (Drive Test). Should drive 24″ forward, then 24″ back. Measure with tape. If actual ≠ 24″, adjust wheelTravel in Section 1: new = old × (24 / actual)
4. Turn Angle (PID) Run Auton 2 (Square Drill) — 4× (24″ + 90°). Should return roughly to start. Robot ends rotated CW of start → decrease trackWidth. Robot ends rotated CCW → increase trackWidth. Adjust ±10mm at a time.
5. Sensor Auton Mission Run Auton 5 (Sensor Mission). End-to-end test using all sensors. Compare repeatability vs. Auton 4 (time-based Grab and Score) — low battery should especially show the difference.

PART 6Common errors — lessons learned the hard way

These are the 6 errors that real teams hit when first using VEXcode V5 with our architecture. Knowing them in advance saves hours of practice time.

Error messageCause & fix
redefinition of 'Brain' Cause: Your project template (likely Empty Project, our recommended setup) auto-declares Brain in robot-config.cpp, but the reference's brain Brain; line in Section 1 is uncommented — producing a duplicate declaration.
Fix: Comment out the brain Brain; line in Section 1. Reference projects ship with this line already commented out for this exact reason. If your template doesn't auto-declare Brain, uncomment it.
Devices wizard refuses to add a sensor / Devices changes break the build Cause: You deleted the #pragma region VEXcode Generated Robot Configuration lines at the top of main.cpp. The Devices wizard uses those markers to know where to inject auto-generated device code — without them, it doesn't know where to write.
Fix: Re-paste the entire reference file (the pragma region is included at the top). Or manually add this at line 1: #pragma region VEXcode Generated Robot Configuration followed by a matching #pragma endregion VEXcode Generated Robot Configuration a few lines down. Path B users who never plan to touch the Devices wizard can technically run without the pragma, but keeping it costs nothing and preserves the upgrade option.
no matching member function for call to 'spinToPosition' Cause: Used the 5-arg overload with percent as velocityUnits — ambiguous because percent matches multiple enums.
Fix: Use Motor.setVelocity(SPEED, percent); in init, then 3-arg spinToPosition(pos, deg, false) everywhere.
using integer absolute value 'abs' when argument is of floating point Cause: Used abs() on a doubleabs is for ints only.
Fix: Change to fabs() (floating-point absolute).
call to member function 'printAt' is ambiguous Cause: Variadic arg can implicitly convert to bool, matching two overloads.
Fix: Add explicit false as the 3rd argument: Brain.Screen.printAt(10, 30, false, ...).
'LeftDriveA' was not declared Cause: Code uses motor names different from what your Devices wizard auto-generated.
Fix: Either use the wizard's names (likely LeftDriveSmart/RightDriveSmart), or switch to Path B and declare manually.
Motor goes wrong direction in opcontrol Cause: reversed flag set incorrectly.
Fix: Flip the third constructor argument (truefalse) for that motor in Section 1, rebuild.

PART 7Using the dashboard for debugging

The sensor-loaded reference projects include a background dashboard task that prints live sensor values to the brain screen during opcontrol and auton. This is your primary debugging tool.

Sample dashboard output:

IMU heading:    142.3 deg
Arm pot angle:  87.0 deg
Arm top limit:    -
Arm bot limit:    -
Front bumper:     -
Back dist:       780 mm
Claw object:   DETECTED
Optical hue:   165.0 deg
Battery:         82 %

Use it for:

PART 8Where to go next

Adding a new subsystem (the 6-step pattern)

When your robot has a new mechanism (intake, lift, flywheel, etc.):

  1. Add the motor to Section 1 HARDWARE
  2. Add the new function names to Section 2 FORWARD DECLS
  3. Add a new subsystem section (copy an existing one, change the names) — constants at top, then init / control / auton API
  4. Call <name>_init() in Section 9 pre_auton()
  5. Call <name>_control() in Section 9 usercontrol()
  6. Optionally use the auton API from autons in Section 7
Architecture payoff: other sections don't change. Adding a mechanism is localized to one new section + 2 lines in main.

Adding a new auton

In Section 7:

  1. Write the new auton as void auton_my_routine() { ... } using pid_drive, pid_turn, and subsystem auton APIs
  2. In Section 8, add an entry to the autons[] array: {"6. My Routine", auton_my_routine}
  3. Rebuild + download. The new auton appears in the selector.

Migrating to multi-file (when you outgrow single-file)

Once your main.cpp exceeds ~800 lines, consider splitting to multi-file. VEXcode V5 standalone doesn't support multi-file well — you'll need the VEX VS Code Extension (NOT the same as PROS + VS Code; much simpler). Each SECTION becomes its own .cpp + .h file. See the Setup Guide's appendix.

Migrating to PROS + EZ-Template (for competitive autons)

When you need tunable PID (custom kP, kI, kD per auton segment), exit conditions, or odometry, the path is PROS + EZ-Template. VEXcode V5's built-in PID uses VEX-tuned constants you can't change — fine for student-level autons, but tournament-winning autons usually need finer control. The architecture pattern is identical; each section maps to its own file.

Companion resources

PART 9Blocks vs Text — when to use which

VEXcode V5 lets students write in Blocks, Python, or C++. All three use the same Devices wizard, same competition template, and same underlying API. But each has different capabilities — here's when to pick which.

What's the same between Blocks and Text

What Blocks CAN'T do (where the Spartan architecture lives)

FeatureWhy our architecture needs itBlocks status
Function pointersThe auton selector's AutonEntry autons[] array maps names to functions✗ No concept of "function as value"
static file-scope statestatic bool claw_open encapsulates subsystem state✗ All variables are global
const typed constantsconst double ARM_HIGH_DEG = 170; for calibration✗ Variables only, no type-safe consts
printf-style formattingprintAt(x, y, false, "Pot: %6.1f deg", angle) for the dashboard✗ Blocks print does string concat only
Structs / arrays of structsAuton selector entries, sensor pose dataPartial (lists exist, structs don't)
Multi-file projectsSubsystem files via VS Code Extension✗ Single workspace only
Forward declarationsFunctions can call each other in any orderN/A in Blocks; limits complex flow
Asymmetry to know about: Blocks → C++ conversion is built into VEXcode V5 (the Code Viewer shows you the C++ that any Blocks project compiles to). C++ → Blocks conversion is not supported and probably never will be — too many text constructs (pointers, structs, templates, static state) don't have block equivalents.

When to use Blocks

When to use Text C++

The graduation path — Blocks → Text

Students don't have to pick once and stick forever. VEXcode V5 makes the transition explicit:

  1. Write a behavior in Blocks (e.g., "drive forward until limit switch hits")
  2. Open the Code Viewer (View menu) — see the generated C++ side-by-side with your blocks
  3. Note the syntax patterns: Drivetrain.drive(forward), while (!LimitA.pressing()), wait(20, msec)
  4. Create a new Text C++ project and replicate the behavior by typing the patterns
  5. Extend with text-only features: function pointers, static state, structs, multi-file

The Code Viewer is a read-only learning tool — you can't edit the generated C++. Treat it as a Rosetta Stone between the two languages.

Recommendation for coaches

Student profileStart withMove to text when...
No prior programming experienceBlocksComfortable with conditionals + loops in Blocks (1-2 sessions)
Prior Scratch / block-language experienceBlocks for 1 sessionComfortable with Devices wizard + opcontrol
Prior Python / Java / any text languageText C++ directly(already there)
Building a competition robotText C++(already there)
Wants to learn the Spartan architectureText C++(already there)

The Spartan curriculum (reference projects, training exercises, sensor-loaded edition) is text-based by design. Starting in Blocks for the first practice session is fine — but the moment a student wants multiple autons with a selector or soft-limit sensors gating motor commands, the natural next step is text.

PART 10The toolchain progression — Blocks → VEXcode V5 → VS Code

The Spartan curriculum moves students through three programming environments. The progression isn't arbitrary — each step changes exactly one variable at a time. You never have to learn a new language AND new tooling simultaneously.

STAGE 1
VEXcode V5
Blocks
Drag-and-drop visual programming
STAGE 2
VEXcode V5
Text (C++)
Same IDE, real C++ syntax
STAGE 3
VEX VS Code
Extension
Same C++, professional IDE

The single-variable-change rule

TransitionWhat changesWhat stays the same
Blocks → VEXcode V5 TextLanguage (visual → syntax)IDE, Devices wizard, build/download workflow, sensor APIs, competition template
VEXcode V5 Text → VS Code ExtensionIDE (proprietary → professional)Language, sensor APIs, SDK, build process — still VEX C++

What each transition unlocks

Stage 1 → Stage 2: the language transition

The student already knows the Devices wizard, the competition template, and the API. The Code Viewer in Blocks shows the C++ equivalent of every block, so the syntax isn't foreign — it's just a different way to write things they already understand.

What gets unlocked: Function pointers (auton selector), static file-scope state (subsystem encapsulation), const calibration values, printf formatting (dashboard), structs. The Spartan 9-section architecture lives here.

Stage 2 → Stage 3: the tooling transition

The student already knows VEX C++, the SDK, the build/download workflow. Now they keep all of that but get a professional editor.

What gets unlocked: Multi-file projects (separate .cpp files per subsystem), IntelliSense (autocomplete + hover docs), Git integration, AI Copilot, the same tools 75% of professional developers actually use. According to VEX, this transition exists specifically to align with industry tooling.

Why not skip Stage 2 — Blocks straight to VS Code?

Because you'd be changing both variables simultaneously: new language AND new IDE AND new file organization. That's a cliff. Most students fall off it. Stage 2 exists specifically to make each transition survivable. The middle step doesn't need any defense beyond "humans can only learn one new system at a time."

Why VEX themselves designed it this way

VEX retired their old VEXcode Pro V5 (their proprietary text-only IDE) in favor of the VS Code Extension. The thinking is two-fold:

VEXcode Pro V5 was the awkward middle ground that didn't serve either purpose well, so VEX killed it. The Blocks → VEXcode V5 Text → VS Code Extension progression is now the official VEX-recommended path.

What each step costs to gain

StepYou gainYou pay
BlocksVisual flow, zero syntax, parallel hat blocks make multitasking obviousNo function pointers, no encapsulation, no multi-file, no PID tuning
VEXcode V5 TextReal C++, the full Spartan architecture, builds a real engineering skillSingle-file (caps practical size around 500-1000 lines), no version control, no IntelliSense
VS Code ExtensionMulti-file projects, Git, IntelliSense, AI Copilot, industry toolingMore setup steps, harder error messages (the VS Code error UI is less forgiving than VEXcode V5's)

When each student moves up

Most VRC teams will never need Stage 3. VEXcode V5 Text is enough for competition — the entire Spartan architecture, all the reference projects, every Clawbot/Flex/Skimmer example fits in a single main.cpp. VS Code Extension is for students aimed at engineering college or industry careers who want to learn professional tooling. It's optional capability, not required progression. A team can win at States with Stage 2.

What this looks like in practice for our team

PhaseToolReference materials
Week 1 (new students)VEXcode V5 BlocksVEX example projects, Devices wizard
Weeks 2-N (most students)VEXcode V5 TextSetup Guide, this Guide, Code Generator, Clawbot SmartDrive
Advanced students / multi-developer projectsVS Code ExtensionMulti-file editions of reference projects (*-vexcode-project.zip), PROS architecture archive
Last lesson: the best way to learn VEXcode V5 is to break it on purpose. Try changing a cartridge value. See what error you get. Try removing the reversed flag. Watch the motor go the wrong way. Every error you fix on a practice robot is one you won't hit at a tournament.

This site is an informational reference. RECF EN4 prohibits AI-generated content in engineering notebooks and programming code. Rewrite everything in your own words.