Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 18, 2025

  • Explore Zaber Motion Library and test installation
  • Document recommendations for Raspberry Pi 5 deployment
  • Create simplified Zaber linear rail module:
    • config.py - Minimal config (USB serial port, device/axis indices only)
    • rail_controller.py - Simple direct wrappers around Zaber API
    • prefect_flows.py - Clean Prefect flows wrapping API calls
  • Address review feedback:
    • Remove TCP/IoT connection options (USB only)
    • Remove validation function
    • Simplify controller to direct API wrappers
    • Add connection check to prevent AttributeError
Original prompt

This section details on the original issue you should resolve

<issue_title>Programmatic control of Zaber linear rail</issue_title>
<issue_description>Install the python library. All docs at https://software.zaber.com/motion-library. Examples at https://context7.com/zabertech/zaber-examples (use your context7 tool). Report your recommendations on how to approach this programmatic control via Python on a Raspberry Pi 5.</issue_description>

<agent_instructions>No new commits. Just explore and report back. Try running actual code (e.g., installing the Python library). </agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@sgbaird
Copy link
Member

sgbaird commented Nov 18, 2025

@copilot Try again. Might be related to https://www.githubstatus.com/

@sgbaird
Copy link
Member

sgbaird commented Nov 19, 2025

@copilot try again

Copy link
Contributor Author

Copilot AI commented Nov 19, 2025

@copilot try again

I've successfully explored the Zaber Motion Library and tested it on this system. Here's my comprehensive report on programmatic control of the Zaber linear rail via Python on Raspberry Pi 5:

✅ Library Installation

pip install zaber-motion

Successfully installed version 7.15.0 (~6.8 MB, lightweight). No system dependencies required.

📋 Key Recommendations

1. Connection Methods Available

  • USB Serial (most common): Connection.open_serial_port("/dev/ttyUSB0")
  • TCP/IP: Connection.open_tcp("192.168.1.100")
  • IoT Cloud: Connection.open_iot(device_id, token)
  • Network Share: Connection.open_network_share(host, port)

2. Basic Control Pattern

from zaber_motion import Library
from zaber_motion.ascii import Connection

Library.enable_device_db_store()
connection = Connection.open_serial_port("/dev/ttyUSB0")
device_list = connection.detect_devices()
axis = device_list[0].get_axis(1)

# Control operations
axis.home()                          # Home the axis
axis.move_absolute(100, "mm")        # Move to position
axis.move_relative(10, "mm")         # Move by distance
position = axis.get_position("mm")   # Read position
axis.wait_until_idle()              # Wait for completion

3. Raspberry Pi 5 Specific Setup

Permissions:

# Add user to dialout group
sudo usermod -a -G dialout $USER

# Create udev rule: /etc/udev/rules.d/99-zaber.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="2939", MODE="0666"
sudo udevadm control --reload-rules

Port Detection:

ls /dev/ttyUSB*  # Find connected devices
dmesg | grep tty  # Check connection logs

4. MQTT/HiveMQ Integration

The library doesn't have built-in MQTT support, but integration is straightforward using paho-mqtt. I created a complete example showing:

  • MQTT command handling (home, move_absolute, move_relative, stop)
  • Status publishing to MQTT topics
  • Periodic position monitoring
  • HiveMQ Cloud TLS/SSL support

5. Interface Options

CLI Script: Direct control via command line
Web API: Flask/FastAPI REST endpoints
GUI: Touchscreen interface (examples available for RPi)
MQTT: IoT messaging integration (my example)

6. Performance Notes

  • RPi 5 is more than capable (library has low overhead)
  • Default baud rate: 115200 (configurable)
  • Supports both ASCII and Binary protocols
  • Excellent error handling and timeout management

7. Example Files Created

I created two demo scripts in /tmp/:

  1. zaber_demo.py - Basic connection and status checking
  2. zaber_mqtt_integration.py - Complete MQTT integration with HiveMQ

Recommended Approach: Start with USB serial connection, implement MQTT wrapper for remote control, add Flask API for web interface if needed. The library is well-designed, thoroughly documented, and perfect for RPi 5 deployment.

Documentation: https://software.zaber.com/motion-library
Examples: https://github.com/zabertech/zaber-examples

Copilot AI changed the title [WIP] Explore programmatic control of Zaber linear rail Explore programmatic control of Zaber linear rail Nov 19, 2025
@sgbaird
Copy link
Member

sgbaird commented Nov 26, 2025

Kelvin wrote some code that is probably local on the corresponding Pi. We can set that up similarly to how we did with the lift module with Prefect.

@copilot you can take your example here and add prefect functionality similar to https://github.com/AccelerationConsortium/progressive-automations-python/tree/main/src/progressive_automations_python

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

Kelvin wrote some code that is probably local on the corresponding Pi. We can set that up similarly to how we did with the lift module with Prefect.

@copilot you can take your example here and add ...

Created the Zaber linear rail module with Prefect workflow support in e7c06f1. Following the same pattern as progressive-automations-python:

Module structure (src/ac_training_lab/zaber_linear_rail/):

  • config.py - Configuration settings (serial port, motion params, limits)
  • rail_controller.py - Core controller (connect, home, move_to_position, move_relative, get_position, stop)
  • prefect_flows.py - Prefect flows and deployment functions

Prefect flows available:

  • move_to_position_flow - Move to absolute position with optional homing
  • move_relative_flow - Move by relative distance
  • home_flow - Home the axis
  • get_status_flow - Get device status
  • sequence_flow - Execute sequence of positions

Deployment:

from ac_training_lab.zaber_linear_rail.prefect_flows import deploy_all_flows
deploy_all_flows("zaber-linear-rail-pool")

Then start a worker and trigger flows remotely:

prefect worker start --pool zaber-linear-rail-pool
prefect deployment run 'move-to-position-flow/move-to-position' --param target_position=100.0

Copilot AI changed the title Explore programmatic control of Zaber linear rail Add Zaber linear rail module with Prefect workflow support Nov 26, 2025
Copy link
Member

@sgbaird sgbaird left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot see comments

# =============================================================================
# Serial port where Zaber device is connected
# On Raspberry Pi, typically /dev/ttyUSB0 or /dev/ttyACM0
SERIAL_PORT = os.getenv("ZABER_SERIAL_PORT", "/dev/ttyUSB0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume USB connection and no other form of communication except for Prefect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified to USB-only in a0f7746. Removed TCP/IoT connection options - now only SERIAL_PORT config remains.

# =============================================================================
# VALIDATION
# =============================================================================
def validate_config():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems unnecessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed validation function in a0f7746. Config now only has 3 settings: SERIAL_PORT, DEVICE_INDEX, AXIS_NUMBER.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this seems overly complicated. Sure we can't just wrap zaber API calls with task and flow directly in most cases? Do we really need all this extra logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified in a0f7746. The controller now directly wraps Zaber API calls:

def home() -> float:
    _axis.home()
    _axis.wait_until_idle()
    return _axis.get_position("mm")

Removed state management, position validation, verbose logging. Functions simply call Zaber API and return results. Module went from 329 lines to 96 lines.

Copilot AI requested a review from sgbaird November 26, 2025 18:10
Copy link
Member

@sgbaird sgbaird left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot ok, I guess it's fine. Seems it makes it blocking for a lot of the commands, which is fine. Just that I'm not sure it was non-blocking to begin with. Isn't prefect going to have some issues with the global variables though?

I.e., persisting the connection between for runs.

Copy link
Contributor Author

Copilot AI commented Nov 27, 2025

@copilot ok, I guess it's fine. Seems it makes it blocking for a lot of the commands, which is fine. Just that I'm not sure it was non-blocking to begin with. Isn't prefect going to have some issues w...

The global variables won't cause issues because each flow explicitly calls connect() at the start and disconnect() in the finally block. The connection is not persisted between runs - each flow run establishes its own connection and closes it when done. Prefect workers spawn fresh processes for each run, so globals are reset anyway. The blocking behavior (via wait_until_idle()) ensures movements complete before returning.

Copilot AI requested a review from sgbaird November 27, 2025 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Programmatic control of Zaber linear rail

2 participants