How to generate signals for a Simulink's transfer function block in Matlab?
16 views (last 30 days)
Show older comments
Gianluca Mammone
on 11 Jun 2019
Commented: Gianluca Mammone
on 14 Jun 2019
Hello,
I'm trying to run a simulink project using the matlab command "sim()". This is a semplification of my simulink project
where, instead of 'simin' and 'simout' there are the names of the vars to import and export from the workspace.
Now I'd like to give to this system various input (step, waves, ramps etc) without using the Simulink blocks but directly from Matlab.
My question is: how can I create such mathematical functions?
I've tried this code for example:
x=0:0.1:1000
simin=cox(x)
sim('Simulation.slx')
but it give me the following error
Error using MatlabProject (line 47)
Error due to multiple causes.
Caused by:
Error using MatlabProject (line 47)
Error in port widths or dimensions. Output port 1 of 'Simulation/Sum4' has 10000 elements. This port does not accept the
dimensions (or orientation) specified by the output signal.
Error using MatlabProject (line 47)
Error in port widths or dimensions. Invalid dimension has been specified for input port 1 of 'Simulation/Plant1'.
where MatlabProject is the Matlab file and Sum4 is the sum block in the previous picture.
Can you please help me?
Thanks.
Gianluca
0 Comments
Accepted Answer
James Browne
on 12 Jun 2019
Greetings,
I believe I have a solution to your problem. First, in line 2 of your sample code, I believe there is a type as cox() is not a function that MATLAB recognizes (at least not my version). Perhaps you meant cos(x)?
I recreated your Simulink model and got it to work. So the second thing I found is that, when using the simin, the expected input signal needs to have time information associated with the input signal amplitude, if you hover over the simin finction block in the Simulink library, it will give you a description of the input data format, as shown in Figure 1.
Figure 1
Data trype description for simin function block
So the second problem is that, in your example code, you are inputing a set of amplitude values to Simulink but there is no time information associated with each amplitude value so Simulink can not generate an output. Below is an example of a modification of your original code which should help:
%Generate vector of time values
t = 0:0.1:1000;
%Transpose time values vector to be compatible with Simulink data input
%structure
t = t.';
%Calculate amplitude values for time vector input
y = cos(t);
%Combine time vector and amplitude vector to create the Simulink data
%structure
simin = [t,y];
%Call simulink model
sim('Simulation.slx')
%Plot Simulink model results
plot(simout)
It may not be very obvious from the code or the data type descrition in Figure 1, however, the data input type to the simin function block should look something like the following, where tn is the nth time value and yn is the nth amplitude value:
simin = [ t1, y1
t2, y2
t3, y3
... ...
tn, yn];
The output of the simout function block is a timeseriese, by default so it will have the same structure as simin, which means you can just plot it and see the results of the model with no further post processing!
As far as the different types of input signals goes, using the simin and simout function block method, you need to come up with a method for generating the amplitude values, based on a vector of time values, just as we did earlier, with the cos(t) function.
At this point, I should say that I am a beginner with MATLAB so there may very well be easier ways of creating the wave form data which you are talking about so you may want to look into that. That being said, here are a few examples for some basic input signal types:
For a ramp input:
function rampGen
%Choose start time of time vector
startTime = 0;
%Choose end time of time vector
endTime = 5;
%Choose time step increment value, this is effectively the sampling period
%of the input/output signals
dt = 0.01;
%Create time vector
t = startTime:dt:endTime;
%Transpose time vector for simin compatibility
t = t.';
%Choose the slope of the ramp signal
slope = 2;
%Choose offset of ramp signal
offset = 0;
%Create amplitude vector
y = slope*t + offset;
%Create simin data structure
simin = [t,y];
%Plot simin signal to check that it is correct (optional)
plot(simin(:,1),simin(:,2))
For a sine wave input:
function sinGen
%Choose number of cycles in sin signal
nCycles = 5;
%Choose frequency of sine signal (in Hz)
f = 3;
%Choose start time of time vector
startTime = 0;
%Choose time step increment value, this is effectively the sampling period
%of the input/output signals
dt = 0.01;
%Choose offset of sin signal
offset = 0;
%Calculate angular velocity of sine signal (in rad/sec)
omega = 2*pi*f;
%Choose amplitude of sin signal
amplitude = 2;
%Calculate period of sine signal
T = 1/f;
%Calculate end time value of time vector
endTime = nCycles*T;
%Create time vector
t = startTime:dt:endTime;
%Transpose time vector for simin compatibility
t = t.';
%Create amplitude vector
y = offset + amplitude*sin(omega*t);
%Create simin data structure
simin = [t,y];
%Plot ramp signal to check that it is correct (optional)
plot(simin(:,1),simin(:,2))
For a parabolic input:
function paraGen
%Choose start time of time vector
startTime = 0;
%Choose end time of time vector
endTime = 5;
%Choose time step increment value, this is effectively the sampling period
%of the input/output signals
dt = 0.01;
%Choose the order of the parabolic signal
order = 2;
%Choose offset of parabolic signal
offset = 0;
%Create time vector
t = startTime:dt:endTime;
%Transpose time vector for simin compatibility
t = t.';
%Create amplitude vector
y = t.^order + offset;
%Create simin data structure
simin = [t,y];
%Plot simin signal to check that it is correct (optional)
plot(simin(:,1),simin(:,2))
For a saw tooth input:
function sawGen
%Choose number of cycles of sawtooth signal
nCycles = 5;
%Choose frequency of sawthooth signal (in Hz)
f = 5;
%Choose start time of time vector
startTime = 0;
%Choose time step increment value, this is effectively the sampling period
%of the input/output signals
dt = 0.001;
%Choose offset of sawtooth signal
offset = 0;
%Choose amplitude of sawtooth signal
amplitude = 2;
%Calculate period of sawtooth signal
T = 1/f;
%Calculate end time value of time vector
endTime = nCycles*T;
%Calculate the slope of the sawtooth signal
slope = amplitude/T;
%Create time vector
t = startTime:dt:endTime;
%Transpose time vector for simin compatibility
t = t.';
%Calculate number of entries in the time vector
L = length(t);
%Preallocate memory fo amplitude values
y = zeros(L,1);
%initialize local time vector for sawtooth ramp calculation
tLocal = t;
%Calculate amplitude values
for i = 1:L
if (mod(t(i),T) == 0)
tLocal = t - t(i);
end
y(i,1) = tLocal(i)*slope + offset;
end
%Create simin data structure
simin = [t,y];
%Plot ramp signal to check that it is correct (optional)
plot(simin(:,1),simin(:,2))
Note: The code above for the sawtooth wave form generation prioritizes consistant signal slope and frequency at the cost of amplitude accuracy. The accuracy of the amplitude at the end of each period is dependant on the sampling time, dt, and frequency of the sawtooth signal.
Figure 2 shows a comparison of the output signal that is generated by the sawGen function, with various sampling periods (all other parameters are the same as in the example code, above). The reason for the amplitude inaccuracy is that the sawGen code terminates the ramp and resets the amplitude of the signal to zero on the last timestep of each period. There are certainly other methods of generating a sawtooth signal, probably some which are less sensitive to sampling period and frequency parameters but this is what I came up with.
The dependancy of amplitude accuracy on the wave form's frequency lies in the fact that for higher frequencies, there will be fewer time steps per wave form, for a given sampling period (dt). This also means that the slope of the ramp portion of the wave form will be higher (for higher frequencies) and the amplitude error, resulting from the final time step of the wave form period being zero instead of the final amplitude value, will be greater, for a given sampling period (dt). For this reason, a general rule of thumb for using this method of generating a sawtooth wave form is that higher wave form frequencies require higher sampling frequencies (lower sampling periods) to maintain amplitude accuracy.
Figure 2
Comparison of the effects of sampling period (dt parameter) on saw gen output signal
Note: Though not shown in the figure, a sampling period of dt = 0.3 will cause the frequency of the output signal to be half of what it should be. Additionally, if the sampling period parameter (dt) is not an integer multiple of the wave form's period, the sawGen function will not terminate reset the amplitude to zero at the end of the wave form's periods.
Figure two shows how the sawGen function prioritizes a constant slope at the cost of amplitude accuracy. Again, the accuracy of the amplitude of the output signal is dependant on the sampling period parameter, dt, and the frequency of the sawthooth wave form. Again, there may be easier ways of generating a sawtooth wave form (probably a built in function) but I like to make scripts and explore their limitations so there you go. As long as you keep your sampling period below 0.01 seconds, you should get a pretty good sawtooth wave form output.
For a square wave input:
function squareGen
%Choose time step increment value, this is effectively the sampling period
%of the input/output signals
dt = 0.001;
%Choose number of cycles of sawtooth signal
nCycles = 2;
%Choose frequency of sawthooth signal (in Hz)
f = 1;
%Choose start time of time vector
startTime = 0;
%Choose offset of sawtooth signal
offset = 0;
%Choose amplitude of sawtooth signal
amplitude = 2;
%Calculate period of sawtooth signal
T = 1/f;
%Calculate end time value of time vector
endTime = nCycles*T;
%Create time vector
t = startTime:dt:endTime;
%Transpose time vector for simin compatibility
t = t.';
%Calculate number of entries in the time vector
L = length(t);
%Preallocate memory fo amplitude values
y = zeros(L,1);
%Calculate amplitude values
for i = 1:L
if (mod(t(i),T/2) == 0)
amplitudeMod = offset;
end
if (mod(t(i),T) == 0)
amplitudeMod = amplitude + offset;
end
y(i,1) = amplitudeMod;
end
%Create simin data structure
simin = [t,y];
%Plot ramp signal to check that it is correct (optional)
plot(simin(:,1),simin(:,2))
Note: Just as with the sawgen function, the quality of the output signal of the squareGen wave form is dependant on wave form frequency and sampling period (dt). Additionally, similar to the sawGen function, the sampling period of the squareGen function must be an integer multiple of the wave form's period AND half of the wave form's period in order for the rising and falling edges to be properly generated.
Just as with the sawGen function, a good rule of thumb for the squareGen function is that higher frequency wave forms require higher sampling frequencies (lower sampling periods). Figure 3 shows how sampling period affects the quality of the output signal of the squareGen function (all other parameters are the same as in the sample code above).
Figure 3
Effects of sampling time on output of squareGen function
Note: Not shown in Figure 3 is the effect of having a sampling period that is not an integer multiple of the square wave form's period AND half of the square wave forms period. If the sampling period does not satisfy both of the wave form period requirements, one or both of the if statements in the for loop of the squareGen code will fail to detect the end or midpoint of a waveform's period and the output amplitude will not change appropriately as a result.
The dependancy of the sawGen and squareGen functions on sampling period being an integer multiple of wave form period (AND half of wave form period, for squareGen) could be eliminated by writing additional code which allows for some error in the detection of a time value of interest (end or midpoint of a waveform's period, in this case) but for simplicity's sake, I did not implement such methods here.
The good news is though, you can have Simulink do all of the work for you (and probably one or more other built-in MATLAB functions). If you open the Simulink library browser ( [ View ] => [ Library Browser ] ) you can access lots of different input signal types, sine, ramp and step are all in there and I am sure there is probably a generic wave form generator too but I am a beginer in Simulink so my knowledge is very basic.
Just as with the simin function block though, you can assign parameter values such as frequency and amplitude to the Simulink signal generators ( [ Simulink ] => [ sources ] in the Simulink Library Browser ). Figure 4 shows a modification of your original function block diagram in Simulink with a sine wave generator. Double clicking on the sine wave generator brings up the window, shown in Figure 4, where you can assign parameters of the signal generator to values from your workspace. In figure 4, I have the values for "omega" and "Ampl" set in my base workspace. When you start typing in the variable name to one of the value fields in Simulink, you will see your parameter from your base workspace as an option that you can click on. In Figure 4, I had just started typing the word "omega" into the frequency field and as you can see, the dropdown menu with the variable name and workspace location appeared. This is a very useful feature!
Figure 4
Selecting parameters for sine wave generator from base workspace
The nice thing about using function blocks in Simulink to generate the data for you, is that, once you have your signal generator parameters set in Simulink, all you need to do is call the simulation from MATLAB and you are done! No need to reinvent the wheel (although sometimes it is fun to reinvent the wheel, to each their own).
For example, for the Simulink model shown above, the only code needed to get the response of the system is the following:
Ampl = 5;
omega = 3;
t = 0:0.01:10;
sim('Simulation.slx',t)
plot(simout)
You can also set the simulation time parameters in the Simulink model (though I do not remember how, just off the top of my head) so that you do not ave to feed the simulation a time vector.
Additionally, there is a method for accessing the workspace of a Simulink model from inside a function, which can also be useful. I do not recall how to do that off the top of my head either but I did write a function which accessed the workspace of a Simulink model about six months ago so I know that it can be done~
Hope that helps and good luck!
More Answers (0)
See Also
Categories
Find more on Signal Generation in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!