diff --git a/docs/protocol-documentation.md b/docs/protocol-documentation.md index bd5dc1c..fde0f88 100644 --- a/docs/protocol-documentation.md +++ b/docs/protocol-documentation.md @@ -789,9 +789,10 @@ Server version and name. | id | [uint32](#uint32) | | Line ID. Numeric ID, starting from 1, that is unique to each line in the track. This ID is used to address the line in other requests. | | name | [string](#string) | | Configured line name. This name is otherwise unused by the API, and is provided to the client for end-user convenience. | | axes | [uint32](#uint32) | | Total number of axes in the line. | -| axis_length | [float](#float) | | Length of each axis in the line, in meters. | -| carrier_length | [float](#float) | | Carrier magnet length, in meters. | +| axis_length | [float](#float) | | Length of each axis in the line, in millimeters. | +| carrier_length | [float](#float) | | Carrier dimension parallel to carrier movement, in millimeters. | | drivers | [uint32](#uint32) | | Total number of drivers in the line. | +| carrier_width | [float](#float) | | Carrier dimension perpendicular to carrier movement, in millimeters. | diff --git a/protobuf/mmc/core.proto b/protobuf/mmc/core.proto index f576afd..df98a46 100644 --- a/protobuf/mmc/core.proto +++ b/protobuf/mmc/core.proto @@ -49,12 +49,14 @@ message Response { string name = 2; // Total number of axes in the line. uint32 axes = 3; - // Length of each axis in the line, in meters. + // Length of each axis in the line, in millimeters. float axis_length = 4; - // Carrier magnet length, in meters. + // Carrier dimension parallel to carrier movement, in millimeters. float carrier_length = 5; // Total number of drivers in the line. uint32 drivers = 6; + // Carrier dimension perpendicular to carrier movement, in millimeters. + float carrier_width = 7; } // All configured lines in track. repeated Line lines = 1; diff --git a/site/protocol-documentation.html b/site/protocol-documentation.html index 396bbbc..86bb962 100644 --- a/site/protocol-documentation.html +++ b/site/protocol-documentation.html @@ -3294,13 +3294,13 @@
PMF provides the Motion Motor Control (MMC) system for controlling Linear Motor Systems (LMS) with ease and high precision.
"},{"location":"index.html#getting-started","title":"Getting started","text":""},{"location":"index.html#mmc-server","title":"MMC Server","text":"The MMC Server acts as an endpoint that allows multiple clients to interface with the LMS. The server must run on a PC connected to the first driver of the LMS. Contact our engineers to obtain the MMC Server files and organize them as follows:
mmc-server\n\u251c\u2500 config.json5\n\u251c\u2500 mmc.exe\n\u2514\u2500 mmc.pdb\n Navigate to the mmc-server folder and run the executable: mmc.exe --log_level=info\n"},{"location":"index.html#mmc-api","title":"MMC-API","text":"Our API is built with Protobuf, offering cross-language compatibility to support your programming language of choice. To integrate our API into your program, ensure your working environment supports Protobuf. For complete integration instructions, see the MMC-API Guidelines page.
"},{"location":"index.html#conventions","title":"Conventions","text":"This section defines the terminology used throughout the PMF MMC documentation.
"},{"location":"index.html#system-hierarchy","title":"System Hierarchy","text":"The following terms apply to the PMF MMC system:
Sensor: A hall sensor installed next to a motor to determine the precise location of a carrier on a line.Axis: A functional unit consisting of one motor and the two adjacent hall sensors.Driver: A physical board responsible for controlling one or more axes. The number of axes per driver is defined in the config.json5 file. A single driver can control up to 3 axes.Line: A unit consisting of one or more drivers. Driver, axis, and carrier states are determined on a per-line basis.Track: The highest-level unit in the PMF MMC system, consisting of one or more lines. One MMC Server operates exactly one track.Carrier: Magnet to be moved by PMF's MMC system that is placed on top of LMS. Every carrier must have unique ID per line.Important: ID Indexing
All system IDs (Lines, Drivers, Axes, and Carriers) use 1-based indexing. The first ID is always 1.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
"},{"location":"changelog.html#200-2026-03-16","title":"2.0.0 - 2026-03-16","text":""},{"location":"changelog.html#added","title":"Added","text":"BREAKING: Ability to retrieve all track information without specifying a Line ID Removed:
mmc.info.Request.Track.line\n Use instead: mmc.info.Request.Track.lines\n BREAKING: Track info response structure updated Removed:
mmc.info.Response.Track.line \nmmc.info.Response.Line.line\n Use instead: mmc.info.Response.Track.lines\nmmc.info.Response.Line.id\n BREAKING: velocity and acceleration behaviour Changed unit from dm/s to mm/s and dm/s^2 to mm/s^2 respectively. Additionally changed type from uint32 to float.
mmc_client.Line.velocity\nmmc_client.Line.acceleration\nAutoInitialize.Line.velocity\nAutoInitialize.Line.acceleration\nMove.velocity\nMove.acceleration\nPush.velocity\nPush.acceleration\nPull.velocity\nPull.acceleration\n BREAKING: Error and state enum definitions updated If you were using these error enums, they have been removed:
mmc.command.Request.Error.COMMAND_REQUEST_ERROR_CC_LINK_DISCONNECTED\n Use instead: mmc.info.Response.Command.Error.COMMAND_ERROR_DRIVER_DISCONNECTED\n If you were using these carrier states, they have been removed: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_PUSH_COMPLETED\nmmc.info.Response.Command.Carrier.State.CARRIER_STATE_PULL_COMPLETED\n Use instead: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_MOVE_COMPLETED\n The following error enums were added: mmc.command.Request.Error.COMMAND_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_COMMAND_NOT_FOUND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_CARRIER\n BREAKING: Pull command target behavior Removed:
mmc.command.Request.Pull.Transition.axis\nmmc.command.Request.Pull.Transition.location\nmmc.command.Request.Pull.Transition.distance\n Use instead: mmc.command.Request.Pull.Transition.target\n The behavior of target is equivalent to the previous location field. Additional change: Pass NaN to pull without motor-controlled transition. Release pipeline and artifacts updated
mmc.core.Request.Kind.CORE_REQUEST_KIND_API_VERSION\nmmc.core.Response.api_version\n Use instead: mmc.core.Request.Kind.CORE_REQUEST_KIND_SERVER_INFO\nmmc.core.Response.Server.api\nVelocityMode enum and related fields
mmc.command.Request.VelocityMode\nmmc.command.Request.AutoInitialize.Line.velocity_mode\nmmc.command.Request.Move.velocity_mode\nmmc.command.Request.Push.velocity_mode\nmmc.command.Request.Pull.velocity_mode\n Documentation component sabledocs
This page covers how to use MMC-API to operate on LMS connected to PMF's MMC system.
"},{"location":"mmc-api.html#mmc-api-structure","title":"MMC-API Structure","text":"The MMC API consists of three categories: core, command, and info. Each category contains corresponding requests and responses. Please refer to the protocol documentation page for the expected response for each request.
"},{"location":"mmc-api.html#mmc-core","title":"MMC Core","text":"Use MMC core messages to retrieve server information and track configuration. PMF recommends that clients verify compatibility with the server API version before operation. Starting from version 2.0.0, breaking changes may occur between major versions, therefore clients must ensure they are compatible with the server's API version. Mismatched versions may result in invalid requests or undefined behavior. Clients must fetch the track configuration prior to operating the PMF MMC system to ensure all messages passed to the server contain valid parameters. Refer to the MMC core documentation for a comprehensive list of message types and expected responses.
"},{"location":"mmc-api.html#mmc-command","title":"MMC Command","text":"Use MMC command messages to operate the PMF MMC system. Clients must use the following rules when sending MMC command messages.
remove_command once the command state becomes COMPLETED. Failure to do so will block the queue and prevent the server from accepting further commands.Monitor command status via the command info request defined in the MMC Info section. A list of commands are available on MMC command documentation.
"},{"location":"mmc-api.html#mmc-info","title":"MMC Info","text":"Use MMC info messages to monitor the real-time state of the track and command status. The client can specify which track information to request by enabling the relevant flags within the track info message definition. The API also allows filtering track info based on driver range, axis range, or specific carrier IDs. Refer to the MMC info documentation for the complete message definitions used to request track and command states.
"},{"location":"mmc-api.html#create-request","title":"Create Request","text":"This section demonstrates how to construct and encode a request for transmission. The first example illustrates how to decode and validate a response before use. Subsequent examples will omit the response processing logic to focus on request creation and key considerations for specific commands.
Info
Client must exclusively use the mmc.Request message type to send requests to the server. The server always returns an mmc.Response message to be decoded on client side. Any other message sent to server will return mmc.Response.request_error, showing the message is invalid.
Info
A core request message contains only one enum field. The following example demonstrates how to request the API version used by the server. Other core requests are implemented in the same manner.
Warning
Sending a core request with kind CORE_REQUEST_KIND_SERVER_INFO will always return mmc.Response.core.request_error.
Tip
Zig users can directly use the pmotionf/mmc-api repository for ease of integration. If you are using a different Zig version, generate the Zig files from the source Protobuf files using zig-protobuf library.
const api = @import(\"mmc-api\");\n// Create a request and encode the message. Encode with passing the\n// transport writer interface pointer and allocator. Send the message by \n// flush the writer..\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .core = .{ .kind = .CORE_REQUEST_KIND_SERVER_INFO },\n },\n};\ntry request.encode(&writer.interface, allocator);\ntry writer.interface.flush();\n// Receive and decode the message by passing the reader interface pointer \n// and allocator.\nconst decoded: api.protobuf.mmc.Response = try .decode(\n &client.reader.interface,\n client.allocator,\n);\nswitch (decoded.body orelse std.log.err(\"Invalid Response\",.{})) {\n .core => |core_resp| switch (core_resp.body orelse\n std.log.err(\"Invalid Response\",.{})) {\n .server => |server| std.log.info(\n \"Server API version: {}.{}.{}\",\n .{server.api.major, server.api.minor, server.api.patch,}\n ),\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n },\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n};\n import mmc_pb2 as mmc\n\n# Snipped: Create and connect socket to server\n\n# Create a request message\nrequest = mmc.Request()\nrequest.core.kind = mmc.mmc_dot_core__pb2.Request.CORE_REQUEST_KIND_SERVER_INFO\n\n# Snipped: Send and receive the message\n\n# Parse response\nmsg = mmc.Response()\nmsg.ParseFromString(response)\n\n# Validate and use the response accordingly\nif msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Error: \", mmc.Request.Error.Name(msg.request_error))\nelif msg.WhichOneof(\"body\") == \"core\":\n # Validate if the core response that we receive is `api_version`\n if msg.core.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Error: \",\n mmc.mmc_dot_core__pb2.Request.Error.Name(msg.core.request_error),\n )\n elif msg.core.WhichOneof(\"body\") == \"server\":\n api = msg.core.server.api\n print(\n f\"Server API Version: {api.major}.{api.minor}.{api.patch}\"\n )\n else:\n print(\"Invalid Response\")\nelse:\n print(\"Invalid Response\")\n\ns.close()\n"},{"location":"mmc-api.html#command-request","title":"Command Request","text":"Mandatory Command Cleanup
Every command request returns a unique Command ID. The client is required to:
remove_command once the state reaches COMPLETED or FAILED.Failure to remove finished commands will block the server queue and prevent further command execution.
Check Error Reason
If the command status is FAILED, users can find a descriptive reason by checking the command's error field.
Info
A carrier must be initialized before any actions can be performed. The initialize command is one of many available methods for initializing carriers. This command is sent to the axis specified by the axis parameter.
link_axis field must be ignored.axis parameter must be given as a link_axis, and specified as a direction relative to the provided axis.Unique Carrier ID Requirement
The client must ensure the carrier_id is unique across the entire line. If the ID is already in use by another initialized carrier on the same line, the server will return CONFLICTING_CARRIER_ID.
Example
The following request initializes an uninitialized carrier with ID 1 on the first line in the forward direction. This carrier's position is on top of axis 1 and axis 2.
zigpythonconst api = @import(\"mmc-api\");\n\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .initialize = .{\n .line = 1,\n .axis = 2,\n .carrier = 1,\n .direction = .DIRECTION_BACKWARD,\n .link_axis = .DIRECTION_FORWARD,\n },\n },\n },\n },\n};\n// Snipped content: \n// - Send `initialize` command\n// - Receive command ID as the response of command request\n// - Track command state until state `COMPLETED`\n// - Send `remove_command` command\n// - Receive `removed_id` response as the response of `remove_command` request\n import mmc_pb2 as mmc\n\n# Creating a request message\nCommand = mmc.mmc_dot_command__pb2.Request()\nrequest = mmc.Request()\nrequest.command.initialize.line = 1\nrequest.command.initialize.axis = 2\nrequest.command.initialize.carrier = 1\nrequest.command.initialize.direction = Command.Direction.DIRECTION_FORWARD\nrequest.command.initialize.link_axis = Command.Direction.DIRECTION_BACKWARD\n# Snipped content: \n# - Send `initialize` command\n# - Receive command ID as the response of command request\n# - Track command state until state `COMPLETED`\n# - Send `remove_command` command\n# - Receive `removed_id` response as the response of `remove_command` request\n"},{"location":"mmc-api.html#auto-initialize-carriers","title":"Auto Initialize Carriers","text":"Info
Auto initialize all carriers on the specified lines simultaneously. This process operates on carrier clusters, where a cluster is defined as a group of uninitialized carriers located on adjacent axis.
Warning
Each cluster requires at least one free axis to successfully perform the auto-initialization. Any cluster lacking a free axis will be ignored, and all carriers within that cluster will remain uninitialized upon command completion.
Tip
Ignore the acceleration and velocity fields to use the default values. The default value are:
Example
Auto initialize all carriers on line 1 and line 2.
zigpythonconst api = @import(\"mmc-api\");\n\n// Allocate lines\nvar lines: std.ArrayList(\n api.protobuf.mmc.command.Request.AutoInitialize.Line,\n) = .empty;\ndefer lines.deinit(allocator);\n\n// Define first line\ntry lines.append(allocator, .{\n .line = 1,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Define second line\ntry lines.append(allocator, .{\n .line = 2,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .auto_initialize = .{\n .lines = lines,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n\n# Define first line\nline1 = Command.AutoInitialize.Line()\nline1.line = 1\nline1.velocity = 600\nline1.acceleration = 6000\n\n# Define second line\nline2 = Command.AutoInitialize.Line()\nline2.line = 2\nline2.velocity = 600\nline2.acceleration = 6000\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.auto_initialize.lines.append(line1)\nrequest.command.auto_initialize.lines.append(line2)\n"},{"location":"mmc-api.html#deinitialize-carriers","title":"Deinitialize Carriers","text":"Info
Deinitialize will release motor control on the specified carriers and remove carrier states from MMC system. Deinitialize all carriers on a line by not specifying a target. If a target is specified, carriers are deinitialized based on that target:
Example
Deinitialize carrier 1 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .deinitialize = .{\n .line = line.id,\n .target = .{ .carrier = 1 }\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.deinitialize.line = 1\nrequest.command.deinitialize.carrier = 1\n"},{"location":"mmc-api.html#move-carrier","title":"Move Carrier","text":"Tip
Track the carrier state until it reaches MOVE_COMPLETED before sending further commands to the specified carrier to avoid unwanted behavior. The command state COMPLETED only indicates that the command was successfully received and is being processed by the MMC system.
Warning
The target field must be specified by the user, and only the last target value will be serialized to the server. See Oneof for complete a description on Oneof protobuf type.
Example
Move initialized carrier 1 to axis 3 on the second line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .move = .{\n .line = 2,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .target = .{.axis = 3},\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.move.line = 2\nrequest.command.move.carrier = 1\nrequest.command.move.velocity = 1000\nrequest.command.move.acceleration = 6000\nrequest.command.move.axis = 3\n# mmc.Control() message is not generated by protoc compiler because Python does\n# not allow to use definition based on namespace.\n# 1 for CONTROL_POSITION\n# 2 for CONTROL_VELOCITY.\nrequest.command.move.control = 1\nrequest.command.move.disable_cas = False\n"},{"location":"mmc-api.html#push","title":"Push","text":"Info
Forcefully moves an initialized carrier on the specified axis by one carrier length. Use this movement to cross a line boundary, which deinitializes the carrier from the current line upon completion.
If the carrier field is provided in the push command, the axis enters a pushing state. In this state, the axis remains busy and waits for the specified carrier to arrive; once it arrives, the axis automatically pushes the carrier.
Warning
When pushing the carrier to a different line, the receiving axis on the destination line must be in a pulling state.
Tip
To disable the pushing state on an axis, utilize the stop push command.
Example
Push carrier on axis 1 of line 2 backward to line 1.
Warning
The destination axis on line 1 must be in pulling state.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .push = .{\n .line = 2,\n .axis = 1,\n .direction = .DIRECTION_BACKWARD,\n .velocity = 1000,\n .acceleration = 6000,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.push.line = 2\nrequest.command.push.axis = 1\nrequest.command.push.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.push.velocity = 1000\nrequest.command.push.acceleration = 6000\n"},{"location":"mmc-api.html#pull","title":"Pull","text":"Info
Initialize an incoming carrier located outside the current line. This command puts the specified axis into pulling state. This initialization procedure has the following behavior:
transition field to initialize the carrier at the center of the pulling axistransition field to automatically move to the specified destination as soon as the carrier is recognized.transition, velocity, and acceleration fields to initializes the carrier in the NONE state (not controlled by the motor), allowing it to be moved manually or by external systems.Example
Set axis 6 of line 1 to pulling state, and move the pulled carrier to axis 3.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pull = .{\n .line = 1,\n .axis = 6,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .direction = .DIRECTION_BACKWARD,\n .transition = .{\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n .target = .{.axis = 3},\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.pull.line = 1\nrequest.command.pull.axis = 6\nrequest.command.pull.carrier = 1\nrequest.command.pull.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.pull.velocity = 1000\nrequest.command.pull.acceleration = 6000\nrequest.command.pull.transition.control = 1\nrequest.command.pull.transition.disable_cas = False\nrequest.command.pull.transition.axis = 3\n"},{"location":"mmc-api.html#release-carrier","title":"Release Carrier","text":"Info
Put the initialized carrier into the NONE state, allowing it to be moved manually or by external systems.
Example
Release control of carrier 1 on line 1.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .release = .{\n .line = 1,\n .target = .{.carrier = 1},\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.release.line = 1\nrequest.command.release.carrier = 1\n"},{"location":"mmc-api.html#calibrate-line","title":"Calibrate Line","text":"Info
To calibrate the drivers' configuration on a line, an uninitialized carrier must be located at the center of the first axis
Example
Calibrate the drivers' configuration on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .calibrate = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.calibrate.line = 1\n"},{"location":"mmc-api.html#stop-push","title":"Stop Push","text":"Tip
To reset pushing state on all axis, ignore the axes field.
Example
Reset the pushing state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_push = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_push.line = 1\nrequest.command.stop_push.axes.start = 1\nrequest.command.stop_push.axes.end = 4\n"},{"location":"mmc-api.html#stop-pull","title":"Stop Pull","text":"Tip
To reset the pulling state on all axes, omit the axes field.
Example
Reset the pulling state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_pull = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_pull.line = 1\nrequest.command.stop_pull.axes.start = 1\nrequest.command.stop_pull.axes.end = 4\n"},{"location":"mmc-api.html#set-carrier-id","title":"Set Carrier ID","text":"Warning
The carrier ID of each carrier must be unique within a line.
Example
Change the carrier ID of carrier 1 to 4 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_carrier_id = .{\n .line = 1,\n .carrier = 1,\n .new_carrier = 4,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_carrier_id.line = 1\nrequest.command.set_carrier_id.carrier = 1\nrequest.command.set_carrier_id.new_carrier = 4\n"},{"location":"mmc-api.html#set-zero","title":"Set Zero","text":"Example
Set the zero point of the first line.
Warning
An initialized carrier must be located on the first axis of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_zero = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_zero.line = 1\n"},{"location":"mmc-api.html#clear-errors","title":"Clear Errors","text":"Warning
Always clear errors whenever an error is detected on an axis or driver. Failing to clear errors may result in unwanted behavior.
Tip
Ignore the axes field to clear errors on all drivers and axes on the line.
Example
Clear all errors on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .clear_errors = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.clear_errors.line = 1\n"},{"location":"mmc-api.html#emergency-stop","title":"Emergency Stop","text":"Tip
Pass an empty list to stop operations on all lines.
Example
Stop operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop.lines.extend([])\n"},{"location":"mmc-api.html#pause-execution","title":"Pause Execution","text":"Tip
Pass empty list to pause operations on all lines.
Example
Pause operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pause = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.pause.lines.extend([])\n"},{"location":"mmc-api.html#resume-execution","title":"Resume Execution","text":"Tip
Pass an empty list to resume operation on all lines.
Example
Resume operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .@\"resume\" = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.resume.lines.extend([])\n"},{"location":"mmc-api.html#remove-command","title":"Remove Command","text":"Warning
Failure to remove a command will block the queue and prevent the server from accepting further commands.
Tip
Always check the command status after sending a command message. (Request Command State)
Example
Remove the command with ID 1 from the server.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .remove_command = .{.command = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Creating a request message\nrequest = mmc.Request()\nrequest.command.remove_command.command = id\n"},{"location":"mmc-api.html#info-request","title":"Info Request","text":""},{"location":"mmc-api.html#request-command-state","title":"Request Command State","text":"Example
Wait till the command state becomes COMPLETED or FAILED, then remove the command.
const api = @import(\"mmc-api\");\n\nfn waitCommand(id: u32) !void {\n defer removeCommand(id);\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .command = .{ .id = id },\n },\n },\n },\n };\n while (true) {\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n const command_response = switch (decoded.body orelse\n return error.InvalidResponse) {\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .command => |commands_resp| commands_resp.items.items[0],\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n },\n else => return error.InvalidResponse,\n };\n switch (command_response.status) {\n .COMMAND_STATUS_PROGRESSING => {}, // continue the loop\n .COMMAND_STATUS_COMPLETED => return,\n .COMMAND_STATUS_FAILED => {\n std.log.err(\"{t}\", .{command_response.@\"error\".?});\n return;\n },\n .COMMAND_STATUS_UNSPECIFIED => return error.InvalidResponse,\n }\n }\n}\n import mmc_pb2 as mmc\n\ndef waitCommand(id):\n # Creating a request message\n request = mmc.Request()\n request.info.command.id = id\n while True:\n # Send and receive response\n s.sendall(request.SerializeToString())\n response = s.recv(4096)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n Command = mmc.mmc_dot_info__pb2.Response.Command()\n\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n return\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n return\n elif msg.info.WhichOneof(\"body\") == \"command\":\n command = msg.info.command.items[0]\n if command.status == Command.Status.COMMAND_STATUS_COMPLETED:\n removeCommand(id)\n return\n elif command.status == Command.Status.COMMAND_STATUS_FAILED:\n removeCommand(id)\n raise Exception(Command.Error.Name(command.error))\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n"},{"location":"mmc-api.html#request-track-state","title":"Request Track State","text":"Tip
Certain commands require the client to monitor carrier status to ensure movement is completed.
MOVE_COMPLETED before sending a new command to that carrier.CALIBRATE_COMPLETED to ensure the driver configuration is valid.INITIALIZE_COMPLETED before performing further operations on the carrier.transition field is omitted, wait for PULL_COMPLETED; otherwise, wait for MOVE_COMPLETED.Warning
Monitor the error flags of driver, axis and carriers to prevent damage to the motor or driver board. Pay close attention to inverter_overheat on the driver and overcurrent flags on the axis; immediately deinitialize any carrier on the affected axes and drivers if these are detected. The overvoltage and undervoltage flags indicate that the system voltage supply may have a problem; please consult with our engineers to resolve the issue.
Request carrier state
Tip
filter field when sending track info message to retrieve all toggled flags information.const api = @import(\"mmc-api\");\nfn carrierState(line: u32, carrier: u32) !void {\n var carrier_id = [1]u32{carrier};\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .track = .{\n .line = line,\n .info_carrier_state = true,\n .filter = .{\n .carriers = .{\n .ids = .fromOwnedSlice(&carrier_id),\n },\n },\n },\n },\n },\n },\n };\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n switch (decoded.body orelse return error.InvalidResponse) {\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .track => |track_resp| {\n std.log.info(\"{}\", .{track_resp.carrier_state.items[0]});\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n },\n else => return error.InvalidResponse,\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n }\n}\n import mmc_pb2 as mmc\ndef carrierState(line, carrier):\n # Creating a request message\n request = mmc.Request()\n request.info.track.line = line\n request.info.track.info_carrier_state = True\n request.info.track.carriers.ids.append(carrier)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n elif msg.info.WhichOneof(\"body\") == \"track\":\n assert len(msg.info.track.carrier_state) != 0\n carrier = msg.info.track.carrier_state[0]\n print(carrier)\n else:\n print(\"Invalid Response\")\n else:\n print(\"Invalid Response\")\n"},{"location":"protocol-documentation.html","title":"Protocol Documentation","text":""},{"location":"protocol-documentation.html#table-of-contents","title":"Table of Contents","text":"mmc.proto
Response
Request.Error
range.proto
mmc/command.proto
Response
Request.Direction
mmc/control.proto
mmc/core.proto
Response.TrackConfig.Line
Request.Error
mmc/info.proto
Response.Track
Request.Error
Scalar Value Types
Top
"},{"location":"protocol-documentation.html#mmcproto","title":"mmc.proto","text":""},{"location":"protocol-documentation.html#request","title":"Request","text":"Request message. All client-to-server messages should be of this message type.
Field Type Label Description core core.Request Core request. Used to retrieve information about the server or the configured track. command command.Request Command request. Used to send and manage commands to the server, which will execute commands on the connected track. info info.Request Info request. Used to retrieve information about track state or commands processed by the server. "},{"location":"protocol-documentation.html#response","title":"Response","text":"Response message. All server-to-client messages will be of this message type.
Field Type Label Description core core.Response Core response. command command.Response Command response. info info.Response Info Response. request_error Request.Error Top-level request error. This error field will be returned only if the top-level request could not be handled properly. Otherwise, response kinds may contain more specific error codes. "},{"location":"protocol-documentation.html#requesterror","title":"Request.Error","text":"Name Number Description MMC_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. MMC_REQUEST_ERROR_INVALID_MESSAGE 1 The request could not be decoded as a valid protobuf message.Top
"},{"location":"protocol-documentation.html#rangeproto","title":"range.proto","text":""},{"location":"protocol-documentation.html#range","title":"Range","text":"Field Type Label Description start uint32 Start of range, inclusive. end uint32 End of range, inclusive.Top
"},{"location":"protocol-documentation.html#mmccommandproto","title":"mmc/command.proto","text":""},{"location":"protocol-documentation.html#request_1","title":"Request","text":"Command API: List of commands to operate the PMF's motion system.
When a command is sent to the server, it will be queued for execution. Command execution status can be polled through the Info API. The status remains stored in a limited history buffer, and should be cleared with remove_command after completion.
Automatically initialize carriers on every specified lines.
Expected response: mmc.Response.body.command.body.id (uint32).
Calibrate a line by positioning an uninitialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear all error information on the driver. If a target is specified, clear error information of drivers included in that target. If not, clear error information on all drivers of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear carrier information located on the axis. If a target is specified, clear information of carriers included in that target. If not, clear all carrier information of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Initialize a carrier.
Expected response: mmc.Response.body.command.body.id (uint32).
Move a carrier to the desired position.
Expected response: mmc.Response.body.command.body.id (uint32).
SetZero command. distance float Move carrier to relative distance to current carrier position. Negative distance moves the carrier backwards. control mmc.Control Control method for moving carrier. disable_cas bool Disable the carrier's collision avoidance system (CAS). "},{"location":"protocol-documentation.html#requestpause","title":"Request.Pause","text":"Pause any operation in PMF LMS. Any queued commands in the server will be continued once the resume command is given.
Expected response: mmc.Response.body.command.body.id (uint32).
Pull and initialize a new carrier into a line.
Expected response: mmc.Response.body.command.body.id (uint32).
NaN, the velocity must be 0. acceleration float Acceleration of carrier movement. Floating point with range 100 - 24,500 mm/s^2. When the transition location target is set to NaN, the acceleration must be 0. transition Request.Pull.Transition optional Smoothly transition to carrier movement after pull completion. "},{"location":"protocol-documentation.html#requestpulltransition","title":"Request.Pull.Transition","text":"Field Type Label Description control mmc.Control Control method for moving carrier. disable_cas bool Disabling the carrier's collision avoidance system (CAS). target float Move carrier to relative location to the zero-point of the line, which is set by default at the center of the line's first axis after calibration, but can also be set with the SetZero command. Pass NaN to pull carrier without motor control, allowing carrier to be pulled with external force."},{"location":"protocol-documentation.html#requestpush","title":"Request.Push","text":"Push an initialized carrier to the specified direction.
Expected response: mmc.Response.body.command.body.id (uint32).
Release the control imposed by the motor to the carrier. If a target is specified, all motors included in that target release control. Otherwise, all carriers on the provided line will be released from control.
Expected response: mmc.Response.body.command.body.id (uint32).
Remove a command on the server if the command ID is specified. If no command ID is specified, remove any commands received by the server. If the commands are still progressing, cancel the command execution.
Expected response: mmc.Response.body.command.body.removed_id (uint32).
Resume lines that have been stopped or paused. If the line is not paused or emergency stopped, this command will succeed without any effect.
Expected response: mmc.Response.body.command.body.id (uint32).
Change the carrier ID of an existing initialized carrier. If the new carrier ID already exists on the line, returns INVALID_CARRIER.
Expected response: mmc.Response.body.command.body.id (uint32).
Set a zero position of a line by positioning an initialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Send an emergency stop command to stop any operation in PMF LMS. This command also removes all queued commands in the server.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pulling a carrier to the specified axis. If no axis is provided, then all pending carrier pulls on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pushing a carrier from the specified axis. If no axis is provided, then all pending carrier pushes on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Response description to the command API.
Field Type Label Description id uint32 Assigned ID for newly sent command. removed_id uint32 ID of cleared existing command. request_error Request.Error Error during command's execution. "},{"location":"protocol-documentation.html#requestdirection","title":"Request.Direction","text":"Name Number Description DIRECTION_UNSPECIFIED 0 DIRECTION_BACKWARD 1 DIRECTION_FORWARD 2"},{"location":"protocol-documentation.html#requesterror_1","title":"Request.Error","text":"Name Number Description COMMAND_REQUEST_ERROR_UNSPECIFIED 0 COMMAND_REQUEST_ERROR_INVALID_LINE 1 Attempted to use line ID outside of the configured lines. COMMAND_REQUEST_ERROR_INVALID_AXIS 2 Attempted to use axis ID outside of the configured axes of the line. COMMAND_REQUEST_ERROR_INVALID_DRIVER 3 Attempted to use driver ID outside of the configured drivers of the line. COMMAND_REQUEST_ERROR_INVALID_ACCELERATION 4 Attempted to use acceleration value outside of 1-245. COMMAND_REQUEST_ERROR_INVALID_VELOCITY 5 Attempted to use velocity value outside of 1-60. COMMAND_REQUEST_ERROR_INVALID_DIRECTION 6 Using invalid direction for the command. COMMAND_REQUEST_ERROR_INVALID_LOCATION 7 Deprecated. CheckCOMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_DISTANCE 8 Deprecated. Check COMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_CARRIER 9 Attempted to send a command to carrier outside of 1-2048. COMMAND_REQUEST_ERROR_MISSING_PARAMETER 10 A command missing the required parameter. COMMAND_REQUEST_ERROR_COMMAND_NOT_FOUND 11 Attempted to remove or cancel a non-existing command. COMMAND_REQUEST_ERROR_CARRIER_NOT_FOUND 12 Attempted to send command to an uninitialized carrier. COMMAND_REQUEST_ERROR_OUT_OF_MEMORY 14 Server unable to receive new command caused by out of memory. Try Command.Request.remove_command to free the memory. COMMAND_REQUEST_ERROR_MAXIMUM_AUTO_INITIALIZE_EXCEEDED 15 Attempted to run more than 8 auto initialize instance. COMMAND_REQUEST_ERROR_CONFLICTING_CARRIER_ID 16 Attempted to assign a carrier ID that is already used by another carrier on the same line. COMMAND_REQUEST_ERROR_INVALID_COMMAND 17 Command index is out of bounds for the configured command status buffer. Top
"},{"location":"protocol-documentation.html#mmccontrolproto","title":"mmc/control.proto","text":""},{"location":"protocol-documentation.html#control","title":"Control","text":"Carrier motor control kind.
Name Number Description CONTROL_UNSPECIFIED 0 CONTROL_POSITION 1 Carrier controlled with position priority. CONTROL_VELOCITY 2 Carrier controlled with velocity priority.Top
"},{"location":"protocol-documentation.html#mmccoreproto","title":"mmc/core.proto","text":""},{"location":"protocol-documentation.html#request_2","title":"Request","text":"Field Type Label Description kind Request.Kind"},{"location":"protocol-documentation.html#response_2","title":"Response","text":"Response description to the core API.
Field Type Label Description server Response.Server Server process information. track_config Response.TrackConfig Track configuration. request_error Request.Error Error response if the core request could not be handled. "},{"location":"protocol-documentation.html#responsesemanticversion","title":"Response.SemanticVersion","text":"Field Type Label Description major uint32 minor uint32 patch uint32"},{"location":"protocol-documentation.html#responseserver","title":"Response.Server","text":"Server version and name.
Field Type Label Description name string Server name. version Response.SemanticVersion Server implementation version. api Response.SemanticVersion "},{"location":"protocol-documentation.html#responsetrackconfig","title":"Response.TrackConfig","text":"Field Type Label Description lines Response.TrackConfig.Line repeated All configured lines in track."},{"location":"protocol-documentation.html#responsetrackconfigline","title":"Response.TrackConfig.Line","text":"Field Type Label Description id uint32 Line ID. Numeric ID, starting from 1, that is unique to each line in the track. This ID is used to address the line in other requests. name string Configured line name. This name is otherwise unused by the API, and is provided to the client for end-user convenience. axes uint32 Total number of axes in the line. axis_length float Length of each axis in the line, in meters. carrier_length float Carrier magnet length, in meters. drivers uint32 Total number of drivers in the line."},{"location":"protocol-documentation.html#requesterror_2","title":"Request.Error","text":"Name Number Description CORE_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. CORE_REQUEST_ERROR_REQUEST_UNKNOWN 1 The core request kind was unspecified."},{"location":"protocol-documentation.html#requestkind","title":"Request.Kind","text":"Name Number Description CORE_REQUEST_KIND_UNSPECIFIED 0 This request kind is unused, and should never be sent. It is reserved as the default request kind according to protobuf specification. CORE_REQUEST_KIND_SERVER_INFO 2 Request server process information. This includes the configured server name and server implementation version. CORE_REQUEST_KIND_TRACK_CONFIG 3 Request the configured track information of the server.Top
"},{"location":"protocol-documentation.html#mmcinfoproto","title":"mmc/info.proto","text":""},{"location":"protocol-documentation.html#request_3","title":"Request","text":"Field Type Label Description command Request.Command Command information request. Get current status of command; necessary to determine if command is currently running, completed, or failed. track Request.Track Track information request. Get current track state information."},{"location":"protocol-documentation.html#requestcommand","title":"Request.Command","text":"Request for status of specified command ID from the server. If no command ID is provided, then request for status of all commands from the server.
Expected response: mmc.Response.body.info.body.commands
Request track state information from server. One or more of the info_ flags must be enabled to select the kind of track information desired. A filter may be optionally provided to limit the source of information from the track.
Expected response: mmc.Response.body.info.body.track
List of IDs. At least one ID must be provided.
Field Type Label Description ids uint32 repeated "},{"location":"protocol-documentation.html#response_3","title":"Response","text":"Field Type Label Description command Response.Commands Information for requested command(s). If empty, no matching command(s) was found. track Response.Track Information for requested track state. request_error Request.Error Info request error. This error field will be returned if the provided info request could not be handled properly."},{"location":"protocol-documentation.html#responsecommand","title":"Response.Command","text":"Field Type Label Description id uint32 Command ID. Valid IDs begin from 1, and may be reused after command status is cleared from server history. status Response.Command.Status Command status. error Response.Command.Error optional Command error response, only if the status isCOMMAND_STATUS_FAILED."},{"location":"protocol-documentation.html#responsecommands","title":"Response.Commands","text":"Field Type Label Description items Response.Command repeated"},{"location":"protocol-documentation.html#responseline","title":"Response.Line","text":"Field Type Label Description id uint32 Line ID. driver_state Response.Line.Driver.State repeated Driver state information list. Empty if request flag was disabled. driver_errors Response.Line.Driver.Error repeated Driver error information list. Empty if request flag was disabled. axis_state Response.Line.Axis.State repeated Axis state information list. Empty if request flag was disabled. axis_errors Response.Line.Axis.Error repeated Axis error information list. Empty if request flag was disabled. carrier_state Response.Line.Carrier.State repeated Carrier state information list. Empty if request flag was disabled."},{"location":"protocol-documentation.html#responselineaxis","title":"Response.Line.Axis","text":""},{"location":"protocol-documentation.html#responselineaxiserror","title":"Response.Line.Axis.Error","text":"Field Type Label Description id uint32 Axis ID. overcurrent bool Motor overcurrent detected. Motor control released to prevent damage."},{"location":"protocol-documentation.html#responselineaxisstate","title":"Response.Line.Axis.State","text":"Field Type Label Description id uint32 Axis ID. motor_active bool Axis is currently controlling a carrier. waiting_pull bool Axis is waiting to pull carrier. waiting_push bool Axis is waiting to push carrier. carrier uint32 Carrier ID; non-zero if an initialized carrier is on the axis. hall_alarm_back bool Axis back hall alarm is active. Magnet is detected above back hall sensor. hall_alarm_front bool Axis front hall alarm is active. Magnet is detected above front hall sensor."},{"location":"protocol-documentation.html#responselinecarrier","title":"Response.Line.Carrier","text":""},{"location":"protocol-documentation.html#responselinecarrierstate","title":"Response.Line.Carrier.State","text":"Field Type Label Description id uint32 Carrier ID. Will always be non-zero. position float Position of the carrier in line, in meters. axis_main uint32 Carrier's primary axis ID. axis_auxiliary uint32 optional Carrier's auxiliary axis ID, if carrier is on top of two axes. cas_disabled bool Collision avoidance system (CAS) disabled. cas_triggered bool Collision avoidance system (CAS) triggered. Carrier will automatically resume movement when path is clear. state Response.Line.Carrier.State.State Carrier state."},{"location":"protocol-documentation.html#responselinedriver","title":"Response.Line.Driver","text":""},{"location":"protocol-documentation.html#responselinedrivererror","title":"Response.Line.Driver.Error","text":"Field Type Label Description id uint32 Driver ID. control_loop_time_exceeded bool Control loop exceeded maximum loop time. inverter_overheat bool Inverter is overheated. undervoltage bool Driver voltage supply too low. overvoltage bool Driver voltage supply too high. comm_error_prev bool Communication error with previous driver in line. comm_error_next bool Communication error with next driver in line."},{"location":"protocol-documentation.html#responselinedriverstate","title":"Response.Line.Driver.State","text":"Field Type Label Description id uint32 Driver ID. connected bool Connection status between driver and server. busy bool Driver is currently executing a command. motor_disabled bool Driver motor release activated. All driver motors are inactive. stopped bool Driver emergency stop activated. paused bool Driver pause activated."},{"location":"protocol-documentation.html#responsetrack","title":"Response.Track","text":"Field Type Label Description lines Response.Line repeated"},{"location":"protocol-documentation.html#requesterror_3","title":"Request.Error","text":"Name Number Description INFO_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. INFO_REQUEST_ERROR_INVALID_LINE 1 Invalid line ID provided. Ensure that line ID exists in track configuration. INFO_REQUEST_ERROR_INVALID_AXIS 2 Invalid axis ID provided. Ensure that axis ID exists in line. INFO_REQUEST_ERROR_INVALID_DRIVER 3 Invalid driver ID provided. Ensure that driver ID exists in line. INFO_REQUEST_ERROR_MISSING_PARAMETER 4 Request is missing a required parameter. Ensure that at least one of the information flag is selected when requesting track information. INFO_REQUEST_ERROR_COMMAND_NOT_FOUND 5 Attempted to request information from a non-existing command. INFO_REQUEST_ERROR_INVALID_COMMAND 6 Command index is out of bounds for the configured command status buffer. INFO_REQUEST_ERROR_INVALID_CARRIER 7 Attempted to send a command to carrier outside of range."},{"location":"protocol-documentation.html#responsecommanderror","title":"Response.Command.Error","text":"Name Number Description COMMAND_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. COMMAND_ERROR_INVALID_SYSTEM_STATE 1 System state prevented successful command execution. Ensure that all preconditions are met with track info request before sending command. COMMAND_ERROR_INVALID_CARRIER_ID 2 Deprecated. Check COMMAND_REQUEST_ERROR_INVALID_CARRIER on Command.Request.Error. COMMAND_ERROR_DRIVER_DISCONNECTED 3 Driver connection failed while command progressing. COMMAND_ERROR_UNEXPECTED 4 Unexpected command execution error. This is likely an implementation bug; please contact PMF support for assistance. COMMAND_ERROR_CARRIER_NOT_FOUND 5 Target carrier is removed while command progressing. COMMAND_ERROR_CARRIER_ALREADY_INITIALIZED 6 Attempted to initialize an initialized carrier. COMMAND_ERROR_DRIVER_STOPPED 7 Target driver is stopped while command progressing. Consider resume the driver before sending further command. COMMAND_ERROR_INVALID_CARRIER_TARGET 8 Carrier targeting a location outside of the configured track. COMMAND_ERROR_CONFLICTING_CARRIER_ID 9 Attempted to assign a new carrier with an ID that is already used by other carrier on the same line"},{"location":"protocol-documentation.html#responsecommandstatus","title":"Response.Command.Status","text":"Name Number Description COMMAND_STATUS_UNSPECIFIED 0 This command status is unused, and will never be returned. It is reserved as the default status code according to protobuf specification. COMMAND_STATUS_PROGRESSING 1 Command currently executing. COMMAND_STATUS_COMPLETED 2 Command completed. COMMAND_STATUS_FAILED 3 Command execution failed."},{"location":"protocol-documentation.html#responselinecarrierstatestate","title":"Response.Line.Carrier.State.State","text":"Name Number Description CARRIER_STATE_NONE 0 CARRIER_STATE_CALIBRATING 1 Carrier is currently operating for line calibration. CARRIER_STATE_CALIBRATE_COMPLETED 2 Carrier has completed line calibration, and may now be used for normal operation. CARRIER_STATE_MOVING 3 Carrier is currently moving towards target destination. CARRIER_STATE_MOVE_COMPLETED 4 Carrier has arrived within threshold at target destination. CARRIER_STATE_INITIALIZING 5 Carrier is initializing. Must not be used until initialization is completed. CARRIER_STATE_INITIALIZE_COMPLETED 6 Carrier initialization completed. May now be used for normal operation. CARRIER_STATE_PUSHING 7 Carrier is being pushed by axis. Used to eject carrier from line. CARRIER_STATE_PULLING 9 Carrier is being pulled by axis. Must not be used until pull is completed. CARRIER_STATE_OVERCURRENT 11 Overcurrent detected in carrier axis motor. Carrier movement has been canceled."},{"location":"protocol-documentation.html#scalar-value-types","title":"Scalar Value Types","text":".proto Type Notes C++ Java Python Go C# PHP Ruby double double double float float64 double float Float float float float float float32 float float Float int32 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required) int64 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required) uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required) sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required) sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required) fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required) sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum bool bool boolean boolean bool bool boolean TrueClass/FalseClass string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8) bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)"}]}
\ No newline at end of file
+var __index = {"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"index.html","title":"PMF MMC system","text":"PMF provides the Motion Motor Control (MMC) system for controlling Linear Motor Systems (LMS) with ease and high precision.
"},{"location":"index.html#getting-started","title":"Getting started","text":""},{"location":"index.html#mmc-server","title":"MMC Server","text":"The MMC Server acts as an endpoint that allows multiple clients to interface with the LMS. The server must run on a PC connected to the first driver of the LMS. Contact our engineers to obtain the MMC Server files and organize them as follows:
mmc-server\n\u251c\u2500 config.json5\n\u251c\u2500 mmc.exe\n\u2514\u2500 mmc.pdb\n Navigate to the mmc-server folder and run the executable: mmc.exe --log_level=info\n"},{"location":"index.html#mmc-api","title":"MMC-API","text":"Our API is built with Protobuf, offering cross-language compatibility to support your programming language of choice. To integrate our API into your program, ensure your working environment supports Protobuf. For complete integration instructions, see the MMC-API Guidelines page.
"},{"location":"index.html#conventions","title":"Conventions","text":"This section defines the terminology used throughout the PMF MMC documentation.
"},{"location":"index.html#system-hierarchy","title":"System Hierarchy","text":"The following terms apply to the PMF MMC system:
Sensor: A hall sensor installed next to a motor to determine the precise location of a carrier on a line.Axis: A functional unit consisting of one motor and the two adjacent hall sensors.Driver: A physical board responsible for controlling one or more axes. The number of axes per driver is defined in the config.json5 file. A single driver can control up to 3 axes.Line: A unit consisting of one or more drivers. Driver, axis, and carrier states are determined on a per-line basis.Track: The highest-level unit in the PMF MMC system, consisting of one or more lines. One MMC Server operates exactly one track.Carrier: Magnet to be moved by PMF's MMC system that is placed on top of LMS. Every carrier must have unique ID per line.Important: ID Indexing
All system IDs (Lines, Drivers, Axes, and Carriers) use 1-based indexing. The first ID is always 1.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
"},{"location":"changelog.html#200-2026-03-16","title":"2.0.0 - 2026-03-16","text":""},{"location":"changelog.html#added","title":"Added","text":"BREAKING: Ability to retrieve all track information without specifying a Line ID Removed:
mmc.info.Request.Track.line\n Use instead: mmc.info.Request.Track.lines\n BREAKING: Track info response structure updated Removed:
mmc.info.Response.Track.line \nmmc.info.Response.Line.line\n Use instead: mmc.info.Response.Track.lines\nmmc.info.Response.Line.id\n BREAKING: velocity and acceleration behaviour Changed unit from dm/s to mm/s and dm/s^2 to mm/s^2 respectively. Additionally changed type from uint32 to float.
mmc_client.Line.velocity\nmmc_client.Line.acceleration\nAutoInitialize.Line.velocity\nAutoInitialize.Line.acceleration\nMove.velocity\nMove.acceleration\nPush.velocity\nPush.acceleration\nPull.velocity\nPull.acceleration\n BREAKING: Error and state enum definitions updated If you were using these error enums, they have been removed:
mmc.command.Request.Error.COMMAND_REQUEST_ERROR_CC_LINK_DISCONNECTED\n Use instead: mmc.info.Response.Command.Error.COMMAND_ERROR_DRIVER_DISCONNECTED\n If you were using these carrier states, they have been removed: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_PUSH_COMPLETED\nmmc.info.Response.Command.Carrier.State.CARRIER_STATE_PULL_COMPLETED\n Use instead: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_MOVE_COMPLETED\n The following error enums were added: mmc.command.Request.Error.COMMAND_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_COMMAND_NOT_FOUND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_CARRIER\n BREAKING: Pull command target behavior Removed:
mmc.command.Request.Pull.Transition.axis\nmmc.command.Request.Pull.Transition.location\nmmc.command.Request.Pull.Transition.distance\n Use instead: mmc.command.Request.Pull.Transition.target\n The behavior of target is equivalent to the previous location field. Additional change: Pass NaN to pull without motor-controlled transition. Release pipeline and artifacts updated
mmc.core.Request.Kind.CORE_REQUEST_KIND_API_VERSION\nmmc.core.Response.api_version\n Use instead: mmc.core.Request.Kind.CORE_REQUEST_KIND_SERVER_INFO\nmmc.core.Response.Server.api\nVelocityMode enum and related fields
mmc.command.Request.VelocityMode\nmmc.command.Request.AutoInitialize.Line.velocity_mode\nmmc.command.Request.Move.velocity_mode\nmmc.command.Request.Push.velocity_mode\nmmc.command.Request.Pull.velocity_mode\n Documentation component sabledocs
This page covers how to use MMC-API to operate on LMS connected to PMF's MMC system.
"},{"location":"mmc-api.html#mmc-api-structure","title":"MMC-API Structure","text":"The MMC API consists of three categories: core, command, and info. Each category contains corresponding requests and responses. Please refer to the protocol documentation page for the expected response for each request.
"},{"location":"mmc-api.html#mmc-core","title":"MMC Core","text":"Use MMC core messages to retrieve server information and track configuration. PMF recommends that clients verify compatibility with the server API version before operation. Starting from version 2.0.0, breaking changes may occur between major versions, therefore clients must ensure they are compatible with the server's API version. Mismatched versions may result in invalid requests or undefined behavior. Clients must fetch the track configuration prior to operating the PMF MMC system to ensure all messages passed to the server contain valid parameters. Refer to the MMC core documentation for a comprehensive list of message types and expected responses.
"},{"location":"mmc-api.html#mmc-command","title":"MMC Command","text":"Use MMC command messages to operate the PMF MMC system. Clients must use the following rules when sending MMC command messages.
remove_command once the command state becomes COMPLETED. Failure to do so will block the queue and prevent the server from accepting further commands.Monitor command status via the command info request defined in the MMC Info section. A list of commands are available on MMC command documentation.
"},{"location":"mmc-api.html#mmc-info","title":"MMC Info","text":"Use MMC info messages to monitor the real-time state of the track and command status. The client can specify which track information to request by enabling the relevant flags within the track info message definition. The API also allows filtering track info based on driver range, axis range, or specific carrier IDs. Refer to the MMC info documentation for the complete message definitions used to request track and command states.
"},{"location":"mmc-api.html#create-request","title":"Create Request","text":"This section demonstrates how to construct and encode a request for transmission. The first example illustrates how to decode and validate a response before use. Subsequent examples will omit the response processing logic to focus on request creation and key considerations for specific commands.
Info
Client must exclusively use the mmc.Request message type to send requests to the server. The server always returns an mmc.Response message to be decoded on client side. Any other message sent to server will return mmc.Response.request_error, showing the message is invalid.
Info
A core request message contains only one enum field. The following example demonstrates how to request the API version used by the server. Other core requests are implemented in the same manner.
Warning
Sending a core request with kind CORE_REQUEST_KIND_SERVER_INFO will always return mmc.Response.core.request_error.
Tip
Zig users can directly use the pmotionf/mmc-api repository for ease of integration. If you are using a different Zig version, generate the Zig files from the source Protobuf files using zig-protobuf library.
const api = @import(\"mmc-api\");\n// Create a request and encode the message. Encode with passing the\n// transport writer interface pointer and allocator. Send the message by \n// flush the writer..\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .core = .{ .kind = .CORE_REQUEST_KIND_SERVER_INFO },\n },\n};\ntry request.encode(&writer.interface, allocator);\ntry writer.interface.flush();\n// Receive and decode the message by passing the reader interface pointer \n// and allocator.\nconst decoded: api.protobuf.mmc.Response = try .decode(\n &client.reader.interface,\n client.allocator,\n);\nswitch (decoded.body orelse std.log.err(\"Invalid Response\",.{})) {\n .core => |core_resp| switch (core_resp.body orelse\n std.log.err(\"Invalid Response\",.{})) {\n .server => |server| std.log.info(\n \"Server API version: {}.{}.{}\",\n .{server.api.major, server.api.minor, server.api.patch,}\n ),\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n },\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n};\n import mmc_pb2 as mmc\n\n# Snipped: Create and connect socket to server\n\n# Create a request message\nrequest = mmc.Request()\nrequest.core.kind = mmc.mmc_dot_core__pb2.Request.CORE_REQUEST_KIND_SERVER_INFO\n\n# Snipped: Send and receive the message\n\n# Parse response\nmsg = mmc.Response()\nmsg.ParseFromString(response)\n\n# Validate and use the response accordingly\nif msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Error: \", mmc.Request.Error.Name(msg.request_error))\nelif msg.WhichOneof(\"body\") == \"core\":\n # Validate if the core response that we receive is `api_version`\n if msg.core.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Error: \",\n mmc.mmc_dot_core__pb2.Request.Error.Name(msg.core.request_error),\n )\n elif msg.core.WhichOneof(\"body\") == \"server\":\n api = msg.core.server.api\n print(\n f\"Server API Version: {api.major}.{api.minor}.{api.patch}\"\n )\n else:\n print(\"Invalid Response\")\nelse:\n print(\"Invalid Response\")\n\ns.close()\n"},{"location":"mmc-api.html#command-request","title":"Command Request","text":"Mandatory Command Cleanup
Every command request returns a unique Command ID. The client is required to:
remove_command once the state reaches COMPLETED or FAILED.Failure to remove finished commands will block the server queue and prevent further command execution.
Check Error Reason
If the command status is FAILED, users can find a descriptive reason by checking the command's error field.
Info
A carrier must be initialized before any actions can be performed. The initialize command is one of many available methods for initializing carriers. This command is sent to the axis specified by the axis parameter.
link_axis field must be ignored.axis parameter must be given as a link_axis, and specified as a direction relative to the provided axis.Unique Carrier ID Requirement
The client must ensure the carrier_id is unique across the entire line. If the ID is already in use by another initialized carrier on the same line, the server will return CONFLICTING_CARRIER_ID.
Example
The following request initializes an uninitialized carrier with ID 1 on the first line in the forward direction. This carrier's position is on top of axis 1 and axis 2.
zigpythonconst api = @import(\"mmc-api\");\n\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .initialize = .{\n .line = 1,\n .axis = 2,\n .carrier = 1,\n .direction = .DIRECTION_BACKWARD,\n .link_axis = .DIRECTION_FORWARD,\n },\n },\n },\n },\n};\n// Snipped content: \n// - Send `initialize` command\n// - Receive command ID as the response of command request\n// - Track command state until state `COMPLETED`\n// - Send `remove_command` command\n// - Receive `removed_id` response as the response of `remove_command` request\n import mmc_pb2 as mmc\n\n# Creating a request message\nCommand = mmc.mmc_dot_command__pb2.Request()\nrequest = mmc.Request()\nrequest.command.initialize.line = 1\nrequest.command.initialize.axis = 2\nrequest.command.initialize.carrier = 1\nrequest.command.initialize.direction = Command.Direction.DIRECTION_FORWARD\nrequest.command.initialize.link_axis = Command.Direction.DIRECTION_BACKWARD\n# Snipped content: \n# - Send `initialize` command\n# - Receive command ID as the response of command request\n# - Track command state until state `COMPLETED`\n# - Send `remove_command` command\n# - Receive `removed_id` response as the response of `remove_command` request\n"},{"location":"mmc-api.html#auto-initialize-carriers","title":"Auto Initialize Carriers","text":"Info
Auto initialize all carriers on the specified lines simultaneously. This process operates on carrier clusters, where a cluster is defined as a group of uninitialized carriers located on adjacent axis.
Warning
Each cluster requires at least one free axis to successfully perform the auto-initialization. Any cluster lacking a free axis will be ignored, and all carriers within that cluster will remain uninitialized upon command completion.
Tip
Ignore the acceleration and velocity fields to use the default values. The default value are:
Example
Auto initialize all carriers on line 1 and line 2.
zigpythonconst api = @import(\"mmc-api\");\n\n// Allocate lines\nvar lines: std.ArrayList(\n api.protobuf.mmc.command.Request.AutoInitialize.Line,\n) = .empty;\ndefer lines.deinit(allocator);\n\n// Define first line\ntry lines.append(allocator, .{\n .line = 1,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Define second line\ntry lines.append(allocator, .{\n .line = 2,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .auto_initialize = .{\n .lines = lines,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n\n# Define first line\nline1 = Command.AutoInitialize.Line()\nline1.line = 1\nline1.velocity = 600\nline1.acceleration = 6000\n\n# Define second line\nline2 = Command.AutoInitialize.Line()\nline2.line = 2\nline2.velocity = 600\nline2.acceleration = 6000\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.auto_initialize.lines.append(line1)\nrequest.command.auto_initialize.lines.append(line2)\n"},{"location":"mmc-api.html#deinitialize-carriers","title":"Deinitialize Carriers","text":"Info
Deinitialize will release motor control on the specified carriers and remove carrier states from MMC system. Deinitialize all carriers on a line by not specifying a target. If a target is specified, carriers are deinitialized based on that target:
Example
Deinitialize carrier 1 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .deinitialize = .{\n .line = line.id,\n .target = .{ .carrier = 1 }\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.deinitialize.line = 1\nrequest.command.deinitialize.carrier = 1\n"},{"location":"mmc-api.html#move-carrier","title":"Move Carrier","text":"Tip
Track the carrier state until it reaches MOVE_COMPLETED before sending further commands to the specified carrier to avoid unwanted behavior. The command state COMPLETED only indicates that the command was successfully received and is being processed by the MMC system.
Warning
The target field must be specified by the user, and only the last target value will be serialized to the server. See Oneof for complete a description on Oneof protobuf type.
Example
Move initialized carrier 1 to axis 3 on the second line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .move = .{\n .line = 2,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .target = .{.axis = 3},\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.move.line = 2\nrequest.command.move.carrier = 1\nrequest.command.move.velocity = 1000\nrequest.command.move.acceleration = 6000\nrequest.command.move.axis = 3\n# mmc.Control() message is not generated by protoc compiler because Python does\n# not allow to use definition based on namespace.\n# 1 for CONTROL_POSITION\n# 2 for CONTROL_VELOCITY.\nrequest.command.move.control = 1\nrequest.command.move.disable_cas = False\n"},{"location":"mmc-api.html#push","title":"Push","text":"Info
Forcefully moves an initialized carrier on the specified axis by one carrier length. Use this movement to cross a line boundary, which deinitializes the carrier from the current line upon completion.
If the carrier field is provided in the push command, the axis enters a pushing state. In this state, the axis remains busy and waits for the specified carrier to arrive; once it arrives, the axis automatically pushes the carrier.
Warning
When pushing the carrier to a different line, the receiving axis on the destination line must be in a pulling state.
Tip
To disable the pushing state on an axis, utilize the stop push command.
Example
Push carrier on axis 1 of line 2 backward to line 1.
Warning
The destination axis on line 1 must be in pulling state.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .push = .{\n .line = 2,\n .axis = 1,\n .direction = .DIRECTION_BACKWARD,\n .velocity = 1000,\n .acceleration = 6000,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.push.line = 2\nrequest.command.push.axis = 1\nrequest.command.push.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.push.velocity = 1000\nrequest.command.push.acceleration = 6000\n"},{"location":"mmc-api.html#pull","title":"Pull","text":"Info
Initialize an incoming carrier located outside the current line. This command puts the specified axis into pulling state. This initialization procedure has the following behavior:
transition field to initialize the carrier at the center of the pulling axistransition field to automatically move to the specified destination as soon as the carrier is recognized.transition, velocity, and acceleration fields to initializes the carrier in the NONE state (not controlled by the motor), allowing it to be moved manually or by external systems.Example
Set axis 6 of line 1 to pulling state, and move the pulled carrier to axis 3.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pull = .{\n .line = 1,\n .axis = 6,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .direction = .DIRECTION_BACKWARD,\n .transition = .{\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n .target = .{.axis = 3},\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.pull.line = 1\nrequest.command.pull.axis = 6\nrequest.command.pull.carrier = 1\nrequest.command.pull.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.pull.velocity = 1000\nrequest.command.pull.acceleration = 6000\nrequest.command.pull.transition.control = 1\nrequest.command.pull.transition.disable_cas = False\nrequest.command.pull.transition.axis = 3\n"},{"location":"mmc-api.html#release-carrier","title":"Release Carrier","text":"Info
Put the initialized carrier into the NONE state, allowing it to be moved manually or by external systems.
Example
Release control of carrier 1 on line 1.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .release = .{\n .line = 1,\n .target = .{.carrier = 1},\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.release.line = 1\nrequest.command.release.carrier = 1\n"},{"location":"mmc-api.html#calibrate-line","title":"Calibrate Line","text":"Info
To calibrate the drivers' configuration on a line, an uninitialized carrier must be located at the center of the first axis
Example
Calibrate the drivers' configuration on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .calibrate = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.calibrate.line = 1\n"},{"location":"mmc-api.html#stop-push","title":"Stop Push","text":"Tip
To reset pushing state on all axis, ignore the axes field.
Example
Reset the pushing state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_push = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_push.line = 1\nrequest.command.stop_push.axes.start = 1\nrequest.command.stop_push.axes.end = 4\n"},{"location":"mmc-api.html#stop-pull","title":"Stop Pull","text":"Tip
To reset the pulling state on all axes, omit the axes field.
Example
Reset the pulling state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_pull = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_pull.line = 1\nrequest.command.stop_pull.axes.start = 1\nrequest.command.stop_pull.axes.end = 4\n"},{"location":"mmc-api.html#set-carrier-id","title":"Set Carrier ID","text":"Warning
The carrier ID of each carrier must be unique within a line.
Example
Change the carrier ID of carrier 1 to 4 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_carrier_id = .{\n .line = 1,\n .carrier = 1,\n .new_carrier = 4,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_carrier_id.line = 1\nrequest.command.set_carrier_id.carrier = 1\nrequest.command.set_carrier_id.new_carrier = 4\n"},{"location":"mmc-api.html#set-zero","title":"Set Zero","text":"Example
Set the zero point of the first line.
Warning
An initialized carrier must be located on the first axis of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_zero = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_zero.line = 1\n"},{"location":"mmc-api.html#clear-errors","title":"Clear Errors","text":"Warning
Always clear errors whenever an error is detected on an axis or driver. Failing to clear errors may result in unwanted behavior.
Tip
Ignore the axes field to clear errors on all drivers and axes on the line.
Example
Clear all errors on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .clear_errors = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.clear_errors.line = 1\n"},{"location":"mmc-api.html#emergency-stop","title":"Emergency Stop","text":"Tip
Pass an empty list to stop operations on all lines.
Example
Stop operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop.lines.extend([])\n"},{"location":"mmc-api.html#pause-execution","title":"Pause Execution","text":"Tip
Pass empty list to pause operations on all lines.
Example
Pause operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pause = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.pause.lines.extend([])\n"},{"location":"mmc-api.html#resume-execution","title":"Resume Execution","text":"Tip
Pass an empty list to resume operation on all lines.
Example
Resume operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .@\"resume\" = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.resume.lines.extend([])\n"},{"location":"mmc-api.html#remove-command","title":"Remove Command","text":"Warning
Failure to remove a command will block the queue and prevent the server from accepting further commands.
Tip
Always check the command status after sending a command message. (Request Command State)
Example
Remove the command with ID 1 from the server.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .remove_command = .{.command = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Creating a request message\nrequest = mmc.Request()\nrequest.command.remove_command.command = id\n"},{"location":"mmc-api.html#info-request","title":"Info Request","text":""},{"location":"mmc-api.html#request-command-state","title":"Request Command State","text":"Example
Wait till the command state becomes COMPLETED or FAILED, then remove the command.
const api = @import(\"mmc-api\");\n\nfn waitCommand(id: u32) !void {\n defer removeCommand(id);\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .command = .{ .id = id },\n },\n },\n },\n };\n while (true) {\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n const command_response = switch (decoded.body orelse\n return error.InvalidResponse) {\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .command => |commands_resp| commands_resp.items.items[0],\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n },\n else => return error.InvalidResponse,\n };\n switch (command_response.status) {\n .COMMAND_STATUS_PROGRESSING => {}, // continue the loop\n .COMMAND_STATUS_COMPLETED => return,\n .COMMAND_STATUS_FAILED => {\n std.log.err(\"{t}\", .{command_response.@\"error\".?});\n return;\n },\n .COMMAND_STATUS_UNSPECIFIED => return error.InvalidResponse,\n }\n }\n}\n import mmc_pb2 as mmc\n\ndef waitCommand(id):\n # Creating a request message\n request = mmc.Request()\n request.info.command.id = id\n while True:\n # Send and receive response\n s.sendall(request.SerializeToString())\n response = s.recv(4096)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n Command = mmc.mmc_dot_info__pb2.Response.Command()\n\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n return\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n return\n elif msg.info.WhichOneof(\"body\") == \"command\":\n command = msg.info.command.items[0]\n if command.status == Command.Status.COMMAND_STATUS_COMPLETED:\n removeCommand(id)\n return\n elif command.status == Command.Status.COMMAND_STATUS_FAILED:\n removeCommand(id)\n raise Exception(Command.Error.Name(command.error))\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n"},{"location":"mmc-api.html#request-track-state","title":"Request Track State","text":"Tip
Certain commands require the client to monitor carrier status to ensure movement is completed.
MOVE_COMPLETED before sending a new command to that carrier.CALIBRATE_COMPLETED to ensure the driver configuration is valid.INITIALIZE_COMPLETED before performing further operations on the carrier.transition field is omitted, wait for PULL_COMPLETED; otherwise, wait for MOVE_COMPLETED.Warning
Monitor the error flags of driver, axis and carriers to prevent damage to the motor or driver board. Pay close attention to inverter_overheat on the driver and overcurrent flags on the axis; immediately deinitialize any carrier on the affected axes and drivers if these are detected. The overvoltage and undervoltage flags indicate that the system voltage supply may have a problem; please consult with our engineers to resolve the issue.
Request carrier state
Tip
filter field when sending track info message to retrieve all toggled flags information.const api = @import(\"mmc-api\");\nfn carrierState(line: u32, carrier: u32) !void {\n var carrier_id = [1]u32{carrier};\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .track = .{\n .line = line,\n .info_carrier_state = true,\n .filter = .{\n .carriers = .{\n .ids = .fromOwnedSlice(&carrier_id),\n },\n },\n },\n },\n },\n },\n };\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n switch (decoded.body orelse return error.InvalidResponse) {\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .track => |track_resp| {\n std.log.info(\"{}\", .{track_resp.carrier_state.items[0]});\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n },\n else => return error.InvalidResponse,\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n }\n}\n import mmc_pb2 as mmc\ndef carrierState(line, carrier):\n # Creating a request message\n request = mmc.Request()\n request.info.track.line = line\n request.info.track.info_carrier_state = True\n request.info.track.carriers.ids.append(carrier)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n elif msg.info.WhichOneof(\"body\") == \"track\":\n assert len(msg.info.track.carrier_state) != 0\n carrier = msg.info.track.carrier_state[0]\n print(carrier)\n else:\n print(\"Invalid Response\")\n else:\n print(\"Invalid Response\")\n"},{"location":"protocol-documentation.html","title":"Protocol Documentation","text":""},{"location":"protocol-documentation.html#table-of-contents","title":"Table of Contents","text":"mmc.proto
Response
Request.Error
range.proto
mmc/command.proto
Response
Request.Direction
mmc/control.proto
mmc/core.proto
Response.TrackConfig.Line
Request.Error
mmc/info.proto
Response.Track
Request.Error
Scalar Value Types
Top
"},{"location":"protocol-documentation.html#mmcproto","title":"mmc.proto","text":""},{"location":"protocol-documentation.html#request","title":"Request","text":"Request message. All client-to-server messages should be of this message type.
Field Type Label Description core core.Request Core request. Used to retrieve information about the server or the configured track. command command.Request Command request. Used to send and manage commands to the server, which will execute commands on the connected track. info info.Request Info request. Used to retrieve information about track state or commands processed by the server. "},{"location":"protocol-documentation.html#response","title":"Response","text":"Response message. All server-to-client messages will be of this message type.
Field Type Label Description core core.Response Core response. command command.Response Command response. info info.Response Info Response. request_error Request.Error Top-level request error. This error field will be returned only if the top-level request could not be handled properly. Otherwise, response kinds may contain more specific error codes. "},{"location":"protocol-documentation.html#requesterror","title":"Request.Error","text":"Name Number Description MMC_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. MMC_REQUEST_ERROR_INVALID_MESSAGE 1 The request could not be decoded as a valid protobuf message.Top
"},{"location":"protocol-documentation.html#rangeproto","title":"range.proto","text":""},{"location":"protocol-documentation.html#range","title":"Range","text":"Field Type Label Description start uint32 Start of range, inclusive. end uint32 End of range, inclusive.Top
"},{"location":"protocol-documentation.html#mmccommandproto","title":"mmc/command.proto","text":""},{"location":"protocol-documentation.html#request_1","title":"Request","text":"Command API: List of commands to operate the PMF's motion system.
When a command is sent to the server, it will be queued for execution. Command execution status can be polled through the Info API. The status remains stored in a limited history buffer, and should be cleared with remove_command after completion.
Automatically initialize carriers on every specified lines.
Expected response: mmc.Response.body.command.body.id (uint32).
Calibrate a line by positioning an uninitialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear all error information on the driver. If a target is specified, clear error information of drivers included in that target. If not, clear error information on all drivers of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear carrier information located on the axis. If a target is specified, clear information of carriers included in that target. If not, clear all carrier information of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Initialize a carrier.
Expected response: mmc.Response.body.command.body.id (uint32).
Move a carrier to the desired position.
Expected response: mmc.Response.body.command.body.id (uint32).
SetZero command. distance float Move carrier to relative distance to current carrier position. Negative distance moves the carrier backwards. control mmc.Control Control method for moving carrier. disable_cas bool Disable the carrier's collision avoidance system (CAS). "},{"location":"protocol-documentation.html#requestpause","title":"Request.Pause","text":"Pause any operation in PMF LMS. Any queued commands in the server will be continued once the resume command is given.
Expected response: mmc.Response.body.command.body.id (uint32).
Pull and initialize a new carrier into a line.
Expected response: mmc.Response.body.command.body.id (uint32).
NaN, the velocity must be 0. acceleration float Acceleration of carrier movement. Floating point with range 100 - 24,500 mm/s^2. When the transition location target is set to NaN, the acceleration must be 0. transition Request.Pull.Transition optional Smoothly transition to carrier movement after pull completion. "},{"location":"protocol-documentation.html#requestpulltransition","title":"Request.Pull.Transition","text":"Field Type Label Description control mmc.Control Control method for moving carrier. disable_cas bool Disabling the carrier's collision avoidance system (CAS). target float Move carrier to relative location to the zero-point of the line, which is set by default at the center of the line's first axis after calibration, but can also be set with the SetZero command. Pass NaN to pull carrier without motor control, allowing carrier to be pulled with external force."},{"location":"protocol-documentation.html#requestpush","title":"Request.Push","text":"Push an initialized carrier to the specified direction.
Expected response: mmc.Response.body.command.body.id (uint32).
Release the control imposed by the motor to the carrier. If a target is specified, all motors included in that target release control. Otherwise, all carriers on the provided line will be released from control.
Expected response: mmc.Response.body.command.body.id (uint32).
Remove a command on the server if the command ID is specified. If no command ID is specified, remove any commands received by the server. If the commands are still progressing, cancel the command execution.
Expected response: mmc.Response.body.command.body.removed_id (uint32).
Resume lines that have been stopped or paused. If the line is not paused or emergency stopped, this command will succeed without any effect.
Expected response: mmc.Response.body.command.body.id (uint32).
Change the carrier ID of an existing initialized carrier. If the new carrier ID already exists on the line, returns INVALID_CARRIER.
Expected response: mmc.Response.body.command.body.id (uint32).
Set a zero position of a line by positioning an initialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Send an emergency stop command to stop any operation in PMF LMS. This command also removes all queued commands in the server.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pulling a carrier to the specified axis. If no axis is provided, then all pending carrier pulls on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pushing a carrier from the specified axis. If no axis is provided, then all pending carrier pushes on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Response description to the command API.
Field Type Label Description id uint32 Assigned ID for newly sent command. removed_id uint32 ID of cleared existing command. request_error Request.Error Error during command's execution. "},{"location":"protocol-documentation.html#requestdirection","title":"Request.Direction","text":"Name Number Description DIRECTION_UNSPECIFIED 0 DIRECTION_BACKWARD 1 DIRECTION_FORWARD 2"},{"location":"protocol-documentation.html#requesterror_1","title":"Request.Error","text":"Name Number Description COMMAND_REQUEST_ERROR_UNSPECIFIED 0 COMMAND_REQUEST_ERROR_INVALID_LINE 1 Attempted to use line ID outside of the configured lines. COMMAND_REQUEST_ERROR_INVALID_AXIS 2 Attempted to use axis ID outside of the configured axes of the line. COMMAND_REQUEST_ERROR_INVALID_DRIVER 3 Attempted to use driver ID outside of the configured drivers of the line. COMMAND_REQUEST_ERROR_INVALID_ACCELERATION 4 Attempted to use acceleration value outside of 1-245. COMMAND_REQUEST_ERROR_INVALID_VELOCITY 5 Attempted to use velocity value outside of 1-60. COMMAND_REQUEST_ERROR_INVALID_DIRECTION 6 Using invalid direction for the command. COMMAND_REQUEST_ERROR_INVALID_LOCATION 7 Deprecated. CheckCOMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_DISTANCE 8 Deprecated. Check COMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_CARRIER 9 Attempted to send a command to carrier outside of 1-2048. COMMAND_REQUEST_ERROR_MISSING_PARAMETER 10 A command missing the required parameter. COMMAND_REQUEST_ERROR_COMMAND_NOT_FOUND 11 Attempted to remove or cancel a non-existing command. COMMAND_REQUEST_ERROR_CARRIER_NOT_FOUND 12 Attempted to send command to an uninitialized carrier. COMMAND_REQUEST_ERROR_OUT_OF_MEMORY 14 Server unable to receive new command caused by out of memory. Try Command.Request.remove_command to free the memory. COMMAND_REQUEST_ERROR_MAXIMUM_AUTO_INITIALIZE_EXCEEDED 15 Attempted to run more than 8 auto initialize instance. COMMAND_REQUEST_ERROR_CONFLICTING_CARRIER_ID 16 Attempted to assign a carrier ID that is already used by another carrier on the same line. COMMAND_REQUEST_ERROR_INVALID_COMMAND 17 Command index is out of bounds for the configured command status buffer. Top
"},{"location":"protocol-documentation.html#mmccontrolproto","title":"mmc/control.proto","text":""},{"location":"protocol-documentation.html#control","title":"Control","text":"Carrier motor control kind.
Name Number Description CONTROL_UNSPECIFIED 0 CONTROL_POSITION 1 Carrier controlled with position priority. CONTROL_VELOCITY 2 Carrier controlled with velocity priority.Top
"},{"location":"protocol-documentation.html#mmccoreproto","title":"mmc/core.proto","text":""},{"location":"protocol-documentation.html#request_2","title":"Request","text":"Field Type Label Description kind Request.Kind"},{"location":"protocol-documentation.html#response_2","title":"Response","text":"Response description to the core API.
Field Type Label Description server Response.Server Server process information. track_config Response.TrackConfig Track configuration. request_error Request.Error Error response if the core request could not be handled. "},{"location":"protocol-documentation.html#responsesemanticversion","title":"Response.SemanticVersion","text":"Field Type Label Description major uint32 minor uint32 patch uint32"},{"location":"protocol-documentation.html#responseserver","title":"Response.Server","text":"Server version and name.
Field Type Label Description name string Server name. version Response.SemanticVersion Server implementation version. api Response.SemanticVersion "},{"location":"protocol-documentation.html#responsetrackconfig","title":"Response.TrackConfig","text":"Field Type Label Description lines Response.TrackConfig.Line repeated All configured lines in track."},{"location":"protocol-documentation.html#responsetrackconfigline","title":"Response.TrackConfig.Line","text":"Field Type Label Description id uint32 Line ID. Numeric ID, starting from 1, that is unique to each line in the track. This ID is used to address the line in other requests. name string Configured line name. This name is otherwise unused by the API, and is provided to the client for end-user convenience. axes uint32 Total number of axes in the line. axis_length float Length of each axis in the line, in millimeters. carrier_length float Carrier dimension parallel to carrier movement, in millimeters. drivers uint32 Total number of drivers in the line. carrier_width float Carrier dimension perpendicular to carrier movement, in millimeters."},{"location":"protocol-documentation.html#requesterror_2","title":"Request.Error","text":"Name Number Description CORE_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. CORE_REQUEST_ERROR_REQUEST_UNKNOWN 1 The core request kind was unspecified."},{"location":"protocol-documentation.html#requestkind","title":"Request.Kind","text":"Name Number Description CORE_REQUEST_KIND_UNSPECIFIED 0 This request kind is unused, and should never be sent. It is reserved as the default request kind according to protobuf specification. CORE_REQUEST_KIND_SERVER_INFO 2 Request server process information. This includes the configured server name and server implementation version. CORE_REQUEST_KIND_TRACK_CONFIG 3 Request the configured track information of the server.Top
"},{"location":"protocol-documentation.html#mmcinfoproto","title":"mmc/info.proto","text":""},{"location":"protocol-documentation.html#request_3","title":"Request","text":"Field Type Label Description command Request.Command Command information request. Get current status of command; necessary to determine if command is currently running, completed, or failed. track Request.Track Track information request. Get current track state information."},{"location":"protocol-documentation.html#requestcommand","title":"Request.Command","text":"Request for status of specified command ID from the server. If no command ID is provided, then request for status of all commands from the server.
Expected response: mmc.Response.body.info.body.commands
Request track state information from server. One or more of the info_ flags must be enabled to select the kind of track information desired. A filter may be optionally provided to limit the source of information from the track.
Expected response: mmc.Response.body.info.body.track
List of IDs. At least one ID must be provided.
Field Type Label Description ids uint32 repeated "},{"location":"protocol-documentation.html#response_3","title":"Response","text":"Field Type Label Description command Response.Commands Information for requested command(s). If empty, no matching command(s) was found. track Response.Track Information for requested track state. request_error Request.Error Info request error. This error field will be returned if the provided info request could not be handled properly."},{"location":"protocol-documentation.html#responsecommand","title":"Response.Command","text":"Field Type Label Description id uint32 Command ID. Valid IDs begin from 1, and may be reused after command status is cleared from server history. status Response.Command.Status Command status. error Response.Command.Error optional Command error response, only if the status isCOMMAND_STATUS_FAILED."},{"location":"protocol-documentation.html#responsecommands","title":"Response.Commands","text":"Field Type Label Description items Response.Command repeated"},{"location":"protocol-documentation.html#responseline","title":"Response.Line","text":"Field Type Label Description id uint32 Line ID. driver_state Response.Line.Driver.State repeated Driver state information list. Empty if request flag was disabled. driver_errors Response.Line.Driver.Error repeated Driver error information list. Empty if request flag was disabled. axis_state Response.Line.Axis.State repeated Axis state information list. Empty if request flag was disabled. axis_errors Response.Line.Axis.Error repeated Axis error information list. Empty if request flag was disabled. carrier_state Response.Line.Carrier.State repeated Carrier state information list. Empty if request flag was disabled."},{"location":"protocol-documentation.html#responselineaxis","title":"Response.Line.Axis","text":""},{"location":"protocol-documentation.html#responselineaxiserror","title":"Response.Line.Axis.Error","text":"Field Type Label Description id uint32 Axis ID. overcurrent bool Motor overcurrent detected. Motor control released to prevent damage."},{"location":"protocol-documentation.html#responselineaxisstate","title":"Response.Line.Axis.State","text":"Field Type Label Description id uint32 Axis ID. motor_active bool Axis is currently controlling a carrier. waiting_pull bool Axis is waiting to pull carrier. waiting_push bool Axis is waiting to push carrier. carrier uint32 Carrier ID; non-zero if an initialized carrier is on the axis. hall_alarm_back bool Axis back hall alarm is active. Magnet is detected above back hall sensor. hall_alarm_front bool Axis front hall alarm is active. Magnet is detected above front hall sensor."},{"location":"protocol-documentation.html#responselinecarrier","title":"Response.Line.Carrier","text":""},{"location":"protocol-documentation.html#responselinecarrierstate","title":"Response.Line.Carrier.State","text":"Field Type Label Description id uint32 Carrier ID. Will always be non-zero. position float Position of the carrier in line, in meters. axis_main uint32 Carrier's primary axis ID. axis_auxiliary uint32 optional Carrier's auxiliary axis ID, if carrier is on top of two axes. cas_disabled bool Collision avoidance system (CAS) disabled. cas_triggered bool Collision avoidance system (CAS) triggered. Carrier will automatically resume movement when path is clear. state Response.Line.Carrier.State.State Carrier state."},{"location":"protocol-documentation.html#responselinedriver","title":"Response.Line.Driver","text":""},{"location":"protocol-documentation.html#responselinedrivererror","title":"Response.Line.Driver.Error","text":"Field Type Label Description id uint32 Driver ID. control_loop_time_exceeded bool Control loop exceeded maximum loop time. inverter_overheat bool Inverter is overheated. undervoltage bool Driver voltage supply too low. overvoltage bool Driver voltage supply too high. comm_error_prev bool Communication error with previous driver in line. comm_error_next bool Communication error with next driver in line."},{"location":"protocol-documentation.html#responselinedriverstate","title":"Response.Line.Driver.State","text":"Field Type Label Description id uint32 Driver ID. connected bool Connection status between driver and server. busy bool Driver is currently executing a command. motor_disabled bool Driver motor release activated. All driver motors are inactive. stopped bool Driver emergency stop activated. paused bool Driver pause activated."},{"location":"protocol-documentation.html#responsetrack","title":"Response.Track","text":"Field Type Label Description lines Response.Line repeated"},{"location":"protocol-documentation.html#requesterror_3","title":"Request.Error","text":"Name Number Description INFO_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. INFO_REQUEST_ERROR_INVALID_LINE 1 Invalid line ID provided. Ensure that line ID exists in track configuration. INFO_REQUEST_ERROR_INVALID_AXIS 2 Invalid axis ID provided. Ensure that axis ID exists in line. INFO_REQUEST_ERROR_INVALID_DRIVER 3 Invalid driver ID provided. Ensure that driver ID exists in line. INFO_REQUEST_ERROR_MISSING_PARAMETER 4 Request is missing a required parameter. Ensure that at least one of the information flag is selected when requesting track information. INFO_REQUEST_ERROR_COMMAND_NOT_FOUND 5 Attempted to request information from a non-existing command. INFO_REQUEST_ERROR_INVALID_COMMAND 6 Command index is out of bounds for the configured command status buffer. INFO_REQUEST_ERROR_INVALID_CARRIER 7 Attempted to send a command to carrier outside of range."},{"location":"protocol-documentation.html#responsecommanderror","title":"Response.Command.Error","text":"Name Number Description COMMAND_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. COMMAND_ERROR_INVALID_SYSTEM_STATE 1 System state prevented successful command execution. Ensure that all preconditions are met with track info request before sending command. COMMAND_ERROR_INVALID_CARRIER_ID 2 Deprecated. Check COMMAND_REQUEST_ERROR_INVALID_CARRIER on Command.Request.Error. COMMAND_ERROR_DRIVER_DISCONNECTED 3 Driver connection failed while command progressing. COMMAND_ERROR_UNEXPECTED 4 Unexpected command execution error. This is likely an implementation bug; please contact PMF support for assistance. COMMAND_ERROR_CARRIER_NOT_FOUND 5 Target carrier is removed while command progressing. COMMAND_ERROR_CARRIER_ALREADY_INITIALIZED 6 Attempted to initialize an initialized carrier. COMMAND_ERROR_DRIVER_STOPPED 7 Target driver is stopped while command progressing. Consider resume the driver before sending further command. COMMAND_ERROR_INVALID_CARRIER_TARGET 8 Carrier targeting a location outside of the configured track. COMMAND_ERROR_CONFLICTING_CARRIER_ID 9 Attempted to assign a new carrier with an ID that is already used by other carrier on the same line"},{"location":"protocol-documentation.html#responsecommandstatus","title":"Response.Command.Status","text":"Name Number Description COMMAND_STATUS_UNSPECIFIED 0 This command status is unused, and will never be returned. It is reserved as the default status code according to protobuf specification. COMMAND_STATUS_PROGRESSING 1 Command currently executing. COMMAND_STATUS_COMPLETED 2 Command completed. COMMAND_STATUS_FAILED 3 Command execution failed."},{"location":"protocol-documentation.html#responselinecarrierstatestate","title":"Response.Line.Carrier.State.State","text":"Name Number Description CARRIER_STATE_NONE 0 CARRIER_STATE_CALIBRATING 1 Carrier is currently operating for line calibration. CARRIER_STATE_CALIBRATE_COMPLETED 2 Carrier has completed line calibration, and may now be used for normal operation. CARRIER_STATE_MOVING 3 Carrier is currently moving towards target destination. CARRIER_STATE_MOVE_COMPLETED 4 Carrier has arrived within threshold at target destination. CARRIER_STATE_INITIALIZING 5 Carrier is initializing. Must not be used until initialization is completed. CARRIER_STATE_INITIALIZE_COMPLETED 6 Carrier initialization completed. May now be used for normal operation. CARRIER_STATE_PUSHING 7 Carrier is being pushed by axis. Used to eject carrier from line. CARRIER_STATE_PULLING 9 Carrier is being pulled by axis. Must not be used until pull is completed. CARRIER_STATE_OVERCURRENT 11 Overcurrent detected in carrier axis motor. Carrier movement has been canceled."},{"location":"protocol-documentation.html#scalar-value-types","title":"Scalar Value Types","text":".proto Type Notes C++ Java Python Go C# PHP Ruby double double double float float64 double float Float float float float float float32 float float Float int32 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required) int64 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required) uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required) sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required) sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required) fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required) sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum bool bool boolean boolean bool bool boolean TrueClass/FalseClass string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8) bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)"}]}
\ No newline at end of file
diff --git a/site/search/search_index.json b/site/search/search_index.json
index 20f61a0..d9938e5 100644
--- a/site/search/search_index.json
+++ b/site/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"index.html","title":"PMF MMC system","text":"PMF provides the Motion Motor Control (MMC) system for controlling Linear Motor Systems (LMS) with ease and high precision.
"},{"location":"index.html#getting-started","title":"Getting started","text":""},{"location":"index.html#mmc-server","title":"MMC Server","text":"The MMC Server acts as an endpoint that allows multiple clients to interface with the LMS. The server must run on a PC connected to the first driver of the LMS. Contact our engineers to obtain the MMC Server files and organize them as follows:
mmc-server\n\u251c\u2500 config.json5\n\u251c\u2500 mmc.exe\n\u2514\u2500 mmc.pdb\n Navigate to the mmc-server folder and run the executable: mmc.exe --log_level=info\n"},{"location":"index.html#mmc-api","title":"MMC-API","text":"Our API is built with Protobuf, offering cross-language compatibility to support your programming language of choice. To integrate our API into your program, ensure your working environment supports Protobuf. For complete integration instructions, see the MMC-API Guidelines page.
"},{"location":"index.html#conventions","title":"Conventions","text":"This section defines the terminology used throughout the PMF MMC documentation.
"},{"location":"index.html#system-hierarchy","title":"System Hierarchy","text":"The following terms apply to the PMF MMC system:
Sensor: A hall sensor installed next to a motor to determine the precise location of a carrier on a line.Axis: A functional unit consisting of one motor and the two adjacent hall sensors.Driver: A physical board responsible for controlling one or more axes. The number of axes per driver is defined in the config.json5 file. A single driver can control up to 3 axes.Line: A unit consisting of one or more drivers. Driver, axis, and carrier states are determined on a per-line basis.Track: The highest-level unit in the PMF MMC system, consisting of one or more lines. One MMC Server operates exactly one track.Carrier: Magnet to be moved by PMF's MMC system that is placed on top of LMS. Every carrier must have unique ID per line.Important: ID Indexing
All system IDs (Lines, Drivers, Axes, and Carriers) use 1-based indexing. The first ID is always 1.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
"},{"location":"changelog.html#200-2026-03-16","title":"2.0.0 - 2026-03-16","text":""},{"location":"changelog.html#added","title":"Added","text":"BREAKING: Ability to retrieve all track information without specifying a Line ID Removed:
mmc.info.Request.Track.line\n Use instead: mmc.info.Request.Track.lines\n BREAKING: Track info response structure updated Removed:
mmc.info.Response.Track.line \nmmc.info.Response.Line.line\n Use instead: mmc.info.Response.Track.lines\nmmc.info.Response.Line.id\n BREAKING: velocity and acceleration behaviour Changed unit from dm/s to mm/s and dm/s^2 to mm/s^2 respectively. Additionally changed type from uint32 to float.
mmc_client.Line.velocity\nmmc_client.Line.acceleration\nAutoInitialize.Line.velocity\nAutoInitialize.Line.acceleration\nMove.velocity\nMove.acceleration\nPush.velocity\nPush.acceleration\nPull.velocity\nPull.acceleration\n BREAKING: Error and state enum definitions updated If you were using these error enums, they have been removed:
mmc.command.Request.Error.COMMAND_REQUEST_ERROR_CC_LINK_DISCONNECTED\n Use instead: mmc.info.Response.Command.Error.COMMAND_ERROR_DRIVER_DISCONNECTED\n If you were using these carrier states, they have been removed: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_PUSH_COMPLETED\nmmc.info.Response.Command.Carrier.State.CARRIER_STATE_PULL_COMPLETED\n Use instead: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_MOVE_COMPLETED\n The following error enums were added: mmc.command.Request.Error.COMMAND_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_COMMAND_NOT_FOUND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_CARRIER\n BREAKING: Pull command target behavior Removed:
mmc.command.Request.Pull.Transition.axis\nmmc.command.Request.Pull.Transition.location\nmmc.command.Request.Pull.Transition.distance\n Use instead: mmc.command.Request.Pull.Transition.target\n The behavior of target is equivalent to the previous location field. Additional change: Pass NaN to pull without motor-controlled transition. Release pipeline and artifacts updated
mmc.core.Request.Kind.CORE_REQUEST_KIND_API_VERSION\nmmc.core.Response.api_version\n Use instead: mmc.core.Request.Kind.CORE_REQUEST_KIND_SERVER_INFO\nmmc.core.Response.Server.api\nVelocityMode enum and related fields
mmc.command.Request.VelocityMode\nmmc.command.Request.AutoInitialize.Line.velocity_mode\nmmc.command.Request.Move.velocity_mode\nmmc.command.Request.Push.velocity_mode\nmmc.command.Request.Pull.velocity_mode\n Documentation component sabledocs
This page covers how to use MMC-API to operate on LMS connected to PMF's MMC system.
"},{"location":"mmc-api.html#mmc-api-structure","title":"MMC-API Structure","text":"The MMC API consists of three categories: core, command, and info. Each category contains corresponding requests and responses. Please refer to the protocol documentation page for the expected response for each request.
"},{"location":"mmc-api.html#mmc-core","title":"MMC Core","text":"Use MMC core messages to retrieve server information and track configuration. PMF recommends that clients verify compatibility with the server API version before operation. Starting from version 2.0.0, breaking changes may occur between major versions, therefore clients must ensure they are compatible with the server's API version. Mismatched versions may result in invalid requests or undefined behavior. Clients must fetch the track configuration prior to operating the PMF MMC system to ensure all messages passed to the server contain valid parameters. Refer to the MMC core documentation for a comprehensive list of message types and expected responses.
"},{"location":"mmc-api.html#mmc-command","title":"MMC Command","text":"Use MMC command messages to operate the PMF MMC system. Clients must use the following rules when sending MMC command messages.
remove_command once the command state becomes COMPLETED. Failure to do so will block the queue and prevent the server from accepting further commands.Monitor command status via the command info request defined in the MMC Info section. A list of commands are available on MMC command documentation.
"},{"location":"mmc-api.html#mmc-info","title":"MMC Info","text":"Use MMC info messages to monitor the real-time state of the track and command status. The client can specify which track information to request by enabling the relevant flags within the track info message definition. The API also allows filtering track info based on driver range, axis range, or specific carrier IDs. Refer to the MMC info documentation for the complete message definitions used to request track and command states.
"},{"location":"mmc-api.html#create-request","title":"Create Request","text":"This section demonstrates how to construct and encode a request for transmission. The first example illustrates how to decode and validate a response before use. Subsequent examples will omit the response processing logic to focus on request creation and key considerations for specific commands.
Info
Client must exclusively use the mmc.Request message type to send requests to the server. The server always returns an mmc.Response message to be decoded on client side. Any other message sent to server will return mmc.Response.request_error, showing the message is invalid.
Info
A core request message contains only one enum field. The following example demonstrates how to request the API version used by the server. Other core requests are implemented in the same manner.
Warning
Sending a core request with kind CORE_REQUEST_KIND_SERVER_INFO will always return mmc.Response.core.request_error.
Tip
Zig users can directly use the pmotionf/mmc-api repository for ease of integration. If you are using a different Zig version, generate the Zig files from the source Protobuf files using zig-protobuf library.
const api = @import(\"mmc-api\");\n// Create a request and encode the message. Encode with passing the\n// transport writer interface pointer and allocator. Send the message by \n// flush the writer..\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .core = .{ .kind = .CORE_REQUEST_KIND_SERVER_INFO },\n },\n};\ntry request.encode(&writer.interface, allocator);\ntry writer.interface.flush();\n// Receive and decode the message by passing the reader interface pointer \n// and allocator.\nconst decoded: api.protobuf.mmc.Response = try .decode(\n &client.reader.interface,\n client.allocator,\n);\nswitch (decoded.body orelse std.log.err(\"Invalid Response\",.{})) {\n .core => |core_resp| switch (core_resp.body orelse\n std.log.err(\"Invalid Response\",.{})) {\n .server => |server| std.log.info(\n \"Server API version: {}.{}.{}\",\n .{server.api.major, server.api.minor, server.api.patch,}\n ),\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n },\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n};\n import mmc_pb2 as mmc\n\n# Snipped: Create and connect socket to server\n\n# Create a request message\nrequest = mmc.Request()\nrequest.core.kind = mmc.mmc_dot_core__pb2.Request.CORE_REQUEST_KIND_SERVER_INFO\n\n# Snipped: Send and receive the message\n\n# Parse response\nmsg = mmc.Response()\nmsg.ParseFromString(response)\n\n# Validate and use the response accordingly\nif msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Error: \", mmc.Request.Error.Name(msg.request_error))\nelif msg.WhichOneof(\"body\") == \"core\":\n # Validate if the core response that we receive is `api_version`\n if msg.core.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Error: \",\n mmc.mmc_dot_core__pb2.Request.Error.Name(msg.core.request_error),\n )\n elif msg.core.WhichOneof(\"body\") == \"server\":\n api = msg.core.server.api\n print(\n f\"Server API Version: {api.major}.{api.minor}.{api.patch}\"\n )\n else:\n print(\"Invalid Response\")\nelse:\n print(\"Invalid Response\")\n\ns.close()\n"},{"location":"mmc-api.html#command-request","title":"Command Request","text":"Mandatory Command Cleanup
Every command request returns a unique Command ID. The client is required to:
remove_command once the state reaches COMPLETED or FAILED.Failure to remove finished commands will block the server queue and prevent further command execution.
Check Error Reason
If the command status is FAILED, users can find a descriptive reason by checking the command's error field.
Info
A carrier must be initialized before any actions can be performed. The initialize command is one of many available methods for initializing carriers. This command is sent to the axis specified by the axis parameter.
link_axis field must be ignored.axis parameter must be given as a link_axis, and specified as a direction relative to the provided axis.Unique Carrier ID Requirement
The client must ensure the carrier_id is unique across the entire line. If the ID is already in use by another initialized carrier on the same line, the server will return CONFLICTING_CARRIER_ID.
Example
The following request initializes an uninitialized carrier with ID 1 on the first line in the forward direction. This carrier's position is on top of axis 1 and axis 2.
zigpythonconst api = @import(\"mmc-api\");\n\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .initialize = .{\n .line = 1,\n .axis = 2,\n .carrier = 1,\n .direction = .DIRECTION_BACKWARD,\n .link_axis = .DIRECTION_FORWARD,\n },\n },\n },\n },\n};\n// Snipped content: \n// - Send `initialize` command\n// - Receive command ID as the response of command request\n// - Track command state until state `COMPLETED`\n// - Send `remove_command` command\n// - Receive `removed_id` response as the response of `remove_command` request\n import mmc_pb2 as mmc\n\n# Creating a request message\nCommand = mmc.mmc_dot_command__pb2.Request()\nrequest = mmc.Request()\nrequest.command.initialize.line = 1\nrequest.command.initialize.axis = 2\nrequest.command.initialize.carrier = 1\nrequest.command.initialize.direction = Command.Direction.DIRECTION_FORWARD\nrequest.command.initialize.link_axis = Command.Direction.DIRECTION_BACKWARD\n# Snipped content: \n# - Send `initialize` command\n# - Receive command ID as the response of command request\n# - Track command state until state `COMPLETED`\n# - Send `remove_command` command\n# - Receive `removed_id` response as the response of `remove_command` request\n"},{"location":"mmc-api.html#auto-initialize-carriers","title":"Auto Initialize Carriers","text":"Info
Auto initialize all carriers on the specified lines simultaneously. This process operates on carrier clusters, where a cluster is defined as a group of uninitialized carriers located on adjacent axis.
Warning
Each cluster requires at least one free axis to successfully perform the auto-initialization. Any cluster lacking a free axis will be ignored, and all carriers within that cluster will remain uninitialized upon command completion.
Tip
Ignore the acceleration and velocity fields to use the default values. The default value are:
Example
Auto initialize all carriers on line 1 and line 2.
zigpythonconst api = @import(\"mmc-api\");\n\n// Allocate lines\nvar lines: std.ArrayList(\n api.protobuf.mmc.command.Request.AutoInitialize.Line,\n) = .empty;\ndefer lines.deinit(allocator);\n\n// Define first line\ntry lines.append(allocator, .{\n .line = 1,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Define second line\ntry lines.append(allocator, .{\n .line = 2,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .auto_initialize = .{\n .lines = lines,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n\n# Define first line\nline1 = Command.AutoInitialize.Line()\nline1.line = 1\nline1.velocity = 600\nline1.acceleration = 6000\n\n# Define second line\nline2 = Command.AutoInitialize.Line()\nline2.line = 2\nline2.velocity = 600\nline2.acceleration = 6000\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.auto_initialize.lines.append(line1)\nrequest.command.auto_initialize.lines.append(line2)\n"},{"location":"mmc-api.html#deinitialize-carriers","title":"Deinitialize Carriers","text":"Info
Deinitialize will release motor control on the specified carriers and remove carrier states from MMC system. Deinitialize all carriers on a line by not specifying a target. If a target is specified, carriers are deinitialized based on that target:
Example
Deinitialize carrier 1 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .deinitialize = .{\n .line = line.id,\n .target = .{ .carrier = 1 }\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.deinitialize.line = 1\nrequest.command.deinitialize.carrier = 1\n"},{"location":"mmc-api.html#move-carrier","title":"Move Carrier","text":"Tip
Track the carrier state until it reaches MOVE_COMPLETED before sending further commands to the specified carrier to avoid unwanted behavior. The command state COMPLETED only indicates that the command was successfully received and is being processed by the MMC system.
Warning
The target field must be specified by the user, and only the last target value will be serialized to the server. See Oneof for complete a description on Oneof protobuf type.
Example
Move initialized carrier 1 to axis 3 on the second line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .move = .{\n .line = 2,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .target = .{.axis = 3},\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.move.line = 2\nrequest.command.move.carrier = 1\nrequest.command.move.velocity = 1000\nrequest.command.move.acceleration = 6000\nrequest.command.move.axis = 3\n# mmc.Control() message is not generated by protoc compiler because Python does\n# not allow to use definition based on namespace.\n# 1 for CONTROL_POSITION\n# 2 for CONTROL_VELOCITY.\nrequest.command.move.control = 1\nrequest.command.move.disable_cas = False\n"},{"location":"mmc-api.html#push","title":"Push","text":"Info
Forcefully moves an initialized carrier on the specified axis by one carrier length. Use this movement to cross a line boundary, which deinitializes the carrier from the current line upon completion.
If the carrier field is provided in the push command, the axis enters a pushing state. In this state, the axis remains busy and waits for the specified carrier to arrive; once it arrives, the axis automatically pushes the carrier.
Warning
When pushing the carrier to a different line, the receiving axis on the destination line must be in a pulling state.
Tip
To disable the pushing state on an axis, utilize the stop push command.
Example
Push carrier on axis 1 of line 2 backward to line 1.
Warning
The destination axis on line 1 must be in pulling state.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .push = .{\n .line = 2,\n .axis = 1,\n .direction = .DIRECTION_BACKWARD,\n .velocity = 1000,\n .acceleration = 6000,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.push.line = 2\nrequest.command.push.axis = 1\nrequest.command.push.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.push.velocity = 1000\nrequest.command.push.acceleration = 6000\n"},{"location":"mmc-api.html#pull","title":"Pull","text":"Info
Initialize an incoming carrier located outside the current line. This command puts the specified axis into pulling state. This initialization procedure has the following behavior:
transition field to initialize the carrier at the center of the pulling axistransition field to automatically move to the specified destination as soon as the carrier is recognized.transition, velocity, and acceleration fields to initializes the carrier in the NONE state (not controlled by the motor), allowing it to be moved manually or by external systems.Example
Set axis 6 of line 1 to pulling state, and move the pulled carrier to axis 3.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pull = .{\n .line = 1,\n .axis = 6,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .direction = .DIRECTION_BACKWARD,\n .transition = .{\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n .target = .{.axis = 3},\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.pull.line = 1\nrequest.command.pull.axis = 6\nrequest.command.pull.carrier = 1\nrequest.command.pull.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.pull.velocity = 1000\nrequest.command.pull.acceleration = 6000\nrequest.command.pull.transition.control = 1\nrequest.command.pull.transition.disable_cas = False\nrequest.command.pull.transition.axis = 3\n"},{"location":"mmc-api.html#release-carrier","title":"Release Carrier","text":"Info
Put the initialized carrier into the NONE state, allowing it to be moved manually or by external systems.
Example
Release control of carrier 1 on line 1.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .release = .{\n .line = 1,\n .target = .{.carrier = 1},\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.release.line = 1\nrequest.command.release.carrier = 1\n"},{"location":"mmc-api.html#calibrate-line","title":"Calibrate Line","text":"Info
To calibrate the drivers' configuration on a line, an uninitialized carrier must be located at the center of the first axis
Example
Calibrate the drivers' configuration on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .calibrate = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.calibrate.line = 1\n"},{"location":"mmc-api.html#stop-push","title":"Stop Push","text":"Tip
To reset pushing state on all axis, ignore the axes field.
Example
Reset the pushing state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_push = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_push.line = 1\nrequest.command.stop_push.axes.start = 1\nrequest.command.stop_push.axes.end = 4\n"},{"location":"mmc-api.html#stop-pull","title":"Stop Pull","text":"Tip
To reset the pulling state on all axes, omit the axes field.
Example
Reset the pulling state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_pull = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_pull.line = 1\nrequest.command.stop_pull.axes.start = 1\nrequest.command.stop_pull.axes.end = 4\n"},{"location":"mmc-api.html#set-carrier-id","title":"Set Carrier ID","text":"Warning
The carrier ID of each carrier must be unique within a line.
Example
Change the carrier ID of carrier 1 to 4 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_carrier_id = .{\n .line = 1,\n .carrier = 1,\n .new_carrier = 4,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_carrier_id.line = 1\nrequest.command.set_carrier_id.carrier = 1\nrequest.command.set_carrier_id.new_carrier = 4\n"},{"location":"mmc-api.html#set-zero","title":"Set Zero","text":"Example
Set the zero point of the first line.
Warning
An initialized carrier must be located on the first axis of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_zero = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_zero.line = 1\n"},{"location":"mmc-api.html#clear-errors","title":"Clear Errors","text":"Warning
Always clear errors whenever an error is detected on an axis or driver. Failing to clear errors may result in unwanted behavior.
Tip
Ignore the axes field to clear errors on all drivers and axes on the line.
Example
Clear all errors on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .clear_errors = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.clear_errors.line = 1\n"},{"location":"mmc-api.html#emergency-stop","title":"Emergency Stop","text":"Tip
Pass an empty list to stop operations on all lines.
Example
Stop operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop.lines.extend([])\n"},{"location":"mmc-api.html#pause-execution","title":"Pause Execution","text":"Tip
Pass empty list to pause operations on all lines.
Example
Pause operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pause = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.pause.lines.extend([])\n"},{"location":"mmc-api.html#resume-execution","title":"Resume Execution","text":"Tip
Pass an empty list to resume operation on all lines.
Example
Resume operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .@\"resume\" = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.resume.lines.extend([])\n"},{"location":"mmc-api.html#remove-command","title":"Remove Command","text":"Warning
Failure to remove a command will block the queue and prevent the server from accepting further commands.
Tip
Always check the command status after sending a command message. (Request Command State)
Example
Remove the command with ID 1 from the server.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .remove_command = .{.command = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Creating a request message\nrequest = mmc.Request()\nrequest.command.remove_command.command = id\n"},{"location":"mmc-api.html#info-request","title":"Info Request","text":""},{"location":"mmc-api.html#request-command-state","title":"Request Command State","text":"Example
Wait till the command state becomes COMPLETED or FAILED, then remove the command.
const api = @import(\"mmc-api\");\n\nfn waitCommand(id: u32) !void {\n defer removeCommand(id);\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .command = .{ .id = id },\n },\n },\n },\n };\n while (true) {\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n const command_response = switch (decoded.body orelse\n return error.InvalidResponse) {\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .command => |commands_resp| commands_resp.items.items[0],\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n },\n else => return error.InvalidResponse,\n };\n switch (command_response.status) {\n .COMMAND_STATUS_PROGRESSING => {}, // continue the loop\n .COMMAND_STATUS_COMPLETED => return,\n .COMMAND_STATUS_FAILED => {\n std.log.err(\"{t}\", .{command_response.@\"error\".?});\n return;\n },\n .COMMAND_STATUS_UNSPECIFIED => return error.InvalidResponse,\n }\n }\n}\n import mmc_pb2 as mmc\n\ndef waitCommand(id):\n # Creating a request message\n request = mmc.Request()\n request.info.command.id = id\n while True:\n # Send and receive response\n s.sendall(request.SerializeToString())\n response = s.recv(4096)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n Command = mmc.mmc_dot_info__pb2.Response.Command()\n\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n return\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n return\n elif msg.info.WhichOneof(\"body\") == \"command\":\n command = msg.info.command.items[0]\n if command.status == Command.Status.COMMAND_STATUS_COMPLETED:\n removeCommand(id)\n return\n elif command.status == Command.Status.COMMAND_STATUS_FAILED:\n removeCommand(id)\n raise Exception(Command.Error.Name(command.error))\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n"},{"location":"mmc-api.html#request-track-state","title":"Request Track State","text":"Tip
Certain commands require the client to monitor carrier status to ensure movement is completed.
MOVE_COMPLETED before sending a new command to that carrier.CALIBRATE_COMPLETED to ensure the driver configuration is valid.INITIALIZE_COMPLETED before performing further operations on the carrier.transition field is omitted, wait for PULL_COMPLETED; otherwise, wait for MOVE_COMPLETED.Warning
Monitor the error flags of driver, axis and carriers to prevent damage to the motor or driver board. Pay close attention to inverter_overheat on the driver and overcurrent flags on the axis; immediately deinitialize any carrier on the affected axes and drivers if these are detected. The overvoltage and undervoltage flags indicate that the system voltage supply may have a problem; please consult with our engineers to resolve the issue.
Request carrier state
Tip
filter field when sending track info message to retrieve all toggled flags information.const api = @import(\"mmc-api\");\nfn carrierState(line: u32, carrier: u32) !void {\n var carrier_id = [1]u32{carrier};\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .track = .{\n .line = line,\n .info_carrier_state = true,\n .filter = .{\n .carriers = .{\n .ids = .fromOwnedSlice(&carrier_id),\n },\n },\n },\n },\n },\n },\n };\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n switch (decoded.body orelse return error.InvalidResponse) {\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .track => |track_resp| {\n std.log.info(\"{}\", .{track_resp.carrier_state.items[0]});\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n },\n else => return error.InvalidResponse,\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n }\n}\n import mmc_pb2 as mmc\ndef carrierState(line, carrier):\n # Creating a request message\n request = mmc.Request()\n request.info.track.line = line\n request.info.track.info_carrier_state = True\n request.info.track.carriers.ids.append(carrier)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n elif msg.info.WhichOneof(\"body\") == \"track\":\n assert len(msg.info.track.carrier_state) != 0\n carrier = msg.info.track.carrier_state[0]\n print(carrier)\n else:\n print(\"Invalid Response\")\n else:\n print(\"Invalid Response\")\n"},{"location":"protocol-documentation.html","title":"Protocol Documentation","text":""},{"location":"protocol-documentation.html#table-of-contents","title":"Table of Contents","text":"mmc.proto
Response
Request.Error
range.proto
mmc/command.proto
Response
Request.Direction
mmc/control.proto
mmc/core.proto
Response.TrackConfig.Line
Request.Error
mmc/info.proto
Response.Track
Request.Error
Scalar Value Types
Top
"},{"location":"protocol-documentation.html#mmcproto","title":"mmc.proto","text":""},{"location":"protocol-documentation.html#request","title":"Request","text":"Request message. All client-to-server messages should be of this message type.
Field Type Label Description core core.Request Core request. Used to retrieve information about the server or the configured track. command command.Request Command request. Used to send and manage commands to the server, which will execute commands on the connected track. info info.Request Info request. Used to retrieve information about track state or commands processed by the server. "},{"location":"protocol-documentation.html#response","title":"Response","text":"Response message. All server-to-client messages will be of this message type.
Field Type Label Description core core.Response Core response. command command.Response Command response. info info.Response Info Response. request_error Request.Error Top-level request error. This error field will be returned only if the top-level request could not be handled properly. Otherwise, response kinds may contain more specific error codes. "},{"location":"protocol-documentation.html#requesterror","title":"Request.Error","text":"Name Number Description MMC_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. MMC_REQUEST_ERROR_INVALID_MESSAGE 1 The request could not be decoded as a valid protobuf message.Top
"},{"location":"protocol-documentation.html#rangeproto","title":"range.proto","text":""},{"location":"protocol-documentation.html#range","title":"Range","text":"Field Type Label Description start uint32 Start of range, inclusive. end uint32 End of range, inclusive.Top
"},{"location":"protocol-documentation.html#mmccommandproto","title":"mmc/command.proto","text":""},{"location":"protocol-documentation.html#request_1","title":"Request","text":"Command API: List of commands to operate the PMF's motion system.
When a command is sent to the server, it will be queued for execution. Command execution status can be polled through the Info API. The status remains stored in a limited history buffer, and should be cleared with remove_command after completion.
Automatically initialize carriers on every specified lines.
Expected response: mmc.Response.body.command.body.id (uint32).
Calibrate a line by positioning an uninitialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear all error information on the driver. If a target is specified, clear error information of drivers included in that target. If not, clear error information on all drivers of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear carrier information located on the axis. If a target is specified, clear information of carriers included in that target. If not, clear all carrier information of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Initialize a carrier.
Expected response: mmc.Response.body.command.body.id (uint32).
Move a carrier to the desired position.
Expected response: mmc.Response.body.command.body.id (uint32).
SetZero command. distance float Move carrier to relative distance to current carrier position. Negative distance moves the carrier backwards. control mmc.Control Control method for moving carrier. disable_cas bool Disable the carrier's collision avoidance system (CAS). "},{"location":"protocol-documentation.html#requestpause","title":"Request.Pause","text":"Pause any operation in PMF LMS. Any queued commands in the server will be continued once the resume command is given.
Expected response: mmc.Response.body.command.body.id (uint32).
Pull and initialize a new carrier into a line.
Expected response: mmc.Response.body.command.body.id (uint32).
NaN, the velocity must be 0. acceleration float Acceleration of carrier movement. Floating point with range 100 - 24,500 mm/s^2. When the transition location target is set to NaN, the acceleration must be 0. transition Request.Pull.Transition optional Smoothly transition to carrier movement after pull completion. "},{"location":"protocol-documentation.html#requestpulltransition","title":"Request.Pull.Transition","text":"Field Type Label Description control mmc.Control Control method for moving carrier. disable_cas bool Disabling the carrier's collision avoidance system (CAS). target float Move carrier to relative location to the zero-point of the line, which is set by default at the center of the line's first axis after calibration, but can also be set with the SetZero command. Pass NaN to pull carrier without motor control, allowing carrier to be pulled with external force."},{"location":"protocol-documentation.html#requestpush","title":"Request.Push","text":"Push an initialized carrier to the specified direction.
Expected response: mmc.Response.body.command.body.id (uint32).
Release the control imposed by the motor to the carrier. If a target is specified, all motors included in that target release control. Otherwise, all carriers on the provided line will be released from control.
Expected response: mmc.Response.body.command.body.id (uint32).
Remove a command on the server if the command ID is specified. If no command ID is specified, remove any commands received by the server. If the commands are still progressing, cancel the command execution.
Expected response: mmc.Response.body.command.body.removed_id (uint32).
Resume lines that have been stopped or paused. If the line is not paused or emergency stopped, this command will succeed without any effect.
Expected response: mmc.Response.body.command.body.id (uint32).
Change the carrier ID of an existing initialized carrier. If the new carrier ID already exists on the line, returns INVALID_CARRIER.
Expected response: mmc.Response.body.command.body.id (uint32).
Set a zero position of a line by positioning an initialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Send an emergency stop command to stop any operation in PMF LMS. This command also removes all queued commands in the server.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pulling a carrier to the specified axis. If no axis is provided, then all pending carrier pulls on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pushing a carrier from the specified axis. If no axis is provided, then all pending carrier pushes on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Response description to the command API.
Field Type Label Description id uint32 Assigned ID for newly sent command. removed_id uint32 ID of cleared existing command. request_error Request.Error Error during command's execution. "},{"location":"protocol-documentation.html#requestdirection","title":"Request.Direction","text":"Name Number Description DIRECTION_UNSPECIFIED 0 DIRECTION_BACKWARD 1 DIRECTION_FORWARD 2"},{"location":"protocol-documentation.html#requesterror_1","title":"Request.Error","text":"Name Number Description COMMAND_REQUEST_ERROR_UNSPECIFIED 0 COMMAND_REQUEST_ERROR_INVALID_LINE 1 Attempted to use line ID outside of the configured lines. COMMAND_REQUEST_ERROR_INVALID_AXIS 2 Attempted to use axis ID outside of the configured axes of the line. COMMAND_REQUEST_ERROR_INVALID_DRIVER 3 Attempted to use driver ID outside of the configured drivers of the line. COMMAND_REQUEST_ERROR_INVALID_ACCELERATION 4 Attempted to use acceleration value outside of 1-245. COMMAND_REQUEST_ERROR_INVALID_VELOCITY 5 Attempted to use velocity value outside of 1-60. COMMAND_REQUEST_ERROR_INVALID_DIRECTION 6 Using invalid direction for the command. COMMAND_REQUEST_ERROR_INVALID_LOCATION 7 Deprecated. CheckCOMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_DISTANCE 8 Deprecated. Check COMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_CARRIER 9 Attempted to send a command to carrier outside of 1-2048. COMMAND_REQUEST_ERROR_MISSING_PARAMETER 10 A command missing the required parameter. COMMAND_REQUEST_ERROR_COMMAND_NOT_FOUND 11 Attempted to remove or cancel a non-existing command. COMMAND_REQUEST_ERROR_CARRIER_NOT_FOUND 12 Attempted to send command to an uninitialized carrier. COMMAND_REQUEST_ERROR_OUT_OF_MEMORY 14 Server unable to receive new command caused by out of memory. Try Command.Request.remove_command to free the memory. COMMAND_REQUEST_ERROR_MAXIMUM_AUTO_INITIALIZE_EXCEEDED 15 Attempted to run more than 8 auto initialize instance. COMMAND_REQUEST_ERROR_CONFLICTING_CARRIER_ID 16 Attempted to assign a carrier ID that is already used by another carrier on the same line. COMMAND_REQUEST_ERROR_INVALID_COMMAND 17 Command index is out of bounds for the configured command status buffer. Top
"},{"location":"protocol-documentation.html#mmccontrolproto","title":"mmc/control.proto","text":""},{"location":"protocol-documentation.html#control","title":"Control","text":"Carrier motor control kind.
Name Number Description CONTROL_UNSPECIFIED 0 CONTROL_POSITION 1 Carrier controlled with position priority. CONTROL_VELOCITY 2 Carrier controlled with velocity priority.Top
"},{"location":"protocol-documentation.html#mmccoreproto","title":"mmc/core.proto","text":""},{"location":"protocol-documentation.html#request_2","title":"Request","text":"Field Type Label Description kind Request.Kind"},{"location":"protocol-documentation.html#response_2","title":"Response","text":"Response description to the core API.
Field Type Label Description server Response.Server Server process information. track_config Response.TrackConfig Track configuration. request_error Request.Error Error response if the core request could not be handled. "},{"location":"protocol-documentation.html#responsesemanticversion","title":"Response.SemanticVersion","text":"Field Type Label Description major uint32 minor uint32 patch uint32"},{"location":"protocol-documentation.html#responseserver","title":"Response.Server","text":"Server version and name.
Field Type Label Description name string Server name. version Response.SemanticVersion Server implementation version. api Response.SemanticVersion "},{"location":"protocol-documentation.html#responsetrackconfig","title":"Response.TrackConfig","text":"Field Type Label Description lines Response.TrackConfig.Line repeated All configured lines in track."},{"location":"protocol-documentation.html#responsetrackconfigline","title":"Response.TrackConfig.Line","text":"Field Type Label Description id uint32 Line ID. Numeric ID, starting from 1, that is unique to each line in the track. This ID is used to address the line in other requests. name string Configured line name. This name is otherwise unused by the API, and is provided to the client for end-user convenience. axes uint32 Total number of axes in the line. axis_length float Length of each axis in the line, in meters. carrier_length float Carrier magnet length, in meters. drivers uint32 Total number of drivers in the line."},{"location":"protocol-documentation.html#requesterror_2","title":"Request.Error","text":"Name Number Description CORE_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. CORE_REQUEST_ERROR_REQUEST_UNKNOWN 1 The core request kind was unspecified."},{"location":"protocol-documentation.html#requestkind","title":"Request.Kind","text":"Name Number Description CORE_REQUEST_KIND_UNSPECIFIED 0 This request kind is unused, and should never be sent. It is reserved as the default request kind according to protobuf specification. CORE_REQUEST_KIND_SERVER_INFO 2 Request server process information. This includes the configured server name and server implementation version. CORE_REQUEST_KIND_TRACK_CONFIG 3 Request the configured track information of the server.Top
"},{"location":"protocol-documentation.html#mmcinfoproto","title":"mmc/info.proto","text":""},{"location":"protocol-documentation.html#request_3","title":"Request","text":"Field Type Label Description command Request.Command Command information request. Get current status of command; necessary to determine if command is currently running, completed, or failed. track Request.Track Track information request. Get current track state information."},{"location":"protocol-documentation.html#requestcommand","title":"Request.Command","text":"Request for status of specified command ID from the server. If no command ID is provided, then request for status of all commands from the server.
Expected response: mmc.Response.body.info.body.commands
Request track state information from server. One or more of the info_ flags must be enabled to select the kind of track information desired. A filter may be optionally provided to limit the source of information from the track.
Expected response: mmc.Response.body.info.body.track
List of IDs. At least one ID must be provided.
Field Type Label Description ids uint32 repeated "},{"location":"protocol-documentation.html#response_3","title":"Response","text":"Field Type Label Description command Response.Commands Information for requested command(s). If empty, no matching command(s) was found. track Response.Track Information for requested track state. request_error Request.Error Info request error. This error field will be returned if the provided info request could not be handled properly."},{"location":"protocol-documentation.html#responsecommand","title":"Response.Command","text":"Field Type Label Description id uint32 Command ID. Valid IDs begin from 1, and may be reused after command status is cleared from server history. status Response.Command.Status Command status. error Response.Command.Error optional Command error response, only if the status isCOMMAND_STATUS_FAILED."},{"location":"protocol-documentation.html#responsecommands","title":"Response.Commands","text":"Field Type Label Description items Response.Command repeated"},{"location":"protocol-documentation.html#responseline","title":"Response.Line","text":"Field Type Label Description id uint32 Line ID. driver_state Response.Line.Driver.State repeated Driver state information list. Empty if request flag was disabled. driver_errors Response.Line.Driver.Error repeated Driver error information list. Empty if request flag was disabled. axis_state Response.Line.Axis.State repeated Axis state information list. Empty if request flag was disabled. axis_errors Response.Line.Axis.Error repeated Axis error information list. Empty if request flag was disabled. carrier_state Response.Line.Carrier.State repeated Carrier state information list. Empty if request flag was disabled."},{"location":"protocol-documentation.html#responselineaxis","title":"Response.Line.Axis","text":""},{"location":"protocol-documentation.html#responselineaxiserror","title":"Response.Line.Axis.Error","text":"Field Type Label Description id uint32 Axis ID. overcurrent bool Motor overcurrent detected. Motor control released to prevent damage."},{"location":"protocol-documentation.html#responselineaxisstate","title":"Response.Line.Axis.State","text":"Field Type Label Description id uint32 Axis ID. motor_active bool Axis is currently controlling a carrier. waiting_pull bool Axis is waiting to pull carrier. waiting_push bool Axis is waiting to push carrier. carrier uint32 Carrier ID; non-zero if an initialized carrier is on the axis. hall_alarm_back bool Axis back hall alarm is active. Magnet is detected above back hall sensor. hall_alarm_front bool Axis front hall alarm is active. Magnet is detected above front hall sensor."},{"location":"protocol-documentation.html#responselinecarrier","title":"Response.Line.Carrier","text":""},{"location":"protocol-documentation.html#responselinecarrierstate","title":"Response.Line.Carrier.State","text":"Field Type Label Description id uint32 Carrier ID. Will always be non-zero. position float Position of the carrier in line, in meters. axis_main uint32 Carrier's primary axis ID. axis_auxiliary uint32 optional Carrier's auxiliary axis ID, if carrier is on top of two axes. cas_disabled bool Collision avoidance system (CAS) disabled. cas_triggered bool Collision avoidance system (CAS) triggered. Carrier will automatically resume movement when path is clear. state Response.Line.Carrier.State.State Carrier state."},{"location":"protocol-documentation.html#responselinedriver","title":"Response.Line.Driver","text":""},{"location":"protocol-documentation.html#responselinedrivererror","title":"Response.Line.Driver.Error","text":"Field Type Label Description id uint32 Driver ID. control_loop_time_exceeded bool Control loop exceeded maximum loop time. inverter_overheat bool Inverter is overheated. undervoltage bool Driver voltage supply too low. overvoltage bool Driver voltage supply too high. comm_error_prev bool Communication error with previous driver in line. comm_error_next bool Communication error with next driver in line."},{"location":"protocol-documentation.html#responselinedriverstate","title":"Response.Line.Driver.State","text":"Field Type Label Description id uint32 Driver ID. connected bool Connection status between driver and server. busy bool Driver is currently executing a command. motor_disabled bool Driver motor release activated. All driver motors are inactive. stopped bool Driver emergency stop activated. paused bool Driver pause activated."},{"location":"protocol-documentation.html#responsetrack","title":"Response.Track","text":"Field Type Label Description lines Response.Line repeated"},{"location":"protocol-documentation.html#requesterror_3","title":"Request.Error","text":"Name Number Description INFO_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. INFO_REQUEST_ERROR_INVALID_LINE 1 Invalid line ID provided. Ensure that line ID exists in track configuration. INFO_REQUEST_ERROR_INVALID_AXIS 2 Invalid axis ID provided. Ensure that axis ID exists in line. INFO_REQUEST_ERROR_INVALID_DRIVER 3 Invalid driver ID provided. Ensure that driver ID exists in line. INFO_REQUEST_ERROR_MISSING_PARAMETER 4 Request is missing a required parameter. Ensure that at least one of the information flag is selected when requesting track information. INFO_REQUEST_ERROR_COMMAND_NOT_FOUND 5 Attempted to request information from a non-existing command. INFO_REQUEST_ERROR_INVALID_COMMAND 6 Command index is out of bounds for the configured command status buffer. INFO_REQUEST_ERROR_INVALID_CARRIER 7 Attempted to send a command to carrier outside of range."},{"location":"protocol-documentation.html#responsecommanderror","title":"Response.Command.Error","text":"Name Number Description COMMAND_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. COMMAND_ERROR_INVALID_SYSTEM_STATE 1 System state prevented successful command execution. Ensure that all preconditions are met with track info request before sending command. COMMAND_ERROR_INVALID_CARRIER_ID 2 Deprecated. Check COMMAND_REQUEST_ERROR_INVALID_CARRIER on Command.Request.Error. COMMAND_ERROR_DRIVER_DISCONNECTED 3 Driver connection failed while command progressing. COMMAND_ERROR_UNEXPECTED 4 Unexpected command execution error. This is likely an implementation bug; please contact PMF support for assistance. COMMAND_ERROR_CARRIER_NOT_FOUND 5 Target carrier is removed while command progressing. COMMAND_ERROR_CARRIER_ALREADY_INITIALIZED 6 Attempted to initialize an initialized carrier. COMMAND_ERROR_DRIVER_STOPPED 7 Target driver is stopped while command progressing. Consider resume the driver before sending further command. COMMAND_ERROR_INVALID_CARRIER_TARGET 8 Carrier targeting a location outside of the configured track. COMMAND_ERROR_CONFLICTING_CARRIER_ID 9 Attempted to assign a new carrier with an ID that is already used by other carrier on the same line"},{"location":"protocol-documentation.html#responsecommandstatus","title":"Response.Command.Status","text":"Name Number Description COMMAND_STATUS_UNSPECIFIED 0 This command status is unused, and will never be returned. It is reserved as the default status code according to protobuf specification. COMMAND_STATUS_PROGRESSING 1 Command currently executing. COMMAND_STATUS_COMPLETED 2 Command completed. COMMAND_STATUS_FAILED 3 Command execution failed."},{"location":"protocol-documentation.html#responselinecarrierstatestate","title":"Response.Line.Carrier.State.State","text":"Name Number Description CARRIER_STATE_NONE 0 CARRIER_STATE_CALIBRATING 1 Carrier is currently operating for line calibration. CARRIER_STATE_CALIBRATE_COMPLETED 2 Carrier has completed line calibration, and may now be used for normal operation. CARRIER_STATE_MOVING 3 Carrier is currently moving towards target destination. CARRIER_STATE_MOVE_COMPLETED 4 Carrier has arrived within threshold at target destination. CARRIER_STATE_INITIALIZING 5 Carrier is initializing. Must not be used until initialization is completed. CARRIER_STATE_INITIALIZE_COMPLETED 6 Carrier initialization completed. May now be used for normal operation. CARRIER_STATE_PUSHING 7 Carrier is being pushed by axis. Used to eject carrier from line. CARRIER_STATE_PULLING 9 Carrier is being pulled by axis. Must not be used until pull is completed. CARRIER_STATE_OVERCURRENT 11 Overcurrent detected in carrier axis motor. Carrier movement has been canceled."},{"location":"protocol-documentation.html#scalar-value-types","title":"Scalar Value Types","text":".proto Type Notes C++ Java Python Go C# PHP Ruby double double double float float64 double float Float float float float float float32 float float Float int32 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required) int64 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required) uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required) sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required) sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required) fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required) sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum bool bool boolean boolean bool bool boolean TrueClass/FalseClass string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8) bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"index.html","title":"PMF MMC system","text":"PMF provides the Motion Motor Control (MMC) system for controlling Linear Motor Systems (LMS) with ease and high precision.
"},{"location":"index.html#getting-started","title":"Getting started","text":""},{"location":"index.html#mmc-server","title":"MMC Server","text":"The MMC Server acts as an endpoint that allows multiple clients to interface with the LMS. The server must run on a PC connected to the first driver of the LMS. Contact our engineers to obtain the MMC Server files and organize them as follows:
mmc-server\n\u251c\u2500 config.json5\n\u251c\u2500 mmc.exe\n\u2514\u2500 mmc.pdb\n Navigate to the mmc-server folder and run the executable: mmc.exe --log_level=info\n"},{"location":"index.html#mmc-api","title":"MMC-API","text":"Our API is built with Protobuf, offering cross-language compatibility to support your programming language of choice. To integrate our API into your program, ensure your working environment supports Protobuf. For complete integration instructions, see the MMC-API Guidelines page.
"},{"location":"index.html#conventions","title":"Conventions","text":"This section defines the terminology used throughout the PMF MMC documentation.
"},{"location":"index.html#system-hierarchy","title":"System Hierarchy","text":"The following terms apply to the PMF MMC system:
Sensor: A hall sensor installed next to a motor to determine the precise location of a carrier on a line.Axis: A functional unit consisting of one motor and the two adjacent hall sensors.Driver: A physical board responsible for controlling one or more axes. The number of axes per driver is defined in the config.json5 file. A single driver can control up to 3 axes.Line: A unit consisting of one or more drivers. Driver, axis, and carrier states are determined on a per-line basis.Track: The highest-level unit in the PMF MMC system, consisting of one or more lines. One MMC Server operates exactly one track.Carrier: Magnet to be moved by PMF's MMC system that is placed on top of LMS. Every carrier must have unique ID per line.Important: ID Indexing
All system IDs (Lines, Drivers, Axes, and Carriers) use 1-based indexing. The first ID is always 1.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
"},{"location":"changelog.html#200-2026-03-16","title":"2.0.0 - 2026-03-16","text":""},{"location":"changelog.html#added","title":"Added","text":"BREAKING: Ability to retrieve all track information without specifying a Line ID Removed:
mmc.info.Request.Track.line\n Use instead: mmc.info.Request.Track.lines\n BREAKING: Track info response structure updated Removed:
mmc.info.Response.Track.line \nmmc.info.Response.Line.line\n Use instead: mmc.info.Response.Track.lines\nmmc.info.Response.Line.id\n BREAKING: velocity and acceleration behaviour Changed unit from dm/s to mm/s and dm/s^2 to mm/s^2 respectively. Additionally changed type from uint32 to float.
mmc_client.Line.velocity\nmmc_client.Line.acceleration\nAutoInitialize.Line.velocity\nAutoInitialize.Line.acceleration\nMove.velocity\nMove.acceleration\nPush.velocity\nPush.acceleration\nPull.velocity\nPull.acceleration\n BREAKING: Error and state enum definitions updated If you were using these error enums, they have been removed:
mmc.command.Request.Error.COMMAND_REQUEST_ERROR_CC_LINK_DISCONNECTED\n Use instead: mmc.info.Response.Command.Error.COMMAND_ERROR_DRIVER_DISCONNECTED\n If you were using these carrier states, they have been removed: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_PUSH_COMPLETED\nmmc.info.Response.Command.Carrier.State.CARRIER_STATE_PULL_COMPLETED\n Use instead: mmc.info.Response.Command.Carrier.State.CARRIER_STATE_MOVE_COMPLETED\n The following error enums were added: mmc.command.Request.Error.COMMAND_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_COMMAND_NOT_FOUND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_COMMAND\nmmc.info.Request.Error.INFO_REQUEST_ERROR_INVALID_CARRIER\n BREAKING: Pull command target behavior Removed:
mmc.command.Request.Pull.Transition.axis\nmmc.command.Request.Pull.Transition.location\nmmc.command.Request.Pull.Transition.distance\n Use instead: mmc.command.Request.Pull.Transition.target\n The behavior of target is equivalent to the previous location field. Additional change: Pass NaN to pull without motor-controlled transition. Release pipeline and artifacts updated
mmc.core.Request.Kind.CORE_REQUEST_KIND_API_VERSION\nmmc.core.Response.api_version\n Use instead: mmc.core.Request.Kind.CORE_REQUEST_KIND_SERVER_INFO\nmmc.core.Response.Server.api\nVelocityMode enum and related fields
mmc.command.Request.VelocityMode\nmmc.command.Request.AutoInitialize.Line.velocity_mode\nmmc.command.Request.Move.velocity_mode\nmmc.command.Request.Push.velocity_mode\nmmc.command.Request.Pull.velocity_mode\n Documentation component sabledocs
This page covers how to use MMC-API to operate on LMS connected to PMF's MMC system.
"},{"location":"mmc-api.html#mmc-api-structure","title":"MMC-API Structure","text":"The MMC API consists of three categories: core, command, and info. Each category contains corresponding requests and responses. Please refer to the protocol documentation page for the expected response for each request.
"},{"location":"mmc-api.html#mmc-core","title":"MMC Core","text":"Use MMC core messages to retrieve server information and track configuration. PMF recommends that clients verify compatibility with the server API version before operation. Starting from version 2.0.0, breaking changes may occur between major versions, therefore clients must ensure they are compatible with the server's API version. Mismatched versions may result in invalid requests or undefined behavior. Clients must fetch the track configuration prior to operating the PMF MMC system to ensure all messages passed to the server contain valid parameters. Refer to the MMC core documentation for a comprehensive list of message types and expected responses.
"},{"location":"mmc-api.html#mmc-command","title":"MMC Command","text":"Use MMC command messages to operate the PMF MMC system. Clients must use the following rules when sending MMC command messages.
remove_command once the command state becomes COMPLETED. Failure to do so will block the queue and prevent the server from accepting further commands.Monitor command status via the command info request defined in the MMC Info section. A list of commands are available on MMC command documentation.
"},{"location":"mmc-api.html#mmc-info","title":"MMC Info","text":"Use MMC info messages to monitor the real-time state of the track and command status. The client can specify which track information to request by enabling the relevant flags within the track info message definition. The API also allows filtering track info based on driver range, axis range, or specific carrier IDs. Refer to the MMC info documentation for the complete message definitions used to request track and command states.
"},{"location":"mmc-api.html#create-request","title":"Create Request","text":"This section demonstrates how to construct and encode a request for transmission. The first example illustrates how to decode and validate a response before use. Subsequent examples will omit the response processing logic to focus on request creation and key considerations for specific commands.
Info
Client must exclusively use the mmc.Request message type to send requests to the server. The server always returns an mmc.Response message to be decoded on client side. Any other message sent to server will return mmc.Response.request_error, showing the message is invalid.
Info
A core request message contains only one enum field. The following example demonstrates how to request the API version used by the server. Other core requests are implemented in the same manner.
Warning
Sending a core request with kind CORE_REQUEST_KIND_SERVER_INFO will always return mmc.Response.core.request_error.
Tip
Zig users can directly use the pmotionf/mmc-api repository for ease of integration. If you are using a different Zig version, generate the Zig files from the source Protobuf files using zig-protobuf library.
const api = @import(\"mmc-api\");\n// Create a request and encode the message. Encode with passing the\n// transport writer interface pointer and allocator. Send the message by \n// flush the writer..\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .core = .{ .kind = .CORE_REQUEST_KIND_SERVER_INFO },\n },\n};\ntry request.encode(&writer.interface, allocator);\ntry writer.interface.flush();\n// Receive and decode the message by passing the reader interface pointer \n// and allocator.\nconst decoded: api.protobuf.mmc.Response = try .decode(\n &client.reader.interface,\n client.allocator,\n);\nswitch (decoded.body orelse std.log.err(\"Invalid Response\",.{})) {\n .core => |core_resp| switch (core_resp.body orelse\n std.log.err(\"Invalid Response\",.{})) {\n .server => |server| std.log.info(\n \"Server API version: {}.{}.{}\",\n .{server.api.major, server.api.minor, server.api.patch,}\n ),\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n },\n .request_error => |req_err| std.log.err(\"{t}\",.{req_err}),\n else => std.log.err(\"Invalid Response\",.{}),\n};\n import mmc_pb2 as mmc\n\n# Snipped: Create and connect socket to server\n\n# Create a request message\nrequest = mmc.Request()\nrequest.core.kind = mmc.mmc_dot_core__pb2.Request.CORE_REQUEST_KIND_SERVER_INFO\n\n# Snipped: Send and receive the message\n\n# Parse response\nmsg = mmc.Response()\nmsg.ParseFromString(response)\n\n# Validate and use the response accordingly\nif msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Error: \", mmc.Request.Error.Name(msg.request_error))\nelif msg.WhichOneof(\"body\") == \"core\":\n # Validate if the core response that we receive is `api_version`\n if msg.core.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Error: \",\n mmc.mmc_dot_core__pb2.Request.Error.Name(msg.core.request_error),\n )\n elif msg.core.WhichOneof(\"body\") == \"server\":\n api = msg.core.server.api\n print(\n f\"Server API Version: {api.major}.{api.minor}.{api.patch}\"\n )\n else:\n print(\"Invalid Response\")\nelse:\n print(\"Invalid Response\")\n\ns.close()\n"},{"location":"mmc-api.html#command-request","title":"Command Request","text":"Mandatory Command Cleanup
Every command request returns a unique Command ID. The client is required to:
remove_command once the state reaches COMPLETED or FAILED.Failure to remove finished commands will block the server queue and prevent further command execution.
Check Error Reason
If the command status is FAILED, users can find a descriptive reason by checking the command's error field.
Info
A carrier must be initialized before any actions can be performed. The initialize command is one of many available methods for initializing carriers. This command is sent to the axis specified by the axis parameter.
link_axis field must be ignored.axis parameter must be given as a link_axis, and specified as a direction relative to the provided axis.Unique Carrier ID Requirement
The client must ensure the carrier_id is unique across the entire line. If the ID is already in use by another initialized carrier on the same line, the server will return CONFLICTING_CARRIER_ID.
Example
The following request initializes an uninitialized carrier with ID 1 on the first line in the forward direction. This carrier's position is on top of axis 1 and axis 2.
zigpythonconst api = @import(\"mmc-api\");\n\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .initialize = .{\n .line = 1,\n .axis = 2,\n .carrier = 1,\n .direction = .DIRECTION_BACKWARD,\n .link_axis = .DIRECTION_FORWARD,\n },\n },\n },\n },\n};\n// Snipped content: \n// - Send `initialize` command\n// - Receive command ID as the response of command request\n// - Track command state until state `COMPLETED`\n// - Send `remove_command` command\n// - Receive `removed_id` response as the response of `remove_command` request\n import mmc_pb2 as mmc\n\n# Creating a request message\nCommand = mmc.mmc_dot_command__pb2.Request()\nrequest = mmc.Request()\nrequest.command.initialize.line = 1\nrequest.command.initialize.axis = 2\nrequest.command.initialize.carrier = 1\nrequest.command.initialize.direction = Command.Direction.DIRECTION_FORWARD\nrequest.command.initialize.link_axis = Command.Direction.DIRECTION_BACKWARD\n# Snipped content: \n# - Send `initialize` command\n# - Receive command ID as the response of command request\n# - Track command state until state `COMPLETED`\n# - Send `remove_command` command\n# - Receive `removed_id` response as the response of `remove_command` request\n"},{"location":"mmc-api.html#auto-initialize-carriers","title":"Auto Initialize Carriers","text":"Info
Auto initialize all carriers on the specified lines simultaneously. This process operates on carrier clusters, where a cluster is defined as a group of uninitialized carriers located on adjacent axis.
Warning
Each cluster requires at least one free axis to successfully perform the auto-initialization. Any cluster lacking a free axis will be ignored, and all carriers within that cluster will remain uninitialized upon command completion.
Tip
Ignore the acceleration and velocity fields to use the default values. The default value are:
Example
Auto initialize all carriers on line 1 and line 2.
zigpythonconst api = @import(\"mmc-api\");\n\n// Allocate lines\nvar lines: std.ArrayList(\n api.protobuf.mmc.command.Request.AutoInitialize.Line,\n) = .empty;\ndefer lines.deinit(allocator);\n\n// Define first line\ntry lines.append(allocator, .{\n .line = 1,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Define second line\ntry lines.append(allocator, .{\n .line = 2,\n .acceleration = 6000,\n .velocity = 600,\n});\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .auto_initialize = .{\n .lines = lines,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n\n# Define first line\nline1 = Command.AutoInitialize.Line()\nline1.line = 1\nline1.velocity = 600\nline1.acceleration = 6000\n\n# Define second line\nline2 = Command.AutoInitialize.Line()\nline2.line = 2\nline2.velocity = 600\nline2.acceleration = 6000\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.auto_initialize.lines.append(line1)\nrequest.command.auto_initialize.lines.append(line2)\n"},{"location":"mmc-api.html#deinitialize-carriers","title":"Deinitialize Carriers","text":"Info
Deinitialize will release motor control on the specified carriers and remove carrier states from MMC system. Deinitialize all carriers on a line by not specifying a target. If a target is specified, carriers are deinitialized based on that target:
Example
Deinitialize carrier 1 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .deinitialize = .{\n .line = line.id,\n .target = .{ .carrier = 1 }\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.deinitialize.line = 1\nrequest.command.deinitialize.carrier = 1\n"},{"location":"mmc-api.html#move-carrier","title":"Move Carrier","text":"Tip
Track the carrier state until it reaches MOVE_COMPLETED before sending further commands to the specified carrier to avoid unwanted behavior. The command state COMPLETED only indicates that the command was successfully received and is being processed by the MMC system.
Warning
The target field must be specified by the user, and only the last target value will be serialized to the server. See Oneof for complete a description on Oneof protobuf type.
Example
Move initialized carrier 1 to axis 3 on the second line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .move = .{\n .line = 2,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .target = .{.axis = 3},\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.move.line = 2\nrequest.command.move.carrier = 1\nrequest.command.move.velocity = 1000\nrequest.command.move.acceleration = 6000\nrequest.command.move.axis = 3\n# mmc.Control() message is not generated by protoc compiler because Python does\n# not allow to use definition based on namespace.\n# 1 for CONTROL_POSITION\n# 2 for CONTROL_VELOCITY.\nrequest.command.move.control = 1\nrequest.command.move.disable_cas = False\n"},{"location":"mmc-api.html#push","title":"Push","text":"Info
Forcefully moves an initialized carrier on the specified axis by one carrier length. Use this movement to cross a line boundary, which deinitializes the carrier from the current line upon completion.
If the carrier field is provided in the push command, the axis enters a pushing state. In this state, the axis remains busy and waits for the specified carrier to arrive; once it arrives, the axis automatically pushes the carrier.
Warning
When pushing the carrier to a different line, the receiving axis on the destination line must be in a pulling state.
Tip
To disable the pushing state on an axis, utilize the stop push command.
Example
Push carrier on axis 1 of line 2 backward to line 1.
Warning
The destination axis on line 1 must be in pulling state.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .push = .{\n .line = 2,\n .axis = 1,\n .direction = .DIRECTION_BACKWARD,\n .velocity = 1000,\n .acceleration = 6000,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.push.line = 2\nrequest.command.push.axis = 1\nrequest.command.push.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.push.velocity = 1000\nrequest.command.push.acceleration = 6000\n"},{"location":"mmc-api.html#pull","title":"Pull","text":"Info
Initialize an incoming carrier located outside the current line. This command puts the specified axis into pulling state. This initialization procedure has the following behavior:
transition field to initialize the carrier at the center of the pulling axistransition field to automatically move to the specified destination as soon as the carrier is recognized.transition, velocity, and acceleration fields to initializes the carrier in the NONE state (not controlled by the motor), allowing it to be moved manually or by external systems.Example
Set axis 6 of line 1 to pulling state, and move the pulled carrier to axis 3.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pull = .{\n .line = 1,\n .axis = 6,\n .carrier = 1,\n .velocity = 1000,\n .acceleration = 6000,\n .direction = .DIRECTION_BACKWARD,\n .transition = .{\n .control = .CONTROL_POSITION,\n .disable_cas = false,\n .target = .{.axis = 3},\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\nCommand = mmc.mmc_dot_command__pb2.Request()\n# Create a request\nrequest = mmc.Request()\nrequest.command.pull.line = 1\nrequest.command.pull.axis = 6\nrequest.command.pull.carrier = 1\nrequest.command.pull.direction = Command.Direction.DIRECTION_BACKWARD\nrequest.command.pull.velocity = 1000\nrequest.command.pull.acceleration = 6000\nrequest.command.pull.transition.control = 1\nrequest.command.pull.transition.disable_cas = False\nrequest.command.pull.transition.axis = 3\n"},{"location":"mmc-api.html#release-carrier","title":"Release Carrier","text":"Info
Put the initialized carrier into the NONE state, allowing it to be moved manually or by external systems.
Example
Release control of carrier 1 on line 1.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .release = .{\n .line = 1,\n .target = .{.carrier = 1},\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.release.line = 1\nrequest.command.release.carrier = 1\n"},{"location":"mmc-api.html#calibrate-line","title":"Calibrate Line","text":"Info
To calibrate the drivers' configuration on a line, an uninitialized carrier must be located at the center of the first axis
Example
Calibrate the drivers' configuration on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .calibrate = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.calibrate.line = 1\n"},{"location":"mmc-api.html#stop-push","title":"Stop Push","text":"Tip
To reset pushing state on all axis, ignore the axes field.
Example
Reset the pushing state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_push = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_push.line = 1\nrequest.command.stop_push.axes.start = 1\nrequest.command.stop_push.axes.end = 4\n"},{"location":"mmc-api.html#stop-pull","title":"Stop Pull","text":"Tip
To reset the pulling state on all axes, omit the axes field.
Example
Reset the pulling state on axes 1 to 4 of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop_pull = .{\n .line = 1,\n .axes = .{\n .start = 1,\n .end = 4,\n },\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop_pull.line = 1\nrequest.command.stop_pull.axes.start = 1\nrequest.command.stop_pull.axes.end = 4\n"},{"location":"mmc-api.html#set-carrier-id","title":"Set Carrier ID","text":"Warning
The carrier ID of each carrier must be unique within a line.
Example
Change the carrier ID of carrier 1 to 4 on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_carrier_id = .{\n .line = 1,\n .carrier = 1,\n .new_carrier = 4,\n },\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_carrier_id.line = 1\nrequest.command.set_carrier_id.carrier = 1\nrequest.command.set_carrier_id.new_carrier = 4\n"},{"location":"mmc-api.html#set-zero","title":"Set Zero","text":"Example
Set the zero point of the first line.
Warning
An initialized carrier must be located on the first axis of the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .set_zero = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.set_zero.line = 1\n"},{"location":"mmc-api.html#clear-errors","title":"Clear Errors","text":"Warning
Always clear errors whenever an error is detected on an axis or driver. Failing to clear errors may result in unwanted behavior.
Tip
Ignore the axes field to clear errors on all drivers and axes on the line.
Example
Clear all errors on the first line.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .clear_errors = .{.line = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.clear_errors.line = 1\n"},{"location":"mmc-api.html#emergency-stop","title":"Emergency Stop","text":"Tip
Pass an empty list to stop operations on all lines.
Example
Stop operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .stop = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.stop.lines.extend([])\n"},{"location":"mmc-api.html#pause-execution","title":"Pause Execution","text":"Tip
Pass empty list to pause operations on all lines.
Example
Pause operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .pause = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.pause.lines.extend([])\n"},{"location":"mmc-api.html#resume-execution","title":"Resume Execution","text":"Tip
Pass an empty list to resume operation on all lines.
Example
Resume operations on all lines.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .@\"resume\" = .{.lines = &.{}},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Create a request\nrequest = mmc.Request()\nrequest.command.resume.lines.extend([])\n"},{"location":"mmc-api.html#remove-command","title":"Remove Command","text":"Warning
Failure to remove a command will block the queue and prevent the server from accepting further commands.
Tip
Always check the command status after sending a command message. (Request Command State)
Example
Remove the command with ID 1 from the server.
zigpythonconst api = @import(\"mmc-api\");\n\n// Create a request\nconst request: api.protobuf.mmc.Request = .{\n .body = .{\n .command = .{\n .body = .{\n .remove_command = .{.command = 1},\n },\n },\n },\n};\n import mmc_pb2 as mmc\n\n# Creating a request message\nrequest = mmc.Request()\nrequest.command.remove_command.command = id\n"},{"location":"mmc-api.html#info-request","title":"Info Request","text":""},{"location":"mmc-api.html#request-command-state","title":"Request Command State","text":"Example
Wait till the command state becomes COMPLETED or FAILED, then remove the command.
const api = @import(\"mmc-api\");\n\nfn waitCommand(id: u32) !void {\n defer removeCommand(id);\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .command = .{ .id = id },\n },\n },\n },\n };\n while (true) {\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n const command_response = switch (decoded.body orelse\n return error.InvalidResponse) {\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .command => |commands_resp| commands_resp.items.items[0],\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n },\n else => return error.InvalidResponse,\n };\n switch (command_response.status) {\n .COMMAND_STATUS_PROGRESSING => {}, // continue the loop\n .COMMAND_STATUS_COMPLETED => return,\n .COMMAND_STATUS_FAILED => {\n std.log.err(\"{t}\", .{command_response.@\"error\".?});\n return;\n },\n .COMMAND_STATUS_UNSPECIFIED => return error.InvalidResponse,\n }\n }\n}\n import mmc_pb2 as mmc\n\ndef waitCommand(id):\n # Creating a request message\n request = mmc.Request()\n request.info.command.id = id\n while True:\n # Send and receive response\n s.sendall(request.SerializeToString())\n response = s.recv(4096)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n Command = mmc.mmc_dot_info__pb2.Response.Command()\n\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n return\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n return\n elif msg.info.WhichOneof(\"body\") == \"command\":\n command = msg.info.command.items[0]\n if command.status == Command.Status.COMMAND_STATUS_COMPLETED:\n removeCommand(id)\n return\n elif command.status == Command.Status.COMMAND_STATUS_FAILED:\n removeCommand(id)\n raise Exception(Command.Error.Name(command.error))\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n else:\n print(\"Invalid Response\")\n return\n"},{"location":"mmc-api.html#request-track-state","title":"Request Track State","text":"Tip
Certain commands require the client to monitor carrier status to ensure movement is completed.
MOVE_COMPLETED before sending a new command to that carrier.CALIBRATE_COMPLETED to ensure the driver configuration is valid.INITIALIZE_COMPLETED before performing further operations on the carrier.transition field is omitted, wait for PULL_COMPLETED; otherwise, wait for MOVE_COMPLETED.Warning
Monitor the error flags of driver, axis and carriers to prevent damage to the motor or driver board. Pay close attention to inverter_overheat on the driver and overcurrent flags on the axis; immediately deinitialize any carrier on the affected axes and drivers if these are detected. The overvoltage and undervoltage flags indicate that the system voltage supply may have a problem; please consult with our engineers to resolve the issue.
Request carrier state
Tip
filter field when sending track info message to retrieve all toggled flags information.const api = @import(\"mmc-api\");\nfn carrierState(line: u32, carrier: u32) !void {\n var carrier_id = [1]u32{carrier};\n const request: api.protobuf.mmc.Request = .{\n .body = .{\n .info = .{\n .body = .{\n .track = .{\n .line = line,\n .info_carrier_state = true,\n .filter = .{\n .carriers = .{\n .ids = .fromOwnedSlice(&carrier_id),\n },\n },\n },\n },\n },\n },\n };\n try request.encode(&writer.interface, allocator);\n try writer.interface.flush();\n var decoded: api.protobuf.mmc.Response = try .decode(\n &reader.interface,\n allocator,\n );\n defer decoded.deinit(allocator);\n switch (decoded.body orelse return error.InvalidResponse) {\n .info => |info_resp| switch (info_resp.body orelse\n return error.InvalidResponse) {\n .track => |track_resp| {\n std.log.info(\"{}\", .{track_resp.carrier_state.items[0]});\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n },\n else => return error.InvalidResponse,\n },\n .request_error => |req_err| {\n std.log.err(\"{t}\", .{req_err});\n return;\n },\n else => return error.InvalidResponse,\n }\n}\n import mmc_pb2 as mmc\ndef carrierState(line, carrier):\n # Creating a request message\n request = mmc.Request()\n request.info.track.line = line\n request.info.track.info_carrier_state = True\n request.info.track.carriers.ids.append(carrier)\n\n # Parsing the response\n msg = mmc.Response()\n msg.ParseFromString(response)\n # Validate and use the response accordingly\n if msg.WhichOneof(\"body\") == \"request_error\":\n print(\"Request Error\", mmc.Request.Error.Name(msg.request_error))\n elif msg.WhichOneof(\"body\") == \"info\":\n # Validate if the core response that we receive is `api_version`\n if msg.info.WhichOneof(\"body\") == \"request_error\":\n print(\n \"Request Error\",\n mmc.mmc_dot_info__pb2.Request.Error.Name(msg.info.request_error),\n )\n elif msg.info.WhichOneof(\"body\") == \"track\":\n assert len(msg.info.track.carrier_state) != 0\n carrier = msg.info.track.carrier_state[0]\n print(carrier)\n else:\n print(\"Invalid Response\")\n else:\n print(\"Invalid Response\")\n"},{"location":"protocol-documentation.html","title":"Protocol Documentation","text":""},{"location":"protocol-documentation.html#table-of-contents","title":"Table of Contents","text":"mmc.proto
Response
Request.Error
range.proto
mmc/command.proto
Response
Request.Direction
mmc/control.proto
mmc/core.proto
Response.TrackConfig.Line
Request.Error
mmc/info.proto
Response.Track
Request.Error
Scalar Value Types
Top
"},{"location":"protocol-documentation.html#mmcproto","title":"mmc.proto","text":""},{"location":"protocol-documentation.html#request","title":"Request","text":"Request message. All client-to-server messages should be of this message type.
Field Type Label Description core core.Request Core request. Used to retrieve information about the server or the configured track. command command.Request Command request. Used to send and manage commands to the server, which will execute commands on the connected track. info info.Request Info request. Used to retrieve information about track state or commands processed by the server. "},{"location":"protocol-documentation.html#response","title":"Response","text":"Response message. All server-to-client messages will be of this message type.
Field Type Label Description core core.Response Core response. command command.Response Command response. info info.Response Info Response. request_error Request.Error Top-level request error. This error field will be returned only if the top-level request could not be handled properly. Otherwise, response kinds may contain more specific error codes. "},{"location":"protocol-documentation.html#requesterror","title":"Request.Error","text":"Name Number Description MMC_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. MMC_REQUEST_ERROR_INVALID_MESSAGE 1 The request could not be decoded as a valid protobuf message.Top
"},{"location":"protocol-documentation.html#rangeproto","title":"range.proto","text":""},{"location":"protocol-documentation.html#range","title":"Range","text":"Field Type Label Description start uint32 Start of range, inclusive. end uint32 End of range, inclusive.Top
"},{"location":"protocol-documentation.html#mmccommandproto","title":"mmc/command.proto","text":""},{"location":"protocol-documentation.html#request_1","title":"Request","text":"Command API: List of commands to operate the PMF's motion system.
When a command is sent to the server, it will be queued for execution. Command execution status can be polled through the Info API. The status remains stored in a limited history buffer, and should be cleared with remove_command after completion.
Automatically initialize carriers on every specified lines.
Expected response: mmc.Response.body.command.body.id (uint32).
Calibrate a line by positioning an uninitialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear all error information on the driver. If a target is specified, clear error information of drivers included in that target. If not, clear error information on all drivers of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Clear carrier information located on the axis. If a target is specified, clear information of carriers included in that target. If not, clear all carrier information of the specified line ID.
Expected response: mmc.Response.body.command.body.id (uint32).
Initialize a carrier.
Expected response: mmc.Response.body.command.body.id (uint32).
Move a carrier to the desired position.
Expected response: mmc.Response.body.command.body.id (uint32).
SetZero command. distance float Move carrier to relative distance to current carrier position. Negative distance moves the carrier backwards. control mmc.Control Control method for moving carrier. disable_cas bool Disable the carrier's collision avoidance system (CAS). "},{"location":"protocol-documentation.html#requestpause","title":"Request.Pause","text":"Pause any operation in PMF LMS. Any queued commands in the server will be continued once the resume command is given.
Expected response: mmc.Response.body.command.body.id (uint32).
Pull and initialize a new carrier into a line.
Expected response: mmc.Response.body.command.body.id (uint32).
NaN, the velocity must be 0. acceleration float Acceleration of carrier movement. Floating point with range 100 - 24,500 mm/s^2. When the transition location target is set to NaN, the acceleration must be 0. transition Request.Pull.Transition optional Smoothly transition to carrier movement after pull completion. "},{"location":"protocol-documentation.html#requestpulltransition","title":"Request.Pull.Transition","text":"Field Type Label Description control mmc.Control Control method for moving carrier. disable_cas bool Disabling the carrier's collision avoidance system (CAS). target float Move carrier to relative location to the zero-point of the line, which is set by default at the center of the line's first axis after calibration, but can also be set with the SetZero command. Pass NaN to pull carrier without motor control, allowing carrier to be pulled with external force."},{"location":"protocol-documentation.html#requestpush","title":"Request.Push","text":"Push an initialized carrier to the specified direction.
Expected response: mmc.Response.body.command.body.id (uint32).
Release the control imposed by the motor to the carrier. If a target is specified, all motors included in that target release control. Otherwise, all carriers on the provided line will be released from control.
Expected response: mmc.Response.body.command.body.id (uint32).
Remove a command on the server if the command ID is specified. If no command ID is specified, remove any commands received by the server. If the commands are still progressing, cancel the command execution.
Expected response: mmc.Response.body.command.body.removed_id (uint32).
Resume lines that have been stopped or paused. If the line is not paused or emergency stopped, this command will succeed without any effect.
Expected response: mmc.Response.body.command.body.id (uint32).
Change the carrier ID of an existing initialized carrier. If the new carrier ID already exists on the line, returns INVALID_CARRIER.
Expected response: mmc.Response.body.command.body.id (uint32).
Set a zero position of a line by positioning an initialized carrier on the first axis of the line.
Expected response: mmc.Response.body.command.body.id (uint32).
Send an emergency stop command to stop any operation in PMF LMS. This command also removes all queued commands in the server.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pulling a carrier to the specified axis. If no axis is provided, then all pending carrier pulls on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Stop pushing a carrier from the specified axis. If no axis is provided, then all pending carrier pushes on the line will be stopped.
Expected response: mmc.Response.body.command.body.id (uint32).
Response description to the command API.
Field Type Label Description id uint32 Assigned ID for newly sent command. removed_id uint32 ID of cleared existing command. request_error Request.Error Error during command's execution. "},{"location":"protocol-documentation.html#requestdirection","title":"Request.Direction","text":"Name Number Description DIRECTION_UNSPECIFIED 0 DIRECTION_BACKWARD 1 DIRECTION_FORWARD 2"},{"location":"protocol-documentation.html#requesterror_1","title":"Request.Error","text":"Name Number Description COMMAND_REQUEST_ERROR_UNSPECIFIED 0 COMMAND_REQUEST_ERROR_INVALID_LINE 1 Attempted to use line ID outside of the configured lines. COMMAND_REQUEST_ERROR_INVALID_AXIS 2 Attempted to use axis ID outside of the configured axes of the line. COMMAND_REQUEST_ERROR_INVALID_DRIVER 3 Attempted to use driver ID outside of the configured drivers of the line. COMMAND_REQUEST_ERROR_INVALID_ACCELERATION 4 Attempted to use acceleration value outside of 1-245. COMMAND_REQUEST_ERROR_INVALID_VELOCITY 5 Attempted to use velocity value outside of 1-60. COMMAND_REQUEST_ERROR_INVALID_DIRECTION 6 Using invalid direction for the command. COMMAND_REQUEST_ERROR_INVALID_LOCATION 7 Deprecated. CheckCOMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_DISTANCE 8 Deprecated. Check COMMAND_ERROR_INVALID_CARRIER_TARGET on Info.Response.Command.Error. COMMAND_REQUEST_ERROR_INVALID_CARRIER 9 Attempted to send a command to carrier outside of 1-2048. COMMAND_REQUEST_ERROR_MISSING_PARAMETER 10 A command missing the required parameter. COMMAND_REQUEST_ERROR_COMMAND_NOT_FOUND 11 Attempted to remove or cancel a non-existing command. COMMAND_REQUEST_ERROR_CARRIER_NOT_FOUND 12 Attempted to send command to an uninitialized carrier. COMMAND_REQUEST_ERROR_OUT_OF_MEMORY 14 Server unable to receive new command caused by out of memory. Try Command.Request.remove_command to free the memory. COMMAND_REQUEST_ERROR_MAXIMUM_AUTO_INITIALIZE_EXCEEDED 15 Attempted to run more than 8 auto initialize instance. COMMAND_REQUEST_ERROR_CONFLICTING_CARRIER_ID 16 Attempted to assign a carrier ID that is already used by another carrier on the same line. COMMAND_REQUEST_ERROR_INVALID_COMMAND 17 Command index is out of bounds for the configured command status buffer. Top
"},{"location":"protocol-documentation.html#mmccontrolproto","title":"mmc/control.proto","text":""},{"location":"protocol-documentation.html#control","title":"Control","text":"Carrier motor control kind.
Name Number Description CONTROL_UNSPECIFIED 0 CONTROL_POSITION 1 Carrier controlled with position priority. CONTROL_VELOCITY 2 Carrier controlled with velocity priority.Top
"},{"location":"protocol-documentation.html#mmccoreproto","title":"mmc/core.proto","text":""},{"location":"protocol-documentation.html#request_2","title":"Request","text":"Field Type Label Description kind Request.Kind"},{"location":"protocol-documentation.html#response_2","title":"Response","text":"Response description to the core API.
Field Type Label Description server Response.Server Server process information. track_config Response.TrackConfig Track configuration. request_error Request.Error Error response if the core request could not be handled. "},{"location":"protocol-documentation.html#responsesemanticversion","title":"Response.SemanticVersion","text":"Field Type Label Description major uint32 minor uint32 patch uint32"},{"location":"protocol-documentation.html#responseserver","title":"Response.Server","text":"Server version and name.
Field Type Label Description name string Server name. version Response.SemanticVersion Server implementation version. api Response.SemanticVersion "},{"location":"protocol-documentation.html#responsetrackconfig","title":"Response.TrackConfig","text":"Field Type Label Description lines Response.TrackConfig.Line repeated All configured lines in track."},{"location":"protocol-documentation.html#responsetrackconfigline","title":"Response.TrackConfig.Line","text":"Field Type Label Description id uint32 Line ID. Numeric ID, starting from 1, that is unique to each line in the track. This ID is used to address the line in other requests. name string Configured line name. This name is otherwise unused by the API, and is provided to the client for end-user convenience. axes uint32 Total number of axes in the line. axis_length float Length of each axis in the line, in millimeters. carrier_length float Carrier dimension parallel to carrier movement, in millimeters. drivers uint32 Total number of drivers in the line. carrier_width float Carrier dimension perpendicular to carrier movement, in millimeters."},{"location":"protocol-documentation.html#requesterror_2","title":"Request.Error","text":"Name Number Description CORE_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. CORE_REQUEST_ERROR_REQUEST_UNKNOWN 1 The core request kind was unspecified."},{"location":"protocol-documentation.html#requestkind","title":"Request.Kind","text":"Name Number Description CORE_REQUEST_KIND_UNSPECIFIED 0 This request kind is unused, and should never be sent. It is reserved as the default request kind according to protobuf specification. CORE_REQUEST_KIND_SERVER_INFO 2 Request server process information. This includes the configured server name and server implementation version. CORE_REQUEST_KIND_TRACK_CONFIG 3 Request the configured track information of the server.Top
"},{"location":"protocol-documentation.html#mmcinfoproto","title":"mmc/info.proto","text":""},{"location":"protocol-documentation.html#request_3","title":"Request","text":"Field Type Label Description command Request.Command Command information request. Get current status of command; necessary to determine if command is currently running, completed, or failed. track Request.Track Track information request. Get current track state information."},{"location":"protocol-documentation.html#requestcommand","title":"Request.Command","text":"Request for status of specified command ID from the server. If no command ID is provided, then request for status of all commands from the server.
Expected response: mmc.Response.body.info.body.commands
Request track state information from server. One or more of the info_ flags must be enabled to select the kind of track information desired. A filter may be optionally provided to limit the source of information from the track.
Expected response: mmc.Response.body.info.body.track
List of IDs. At least one ID must be provided.
Field Type Label Description ids uint32 repeated "},{"location":"protocol-documentation.html#response_3","title":"Response","text":"Field Type Label Description command Response.Commands Information for requested command(s). If empty, no matching command(s) was found. track Response.Track Information for requested track state. request_error Request.Error Info request error. This error field will be returned if the provided info request could not be handled properly."},{"location":"protocol-documentation.html#responsecommand","title":"Response.Command","text":"Field Type Label Description id uint32 Command ID. Valid IDs begin from 1, and may be reused after command status is cleared from server history. status Response.Command.Status Command status. error Response.Command.Error optional Command error response, only if the status isCOMMAND_STATUS_FAILED."},{"location":"protocol-documentation.html#responsecommands","title":"Response.Commands","text":"Field Type Label Description items Response.Command repeated"},{"location":"protocol-documentation.html#responseline","title":"Response.Line","text":"Field Type Label Description id uint32 Line ID. driver_state Response.Line.Driver.State repeated Driver state information list. Empty if request flag was disabled. driver_errors Response.Line.Driver.Error repeated Driver error information list. Empty if request flag was disabled. axis_state Response.Line.Axis.State repeated Axis state information list. Empty if request flag was disabled. axis_errors Response.Line.Axis.Error repeated Axis error information list. Empty if request flag was disabled. carrier_state Response.Line.Carrier.State repeated Carrier state information list. Empty if request flag was disabled."},{"location":"protocol-documentation.html#responselineaxis","title":"Response.Line.Axis","text":""},{"location":"protocol-documentation.html#responselineaxiserror","title":"Response.Line.Axis.Error","text":"Field Type Label Description id uint32 Axis ID. overcurrent bool Motor overcurrent detected. Motor control released to prevent damage."},{"location":"protocol-documentation.html#responselineaxisstate","title":"Response.Line.Axis.State","text":"Field Type Label Description id uint32 Axis ID. motor_active bool Axis is currently controlling a carrier. waiting_pull bool Axis is waiting to pull carrier. waiting_push bool Axis is waiting to push carrier. carrier uint32 Carrier ID; non-zero if an initialized carrier is on the axis. hall_alarm_back bool Axis back hall alarm is active. Magnet is detected above back hall sensor. hall_alarm_front bool Axis front hall alarm is active. Magnet is detected above front hall sensor."},{"location":"protocol-documentation.html#responselinecarrier","title":"Response.Line.Carrier","text":""},{"location":"protocol-documentation.html#responselinecarrierstate","title":"Response.Line.Carrier.State","text":"Field Type Label Description id uint32 Carrier ID. Will always be non-zero. position float Position of the carrier in line, in meters. axis_main uint32 Carrier's primary axis ID. axis_auxiliary uint32 optional Carrier's auxiliary axis ID, if carrier is on top of two axes. cas_disabled bool Collision avoidance system (CAS) disabled. cas_triggered bool Collision avoidance system (CAS) triggered. Carrier will automatically resume movement when path is clear. state Response.Line.Carrier.State.State Carrier state."},{"location":"protocol-documentation.html#responselinedriver","title":"Response.Line.Driver","text":""},{"location":"protocol-documentation.html#responselinedrivererror","title":"Response.Line.Driver.Error","text":"Field Type Label Description id uint32 Driver ID. control_loop_time_exceeded bool Control loop exceeded maximum loop time. inverter_overheat bool Inverter is overheated. undervoltage bool Driver voltage supply too low. overvoltage bool Driver voltage supply too high. comm_error_prev bool Communication error with previous driver in line. comm_error_next bool Communication error with next driver in line."},{"location":"protocol-documentation.html#responselinedriverstate","title":"Response.Line.Driver.State","text":"Field Type Label Description id uint32 Driver ID. connected bool Connection status between driver and server. busy bool Driver is currently executing a command. motor_disabled bool Driver motor release activated. All driver motors are inactive. stopped bool Driver emergency stop activated. paused bool Driver pause activated."},{"location":"protocol-documentation.html#responsetrack","title":"Response.Track","text":"Field Type Label Description lines Response.Line repeated"},{"location":"protocol-documentation.html#requesterror_3","title":"Request.Error","text":"Name Number Description INFO_REQUEST_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. INFO_REQUEST_ERROR_INVALID_LINE 1 Invalid line ID provided. Ensure that line ID exists in track configuration. INFO_REQUEST_ERROR_INVALID_AXIS 2 Invalid axis ID provided. Ensure that axis ID exists in line. INFO_REQUEST_ERROR_INVALID_DRIVER 3 Invalid driver ID provided. Ensure that driver ID exists in line. INFO_REQUEST_ERROR_MISSING_PARAMETER 4 Request is missing a required parameter. Ensure that at least one of the information flag is selected when requesting track information. INFO_REQUEST_ERROR_COMMAND_NOT_FOUND 5 Attempted to request information from a non-existing command. INFO_REQUEST_ERROR_INVALID_COMMAND 6 Command index is out of bounds for the configured command status buffer. INFO_REQUEST_ERROR_INVALID_CARRIER 7 Attempted to send a command to carrier outside of range."},{"location":"protocol-documentation.html#responsecommanderror","title":"Response.Command.Error","text":"Name Number Description COMMAND_ERROR_UNSPECIFIED 0 This error code is unused, and will never be returned. It is reserved as the default error code according to protobuf specification. COMMAND_ERROR_INVALID_SYSTEM_STATE 1 System state prevented successful command execution. Ensure that all preconditions are met with track info request before sending command. COMMAND_ERROR_INVALID_CARRIER_ID 2 Deprecated. Check COMMAND_REQUEST_ERROR_INVALID_CARRIER on Command.Request.Error. COMMAND_ERROR_DRIVER_DISCONNECTED 3 Driver connection failed while command progressing. COMMAND_ERROR_UNEXPECTED 4 Unexpected command execution error. This is likely an implementation bug; please contact PMF support for assistance. COMMAND_ERROR_CARRIER_NOT_FOUND 5 Target carrier is removed while command progressing. COMMAND_ERROR_CARRIER_ALREADY_INITIALIZED 6 Attempted to initialize an initialized carrier. COMMAND_ERROR_DRIVER_STOPPED 7 Target driver is stopped while command progressing. Consider resume the driver before sending further command. COMMAND_ERROR_INVALID_CARRIER_TARGET 8 Carrier targeting a location outside of the configured track. COMMAND_ERROR_CONFLICTING_CARRIER_ID 9 Attempted to assign a new carrier with an ID that is already used by other carrier on the same line"},{"location":"protocol-documentation.html#responsecommandstatus","title":"Response.Command.Status","text":"Name Number Description COMMAND_STATUS_UNSPECIFIED 0 This command status is unused, and will never be returned. It is reserved as the default status code according to protobuf specification. COMMAND_STATUS_PROGRESSING 1 Command currently executing. COMMAND_STATUS_COMPLETED 2 Command completed. COMMAND_STATUS_FAILED 3 Command execution failed."},{"location":"protocol-documentation.html#responselinecarrierstatestate","title":"Response.Line.Carrier.State.State","text":"Name Number Description CARRIER_STATE_NONE 0 CARRIER_STATE_CALIBRATING 1 Carrier is currently operating for line calibration. CARRIER_STATE_CALIBRATE_COMPLETED 2 Carrier has completed line calibration, and may now be used for normal operation. CARRIER_STATE_MOVING 3 Carrier is currently moving towards target destination. CARRIER_STATE_MOVE_COMPLETED 4 Carrier has arrived within threshold at target destination. CARRIER_STATE_INITIALIZING 5 Carrier is initializing. Must not be used until initialization is completed. CARRIER_STATE_INITIALIZE_COMPLETED 6 Carrier initialization completed. May now be used for normal operation. CARRIER_STATE_PUSHING 7 Carrier is being pushed by axis. Used to eject carrier from line. CARRIER_STATE_PULLING 9 Carrier is being pulled by axis. Must not be used until pull is completed. CARRIER_STATE_OVERCURRENT 11 Overcurrent detected in carrier axis motor. Carrier movement has been canceled."},{"location":"protocol-documentation.html#scalar-value-types","title":"Scalar Value Types","text":".proto Type Notes C++ Java Python Go C# PHP Ruby double double double float float64 double float Float float float float float float32 float float Float int32 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required) int64 Uses variable-length encoding. Inefficient for encoding negative numbers \u2013 if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required) uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required) sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required) sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required) fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required) sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum bool bool boolean boolean bool bool boolean TrueClass/FalseClass string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8) bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)"}]}
\ No newline at end of file
diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz
index 07d697c..b751ac7 100644
Binary files a/site/sitemap.xml.gz and b/site/sitemap.xml.gz differ
diff --git a/src/protobuf/mmc/core.pb.zig b/src/protobuf/mmc/core.pb.zig
index cb2dc32..a41da3b 100644
--- a/src/protobuf/mmc/core.pb.zig
+++ b/src/protobuf/mmc/core.pb.zig
@@ -118,6 +118,7 @@ pub const Response = struct {
axis_length: f32 = 0,
carrier_length: f32 = 0,
drivers: u32 = 0,
+ carrier_width: f32 = 0,
pub const _desc_table = .{
.id = fd(1, .{ .scalar = .uint32 }),
@@ -126,6 +127,7 @@ pub const Response = struct {
.axis_length = fd(4, .{ .scalar = .float }),
.carrier_length = fd(5, .{ .scalar = .float }),
.drivers = fd(6, .{ .scalar = .uint32 }),
+ .carrier_width = fd(7, .{ .scalar = .float }),
};
pub fn encode(