S curve ramp function

56 visualizaciones (últimos 30 días)
David Cole
David Cole el 17 de Mayo de 2025
Respondida: Sam Chak el 28 de Mayo de 2025
I need help creating a function for an s curve ramp. The code below will create the inserted picture below. However, this code only works for a constant ramp block (connected to x). This code from the piecewise function on the Matlab smf() help file page.
I need two additional inputs (acceleration rate and jerk rate). The output should ramp the input velocity (x) signal based on the acceleration rate (a), and jerk rate (j). I need the block or code to be dynamic. I do not want to put a time value inside of my code. I will be exporting the code to structure text and input the code into a Siemens PLC.
I don't want to include a fixed dt in my code because I will be running the code in a PLC. Maybe it would be better to design this function in simulink and set a fixed time solver and use integrator blocks?
x = 0:0.01:10; % domain
a = 1; % unsaturated interval's left endpoint
b = 8; % unsaturated interval's right endpoint
y = smf(x, a, b);
plot(x, y), grid on
xline(a, '--')
xline(b, '--')
title("S-curve piecewise function")
xlabel("x")
ylabel("Amplitude")
ylim([-0.05 1.05])
%% S-curve piecewise function
function y = smf(x, a, b)
m = (a + b)/2;
y = (x > a & x <= m) .* ( 2*((x-a)/(b-a)).^2) + ...
(x > m & x <= b) .* (1-2*((x-b)/(b-a)).^2) + ...
(x > b);
end
  4 comentarios
David Cole
David Cole el 17 de Mayo de 2025
I am working on a PLC and VFD project. My PLC does not have a native s curve block that will take in a continous signal and output a continous signal. For example, the PLC might receive a speed (velocity) signal of 10 m/s from an initial speed of 0 m/s. I need the PLC to generate a signal that goes from 0 to 10 and follows an s curve. The equipment will have an acceleration limit (m/s^2) and and jerk limit (m/s^3). I need the s curve to take both of these limit into consideration a produce a s curve that will ramp the speed from 0 to 10 m/s (as an example). The goal is to produce the code in Simulink to observe the correct behavior and then export to code so it can be used in the PLC.
John D'Errico
John D'Errico el 17 de Mayo de 2025
Editada: John D'Errico el 17 de Mayo de 2025
Ah. You have a limit on acceleration AND jerk. Note that the set of curves that satisfy such a constraint will require nonlinear bounds on the curve. It should not be too difficult though.

Iniciar sesión para comentar.

Respuestas (2)

Sam Chak
Sam Chak el 18 de Mayo de 2025
This might not be what PLC users like to do.
%% 99% Math-free Jerk-based Velocity
% parameter
c = 1e-3; % control parameter for accuracy purposes
% Velocity and Jerk settings
Vref = 10; % desired velocity (specified by PLC user)
Jlimit = 40/49; % Jerk limit (specified by PLC user)
Jon = 1.0; % Jerk on time (specified by PLC user)
Joff = 2/sqrt(Jlimit/Vref) + Jon; % Jerk off time <-- this is math!
Jmid = (Jon + Joff)/2; % Jerk half-time <-- this is math!
% simulation time
tStart = 0; % start running but not producing velocity until Jerk on time
h = 0.1; % sampling time
tEnd = round(1.2*Joff); % stop running
t = (tStart:h:tEnd);
% Jerk specifications on the PLC
tdata = [tStart Jon-c Jon+c Jmid-c Jmid+c Joff-c Joff+c tEnd];
Jdata = [0.0 0.0 Jlimit Jlimit -Jlimit -Jlimit 0.0 0.0];
% maybe call ordinary Jerk function?
d2y = @(t) interp1(tdata, Jdata, t); % OpenPLC can perform interpolation
Jerkode = @(t, y) [ y(2); % dy = y(2) acceleration
d2y(t)]; % d2y = dy(2)/dt jerk
% initial condition
y0 = [0; 0]; % zero velocity, zero acceleration
% set solver options
options = odeset('RelTol', 1e-6, 'AbsTol', 1e-8);
% call ode45 Solver (OpenPLC can solve simple ODEs)
[t, y] = ode45(@(t, y) Jerkode(t, y), t, y0, options);
% True Velocity Profile
tt = linspace(tStart, tEnd, 51);
TrueVel = Vref*smf(tt, Jon, Joff);
% Plot the solution
figure
hold on
plot(t, y(:,1))
plot(tt, TrueVel, 'o')
hold off
grid on
xlabel('Time')
ylabel('Amplitude')
title('Jerk-based S-curve Velocity')
legend('Numerical solution', 'True Velocity Profile', 'location', 'best')
%% S-curve membership function (borrowed from Fuzzy Logic Toolbox)
function y = smf(x, a, b)
m = (a + b)/2;
y = (x > a & x <= m) .* ( 2*((x-a)/(b-a)).^2) + ...
(x > m & x <= b) .* (1-2*((x-b)/(b-a)).^2) + ...
(x > b);
end
  2 comentarios
David Cole
David Cole el 18 de Mayo de 2025
Thank you for the code. I will start reviewing it immediately. My goal is to test the code and then export the code to structured text, which can be imported into a Siemens PLC. Within the PLC, the structured text can be made into a block (like a Simulink subsystem) that takes in inputs and produces an output. Once the constants are set they should never change. However, the input speed will change continuously throught the day based on the desired speed; for example, the speed might change from 0 to 10 m/s and 10 m/s to 3 m/s. The s curve block should produce an s curve output based on the user defined constants. The block will probably be placed in a 20 milli-second cyclic routine (like using a fixed time solver), but that might change. A 10 milli-second cyclic routine might be better.
I need to be careful about placing a time inside of the routine. I though about using integrators inside on simulink so I could avoid derivatives and odes.
Utilimately, here is what I want:
David Cole
David Cole el 18 de Mayo de 2025
Here is my simulink file. The bottom part works but the top part does not ramp down in a curve.

Iniciar sesión para comentar.


Sam Chak
Sam Chak el 28 de Mayo de 2025
In addition to your user inputs (Vin, accel, and jerk), you also need to provide the "Jerk On" time. You can use my S-curvy function to generate the desired S-shaped velocity profile that satisfies the acceleration and jerk constraints.
If you find my solution helpful, please remember to vote and click "Accept".
%% user inputs
Vref = 10; % Target Velocity
Alimit = 0.5; % hardware Acceleration limit
Jlimit = 0.1; % hardware Jerk limit
Jon = 5.0; % Preferred Jerk-Trigger 'on' time
%% call my S-curvy fun
[t, V] = scurve(Vref, Alimit, Jlimit, Jon);
acc = gradient(V)./gradient(t);
jerk = gradient(acc)./gradient(t);
%% plot results
figure
plot(t, V), grid on
xlabel('Time')
ylabel('Amplitude')
title('I''m S-curve Velocity')
figure
subplot(211)
mv = min(acc);
Mv = max(acc);
yL = 0.2*(Mv - mv);
plot(t, acc), grid on
ylim([mv-yL, Mv+yL])
title('I''m acceleration')
subplot(212)
mv = min(jerk);
Mv = max(jerk);
yL = 0.2*(Mv - mv);
plot(t, jerk), grid on
ylim([mv-yL, Mv+yL])
title('I''m jerk')
%% S-curvy function
function [t, out] = scurve(Vref, Alimit, Jlimit, Jon)
% parameter
c = 1e-3; % control parameter for accuracy purposes
% Jerk settings
Alim = sqrt(Jlimit*Vref);
if Alim <= Alimit
Jlim = Jlimit;
else
Jlim = Alimit^2/Vref;
end
Joff = 2/sqrt(Jlim/Vref) + Jon; % Jerk off time
Jmid = (Jon + Joff)/2; % Jerk half-time
% simulation time
tStart = 0; % start running but not producing velocity until Jerk on time
h = 0.01; % sampling time
tEnd = round(Joff) + Jon; % stop running
t = (tStart:h:tEnd);
% Jerk specifications on the PLC
tdata = [tStart Jon-c Jon+c Jmid-c Jmid+c Joff-c Joff+c tEnd];
Jdata = [0.0 0.0 Jlim Jlim -Jlim -Jlim 0.0 0.0];
% maybe call ordinary Jerk function?
d2y = @(t) interp1(tdata, Jdata, t); % OpenPLC can perform interpolation
Jerkode = @(t, y) [ y(2); % dy = y(2) acceleration
d2y(t)]; % d2y = dy(2)/dt jerk
% initial condition
y0 = [0; 0]; % zero velocity, zero acceleration
% set solver options
options = odeset('RelTol', 1e-6, 'AbsTol', 1e-8);
% call ode45 Solver (OpenPLC can solve simple ODEs)
[t, y] = ode45(@(t, y) Jerkode(t, y), t, y0, options);
out = y(:,1);
end

Categorías

Más información sobre Simulink PLC Coder en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by