Engee documentation
Notebook

Code generation for STM32 (Full step stepper motor control)

Introduction

This demonstration implements a hardware embodiment of an example full-step control of a bipolar stepper motor.

Hardware

The control object of this example is a 17HS1352-P4130 bipolar stepper motor, as already specified in the simulation example. A dual full-bridge MOSFET driver L6206PD based on the X-NUCLEO-IHM04A1 expansion board is used as the inverter. This board is compatible with the STM NUCLEO F446RE debugging microcontroller board whose digital I/O operation is discussed in related example.

The figure below shows the wiring diagram of the drive.

scheme.png

According to the pinout and circuit diagram of the IHM04A1 board, as well as the functional diagram of the driver, inputs EN-A and EN-B are designed for hardware switching on/off of the A and B bridges of the driver. Inputs IN1A and IN2A control the first and second arms of the A bridge, inputs IN1B and IN2B - of the B bridge.

image.png

The control inputs are connected to the GPIO of the debug board as indicated in the connection diagram. The frequency of signals to the control inputs, according to the motor data, does not exceed 250 Hz. For this reason it is sufficient to use peripheral digital input modules to realise the control, PWM modules will not be considered in this example.

Control system model

Compared to the model used in the original example, the new model differs only in the controller periphery blocks based on C Function blocks and blocks for data type/dimensionality matching of input signals. All of them are included in the "Control System" subsystem.

image.png

Blocks C Function "BUTTON_GPIO_PC13" and "LED_GPIO_PA5" have already been shown in STM32 digital I/O example. Block C Function "NUCLEO_IHM04A1" is necessary to realise the interaction of the control algorithm with the peripherals used to control the driver - digital inputs PA10, PB4, PB5, PC1, PA0, PA1. Also this block realises exclusively full-step control of the driver.
When a high level signal is applied to the enable block input, a high level is also set on GPIO PA10, PC1, which enables both bridges of the driver. A vector of GPIO PB4, PB5, PA0 and PA1 states is transmitted to the input of pulses block, thus enabling/disabling the corresponding driver keys.

In this block, you should also note that the states of the inputs in the previous step are stored in the global variables flag and flags. These variables are declared in tab Shared Code of the block.

The user programme with the algorithm generated from the subsystem "Contol System" will work as follows: on the trailing edge of the signal after pressing the button contact built into the board, the LED built into the board lights up, the driver bridges are switched on and the sequential formation of control pulses begins. The sequence of pulses for clockwise rotation of the motor shaft corresponds to the output of pulses to the inputs in the sequence PB4-PB5-PA0-PA1. After pressing the pushbutton contact again, the driver bridges and LED are switched off and the pulse output is stopped.

Modelling results

Since we have made changes to the original model, let's simulate it again, repeating the same steps of the original example This way we will make sure that the algorithms work identically and check the correctness of work with the signals coming to the blocks C Function.

Loading the necessary libraries:

In [ ]:
using Plots
using DataFrames
plotlyjs();

Running the model:

In [ ]:
modelName = "stm32_sm_fullstep_control";
if modelName  getfield.(engee.get_all_models(), :name)
    engee.load( "$(@__DIR__)/$(modelName).engee");
end

model = engee.run(modelName);

Read instantaneous values of voltages and currents, as well as rotational speed and shaft position:

In [ ]:
t = model["Speed"].time;
Ia = model["Ia"].value;
Ib = model["Ib"].value;
Va = model["Va"].value;
Vb = model["Vb"].value;
Speed = model["Speed"].value;
Position = model["Position"].value;

Plotting shaft position and speed:

In [ ]:
plot(t, Position, layout = (2,1), ylabel = "Положение, град", legend = :none)
plot!(t, Speed, subplot = 2, ylabel = "Скорость вращения, рад/с", xlabel = "Время, c", legend = :none)
Out[0]:

Plotting phase currents and voltages:

In [ ]:
plot(t, [Va Vb], label = ["Va" "Vb"], ylabel = "Фазные напряжения, В", color = [:red :blue], layout = (2,1), subplot = 1)
plot!(t, [Ia Ib], label = ["Ia" "Ib"], ylabel = "Фазные токи, А", xlabel = "Время, c", color = [:green :black], subplot = 2)
Out[0]:

As can be seen from the resulting graphs, the operation of the algorithms of this example model is identical to the original model.

Code generation and project assembly

Let's generate the code from the subsystem Control System:

In [ ]:
engee.generate_code("$(@__DIR__)/$(modelName).engee",
                    "$(@__DIR__)/code/";
                    subsystem_name = "Control System")
[ Info: Generated code and artifacts: /user/start/examples/codegen/stm32_sm_fullstep_control/code

Download the obtained files and add them to the project in the development environment VS Code + PlatformIO. The code of the user program of the example is given in the file /stm32_sm_fullstep_control/main.c, it will also be added to the project. Work with generated files in VS Code + PlatformIO in the framework stm32cube is shown in the example flashing LED on STM32.

Code execution on STM32

After loading the code into the microcontroller, let's proceed to the execution of the programme.

vid480.gif

By pressing a button integrated on the NUCLEO board, the stepper motor starts and stops.

Conclusion

In this example, we have refined the full-step stepper motor control model by adding microcontroller peripheral blocks. The control algorithm works correctly on a real control object.