Use this page when you need to choose or understand a homing sequence.
For new configurations:
encoder.homingLegacy epicsEnvSet(...) examples are still shown in some sections because many
older IOCs still use them, but YAML is preferred for new setups.
The most common homing cases are:
03 or 411 or 1211 or 1226CSV, CSP, or a special homing modeThis page describes the homing sequences supported by ecmc. The following sequences are available:
ECMC_SEQ_HOME_NOT_VALID = 0,
ECMC_SEQ_HOME_LOW_LIM = 1,
ECMC_SEQ_HOME_HIGH_LIM = 2,
ECMC_SEQ_HOME_LOW_LIM_HOME = 3,
ECMC_SEQ_HOME_HIGH_LIM_HOME = 4,
ECMC_SEQ_HOME_LOW_LIM_HOME_HOME = 5,
ECMC_SEQ_HOME_HIGH_LIM_HOME_HOME = 6,
ECMC_SEQ_HOME_BWD_HOME = 7,
ECMC_SEQ_HOME_FWD_HOME = 8,
ECMC_SEQ_HOME_BWD_HOME_HOME = 9,
ECMC_SEQ_HOME_FWD_HOME_HOME = 10,
ECMC_SEQ_HOME_LOW_LIM_INDEX = 11,
ECMC_SEQ_HOME_HIGH_LIM_INDEX = 12,
ECMC_SEQ_HOME_SET_POS = 15,
ECMC_SEQ_HOME_LOW_LIM_SINGLE_TURN_ABS = 21,
ECMC_SEQ_HOME_HIGH_LIM_SINGLE_TURN_ABS = 22,
ECMC_SEQ_HOME_SET_POS_2 = 25,
ECMC_SEQ_HOME_TRIGG_EXTERN = 26,
Additionally, for homing of absolute encoder with ONE overflow in the range, please check here.
ECMC_HOME_POS is the position written when homing is finalized.
Low limit means backward limit switch. High limit means forward limit switch.
Home switch edge means a change of the home switch state, with the effective edge depending on switch polarity.
After a homing sequence has finalized the reference position, ecmc can optionally execute one absolute positioning move. This is useful when the reference point is at a switch edge or at an index mark, but the desired final parked position is somewhere else.
If post move is enabled:
ECMC_HOME_POS).If the current position already equals the configured post-move target, then no extra move is started.
Command interface:
ecmcConfigOrDie "Cfg.SetAxisHomePostMoveEnable(${ECMC_AXIS_NO}, 1)"
ecmcConfigOrDie "Cfg.SetAxisHomePostMoveTargetPosition(${ECMC_AXIS_NO}, 10.0)"
The same functionality is available in YAML through the homing configuration:
homing:
type: 3
position: 0
postMoveEnable: 1
postMovePosition: 10.0
The post-move settings can also be stored in the encoder homing configuration and then reused when the homing sequence is read from encoder settings.
Not a valid homing sequence. This value can be used when no active homing sequence is required, for example with a trusted absolute encoder setup.
ECMC_HOME_POS.ECMC_HOME_POS.ECMC_HOME_POS.ECMC_HOME_POS.ECMC_HOME_POS.ECMC_HOME_POS.ECMC_HOME_POS.The effective edge depends on the configured home-switch polarity.
ECMC_HOME_POS.The effective edge depends on the configured home-switch polarity.
ECMC_HOME_POS.The effective active/inactive edges depend on the configured home-switch polarity.
ECMC_HOME_POS.The effective active/inactive edges depend on the configured home-switch polarity.
ECMC_HOME_POS.This sequence requires encoder latch support. ECMC_HOME_LATCH_COUNT_OFFSET selects which index/latch event to use.
Two common hardware patterns are used for this:
encoder.control and encoder.status are the encoder latch control/status PDOs, and encoder.latch.position is the latched encoder position PDO.encoder.control and encoder.status map to touch-probe control/status PDOs, and encoder.latch.position maps to the touch-probe latched position PDO.Legacy epicsEnvSet(...) configuration still works:
epicsEnvSet("ECMC_EC_ENC_LATCHPOS", "ec0.s3.encoderLatchPostion01") # Latch position entry
epicsEnvSet("ECMC_EC_ENC_LATCH_CONTROL", "ec0.s3.encoderControl01.0") # Latch arm bit
epicsEnvSet("ECMC_EC_ENC_LATCH_STATUS", "ec0.s3.encoderStatus01.0") # Latch occurred bit
epicsEnvSet("ECMC_HOME_LATCH_COUNT_OFFSET","2") # 1 = first latch, 2 = second latch, ...
For new configs, prefer the YAML-based encoder configuration used in the EL7047 + EL5102 best-practice example:
YAML-based EL51xx example from the EL7047 + EL5102 best-practice config:
encoder:
desc: Incremental RS422
unit: mm
numerator: 1
denominator: 4096
type: 0
bits: 32
absBits: 0
position: ec0.s$(ENC_SID).positionActual${ENC_CH=01}
status: ec0.s$(ENC_SID).encoderStatus${ENC_CH=01}
control: ec0.s$(ENC_SID).encoderControl${ENC_CH=01}
primary: True
latch:
position: ec0.s$(ENC_SID).encoderLatchPostion$(ENC_CH=01)
control: 0
status: 0
homing:
type: 11
position: 0
velocity:
to: 2
from: 1
acceleration: 1
deceleration: 1
latchCount: 1
Latch bit mapping:
0x7000:01, enable latch on index0x6000:01, latch occurredECMC_HOME_POS.This sequence requires encoder latch support. ECMC_HOME_LATCH_COUNT_OFFSET selects which index/latch event to use.
The same EL51xx versus EL7062 distinction applies here as for sequence 11:
Legacy epicsEnvSet(...) configuration still works:
epicsEnvSet("ECMC_EC_ENC_LATCHPOS", "ec0.s3.encoderLatchPostion01") # Latch position entry
epicsEnvSet("ECMC_EC_ENC_LATCH_CONTROL", "ec0.s3.encoderControl01.0") # Latch arm bit
epicsEnvSet("ECMC_EC_ENC_LATCH_STATUS", "ec0.s3.encoderStatus01.0") # Latch occurred bit
epicsEnvSet("ECMC_HOME_LATCH_COUNT_OFFSET","2") # 1 = first latch, 2 = second latch, ...
For new configs, prefer the YAML-based encoder configuration used in the EL7047 + EL5102 best-practice example:
YAML-based EL51xx example from the EL7047 + EL5102 best-practice config:
encoder:
desc: Incremental RS422
unit: mm
numerator: 1
denominator: 4096
type: 0
bits: 32
absBits: 0
position: ec0.s$(ENC_SID).positionActual${ENC_CH=01}
status: ec0.s$(ENC_SID).encoderStatus${ENC_CH=01}
control: ec0.s$(ENC_SID).encoderControl${ENC_CH=01}
primary: True
latch:
position: ec0.s$(ENC_SID).encoderLatchPostion$(ENC_CH=01)
control: 0
status: 0
homing:
type: 12
position: 0
velocity:
to: 2
from: 1
acceleration: 1
deceleration: 1
latchCount: 1
Latch bit mapping:
0x7000:01, enable latch on index0x6000:01, latch occurredFor EL7062, index homing is configured through the touch probe objects, not through the EL51xx-style latch bits.
The basic setup is:
11 or 12.In startup.cmd, the best-practice example configures the drive like this:
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=3,HW_DESC=EL7062_CSP"
${SCRIPTEXEC} ${ecmccfg_DIR}applyComponent.cmd "COMP=Encoder-Generic-INC, CH_ID=1, MACROS='ST_ENC_RES=4000,TP1_POS_SRC=SEC,TP1_TRG=INDEX'"
The matching encoder YAML uses the EL7062 touch-probe PDOs:
encoder:
position: ec0.s$(ENC_SID).positionActual${ENC_CH=01}_2
status: ec0.s$(ENC_SID).touchProbeStatus${ENC_CH=01}
control: ec0.s$(ENC_SID).touchProbeControl${ENC_CH=01}
primary: True
latch:
position: ec0.s$(ENC_SID).touchProbePositionPos$(ENC_CH=01)_1
control: 0
status: 1
armCmd: 21
armBits: 5
homing:
type: 11
position: 0
latchCount: 1
Meaning of the EL7062-specific latch settings:
encoder.control: touch-probe control word.encoder.status: touch-probe status word.encoder.latch.position: latched touch-probe position.encoder.latch.control: start bit in the touch-probe control word where the arm command is written.encoder.latch.armCmd: value written to arm the touch probe. 21 means 0b10101, which enables touch probe 1, selects trigger mode B1, and enables latching on positive edge.encoder.latch.armBits: number of bits written from armCmd. For the EL7062 touch-probe example this is 5.Use homing sequence 11 for low-limit plus index homing and 12 for high-limit plus index homing.
See also:
Sequence 15 is reserved for save/restore functionality.
Use ECMC_SEQ_HOME_SET_POS_2 instead if you need the same behavior from normal motion interfaces.
Sequence 15 can still be triggered manually, for example:
# Turn off amplifier
caput IOC_TEST:Axis1.CNEN 0
# Homing using seq 15
caput IOC_TEST:Axis1.FOFF 1
caput IOC_TEST:Axis1.SET 1
caput IOC_TEST:Axis1.VAL <new position value>
caput IOC_TEST:Axis1.FOFF 0
caput IOC_TEST:Axis1.SET 0
Intended for single-turn absolute encoders such as resolvers.
ECMC_HOME_POS, including the turn offset defined by ECMC_HOME_LATCH_COUNT_OFFSET.Only the multi-turn part is adjusted. The single-turn absolute bits are preserved.
Important parameters:
epicsEnvSet("ECMC_ENC_BITS", "25") # Total encoder raw bit count
epicsEnvSet("ECMC_ENC_ABS_BITS", "12") # Absolute single-turn bit count
epicsEnvSet("ECMC_HOME_LATCH_COUNT_OFFSET","2") # Turn offset for homing
ECMC_HOME_POS, including the turn offset defined by ECMC_HOME_LATCH_COUNT_OFFSET.Only the multi-turn part is adjusted. The single-turn absolute bits are preserved.
Important parameters:
epicsEnvSet("ECMC_ENC_BITS", "25") # Total encoder raw bit count
epicsEnvSet("ECMC_ENC_ABS_BITS", "12") # Absolute single-turn bit count
epicsEnvSet("ECMC_HOME_LATCH_COUNT_OFFSET","2") # Turn offset for homing
Sequence 25 is the same as sequence 15, but it is not blocked by the motor record. It writes a new encoder position without any motion.
Trigger a homing sequence in the drive itself.
ECMC_HOME_POS.For drives such as SmarAct MCS2, this sequence is normally used together with
automatic drive-mode switching. In YAML-based axis configuration this is done
with autoMode, where modeSet and modeAct point to the drive mode process
data, and modeCmdHome/modeCmdMotion define the drive-specific mode values.
Example:
axis:
mode: CSP
autoMode:
modeSet: ec0.s${MCS2_SLAVE_NUM}.mode0${MCS2_CHID}
modeAct: ec0.s${MCS2_SLAVE_NUM}.modeActual0${MCS2_CHID}
modeCmdMotion: 8
modeCmdHome: 6
encoder:
homing:
type: 26
trigg: ec0.s${MCS2_SLAVE_NUM}.driveCmdExe0${MCS2_CHID}.0
ready: ec0.s${MCS2_SLAVE_NUM}.driveStatus0${MCS2_CHID}.10
refAtHome: 1
Notes:
trigg shall point to the bit that starts homing in the drive.ready shall point to the homing-done or homing-ready status bit from the drive.8 and homing uses 6.Example:
For several sequences it is useful to invert the effective home-switch polarity. Use:
"Cfg.SetAxisMonHomeSwitchPolarity(int axisIndex, int polarity)";
# polarity == 0: NC (default)
# polarity == 1: NO
Always adjust the absolute encoder so that no overflow occurs within the usable motion range if possible.
If that is not possible, homing can be handled in PLC code. No dedicated ecmc homing sequence exists for this case.
Example:
/*
PLC code to home an axis with an absolute encoder which has ONE overflow in the range
If actual encoder value is higher than ${THRESHOLD} it will be referenced to current actual position - ${RANGE}.
NOTE: Make sure the default axis encoder scaling offset is correct for the lower part of the raw values.
macros:
AX_ID : ID of axis
ENC_ID : ID of encoder (starts from 1)
THRESHOLD : Threshold to identify overflow (in EGU)
RANGE : Total encoder range, both single-turn and multi-turn (in EGU)
DBG : Print debug messages, or leave empty (DBG='')
*/
if(${SELF}.firstscan) {
var plc := ${SELF_ID};
${DBG=#}println('PLC ', plc, ' Initiating homing seq for abs. encoder with overflow');
};
if(mc_get_enc_ready(${AX_ID=1}, ${ENC_ID=1}) and not(static.encoderHomed)) {
${DBG=#}println('Checking if homing encoder is needed');
if(mc_get_act_pos(${AX_ID=1}, ${ENC_ID=1}) > ${THRESHOLD=0}) {
${DBG=#}println('Homing encoder to: ', mc_get_act_pos(${AX_ID=1}, ${ENC_ID=1}) - ${RANGE=0});
mc_set_act_pos(${AX_ID=1}, ${ENC_ID=1}, mc_get_act_pos(${AX_ID=1}, ${ENC_ID=1}) - ${RANGE=0});
} else {
${DBG=#}println('Homing not needed!');
};
static.encoderHomed${AX_ID=1}_${ENC_ID=1} := 1;
}
/* Do not allow power on axis if encoder is not homed */
if(not(static.encoderHomed${AX_ID=1}_${ENC_ID=1})) {
${DBG=#}println('Waiting for encoder ready and homing...');
mc_power(${AX_ID=1}, 0);
};
The code is available in: home_abs_enc_overflow.plc_inc
It is installed with ecmccfg and can be loaded from ecmccfg_DIR:
${SCRIPTEXEC} ${ecmccfg_DIR}loadPLCFile.cmd, "FILE=${ecmccfg_DIR}home_abs_enc_overflow.plc_inc, SAMPLE_RATE_MS=1000, PLC_MACROS='DBG='"
The file can also be included from another PLC file.
Example main.plc:
# macros here or in PLC_MACROS in call to loadPLCFile.cmd:
substitute(AX_ID=1,ENC_ID=1,RANGE=360,THRESHOLD=240)
include "home_abs_enc_overflow.plc_inc"
Load the file with an include directory:
${SCRIPTEXEC} ${ecmccfg_DIR}loadPLCFile.cmd, "FILE=./cfg/main.plc, INC=${ecmccfg_DIR}, SAMPLE_RATE_MS=1000, PLC_MACROS='DBG='"