.. _modbus-index: ########## Modbus TCP ########## .. warning:: The Modbus functionality is under development and may be subject to change. Note that Modbus features are only supported from version 0.27.0. ======== Overview ======== Evolabel printers provide a Modbus TCP Server interface which can be accessed on port 502. Only one client connection at a time is allowed. All Modbus addresses in this documentation are 1-based, and offsets are 0-based from their respective register bank. Supported Function Codes ------------------------ FC 1 Read Discrete Output Coils The output coil registers 00001-00004 can be read using a single Modbus transaction. FC 2 Read Discrete Input Contacts The discrete input registers 10001-10006 can be read using a single Modbus transaction. FC 3 Read Multiple Holding Registers It is only supported to read one register at a time. Most holding registers map to unique function calls that are not useful to group together in a single transaction. FC 4 Read Input Registers The modbus registers 30001-30080 can be read using a single Modbus transaction. FC 5 Write Single Discrete Output Coil Set the state of a single hardware output port. FC 6 Write Single Register Trigger a function call. FC 15 Write Multiple Discrete Output Coils Set the state of multiple hardware output ports 00001-00006 in a single transaction. FC 16 Write Multiple Registers It is only supported to write one register at a time. Most holding registers map to unique function calls that are not useful to group together in a single transaction. Discrete Output Coils --------------------- .. modbus-table:: COILS Discrete Input Contacts ----------------------- .. modbus-table:: DISCRETE_INPUTS Input Registers --------------- .. modbus-table:: INPUT_REGISTERS Holding Registers ----------------- .. modbus-table:: HOLDING_REGISTERS Motorized Stands ---------------- Motorized Stands are controlled by addressing a *stand number*. The stand number is shown in the user interface under *Peripherals -> Motorized Stand*. .. _modbus_discrete_output_coils: ===================== Discrete Output Coils ===================== The state of hardware output ports can be read and set by reading and writing to the corresponding address. .. modbus-register:: COILS RW_IO_O1 .. modbus-register:: COILS RW_IO_O2 .. modbus-register:: COILS RW_IO_O3 .. modbus-register:: COILS RW_IO_O4 .. _modbus_discrete_inputs: =============== Discrete Inputs =============== The state of hardware input ports can be read by reading the corresponding address. .. modbus-register:: DISCRETE_INPUTS RD_IO_IN1 .. modbus-register:: DISCRETE_INPUTS RD_IO_IN2 .. modbus-register:: DISCRETE_INPUTS RD_IO_IN3 .. modbus-register:: DISCRETE_INPUTS RD_IO_IN4 .. modbus-register:: DISCRETE_INPUTS RD_IO_TRIG1 .. modbus-register:: DISCRETE_INPUTS RD_IO_TRIG2 .. _modbus_input_registers: =============== Input Registers =============== .. modbus-register:: INPUT_REGISTERS RD_MARKER_STATE The lower bits of the register holds the current marker state. This is a bitfield where each bit indicates one of the states ``"offline"``, ``"online"``, ``"stopping"``, ``"alarm"`` and ``"test"``. Note that ``"stopping"`` is a substate to ``"online"`` and ``"alarm"`` is a substate to ``"offline"``. Those states will have the bit representing their superstate set as well. The upper bits are used for indicating state changes and that more information can be read in other registers. The upper bits are cleared on read. b15: Updated information in any of :ref:`RD_STAND1_POS `, :ref:`RD_STAND2_POS `, or :ref:`RD_STAND3_POS ` .. modbus-register:: INPUT_REGISTERS RD_SEQUENCE_STATE Get the current print and apply sequence state. This is useful for high level tracking of print and apply sequences. The register is divided into two parts: *state*, and *label index*. .. image:: /media/modbus-sequence.png :width: 500px .. note:: Some states are transient (will only be active during a very brief time), so a PLC program must handle that e.g. after *printing*, the next state *wait_apply* is never read, but the state will transfer directly to *applying*, as shown in the examples below. Example: *Triggering a single label print and apply cycle with a normal sequential sequence* .. wavedrom:: { signal: [ { name: "PLC", node: ".A........" }, {}, { name: "state", wave: "=.=.=.=.", node: "..B.......", data: ["idle", "printing", "applying", "idle"] }, { name: "label index", wave: "=.=...=.", data: ["0", "1", "0"] }, ], edge: [ 'A->B WR_SEQUENCE_PRINT 0' ] } | Example: *Triggering a dual label print and apply cycle with a normal sequential sequence* .. wavedrom:: { signal: [ { name: "PLC", node: ".A........" }, {}, { name: "state", wave: "=.=.=.=.=.=.", node: "..B.......", data: ["idle", "printing", "applying", "printing", "applying", "idle"] }, { name: "label index", wave: "=.=...=...=.", data: ["0", "1", "2", "0"] }, ], edge: [ 'A->B WR_SEQUENCE_PRINT 0' ] } | Example: *Externally controlled print and apply cycle* .. wavedrom:: { signal: [ { name: "PLC", node: ".A....C....E.." }, {}, { name: "state", wave: "=.=.=.==.=.==.", node: "..B....D....F.", data: ["idle", "printing", "applying", "wait", "printing", "applying", "wait", "idle"] }, { name: "label index", wave: "=.=....=....=.", data: ["0", "1", "2", "0"] }, ], edge: [ 'A->B WR_SEQUENCE_PRINT 1', 'C->D WR_SEQUENCE_PRINT_2', 'E->F WR_SEQUENCE_FINISH', ] } | .. modbus-register:: INPUT_REGISTERS RD_SEQUENCE_RESULT Read the result of the last finished sequence (either successfully finished, or aborted). ``b0`` contains the result when ``b14`` is ``1``. Success When *Data valid* is set, this bit represents the success of the last sequence. Automatically cleared upon read. Data valid Set when a sequence is finished or aborted. Automatically cleared upon read. Data loss Unread data was overwritten by new state changes. Automatically cleared upon read. Example: *One successful sequence followed by one failed sequence* (where *state* is from RD_SEQUENCE_STATE). .. wavedrom:: { signal: [ { name: "PLC", node: ".A.....C...E.." }, {}, { name: "state", wave: "=.=.=.=.=.=.=.", node: "..B.....D...F.", data: ["idle", "printing", "applying", "idle", "printing", "error", "idle"] }, { name: "valid", wave: "0.....10....10", }, { name: "success", wave: "0.....1x....0x", }, ], edge: [ 'A->B WR_SEQUENCE_PRINT', 'C->D WR_SEQUENCE_PRINT', 'E->F WR_SEQUENCE_ABORT', ] } | .. modbus-register:: INPUT_REGISTERS RD_APPLICATOR_STATE Get the current applicator state. This is valid both for test sequences and production sequences. Each bit represents one state, and multiple bits can be set simultaneously. Nonblocking The applicator is in a position that will not block products in front of it. This may include printing or service positions, and will always be ``1`` for some applicator types that never block. Applying The applicator is applying. Note that this state may be very short and can cause data loss for fast applicators. Error The applicator is in an error state. Data loss Unread data was overwritten by new state changes. .. modbus-register:: INPUT_REGISTERS RD_PRINTER_STATE Get the current printer state. This is valid both for test sequences and production sequences. Each bit represents one aspect, and multiple bits can be set simultaneously. .. note:: A printout can only be started if all bits in this register is zero. Label stabilizing The label is printed but waits for mechanical stabilization before application can start. This is a transient state that is only active up to 200 ms. Print sequence is active Printer is printing, waiting for application to start, or backfeeding. No print data No print data is loaded to the printhead. If the printer is in *Dispenser Mode* this bit is never set. Trig blocking Trig block timer is active. Printer alarm Print head open, paper out, or ribbon out. .. versionadded:: Unreleased Soft inhibition A software inhibition is active. Applicator is active Applicator is blocking printouts. .. modbus-register:: INPUT_REGISTERS RD_MESSAGES_ALARMS Get active alarms. The lower bits are mapped to specific alarms or alarm groups. The highest bit (b15) is set whenever *any* alarm, including ones not represented by the lower bits, is active. The description in the table below is the exact alarm name, as would have been reported as `"message_id"` in :ref:`notification-messages_active_changed` , with the exception of b4 (which represents any alarm in the `group` `"applicator"`) and b15. .. modbus-register:: INPUT_REGISTERS RD_MESSAGES_WARNINGS Get active warnings. The register works similar to :ref:`RD_MESSAGES_ALARMS `. .. modbus-register:: INPUT_REGISTERS RD_JOB_STATE Get job availability. API documentation: :ref:`method-jobs_state_get` .. modbus-register:: INPUT_REGISTERS RD_STAND1_POS This register contains the last known position for the first motorized stand. If b15 is ``1`` the position is unknown. If b15 is ``0``, b10-b0 contains the stand position in mm in user coordinates. b11 specifies the sign of the position value. ``0`` means positive, and ``1`` means negative. .. modbus-register:: INPUT_REGISTERS RD_STAND2_POS This register contains the last known position for the second motorized stand. For details, see :ref:`RD_STAND1_POS `. .. modbus-register:: INPUT_REGISTERS RD_STAND3_POS This register contains the last known position for the third motorized stand. For details, see :ref:`RD_STAND1_POS `. .. modbus-register:: INPUT_REGISTERS RD_SCANNER1_RESULT beta These registers contain the scanner data from scanner 1. Each register (16 bits) is interpreted as two ASCII characters. The data is truncated if it is longer that 64 characters. If shorter it is padded with ``0x00``. If the last status from the scanner is not ``"ok"``, the data will be the empty string (all ``0x00``). .. modbus-register:: INPUT_REGISTERS RD_SCANNER2_RESULT beta These registers contain the scanner data from scanner 2. For details, see :ref:`RD_SCANNER1_RESULT `. .. modbus-register:: INPUT_REGISTERS RD_SCANNER3_RESULT beta These registers contain the scanner data from scanner 3. For details, see :ref:`RD_SCANNER1_RESULT `. .. _modbus_holding_registers: ================= Holding Registers ================= Complex commands with parameters or options are issued by writing a 16 bit value to the corresponding address. .. modbus-register:: HOLDING_REGISTERS WR_MARKER_STATE Instruct the printer to go either offline or online. .. modbus-register:: HOLDING_REGISTERS WR_API_HEARTBEAT_TIMEOUT If client writes any value but ``0`` to this register, :ref:`WR_API_HEARTBEAT ` must be written to at least every `N` seconds, where `N` is the value written to this register. If the client disconnects or :ref:`WR_API_HEARTBEAT ` is *not* written to at least every `N` seconds, the printer will enter alarm state. Set to ``0`` (default) to toggle off. Maximum accepted value is ``10``. This setting is transient. If the client disconnects, or fails to send :ref:`WR_ALIVE ` in time so that an alarm is raised, the value is reset to ``0`` and will have to be set again. If any non ``0`` value has been written, a client must write ``0`` to this register again before disconnecting to avoid raising an alarm. .. modbus-register:: HOLDING_REGISTERS WR_API_HEARTBEAT Inform printer that the client is still alive. This is needed when :ref:`WR_API_HEARTBEAT_TIMEOUT ` has been set to anything but ``0``. .. modbus-register:: HOLDING_REGISTERS WR_SEQUENCE_PRINT Print the active job immediately. API documentation: :ref:`method-sequence_print` If the printer is *not* configured for :ref:`external_sequence_control-index`, only the value ``0`` may be written to this register. This will trigger printing of the loaded label. If the printer *is* configured for :ref:`external_sequence_control-index`, the values ``1``, ``2`` or ``3`` written to this register will trigger *both* printing and then applying with the specified preconfigured External Apply Sequence, similar to if :ref:`WR_SEQUENCE_APPLY ` had been written to when printing was completed. It is still possible to write ``0`` in this mode, in order to just trigger printing. .. modbus-register:: HOLDING_REGISTERS WR_SEQUENCE_APPLY Apply current label. API documentation: :ref:`method-sequence_apply` If the printer is *not* configured for :ref:`external_sequence_control-index`, only the value ``0`` may be written to this register, and initiates the apply sequence configured for the current label. This is equivalent to invoking :ref:`method-sequence_apply` with no parameters. If the printer *is* configured for :ref:`external_sequence_control-index`, only the values ``1``, ``2`` or ``3`` may be written to this register, and will then trigger the corresponding preconfigured External Apply Sequence. Writing ``1`` is equivalent to invoking :ref:`method-sequence_apply` with the parameters ``{"index": 1}``. .. modbus-register:: HOLDING_REGISTERS WR_SEQUENCE_ABORT Abort the current sequence. API documentation: :ref:`method-sequence_abort` .. modbus-register:: HOLDING_REGISTERS WR_SEQUENCE_FINISH Finish the current external sequence. Only applicable for :ref:`external_sequence_control-index`. API documentation: :ref:`method-sequence_finish` .. modbus-register:: HOLDING_REGISTERS WR_MESSAGES_RESET Reset active alarms. Note that not all alarms can be reset this way. Only alarms that would be possible to reset by pressing the Control Bar button Reset are possible to reset. .. modbus-register:: HOLDING_REGISTERS WR_MESSAGE1 Acivate or inactivate custom message 1. .. modbus-register:: HOLDING_REGISTERS WR_MESSAGE2 Acivate or inactivate custom message 2. .. modbus-register:: HOLDING_REGISTERS WR_JOB_CLEAR Remove all elements in the print job queue. API documentation: :ref:`method-jobs_clear`. .. modbus-register:: HOLDING_REGISTERS WR_STAND_STOP Stop specified stands. More than one stand can be specified. API documentation: :ref:`method-stand_stop`. .. modbus-register:: HOLDING_REGISTERS WR_STAND1_GOTO_MM Move motorized stand to specified position in user coordinates. In order to ensure that stands are moved only when there is a working communication, it is recommended to enable :ref:`WR_API_HEARTBEAT_TIMEOUT ` before writing to this register. .. modbus-register:: HOLDING_REGISTERS WR_STAND2_GOTO_MM Move stand2 to specified position. For details, see :ref:`WR_STAND1_GOTO `. .. modbus-register:: HOLDING_REGISTERS WR_STAND3_GOTO_MM Move stand3 to specified position. For details, see :ref:`WR_STAND1_GOTO `. .. modbus-register:: HOLDING_REGISTERS WR_STAND1_GOTO_STORED_POS Move motorized stand to position with numerical name matching value written to this register. If you write e.g. ``0x0002`` to this registry there should be a configured position named ``"2"`` for the stand to go to. In order to ensure that stands are moved only when there is a working communication, it is recommended to enable :ref:`WR_API_HEARTBEAT_TIMEOUT ` before writing to this register. .. modbus-register:: HOLDING_REGISTERS WR_STAND2_GOTO_STORED_POS Move stand2 to position with numerical name matching value written to this register See :ref:`WR_STAND1_GOTO_STORED_POS ` for details. .. modbus-register:: HOLDING_REGISTERS WR_STAND3_GOTO_STORED_POS Move stand3 to position with numerical name matching value written to this register See :ref:`WR_STAND1_GOTO_STORED_POS ` for details. ======== See Also ======== More information about Modbus and Modbus TCP can be found at http://www.modbus.org