Skip to main content
emobility.academy
M.TechCode generation & HILAdvanced About 9 weeksMATLAB & Simulink

Processor-in-the-Loop Verification of a Motor Controller on STM32

Design a speed and current controller for a brushed DC motor in Simulink, then run the generated controller code on the STM32F103 of the DIYguru EV Embedded Development Kit in processor-in-the-loop (PIL) mode, comparing it numerically with the model and measuring execution time on the target.

Tools: Embedded Coder Ā· STM32 support package

Processor-in-the-Loop Verification of a Motor Controller on STM32: STM32 board, LCD and laptop running firmware on a DIYguru lab desk
Representative photo from DIYguru's EV lab, not of this specific project.

The problem

Simulation shows that a controller works in floating-point on a PC; it does not show that the generated code behaves the same on a 72 MHz microcontroller without an FPU, with its compiler, word length and timing. Processor-in-the-loop runs the generated code on the real processor against a simulated plant, revealing numerical differences and timing problems before any motor is connected.

Objectives

  • Model a brushed DC motor and design cascaded current and speed PI controllers.
  • Generate controller code with Embedded Coder for the STM32F103.
  • Run PIL simulations over UART and compare outputs with model-in-the-loop.
  • Measure execution time on the target and check it against the control period.
  • Compare floating-point and fixed-point implementations on the target.

What you need

Tools and toolboxes

  • Simulink — Motor plant, controller design and the PIL test harness.
  • Embedded Coder — Code generation, PIL simulation and code execution profiling.
  • Embedded Coder Support Package for STMicroelectronics STM32 Processors — STM32 target configuration and PIL over serial; check the installed version supports the STM32F1 family, and otherwise set up a custom PIL target with a serial connectivity configuration.
  • Control System Toolbox — Plant transfer functions, PI tuning with pidtune and loop analysis; manual pole placement in base MATLAB is an alternative.
  • Fixed-Point Designer (optional) — Fixed-point version of the controller for comparison on the no-FPU target.

From the EV Embedded Development Kit

  • STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
  • Serial UART interface
  • Motor driver for PWM motor-control experiments
  • Analog potentiometer input

Software

  • MATLAB R2023b or later
  • Simulink
  • STM32CubeMX and STM32CubeIDE toolchain
  • USB-to-UART link to the kit

Extra parts and data

  • A small brushed DC gear motor with a quadrature encoder, within the motor driver's rating — Only for the optional final step of running the controller on a real motor; PIL itself uses a simulated motor.

Key concepts

Processor-in-the-loop
The controller's generated code runs on the target processor while the plant runs in Simulink; inputs and outputs are exchanged each step over a serial link. It checks numerics and timing, not real-time behaviour.
Cascaded control
An inner current loop controls torque quickly and an outer speed loop sets the current reference, so each loop can be tuned for its own bandwidth.
Execution profiling
Embedded Coder can measure how many cycles each generated function takes on the target, which shows whether the code fits in the control period.
Numerical equivalence
Comparing PIL and MIL outputs; small differences come from compiler and floating-point differences, larger ones show bugs or data-type problems.

Step-by-step guide

  1. 1

    Model the motor

    Model the brushed DC motor with LĀ·di/dt = V āˆ’ RĀ·i āˆ’ Ke·ω and JĀ·dω/dt = KtĀ·i āˆ’ B·ω āˆ’ T_load, using example values for a small 12 V gear motor (R = 2 Ī©, L = 1 mH, Kt = Ke = 0.02 NĀ·m/A, J = 2Ɨ10⁻⁶ kgĀ·m²) or values identified from your motor. Model the motor driver as an average voltage gain from duty to volts with saturation.

    Checkpoint: Open-loop step response with time constants that match hand calculations for L/R and the mechanical time constant.

  2. 2

    Design the controllers

    Design the current PI for a bandwidth of a few hundred hertz at a 10 kHz control rate if your timing allows, or a lower bandwidth at a slower rate, and the speed PI about ten times slower. Use pidtune on the plant transfer functions or place zeros to cancel the electrical pole. Add anti-windup by clamping integrator states when the output saturates. Discretise the controllers at their sample times.

    Checkpoint: Bode or step plots showing phase margins above about 45 degrees for both loops.

  3. 3

    Build and verify MIL

    Put the controllers in an atomic subsystem called MotorCtrl with discrete sample times, and close the loop around the plant. Run speed steps, load torque steps and a saturation case. Log speed, current and duty in the Simulation Data Inspector. This model-in-the-loop run is the reference for PIL. Save these MIL results as the reference dataset, because every PIL run and the later fixed-point version will be compared against them.

    Checkpoint: Speed step settles without large overshoot and recovers after a load step, with the integrator not winding up in saturation.

  4. 4

    Set up the target

    Set the model's hardware board to the STM32 target, configure the clock at 72 MHz and choose a serial PIL connection on the USART connected to the USB-to-UART link. Enable code execution profiling in the configuration parameters. Confirm the toolchain builds a simple model for the target before trying PIL. Set the serial baud rate as high as the link reliably supports, since PIL speed depends on it, and note the exact board and toolchain versions used.

    Checkpoint: A trivial test model builds and downloads to the kit.

  5. 5

    Run PIL

    Set MotorCtrl to Processor-in-the-loop (PIL) simulation mode, through a Model block or a PIL block. Run the same scenarios as MIL. Simulink builds the code, downloads it, and exchanges data over UART each step. PIL runs slower than real time because of the serial link, which is expected. If the connection fails, check the COM port, baud rate and that no other program is using the serial port, then rerun a simpler model before returning to the controller.

    Checkpoint: PIL simulation runs to completion for all scenarios with logged outputs.

  6. 6

    Compare MIL and PIL

    Use the Simulation Data Inspector's Compare feature to overlay MIL and PIL signals with a tolerance. With single-precision float on both sides, differences should be tiny. If you used double in the model, note that double on a Cortex-M3 is also emulated and slow; consider single. Investigate any difference larger than the tolerance. Report the maximum absolute difference for speed, current and duty for each scenario, together with the tolerance used and the reason it was chosen.

    Checkpoint: MIL and PIL outputs agree within the chosen tolerance for every scenario.

  7. 7

    Profile execution time

    Open the code execution profiling report after a PIL run. Note the average and maximum time of the MotorCtrl step function in microseconds. Compare with the control period. If the current loop at 10 kHz needs more than the 100 µs period, reduce the rate or optimise. Record results for float and, later, fixed-point. Profile both loops separately if they run at different rates, since the faster loop sets the tighter limit on execution time.

    Checkpoint: A profiling table with maximum execution time and CPU load for each loop rate.

  8. 8

    Convert to fixed-point

    Use Fixed-Point Designer's tool to propose data types from simulation ranges, or set Q-format types by hand. Rerun MIL with fixed-point, then PIL. Compare outputs against the float reference and compare execution time. On a no-FPU core, fixed-point is usually much faster, at the cost of quantisation error. Start with 16-bit signals and 32-bit integrator states, then check for overflow warnings in every scenario before comparing accuracy with the float reference.

    Checkpoint: A table of execution time and maximum output error for float and fixed-point versions.

  9. 9

    Run on a real motor (optional)

    If a small encoder motor is available, build a deployment model with ADC and encoder or timer-capture input blocks and PWM output to the motor driver, running MotorCtrl as a timer-driven task. Use the potentiometer as the speed command. Start at low duty limits. Compare measured speed response with simulation. Keep supply voltage and current within the driver's rating. Stop if the motor or driver heats noticeably.

    Checkpoint: The motor follows speed commands, and measured step response resembles the simulated one.

  10. 10

    Report

    Present the plant, controller design, MIL results, PIL setup, MIL–PIL comparison, profiling, fixed-point comparison and optional hardware results. Discuss what PIL does and does not prove: it checks numerics and execution time but not real-time interrupt timing or sensor noise. Release models and scripts. Include the profiling reports and comparison plots as figures, and list the toolchain versions, compiler options and board used, since they affect timing results.

    Checkpoint: A report with MIL–PIL comparison plots and a profiling table.

Testing & validation

  • Controller design margins checked in frequency domain.
  • MIL and PIL outputs agree within tolerance on all scenarios.
  • Execution time on target measured and compared with control period.
  • Float and fixed-point versions compared for speed and accuracy.

Expected results

A cascaded DC motor controller verified by PIL on the STM32F103 of the DIYguru kit, with numerical agreement to the model, measured execution times and a float versus fixed-point comparison on a no-FPU processor.

Research angle for your M.Tech thesis

Research questions: what is the numerical and timing cost of moving a cascaded motor controller from floating-point to fixed-point on a no-FPU microcontroller, and how well does PIL predict on-hardware behaviour? Metrics: MIL–PIL error, execution time and CPU load, control performance (settling time, overshoot, load-disturbance recovery). Baselines: floating-point MIL and hand-written C. Adding real-motor comparisons and documenting the workflow carefully makes the work useful to others; a systematic study of word length against control performance and cycle cost on low-cost targets is suitable for a conference paper.

Take it further

  • Add an encoder-based speed observer and test it in PIL.
  • Automate MIL–PIL comparison with Simulink Test.
  • Move to field-oriented control of a PMSM on a target with an FPU.
  • Measure code coverage during PIL.

Viva and review questions

What does PIL test that SIL does not?

PIL runs the code on the actual processor with its compiler and arithmetic, so it reveals target-specific numerical differences and measures real execution time, which SIL on a PC cannot.

Why is PIL not real-time?

The plant runs in Simulink and data passes over a serial link every step, so the loop runs as fast as the link allows, not at the true control rate.

Why is fixed-point attractive on the STM32F103?

It has no FPU, so floating-point operations are emulated in software and take many cycles, while integer operations run in hardware.

Learn it at DIYguru

These DIYguru courses and programmes teach what this project needs.

Related EV projects

All 100 MATLAB & Simulink EV projects