Table of Contents
This note provides practical guidelines and code snippets for programming imperix controllers with the CPP SDK. It follows up on the getting started guide and provides specific details and guidance about how to efficiently implement commonly-used functions, such as control strategies, state machines, background tasks, communication interfaces, etc. To this end, the article uses a three-phase PV inverter as an example, which advantageously regroups and illustrates all of these concepts.
When developing control software for imperix controllers, users should typically start by referring to the software documentation and/or the header files. However, to quickly bridge the gap between the template and a functioning system, it is also possible to draw inspiration from existing examples. With this mindset, this page dissects the user.cpp file from the AN006. The corresponding C++ project is provided below.
Control algorithms
To facilitate the development of control algorithms, the CPP SDK includes a dedicated API folder with pre-validated functions specific to power electronics, such as PI controllers, PLLs, and coordinate transformations. Developers are encouraged to use these standard functions, which they can also modify as needed.
The two next paragraphs showcase how to use a few of these functions.
State machines
Power converter control often requires managing different operating states, such as standby, precharging, operating, discharging, fault, etc. State machines are powerful tools that allow managing transitions between these states safely. They can be implemented in many ways. The following snippet serves as a practical example, detailing the different operating states of the PV inverter.
Programmatic enabling/disabling of PWM outputs
Following the implementation of a state machine, developers may seek to automate the enabling/disabling of the PWM outputs. This relates to the different operating states of the so-called core state machine, which is further described in PN261.
While this action is usually performed manually via the dedicated Cockpit button (see the related documentation), it is also possible to do it programmatically using the CoreStart() and CoreStop() functions. When combined with state machine logic, these functions enable fully automated operation.
System logging and diagnostics
User log messages are useful for tracking state machine transitions or reporting converter faults. These messages can be elaborated and displayed in Cockpit using the Log_AddMsg and Log_SendMsg functions. However, since simply placing Log_SendMsg within the main interrupt may continuously spam the Cockpit log messages, developers must implement trigger conditions instead. The following code demonstrates a possible approach.
Background tasks
Tasks such as MPPT, thermal monitoring, or background communication may not require execution at the deterministic, high-frequency rate of the main control interrupt. Instead, to manage non-critical tasks, the CPP SDK provides a background callback routine, typically implemented as UserBackground(), which executes during the CPU’s idle time. In this PV-related example, the background routine is used to implement an MPPT algorithm executed at 200Hz.
The example below shows how developers can implement sub-rate tasks by using a software timer inside the main interrupt to periodically raise a flag to trigger a task in the background.
Software interrupts
Starting with SDK 2026.2, the CPP SDK introduced native support for software interrupts, providing a more robust alternative to using the background callback routine for sub rate tasks execution.
For each task that must be executed at a lower rate, the user can assign a callback routine to a software interrupt ID (0 through 7) using ConfigureSoftwareInterrupt(). Then the software interrupt callback is immediately executed when TriggerSoftwareInterrupt() is called. This approach offers several advantages:
- The software interrupts support preemption. Higher-priority tasks can preempt slower, lower-priority ones. (Lower ID have a higher priority. The main interrupt has a higher priority than the soft interrupts)
- The software interrupt mechanism detects overruns. An error is raised if a software interrupts is triggered again before the task completed.
In the example below, similar to the UserBackground() example, the sub rate task is managed using a software timer inside the main control interrupt. However, instead of setting a global flag that is continuously polled during the CPU’s idle time, the software interrupt is dispatched explicitly by calling TriggerSoftwareInterrupt(). Once triggered, the assigned callback is executed right after the main interrupt finished its execution.
User faults
Imperix controllers implement hardware-level protections that respond to three different fault types:
- Hardware faults, typically occurring when an over.value is detected (e.g. over-current or over-voltage).
- Software faults, typically indicating a loss of real time or a similar exception.
- User faults, voluntarily thrown by the user from the user code.
The third type – user faults – is discussed below. The others are further documented in PN263.
To declare user fault, SetUserFault(const char* user_txt) may be called at any time. When triggered, this immediately disables all PWM outputs and displays the corresponding message in the Cockpit logs.
if(V_meas > V_max){
SetUserFault("Maximum voltage exceeded");
}Code language: C++ (cpp)
As an alternative, it is also possible to trigger a user fault by returning the state UNSAFE state at the end of the user interrupt. Returning SAFE implies that no errors happened during execution. Note that returning UNSAFE will generate a generic fault. It is then recommended to use the SetUserFault(const char* user_txt) method to display a informative fault message.
Further readings
- Programming and operating imperix controllers about deploying code onto imperix controllers.
- Cockpit user guide regarding how to work with Cockpit.



