+1 vote
57 views
in Helper by AVINASH MAURYA (13 points)

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:

  1. Code Structure: How to adapt my MATLAB C-function for Typhoon HIL’s C-block (syntax, supported functions, use of init() and step()).

  2. 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.

  3. 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.

  4. 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)

Please log in or register to answer this question.

Welcome to the Typhoon HIL user forum. Please check self-service support resources before posting a question.

HIL Specialist 2.0 courses
Documentation
Knowledgebase (Legacy)
Video support on demand
Youtube tutorials

For subscription-based support visit Typhoon HIL Support Center
...