Engee documentation
Notebook

Code generation for MIC32 (Fuzzy Controller Testing)

This demo shows the development of the Engee model for testing a fuzzy controller over the entire input signal range with output output to the DAC of the MIK32V2 microcontroller.

Introduction

The purpose of the example is to test the operation of a fuzzy controller with two inputs and one output. The fuzzy controller model is assembled from separate blocks of the Engee basic library for ease of familiarization with the functional features of the controller. The target device used in this demo is the MIK32 NUKE V0 debugging board.3 based on microcontroller [K1948VK018 MIK32 Amur](https://mikron.ru/products/mikrokontrollery/mk32-amur /). The code was compiled and uploaded to the microcontroller from VS Code with the PlatformIO extension.

Description of the model

The general view of the model is shown in the figure below.

mik32_fuzzy_model.png

It consists of blocks for setting two input, testing signals, a subsystem of a fuzzy controller with two inputs and one output, a subsystem for scaling the output signal, and peripheral blocks of the HAL library MIC32.

Inputs and outputs of the regulator

Repeating variable discrete signals from the [Repeating Sequence Stair] blocks are applied to the inputs of the controller (https://engee.com/helpcenter/stable/ru/base-lib-sources/repeating-sequence-stair.html ):

In [ ]:
# Входные сигналы:
x1_data = Vector(range(-2,2,105))
x2_data = Vector(range(-2,2,21))

# Шаг дискретизации:
Ts = 0.01

using Plots
gr()
plot([x1_data,x2_data]; label=["x1_data" "x2_data"],
     st=:step, title = "Входные сигналы", aspect_ratio=10)
Out[0]:
No description has been provided for this image

This setting of the input signals allows you to check the results of calculations of the output signal of the controller over the entire range of values of one and the second signals.

Subsystem operation scaling it consists in changing the range of values and the data type of the output signal of the controller: :

mik32_output_model.png

The signal is limited from 0 to 4095, since the MIC32 DACs have a 12-bit bit rate, the data format is integer, unsigned, 2 bytes.

The structure of the fuzzy controller

The fuzzy controller is built according to the Mamdani algorithm and consists of identical fuzzification and aggregation blocks, an activation block (min function), an accumulation block (max function), and a defuzzification block (center of gravity method for single-point sets, COGS).

mik32_fuzzy_controller_model_2.png

The number of linguistic terms of the input signals is 3, the output signal is 3.

Fuzzification and aggregation

The input variables have three linguistic terms that accept non-zero truth values in the ranges "LOW".: , "AVERAGE": , "HIGH": . At the aggregation stage, triangular membership functions (AF), symmetrical with respect to zero, are applied to the input signals. In subsystems fuzzyfication The OP is played in blocks 1-D Lookup Table. The calculation of the AF for the terms of the input variables is given below.

In [ ]:
# ФП для x1
μ_S_x1 = -x1_data;
μ_M_x1 = 1.0.-abs.(x1_data);
μ_L_x1 = copy(x1_data);

μ_x1 = [μ_S_x1, μ_M_x1, μ_L_x1];

# ФП для x2
μ_S_x2 = -x2_data;
μ_M_x2 = 1.0.-abs.(x2_data);
μ_L_x2 = copy(x2_data);

μ_x2 = [μ_S_x2, μ_M_x2, μ_L_x2];

термы = ["низкое" "среднее" "высокое"];

Input saturation function:

In [ ]:
function насыщение(μ)
    for i in 1:length(μ) 
        if μ[i] > 1
            μ[i] = 1.0
        end
        if μ[i] < 0
            μ[i] = 0.0
        end
    end 
end;

Applying saturation to terms, constructing membership functions:

In [ ]:
for i in 1:3
    насыщение(μ_x1[i])
end

for i in 1:3
    насыщение(μ_x2[i])
end

график1 = plot(x1_data, μ_x1; title = "ФП для x1", label = термы, xlabel = "x1")
график2 = plot(x2_data, μ_x2; title = "ФП для x2", label = :none, xlabel = "x2")
plot(график1, график2;
     ylabel = "Степень принадлежености, μ", legend = :right, aspect_ratio=3)
Out[0]:
No description has been provided for this image

Activation

At the stage of activation in the subsystem activation The conclusions for all combinations of terms are defined. Activation is performed by the minimum function:

Accumulation

In the subsystem accumulation The following rule base is reproduced:

  1. ** IF** ( "LOW" AND ( "LOW" OR "AVERAGE")) ** THEN** "LOW"
  2. ** IF** ( "LOW" AND "HIGH") OR
    ( "AVERAGE" AND ( "LOW" OR "AVERAGE")) ** OR**
    ( "HIGH" AND "LOW") THEN "AVERAGE"
  3. ** IF** ( "AVERAGE" AND "HIGH") OR
    ( "HIGH" AND ( "AVERAGE" ** OR** "HIGH")) THAT "HIGH"

For clarity, let's present it in the form of a table.:

In [ ]:
колонки = ["низкое", "среднее", "высокое"];
строки = copy(колонки);
база_правил = [
                "низкое" "среднее" "среднее";
                "низкое" "среднее" "высокое";
                "среднее" "высокое" "высокое"
               ];
(n,m) = size(база_правил)

heatmap(база_правил, fc = cgrad([:blue; :red; :green]), leg=false, xticks=(1:3,колонки), yticks=(1:3,строки))
title!("База правил")
xlabel!("Термы x1")
ylabel!("Термы x2")
annotate!( [(j, i, база_правил[i,j]) for i in 1:n for j in 1:m])
vline!(0.5:(n+0.5), c=:black)
hline!(0.5:(m+0.5), c=:black)
Out[0]:

The degrees of truth of the output terms are determined in the maximum function from the conclusions according to the expressions:

Defuzzification

In the subsystem defuzzyfication The center of gravity method for single-point sets (COGS) is implemented. The midpoints for the membership functions of the output terms: . The calculation is implemented without reducing the degrees of membership to the sum ( ) and with a cast ( ). For modeling and testing, we further use the first method.

mik32_defuzzy_model.png

Simulation results

Download and execute the example model:

In [ ]:
# @markdown **Программное управление моделированием:**  
# @markdown Требуется ввести только имя модели
имя_модели = "mik32_fuzzy_reg" # @param {type:"string"}
if имя_модели in [m.name for m in engee.get_all_models()]
    модель = engee.open( имя_модели );
else
    модель = engee.load( "$(@__DIR__)/"*имя_модели*".engee" );
end
данные = engee.run(модель);

Plotting the output variable

In [ ]:
plot(данные["dac_val"].time, данные["dac_val"].value;
     label="y", title="Выходной сигнал", xlims=(0,1.1))
Out[0]:

This signal is included in the program loaded into the controller and will be transmitted to the digital-to-analog converter.

The controller peripherals in the model are implemented using [C Function] blocks (https://engee.com/helpcenter/stable/ru/base-lib-user-defined-function/c-function.html ), as it was implemented in early DAC examples for MIC32: sawtooth signal, Engee logo.

Code generation and project assembly

In [ ]:
# @markdown **Генерация кода:**  
# @markdown Папка для результатов генерации кода будет создана в папке скрипта:
папка = "code" # @param {type:"string"}

# @markdown Генерация кода для подсистемы:
включить = false # @param {type:"boolean"}
if(включить)
    подсистема = "" # @param {type:"string"}
    engee.generate_code( "$(@__DIR__)/"*имя_модели*".engee", "$(@__DIR__)/"*папка;
                     subsystem_name = подсистема)
else
    engee.generate_code( "$(@__DIR__)/"*имя_модели*".engee", "$(@__DIR__)/"*папка)
end
[ Info: Generated code and artifacts: /user/start/examples/codegen/mik32_fuzzy/code

The project with the model is assembled in the IDE VS Code+PlatformIO, the assembly process is similar to the process from the example MIC32: Sawtooth signal generator.
The only exception is that the compiled program is loaded not into the RAM of the controller, but into flash memory via the SPIFI interface. The configuration file is attached to configure PlatformIO in the example. platformio.ini. Let's move on to executing the code on the microcontroller.

Code execution on MIK 32

After successful assembly and compilation of the project, we will connect an oscilloscope to the P1.12 microcontroller channel and display the oscilloscope.

mik32_fuzzy_results.gif

As can be seen from the waveform, the shape of the simulated output signal of the fuzzy controller under test is reproduced in the DAC channel.

Conclusion

In this example, we examined the structure of the fuzzy controller in the Engee model, simulated its testing, and tested the controller on the MIC32 Amur microcontroller after generating the code from the model. The simulation and test results on the controller are identical and correspond to the specified algorithm.