18-Channel Maestro and Shutdown on SBC

As some of you know, I am an issue at times to myself.

Outside of me thinking I know everything, what would cause the 18-Channel Maestro to shutdown a SBC (BeagleY-AI)?

#!/usr/bin/python3

# Where did this source code come from?
# I am still researching older notes and ideas...

import sys
import usb.core
import usb.util

# Constant definitions mimicking the C++ implementation
VENDOR_ID = 0x1FFB
PRODUCT_IDS = [0x0089, 0x008A, 0x008B, 0x008C]
REQUEST_SET_TARGET = 0x85  # The standard Pololu Maestro native USB request ID

def find_maestro_device():
    """Loops through known product IDs to find the Pololu Maestro device."""
    for pid in PRODUCT_IDS:
        device = usb.core.find(idVendor=VENDOR_ID, idProduct=pid)
        if device is not None:
            return device
    return None

def set_target_zero(device, position, servo0):
    """Sends the target position to a specific servo channel using a control transfer."""
    # bmRequestType = 0x40 (Vendor-defined request, host-to-device direction)
    bm_request_type = 0x40
    b_request = REQUEST_SET_TARGET

    # Value parameter requires position in quarter-microseconds (input * 4)
    w_value = int(position * 4)
    w_index = int(servo0)

    try:
        # usb.core.Device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
        device.ctrl_transfer(
            bm_request_type, b_request, w_value, w_index, data_or_wLength=0, timeout=5000
        )
    except usb.core.USBError as e:
        print(f"USB Transfer failed: {e}", file=sys.stderr)

def set_target_one(device, position, servo1):
    """Sends the target position to a specific servo channel using a control transfer."""
    # bmRequestType = 0x40 (Vendor-defined request, host-to-device direction)
    bm_request_type = 0x40
    b_request = REQUEST_SET_TARGET

    # Value parameter requires position in quarter-microseconds (input * 4)
    w_value = int(position * 4)
    w_index = int(servo1)

    try:
        # usb.core.Device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
        device.ctrl_transfer(
            bm_request_type, b_request, w_value, w_index, data_or_wLength=0, timeout=5000
        )
    except usb.core.USBError as e:
        print(f"USB Transfer failed: {e}", file=sys.stderr)

def set_target_two(device, position, servo2):
    """Sends the target position to a specific servo channel using a control transfer."""
    # bmRequestType = 0x40 (Vendor-defined request, host-to-device direction)
    bm_request_type = 0x40
    b_request = REQUEST_SET_TARGET

    # Value parameter requires position in quarter-microseconds (input * 4)
    w_value = int(position * 4)
    w_index = int(servo2)

    try:
        # usb.core.Device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
        device.ctrl_transfer(
            bm_request_type, b_request, w_value, w_index, data_or_wLength=0, timeout=5000
        )
    except usb.core.USBError as e:
        print(f"USB Transfer failed: {e}", file=sys.stderr)

    servo0 = 0

    servo1 = 1

    servo2 = 2

def main():
    print("Searching for Pololu Maestro device...")
    device = find_maestro_device()

    if device is None:
        print("Error: Maestro device not found. Check physical connections or permissions.")
        sys.exit(1)

    print("Device found and initialized successfully.")

    try:
        while True:
            user_input = input("Enter position (or 'q' to quit): ").strip()
            if user_input.lower() == "q":
                break

            try:
                position = int(user_input)

                set_target_zero(device, position, 0)
                set_target_zero(device, position, 1)

            except ValueError:
                print("Invalid input. Please enter an integer number.")

    except KeyboardInterrupt:
        print("\nExiting program.")
    finally:
        # PyUSB handles closing the device and recycling handles implicitly on exit,
        # but clearing configurations ensures safe detachment.
        usb.util.dispose_resources(device)


if __name__ == "__main__":
    main()

That is the source code. When I place a positive integer on the bash prompt, everything works and well.

Then, I try to reverse the move to a previously known position via a negative integer and the SBC shuts down.

Seth

Hello.

I am not sure why it would be causing your SBC to shut down, but supplying a negative position value does not make sense, so I am not surprised that is causing some kind of issue.

The Maestro indicates what position a servo should move to by varying the length of its servo pulse signals (i.e. how much time the signals spend high), and when you send the serial command to set the servo position, you are specifying that pulse length (i.e. the high time) in units of quarter-microseconds. Our blog has a series of posts about hobby servos that might be helpful.

- Patrick

1 Like

Thank you.

so, supplying a negative integer should be an error in the code.

I was using the wrong library…

I was using ctrl_transfer() which is not pyusb (I think).

Anyway, I got sort of far with the python3 coding but am now getting:

# USB Error: [Errno 16] Resource busy

Any ideas are welcomed. This is my blocker for now. Errno 16?

pyserial seems to work for me. I will not be using pyusb.