release 1.01

чуть доработано:
- добавлен перенос шаблонов в проект
- убрана линковка с библиотекой для изменения маски из конфига
- исправлено изменение названия бинарника S-Function
- исправлено некорректная запись из буфера в входы/выходы и обратно
This commit is contained in:
2025-06-14 23:53:50 +03:00
parent 1bd5009b9d
commit d983f2525a
14 changed files with 118 additions and 201 deletions

View File

@@ -67,7 +67,6 @@ classdef asynchManage < handle
if ~isempty(obj.maskBlockPath)
try
mcuMask.open(obj.maskBlockPath, 1);
fprintf('Mask opened for block %s\n', obj.maskBlockPath);
catch ME
warning('progr:Nneg', 'Не удалось открыть маску: %s', ME.message);
end

View File

@@ -1,120 +0,0 @@
% Cкрипт для задания параметров модели
clear;%очищаем рабочее пространство
%% ПАРАМЕТРЫ МОДЕЛИ
addpath('MCU_Wrapper');
addpath('motor');
Ts = 10e-6;%шаг интегрирования
Decim = 1;%интервал прореживания
DisableScope = {
"Idc";
"Udc";
};
GED = "23550";
% GED = "22220";
% начальная скорость ГЭД, доля от NmNom
w0 = 0;%0.5;%-0.75;%
% пусковой момент, о.е.
Mst = 0.6;%0.6;
% разрешаем/запрещаем сбросы/набросы момента нагрузки
changingLoadEnable = 0;%1
% разрешаем/запрещаем шум в измеренном токе
noiseEnable = 0;%1;%
% ... мощность шума
NP = 0.08;
%% НОМИНАЛЬНЫЕ ВЕЛИЧИНЫ ГЭД
% ... мощность на валу, Вт
Pnom = 6300e3;
% ... линейное напряжение, В (rms)
Unom = 3300;
% ... механическая скорость, об/мин
NmNom = 180;
% ... число пар полюсов
Pp = 6;
% ... коэффициент мощности
CosFi = 0.87;
% ... КПД
Eff = 0.968;
% ... приведенный к валу момент инерции, кг*м^2
J = 87e3*0.1;
%% РАСЧЕТЫ
% разкомментирование всех блоков
modelName = [bdroot '/Measurements'];
blocks = find_system(modelName, ...
'IncludeCommented', 'on', ...
'FollowLinks', 'on', ...
'LookUnderMasks', 'all', ...
'BlockType', 'Scope');
for i = 1:length(blocks)
set_param(blocks{i}, 'Commented', 'off');
end
% отключение графиков для ускорения смуляции
for i = 1:length(DisableScope)
set_param([modelName '/'] + DisableScope{i}, 'Commented', 'on');
end
% для упрощения записи
SQRT2 = sqrt(2);
SQRT3 = sqrt(3);
PI2 = pi*2;
% ... полная мощность, ВА
Snom = Pnom/CosFi/Eff;
% ... механическая скорость, рад/с
WmNom = NmNom/60*PI2;
% ... момент на валу, Н*м
Mnom = Pnom/WmNom;
% ... эл. скорость, рад/с
WeNom = WmNom*Pp;
% ... эл. скорость, Гц
FeNom = WeNom/PI2;
% ... потокосцепление статора, Вб
PsiNom = Unom*SQRT2/(WeNom*SQRT3);
% ... напряжение на входе инвертора, B
UdcNom = Unom*SQRT2;
% ... ток, А (ampl)
Inom = Snom/(Unom*SQRT3)*SQRT2*0.5;%0.5 - т.к. обмоток две
% схема замещения ГЭД
if GED == "22220"
GED
Rs = 11.8e-3;%Ом
Xls = 72.7e-3;%72.7e-3;%Ом
Rr = 11.1e-3*2.0;%*0.8;%Ом
Xlr = 85.5e-3;%Ом
Xm = 2.9322;%2.87;%Ом
Fe = 18;%Гц
Lls = Xls/(Fe*PI2);%Гн
Llr = Xlr/(Fe*PI2);%Гн
Lm = Xm/(Fe*PI2);%Гн
elseif GED == "23550"
GED
Rs = 0.0282;%Ом
Xls = 0.4016;%Ом
Rr = 0.139;%Ом
Xlr = 0.2006;%Ом
Xm = 5.2796;%Ом
Fe = 18.2;%Гц
Lls = Xls/(Fe*PI2);%Гн
Llr = Xlr/(Fe*PI2);%Гн
Lm = Xm/(Fe*PI2);%Гн
end
% ёмкость на входе INU, Ф
Cdc = 50e-3;
% снаберы в INU
Csn = Pnom/(1000*WeNom*Unom^2)/10;%Ф (0.5 - т.к. преобразователей два)
Rsn = 2*Ts/Csn*10;%Ом
% постоянная времени фильтра для тока ГЭД, c
Tiac = 30e-6;

View File

@@ -0,0 +1,59 @@
function installTemplates(forceCopy)
% installTemplates Копирует содержимое папки templates (включая вложенные папки) из уровня выше McuLib.slx в текущую папку
%
% installTemplates(forceCopy)
%
% forceCopy логический параметр (true/false)
% Если true, файлы будут перезаписаны.
% Если false или не указан, копирование происходит без перезаписи существующих файлов.
if nargin < 1
forceCopy = false;
end
try
libDir = fileparts(which('McuLib.slx')); % папка с McuLib.slx
parentDir = fileparts(libDir); % уровень выше
templatesDir = fullfile(parentDir, 'templates'); % папка templates
targetDir = pwd; % текущая папка
mcuMask.disp(1, '');
if ~exist(templatesDir, 'dir')
mcuMask.disp(1, 'Папка шаблонов %s не найдена.', templatesDir);
return;
end
% Список всех файлов и папок внутри templates (рекурсивно)
entries = dir(fullfile(templatesDir, '**', '*'));
for k = 1:length(entries)
if ~entries(k).isdir
% Относительный путь внутри templates
relPath = erase(entries(k).folder, [templatesDir filesep]);
if startsWith(relPath, filesep)
relPath = relPath(2:end); % убрать начальный слеш
end
srcFile = fullfile(entries(k).folder, entries(k).name);
destFolder = fullfile(targetDir, relPath);
destFile = fullfile(destFolder, entries(k).name);
if ~exist(destFolder, 'dir')
mkdir(destFolder);
end
if forceCopy || ~exist(destFile, 'file')
copyfile(srcFile, destFile);
mcuMask.disp(0, 'Скопирован файл: %s\n', fullfile(relPath, entries(k).name));
else
% mcuMask.disp(0, 'Файл уже существует и не перезаписывается: %s\n', fullfile(relPath, entries(k).name));
end
end
end
mcuMask.disp(0, ['Шаблоны успешно скопированы в ', targetDir]);
catch ME
mcuMask.disp(0, 'Ошибка при копировании шаблонов: %s', ME.message);
end
end

View File

@@ -8,6 +8,8 @@ classdef mcuMask
function MaskInitialization(maskInitContext)
% Получаем хэндл текущего блока
blk = gcbh;
set_param(blk,"MaskSelfModifiable","on")
set_param(blk, 'LinkStatus', 'none');
% Получаем объект маски текущего блока
mask = Simulink.Mask.get(gcb);
% mcuMask.disp(1,'');
@@ -143,11 +145,14 @@ classdef mcuMask
% Загружаем содержимое файла
set_param(block, 'wrapperCode', '');
code = fileread(filename);
code = regexprep(code, '\r\n?', '\n'); % нормализуем окончания строк
try
code = fileread(filename);
code = regexprep(code, '\r\n?', '\n'); % нормализуем окончания строк
includesText = editCode.extractSection(code, section);
set_param(block, 'wrapperCode', includesText);
includesText = editCode.extractSection(code, section);
set_param(block, 'wrapperCode', includesText);
catch
end
% % Поиск тела обычной функции
% expr = sprintf('void %s()', sel);
% funcBody = editCode.extractSection(code, expr);
@@ -312,13 +317,17 @@ classdef mcuMask
function set_name()
block = gcb;
% Получаем параметр имени S-Function из маски блока
newName = get_param(block, 'sfuncName');
newName = mcuMask.get_name();
% Путь к файлу, в котором надо заменить строку
cFilePath = fullfile(pwd, './MCU_Wrapper/MCU.c'); % <-- укажи правильный путь
% Считаем файл в память
fileText = fileread(cFilePath);
try
fileText = fileread(cFilePath);
catch
return;
end
% Регулярное выражение для поиска строки с define
% Заменим строку вида: #define S_FUNCTION_NAME old_name
@@ -336,10 +345,14 @@ classdef mcuMask
error('Не удалось открыть файл для записи.');
end
fwrite(fid, updatedText);
fclose(fid);
fclose(fid);
end
function name = get_name()
block = gcb;
% Получаем параметр имени S-Function из маски блока
name = get_param(block, 'sfuncName');
end
end

View File

@@ -8,8 +8,6 @@ function res = mexing(compile_mode)
delete("*.mexw64.pdb")
delete(".\MCU_Wrapper\Outputs\*.*");
set_param(gcb, 'consoleOutput', '');
% Порты S-Function
mcuPorts.write();
% Дефайны
definesUserArg = parseDefinesMaskText();
definesWrapperConfigArg = buildWrapperDefinesString();
@@ -30,8 +28,10 @@ function res = mexing(compile_mode)
[includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
Name = mcuMask.get_name();
% Вызов батника с двумя параметрами: includes и code
cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" "%s" %s %s', includesArg, codeArg, definesUserArg, definesConfigArg, modeArg, echoArg);
cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat %s "%s" "%s" "%s" "%s" %s %s', Name, includesArg, codeArg, definesUserArg, definesConfigArg, modeArg, echoArg);
if mcuMask.read_checkbox('extConsol')
cmdout = runBatAndShowOutput(cmd);