Resolving SIMOTION SCOUT Error 30001: Illegal Parameter Index

David Krause11 min read
Motion ControlSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Description: SIMOTION SCOUT Alarms 30001

Engineers commissioning a Siemens SIMOTION D445-2 DP/PN controller in SIMOTION SCOUT (versions V4.x through V5.x) frequently encounter the following alarm text in the diagnostic buffer, HMI alarm view, or ret= return of a system function call:

30001  Illegal parameter (parameter index according to standard sequence
        in the system functions: 2, command type: 101f)

The alarm number 30001 belongs to the SIMOTION runtime system function error class. It is a generic alarm that the SIMOTION runtime issues whenever a system function, technology object (TO) command, or — less obviously — a function that is invoked internally by a higher-level library receives an argument that is out of range, of the wrong data type, or uninitialized.

Unlike most technology alarms (e.g., 20101, 20110, 20201), alarm 30001 always carries a command type sub-code. In this case the command type is 0x101F (hex) = 4127 decimal. The parameter index is 2, meaning the second input parameter of the function's standard parameter sequence is the offending argument.

Key field fact: The runtime reports the parameter index using the function's standard sequence (1-based counting of declared input parameters), not the textual order shown in SCOUT's auto-complete or the source-code variable name. This is why the alarm text is confusing to read: the parameter at index 2 of the standard sequence is not necessarily the second argument you typed in the ST source.

Affected Products, Firmware, and Versions

Item Value
Controller SIMOTION D445-2 DP/PN (6AU1 445-2AD00-0AA0, all MLFB variants)
Controller family SIMOTION D4x5-2, D4x5, P350, C240, C240 PN (when same project is migrated)
Engineering SIMOTION SCOUT V4.4, V4.5, V5.1, V5.2, V5.3, V5.4 (incl. SP)
Runtime firmware SIMOTION Kernel V4.4.x through V5.4.x
Triggering function _getAxisErrorNumberState() (command type 0x101F)
Alarm class System function error, alarm 30001

The alarm is not a hardware fault, a PROFIBUS/PROFINET diagnostic, or a technology object configuration error. It is a parameter validation alarm emitted from the SIMOTION runtime's system function dispatcher, so it appears regardless of whether the function is called from a Motion Control chart, an ST unit, an LAD/FBD block, or — critically — a Siemens-supplied library that wraps the function internally.

Decoding the Command Type 0x101F

The command type field is a 16-bit identifier that maps to a specific system function. The standard command type IDs are listed in the SIMOTION System Functions / System Variables reference manual and the SCOUT online help index "System functions → Alphabetical / Command type IDs".

Command type (hex) Command type (dec) Function Signature
0x1010 4112 _enableAxis() axis, logical state
0x1012 4114 _disableAxis() axis
0x101A 4122 _getAxisState() axis
0x101B 4123 _getAxisError() axis
0x101F 4127 _getAxisErrorNumberState() axis, errorNumber, state
0x1020 4128 _resetAxisError() axis, errorNumber

Command type 0x101F / 4127 therefore identifies the _getAxisErrorNumberState() system function. This is an axis-diagnostic function that returns both the most recent active error number on the axis and the associated axis error state (a bitfield describing whether the error is pending, acknowledged, cleared, etc.).

Reference: Siemens Industry Online Support → SIMOTION documentation → "System Functions - Listing" manual. The exact command type IDs are listed in appendix A of the SIMOTION Programming and Operating Manual - System Functions and reproduced in the SCOUT online help under "Command type ID".

Root Cause: Why Index 2 Fails

The standard parameter sequence of _getAxisErrorNumberState() is:

Index Parameter name Direction Data type Allowed values
1 axis IN AXIS_REF / TO reference Any declared TO axis / compound TO
2 errorNumber IN_OUT DINT 0 (query next pending), or a valid axis error number; 0x80000000..0x7FFFFFFF
3 state OUT BYTE / DWORD Returned bitfield

Parameter index 2 is therefore the errorNumber argument. The runtime rejects this argument when:

  1. The errorNumber variable is uninitialized (left over from a previous block, set to 0 with a stray write) and the system is in a state where 0 is not legal in that exact call context.
  2. The variable is a different elementary type (e.g., BOOL, INT, REAL) and cannot be implicitly widened to DINT by the runtime.
  3. The variable is a member of a derived UDT/STRUCT that the SCOUT compiler accepted, but the runtime interprets as an incompatible layout.
  4. The same variable is being passed by reference to two or more concurrent system function calls (a classic race condition in cyclic tasks that share global state) and one task writes garbage into it between read and write.
  5. A Siemens library (e.g., LAcycCom, CamExt, LAxisBasic, or any SIMOTION Easy Baseline block) calls _getAxisErrorNumberState() internally and the calling code passes a non-axis TO handle or an alias to a non-existent axis.

The "I do not call this function" perception reported in the field is correct on the surface but wrong in practice: most axis error-handling blocks in the SIMOTION standard library — and many vendor-supplied function blocks — wrap _getAxisErrorNumberState() internally to scan for pending axis errors. The runtime reports the underlying function, not the high-level wrapper. This is exactly the situation described in the source case.

Step-by-Step Resolution

Step 1 - Confirm the triggering axis

Open the alarm in the SCOUT Diagnostics → Alarm history view. Each 30001 alarm carries an instance identifier in the extended alarm view (right-click → "Properties"). The instance tells you which TO handle was passed as parameter 1.

// In the MCC chart / ST source linked to the alarm, search for the axis name:
myErrorNumber := 0;                // uninitialised - root cause variant 1
ret := _getAxisErrorNumberState(
          axis        := axis_1,   // parameter 1: axis handle
          errorNumber := myErrorNumber,  // parameter 2: errorNumber
          state       := myState);       // parameter 3: state

If you never typed the call, the next step is to find the caller.

Step 2 - Locate the indirect caller

  1. In the project navigator, right-click the project root → Find in project and search for the axis name (e.g., axis_1).
  2. For each hit, open the unit and use the SCOUT References view (Ctrl+Shift+G) to find every block that touches the axis.
  3. Common indirect callers in the SIMOTION standard library: LAxisBasic_S1, LAxisControl_S1, LAxisBasic_DS1, plus the cam/automatic blocks in CamExt.
  4. Open the library unit (right-click → "Open source") and look for any call to _getAxisErrorNumberState, _getAxisError, or the higher-level getAxisErrorNumberState export.

Step 3 - Initialize the errorNumber argument

The most common fix is to ensure the variable passed as errorNumber is explicitly initialised to a legal sentinel value (typically 0) at the start of every scan, and that its data type is exactly DINT (LREAL/REAL/INT are not legal):

VAR
    myErrorNumber : DINT := 0;   // 0 = "query first pending error"
    myState       : DWORD;
    ret           : DINT;
END_VAR

// At the start of the cycle:
myErrorNumber := 0;
ret := _getAxisErrorNumberState(
          axis        := axis_1,
          errorNumber := myErrorNumber,
          state       := myState);
IF ret <> 0 THEN
    // handle / log ret
END_IF;

Step 4 - Remove aliasing across tasks

If myErrorNumber is a UNIT_GLOBAL variable shared by the background task, the IPO task, and a synchronous Motion task, you have a race. Make it UNIT_LOCAL or wrap the call in a semaphore:

VAR GLOBAL    // shared lock
    axisErrSem : BOOL := FALSE;
END_VAR

// In any task that touches the function:
IF NOT axisErrSem THEN
    axisErrSem := TRUE;
    myErrorNumber := 0;
    ret := _getAxisErrorNumberState(axis_1, myErrorNumber, myState);
    axisErrSem := FALSE;
END_IF;

Step 5 - Verify the TO handle is valid

If the indirect caller is passing a TO alias (e.g., axis := g_axleTable[i]), confirm that i is in range and that the alias points to a configured axis. Out-of-range TO references yield exactly this 30001 alarm with the index pointing at errorNumber because the runtime rejects the call before validating errorNumber.

Step 6 - Recompile and download

After the change, perform a full project Compile (Ctrl+B) and Download to target system. Use Download with consistency check to force the runtime to re-validate every TO reference.

Verification

  1. Open Diagnostics → Alarm history and clear it.
  2. Run the axis through a normal motion profile, including at least one simulated error (e.g., temporarily disable a drive via STARTER/SINAMICS commissioning, or use Axis → Force error in the SCOUT commission dialog).
  3. Cycle power on the controller (D445-2) to clear the RAM-resident alarm buffer.
  4. Re-run the same motion profile for at least 10 minutes of continuous operation.
  5. Confirm that no new 30001 alarm with command type 0x101F is logged. Other alarms (drive-side, PROFIsafe, etc.) are acceptable and unrelated.

For a permanent test, add a self-diagnostic ST unit that periodically calls the function and asserts the return value:

IF ret <> 0 AND ret <> 5000 /* "no error pending" */ THEN
    _writeAndSendAlarm(ret, axis_1, "_getAxisErrorNumberState");
END_IF;

Related Alarm Codes and Decoding Rules

Alarm # Meaning Decoding
30001 Illegal parameter in a system function Index 1..N, command type 0x1000..0xFFFF per appendix A of the SIMOTION System Functions manual
30002 System function not executable in current axis state Same command type field; parameter index irrelevant
30003 Command type not supported on this TO Verify TO type matches the function (e.g., _getAxisErrorNumberState requires an axis TO, not a measuring-input TO)
30004 Internal pointer error Reboot the controller; if persistent, re-image the CFast card
30005 Function aborted by higher-priority command Check task priorities and re-synchronise the calling task

The general decoding rule for the "parameter index according to standard sequence in the system functions" string is:

  1. Read the command type (hex → look up the function in Siemens Industry Online Support → SIMOTION → "System functions - Reference").
  2. Open the function's help page in SCOUT (F1 on the function name in the ST editor) and count the input parameters 1..N as listed in the function's declaration block.
  3. The reported index is that exact position. It is not the textual order, the alphabetical order, or the order of OUT parameters.

This convention is consistent with the broader industry concept of standard built-in parameter sequences and sequence parameter ordering: the runtime always walks the parameters in the order declared by the function's prototype, regardless of the call-site syntax. Likewise, the order parameter template used in SIMATIC BATCH applies the same principle — a standard sequence defined in the system, not in the caller's source.

Preventive Measures and Best Practice

  • Always declare errorNumber, ret, and any other IN_OUT argument of an axis-diagnostic system function as a strictly typed local variable (VAR block of the unit) and initialize it at declaration time.
  • Never share IN_OUT arguments to system functions across tasks. Copy the value into a task-local first.
  • Wrap _getAxisErrorNumberState() (and the entire _get*State family) in a thin, well-named project function, e.g., fbGetAxisErr(TO_Axis, DINT, BY REF DINT, DWORD). The wrapper owns the variable and the initialization rule, so the convention is enforced by code review.
  • In the SCOUT Project → Settings → Compile options, enable Strict type checking and Warn on implicit conversions. This converts runtime parameter traps into compile-time errors where possible.
  • Add a cyclic self-test task that exercises the wrapper on a known-good axis once per shift; a successful call proves the project's axis-diagnostic path is healthy.

When the Alarm Persists

If the alarm remains after applying Steps 1–6, escalate the diagnostic as follows:

  1. Export the complete alarm history to XML (Diagnostics → Save as XML) and grep for the same command type 0x101F — a re-occurrence from a different axis confirms a project-wide misuse of the indirect caller.
  2. Rebuild the project from a clean SCOUT Save as → New project using the same hardware catalog. Migration artifacts from older SIMOTION versions (pre-V4.2) can carry stale TO references that only surface as 30001 alarms on D445-2 hardware.
  3. Update the SIMOTION Kernel to the latest available firmware release matching the SCOUT version. Several 30001 root causes were fixed in V4.5 HF9, V5.1 SP2 HF7, and V5.3 SP1.
  4. If you use SIMOTION Easy Baseline or a Siemens-issued FB library, check the library's release notes for known issues with _getAxisErrorNumberState on D445-2.
Safety note: Alarm 30001 with command type 0x101F is not a safety alarm and does not require PROFIsafe acknowledgment. The drive and axis remain operable, but the diagnostic path is broken. Resolve it within the planned maintenance window; do not ignore it on a production machine because the next pending axis error will be invisible to the HMI.

FAQ

What does "parameter index according to standard sequence in the system functions" mean in SIMOTION alarm 30001?

It means the runtime rejected the Nth input parameter (1-based) of a system function, where N is the order declared in the function's prototype — not the order in your source. For command type 0x101F (_getAxisErrorNumberState), index 2 is the errorNumber IN_OUT argument.

How do I look up what command type 0x101F is in SIMOTION SCOUT?

Convert 0x101F to decimal (4127) and search the SCOUT online help index "System functions → Command type ID", or open the SIMOTION System Functions reference manual, appendix A. 0x101F maps to _getAxisErrorNumberState().

I never call _getAxisErrorNumberState() in my project — why is the alarm raised?

Most SIMOTION standard library blocks (LAxisBasic, LAxisControl, LAxisBasic_DS1, CamExt) call it internally. The runtime reports the underlying function, not the wrapper. Use the SCOUT reference search (Ctrl+Shift+G) on the axis name to find the indirect caller.

What data type must the errorNumber argument have for _getAxisErrorNumberState?

It must be a 32-bit signed integer (DINT in SIMOTION ST). Booleans, 16-bit INT, and floating-point types are rejected and trigger the 30001 alarm. Initialize the variable to 0 at the top of each cycle.

Is alarm 30001 a safety-relevant alarm on a D445-2 DP/PN?

No. 30001 is a system function parameter-validation alarm, not a PROFIsafe, drive, or stop-category alarm. The axis remains operable, but axis-error diagnostics are degraded. Resolve it during the next planned maintenance window; do not ignore it on a production machine.

Back to blog