PLC Application¶
This document specifies the PLC-side integration required to communicate with Pick[+] for the Execution routine.
Currently, the supported PLC communication protocols are:
- Modbus TCP: (all data, including booleans, uses Holding Registers)
- Siemens
The integration supports two PLC requests:
- Trigger request: Capture an image and start detection.
- Output request: Retrieve the latest available result (pick pose + metadata) for a given robot/ROI.
The goal is to provide a deterministic handshake and a clear register contract so PLC code can be implemented consistently.
Related Documentation
For calibration-specific PLC integration, see Calibration with PLC.
Standards and Conventions¶
All poses use 6 consecutive registers with the following encoding:
| Setting | Value | Description |
|---|---|---|
| Endianness | Big-Endian | Network Byte Order |
| Pose Order | X, Y, Z, R, P, Y | 6 consecutive registers per pose |
| Translation Scale | 10000 | Tenths of millimeter (0.1 mm / 0.0001 m) |
| Rotation Scale | 10000 | 1/10,000th of a radian (0.0001 rad) |
Coordinate Format
All spatial coordinates use this default format. These values must be respected when sending position data to ensure correct interpretation by Pick[+]. The format can be modified if required.
Communication is described from the PLC perspective:
| Direction | Description |
|---|---|
| PLC Inputs (Read-Only) | Registers written by Pick[+] and read by the PLC (status, flags, results) |
| PLC Outputs (Write) | Registers written by the PLC and read by Pick[+] (requests + parameters) |
Request Mechanism
Requests are assigned to different registers or coils. A request is made by inverting its toggle bit value (0 → 1 or 1 → 0). Pick[+] detects a change, not the value itself.
All configuration parameters associated with a request must be written before toggling the corresponding register. Once the toggle is detected, Pick[+] immediately reads and uses the parameters.
General Registers¶
The following registers provide system-wide status information and control.
Shared Registers
Registers marked as "Shared" (addresses 0-4) are global across all routines (Calibration, Execution, Scan). These registers use the same addresses regardless of which routine is active. See also: Calibration with PLC for calibration routine-specific registers.
Routine Status
- Access: Read-Only
- Register type:
uint16
Indicates which routine is currently running.
| Value | State | Description |
|---|---|---|
0 |
Configuration | No routine is currently running |
1 |
Scan | Scanning routine is running |
2 |
Execution | Execution routine is running |
3 |
Calibration | Calibration routine is running |
Life Bit / Heartbeat
- Access: Read-Only
- Register type:
bool
Pick[+] toggles the value of this register between 0 and 1 at regular intervals to indicate it is operating and connected. The default interval is 1 second and it can be configured.
Error Code
- Access: Read-Only
- Register type:
uint16
This register provides information about errors detected by Pick[+]. The PLC should monitor this register continuously, especially during startup and normal operation.
| Value | State | Description |
|---|---|---|
0 |
No error | No error detected. Operating normally |
1 |
Initialization Error | Error during initialization (e.g., hardware communication issues) |
2 |
Runtime error | Error occurred during routine execution |
Controllable
- Access: Write
- Register type:
bool
This register indicates to Pick[+] that the robot is ready to be controlled. This is required in order to start the calibration or execution. This is a safety mechanism to prevent sending commands to the robot when the robot is not ready to be moved.
Application Selection¶
A single Pick[+] license can hold multiple applications (see Application Mode). When the Application Source is set to PLC, the PLC chooses which application runs during execution through the APP_ID register.
APP_ID
- Access: Write
- Register type:
uint16
Holds the numeric ID of the application to run. Each application defines its own ID in Pick[+].
| Value | Meaning |
|---|---|
0 |
No application selected. Nothing runs. |
X (> 0) |
Start the application whose ID is X, as defined in Pick[+] |
Pick[+] reacts to a change in APP_ID, not to the value being rewritten:
- Writing
0 → Xstarts applicationX. - Writing
X → Y(switching between two applications) unloads the current application and loads the new one.
Interaction with ROUTINE_STATUS: switching applications is not instantaneous. When the PLC changes APP_ID (for example from 2 to 5), Pick[+] unloads the current application and ROUTINE_STATUS drops to 0 (Configuration). Once the new application has loaded and execution has started, ROUTINE_STATUS returns to 2 (Execution).
Wait for ROUTINE_STATUS before triggering
After changing APP_ID, wait until ROUTINE_STATUS returns to 2 before sending any Trigger or Output request. Loading an application takes several seconds, so application switching is intended for production or batch changes, not for frequent switching during normal operation.
Request Handshake Flags¶
Register Scope
TOGGLE_FLAG_TRIGGERis shared across routines (used in Calibration, Execution and Scan)TOGGLE_FLAG_OUTPUTis execution-specific (Execution routine only)
These flags indicate that Pick[+] has processed a toggle. The flags change state (0 ↔ 1) when the associated request has been handled.
| Name | Count | Type | Scope | Description |
|---|---|---|---|---|
TOGGLE_FLAG_TRIGGER |
1 | bool |
Shared | Toggled by Pick[+] once a Trigger request has been accepted and processing has started (does not guarantee results are ready yet). Also used in Calibration and Scan routines. |
TOGGLE_FLAG_OUTPUT |
1 | bool |
Execution | Toggled by Pick[+] once an Output request has been processed and output registers have been written |
Trigger Request¶
This request asks Pick[+] to capture an image and start the detection process using the parameters below.
Register Layout
It's recommended to use consecutive holding registers for all parameters. For example, if holding register 10 is used for TRIGGER_REQ, then 11, 12, etc. should be used for the remaining parameters.
Trigger Parameters¶
| Name | Count | Type | Description |
|---|---|---|---|
TRIGGER_REQ |
1 | bool |
Toggle bit to request a trigger action from Pick[+] |
TRIGGER_BOX_ID |
1 | uint16 |
Identifier of the combination of boxes (ROI) to pick objects from. |
TRIGGER_BOX_ID_IGNORE |
1 | bool |
Ignores the combination of boxes (ROI) of TRIGGER_BOX_ID. |
TRIGGER_CATEGORY_ID |
N | int16 |
List of category IDs to filter detection results. Uses N consecutive registers. See List-Based Filtering. |
TRIGGER_CATEGORY_ID_SUBTRACT |
1 | bool |
When 0: include only listed categories. When 1: exclude listed categories. |
TRIGGER_ENV_ID |
N | int16 |
List of environment IDs to filter detection. Uses N consecutive registers. See List-Based Filtering. |
TRIGGER_ENV_ID_SUBTRACT |
1 | bool |
When 0: include only listed environments. When 1: exclude listed environments. |
MAX_PICK_ANGLE |
1 | uint16 |
Max allowed angle between tool Z-axis and ROI plane normal (degrees). Typical value: 15-25 |
TRIGGER_3D_MODEL_ID |
N | int16 |
List of 3D model IDs to filter detection results. Uses N consecutive registers. See List-Based Filtering. |
TRIGGER_3D_MODEL_ID_SUBTRACT |
1 | bool |
When 0: include only listed models. When 1: exclude listed 3D models. |
ROBOT_TOOL_FLANGE_POSE |
6 | int16 |
Robot tool flange pose at trigger time (using pose format and scaling defined above) |
List-Based Filtering¶
Several trigger parameters (TRIGGER_CATEGORY_ID, TRIGGER_ENV_ID, TRIGGER_3D_MODEL_ID) use lists of consecutive registers to send multiple IDs in a single trigger request. This allows Pick[+] to filter detection results based on categories, environments, or 3D models.
| Property | Value |
|---|---|
| Register type | int16 |
| Number of registers | Configurable per list (default: 1) |
| Empty value | -1 |
How it works:
- Each register in the list holds one ID value.
- Registers set to the empty value (
-1) are ignored by Pick[+]. The PLC must write-1to any unused register to indicate it should not be read. - Pick[+] reads only registers whose value differs from the empty value.
- All list registers must be written before toggling
TRIGGER_REQ.
Subtract mode:
Each list has an associated _SUBTRACT flag that changes the filter behavior:
| Flag Value | Behavior |
|---|---|
0 |
Include mode: Only items matching the listed IDs are considered |
1 |
Exclude mode: Items matching the listed IDs are excluded (subtracted) |
Example: With 2 registers configured for TRIGGER_3D_MODEL_ID, and the following values written:
| Register | Value |
|---|---|
TRIGGER_3D_MODEL_ID[0] |
2 |
TRIGGER_3D_MODEL_ID[1] |
5 |
TRIGGER_3D_MODEL_ID_SUBTRACT |
Result |
|---|---|
0 (Include) |
Only models 2 and 5 are considered |
1 (Exclude) |
All models except 2 and 5 are considered |
If only one model is needed, write -1 to the unused register:
| Register | Value |
|---|---|
TRIGGER_3D_MODEL_ID[0] |
2 |
TRIGGER_3D_MODEL_ID[1] |
-1 |
TRIGGER_3D_MODEL_ID_SUBTRACT |
Result |
|---|---|
0 (Include) |
Only model 2 is considered |
1 (Exclude) |
All models except 2 are considered |
Trigger Request Sequence¶
- Wait until
ROUTINE_STATUS = 2 - Write all Trigger parameters
- Toggle
TRIGGER_REQ - Wait until
TOGGLE_FLAG_TRIGGERchanges (handshake complete, capture/detection has started) - Proceed to Output requests to fetch results
Output Request¶
Requests Pick[+] to write the currently available results to the PLC. It can be used to retrieve more than one pick point per trigger, as Pick[+] processes more pick points you can request them by specifying the robot and box.
Register Layout
It's recommended to use consecutive holding registers for all parameters.
Output Parameters
| Name | Count | Type | Description |
|---|---|---|---|
OUTPUT_REQ |
1 | bool |
Toggle bit to request the output data from Pick[+] |
ROBOT_ID |
1 | uint16 |
Numeric ID of the robot used. Required for multi-robot setup. |
OUTPUT_BOX_ID |
1 | uint16 |
Identifier of the combination of boxes (ROI) to pick objects from. |
Results Data¶
Result registers written by Pick[+] obtained for the robot and the specified boxes.
| Name | Count | Type | Description |
|---|---|---|---|
COMPUTING_FLAG |
1 | int16 |
Indicates if results are still being computed when Output is requested. See Computing Flag Values. |
COUNT |
1 | uint16 |
Number of available pick candidates |
OUTPUT_BOX |
1 | uint16 |
Box (ROI) identifier associated with the pick candidate |
OUTPUT_CATEGORY_ID |
1 | int16 |
Category ID of the detected object. If no results exists: -1 |
OUTPUT_MODEL_ID |
1 | int16 |
Confirmation of the requested model ID candidate. If no result exists: -1 |
PICK_ID |
1 | int16 |
Candidate identifier |
PICK_POSE |
6 | int16 |
Pick pose (X, Y, Z, R, P, Y) of the candidate |
Computing Flag Values¶
| Value | State | Description |
|---|---|---|
0 |
Ready | Results are available |
1 |
Computing | Results are still being computed |
2 |
Error | An error occurred |
No Valid Poses Available
If no valid poses are available:
PICK_POSE=[0, 0, 0, 0, 0, 0]OUTPUT_CATEGORY_ID=-1
Proposed Memory Map¶
Addresses shown in this document are indicative and may be remapped to match your PLC memory layout. Keep related blocks consecutive.
List Registers
Registers marked with * use a default list size of 3 registers. Adjust to match your application needs. See List-Based Filtering for details.
Each address corresponds to one 16-bit Holding Register. Booleans are stored as 0 / 1 in a full register.
Memory Layout
- Addresses 0–4: Global registers shared across all routines
- Addresses 5–30: Reserved for Calibration routine (see Calibration with PLC)
- Addresses 31+: Execution routine registers
| Address | Name | Type | Access | Scope |
|---|---|---|---|---|
| Shared - Base Control & Status | ||||
| 0 | ROUTINE_STATUS |
uint16 |
Read-Only | Shared |
| 1 | LIFE_BIT |
bool |
Read-Only | Shared |
| 2 | ERROR_CODE |
uint16 |
Read-Only | Shared |
| 3 | CONTROLLABLE |
bool |
Write | Shared |
| 4 | TOGGLE_FLAG_TRIGGER |
bool |
Read-Only | Shared |
| Execution - Application Selection | ||||
| 31 | APP_ID |
uint16 |
Write | Execution |
| Execution - Trigger Request | ||||
| 32 | TRIGGER_REQ |
bool |
Write | Execution |
| 33 | TRIGGER_BOX_ID |
uint16 |
Write | Execution |
| 34 | TRIGGER_BOX_ID_IGNORE |
bool |
Write | Execution |
| 35-37 | TRIGGER_CATEGORY_ID * |
int16[3] |
Write | Execution |
| 38 | TRIGGER_CATEGORY_ID_SUBTRACT |
bool |
Write | Execution |
| 39-41 | TRIGGER_ENV_ID * |
int16[3] |
Write | Execution |
| 42 | TRIGGER_ENV_ID_SUBTRACT |
bool |
Write | Execution |
| 43 | MAX_PICK_ANGLE |
uint16 |
Write | Execution |
| 44-46 | TRIGGER_3D_MODEL_ID * |
int16[3] |
Write | Execution |
| 47 | TRIGGER_3D_MODEL_ID_SUBTRACT |
bool |
Write | Execution |
| 48-53 | ROBOT_TOOL_FLANGE_POSE |
int16[6] |
Write | Execution |
| Execution - Output Request | ||||
| 54 | OUTPUT_REQ |
bool |
Write | Execution |
| 55 | ROBOT_ID |
uint16 |
Write | Execution |
| 56 | OUTPUT_BOX_ID |
uint16 |
Write | Execution |
| Execution - Response Data | ||||
| 57 | COMPUTING_FLAG |
int16 |
Read-Only | Execution |
| 58 | COUNT |
uint16 |
Read-Only | Execution |
| 59 | OUTPUT_BOX |
uint16 |
Read-Only | Execution |
| 60 | OUTPUT_CATEGORY_ID |
int16 |
Read-Only | Execution |
| 61 | OUTPUT_MODEL_ID |
int16 |
Read-Only | Execution |
| 62 | PICK_ID |
int16 |
Read-Only | Execution |
| 63 | TOGGLE_FLAG_OUTPUT |
bool |
Read-Only | Execution |
| 64-69 | PICK_POSE |
int16[6] |
Read-Only | Execution |
Addresses are byte offsets within a Data Block (DB). Booleans use bit notation (byte.bit) and each occupies one byte. INT/UINT occupy 2 bytes and padding is added automatically before them when needed for even-byte alignment.
Memory Layout
- Addresses 0–7: Global registers shared across all routines
- Addresses 8–55: Reserved for Calibration routine (see Calibration with PLC)
- Addresses 56+: Execution routine registers
| Address | Name | Type | Access | Scope |
|---|---|---|---|---|
| Shared - Base Control & Status | ||||
| 0 | ROUTINE_STATUS |
uint16 |
Read-Only | Shared |
| 2.0 | LIFE_BIT |
bool |
Read-Only | Shared |
| 4 | ERROR_CODE |
uint16 |
Read-Only | Shared |
| 6.0 | CONTROLLABLE |
bool |
Write | Shared |
| 7.0 | TOGGLE_FLAG_TRIGGER |
bool |
Read-Only | Shared |
| Application Selection | ||||
| 56 | APP_ID |
uint16 |
Write | Execution |
| Trigger Request | ||||
| 58.0 | TRIGGER_REQ |
bool |
Write | Execution |
| 60 | TRIGGER_BOX_ID |
uint16 |
Write | Execution |
| 62.0 | TRIGGER_BOX_ID_IGNORE |
bool |
Write | Execution |
| 64-69 | TRIGGER_CATEGORY_ID * |
int16[3] |
Write | Execution |
| 70.0 | TRIGGER_CATEGORY_ID_SUBTRACT |
bool |
Write | Execution |
| 72-77 | TRIGGER_ENV_ID * |
int16[3] |
Write | Execution |
| 78.0 | TRIGGER_ENV_ID_SUBTRACT |
bool |
Write | Execution |
| 80 | MAX_PICK_ANGLE |
uint16 |
Write | Execution |
| 82-87 | TRIGGER_3D_MODEL_ID * |
int16[3] |
Write | Execution |
| 88.0 | TRIGGER_3D_MODEL_ID_SUBTRACT |
bool |
Write | Execution |
| 90-101 | ROBOT_TOOL_FLANGE_POSE |
int16[6] |
Write | Execution |
| Output Request | ||||
| 102.0 | OUTPUT_REQ |
bool |
Write | Execution |
| 104 | ROBOT_ID |
uint16 |
Write | Execution |
| 106 | OUTPUT_BOX_ID |
uint16 |
Write | Execution |
| Results Data | ||||
| 108 | COMPUTING_FLAG |
int16 |
Read-Only | Execution |
| 110 | COUNT |
uint16 |
Read-Only | Execution |
| 112 | OUTPUT_BOX |
uint16 |
Read-Only | Execution |
| 114 | OUTPUT_CATEGORY_ID |
int16 |
Read-Only | Execution |
| 116 | OUTPUT_MODEL_ID |
int16 |
Read-Only | Execution |
| 118 | PICK_ID |
int16 |
Read-Only | Execution |
| 120.0 | TOGGLE_FLAG_OUTPUT |
bool |
Read-Only | Execution |
| 122-133 | PICK_POSE |
int16[6] |
Read-Only | Execution |
Programming Guide¶
| Component | Responsibility |
|---|---|
| Pick[+] | Captures image, computes candidates, writes flags/results |
| PLC | Owns robot motion execution and request timing |
The PLC program should follow this logical flow:
- Startup / Wait ready
- Trigger
- Output polling loop (until a valid, reachable pose is obtained)
- Robot move
- Repeat
Recommended PLC Sequence¶
Step 0 - Startup¶
- If the Application Source is set to PLC, write the desired application ID to
APP_ID(see Application Selection) - Ensure
ROUTINE_STATUS = 2before sending any request - Monitor
LIFE_BITandERROR_CODEcontinuously
Step 1 - Trigger¶
- Write Trigger parameters
- Toggle
TRIGGER_REQ - Wait until
TOGGLE_FLAG_TRIGGERchanges
Step 2 - Request Output and Handle Computing¶
- Toggle
OUTPUT_REQ - Wait until
TOGGLE_FLAG_OUTPUTchanges (Pick[+] has written output registers) - Read
COMPUTING_FLAG:- If
1(Computing): Results aren't ready. Go back to Step 2.1 (request Output again after 50-100ms) - If
0(Ready): Data is valid. Proceed to Step 3
- If
Step 3 - Validate Result¶
- If
PICK_POSE= zeros andOUTPUT_MODEL_ID=-1→ No candidates available. Go back to Step 1 (new Trigger) - Else → Read the pose as the next pick candidate
Step 4 - Reachability / Candidate Iteration¶
- If the pose is reachable → Move robot to pose and execute pick
- If not reachable → Request Output again (Step 2) to retrieve another candidate