Skip to main content

Overview

The SafetyModule class provides hardware validation and emergency safety mechanisms for the robotic arm controller. It performs sequential safety checks on critical components and implements immediate stop capabilities to prevent hardware damage. Location: arm_controller/src/main.py:254

SafetyModule Class

main.py
class SafetyModule:
    def __init__(self, sensor_module: SensorModule, control_module: ControlModule):
        self.sensor_module = sensor_module
        self.control_module = control_module
        self.error_count = 0
        self.error_threshold = 3
Dependencies:
  • SensorModule: Sensor interface for bumper, distance, and LED control
  • ControlModule: Motor control for emergency stop and safety movements
Error threshold is set to 3 consecutive errors before system halt. This parameter is currently tracked but not actively enforced in safety checks.

Sensor Safety Checks

Hardware Validation

Check Motors

main.py
def check_motors(self):
    return self.control_module.check_motors()
Validates all four motors are installed and operational:
  • Base motor (PORT1)
  • Shoulder motor (PORT2)
  • Elbow motor (PORT3)
  • Gripper motor (PORT4)
Returns: True if all motors pass, False otherwise

Check Sensors

main.py
def check_sensors(self):
    return self.sensor_module.check_sensors()
Validates critical sensors are installed:
  • Base distance sensor (PORT11)
  • Gripper distance sensor (PORT7)
  • Bumper sensor (PORT12)
Returns: True if all sensors pass, False otherwise

Complete Hardware Check

# Used in RoboticServices.check_service()
if self.safety_module.check_sensors() and self.safety_module.check_motors():
    self.sensor_module.set_color(LEDColors.READY)
    return True
else:
    self.sensor_module.set_color(LEDColors.ERROR)
    return False
System will not proceed to safety_service or scan_service if check_service fails. Always validate hardware before operation.

Shoulder Safety Check

Purpose: Validate shoulder mechanism limits using bumper collision detection
main.py
def check_shoulder_safety(self) -> bool:
    if self.sensor_module.is_bumper_pressed():
        self.control_module.general_stop()
        self.sensor_module.set_color(LEDColors.ERROR)
        self.control_module.rotate_motor_reverse(self.control_module.shoulder_motor, 10)
        time.sleep(2)
        self.control_module.general_stop()
        return True
    else:
        self.control_module.rotate_motor_forward(self.control_module.shoulder_motor, 60)
        self.sensor_module.set_color(LEDColors.WARNING)
        return False

Safety Check Flow

1

Raise Shoulder

Rotate shoulder motor forward at 60 RPM while monitoring bumper sensor
2

Detect Collision

When bumper is pressed, immediately trigger emergency stop
3

Reverse Motion

Move shoulder in reverse at 10 RPM for 2 seconds to clear bumper
4

Final Stop

Stop all motors and return success status

LED Status Indicators

ColorPhaseMeaning
Orange (WARNING)RaisingShoulder moving upward toward limit
Red (ERROR)CollisionBumper pressed, emergency stop activated
Green (READY)CompleteSafety check passed, system ready
Bumper Sensor: Binary switch at shoulder upper limit
Reversal Speed: 10 RPM (slow, controlled movement)
Reversal Duration: 2 seconds
The check returns True only when bumper is pressed and reversal completes. Call repeatedly until True is returned.

Gripper Safety Check

Purpose: Validate gripper mechanism using motor current sensing
main.py
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
    else:
        return False

Current-Based Detection

1

Read Current

Measure gripper motor current draw
2

Activate Gripper

Close gripper at 20 RPM while monitoring current
3

Detect Grip

When current exceeds 0.3A, object is gripped or motor stalled
4

Emergency Stop

Immediately stop all motors to prevent damage
Current Threshold: 0.3A
Motor Speed: 20 RPM
Detection Method: Current spike indicates grip force or mechanical resistance
Current threshold of 0.3A must be calibrated for specific gripper hardware. Too low may cause false positives, too high may damage objects.

Safety Check Logic

# Used in RoboticServices.safety_state_service()
while self.safety_service_loop == True:
    if not self.safety_shoulder:
        safety_shoulder = self.safety_module.check_shoulder_safety()
        if safety_shoulder:
            self.safety_shoulder = True
    else:
        if not self.safety_gripper:
            safety_gripper = self.safety_module.check_gripper_safety()
            if safety_gripper:
                self.safety_gripper = True
                self.safety_service_loop = False
                self.safety_mode_active = True
                self.sensor_module.set_color(LEDColors.READY)
                return True

Emergency Stop Mechanisms

General Stop

Purpose: Immediately halt all motor activity
main.py
# In ControlModule
def general_stop(self):
    self.base_motor.stop()
    self.shoulder_motor.stop()
    self.elbow_motor.stop()
    self.gripper_motor.stop()
Motors Stopped:
  • Base motor (scanning rotation)
  • Shoulder motor (vertical positioning)
  • Elbow motor (arm extension)
  • Gripper motor (object grasping)

Stop Triggers

Bumper Collision

Shoulder hits upper limit switch

Current Overload

Gripper motor exceeds 0.3A threshold

Exception Handling

Any unhandled exception in main loop

Manual Stop

Explicit call to general_stop()

Exception-Triggered Stop

main.py
# In RoboticServices.run()
try:
    # Service operations
except Exception as e:
    self.sensor_module.print_screen("Error: {}".format(str(e)[:20]), 1, 95)
    self.control_module.general_stop()
All exceptions in the main loop trigger emergency stop to ensure system safety. Monitor VEX brain screen for error messages.

LED Status Indicators

Visual feedback through TouchLED sensor (PORT10):

LED Color Definitions

main.py
class LEDColors:
    ERROR = (255, 0, 0)             # Red: Error/Stop
    WARNING = (255, 150, 0)         # Orange: Warning
    READY = (0, 255, 0)             # Green: Ready
    RUNNING = (0, 0, 255)           # Blue: Process Running
    OBJECT_DETECTED = (0, 255, 155) # Cyan: Object Detected

Safety State Indicators

StateColorRGBUsage
ERRORRed(255, 0, 0)Bumper collision, hardware failure, emergency stop
WARNINGOrange(255, 150, 0)Safety checks in progress, caution state
READYGreen(0, 255, 0)All checks passed, system operational
RUNNINGBlue(0, 0, 255)Active scanning or normal operation
OBJECT_DETECTEDCyan(0, 255, 155)Object within detection range

LED Control

main.py
# In SensorModule
def set_color(self, color):
    r, g, b = color
    self.touchled.set_color(r, g, b)

# Usage in safety checks
self.sensor_module.set_color(LEDColors.ERROR)    # Red on collision
self.sensor_module.set_color(LEDColors.WARNING)  # Orange during check
self.sensor_module.set_color(LEDColors.READY)    # Green when complete

Safety Service LED Sequence

1

Start - Orange

WARNING color indicates safety checks initiated
2

Collision - Red

ERROR color when bumper pressed during shoulder check
3

Complete - Green

READY color when all safety checks pass successfully

Error Handling

Error Count Tracking

main.py
class SafetyModule:
    def __init__(self, sensor_module: SensorModule, control_module: ControlModule):
        self.sensor_module = sensor_module
        self.control_module = control_module
        self.error_count = 0
        self.error_threshold = 3
Error counting infrastructure is in place but not currently enforced. Future implementations may halt system after 3 consecutive errors.

Hardware Failure Handling

# In RoboticServices.check_service()
if not check_service:
    data = {'error': 'Sensors or motors not installed'}
    self.communication.send_message('check_service', data)
    self.check_mode_active = False
    # System will not proceed to other services
Error Response Message:
{
    "type": "check_service",
    "data": {
        "error": "Sensors or motors not installed"
    }
}

Runtime Error Recovery

main.py
try:
    # Safety service execution
except Exception as e:
    self.sensor_module.print_screen("Error: {}".format(str(e)[:20]), 1, 95)
    self.control_module.general_stop()
    # System continues to next loop iteration
Recovery Strategy:
  1. Stop all motors immediately
  2. Display truncated error message on VEX screen
  3. Continue main loop (allows retry or manual intervention)
  4. LED remains in last known state

Safety Service Integration

Sequential Safety Check

main.py
# In RoboticServices
def safety_state_service(self) -> bool:
    while self.safety_service_loop == True:
        if not self.safety_shoulder:
            safety_shoulder = self.safety_module.check_shoulder_safety()
            if safety_shoulder:
                self.safety_shoulder = True
        else:
            if not self.safety_gripper:
                safety_gripper = self.safety_module.check_gripper_safety()
                if safety_gripper:
                    self.safety_gripper = True
                    self.safety_service_loop = False
                    self.safety_mode_active = True
                    self.sensor_module.set_color(LEDColors.READY)
                    return True
    return False
1

Shoulder Safety

Raise shoulder until bumper pressed, then reverse to safe position
2

Gripper Safety

Close gripper until current threshold reached
3

Service Complete

Set LED to green and send approval message to Raspberry Pi

Safety State Reset

main.py
def reset_safety_sequence(self):
    self.safety_mode_active = False
    self.safety_shoulder = False
    self.safety_gripper = False
    self.safety_service_loop = True
When to Reset:
  • Before starting new safety service
  • After safety service completes
  • When receiving new safety_service message from Raspberry Pi
Always call reset_safety_sequence() before restarting safety checks to clear previous state flags.

Best Practices

Hardware Validation

Always run check_service before any motor operations

Sequential Checks

Complete shoulder safety before gripper safety - order matters

Emergency Response

Monitor LED color for real-time safety status during operations

State Management

Reset safety flags between service runs to avoid stale state

Safety Check Sequence

# Recommended service execution order
serial_manager.send_message('check_service', {})    # 1. Validate hardware
time.sleep(2)
serial_manager.send_message('safety_service', {})   # 2. Perform safety checks
time.sleep(5)
serial_manager.send_message('scan_service', {})     # 3. Execute scan operation

Calibration Parameters

Shoulder Mechanism

ParameterValueAdjustable
Forward Speed60 RPMYes
Reverse Speed10 RPMYes
Reverse Duration2 secondsYes
Bumper PortPORT12No

Gripper Mechanism

ParameterValueAdjustable
Current Threshold0.3AYes (recommended)
Grip Speed20 RPMYes
Detection MethodCurrent sensingNo
Adjust current threshold based on gripper motor specifications and object grip force requirements. Test with representative objects.

Troubleshooting

IssueCauseSolution
Shoulder check never completesBumper not installedVerify PORT12 connection
Gripper check false positiveThreshold too lowIncrease from 0.3A to 0.4-0.5A
Emergency stop during scanBumper sensor malfunctionRun check_service to validate hardware
LED stays red after checkException in safety checkCheck VEX screen for error message

Arm Controller

Service orchestration in RoboticServices

Serial Communication

Safety service message protocol

Overview

Hardware components and LED indicators

Build docs developers (and LLMs) love