MATLAB script to prove functionality of MPPT algorithm
Authors: Andrew Flynn, Ben Beauregard, Johnathan Adams
This script attempts to imulate the functionality of the maximum power point tracking algorithm built in C for use with the projects hardware. This is meant as a proof that the concept is sound and the algorithm will track theoretical and actual maximum power point data, not as an actual implementation to run on the hardware. As such, certain things are abstracted, such as duty cycle setting and tracking, ISRs, and other MCU-specific functionality.
Contents
Flynn's Code to load Experimental Data
We're just calling another script here. It reads a data file in a terribly... unintuitive way, but it does work, and if it ain't broke...
clear; fid = fopen('SolarSweepData.txt', 'r') ; % Open source file. if fid == -1 disp('ERROR 404: File Not Found') ; else fgetl(fid) ; % Read/discard line. fgetl(fid) ; % Read/discard line. buffer = fread(fid, Inf) ; % Read rest of the file. fclose(fid); fid = fopen('_temp.txt', 'w') ; % Open destination file. fwrite(fid, buffer) ; % Save to file. fclose(fid) ; A = tdfread('_temp.txt') ; delete('_temp.txt') ; end
Data-Error Check
If we have more voltage samples than current samples something is wrong and should probably be fixed before the simulation is continued.
if length(A.Voltage_0x5BV0x5D) ~= length(A.x0x23_Current_0x5BA0x5D) error('Sample Size Mismatch. What are you doing?') else IV = [A.Voltage_0x5BV0x5D.'; A.x0x23_Current_0x5BA0x5D.']; end
Ben's MPPT Algorithm
The "Sweep" Algorithm runs continuously in a loop using ISR's that call eachother.
Simulation Parameters
User-Modifiable to change how the simulation is run, and how fast the algorithm itself runs.
delta_dc = 0.625; % Percentage change in duty cycle req_samp = 100 / delta_dc; % Required samples for accurate sim. sample_rate = 500; % Algorithm sample rate, Hz. sim_time = 100; % Simultion time, in milliseconds (ms) sim_res = 100; % Simulation resolution in microseconds (us)
Simulation Parameter Error Check
If you can customize it, someone will break it. Let them know how they did so, so they can fix it.
% Warn user if duty cycle change won't always use a new sample if length(IV) < req_samp disp('Simultion Resolution Low. Results Not Accurate.'); end % Warn user if simulation time is too short to show full sweep if sim_time < req_samp disp('Sim time too short to show full sweep.'); end % ERROR if time step is larger than sweep time step if 1E6 / sample_rate > sim_res error('Simulation Resolution too Large for Sample Rate.'); end
Simultion Resolution Low. Results Not Accurate. Sim time too short to show full sweep.
Error using TimeDomainSimulation (line 68) Simulation Resolution too Large for Sample Rate.
These variables shouldn't be modified by the user
duty_cycle = delta_dc; % Holds the current duty cycle time_count = 0; % Holds the current time during simulation max_power = 0; % Holds Max Power Value max_power_dc = 0; % Emulates Duty-Cycle tracking power = 0; % Holds power value for ind = 1; % Matrix index for logging current_sample = 0; % Current Sample Variable for readibility voltage_sample = 0; % Voltage Sample Variable for readibility % Matrix to hold time-domain result of simulation pts = sim_time * 1E-3 / sim_res * 1E-6; sim_result = zeros(5,pts); % [Time;Power;Voltage;Current;MaxPower]
Algorithm Body
This is the sweep algorithm. It just sweeps. It's the definition of terrible, but basically everything is based on it.
for i = 0:sim_res * 1E-6:sim_time * 1E-3 % Change duty cycle at the designated sample rate, otherwise wait if mod(i,1 / sample_rate) == 0 % Avoiding short and open circuit conditions via duty cycle limits if duty_cycle < 100 - delta_dc; duty_cycle = duty_cycle + delta_dc; else duty_cycle = delta_dc; max_power = 0; max_power_dc = 0; end end % Use duty cycle to compute current, voltage and power % Calculate sample index from duty cycle because we can't just take an % ADC reading in a simulation... ind = round(duty_cycle * length(IV) / 100); % Ensure ind stays within its bounds if ind > length(IV) ind = length(IV); elseif ind < 1 ind = 1; end % Read in samples from ADC current_sample = IV(2,ind); voltage_sample = IV(1,ind); power = current_sample * voltage_sample; % If the current sample is higher than the previous maximum power % point, save it. if power > max_power max_power = power; max_power_dc = duty_cycle; end % Log the simulation results and increment the index sim_result(1,ind) = i; % time sim_result(2,ind) = power; sim_result(3,ind) = voltage_sample; sim_result(4,ind) = current_sample; sim_result(5,ind) = max_power; ind = ind + 1; end
Graph data
This is a wall of nonsense that I promise you works just fine and you don't have to waste your time reading.
% Here, we display consice numerical results. The wierdness comes from % trying to stay under 80 characters per line. disp(['The calculated maximum power was ',num2str(max_power)]); str = 'The theoretical duty cycle is '; st = ' percent'; disp([str,num2str(max_power_dc),st]); % Too complex half-shared axis multiple y-scale plotting % Mostly because of MATLAB 2015... (As opposed to 2016) % x = A.Voltage_0x5BV0x5D; % y1 = A.x0x23_Current_0x5BA0x5D; % y2 = A.Voltage_0x5BV0x5D.*A.x0x23_Current_0x5BA0x5D; % [hAx,hLine1,hLine2] = plotyy(x,y1,x,y2); % title('Power, Current and Voltage Characteristics') % xlabel('Voltage, [V]') % ylabel(hAx(1),'Current, [A]') % left y-axis % ylabel(hAx(2),'Power, [W]') % right y-axis % hLine1.LineStyle = '-'; % hLine2.LineStyle = '-'; % hold on; % v = IV(1,max_power_dc); % plot([v v], [0 max_power],'Color',[0 1 0]); % grid on; % grid minor;