User calibration in the PLC

You can also perform the correction calculation in the PLC instead of in the box. This has the advantage that you can set the measured value resolution as required: if the correction calculation is carried out in the box, the measured value resolution is limited to 1 mg/LSB.

Beckhoff also recommends reading the calibration coefficients from the CoE parameters provided for this purpose when calculating corrections in the PLC. This means that the PLC program does not have to be adapted when the box is replaced.

Sample program for the X-axis

Preparation:

PROGRAM MAIN

VAR
    nAmsNetIdArr AT %I*: T_AmsNetIdArr;
    nSlaveAddress AT %I*: WORD;
    nAxis_Value AT %I*: DINT;
    eState: (IDLE, INIT_READ_OFFSET, READING_OFFSET, INIT_READ_GAIN, READING_GAIN,
             NOMINAL_OPERATION, ERROR);
    fbSdoRead: FB_EcCoESdoRead;
    sAmsNetId: T_AmsNetId;
    nOffset: INT;
    nGainRaw: INT;
    fGain: REAL;
    fAxCalibrated: REAL;
    bExecute: BOOL;
END_VAR
CASE eState OF
    IDLE:
        fbSdoRead(bExecute := FALSE);
        sAmsNetId := F_CreateAmsNetId(nAmsNetIdArr);
        IF bExecute THEN
            eState := INIT_READ_OFFSET;
        END_IF

    INIT_READ_OFFSET:
        fbSdoRead(
            sNetId := sAmsNetId,
            nSlaveAddr := nSlaveAddress,
            nSubIndex := 16#17,
            nIndex := 16#8000,
            pDstBuf := ADR(nOffset),
            cbBufLen := SIZEOF(nOffset),
            bExecute := TRUE
            );
        eState := READING_OFFSET;

    READING_OFFSET:
        fbSdoRead();
        IF NOT fbSdoRead.bBusy THEN
            IF fbSdoRead.bError THEN
                eState := Error;
            ELSE
                fbSdoRead(bExecute := FALSE);
                eState := INIT_READ_GAIN;
            END_IF
        END_IF

    INIT_READ_GAIN:
        fbSdoRead(
            sNetId := sAmsNetId,
            nSlaveAddr := nSlaveAddress,
            nSubIndex := 16#18,
            nIndex := 16#8000,
            pDstBuf := ADR(nGainRaw),
            cbBufLen := SIZEOF(nGainRaw),
            bExecute := TRUE
            );
        eState := READING_GAIN;

    READING_GAIN:
        fbSdoRead();
        IF NOT fbSdoRead.bBusy THEN
            IF fbSdoRead.bError THEN
                eState := ERROR;
            ELSE
                fbSdoRead(bExecute := FALSE);
                fGain := INT_TO_REAL(nGainRaw) / 16384;
                eState := NOMINAL_OPERATION;
            END_IF
        END_IF

    NOMINAL_OPERATION:
        fAxCalibrated := fGain * DINT_TO_REAL(nAxis_Value - nOffset);

    ERROR:
        ;

END_CASE