I am simulating a Dual Active Bridge with a digital control system in PLECS (similar to Simulink). What I want to do is to run a sequence of simulations where I change two variables related to the controller(Kp and Ki), to do this parameter sweep I have to create a simulation script in Octave. I have followed the official tutorial (https://www.youtube.com/watch?v=RB3EdvIE7ds&ab_channel=Plexim), however I didn't manage to achieve an appropriate sweep of the variables.
I expect an output result from majority of the parameter sweeps, however I don't get an output from most of them*. The issues I am seeing:
Some values aren't imported correctly.
Sometimes are real-time result presents an output waveform, however when the trace is automatically saved it disappears.
What I have tried:
I have tried changing the initialization value of Kp and Ki to 0, then to 1. This resulted in invalid results where the system essentially does nothing.
Changing the data in the .csv file to be in general format rather than scientific.
What I think is happening:
the "plecs('simulate', ...)" commands are running individually causing 2 separate simulations to be executed. I don't know how I would solve this issue, but would I have to combine the Kp and Ki structures together and use that as an argument of "plecs('simulate', ...)" function?
mdl = plecs('get', '', 'CurrentCircuit');
scopepath = [mdl '/Output'];
% clear all previous traces in scope 'Scope' in the current model
plecs('scope', scopepath, 'ClearTraces');
potentialStructure = struct('Kp', 0.0000819); %default value KP
integralStructure = struct('Ki', -0.0000505); %default value Ki
potStructure = struct('ModelVars', potentialStructure); %KP simStruct with 'ModelVars
intStructure = struct('ModelVars', integralStructure); %KI simStruct with 'ModelVars
Kpd = dlmread ('Digital Controller PI Values.csv',',', 'A2:A194'); %read first column
Kid = dlmread ('Digital Controller PI Values.csv',',', 'B2:B194'); %read second column
for ix = 1:length(Kpd) %how many loops - same as number of rows
potStructure.ModelVars.Kp = Kpd(ix); %set value of KP
intStructure.ModelVars.Ki = Kid(ix); %set value of KI
plecs('simulate', potStructure); %override the Kp value in the model during each simulation run
plecs('simulate', intStructure); %override the Ki value in the model during each simulation run
%hold and label trace
plecs('scope', scopepath, 'HoldTrace', ['Kp = ' mat2str(Kpd(ix)) ' Ki = ' mat2str(Kid(ix))]);
end
[Simulation Results, Code, Data][1]
*The invalid results are the ones that can be seen as a straight line at 0 in the image attached
[1]: https://i.stack.imgur.com/SXHfW.png
The issue lied how I was using the struct() function. I could set multiple variables and with set value to the single struct. This in turn solved my issue where I was executing 2 simulations in a single loop.
mdl = plecs('get', '', 'CurrentCircuit');
scopepath = [mdl '/Output'];
% clear all previous traces in scope 'Scope' in the current model
plecs('scope', scopepath, 'ClearTraces');
mdlVars = struct('Kp', 0.0000819, 'Ki', -0.0000505 ); %default value KP
simStruct = struct('ModelVars', mdlVars); %KP simStruct with 'ModelVars
Kpd = dlmread ('Digital Controller PI Values.csv',',', 'A2:A194'); %read first column
Kid = dlmread ('Digital Controller PI Values.csv',',', 'B2:B194'); %read second column
for ix = 1:length(Kpd) %how many loops - same as number of rows
simStruct.ModelVars.Kp = Kpd(ix); %set value of KP
simStruct.ModelVars.Ki = Kid(ix); %set value of KI
plecs('simulate', simStruct); %override the Kp value in the model during each simulation run
%hold and label trace
plecs('scope', scopepath, 'HoldTrace', ['Kp = ' mat2str(Kpd(ix)) ' Ki = ' mat2str(Kid(ix))]);
end
Related
I have written a snippet of code including the function bwconncomp() that works perfectly on my computers matlab. However, when the code was put into a simulink block on a different pc (running same version) I received an error
Dot notation on function call return value not allowed.1
When I try adding an extra line where I call the function and than dot notation choosing the item i want after I still receive an error. Do you know what might be going wrong?
function [cleaned_matrix] = pathFindingV2(matrix)
% find height and width of matrix to be cleaned
[HEIGHT,WIDTH] = size(matrix);
% Finds each cluster where a cluster is defined as a blob of trues that
% are connected to eachother
clusters = bwconncomp(matrix, 4).PixelIdxList;
% Choose largest cluster as main path
mainClusterIdxs = [];
maxLength = 0;
for k=1:length(clusters)
if length(clusters{k}) > maxLength
maxLength = length(clusters{k});
mainClusterIdxs = clusters{k};
end
end
% Convert index list to a matrix form
length1 = HEIGHT * WIDTH;
cleaned_matrix = zeros(length1, 1);
cleaned_matrix(mainClusterIdxs) = 1;
cleaned_matrix = reshape(cleaned_matrix, [HEIGHT, WIDTH]);
end
The algorithm above (works in matlab not simulink) takes in a matrix and finds and keeps the largest cluster and sets all other cells to 0.
Any help will be appreciated, I have been banging my head on the wall for hours
I'm trying to plot in 'real time' in Matlab from Arduino. I have the following code to get the data:
clear all; close all;clc;delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.BaudRate=115200;
fopen(puerto);
for i=1:1000
a=fscanf(puerto, '%d');
v(i)=a;
++i;
end
fclose(puerto);
delete(puerto);
However, sometimes I get an error saying the following (in reference to variable a):
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in (line 8)
v(i)=a;
So I have 3 questions:
How can I avoid the error I mentioned?
How can I plot (v) continuously?
Is there a way to send an array of integers from Arduino to Matlab?
Try something like this. Using the BytesAvailableFcn of the serial port.
See Documentation
function serialTest()
lineHandle = plot(now,0);
hold on;
delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.InputBufferSize = 200; %Set to an appropriate number of bytes see docs
puerto.BaudRate=115200;
puerto.BytesAvailableFcnCount = 100; %Set to an appropriate number see docs.
set(puerto,'BytesAvailableFcn',{#bytesFcnCallback,lineHandle});
drawnow
fopen(puerto);
function bytesFcnCallback(puerto,evtData,lineHandle)
temp = fgetl(puerto); %Read a single line from the com port.
C = textscan(temp,'%f');
lineHandle(1).YData= [lineHandle(1).YData C{1}];
lineHandle(1).XData(end+1) = now;
Edit: Update to show how to continuously update a plot.
This is a followup to a previous issue I was having.
I want to give an offset to a signal then add some delay in it and calculate RMSE for that but when taking difference I am having the following issue:
I would like to ask the following things:
How can I solve the above problem?
Will anybody please explain in simple words what iddata does - because I have studied different portals including MATLAB but remained unable to get a good concept.
How can I store data of type iddata in cell for subtraction in the last part of my code?
Code with Problem :
drv(1)=load('123.mat');
t = drv(1).x;
ref = drv(1).y;
angle = drv(1).z;
Fs = 1000;
t1 =t';
ref1= ref';
d_data = iddata(ref1, t1, 1/Fs);
%% Add offset:
x = 1;
afterOffset1= {};
for i = 100:10:130
T = getTrend(d_data);
% <detrend data if needed>
T.InputOffset = i;
T.OutputOffset = i;
afterOffset = retrend(d_data,T);
afterOffset1{x,1}= afterOffset;
x= x+1 ;
end
%% Add delay:
y=20;
afterDelay1= {};
for i = 1:1:4
% delaySamples = i; % Must be a non-negative value
% afterDelay = iddata([NaN(delaySamples,1); d_data.OutputData],...
% [d_data.InputData; NaN(delaySamples,1)], 1/Fs);
afterOffset1{i}.Tstart = y;
afterDelay1{i,1}= afterOffset1{i};
y= y+10;
end
%% Plot:
n = size(afterDelay1,1);
figure();
for i=1:1:n
subplot(2,2,i);
plot(d_data);
hold all
plot(afterDelay1{i});
end
sig_diff = angle(1)-afterDelay1;
square_error(i,:) = (sig_diff(i)).^2;
mse(i,:)= mean(square_error(i));
rmse(i,:) = sqrt(mse(i));
sig_diff = d_data_1 - afterDelay; % <<<<<<<<<<<<<<<<<<<<<< Problem is here
% square_error = (sig_diff).^2;
% mse= mean(square_error);
% rmse = sqrt(mse);
end
You most likely want the OutputData attribute from the iddata object which is the output or y signal of your problem:
sig_diff = angle(1)-afterDelay1.OutputData;
Also note that this will give you a column vector, but your code later on assumes it's a row vector. You may want to transpose this data after you perform the above calculation before proceeding:
sig_diff = angle(1)-afterDelay1.OutputData;
sig_diff = sig_diff.';
In general, iddata is a function that creates an object that represents input and output time or frequency domain data. Take note that when you create an iddata object, the input matrix can potentially have multiple sources and so each column dictates a source. The same can be said for the output where each column dictates an output. Therefore, it is very important that you transpose your data prior to using this function to ensure that each signal is in a separate column, or just use a single column to represent one input / output.
Inside the object has a variety of attributes, including the sampling time or sampling frequency, the valid domain and range that the function takes on and finally accessing the input and output data. OutputData is one of these fields. I'd recommend looking at the documentation that talks about all of the attributes that you can access with iddata. OutputData is clearly defined here: https://www.mathworks.com/help/ident/ref/iddata.html
I've tried to set a maximum execution time for matlab function, but none of them succeeded. I have a matlab file loading a model setting from COMSOL (using COMSOL with Matlab livelink).
%filename ‘mymodel.m'
fff = 0;
store{fff+1,1} = 'out1';
store{fff+1,2} = 'out2';
for i = 1:2
for j = 1:2
fff = fff+1;
%load Model parameter setting
model_parameter_script_file
if i == 1;model.param.set('x1',val1);end
if i == 2;model.param.set('x1',val2);end
if j == 1;model.param.set('x2',val1);end
if j == 2;model.param.set('x2',val2);end
try
%load model solution script from COMSOL
model_soulution_script_file
%store table calculated from the solution into 'store'
%catch null values
catch
store{fff+1,1} = 'null';
store{fff+1,2} = 'null';
end
end
end
The issue is that I cannot figure out a way to tell the computer to terminate the for loop if anyone one of them exceeds the maximum execution time. Is it possible to do with Matlab Parallel Computing Toolbox? This could be used to accelerate program execution, but not sure if it can kill a thread when it finds that particular job exceeds the maximum running time. Thanks a lot for your help in advance.
I have an extremely bizzare situation: I have a function in MATLAB which calls three other main functions and produces two figures for me. The function reads in an input jpeg image, crops it, segments it using kmeans clustering, and outputs 2 figures to the screen - the original image and the clustered image with the cluster centers indicated. Here is the function in MATLAB:
function [textured_avg_x photo_avg_x] = process_database_images()
clear all
warning off %#ok
type_num_max = 3; % type is 1='texture', 2='graph', or 3='photo'
type_num_max = 1;
img_max_num_photo = 100; % 400 photo images
img_max_num_other = 100; % 100 textured, and graph images
for type_num = 1:2:type_num_max
if(type_num == 3)
img_num_max = img_max_num_photo;
else
img_num_max = img_max_num_other;
end
img_num_max = 1;
for img_num = 1:img_num_max
[type img] = load_image(type_num, img_num);
%img = imread('..\images\445.jpg');
img = crop_image(img);
[IDX k block_bounds features] = segment_image(img);
end
end
end
The function segment_image first shows me the color image that was passed in, performs kmeans clustering, and outputs the clustered image. When I run this function on a particular image, I get 3 clusters (which is not what I expect to get).
When I run the following commands from the MATLAB command prompt:
>> img = imread('..\images\texture\1.jpg');
>> img = crop_image(img);
>> segment_image(img);
then the first image that is displayed by segment_image is the same as when I run the function (so I know that the clustering is done on the same image) but the number of clusters is 16 (which is what I expect).
In fact, when I run my process_database_images() function on my entire image database, EVERY image is evaluated to have 3 clusters (this is a problem), whereas when I test some images individually, I get in the range of 12-16 clusters, which is what I prefer and expect.
Why is there such a discrepancy? Am I having some syntax bug in my process_database_images() function? If more code is required from me (i.e. segment_images function, or crop_image function), please let me know.
Thanks.
EDIT:
I found the source of the problem. In my load_image function, after I call img = imread(filename), I convert the image to double: `img = im2double(img);'. When I comment this line out, I get the desired result. Anyone know why this happens? (and also how I can 'close' this question since I have located the problem).
clear all at the top of your function is unnecessary and may be the source of your trouble.
Also, turning off all warnings is a bad idea since it may mask other problems.
Let's look at this code, simplified by removing redundant code or unused code:
function [textured_avg_x photo_avg_x] = process_database_images()
type_num_max = 1;
img_max_num_photo = 100; % 400 photo images
img_max_num_other = 100; % 100 textured, and graph images
for type_num = 1:2:type_num_max %% 1:2:1 => 1
img_num_max = 1; %This nullfiies everything in the if block above anyways
for img_num = 1:img_num_max %% 1:1 => 1
[type img] = load_image(type_num, img_num); %% Input (1,1)
img = crop_image(img);
[IDX k block_bounds features] = segment_image(img);
end
end
end
It looks like this code runs through the double nested for loop exactly once, maybe that is why you get only one answer, three clusters.
Try calling your function on the command line with the same amount of return values as in the function you wrote. Instead of
>> segment_image(img);
Try:
>> [IDX k block_bounds features] = segment_image(img);
Functions in Matlab check how many return values are expected, and may behave differently depending on that.