MATLAB / Simulink: Simulation of a motor control valve - matlab

Problem description:
I want to simulate a motor control valve (MCV) with Matlab / Simulink. A control-singal (red) controls the MCV, which can take every value between 0% (completely closed) and 100% (completely open):
I indicated the three different pulses of the input-signal with 1, 2 and 3. As soon as the input-signal changes from 0 to 1 (rising edge), the MCV starts to opens. After time t_Op, the MCV is completely opened. As soon as the input-signal changes from 1 to 0 (falling edge), the valve starts to close. This process is finished after t_Cl. Please note that t_Op and t_Cl do not neccesarily have to be identical.
As you can see in the diagram, the valve gets completely closed after pulse no. 1 (falling edge). However, the width between pulse no. 2 and pulse no. 3 is not long enough to completely close the valve. At the rising edge of pulse no. 3, the valve opens again until it is completely open.
Question:
I want to simulate the process described above with Matlab (prefered) or Simulink. I am not a 100% sure how to get started with that problem. I thought about extracting rising / edges from the original system and use this "triggers" to initiate some time-dependent, "sloped"-step-function. Maybe you have some hints for me?

To simulate this, you need to define:
1) Time resolution (0.1 s? 0.01s?)
2) Valve resolution (probably 1%)
3) How to quantize your control signal (If it's just 0 or 1, this is already done; if it's 0V -> 5V, you need to pick which values become off, which become neutral, and which become on
If you quantize your data to 0.1 seconds, and quantize the valve resolution to 1%, you can use something similar to the following (you should be able to fill in the %%% sections yourself
pos_initial = 0; % percent, position
t_res = 0.1; % seconds
pos_res = 1; % percent
%%% Declare t_op, t_cl. Solve for open_speed and close_speed If you have t_op and t_res, how can you solve for the open_speed (the amount of opening in a single step? Do the same for close_speed %%%
position(1) = pos_initial;
for ii = 2:length(input)
if(input == 1)
position(ii) = min(position(ii-1) + open_speed, 100); %this makes potition get bigger, but doesn't let it get bigger than 100%
else
%%% Looking at the position(ii) line above, how could you do the same for closing to make sure it doesn't go below zero?
end
end

Related

Simulation tool cannot recognize if pulse width smaller than delay cell in verilog

I am using VCS tool to verify for 1 AND logic cell.
I set the 2 inputs = 1 (pulse signal) with pulse width is 25ps.
Delay cell define in verilog model of cell AND is 26ps.
Because pulse width = 25ps < delay cell = 26ps so output is always 0 even that 2 input equal 1 during 25ps.
I want to ask in the real chip, Whether we can detect this pulse or not ?
Anybody can help me.
output should equal 1 for about 25ps.
VCS (and other simulators) have switches to control how they handle these situations.
Look at +pulse_e, +pulse_r, as well as things like +transport_int_delays, +transport_path_delays, +pulse_on_event, +pulse_on_detect, and +delay_mode_*, etc.
You can have the simulator propagate that short pulse (25 < 26). You can have it propagate 1'bx, or you can have it swallow it and propagate nothing.

Proportional Control Matlab

I am working on a boiler project in matlab with a partner. We are still new to this program and are currently working on the proportional control part of the boiler program. As a result we get 3 graphs like we are supposed to but we keep getting a mysterious dip on our center graph as seen below. Any diagnosis to the problem on how we can get rid of the dip is what we have been trying to figure out.
Here is our code:
clear all;
close all;
endtime=60;
time=0;
ResPer=0.05; %declares basic functions
setpoint=7;
flowrate=2.4;
valveposition=0.2;
delay=5;
timeaxis=[1:endtime];
valveaxis=0; %declares arrays related to time and graphing
steamaxis=0;
propconstant=0.25;
RelError=0; %declares arrays regarding the proportional controller
desiredvalve=0.5823;
while time<endtime
%RelError=SteamRelativeError(flowrate, setpoint);
%calculates the Relative Error used in the rest of the function
if (time <= delay)
valveposition=0.75*valveposition+0.25*(desiredvalve-propconstant*RelError);
%deals with the valve position before the time exceeds the delay
%valveaxis(time)=valveposition;
else
valveaxis(time-delay)=0.75*valveposition+0.25*(desiredvalve-propconstant*RelError); %calculates and stores valve position after the delay has been passed
end
RelError=SteamRelativeError(flowrate, setpoint); %calculates the Relative Error used in the rest of the function
time=time+1; %increments time
flowrate=ValvePerToFlowRate(valveposition); %calculates flow rate from valve position
valveaxis(time)=valveposition; %stores temporary valve position
steamaxis(time)=flowrate; %stores steam flow rate
erroraxis(time)=RelError; %stores the Relative Error
end
subplot(3,1,2), plot(timeaxis, valveaxis, 'b'); axis([0 endtime 0.2 0.8]);
xlabel('Time(min)'); ylabel('Valve%');
subplot(3,1,1), plot(timeaxis, steamaxis, 'b'); axis([0 endtime 2
setpoint+2]); xlabel('Time(min)'); ylabel('Steam mass flow rate (lbm/s)');
title('Proportional Constant=0.25'); %graphs functions
subplot(3,1,3), plot(timeaxis, erroraxis, 'b'); axis([0 endtime -0.6 0.2]);
xlabel('Time(min)'); ylabel('Error');
And here are our graphs:
The dip is occurring because you set valveaxis in two difference places. In your if else block you set it to:
valveaxis(time-delay)=0.75*valveposition+0.25*(desiredvalve-propconstant*RelError);
However outside of this block you set it to:
valveaxis(time)=valveposition;
At each time the valveaxis is set using the second equation, only to be overwritten by the first formula delay iterations later. The very last values will not get overwritten since you break at time==60, so valveaxis(54) will be the last value set by the first formula. This is why your dip occurs between the 54th and 55th values.

Matlab: Execute the loop until the specified conditions are met

Recently came across a simple issues that I could not solve on my own. I have a Simulink model that uses a matlab function for some calculations inside the model. The idea is that at some specified moment of time I need to change the voltage of an electric drive. And I need to change it until the rotor’s position reaches another specified value. For instance:
If control_signal == 1; (command to start the execution);
While Angle ~= 180 \\ desired angle is 180;
Control voltage = 5 - 0.1 (5V is the initial value, while the increment of
the voltage change is 0.1)
End
end
So technically what I was thinking will happen, is that the cycle will be executed until the angle of 180 is reached, at some value of the control voltage (for instance 4.6). But when I am running this code, Simulink can’t execute the model. So without any warning or errors, simulation freezes at some stage (when the main condition kicks in). So looks like it can’t process further when the cycle’s execution starts. Can somebody help me with the code? Because the described behaviour of the model during simulation is definitely caused by the above mentioned code.
Thank you in advance.
My guess is you convert the value of the angle expressed in radians to degrees, and you calculate the angle beforehand using trigonometry functions - it will never reach precisely 180 degrees. You should choose some epsilon such that 180 - epsilon is close enough to 180 for your application and use that value as your loop condition.
Also, based on your description of the problem you are trying to solve, sounds like you actually want to check whether the angle is not greater than 180, not if it equals 180.
Also, you are incrementing your voltage incorrectly. Everytime you enter the loop, your control_voltage variable equals 5 - 0.1, which means it's constant and will equal 4.9 no matter how many times you run that loop. This is the correct way:
control_voltage = 5; % initial value
if control_signal == 1; (command to start the execution);
while Angle ~= (180 - epsilon) % some epsilon of your choice
control_voltage = control_voltage - 0.1; % now it's smaller by 0.1 every time the loop is run
end
end

Hold constant signal

I have the model of a dynamic system in Simulink (I cannot change the programming framework). It can be described as an oscillator subject to periodic oscillations. I am trying to control its motion, in particular, to maximize it (for energy generation).
With latching control (a popular control strategy), the idea is to 'latch', i.e. lock in place, the device when its velocity is 0 for a predefined time, and then release it until its velocity reaches 0 again.
So, what I need to do in Simulink is to output a signal 1 once the velocity signal reaches (or is close to) 0, hold it constant for a time period (at 1), then release it (the signal becomes 0), and repeat the process once the velocity reaches 0 again.
I have found a good blog on holding signals constant in Simulink:
http://blogs.mathworks.com/simulink/2014/08/06/how-do-you-hold-the-value-of-a-signal/
However, in my case, I have two conditions for determining the signal: the magnitude of the velocity and the time within the time period. Now, the problem is that as soon as the period is finished, and the device is released (signal = 0), the velocity is still very small, which could result in an incorrect signal of 1 if an if-loop is used.
I think using an S-function may be the best solution, but then I will have to use a fixed time-step. Are there any Simulink-native solutions for this problem?
I ended up using a Matlab function as a temporary solution, and it is very effective. I have taken inspiration from https://uk.mathworks.com/matlabcentral/answers/11323-hold-true-value-for-finite-length-of-time
u is the velocity signal.
function y = fcn(u,nlatch)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This function is used to determine the latching signal.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Using persistent memory:
persistent tick started sign;
% Initialize variables:
if isempty(tick)
tick = 0;
started = 0;
sign = (u>0);
end
U=0; % no latching
s=(u>0);
if s~=sign
started = 1;
end
if started
if tick<nlatch
tick=tick+1;
U = 1;
else
tick = 0;
started = 0;
sign = s;
end
end
y = U;
end
However, as I mentioned, I have to use a fixed step solver, which is no big deal to me, but it can create problems to other users.
If anyone has a more "Simulink-native" solution, please let me know!
Edit
I have now modified the function: the latching is now applied when there is a change in sign in the velocity signal rather than looking at a small magnitude as earlier on (abs(u)<0.005), which was too case-specific.
A colleague of mine has also found a Simulink-native solution:
However, the Matlab function is faster (less computing intensive) when the same time step is employed. Maybe the least computing-intensive solution is a C S-function.

Scope for improvement in this code

I have written the following code in MATLAB to process large images of the order of 3000x2500 pixels. Currently the operation takes more than half hour to complete. Is there any scope to improve the code to consume less time? I heard parallel processing can make things faster, but I have no idea on how to implement it. How do I do it, given the following code?
function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['#' subfn]); % Function handles
I2 = uint8(nlfilter(I, [7 7], fh));
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');
% Zero Degree Variogram
function [gamma] = ewvar(I)
c = (size(I)+1)/2; % Finds the central pixel of moving window
EW = I(c(1),c(2):end); % Determines the values from central pixel to margin of window
h = length(EW) - ld; % Number of lags
gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end
The input lag distance is usually 1.
You really need to use the profiler to get some improvements out of it. My first guess (as I haven't run the profiler, which you should as suggested already), would be to use as little length operations as possible. Since you are processing every image with a [7 7] window, you can precalculate some parts,
such that you won't repeat these actions
function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['#' subfn]); % Function handles
%% precalculations
wind = [7 7];
center = (wind+1)/2; % Finds the central pixel of moving window
EWlength = (wind(2)+1)/2;
h = EWlength - ld; % Number of lags
%% calculations
I2 = nlfilter(I, wind, fh);
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');
% Zero Degree Variogram
function [gamma] = ewvar(I)
EW = I(center(1),center(2):end); % Determines the values from central pixel to margin of window
gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end
end
Note that by doing so, you trade performance for clearness of your code and coupling (between the function dirvar and the nested function ewvar). However, since I haven't profiled your code (you should do that yourself using your own inputs), you can find what line of your code consumes the most time.
For batch processing, I would also recommend to leave out any input, imshow, imwrite and uigetfile. Those are commands that you typically call from a more high-level function/script and that will force you to enter these inputs even when you want them to stay the same. So instead of that code, make each of the variables they produce (/process) a parameter (/return value) for your function. That way, you could leave MATLAB running during the weekend to process everything (without having manually enter to all those values), even if you are unable to speed up the code.
A few general purpose tricks:
1 - use the MATLAB profiler to determine all the computational bottlenecks
2 - parallel processing can make things faster and there are a lot of tools that you can use, but it depends on how your entire code is set up and whether the code is optimized for it. By far the easiest trick to learn is parfor, where you can replace the top level for loop by parfor. This does mean you must open the MATLAB pool with matlabpool open.
3 - If you have a rather recent Nvidia GPU as well as MATLAB 2011, you can also write some CUDA code.
All in all 30 mins to me is peanuts, so don't fret it too much.
First of all, I strongly suggest you follow the advice by #Egon: Write a separate function that collects a list of files (the excellent UIPICKFILES from the FEX is your friend here), and then runs your filtering code in a loop for each image. Note that you should definitely keep the call to imwrite in your filtering code: In case the analysis crashes at image 48 (e.g. due to power failure), you don't want to lose all the previous work.
Running thusly in batch mode has two big advantages: (1) you can start running your code and go home for the week-end, and (2) you can easily parallelize this outside loop using PARFOR. However, with only a dual-core machine, it is unlikely that you get any significant improvements from parallelization - your OS also wants to run stuff at times, and the overhead of parallelization might be more than the gain from running two workers. Also, 2.5GB of RAM is seriously limiting.
As to your specific code: in my experience using IM2COL is often faster than NLFILTER. im2col creates a nElementsInMask-by-nMasks array out of your image, so that you can apply the filtering in one single operation. With a 7x7 window, the output of im2col will be 3000*2500*49 bytes, which is close to 400MB. Thus, it should just work. All that you need to do is rewrite ewvar so that it works on a 49x1 array of pixels that make up the pixels your mask, which will require some index juggling, if I understand your code correctly.