Welcome to the VEX Robotics curriculum designed to teach students how to program the VEX V5 system using PROS (Purdue Robotics Operating System). This project provides a modular, beginner-friendly path to learning robotics programming in C++ with hands-on examples. This curriculum works best when worked on with a VEX V5 Clawbot.







It might take a while to create a new project… Having trouble? Check out the official PROS installation guide
When writing code for robots, it is important to have a way to store and use information for things like motor speeds, sensor readings, and button presses.
In C++, the programming language commonly used in VEX Robotics, this is done using variables. A variable is a labeled container where you can store a piece of data to use later.
| Data Type | Example | What It Stores | Example Usage |
|---|---|---|---|
int |
int motorSpeed = 100; |
Whole numbers (positive, negative, or zero) | Motor speed, joystick values |
bool |
bool clawOpen = true; |
true or false |
Is the claw open? |
double |
double wheelCircumference = 25.4; |
Decimal numbers with high precision | Distance traveled in cm |
float |
float armAngle = 90.5; |
Decimal numbers (less precision than double) |
Arm angle in degrees |
To define and initialize variables with a value, you need:
Example:
int motorSpeed = 100; // Create a variable and give it the value 100
motorSpeed = 50; // Change the value to 50
In PROS, motors need a port value to be created. Because these values stay constant with each program, a C++ concept called a macro is created to store the number.
#define ARM_PORT 8
Robots need to make decisions; for example, deciding whether to open or close the claw or to move forward or stop.
In C++, conditional statements help run different code depending on whether certain conditions are true or false.
if StatementRuns a block of code only if a condition is true.
Format:
if (condition) {
// Code runs if condition is true
}
Example:
if (buttonPressed) {
Claw.move_velocity(100); // Open claw
}
If buttonPressed is true, then the claw will open.
else if StatementAdds another condition to check if the first one was false.
Format:
if (condition1) {
// Code runs if condition1 is true
}
else if (condition2) {
// Runs if condition2 is true AND condition1 was false
}
Example:
if (buttonOpen) {
Claw.move_velocity(100); // Open claw
}
else if (buttonClose) {
Claw.move_velocity(-100); // Close claw
}
If buttonOpen is true, then the claw will open. But if that was not true and buttonClose is true, then the claw will close.
else StatementRuns a block of code if none of the previous conditions were true.
Format:
if (condition1) {
// ...
}
else if (condition2) {
// ...
}
else {
// Runs if all above are false
}
Example:
if (buttonOpen) {
Claw.move_velocity(100); // Open claw
}
else if (buttonClose) {
Claw.move_velocity(-100); // Close claw
}
else {
Claw.move_velocity(0); // Stop claw
}
If buttonOpen is true, then the claw will open. But if that was not true and buttonClose is true, then the claw will close. If none of those conditions are true, the claw will not move.
It can be helpful to use a flowchart to plan out the logic of your program before you write the code.
You can use
if, multipleelse ifs, andelsetogether or justifandelse. Typically, when you use anif, you will need to use anelsestatement as well.
It is also important to perform calculations or make decisions based on certain conditions. In C++, this is done with operators, symbols that tell the program what action to perform.
| Arithmetic Operator | Example | Meaning | Example Usage |
|---|---|---|---|
+ |
speed + 10 |
Addition | Increase motor speed |
- |
speed - 5 |
Subtraction | Decrease arm position |
* |
wheelDiameter * 3 |
Multiplication | Calculate total distance |
/ |
distance / time |
Division | Calculate average speed |
% |
count % 2 |
Modulus (remainder) | Check if a number is even or odd |
Example:
int leftSpeed = 50;
int rightSpeed = leftSpeed + 10; // rightSpeed is now 60
Logical operators are used to combine or modify true/false (bool) values. These are useful for checking multiple conditions at once.
| Logical Operator | Example | Meaning | Example Usage |
|---|---|---|---|
&& |
(buttonA && buttonB) |
AND — both must be true | Only move claw if both buttons are pressed |
|| |
(buttonA || buttonB) |
OR — one must be true | Move claw if either button is pressed |
! |
!clawOpen |
NOT — reverse the value | Run code if claw is not open |
Example:
bool armUp = true;
bool clawOpen = false;
if (armUp && !clawOpen) {
// Arm is up AND claw is closed
}
Relational operators compare two values and return true or false.
| Relational Operator | Example | Meaning | Example Usage |
|---|---|---|---|
< |
speed < 100 |
Less than | Check if speed is below a limit |
> |
speed > 0 |
Greater than | Check if robot is moving forward |
== |
count == 5 |
Equal to | Check if a counter has reached a target |
!= |
mode != 1 |
Not equal to | Check if the mode is not 1 |
==is to check if two values are equal.=is for assigning a value to something.
Example:
int speed = 80;
if (speed < 100) {
// Increase speed
}
A while loop repeats as long as a certain condition is true.
Format:
while (condtion) {
// code that repeats while a condition is true
}
Example:
int count = 0 {
while (count < 5) {
count = count + 1;
}
This loop will repeat until the count variable reaches 5.
Sometimes in robotics, a while(true) loop will be used, creating an infinite loop which never ends until the program is stopped or break is used. This is common in robot operator control mode, because the robot needs to keep responding to the controller until the match ends.
Example in PROS:
while(true) {
// Check controller input
// Move motors
pros::delay(20); // Prevent CPU overload
}
Here, the robot keeps running the code inside the loop forever during driver control.
A for loop is used when y ou know exactly how many times you want to repeat something.
It is often used for counting or going through a sequence of numbers.
Format:
for (start; condition; update) {
// Code that repeats
}
Example:
for (int i = 0; i < 5; i++) {
// Run 5 times, i goes from 0 until it isn't less than 5 (4)
}
| Feature | while Loop |
for Loop |
|---|---|---|
| Best for | Repeating until a condition changes | Repeating a set number of times |
| Loop setup style | Condition only | Start, condition, and update in one line |
| Common in PROS | while(true) for continuous robot code |
Rare in main control loop, but useful for timed actions |
Functions let you put actions that you would use repeatedly (like setting the claw speed, or driving forwards or backwards) into named blocks of code.
A function has:
void if nothing)return_type functionName(parameterType1 param1, parameterType2 param2){
//do something here
return value;
}
void setClawSpeed(int rpm) {
Claw.move_velocity(rpm);
}
double average(double a, double b) {
return (a + b) / 2.0;
}
openClaw(), driveStraight()).// Input joystick value, output scaled motor speed
int scaleSpeed(int stick) {
return stick * 2; // example scaling
}
If your function doesn’t need to return anything, use void:
void stopDrive() {
LeftDrive.move_velocity(0);
RightDrive.move_velocity(0);
}
By default, parameters are copied (pass‑by‑value). For large data or when you want to modify the caller’s variable, use a reference (&).
// Pass-by-value (copy):
void setTarget(int target) { /* uses a copy */ }
// Pass-by-reference (can modify original):
void zeroIfSmall(int &value) {
if (value < 10) value = 0; // changes caller's variable
}
Use const & when you won’t modify the input but want to avoid copies:
void printName(const std::string &name) {
// name is read-only here
}
If you call a function before it’s defined, you need a prototype at the top of the file (or in a header).
// Prototype (declaration)
void openClaw();
// Later or in another file (definition)
void openClaw() {
Claw.move_velocity(100);
}
You can reuse a function name as long as the parameter list differs.
void driveForTime(int ms, int rpm);
void driveForTime(int ms); // uses a default speed
void driveForTime(int ms, int rpm) {
LeftDrive.move_velocity(rpm);
RightDrive.move_velocity(rpm);
pros::delay(ms);
stopDrive();
}
void driveForTime(int ms) { // default to 100 rpm
driveForTime(ms, 100);
}
Functions are especially useful in robotics for turning common actions—like reading controller input, spinning motors, or using sensors—into reusable building blocks. This keeps your code clean, consistent, and easier to update.
Below are examples of using functions in PROS to handle common robot tasks.
int getLeftJoystick() {
return Controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
}
bool isButtonPressed(pros::controller_digital_e_t button) {
return Controller.get_digital(button);
}
Example Usage:
int left = getLeftJoystick();
if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_R1)) {
// Do something when R1 is pressed
}
Actuating a Piston (Pneumatics):
void setPiston(bool extended) {
piston.set_value(extended); // true = extend, false = retract
}
Example Usage:
if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_L1)) setPiston(true);
if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_L2)) setPiston(false);
Spinning an Intake Motor (Forward & Backward)
void runIntakeForward(int speed) {
Intake.move_velocity(speed);
}
void runIntakeBackward(int speed) {
Intake.move_velocity(-speed);
}
Example usage:
if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_R1)) runIntakeForward(200); // Forward
else if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_R2)) runIntakeBackward(200); // Reverse
else runIntake(0); // Stop
Preset Scoring Heights & Toggling Through Them
int heightIndex = 0;
const int heights[] = {0, 500, 1000}; // Encoder units for arm positions
void nextHeight() {
heightIndex = (heightIndex + 1) % 3;
Arm.move_absolute(heights[heightIndex], 100); // Move to next preset
}
Example usage:
if (isButtonPressed(pros::E_CONTROLLER_DIGITAL_UP)) nextHeight();
Using a Gyro or Rotation Sensor for Movement
void turnToAngle(double targetAngle) {
while (fabs(Gyro.get_heading() - targetAngle) > 2) {
int direction = (Gyro.get_heading() < targetAngle) ? 1 : -1;
LeftDrive.move_velocity(50 * direction);
RightDrive.move_velocity(-50 * direction);
pros::delay(20);
}
LeftDrive.move_velocity(0);
RightDrive.move_velocity(0);
}
Example Usage:
turnToAngle(90); // Turn to 90 degrees using gyro
You can combine these functions in
opcontrol()orautonomous()to make complex behaviors simple to write and easy to adjust later.






In the beginning of your main.cpp file, there is #include "main.h". Beneath it, please add:
#include "pros/motors.hpp"
#include <cmath>
What are
.hand.hppfiles? Check this out
Then, create macros for your motor ports. The format will be #define WHAT_MOTOR X, with X being the number port on the brain that your motor is connected to.
For the beginner clawbot, you will need a left drivetrain motor, right drivetrain motor, arm motor, and claw motor.
Example:
// change numbers as needed to match with ports
#define LEFT_MOTOR 1
#define RIGHT_MOTOR 10
#define ARM 8
#define CLAW 3
Please use all caps for these macros :)
Beneath the macro declarations, we will create the actual motor and motor group declarations.
For drivetrains, we will create a motor group for each side of the drive train (right/left). In most cases, all other motors will just be singular motors. The format for a motor group will be pros::MotorGroup NameOfGroup({FIRST_MOTOR}, {SECOND_MOTOR}, {THIRD_MOTOR}, ...);. The format for a singular motor will be pros::Motor Name(PORTNAME);.
Example:
pros::MotorGroup LeftDriveSmart({LEFT_MOTOR});
pros::MotorGroup RightDriveSmart({RIGHT_MOTOR});
pros::Motor Arm(ARM);
pros::Motor Claw(CLAW);
After these steps, the beginning of your main.cpp file should look something like this
#include "main.h"
#include "pros/motors.hpp"
#include <cmath>
#define LEFT_MOTOR 1
#define RIGHT_MOTOR 10
#define ARM 8
#define CLAW 3
pros::MotorGroup LeftDriveSmart({LEFT_MOTOR});
pros::MotorGroup RightDriveSmart({RIGHT_MOTOR});
pros::Motor Arm(ARM);
pros::Motor Claw(CLAW);
If you are programming a different robot than the clawbot, your motor and motor group declarations will look different than this. This is just a basic example to help you get started.
Recommended! Set the braking modes to hold for your arm and claw motors. Go to
void initialize()and add these two lines.Arm.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); Claw.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD);It should look like this: ```cpp void initialize() { pros::lcd::initialize(); pros::lcd::set_text(1, “Hello PROS User!”);
pros::lcd::register_btn1_cb(on_center_button); Arm.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); Claw.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); }
Created by Uijin Cho, Dhruv Patel
Suggestions? Create an issue
Created for Robolabs / Dublin Robotics Club