Implementation of custom counter logic in SIMULINK - counter

I am trying to implement a counter logic in SIMULINK where
in1, in2 are inputs
out1 is the output
if in2 = 0, out1 = 0;
if in2 = 1, out1 = 1 after x high edges of in1
I have tried using "Detect Rise Positive" block but failed miserably because I don't have sufficient experience of implementing a timing diagram correctly in SIMULINK. Could anyone kindly point me to the right direction?
Update
An approach I have taken since I posted this question is the "Triggered and enabled subsystem". I am trying to set it up so that:
in2 becomes the enable signal
in1 becomes the trigger
in2 becomes the intput to the subsystem
Out1 becomes the output of the subsystem
But I think that the above was rubbish. Unfortunately it is not VHDL where I could have implemented it using 4-5 lines of description of the hardware logic.

Using a Triggered and Enabled subsystem is the right approach, but your inputs (and no doubt what's inside the subsystem) needs to be modified.
Don't have any input to the subsystem (other than the trigger and enable signals).
Inside the subsystem,
set the enable block property to reset the state when disabled.
set the outport property to reset when disabled and give the initial condition as 0.
create a counter out of a constant (value=1), a summation and a unit delay block.
feed the counter into a Compare to Constant block set to the 'x' value in your question.
feed that block to the outport.
When enabled, the counter should count the required number of steps (when triggered) before the output goes high.

A counter logic can be implemented very easily in simulink. Take a switch,give the control input as int1. If int1 is 1 ur output shuld be 0 else take another switch give its control input as int2. if int2 is 1 ur output shuld be 1+ previous value given in feedback funit delay block

Related

if statement block in Simulink accumulates last true value

If statement in Simulink is not like in a programming language, it accumulates last true value untill it occurs again.
As it can be seen here, when random value is lower than 0.5 (if condition) output dosn't give zero as one normally expects from if statement.
What is the proper way to use an if? (Where preferably I don't want to put saturation and matlab function)
The Out block within the If Action subsystem has a property to either hold or reset its output when disabled. The default is to hold; you want it to reset. You'll also need to specify 0 as the initial condition, which is what it'll reset to.
So far what I could do this to use an elementary matlab function;
function y = fcn(u)
if u>0
y = u;
else
y = 0;
end
end
but I wondered it would be a proper way of using if block.
Change out blocks property in If action subsystem to 'reset', it looks like it is 'held' in your current implementation

Updating value in Simulink

I am currently working on a spacecraft body with actuator, and given the equation below:
J·w_dot = -w^x·J·w + u (1)
where w^x is actually a notation of 3x3 matrix
[ 0 -w3 w2
w3 0 -w1
-w2 w1 0]
By rearranging (1), I got w_dot = (-w^x·J·w + u)/J. And here I face the problem, I need to update value constantly for w_dot but I have no idea how. I have tried the Memory block but it only update every 0.2 seconds which is not appropriate for the system.
This is my current setting:
I was thinking the integrator block could be the one to be updated every single cycle as initial condition could be set.
Yes, your solution seems about right; the integrator block will cause the system to be continuous-time, rather than discrete-time. This will output results as accurately as Simulink can accomplish.
You can set initial values for the integrator by double-clicking on the integrator block, setting the "Initial condition source" to "external", then connecting another input or constant block, output, or whatever else you want providing the initial value.
By the way, is J is the inertia tensor? In that case, you can't simply "divide" by it; you should multiply by its inverse (setting "Matrix" as the "Multiplication" option in the Divide block's options)

Change a constant in ODE calculations under particular conditions with a flag

I have an ODE for calculating how acidicity changes. Everything is working just fine, only I would like to change a constant whenever acidicity reaches a critical point. It is supposed to be some kind of irreversible effect I wish to simulate.
My constants are coming from a structure file (c) I load once in the ODE function.
[Time,Results] = ode15s(#(x, c) f1(x, c),[0 c.length],x0,options);
The main problem I have here is not telling Matlab to change the constant but remember if it happened already during the simulation once. so Matlab should take the irreversibly changed constant rather than the one I supply at the beginning.
I would like to write a flag that is saved while the ODE is running and an if condition, "if flag exists, change constant". How to do that?
UPDATE I:
PROBLEM SOLVED
Here a first own solution, it is not polished and requires a structure file approach. Which means, the constants which should suddenly changed upon an event, must be struct files which are handed in the ODE function into the function that should be evaluated (look above for the ODE syntax). The function accepts the inputs like this:
function [OUTPUT] = f1(t, x, c)
% So here, the constants all start with c. followed by the variable name. (because they are structs instead of globals)
%% write a flag when that event happens
if c.someODEevent <= 999 && exist ('flag.txt') == 0
dlmwrite ('flag.txt',1);
end
%% next iteration will either write the flag again or not. more importantly, if it exists, the constant will change because of this.
if exist ('flag.txt') == 2
c.changingconstant = c.changingconstant/2;
end
end
Please look into Horchlers kind answer where you have to take care that such a step may introduce inaccuracies and you have to be careful to check if your code does what it is supposed to do.
To do this accurately, you should use event detection within the ODE solver. I can't give you a specific answer because you've only provided the ode15s call it in your question, but you'll need to write an events function and then specify it via odeset. Something like this:
function acidity_main
% load c data
...
x0 = ...
options = odeset('Events',#events); % add any other options too
% integrate until critical value and stop
[Time1,Results1] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
x0 = Results(end,:); % set new initial conditions
% pass new parameters -it's not clear how you're passing parameters
% if desired, change options to turn off events for faster integration
[Time2,Results2] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
% append outputs, last of 1 is same as first of 2
Time = [Time1;Time2(2:end)];
Results = [Results1;Results2(2:end,:)];
...
function y=f1(x,c)
% your integration function
...
function [value,isterminal,direction] = events(x,c)
value = ... % crossing condition, evaluates to zero at event condition
isterminal = 1; % stop integration when event detected
direction = ... % see documentation
You'll want to use the events to integrate right to the point where the "acidicity reaches a critical point" and stop the integration. Then call ode15s again with the new value and continue the integration. This may seem crude, but it how this sort of thing can be done accurately.
You can see an example of basic event detection here. Type ballode in your command window to see the code for this. You can see a slightly more complex version of this demo in my answer here. Here's an example of using events to accurately change an ODE at specified times (rather than your case of specified state values).
Note: I find it strange that you're passing what you call "constants", c, as the second argument to ode15s. This function has strict input argument requirements: the first is the independent variable (often time), and the second is the array of state variables (same as your initial condition vector). Also if f1 only takes two arguments, #(x,c)f1(x,c) is superfluous – it's sufficient to pass in #f1.

Is there a way to enforce the simulation step to be smaller than a compile-time constant in simulink?

Question
Is there a way to enforce the simulation step to be smaller than a compile-time constant in a simulink model?
Context
I'm trying to build a PWM block on simulink. As it is now, I have to make sure that the user chooses a step size responsibly (smaller than half the period chosen by him), otherwise the block behaves abnormally. The only way I came up was to stop the simulation if the step size is not small enough, but I find that very annoying (as a user). If possible, I'd like for the user to not worry about this at all.
Here's what I would do: add the following pseudo-code to the block callback StartFcn:
T_PWM = get_param(gcb,...); % get the block parameter (period) of the current PWM block (string)
T_PWM = str2double(T_PWM);
T_solver = get_param(bdroot,'FixedStep'); % get fixed used by the solver (string)
T_solver = str2double(T_solver); % convert from string to double
if T_solver > 0.5*T_PWM
error('Solver step size must be smaller than half the PWM period')
end

Rising or Falling Edge-Triggered Delayer for SIMULINK models

My Problem
I want to model a block called "confirmer". The specification is that the output will SIMPLY be the delayed version of input based on an edge (rising/falling). To clarify, I will try to put the timing diagrams below:
___________________________
| |
Input _______| |____________________________
(Tdelay) _____________________
| |
Output ______________| |____________________________
And
____________________________
| |
Input _______________| |____________________________
(Tdelay)
______________________________________
| |
Output _______________| |_____________________
As I tried to draw above, the rising edge means that my output will simply follow the change input after Tdelay. But when it changes back from 1 to 0, there is no delay. This is the diagram for a confirmer block that is rising edge triggered.
For a falling-edge triggered confirmer, it is the opposite. When there is a falling edge, the output will follow the change in input after Tdelay seconds i.e. hold the last input for Tdelay.
My Target Platform
SIMULINK and MATLAB.
My initial solution
I know that there is way to trigger for certain actions by using a triggered subsystem block. But I am struggling to use the delay/unit-delay block in SIMULINK to implement the delay with the trigger. I have managed to use another block called resettable delayer but it does not work properly when it is a rising-edge reset; it simply resets based on an edge.
Has anyone tried this kind of problem before?
Update since #PhilGoddard's answer
I think this should work as I have managed to reproduce the timing diagrams in the question.
How I designed it:
1) Used the repeating sequence stair as my input.
2) configured the unit delay block such that the reset is enabled at rising edge or fallling edge. This will allow either of the following"
i) Input (falling edge) = Output (falling edge) [rising edge is delayed by Tdelay
ii) input (rising edge) = Output (rising edge) [failling edge is delayed by Tdelay]
Unless I am losing my marbles, I think that this solution is okay?
Use an Enabled and Triggered Subsystem.
Drag that block from the Ports and Subsystems library, and make only two changes to its properties: Open the subsystem, open the outport (called Out1), and change the "Output when disabled" property to "reset" and the "Initial Output" to 0.
Then, feed your input into the enable port; feed a delayed version of your input into the trigger port (which by default is set to be rising edge); and feed a constant block (with value=1) into the signal inport.
The output of the subsystem should be as desired.
This is my solution for case 2 of the proposed problem. The output is the sum of two signals of opposite value which is increased at every rising or falling edge of the trigger signal. It is very likely an overkill and there is probably a much easier solution but the proposed solution did not work for me and this did.
My solution:
How the counter is created (credit to How to create a counter in simulink):
Try On/Off delay. It perfectly meets your demand.
(There should be its icon but It seems that I cannot post image with under 10 reputation)
The description from the help page says:
The On/Off Delay block implements the following logic when the Select type parameter is set to On delay:
When the input becomes true, the output becomes true after a preset time delay. The output remains true as long as the input is true.
When the input is false or becomes false, the output becomes false with no delay.
When the Initial condition of previous input parameter is set to 1, and the input is true at t = 0, the output is true with no delay.
The On/Off Delay block implements the following logic when the Select type parameter is set to Off delay:
When the input becomes false, the output becomes false after a preset time delay. The output remains false as long as the input is false.
When the input is true or becomes true, the output is true with no delay.
When the Initial condition of previous input parameter is set to 0, and the input is false at t = 0, the output is false with no delay.
falling edge delay
rising edge delay