Brooks PreciseFlex 400
This page gets a PF400 connected and confirms the connection without moving the arm. Mounting, wiring and safety are covered by the Brooks manuals; the PF400 guides take it from here to teaching positions and moving plates.
The connector targets unitelabs-brooks-preciseflex-400 0.4.0. The connection test below ran
against a simulated arm and a real PF400.
What you need
| Item | Detail |
|---|---|
| Instrument | A PF400 with its Guidance Controller, bolted down, powered, with the emergency stop within reach |
| Controller | Its IP address and basic settings done through the Brooks web interface. See below |
| Network | An Ethernet link from the GroundControl machine to the controller. The factory address is 192.168.0.1 |
| Connector | Brooks PreciseFlex 400 from the UniteLabs registry |
| Vendor software | None at runtime. The connector installs and runs its own program on the controller |
| Machine | Windows, Linux or macOS running GroundControl |
| Access | A tenant and the SDK installed. See Setup |
The GroundControl machine has to reach these ports on the controller:
| Port | Used for |
|---|---|
10100 | Commands to the arm |
10000 | Status reads, and stopping the arm while another command runs |
21 | FTP, to upload the connector's program: on the first start, after a connector update, and when another program answers |
80 | The web console, to write the startup settings and to start or restart the program |
Before you connect
A factory-fresh controller is not ready for the connector. Give it its IP address and initial settings through the Brooks web interface first, as the Guidance Controller documentation describes. The connector takes over from there.
The connector runs its own GPL program on the controller, in its own folder,
/flash/projects/unitelabs_tcp_server/. It never deletes another project. If the controller runs
another program, from Brooks, an integrator or another scheduler, the connector stops and unloads
it and points the startup settings at its own program. It changes these startup settings:
- GPL operating mode on;
- autostart, and auto compile and run, of its own project, at its own project path;
- home the arm on power-up;
- switch motor power on at power-up: off.
Note the current values in the web console before you connect, along with the name of the startup project. To switch back later, disable motor power, set the old project and values again, and save them to flash.
Install and configure the connector
- In GroundControl, add a connector and pick Brooks PreciseFlex 400 from the registry (how to add a connector).
- Fill in the
deviceblock of the configuration. The fields that matter:Field Value hostThe controller's IP address, 192.168.0.1unless it was changedportThe command port, 10100. Change it only if the controller serves commands elsewheresimulationfalsefor the real arm. It defaults totrue, so a fresh install never moves anythingextended_reachAlways set it: truefor an XR arm,falsefor standard reach. A wrong value makes the reach check use the wrong link lengths, up to about 113 mm offrail_axisy, orxif the rail carriage is turned a quarter. Ignored without a railftp_userLeave empty, unless someone added FTP credentials on the controller. Same for ftp_passwordboot_timeoutSeconds to wait for the controller after installing the program, 120by defaultprofilesMotion profiles to write into slots 1to20at startup. Empty leaves the controller's values
The rail is detected from the controller; there is no setting to turn it on. - Start the connector. On the first real-mode start it installs its program, which takes up to two
minutes:
- uploads the program over FTP and sets it to start, compile and run on every power-up;
- starts it from the web console and checks that the code answering is the code it uploaded;
- switches motor power on and homes the arm. The arm moves.
On later starts nothing is uploaded. A connector update with a newer program re-uploads it. If the program is installed but stopped, after a crash or an operator stopping it, the connector only restarts it: no settings rewritten, no homing. The arm comes up powered but not homed, and moves fail with-1021until you home it.
After a power cycle of the controller, the program starts on its own but motor power stays off. The controller ships with power coming on at startup, and the connector turns that off. Switch power on and home the arm before the first move. - GroundControl lists the modules, among them
MovementController,JointMovementController,PathController,GripperController,TransportController,SafetyController,LightingControllerandSimulationController.TransportControlleronly appears when the controller reports plate handling.
To go from simulation to the real arm, set simulation to false and restart the connector.
Switching with the SimulationController module does not install the program, and fails if the
controller runs another program until the connector restarts.
To install the program by hand instead, for example on a site that blocks FTP, set
auto_deploy to false and ask UniteLabs support for the project files.
Try it without an arm
With simulation left at true, the connector answers like a PF400 without one: moves take time
and finish, the gripper grasps, and plate handling is reported. simulate_rail adds a rail. It
checks targets against the arm extended_reach describes, so set that as you would for the real
arm. Every script on this page and in the
PF400 guides runs against it.
First connection test
The script reads what the controller reports about itself, then its state and joint positions. Nothing in it moves the arm. Run it with the SDK authenticated (Connect to Platform), using the connector's name from GroundControl.
import asyncio
from unitelabs.sdk import AsyncApiClient
async def first(subscription, key):
# Sensor streams open with an event that carries no value,
# so read until one that does
async with subscription:
async for value in subscription:
if key in value:
return value
raise RuntimeError("The stream closed without a value")
async def main():
client = AsyncApiClient()
arm = await client.get_service_by_name(name="Brooks PreciseFlex 400")
info = arm.information_provider
# What the controller reports about itself
print("Model:", await info.get_model())
print("Firmware:", await info.get_firmware_version())
rail = await info.get_rail_installed()
print("Rail:", rail)
print("Plate handling:", await info.get_plate_handling_supported())
# Live state and position. Nothing here moves the arm
print("State:", await first(await info.subscribe_state(), "Homed"))
suffix = "_with_rail" if rail else ""
stream = arm.joint_movement_controller.actions[
"subscribe_joint_positions" + suffix
]
print("Joints:", await first(await stream(), "Column"))
asyncio.run(main())
Run it with uv run first_connection.py. On a real arm it prints something like:
Model: PreciseFlex 400
Firmware: TCP Command Server 3.0D2 06-28-2024, ..., PARobot Module 3.0C2 07-11-2023, ...
Rail: False
Plate handling: True
State: {'Status': 'IDLE', 'Enabled': True, 'Homed': True}
Joints: {'Column': 502.27, 'Shoulder': 26.389, 'Elbow': 181.844, 'Wrist': -207.677, 'Gripper': 126.12}
With a rail, Joints also carries Rail. If Plate handling is False, the pick-up and put-down
commands are not available; contact UniteLabs support.
Known quirks and errors
| You see | It means | Do this |
|---|---|---|
-1021 Robot not homed on every move | The program restarted, the controller was power-cycled, or the arm was stopped | Clear the gripper. Switch power on if it is off (update_power(active=True)), then await arm.movement_controller.home() |
-1009 latched fault | A collision or an emergency stop left a fault the controller holds | Check the cell and the gripper, then await arm.safety_controller.recover(). It clears the fault and re-homes, so the arm moves |
The connector does not start with simulation set to false | No arm answered at host | Check the cable, the address and the ports above. The connector does not fall back to simulation |
| An error naming two digests | A different program answers on port 10100, found on a reconnect | Restart the connector. A fresh start installs its own program next to the other one and switches the startup settings; see Before you connect first |
-2805 Unknown command | The controller runs another vendor's program | As above |
| A move is refused with a profile out of range | Profiles 0 to -5 only exist from connector 0.4.0 | Update the connector, or use a slot from 1 to 20 that you have set to a known speed |
| The arm does not respond to the connector | Someone is driving it from the Brooks web console | Close the console; one driver at a time |
Homed in the state can lag behind the arm for a few seconds after a move, a stop or a recovery.
Next steps
- Robot Arms: how UniteLabs represents an arm and its teachpoints.
- Teach positions: capture stations in the Teach view.
- Move a plate and Recover from a stop.
Vendor documentation
Mounting, power, the controller's own settings and safety are covered by the Brooks PreciseFlex 400 manual and the Guidance Controller documentation shipped with the arm.
Last updated