The application is based on an example of basic GPIO for S32K144 (gpio_s32k14_mbd_rtw). The application is extended to fit the needs of motor control application running a sensorless PMSM Field Oriented Control algorithm. Therefore, certain modes (states) and transitions (events) are implemented.
NOTE: Theory of Finite state machines defines states and events (transitions). Following design uses approach which may seem to mix states and transitions at some point. Some states are run just once, thus they may be considered as transitions only. However, the design is considered as an example and may be extended in terms of additional checks for external events, making these "one-shot" states the actual states. The design has been well known from NXP Automotive Motor Control Development Kits and it has been well accepted by majority of customers. Therefore, the same concept is presented for MATLAB Simulink.
The application structure should introduce a systematic tool to handle all the tasks of motor control as well as hardware protection in case of failure. Therefore, a finite state machine is designed to control the application states using MATLAB Simulink Stateflow Chart (Stateflow library/Chart).
The motor control application requires at least two states - "stop" represented by "ready" state and "run" represented by "run" state. However, some additional states need to be implemented to cover e.g. power-on situation, where the program waits for various auxiliary systems (system basis chip, DC-bus to be fully charged, memory checks, etc.). In addition, the motor control application and specifically the sensorless field oriented control requires additional states to calibrate the sensors and to start the motor with known position. Therefore, transition from READY state to RUN state is done through an initialization sequence of CALIB (sensors calibration) and ALIGN (initial rotor position alignment or detection) states. To stop the motor, the application goes back to the READY state via INIT (state variables initialization).
While the INIT state is designed to clear all the internal accumulators and other variables (but the parameters can be changed in the run time and not reset to the default settings), the RESET state is introduced to enable power-on or "default configuration" or "soft reset" initialization in the case of the motor control parameters are changed using FreeMASTER or other user interface.
All the states are linked with an output event which is traced out of the state machine chart block. These events can be used as trigger points for calling the handlers (state functions). The transitions are driven by the input value of the state machine, treated as an event using a simple comparison (e.g. [u==e_start]). To change the state, the event/input value should be changed. If the event has changed, the state machine changes the state only in case of there is an existing action linked with the current state and the event.
The state machine is designed to be used in the application using Event input (to signal the event), State output (to indicate the current state) and Event triggers outputs (to call the state functions / handlers). Following application has been built to show an example of the state machine usage.
Following tables show the nomenclature of the states and events:
State | Purpose | Value |
---|---|---|
Reset | Power-on / Default settings / Soft-reset state. May include some HW checking sequence or fault detection. | 1 |
Init | Initialization of control state variables (integrators, ramps, accumulators, variables, etc.). May include fault detection | 2 |
Ready | Stand-by state, ready to be switched-on. Includes fault detection, e.g. DC-bus overvoltage or high temperature | 3 |
Calib | Calibration state to calibrate ADC channels (remove offsets). Includes fault detection | 4 |
Align | Alignment state to find the rotor position and to prepare to start. Includes fault detection | 5 |
Run | Motor is running either in open-loop or sensorless mode. Includes fault detection | 6 |
Fault | Fault state to switch off the power converter and all the peripherals to a safe state. | 7 |
Input events are the triggers which initiate a change of current state.
Input Event | Purpose | Value |
---|---|---|
e_init_done | Asserted when the Init state has finished the task with success | 1 |
e_start | Asserted when a user sends the switch-on command | 2 |
e_calib_done | Asserted when all the required ADC channels are calibrated | 3 |
e_align_done | Asserted when the initial rotor alignment / position detection is done | 4 |
e_stop | Asserted when a user sends the switch-off command | 5 |
e_fault | Asserted when a fault situation occurs | 6 |
e_fault_clear | Asserted when a user sends the "clear faults" command or when the situation allows this | 7 |
e_reset | Asserted when a user sends the "reset" command to start over with default settings | 8 |
Output events are used to trigger the Motor Control State Handlers and correspond to actual state. These events are triggered with every state machine call. Therefore, the state machine shall be aligned with the control algorithm. For example, it shall be placed within the ADC "conversion completed" interrupt routine or PWM reload interrupt routine.
The state machine shall be used in good alignment with the control algorithm. The usual way of controlling a motor is to have a periodic interrupt linked with the ADC conversion completed or with the PWM reload event (interrupt). The state machine shall be called within this event handler, right after all the external information is collected (voltages, currents, binary inputs, etc.) to let the state machine decide, which state should be called next.
Internal event/state handling inside of the state machine is clearly described by the state machine block definition. Output event triggers are configured to provide clear function-based code interface to the state machine. That means, the output events shall be connected to a function designed to handle the state task. For example, in Run state, the run() output event is triggered with every state machine call, while within the Run state function the whole motor control algorithm is called. If an input information is supposed to switch the state, a simple condition shall be programmed to change the Event variable (defined as a global variable). For example, if a user sends the "stop" command, the Event is set to "e_stop" and the state machine will switch to the Init state.
For more complex triggering of output functions, additional output events can be programmed within the state machine definition.
Template state handler function is based on the function caller block. In general, the function blocks can work with global variables, thus there is no need for inputs or outputs. Thanks to global Event variable, event-driven state machine can react on events thrown inside a state handler function or outside of the state machine (e.g. based on other asynchronous interrupt). An example of a simple template is shown below.
In this example, the function represents the Reset state, which is supposed to be run after the power-on reset or to set all the variables to its default settings. Therefore, the first part is dedicated to hardware-related settings, the second part is covering the application-related settings. The third part checks whether all the tasks are done. If yes, the e_reset_done event is thrown (stored into the Event variable). In this case, the ResetStatus variable is obviously always going from zero to two with no additional influence. Therefore, the final condition may be removed (even by the MATLAB optimization process during compilation). If there is an external condition, such as a waiting for an external pin to be set, then it makes sense to use such "status" variable as a green light for completing the state task and throwing the "done" event.
In default settings, MATLAB Embedded Coder generates the state machine code in a fashion of switch-case structure. This might be not very useful for further code debugging or for manual editing. Therefore, the function call subsystem block parameters should be changed as shown below. The function packaging option is set to "Nonreusable function", other settings might be left at default values. This will keep the state machine code structure in switch-case, however the state handlers function calls will be generated as static functions (instead of putting the code inside the switch-case).
Following code sample is a part of the state machine code generated in the stateMachineTest.c example code. The state machine decides based on the State variable, which is internally stored in the stateMachineTest_DW.is_c1_stateMachineTest. Based on the stateMachineTest_DW.Event, a transition is initiated. Finally, the state handler function is called, in this case stateMachineTest_Resetstate().
void stateMachineTest_step(void)
{
/* ... */
switch (stateMachineTest_DW.is_c1_stateMachineTest) {
/* ... */
case stateMachineTest_IN_Reset:
rtb_y = 1U;
/* During 'Reset': '<S5>:35' */
if (stateMachineTest_DW.Event == stateMachineTest_e_reset_done) {
/* Transition: '<S5>:37' */
stateMachineTest_DW.is_c1_stateMachineTest = stateMachineTest_IN_Init;
/* Entry 'Init': '<S5>:1' */
rtb_y = 2U;
} else if (stateMachineTest_DW.Event == stateMachineTest_e_fault) {
/* Transition: '<S5>:46' */
stateMachineTest_DW.is_c1_stateMachineTest = stateMachineTest_IN_Fault;
/* Entry 'Fault': '<S5>:18' */
rtb_y = 7U;
} else {
/* Outputs for Function Call SubSystem: '<Root>/Reset state' */
/* Event: '<S5>:49' */
stateMachineTest_Resetstate();
/* End of Outputs for SubSystem: '<Root>/Reset state' */
}
break;
/* ... */
}
/* ... */
}
The reset state function is compiled based on priorities set in each block of the Simulink model. If no priorities are set, the default ones are based on the order of adding them to the model. Therefore, it is very important to verify and eventually change the priorities as requested by its logical sequence. This setting can be changed in the block properties as shown below. The priority settings is shown after the model is updated (Ctrl+D) as a number in the upper right corner of each block.
Testing application is designed to test all the features of the state machine, targeting the S32K144EVB. To indicate active states, RGB LED diode is used in combination with flashing frequency. On-board buttons SW2 and SW3 are used to control the application. The application is running in 10 ms interrupt routine (given by the sample time). There is an independent LPIT interrupt controlling the LED flashing.
After the power-on reset, the device is configured and the RESET state is entered, where additional HW and application settings are performed. Then, the application runs into the INIT state with a simulated delay of approx. 2 seconds, indicated by the blue LED diode flashing fast. After the delay, the READY state is entered automatically.
Both buttons are handled by another state machine, which detects short and long button press. While the short press is not directly indicated, the long press is indicated by the red LED diode switched on.
By a short pressing of the SW2, the application is started, entering the CALIB state first, followed by the ALIGN state and finally entering the RUN state. The CALIB and ALIGN states are indicated by higher frequency flashing of the blue LED, while the RUN state is indicated by the green LED being switched on.
The application introduces a simulation of the speed command, which can be changed by long pressing of the SW2 (up) or SW3 (down) within the range of 0 to 10,000. Moreover, to simulate a fault situation, the e_fault event is thrown once the speed command reaches value of 5,000. The FAULT state is entered, indicated by the red LED flashing. To clear the fault, both SW2 and SW3 should be pressed simultaneously. The INIT state is entered, indicated by the blue LED diode flashing fast.
Following tables show the functions and LED indication.
Button | Press lenght | Function |
---|---|---|
SW2 | short press | Start the application |
SW2 | long press | Increase the speed command (indicated by the red LED diode ON) |
SW3 | short press | Stop the application |
SW3 | long press | Decrease the speed command (indicated by the red LED diode ON) |
SW2+SW3 | short press | Clear faults |
State | LED | Flashing |
---|---|---|
Reset | - | |
Init | Blue | period 50 |
Ready | Blue | period 500 |
Calib | Blue | period 250 |
Align | Blue | period 100 |
Run | Green | always on |
Fault | Red | period 100 |
any | Red | always on when a long press of SW2 or SW3 is detected |
The example can be built and run along with the Model Based Design Toolbox for S32K14x, v3.0.0. This version has been created using MATLAB R2017a. Please follow the instructions and courses on the NXP Community page prior to running this example. Usage of the S32K144EVB with no connected extension boards is recommended, however this example doesn't use any HW interfaces except of (please refer to the S32K144EVB documentation):
S32K144 pin | S32K144EVB connector | Usage |
---|---|---|
PTD15 | J2.2 | GPIO output / strength: High / Red LED |
PTD0 | J2.6 | GPIO output / strength: High / Blue LED |
PTD16 | J2.4 | GPIO output / strength: High / Green LED |
PTC12 | J2.10 | GPIO input / Button SW2 |
PTC13 | J2.12 | GPIO input / Button SW3 |
PTC6 | J4.4 | UART1 / RxD / FreeMASTER |
PTC7 | J4.2 | UART1 / TxD / FreeMASTER |
The application works also with the FreeMASTER application. Users can connect to the target and watch or control the application. The FreeMASTER project is attached as well, however, the ELF file location needs to be updated in the FreeMASTER project settings after the application is built and run.