Skip to main content

Overview

The ControlModule class provides a unified interface for controlling all motors on the VEX IQ robotic arm. It manages four motors (base, shoulder, elbow, gripper) with methods for rotation control, current monitoring, and emergency stops. Source: ~/workspace/source/arm_controller/src/main.py:219

Constructor

__init__()

Initializes all motor hardware components with their port configurations.
control = ControlModule()
Initialized Motors:
base_motor
Motor
Rotates the entire arm base for horizontal scanningPort: Ports.PORT1
Reversed: True (motor direction inverted)
shoulder_motor
Motor
Controls shoulder joint for vertical arm movementPort: Ports.PORT2
Reversed: True
elbow_motor
Motor
Controls elbow joint for reach extensionPort: Ports.PORT3
Reversed: True
gripper_motor
Motor
Opens and closes gripper for object manipulationPort: Ports.PORT4
Reversed: True
All motors are configured with reversed=True to standardize positive rotation direction across the arm.
Source: main.py:220

Motor Rotation Methods

rotate_motor_forward(motor: Motor, speed: int)

Rotates specified motor in the forward direction at given speed.
# Rotate base motor for scanning
control.rotate_motor_forward(control.base_motor, 20)

# Raise shoulder
control.rotate_motor_forward(control.shoulder_motor, 60)
motor
Motor
required
Motor object to rotate. Use one of:
  • control.base_motor
  • control.shoulder_motor
  • control.elbow_motor
  • control.gripper_motor
speed
int
required
Rotation speed in RPM (Revolutions Per Minute)
  • Range: 1-100 RPM (typical)
  • Low speeds (1-30): Precise control, scanning
  • Medium speeds (30-70): Normal operation
  • High speeds (70-100): Rapid movement
Motor continues rotating until stopped or reversed.
Motor will run indefinitely at specified speed. Always call general_stop() or monitor safety conditions.
Source: main.py:227

rotate_motor_reverse(motor: Motor, speed: int)

Rotates specified motor in the reverse direction at given speed.
# Lower shoulder
control.rotate_motor_reverse(control.shoulder_motor, 10)

# Open gripper
control.rotate_motor_reverse(control.gripper_motor, 20)
motor
Motor
required
Motor object to rotate (same as forward method)
speed
int
required
Rotation speed in RPM (same range as forward)
Typical Reverse Operations:
  • Base: Counter-clockwise rotation
  • Shoulder: Lowering arm
  • Elbow: Retracting arm
  • Gripper: Opening claws
Source: main.py:230

Motor Monitoring

get_current_motor(motor: Motor)

Reads the electrical current draw of the specified motor.
current = control.get_current_motor(control.gripper_motor)
if current > 0.3:
    print("Gripper has gripped object!")
    control.general_stop()
motor
Motor
required
Motor object to monitor
return
float
Current draw in amperes (A)
  • Idle: ~0.05A
  • Light load: 0.1-0.2A
  • Heavy load: 0.3-0.5A
  • Stall: 0.6A+
Use Cases: Source: main.py:234

Emergency Stop

general_stop()

Immediately stops all motors on the robotic arm.
# Emergency stop
control.general_stop()
Critical safety method. Called in emergency situations, errors, or task completion.
Stopped Motors:
  1. Base motor
  2. Shoulder motor
  3. Elbow motor
  4. Gripper motor
Behavior:
  • Stops motors immediately (not gradual deceleration)
  • Motors enter brake mode (hold position)
  • No motor movement until new rotation command
Common Triggers:
  • Bumper sensor activation
  • Exception handling
  • Scan completion
  • Safety check failure
  • User stop command
Example Safety Pattern:
try:
    # Perform operation
    control.rotate_motor_forward(control.base_motor, 20)
    # ... operation code ...
    
except Exception as e:
    print(f"Error: {e}")
    control.general_stop()  # Emergency stop
    
finally:
    control.general_stop()  # Ensure stopped
Source: main.py:238

Hardware Verification

check_motors()

Verifies that all motors are properly installed and responsive.
if control.check_motors():
    print("All motors operational")
else:
    print("ERROR: Motor installation issue")
return
bool
Returns True if all motors installed, False if any motor missing or unresponsive
Checked Motors:
  • Base motor (Port 1)
  • Shoulder motor (Port 2)
  • Elbow motor (Port 3)
  • Gripper motor (Port 4)
Use Before:
  • Starting any motor operations
  • System initialization
  • After physical maintenance
Source: main.py:244

Port Configuration Summary

MotorPortDirectionPrimary Function
BasePORT1ReversedHorizontal rotation for scanning
ShoulderPORT2ReversedVertical arm positioning
ElbowPORT3ReversedArm reach extension
GripperPORT4ReversedObject grasping

Motor Speed Guidelines

Base Motor (Scanning)

# Slow scan (high precision)
control.rotate_motor_forward(control.base_motor, 10)

# Normal scan
control.rotate_motor_forward(control.base_motor, 20)

# Fast scan (lower precision)
control.rotate_motor_forward(control.base_motor, 40)
Recommended: 15-25 RPM for object detection

Shoulder Motor (Safety Critical)

# Safety check (with bumper monitoring)
control.rotate_motor_forward(control.shoulder_motor, 60)

# Slow recovery after bumper hit
control.rotate_motor_reverse(control.shoulder_motor, 10)
Recommended:
  • Normal: 40-60 RPM
  • Recovery: 5-15 RPM

Gripper Motor (Precision)

# Close gripper with current monitoring
control.rotate_motor_forward(control.gripper_motor, 20)
while control.get_current_motor(control.gripper_motor) < 0.3:
    time.sleep(0.05)
control.general_stop()
Recommended: 15-25 RPM to avoid crushing objects

Complete Usage Examples

Initialization and Hardware Check

from vex import *
import time

# Initialize control module
control = ControlModule()

# Verify all motors installed
if not control.check_motors():
    print("ERROR: Motors not installed properly")
    raise Exception("Hardware check failed")

print("All motors operational")

Environmental Scan

def perform_scan(control, sensor):
    """Rotate base 360° for scanning"""
    
    # Start rotation
    control.rotate_motor_forward(control.base_motor, 20)
    
    start_angle = sensor.get_angle()
    accumulated_rotation = 0
    last_angle = start_angle
    
    while accumulated_rotation < 360:
        current_angle = sensor.get_angle()
        
        # Calculate delta with wraparound
        delta = current_angle - last_angle
        if delta > 180:
            delta -= 360
        elif delta < -180:
            delta += 360
            
        accumulated_rotation += abs(delta)
        last_angle = current_angle
        
        time.sleep(0.05)  # 20Hz update
    
    # Stop when complete
    control.general_stop()
    print("Scan complete")

Safety-Monitored Shoulder Movement

def raise_shoulder_safely(control, sensor):
    """Raise shoulder with bumper monitoring"""
    
    control.rotate_motor_forward(control.shoulder_motor, 60)
    
    while True:
        # Check bumper every cycle
        if sensor.is_bumper_pressed():
            # Emergency stop
            control.general_stop()
            sensor.set_color((255, 0, 0))  # Red error
            
            # Reverse briefly
            control.rotate_motor_reverse(control.shoulder_motor, 10)
            time.sleep(2)
            control.general_stop()
            
            print("Bumper collision detected")
            return False
        
        time.sleep(0.02)  # 50Hz safety check
    
    return True

Current-Monitored Gripper Control

def close_gripper(control):
    """Close gripper until object gripped"""
    
    control.rotate_motor_forward(control.gripper_motor, 20)
    
    max_time = 5  # 5 second timeout
    start_time = time.time()
    
    while time.time() - start_time < max_time:
        current = control.get_current_motor(control.gripper_motor)
        
        if current > 0.3:
            control.general_stop()
            print("Object gripped successfully")
            return True
        
        time.sleep(0.05)
    
    # Timeout - no object
    control.general_stop()
    print("No object detected in gripper")
    return False

def open_gripper(control):
    """Open gripper fully"""
    control.rotate_motor_reverse(control.gripper_motor, 20)
    time.sleep(1.5)  # Time to fully open
    control.general_stop()

Coordinated Multi-Motor Movement

def position_arm(control, base_angle, shoulder_angle, elbow_angle):
    """Move multiple motors to target positions"""
    
    try:
        # Start all motors
        control.rotate_motor_forward(control.base_motor, 30)
        control.rotate_motor_forward(control.shoulder_motor, 40)
        control.rotate_motor_forward(control.elbow_motor, 30)
        
        # Wait for positioning (simplified)
        time.sleep(2)
        
        # Stop all
        control.general_stop()
        print("Positioning complete")
        
    except Exception as e:
        print(f"Error during positioning: {e}")
        control.general_stop()  # Emergency stop
        raise

Safety Integration

The ControlModule is used by SafetyModule for critical safety checks:
# From SafetyModule (main.py:254)
class SafetyModule:
    def check_shoulder_safety(self) -> bool:
        if self.sensor_module.is_bumper_pressed():
            self.control_module.general_stop()  # Emergency stop
            self.control_module.rotate_motor_reverse(
                self.control_module.shoulder_motor, 10
            )
            time.sleep(2)
            self.control_module.general_stop()
            return True
        return False
    
    def check_gripper_safety(self) -> bool:
        gripper_current = self.control_module.get_current_motor(
            self.control_module.gripper_motor
        )
        self.control_module.rotate_motor_forward(
            self.control_module.gripper_motor, 20
        )
        
        if gripper_current > 0.3:
            self.control_module.general_stop()
            return True
        return False

Build docs developers (and LLMs) love