Using matrixes in functions

18 views (last 30 days)
MA
MA on 15 Nov 2017
Answered: Sairam on 24 May 2023
Hi,
I am trying to make a function that will generate a torque speed curve of a AC induction motor. Problem seems to be involved with using matrix as a input variable. Se function below:
function [torque1,torque2,torque3,torque] = computeTorque(x,y)
torque1=11860*1.37+(x./x)-1;
torque2=11860*1.37*94.248./x;
torque3=11860*94.248*188.5./x.^2;
if x<y
torque=torque1;
else
torque=torque2;
end
end
speed range of motor is set from 1-->241 rad/s, which again is set to be input "x" in my function. When i run function I use matrix "Omag" from workspace which is a 2401,1 row matrix (1-241 with steps of 0.1).
"y" variable is the field weakening frequency of the motor which is set to be 94.2. When running function i use y matrix from workspace, which is just a row vector with same size as "Omag" and contains the field weakening frequency. This value is used to compare "Omag" matrix to make sure that below this frequency the torque is equal to maximum torque(Tnom*overload factor).
Command window to run function and plot:
>> [torque1,torque2,torque3,torque]=computeTorque(Omag,y);
>> plot(Omag,torque)
The thing is, that if I put in a scalar speed value for "x" variable, the function gives out a correct single torque value based on speed [rad/s]. The problem is using the Omag row matrix as "x" variable
See attached files, together with a screen shoot on how the plot should look like
Please adwise Marius
  1 Comment
Stephen23
Stephen23 on 15 Nov 2017
"Please advise"
Using if will not help you. You should use logical indexing.

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 15 Nov 2017
Edited: Stephen23 on 16 Nov 2017
Much simpler would be to just use min to pick the output values. Then all you need is this:
function [torque,mat] = computeTorque(x,fw)
mat = fw*[1.37./x; 188.5./x.^2];
mat(3,:) = 1.37;
torque = 11860*min(mat,[],1);
end
and tested:
>> x = 1:0.1:241;
>> y = computeTorque(x,94.248);
>> plot(x,y)
This is how MATLAB code should be: simple, neat, efficient, and vectorized:

More Answers (3)

KL
KL on 15 Nov 2017
Edited: KL on 15 Nov 2017
I'm not sure what you're trying to do with your if else condition in your function, but if you want assign torque1 and torque2 to torque based on the values of x and y, you probably can just use the logical vector you get when you compare x and y. For example,
res = x<y; %this is logical vector, 1 if the condition is true i.e. x(n)<y(n)
torque = zeros(size(x)); %pre-allocate
now use res to assign torque1 and torque2 to torque,
torque(res) = torque1;
torque(~res) = torque2; % ~ meaning "else"
is this what you want?
  3 Comments
Stephen23
Stephen23 on 15 Nov 2017
Edited: Stephen23 on 15 Nov 2017
@Marius Sæther: you code is very complex for such a simple task. You also have several "features" that should be avoided, such as hardcoding the size of y inside the function, and defining the field-weakening as a variable but also using the same value hard-coded in the calculations.
See my answer for a much simpler solution.
KL
KL on 16 Nov 2017
Edited: KL on 16 Nov 2017
Hi Marius, you're unneccesarily complicating some things. For example, y in your case is clearly a constant scalar (meaning just a single value throughout your length). To compare it with x, you do not need another vector.
For example,
x = rand(10,1);
y = 0.5;
res = x<y
res =
10×1 logical array
1
0
0
1
0
1
1
0
0
0
You can simply use this logical vector to index x, if you want to get the values of x that are smaller than y ("our condition for res)),
x(res)
ans =
0.1576
0.4854
0.1419
0.4218
Another thing I noticed is, you're doing x./x, if you do it to our example here,
x./x
ans =
1
1
1
1
1
1
1
1
1
1
So you simple, get ones and then you subtract 1 from them, which means simply zeroes. Why?, this is unnecessary.
Also you were better off passing y as a parameter as you did in your first approach, it's not a good idea to define them inaide a function. Then if the 94.248 in your torque is the same variable, then use it, if not define it and pass it as another variable, like y_something.
Next thing, is when you get a logical vector (res in this example, res1,2,3 in your code), you don't need to multiply it with your vector. You calculate 3 torques (name them better than just 1,2 or 3), fine now assign it to torque directly, for example,
torque(x<y) = torque1(x<y); %and so on
Hope this helps!

Sign in to comment.


MA
MA on 16 Nov 2017
Hi
A lot of good information here. Approached the problem the way Stephen recomended. The only problem using the min function, is when you get negative torque values. If I wanted to make a graph that displays the torque in all four motor quadrants, it would display the values furthest away zero point when getting negative torque(want to get torque closest to zero). Not sure if there is any function that returns the value closest to zero from a matrix?.
Anyway, have done som changes to the code to make it work for all four quadrants. Maybe not the most efficient. If anyone have a more efficient way of approach, please advice.
Have added updated code,workspace, and plot. Blue line in plot, is from a real life test.
New code:
function [torque,AccDir]=computeT(w,O1,O2,Tnom,ft)
w1=diff(w);% used to determine acceleration direction
w2=ones(1,1);% help constant to make matrix same size a w1(looses one row due to "diff" function)
w3=horzcat(w1,w2); % making w3 same size as w1
AccDir=sign(w3); % this matrix is used to give torque correct sign
AccDir(AccDir==0)=1; %replace any zeros in matrix with one
%%Now we have a matrix "AccDir", that determines Torque sign in all four
%%AC motor operational quadrants
eq1=[AccDir.*abs(Tnom*ft*O1./w);AccDir.*abs(Tnom*O1*O2./w.^2)]; %%abs value is taken, beause we only want the "AccDir" matrix to determine the torque sign
eq1(3,:)=AccDir.*Tnom*ft;
torque1=min(eq1,[],1);%%extracting lowest values
eq2=[AccDir.*abs(Tnom*ft*O1./w);AccDir.*abs(Tnom*O1*O2./w.^2)];%%abs value is taken, beause we only want the "AccDir" matrix to determine the torque sign
eq2(3,:)=AccDir.*Tnom*ft;
torque2=max(eq2,[],1);%Extracting highest values
AccDir1=AccDir>0;% Creating logical matrix to be used to extract torque values from 1st and 4th motor operational quadrant from "torque1" matrix
AccDir2=AccDir<0;% Creating logical matrix to be used to extract torque values from 2nd and 3rd motor operational quadrant from "torque2" matrix
torque3=torque1.*AccDir1;%multiplying with logical matrix. In this way, we are only left with the torque values we actually want.
%When torque is negative(3rd and 4th quadrant), we cant extract the min values, since the max
%values is the closest ones to zero, which again is what we want in our
%plot
torque4=torque2.*AccDir2;%multiplying with logical matrix. In this way, we are only left with the torque values we actually want.
torque=torque3+torque4;
end
regards marius
  1 Comment
Stephen23
Stephen23 on 16 Nov 2017
@Marius Sæther: using abs and sign seems to be a reasonable way to deal with all four quadrants.
Note that you should accept the answer that helped you most with your original question. This is the easiest way for you to say "thank you" to the volunteers who helped you.

Sign in to comment.


Sairam
Sairam on 24 May 2023
function [torque1,torque2,torque3,torque] = computeTorque(x,y) torque1=11860*1.37+(x./x)-1; torque2=11860*1.37*94.248./x; torque3=11860*94.248*188.5./x.^2; if x<y torque=torque1; else torque=torque2; end end

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!