After commissioning, the C-based software-in-the-loop (SIL) simulator closes the path from sampled feedback through a compensator and hardware-emulated plant, with each stage verified independently on a Linux desktop. Follow the data: the simulation scheduler initiates an update, the compensator calculates the command, the plant model advances its state, and the resulting measurement returns for the next update.
Where does the SIL data path begin?
Begin with the executable and its local runtime dependencies. In a software-only loop, there is no cable, transceiver, or fieldbus to diagnose unless the simulator has been extended with an external interface. Layer one is therefore the host process: confirm that the program starts, remains running, and can read its configuration before analyzing control behavior.
| Path stage | Input | Output | Commissioning check |
|---|---|---|---|
| Scheduler | Simulation time and configured update interval | Control-step invocation | Step count advances without unexpected gaps |
| Compensator | Reference and measured feedback | Command to the plant | Command changes predictably when error changes |
| Plant model | Command and previous plant state | Updated state | State moves in the expected direction |
| Measurement path | Plant state | Feedback for the next step | Feedback corresponds to the updated state |
The supplied project is described as a C-based simulator with an approximate 20 KB footprint. It runs on a Linux desktop and provides a hardware-emulated plant plus a location for user-written compensator algorithms. Treat that footprint as a project description, not a memory budget for every build; compiler options, libraries, symbols, and platform can change the resulting binary.
Check: start the simulator from the documented project workflow and confirm that the process advances simulation state before changing any controller code.
How do I establish the host and build settings?
Keep the first build unchanged. A clean baseline separates host, compiler, and configuration problems from defects introduced by a compensator. Record the compiler, build mode, configuration file, and executable used for the run. If the build system supports diagnostic and optimized modes, compare behavior only after the baseline works.
| Setting | What to record | Failure it isolates |
|---|---|---|
| Host | Linux distribution and architecture reported by the host | Runtime or toolchain mismatch |
| Build | Compiler, flags, and selected target | Floating-point, optimization, or undefined-behavior differences |
| Configuration | Exact file and selected plant/controller options | Running valid code with unintended settings |
| Executable | Resolved path and build timestamp | Launching a stale binary |
- Obtain the project and follow its supplied README setup sequence on the Linux desktop.
- Build the unmodified baseline using the documented target.
- Resolve all compiler errors before editing the compensator. Treat warnings involving conversions, uninitialized values, array bounds, or function declarations as control-path defects.
- Launch the exact executable produced by that build and retain its startup output with the test record.
Check: rebuild from the same inputs and confirm that the same executable starts with the same configuration.
How do I prove the timing path before tuning?
A discrete compensator is defined by both its equations and its update interval. The scheduler must invoke the controller once per intended control step, and the plant integration must use the time increment selected by the simulator. A controller can compile and still produce misleading results if its coefficients were calculated for a different update interval.
| Timing item | Read it from | Check |
|---|---|---|
| Controller update interval | Project configuration or scheduler definition | Matches the interval assumed when calculating compensator coefficients |
| Plant integration step | Plant-model configuration | Advances monotonically and uses the intended units |
| Execution order | Main simulation loop | Measurement, control calculation, and state update occur in a documented order |
| Stop condition | Run configuration | Produces enough samples to expose transient and settled behavior |
Do not infer real-time execution merely because simulation time advances. A SIL model may execute faster or slower than wall-clock time while preserving its mathematical sample sequence. Measure wall-clock deadlines only if the commissioning objective includes real-time scheduling.
- Trace one iteration through the scheduler, compensator call, plant update, and feedback assignment.
- Log the simulation timestamp and step counter at each controller invocation.
- Calculate successive timestamp differences and compare them with the configured controller interval.
- Stop if the interval changes unexpectedly, a step repeats, or time moves backward.
Check: the step counter, simulation time, and controller invocation count maintain a one-to-one relationship for the selected run.
How do I connect a compensator without breaking the interface?
The compensator boundary is the firmware bridge. Preserve its data types, units, sign convention, state lifetime, and call rate. The minimum useful observation set is reference, feedback, error, unconstrained command, applied command, and plant output. These signals reveal whether a failure begins in the controller or after its output reaches the plant.
| Signal | Required interpretation | Diagnostic use |
|---|---|---|
| Reference | Commanded operating quantity and units | Confirms the stimulus reached the controller |
| Feedback | Measured plant quantity in compatible units | Exposes scaling or stale-data faults |
| Error | Declared reference-minus-feedback convention | Exposes reversed control action |
| Command | Controller output before and after any limit | Separates compensator behavior from actuator limiting |
| State | Persistent controller memory | Exposes unintended reset or carryover between runs |
- Locate the existing compensator entry point and retain its function signature.
- Implement the smallest deterministic control law needed to prove polarity and scaling.
- Initialize every persistent state explicitly at the start of a run.
- Apply output limits only where the simulator interface defines them; record both the calculated and applied values.
- Compile with warnings enabled and repeat the baseline stimulus.
Check: a known increase in control error produces the intended command-direction change, and repeated runs from the same initial state produce the same first command.
Where does a bad response first diverge?
Follow the packet-equivalent sample rather than tuning around the symptom. Find the first stage whose input is correct and output is wrong. A stationary plant with a changing command points downstream of the compensator. A command driven hard in the wrong direction points to polarity or scaling. A plausible command with erratic state changes points to the plant update, numeric handling, or timing path.
| Observed symptom | First checks | Corrective action |
|---|---|---|
| No plant response | Applied command, plant call count, state assignment | Reconnect the command path or correct the plant update sequence |
| Response moves away from reference | Error sign, actuator sign, sensor sign | Correct one documented polarity boundary |
| Command remains limited | Reference magnitude, unit scaling, controller state | Correct scaling and reset accumulated state before retesting |
| Runs disagree | Initialization, stale state, uninitialized memory | Reset all controller and plant states at run start |
| Oscillation changes with build settings | Warnings, numeric types, bounds, undefined behavior | Correct the C implementation before controller tuning |
Change one boundary at a time. Tuning gains while the polarity, units, or sample interval is wrong hides the defect and creates coefficients that work only with the mistake.
Check: identify the earliest mismatched signal in the sequence reference → feedback → error → command → plant state → next feedback and correct that boundary before continuing.
How do I verify the complete closed loop?
End-to-end verification must cover initialization, transient response, limits, steady behavior, and repeatability. Use the same plant configuration and initial conditions for every comparison. Save the build identity and configuration with the recorded signals.
- Start from a declared initial plant state and reset the compensator state.
- Run a fixed reference profile that exercises both command directions when the plant permits them.
- Record simulation time, reference, feedback, error, calculated command, applied command, and plant state.
- Confirm that every controller output becomes the intended plant input and that the resulting feedback is used by the next controller step.
- Repeat the run without rebuilding. Compare step counts and signal sequences to detect hidden state or nondeterministic behavior.
- Introduce one bounded reference change and confirm correct polarity, finite numeric values, expected limiting, and movement toward the reference.
Check: the recorded sequence closes without a missing hop, every value remains finite, and an identical run from identical initial conditions produces the same trace.
FAQ
How do I know the SIL simulator is actually closed loop?
Trace one sample from reference and feedback through the compensator, into the plant update, and back as the next feedback value. The loop is closed only when that returned measurement affects the following command.
How do I check the simulator update interval?
Read the configured scheduler interval, then log successive simulation timestamps at the compensator entry point. Their differences must match the interval used to calculate the discrete compensator coefficients.
How do I diagnose a plant output moving the wrong way?
Compare the signs of reference, feedback, error, command, and state change in that order. Correct the first polarity boundary that contradicts the documented convention; do not reverse multiple signals.
How do I add my own compensator algorithm?
Retain the existing C entry-point interface, use the configured sample interval and declared units, initialize persistent state, and log both calculated and applied commands. First prove polarity and repeatability with a small deterministic test.
How do I perform the final SIL verification?
Reset controller and plant states, run a fixed reference profile, and record every hop from reference through returned feedback. Repeat from identical initial conditions and verify matching step counts, finite values, the same signal trace, and movement toward the reference.