Start with what you need to know about the world. The answer leads to the sensor type. This is THE flowchart to consult before adding any sensor to the bot.
flowchart TD
Start([What do you need
the robot to sense?]) --> Q1{What kind of
question?}
Q1 -->|"Is something there?"| Q2{Is it touching
the robot?}
Q1 -->|"Where is something?"| Q3{Single object
or field-wide?}
Q1 -->|"How much have I rotated?"| Q4{Joint angle
or chassis heading?}
Q1 -->|"What color is this?"| Optical[Optical sensor
get_hue plus get_proximity]
Q2 -->|"Yes, touching"| Discrete[Limit switch
OR bumper switch]
Q2 -->|"No, nearby (β€2m)"| Distance[Distance sensor
time-of-flight, 0-2000mm]
Q3 -->|"Object close-by"| Distance
Q3 -->|"Object across field"| AIVision[AI Vision
AprilTag detection]
Q3 -->|"Robot position on field"| GPS[GPS Sensor
field strip required]
Q4 -->|"Mechanism rotation"| Rotation[Rotation sensor
0.001 deg resolution]
Q4 -->|"Chassis heading"| IMU[Inertial Sensor IMU
heading + acceleration]
style Start fill:#1e293b,stroke:#22d3ee,stroke-width:2px,color:#e2e8f0
style Q1 fill:#fbbf24,color:#0f172a,stroke:#fbbf24
style Q2 fill:#fbbf24,color:#0f172a,stroke:#fbbf24
style Q3 fill:#fbbf24,color:#0f172a,stroke:#fbbf24
style Q4 fill:#fbbf24,color:#0f172a,stroke:#fbbf24
style Discrete fill:#0c4a6e,color:#e2e8f0,stroke:#22d3ee
style Distance fill:#0c4a6e,color:#e2e8f0,stroke:#22d3ee
style Optical fill:#0c4a6e,color:#e2e8f0,stroke:#22d3ee
style AIVision fill:#3f1d77,color:#e2e8f0,stroke:#a78bfa
style GPS fill:#3f1d77,color:#e2e8f0,stroke:#a78bfa
style Rotation fill:#0c4a6e,color:#e2e8f0,stroke:#22d3ee
style IMU fill:#0c4a6e,color:#e2e8f0,stroke:#22d3ee
pros::Vision) but does not include
aivision.hpp. The pros::AIVision class shown below
ships in PROS 4.2+ β until you upgrade your kernel, use VEXcode V5 for
AprilTag work, or substitute the legacy pros::Vision for
color-signature detection.
Most new V5RC teams either skip sensors entirely (everything on motor encoders) or try to install everything at once and end up debugging six things in parallel. Both paths waste competition season.
The right approach: build the sensor stack incrementally. Introduce each sensor when the team is ready to use the data it provides, and after the previous tier is reliable. This guide gives you that order, the testing patterns, and the practical mounting decisions you make once and live with for the season.
| Priority Order | Which sensors to add first, with a rationale for each tier. |
| Onboarding Phases | Roughly how to phase sensor introduction across early/mid/late season. |
| V5 Brain Screen Calibration | The PROS pros::lcd and pros::screen APIs you use to display sensor values for testing — the same screen you'll stare at during pit time. |
| Per-Sensor Calibration Patterns | What to print, what to look for, what bad-vs-good looks like for each sensor type. |
| V5 Brain Placement | Where to mount the Brain on the robot for code uploads, auton selection, and driver visibility. |
| New Team Checklist | A tournament-day checklist that catches the things that bite first-year teams. |
This guide assumes VS Code + PROS + EZ-Template. Code examples are PROS C++. We don't cover Blocks. EZ-Template integration patterns are shown where relevant; LemLib equivalents are noted.
Smart Port. Required for any chassis library (EZ-Template, LemLib, OkapiLib). Provides heading, rotation, pitch/roll. Without an IMU, you cannot use EZ-Template's turn PID, swing, or odometry. Install this first, before any auton work begins.
3-Wire ADI ports. Cheapest sensor VEX makes. Install at the end-of-travel of every motorized mechanism (lift, arm, tilter). Protects mechanisms from motor stalls and over-travel damage. Two switches on a lift is more impactful than one Optical Sensor. Add these as soon as you have any mechanism beyond the drivetrain.
3-Wire ADI port. Add when you have a mechanism with multiple discrete positions (load, score-low, score-mid, score-high). Enables one-button macros for the driver and reliable arm presets for auton. Particularly valuable when the mechanism could be back-driven (a Smart Motor encoder loses its zero if external force rotates the shaft while the brain is off; a potentiometer remembers).
Smart Port. Add when you start using EZ-Template's odometry features or LemLib's tracking. Tracking wheels with V5 Rotation Sensors are how serious teams get repeatable autons. The IMU gives you heading; tracking wheels give you X/Y position. Together they make EZ-Template's pid_odom_set or LemLib's moveToPoint work.
Smart Port. Add when your robot needs to know what it just picked up — in Override, this means cup orientation (transparent vs opaque half) and pin half color (red, blue, or yellow). The cup orientation use case is unique to Override and is the highest-leverage application; see sensors-optical § Override Use Cases.
Smart Port. Both are advanced. AI Vision sees AprilTags and AI-classified objects in the field; GPS tracks absolute position from field code strips. Install only after Tiers 1–5 are working reliably. These are skills-run-grade upgrades that take significant tuning. See the AI Vision deep dive and the GPS Sensor deep dive.
Without an IMU, your robot cannot turn to a heading reliably. EZ-Template's pid_turn_set and pid_odom_set require it. Encoder-only turning drifts severely on coast wheels. The IMU is the foundation everything else builds on. Skipping it makes every higher tier brittle.
A bumper switch costs $10 for a 2-pack. A burned-out V5 Smart Motor from a stalled mechanism costs $40. A broken arm at a competition costs your team a match. Switches are insurance with the highest ROI of any sensor. They also teach new programmers about digital input, which is the simplest sensor type to reason about.
Both require careful mounting (height, orientation, occlusion). Both have failure modes that look like working software (GPS reads stale values when occluded; AI Vision misses tags in poor lighting). A new team installing these before mastering simpler sensors will spend hours debugging "why doesn't my robot turn to the tag" when the issue is a wobbly chassis. Install them when your auton is already 80% reliable on Tiers 1–4.
EZ-Template's example project structure already reflects this priority. The chassis constructor takes the IMU port (Tier 1) as a required parameter. Tracking wheels (Tier 4) are optional — you can use EZ-Template without them. Higher-tier sensors are not part of EZ-Template at all; you compose them into your code as separate pros::Optical, pros::AIVision, pros::Gps instances.
get_value() returns 1 when released, 0 when pressed. Easy bug, hard to spot if you don't print to the screen.pid_odom_set). Auton in absolute coordinates, not relative motions.Pick the highest-leverage sensor you don't have, install it, ship it. The order above is ideal but not gospel. A Tier 5 Optical Sensor can deliver more match value than a Tier 4 tracking wheel for a specific game. Use judgment.
The only true rule: do not install Tier 6 sensors before Tier 1–2 are working. A new team trying GPS-corrected auton without an IMU has not skipped to the fun part — they've skipped to a debugging nightmare.
PROS gives you two ways to draw to the V5 Brain screen:
pros::lcd (LLEMU) | Legacy LCD Emulator. 8 lines of plain text. Dead simple. Use this for sensor calibration prints. Header: pros/llemu.hpp (included by default). |
pros::screen | Richer graphics: rectangles, circles, color, custom fonts, custom positions. Use for auton selectors and dashboards. Header: pros/screen.hpp. |
| LVGL | Full-featured graphics library, accessible by including pros/apix.h. Powerful but complex. Conflicts with pros::lcd: per the PROS docs, you cannot use LVGL and LLEMU at the same time. Avoid for new teams. |
For sensor testing, use pros::lcd. It's 8 lines, plenty of space, and you can write to a specific line by number.
| Tier 1 — IMU |
get_heading() – should be 0–360, never PROS_ERR.get_rotation() – unbounded; resets to 0 only on tare_rotation().is_calibrating() – should print "false" after ~2s startup.
|
| Tier 2 — Switches |
get_value() – 0 when pressed, 1 when released.Print as "PRESSED" / "RELEASED" for human readability, not raw 0/1. |
| Tier 3 — Potentiometer |
get_angle() – 0–333° (V2). Watch for the deadband — should never see jumps from 333 to 0 during normal mechanism travel.Show alongside named positions: "Pot: 45.2 deg (LOAD)" or similar. |
| Tier 4 — Rotation Sensor / Tracking |
Chassis pose: chassis.odom_x_get(), odom_y_get(), odom_theta_get() (EZ-Template). Push robot manually, watch values track.For LemLib: chassis.getPose().
|
| Tier 5 — Optical Sensor | Hue, saturation, brightness, proximity. All four together. Saturation tells you the LED is working; proximity tells you the object is close enough; hue and brightness tell you what you're looking at. |
| Tier 6 — AI Vision & GPS | AI Vision: tag count, first tag's ID and position. GPS: X, Y, heading, error. Use 4–5 lines for these because there's more data per sensor. |
If your driver code prints to the brain screen, the calibration task and driver code can compete for the same lines. Use a convention: dedicate specific lines to specific roles.
EZ-Template includes a built-in auton selector that uses the brain screen + the bottom row of brain buttons. Per EZ-Template docs:
Bonus per EZ-Template: you can map external limit switches as page-up / page-down buttons via limit_switch_lcd_initialize(). Useful for Override pre-match config.
| Calibration trigger | Automatic on power-up. Takes ~2 seconds. Per VEX docs: do not move the robot during calibration. EZ-Template handles this in chassis.drive_imu_reset() at the start of auton. |
| What good looks like | Heading reads consistently as you rotate the robot manually. Heading at start position is 0 or whatever you set. Heading does NOT drift while the robot sits still. |
| What bad looks like | Heading drifts > 1° per minute while sitting still — usually a hardware issue or calibration during motion. Sudden jumps in heading — a hard impact or the IMU coming loose. Heading reads PROS_ERR or 0 forever — sensor not connected or in wrong port. |
| Pit-time check | Read brain screen IMU value. Note it. Pick up robot, rotate 90° by hand, set down. Verify the heading changed by ~90°. |
PROS API to know:
No analog calibration needed — switches are digital. The "calibration" is verifying mechanical alignment.
| What good looks like | Switch reads RELEASED (1) when mechanism is anywhere except the limit. Reads PRESSED (0) only when mechanism reaches the limit. State change is crisp, not flickering. |
| What bad looks like | Reads PRESSED constantly — switch held down by zip-tie or installed too tight. Reads RELEASED constantly — switch arm bent away from contact path, or wrong port. Flickers between 0 and 1 — loose cable connection or marginal mechanical contact. |
| Pit-time check | Move mechanism manually through full range. Confirm switch reads RELEASED everywhere except at the limit, where it reads PRESSED. Wiggle the cable connector to confirm no flicker. |
| What good looks like | Angle changes smoothly as the mechanism moves. No sudden jumps. Mechanism's lower physical limit reads a consistent angle, ditto for upper. The 27° deadband is OUTSIDE normal travel. |
| What bad looks like | Angle jumps from 333 to 0 mid-travel — mechanism rotates through the deadband. Re-orient the pot body using the arc slots. Angle reads identical at two clearly different mechanism positions — pot is slipping on its shaft (loose grub screw or stripped D-hole). Angle changes when you wiggle the cable but not the mechanism — intermittent connection. |
| Pit-time check | Move mechanism to known positions (down, mid, up). Confirm pot angle matches your stored constants for those positions. Re-record if values shifted. |
Calibration utility code:
See the dedicated Optical Sensor mounting section. Summary:
initialize().See the AI Vision Sensor code section. Summary:
aivision.enable_detection_types(pros::AivisionModeType::tags).set_tag_family().| What good looks like | X and Y change as you push the robot around the field. Heading is stable when sitting still. Error reads small (< 0.05m typically). |
| What bad looks like | X and Y stuck at 0.0 — sensor cannot see field code (occluded, wrong height, or no field strips). Wild X/Y jumps — sensor too close to wall, or partial occlusion. Error > 0.5m — sensor is barely seeing the strips. Adjust position. |
| Pit-time check | Place robot at known field position. Read X and Y. Should match within a few cm of expected. Rotate robot 90°; heading should change ~90°. |
Calibration sequence at a competition:
The USB-C port should be reachable WITHOUT removing any structural element of the robot. If you have to take off a cover, unmount a battery, or remove an arm to plug in your laptop, you will hate every code upload of the season — and you upload code dozens of times per practice. Mount the brain so the USB-C side faces an open edge of the robot.
The screen needs to be visible from a standing position so the team can read sensor calibration values during pit time. It also needs to be tappable for auton selection at the start of every match. Mount the touchscreen facing up or sideways at a height between waist and chest.
The driver should be able to glance at the brain screen during a match for status info (battery, mechanism state). This is less critical than 1 and 2, but matters for high-level driver skills runs. If brain orientation forces the driver to bend down to read the screen, they won't use the screen during matches.
The brain should not be on the front-most or outer-most plane of the robot where it'll take direct hits. Recess it inside the chassis frame, or behind structural members. Brain damage from collisions is rare but devastating.
The brain has cables going in many directions: motors front and rear, sensors all over, controller radio out the back. Place the brain centrally (not at one corner) so cable runs are short and there's less strain on connectors.
| Robot doesn't move in opcontrol | Check: battery charged? Brain on? Code running (PROS terminal shows output)? Controller paired? Any motor temp errors on screen? |
| Robot turns the wrong way in auton | IMU heading is reversed. Check if your motor port directions match your IMU mounting orientation. EZ-Template lets you negate motor ports in the chassis constructor. |
| Auton starts then stops immediately | Often a switch reading TRUE when it shouldn't. If your auton has "wait until switch released" logic, a stuck switch hangs you. Check switch states on screen. |
| Mechanism doesn't reach correct position | Pot calibration drifted, or pot is in deadband. Re-record current angles for known positions, update constants. |
| Auton ends too early / runs too long | EZ-Template motion exit timeouts wrong, or sensor-triggered exit fired prematurely. Check brain screen during a test run to see what fired when. |
| Sensor reads PROS_ERR | Almost always wrong port number or unplugged cable. Verify against your subsystems.cpp port assignments. |
Most V5RC matches are won by reliability, not by elaborate code. A simple auton with switch-zeroed mechanisms and pot-feedback positioning beats a complex GPS-AI-Vision auton that fails 30% of the time. Build sensors in the order this guide suggests, calibrate every pit visit, and your match performance will become consistent.
The team next to you with the AprilTag-corrected vision auton is impressive. The team that wins their division is the one whose limit switches always work.