Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Fault Handling

Fault detection and clearing for the L20 dexterous hand.

Overview

Use hand.fault to access fault-related functionality:

  • Read fault status in blocking or cached mode
  • Clear faults on all joints

Fault Code Table

L20 represents fault states with bit flags. Each joint motor can report multiple faults at the same time.

Fault codeValueDescription
NONE0No fault
MOTOR_ROTOR_LOCK1Motor rotor lock
MOTOR_OVER_CURRENT2Motor overcurrent
MOTOR_STALL_FAULT4Motor stall fault
VOLTAGE_ABNORMAL8Voltage abnormality
SELF_CHECK_ABNORMAL16Self-check abnormality
OVER_TEMPERATURE32Overtemperature
SOFT_ROTOR_LOCK64Software rotor lock
MOTOR_COMM_ABNORMAL128Motor communication abnormality

Read Faults

Blocking Read

from realhand.exceptions import TimeoutError

try:
    data = hand.fault.get_blocking(timeout_ms=500)
except TimeoutError:
    print("Read timed out")

Parameter:

  • timeout_ms: Timeout in milliseconds, default 100

Return value: FaultData, containing:

  • faults: L20Fault fault data
  • timestamp: Timestamp

Exception:

  • TimeoutError: No response before timeout

Cached Read

data = hand.fault.get_snapshot()
if data:
    print(f"Has fault: {data.faults.has_any_fault()}")

Returns the latest cached fault data, or None if no data is available.

Clear Faults

hand.fault.clear_faults()

Sends a fire-and-forget command to clear faults on all joints, without waiting for a response.

Streaming Read

Receive all sensor events through the top-level hand.stream() interface:

from realhand.hand.l20 import SensorSource, FaultEvent

hand.start_polling({SensorSource.FAULT: 0.2})

try:
    for event in hand.stream():
        match event:
            case FaultEvent(data=data):
                if data.faults.has_any_fault():
                    for code in data.faults.to_list():
                        if code.has_fault():
                            print(code.get_fault_names())
finally:
    hand.stop_polling()
    hand.stop_stream()

Data Class Reference

L20Fault fields

FieldDescription
thumb_abdThumb abduction
thumb_yawThumb rotation
thumb_root1Thumb root
thumb_tipThumb tip
index_abdIndex abduction
index_root1Index root
index_tipIndex tip
middle_abdMiddle abduction
middle_root1Middle root
middle_tipMiddle tip
ring_abdRing abduction
ring_root1Ring root
ring_tipRing tip
pinky_abdPinky abduction
pinky_root1Pinky root
pinky_tipPinky tip

L20Fault methods

# Check whether any fault exists
faults.has_any_fault()  # -> bool

# Convert to a list
faults.to_list()  # -> list[L20FaultCode]

# Index access
faults[0]  # thumb_abd

L20FaultCode methods

# Check whether a single joint motor has a fault
faults.thumb_abd.has_fault()  # -> bool

# Get the list of fault names
faults.thumb_abd.get_fault_names()  # -> list[str]

Examples

Check Fault Status

from realhand import L20

with L20(side="left", interface_name="can0") as hand:
    # Read fault status
    data = hand.fault.get_blocking(timeout_ms=500)

    if data.faults.has_any_fault():
        print("Fault detected:")
        if data.faults.thumb_abd.has_fault():
            print(f"  Thumb abduction: {data.faults.thumb_abd.get_fault_names()}")
        if data.faults.index_abd.has_fault():
            print(f"  Index abduction: {data.faults.index_abd.get_fault_names()}")
    else:
        print("No faults")

    # Clear all faults
    hand.fault.clear_faults()

Continuous Monitoring

from realhand import L20
from realhand.hand.l20 import SensorSource, FaultEvent

with L20(side="left", interface_name="can0") as hand:
    hand.start_polling({SensorSource.FAULT: 0.2})

    try:
        for event in hand.stream():
            match event:
                case FaultEvent(data=data):
                    if data.faults.has_any_fault():
                        for i, code in enumerate(data.faults.to_list()):
                            if code.has_fault():
                                print(f"Joint {i} fault: {code.get_fault_names()}")
    except KeyboardInterrupt:
        pass
    finally:
        hand.stop_polling()
        hand.stop_stream()