EtherCAT.AL (yaethercat v0.1.0)

Copy Markdown View Source

The AL state machine of a SubDevice (ETG.1000.6, 6.4.1), through its AL control and AL status registers (5.3).

StateCodeThe SubDevice
:init1is set up by the MainDevice, its mailbox sync managers among the rest
:pre_operational2has its mailbox working, and no process data
:bootstrap3takes firmware over FoE, and nothing else
:safe_operational4gives its inputs, and holds its outputs in their safe state
:operational8gives its inputs and drives its outputs

From Init there is a way to Pre-Operational and Bootstrap only, and from Pre-Operational none straight to Operational; any state can go down to one below it. A change that fails leaves the SubDevice with its error flag set and an AL status code that says why, until the MainDevice acknowledges it.

Summary

Types

A state of the AL state machine.

What a SubDevice's AL status registers say.

Functions

The code of a state in AL control and AL status.

AL status from its six bytes, from 0x0130: the state, the error flag, whether R6 holds a device identification, and the AL status code, which counts only with the error flag set.

What an AL status code means, in a few words.

Reads a SubDevice's AL status, by station address.

Asks a SubDevice for a state, by station address, and waits until it is there: :ok, or {:error, {:al_status, state, code}} with the state it is in and the AL status code it gave for refusing, or {:error, :timeout}. A refusal is acknowledged, as is an error from before, so that the SubDevice can be asked again.

The state of a code, or the code itself for one the spec doesn't define.

Every state, from Init up.

Types

state()

@type state() ::
  :init | :pre_operational | :bootstrap | :safe_operational | :operational

A state of the AL state machine.

status()

@type status() :: %{
  state: state() | byte(),
  error: boolean(),
  id_loaded: boolean(),
  code: 0..65535
}

What a SubDevice's AL status registers say.

Functions

code(state)

@spec code(state()) :: byte()

The code of a state in AL control and AL status.

decode_status(arg)

@spec decode_status(binary()) :: status()

AL status from its six bytes, from 0x0130: the state, the error flag, whether R6 holds a device identification, and the AL status code, which counts only with the error flag set.

iex> EtherCAT.AL.decode_status(<<0x14, 0, 0, 0, 0x1E, 0>>)
%{state: :safe_operational, error: true, id_loaded: false, code: 0x001E}

describe(code)

@spec describe(0..65535) :: String.t()

What an AL status code means, in a few words.

iex> EtherCAT.AL.describe(0x001E)
"The inputs are set up wrong"
iex> EtherCAT.AL.describe(0x8001)
"Vendor specific (0x8001)"

read_status(main, station)

@spec read_status(EtherCAT.MainDevice.t(), 0..65535) ::
  {:ok, status()} | {:error, term()}

Reads a SubDevice's AL status, by station address.

request(main, station, state, opts \\ [])

@spec request(EtherCAT.MainDevice.t(), 0..65535, state(), keyword()) ::
  :ok | {:error, {:al_status, state() | byte(), 0..65535} | :timeout | term()}

Asks a SubDevice for a state, by station address, and waits until it is there: :ok, or {:error, {:al_status, state, code}} with the state it is in and the AL status code it gave for refusing, or {:error, :timeout}. A refusal is acknowledged, as is an error from before, so that the SubDevice can be asked again.

Options:

  • timeout: (5 seconds), how long it may take

state(code)

@spec state(byte()) :: state() | byte()

The state of a code, or the code itself for one the spec doesn't define.

states()

@spec states() :: [state()]

Every state, from Init up.