Dear Typhoon HIL Team,
Dear Typhoon HIL Team,
I am working on a research project titled “Photovoltaic MPPT Performance Adaptability to Partial Shading Resilience and Load Variations with PSO.” In MATLAB/Simulink, I have implemented and validated the PSO-based MPPT algorithm using a C-function block, and I now wish to port this into Typhoon HIL Control Center for hardware-in-the-loop testing and real-time verification.
My MATLAB code (attached below) takes PV voltage and current (Vpv, Ipv) as inputs and generates the duty cycle (D_out) as output. It uses persistent variables for swarm initialization, particle updates, personal/global best tracking, and smoothing of the duty cycle output.
I would like guidance on:
Code Structure: How to adapt my MATLAB C-function for Typhoon HIL’s C-block (syntax, supported functions, use of init() and step()).
Inputs/Outputs: Correct way to declare Vpv, Ipv as inputs and D_out as output, and how to connect the duty cycle output to PWM blocks.
Implementation Steps: The procedure to load and compile this code in the Schematic Editor, handle unsupported functions (e.g., rand, linspace), and properly manage persistent variables.
Verification: Best practices to confirm that the Typhoon C-block produces results consistent with MATLAB under partial shading and load variation tests.
My main goal is to compare MATLAB simulations with Typhoon HIL results under identical conditions for benchmarking MPPT performance. Any step-by-step instructions, references, or example templates would be greatly appreciated.
Thank you for your support.
Below, I have provided a detailed explanation of the MATLAB C-function block along with the points where I am seeking clarification:
1. Code Structure
In MATLAB, my MPPT logic is encapsulated in a C-function block with persistent variables for maintaining PSO states such as swarm positions, velocities, particle bests, and global best. Below is the complete implementation:
%% ------------------ PSO Parameters ------------------
persistent swarm iter stepCounter P_hist D_out_prev
% PSO constants
N = 30; % number of particles
maxIter = 300; % max iterations
c1 = 1.8; % cognitive factor
c2 = 1.8; % social factor
w_max = 0.9; % max inertia
w_min = 0.4; % min inertia
D_min = 0.05; % min duty cycle
D_max = 0.95; % max duty cycle
% Moving average for stability
avgWindow = 7;
updatePeriod = 1; % update every step
perturbMagnitude = 0.02; % small perturbation
%% ------------------ Initialization ------------------
if isempty(swarm)
D_sweep = linspace(D_min, D_max, N);
swarm.x = D_sweep; % particle positions (duty cycles)
swarm.v = zeros(1,N); % particle velocities
swarm.pBest = D_sweep; % personal bests
swarm.pBestVal = -inf(1,N); % personal best power
swarm.gBest = D_min; % global best duty cycle
swarm.gBestVal = -inf; % global best power
swarm.k = 1; % current particle index
iter = 1;
stepCounter = 0;
P_hist = zeros(1, avgWindow);
D_out_prev = swarm.gBest;
D_out = swarm.gBest;
return;
end
%% ------------------ Slow Update ------------------
stepCounter = stepCounter + 1;
if stepCounter < updatePeriod
D_out = D_out_prev;
return;
else
stepCounter = 0;
end
%% ------------------ Moving Average Power ------------------
P_hist = [P_hist(2:end), Vpv*Ipv];
P = mean(P_hist);
%% ------------------ Update Personal Best ------------------
if P > swarm.pBestVal(swarm.k)
swarm.pBest(swarm.k) = swarm.x(swarm.k);
swarm.pBestVal(swarm.k) = P;
end
%% ------------------ PSO Update ------------------
w = w_max - (w_max - w_min)*(iter/maxIter);
r1 = rand; r2 = rand;
swarm.v(swarm.k) = w*swarm.v(swarm.k) ...
+ c1*r1*(swarm.pBest(swarm.k)-swarm.x(swarm.k)) ...
+ c2*r2*(swarm.gBest - swarm.x(swarm.k));
swarm.x(swarm.k) = swarm.x(swarm.k) + swarm.v(swarm.k);
%% ------------------ Clamp Duty Cycle ------------------
swarm.x(swarm.k) = max(min(swarm.x(swarm.k), D_max), D_min);
%% ------------------ Move to Next Particle ------------------
swarm.k = swarm.k + 1;
if swarm.k > N
swarm.k = 1;
iter = iter + 1;
% ------------------ Update Global Best after all particles ------------------
[bestP, idx] = max(swarm.pBestVal);
swarm.gBest = swarm.pBest(idx);
swarm.gBestVal = bestP;
% ------------------ Small Random Perturbation ------------------
if mod(iter,20)==0
swarm.x = swarm.x + perturbMagnitude*(rand(1,N)-0.5);
swarm.x = max(min(swarm.x, D_max), D_min);
end
end
%% ------------------ Reset if maxIter ------------------
if iter > maxIter
D_sweep = linspace(D_min,D_max,N);
swarm.x = D_sweep;
swarm.v = zeros(1,N);
swarm.pBest = D_sweep;
swarm.pBestVal = -inf(1,N);
swarm.gBest = D_min;
swarm.gBestVal = -inf;
iter = 1;
end
%% ------------------ Smooth Duty Cycle Output ------------------
alpha = 0.2; % smoothing factor
D_out = alpha*swarm.gBest + (1-alpha)*D_out_prev;
D_out_prev = D_out;
end
function D_out = PSO_MPPT_PV_Stable(Vpv, Ipv)