EtherCAT.Slave (ethercat v0.4.2)

Copy Markdown View Source

EtherCAT State Machine lifecycle for one physical slave device.

EtherCAT.Slave is the public boundary for one named slave. Each slave owns its AL-state transitions, mailbox setup, process-data registration, health polling, reconnect handling, and signal delivery.

One slave process is started per configured name and registered under {:slave, name}. The public API is typically driven by the master, but direct slave-local calls are available here for introspection, output staging, SDO traffic, and controlled retries.

State transitions

stateDiagram-v2
    state "INIT" as init
    state "BOOTSTRAP" as bootstrap
    state "PREOP" as preop
    state "SAFEOP" as safeop
    state "OP" as op
    state "DOWN" as down
    [*] --> init
    init --> preop: auto-advance succeeds
    init --> init: auto-advance retries
    init --> bootstrap: bootstrap is requested
    init --> safeop: SAFEOP request path succeeds
    init --> op: OP request path succeeds
    bootstrap --> init: INIT is requested
    preop --> safeop: SAFEOP is requested
    preop --> op: OP is requested
    preop --> init: INIT is requested or AL health regresses to INIT
    preop --> bootstrap: AL health regresses to BOOTSTRAP
    preop --> down: health poll sees bus loss or zero WKC
    safeop --> op: OP is requested
    safeop --> preop: PREOP is requested or AL health regresses to PREOP
    safeop --> init: INIT is requested or AL health regresses to INIT
    safeop --> bootstrap: AL health regresses to BOOTSTRAP
    safeop --> down: health poll sees bus loss or zero WKC
    op --> safeop: SAFEOP is requested or AL health retreats
    op --> preop: PREOP is requested
    op --> init: INIT is requested
    op --> down: health poll sees bus loss or zero WKC
    down --> preop: link/position probe succeeds and PREOP rebuild succeeds
    down --> init: reconnect rebuild retries from INIT

Summary

Functions

Apply runtime configuration updates for one slave.

Download one CoE SDO value to the slave mailbox.

Return the current AL error code, if the slave has reported one.

Return the cached identity information for the slave, if available.

Return a detailed runtime snapshot for the slave.

Read the latest decoded value for one registered input signal.

Request a target AL state for the named slave.

Retry a retained PREOP configuration failure for one slave.

Return the current slave AL state.

Subscribe pid to a registered process-data signal or configured latch name.

Upload one CoE SDO value from the slave mailbox.

Stage an output value into the slave's process image for the next domain cycle.

Types

server()

@type server() :: :gen_statem.server_ref()

t()

@type t() :: %EtherCAT.Slave{
  active_latches: list() | nil,
  bus: EtherCAT.Bus.server() | nil,
  config: EtherCAT.Slave.Config.t() | nil,
  configuration_error: term() | nil,
  dc_cycle_ns: non_neg_integer() | nil,
  driver: module() | nil,
  error_code: non_neg_integer() | nil,
  esc_info: map() | nil,
  health_poll_ms: pos_integer() | nil,
  identity: map() | nil,
  latch_names: map(),
  latch_poll_ms: pos_integer() | nil,
  mailbox_config: map() | nil,
  mailbox_counter: non_neg_integer() | nil,
  name: atom() | nil,
  output_domain_ids_by_sm: map() | nil,
  output_sm_images: map() | nil,
  position: non_neg_integer() | nil,
  process_data_request: :none | {:all, atom()} | [{atom(), atom()}] | nil,
  signal_registrations: map() | nil,
  signal_registrations_by_sm: map() | nil,
  sii_pdo_configs: list() | nil,
  sii_sm_configs: list() | nil,
  startup_retry_count: non_neg_integer(),
  startup_retry_phase: atom() | nil,
  station: non_neg_integer() | nil,
  subscriber_refs: %{optional(pid()) => reference()},
  subscriptions: map() | nil,
  sync_config: EtherCAT.Slave.Sync.Config.t() | nil
}

Functions

configure(slave_name, opts)

@spec configure(
  atom(),
  keyword()
) :: :ok | {:error, term()}

Apply runtime configuration updates for one slave.

download_sdo(slave_name, index, subindex, data)

@spec download_sdo(atom(), non_neg_integer(), non_neg_integer(), binary()) ::
  :ok | {:error, term()}

Download one CoE SDO value to the slave mailbox.

error(slave_name)

@spec error(atom()) ::
  non_neg_integer()
  | nil
  | {:error, :not_found | :timeout | {:server_exit, term()}}

Return the current AL error code, if the slave has reported one.

identity(slave_name)

@spec identity(atom()) ::
  map() | nil | {:error, :not_found | :timeout | {:server_exit, term()}}

Return the cached identity information for the slave, if available.

info(slave_name)

@spec info(atom()) ::
  {:ok, map()} | {:error, :not_found | :timeout | {:server_exit, term()}}

Return a detailed runtime snapshot for the slave.

read_input(slave_name, signal_name)

@spec read_input(atom(), atom()) :: {:ok, {term(), integer()}} | {:error, term()}

Read the latest decoded value for one registered input signal.

Returns {:error, :not_ready} before the first valid domain refresh and {:error, {:stale, details}} once the cached sample is older than the domain freshness window.

request(slave_name, target)

@spec request(atom(), atom()) :: :ok | {:error, term()}

Request a target AL state for the named slave.

The runtime may walk the required intermediate path internally before the request completes.

retry_preop_configuration(slave_name)

@spec retry_preop_configuration(atom()) :: :ok | {:error, term()}

Retry a retained PREOP configuration failure for one slave.

state(slave_name)

@spec state(atom()) ::
  atom() | {:error, :not_found | :timeout | {:server_exit, term()}}

Return the current slave AL state.

subscribe(slave_name, signal_name, pid)

@spec subscribe(atom(), atom(), pid()) ::
  :ok
  | {:error,
     {:not_registered, atom()} | :not_found | :timeout | {:server_exit, term()}}

Subscribe pid to a registered process-data signal or configured latch name.

Signal updates arrive as {:ethercat, :signal, slave_name, signal_name, value}. Latch edges arrive as {:ethercat, :latch, slave_name, latch_name, timestamp_ns}.

upload_sdo(slave_name, index, subindex)

@spec upload_sdo(atom(), non_neg_integer(), non_neg_integer()) ::
  {:ok, binary()} | {:error, term()}

Upload one CoE SDO value from the slave mailbox.

write_output(slave_name, signal_name, value)

@spec write_output(atom(), atom(), term()) :: :ok | {:error, term()}

Stage an output value into the slave's process image for the next domain cycle.