The VEX IQ Brain (2nd Generation) serves as the real-time control unit for motors and sensors, running MicroPython to handle low-level operations.
Specifications
Processor ARM Cortex processor optimized for real-time control
Ports 12 smart ports for sensors and motors (PORT1-PORT12)
Programming MicroPython support with VEX library
Display Built-in touchscreen for status and debugging
System Architecture
The VEX Brain runs a modular Python architecture defined in vex_brain/src/main.py:
Core Modules
CommunicationManager
Handles JSON-based serial communication with the Raspberry Pi.
Implementation (vex_brain/src/main.py:26-60):
class CommunicationManager :
def __init__ ( self ):
self .serial_port = None
self .buffer = bytearray ()
self .message_end = b ' \n '
def initialize ( self ):
self .serial_port = open ( '/dev/serial1' , 'rb+' )
The VEX Brain opens /dev/serial1 for serial communication. This corresponds to the USB connection on the Raspberry Pi side (/dev/ttyACM1).
Message Format :
{
"type" : "scan_service" ,
"data" : {
"speed" : 20
}
}
SensorModule
Manages all sensor initialization and reading.
Port Assignments (vex_brain/src/main.py:63-71):
Sensor Port Variable Name Purpose Inertial Built-in self.inertialHeading (0-360°) Distance PORT7 self.gripper_distanceGripper proximity TouchLED PORT8 self.touchledStatus indicator Distance PORT9 self.base_distanceEnvironment scan Bumper PORT10 self.bumperCollision detection
Key Methods :
get_angle() -> float # Returns 0-360° heading
get_distance(sensor) -> int # Distance in MM
is_bumper_pressed() -> bool # Collision detection
set_color(color: tuple ) # LED status (R,G,B)
LED Color Codes (vex_brain/src/main.py:17-23):
INIT White (255,255,255) System initialization
READY Green (0,255,0) Ready for operation
RUNNING Blue (0,0,255) Process active
WARNING Orange (255,150,0) Caution state
ERROR Red (255,0,0) Error/Emergency stop
ControlModule
Manages all motor operations with safety limits.
Motor Configuration (vex_brain/src/main.py:169-178):
class ControlModule :
def __init__ ( self , sensor_module : SensorModule):
self .base_motor = Motor(Ports. PORT1 , True )
self .shoulder_motor = Motor(Ports. PORT2 , True )
self .elbow_motor = Motor(Ports. PORT3 , True )
self .gripper_motor = Motor(Ports. PORT4 , True )
# Safety torque limits
self .elbow_motor.set_max_torque( 95 , PERCENT )
self .shoulder_motor.set_max_torque( 95 , PERCENT )
Base Motor Control (vex_brain/src/main.py:180-192):
The base motor uses inertial sensor feedback for precise angle positioning:
def move_motor_to_angle ( self , motor , target , speed ):
if motor == self .base_motor:
current = self .sensor_module.get_angle()
delta = (target - current + 360 ) % 360
if delta > 180 :
delta -= 360 # Shortest path
direction = FORWARD if delta > 0 else REVERSE
target_angle = (current + delta) % 360
while abs ( self .sensor_module.get_angle() - target_angle) > 2 :
motor.spin(direction, speed, RPM )
wait( 10 , MSEC )
motor.stop()
SafetyModule
Implements collision avoidance and safe operation protocols.
Shoulder Safety (vex_brain/src/main.py:225-237):
def check_shoulder_safety ( self , speed_forward : int , speed_reverse : int ):
if self .sensor_module.is_bumper_pressed():
self .control_module.general_stop() # Emergency stop
self .sensor_module.set_color( LED_COLORS [ 'ERROR' ])
self .control_module.shoulder_motor.spin( REVERSE , speed_reverse)
wait( 2 , SECONDS ) # Retract
self .control_module.shoulder_motor.stop( HOLD )
return True
else :
self .control_module.shoulder_motor.spin( FORWARD , speed_forward)
self .sensor_module.set_color( LED_COLORS [ 'WARNING' ])
return False
Gripper Current Sensing (vex_brain/src/main.py:239-248):
The gripper uses current feedback to detect when it has grasped an object:
def gripper_action ( self , action , service ):
threshold = 0.5 if service == 'pick' else 0.3
self .control_module.gripper_motor.spin(
FORWARD if action == 'open' else REVERSE , 20
)
if self .control_module.get_current( self .control_module.gripper_motor) > threshold:
self .control_module.gripper_motor.stop(
HOLD if service == 'pick' else BRAKE
)
return True
PerceptionModule
Processes sensor data for object detection during scanning.
Distance Processing (vex_brain/src/main.py:111-122):
def process_sensor_distance ( self , sensor , min_d , max_d ):
dist = self .sensor.get_distance(sensor)
if min_d <= dist <= max_d:
self .current_object_size = self .sensor.get_object_size(sensor)
self .object_detected = True
self .sensor.set_color( LED_COLORS [ 'READY' ]) # Green
else :
self .current_object_size = 0
self .object_detected = False
self .sensor.set_color( LED_COLORS [ 'RUNNING' ]) # Blue
return {
'distance' : dist,
'size' : self .current_object_size,
'detected' : self .object_detected
}
MappingModule
Tracks detected objects during 360° scan.
Object Tracking (vex_brain/src/main.py:131-165):
class MappingModule :
def __init__ ( self ):
self .objects_map = []
self .current_object = ( 0.0 , 0.0 , 0 , 0 , False )
def process_object_detection ( self , angle , size , dist ):
if size > 0 :
if not self .current_object[ 4 ]: # Start tracking
self .current_object = (angle, angle, size, dist, True )
else : # Update tracking
self .current_object = (
self .current_object[ 0 ],
angle,
max ( self .current_object[ 2 ], size),
self .current_object[ 3 ],
True
)
elif self .current_object[ 4 ]: # End tracking
self ._save_object(angle)
Each detected object is stored with:
center_angle: Center of object in degrees
width: Angular width of object
distance: Distance in mm
max_size: Maximum sensor reading
Services
The VEX Brain responds to service requests from the Raspberry Pi.
Check Service
Verifies all sensors and motors are installed.
Usage :
# Send from Raspberry Pi
send_message( 'check_service' , {})
# Response
{ 'type' : 'check_service' , 'data' : { 'state' : 'approved' }}
Safety Service
Executes safety initialization sequence:
Raise shoulder until bumper pressed
Retract shoulder
Open gripper fully
Implementation (vex_brain/src/main.py:299-316):
Scan Service
Performs 360° rotation while detecting objects.
Parameters :
{ 'speed' : 20 } # RPM for base rotation
Process (vex_brain/src/main.py:318-335):
Start base rotation
Continuously check distance sensor (50-345mm range)
When object detected, pause for 2 seconds
Send real-time detection data to Raspberry Pi
Continue until 360° complete
Return complete objects map
Real-time Message (vex_brain/src/main.py:378-383):
{
"type" : "scan_service" ,
"data" : {
"state" : "detected" ,
"angle" : 127.5 ,
"distance" : 180 ,
"size" : 342
}
}
Pick/Place Service
Executes picking and placing operations.
Base Movement :
{ 'joint' : 'base' , 'angle' : 90 , 'speed' : 30 }
Arm Movement :
{ 'joint' : 'arm' , 'distance' : 180 , 'action' : 'pick' }
{ 'joint' : 'arm' , 'distance' : 180 , 'action' : 'place' }
{ 'joint' : 'arm' , 'action' : 'up' }
Gripper Control :
{ 'joint' : 'gripper' , 'action' : 'close' }
{ 'joint' : 'gripper' , 'action' : 'open' }
Programming Environment
VEX Code Studio
The VEX Brain is programmed using VEX Code Studio with Python support.
Project Configuration (.vscode/vex_project_settings.json):
{
"project" : {
"name" : "robotic_arm" ,
"platform" : "IQ2" ,
"language" : "python"
}
}
Uploading Code
Connect VEX Brain
Connect VEX Brain to computer via USB cable
Open VEX Code Studio
Open arm_system/vex_brain/src/main.py in VEX Code Studio
Build and Download
Click “Download” to upload the program to the VEX Brain
Run Program
The program starts automatically when serial connection is established
Main Loop
The VEX Brain runs a continuous message processing loop (vex_brain/src/main.py:488-505):
def run ( self ):
self .comms.initialize()
self .sensor.set_color( LED_COLORS [ 'INIT' ]) # White LED
while True :
try :
msg = self .comms.read_message()
if msg:
self .process_message(msg)
# Execute active services
if self .states[ 'check_active' ]:
self .run_service( 'check' )
if self .states[ 'safety_active' ]:
self .run_service( 'safety' )
if self .states[ 'scan_active' ]:
self .run_service( 'scan' )
except Exception as e:
self .sensor.print_screen( f "Error: { str (e)[: 20 ] } " , 1 , 95 )
self .control.general_stop()
Debugging
Screen Output
Use the built-in screen for debugging:
self .sensor.clear_screen()
self .sensor.print_screen( "Status: OK" , x = 1 , y = 1 )
LED Status
Monitor the TouchLED on PORT8 for system status:
White : Starting up
Green : Ready and waiting
Blue : Scanning active
Orange : Moving arm
Red : Error or collision detected
Next Steps
Sensor Details Learn about sensor configuration and calibration
Wiring Guide Complete port assignments and connections
Communication Protocol Understand the serial communication protocol