Dual-Fed Square Microstrip Patch Antenna for BLE Applications
This example shows how to use the pcbComponent and pcbcascade functionality of RF PCB Toolbox™ to design and analyze the dual-fed square microstrip patch antenna for Bluetooth Low Energy (BLE) applications.
You can use different feed arrangements to achieve circular and elliptical polarization or by using two orthogonal modes excited with a 90 degree phase difference between them. The two orthogonal modes can be accomplished by adjusting the physical dimensions of the patch and using either single or multiple feeds. For a square patch element, the easiest way to excite for circular polarization is to feed the element at two adjacent edges, to excite the two orthogonal modes as shown in the figure. For a quadrature phase difference, feed the element with a 90 degree power divider or a 90 degree hybrid as shown in the figure below.

Design Parameters
Initialize basic design parameters.
f0 = 2.40e9; % Design (BLE band) fspan = [2.0e9 3.0e9]; % Sweep span Nfreq = 201; % Frequency points freq = unique([linspace(fspan(1), fspan(2), Nfreq),f0]);
1) Design 90° Hybrid (branchline)
Use the design function on the couplerBranchline object to create a branchline coupler at the desired frequency and visualize it. The default substrate for the branchline coupler is Teflon.
coupler = design(couplerBranchline, f0);
figure;
show(coupler);
title('Quadrature Coupler');
1a.) Branchline balance check at design frequency
The branchline coupler has a through and a coupled port which will be used to feed the patch antenna. The amplitude of the input signal across these two ports should be almost the same while the phase difference should be 90 degrees. We can verify this by analyzing the coupler at the design frequency and measuring the amplitude and phase difference across ports 2 and 4.
branchLineBalanceCheck(coupler,f0)
Coupler balance @2.40 GHz: AmpDiff = 2.37 dB, PhaseErr ≈ 0.6° (target ~0 dB, 0°)
The results indicates that there is almost a 2.5 dB difference across the outputs while the phase error from 90 degrees is close to 0.5 deg. Plot the mesh.
figure mesh(coupler)

Remesh this structure and calculate the balance across the coupler output ports again.
mesh(coupler,'MinEdgeLength',coupler.PortLineWidth/2)
branchLineBalanceCheck(coupler,f0)
Coupler balance @2.40 GHz: AmpDiff = 1.20 dB, PhaseErr ≈ 0.1° (target ~0 dB, 0°)
The difference in amplitude is reduced to about a 1 dB and the phase error from 90 degrees is almost 0 after remeshing the structure.
2.) Square Patch Antenna Design with Dual Edge-feeds
The patchLength variable creates a square patch. The feedLineWidth and feedLineLength variable creates the feed lines to the antenna. The portSpacing matches the gap between the feed lines to that of the output ports of the branchline coupler. The patchLength and feedLineLength are close to half wavelength at design frequency.
2a.) Initial patch design
% Substrate parameters er = coupler.Substrate.EpsilonR; h = coupler.Height; tanD = coupler.Substrate.LossTangent; % Build dielectric d1 = dielectric("Teflon"); d1.EpsilonR = er; d1.Thickness = h; d1.LossTangent = tanD; % Compute square patch side from closed-form microstrip formulas c0 = physconst("lightspeed"); W = c0/(2*f0)*sqrt(2/(er+1)); % recommended width eff = (er+1)/2 + (er-1)/2 * (1/sqrt(1 + 12*h/W)); % effective permittivity dL = h*0.412 * ((eff+0.3)*(W/h+0.264))/((eff-0.258)*(W/h+0.8)); Leff = c0/(2*f0*sqrt(eff)); L = Leff - 2*dL; % physical length patchLength = L; % square patch patchLength = round(patchLength*1e6)/1e6; % Feed line to reach coupler outputs feedLineWidth = 3e-3; % initial guess, will not control Z0 feedLineLength = 0.065; % half-wavelength approximately % Match spacing to coupler output spacing (center-to-center) portSpacing = coupler.ShuntArmLength/2 + coupler.PortLineWidth/2;
2b.) Build geometry and modify to accommodate dual-feed design
Use the traceRectangular object to create a square patch with side length as patchLength. Use the rotateZ function to rotate the shape by 45 degrees and visualize it.Use the traceRectangular object to create two feed lines with same length, width, and equal spacing on either side of the square patch. Perform a Boolean add operation for the shapes patch, feed1 and feed2 and visualize it.
patch = traceRectangular('Length',patchLength,'Width',patchLength); patch = rotateZ(patch, 45); feed1 = traceRectangular('Length',feedLineLength,'Width',feedLineWidth, ... 'Center',[-feedLineLength/2, portSpacing]); feed2 = traceRectangular('Length',feedLineLength,'Width',feedLineWidth, ... 'Center',[-feedLineLength/2, -portSpacing]); antShape = patch + feed1 + feed2; % Translate so feed line ends meet x=0 for coax feeds translate(antShape, [feedLineLength, 0, 0]);

2c.) Create antenna
Create a ground plane using the antenna.Rectangle object and use pcbStack to create a PCB antenna. Assign the dielectric created in section (2a) and the ground plane to the Layers property on pcbStack. Assign the FeedLocations to the edge of the feed line, set the BoardThickness on the pcbStack and visualize the antenna
% Make the board safely larger than all metal extents boardMarginL = 0.06; % margin to avoid edge issues boardMarginW = 0.04; boardL = feedLineLength + boardMarginL; boardW = 2*portSpacing+ boardMarginW; Gnd = antenna.Rectangle('Length', boardL, 'Width', boardW, 'Center',[boardL/2, 0]); ant0 = pcbStack; ant0.BoardThickness = h; ant0.Layers = {antShape, d1, Gnd}; ant0.BoardShape = Gnd; ant0.FeedLocations = [0, portSpacing, 1, 3; 0, -portSpacing, 1, 3]; figure; show(ant0); title('Dual-fed patch (pre-transformer)');

2d.) Inspect input impedance at design frequency
Explain band for analysis, interpolating sweep, and conversion to z, use max of real-part of Zin : The result shows that the resistance of the patch is around 216 ohms at 2.4 GHz.
% S-parameters for the designed antenna and convert to Z S = sparameters(ant0, freq, 'SweepOption', 'interp'); Z = zparameters(S); Zin =[rfparam(Z,1,1) rfparam(Z,2,2)] ; Rin = real(Zin); f0Indx = find(freq>=f0); Rin_f0 = max(Rin(f0Indx(1),:)); fprintf('Measured Rin at patch edge (port1) @%.2f GHz: %.1f ohms\n', f0/1e9, Rin_f0);
Measured Rin at patch edge (port1) @2.40 GHz: 290.9 ohms
3) Impedance Matching: Quarter-wave transformer to 50 Ω
In order to match the impedance of the patch with the 50 ohm line, connect a quarter wavelength transformer at the end of the feed-line to transform the impedance to 50 ohm. The impedance of the quarter-wave transformer is the geometric mean of the impedance to be matched. Hence the geometric mean of 50 ohm and 291 ohm comes out to be approximately 121 ohms.
Use the microstripLine design to calculate the width of the line with a Z0 of 121 ohms. Use traceRectangular to create two quarter wave transformer lines with same length, width, and equal spacing on either side of the X-axis. Perform a Boolean add operation for the shapes patch, Line1 and Line2 and visualize it.
Use the pcbStack to create a PCB antenna and assign the dielectric and ground plane to the Layers property on pcbStack. Assign the FeedLocations to the edge of the feed-line, set the BoardThickness on the pcbStack and visualize the antenna.
R_tgt = 50; useTransformer = 100*(abs(Rin_f0-R_tgt)/R_tgt) > 10; if useTransformer Zt = sqrt(50*max(Rin_f0, 1)); % guard against zero/negatives tline = microstripLine; tline.Height = h; % IMPORTANT: same substrate as antenna tline = design(tline, f0, "Z0", Zt, "LineLength", 0.26); % length in wavelengths % Add the two λ/4 sections t1 = traceRectangular('Length',tline.Length,'Width',tline.Width, ... 'Center',[tline.Length/2, portSpacing]); t2 = traceRectangular('Length',tline.Length,'Width',tline.Width, ... 'Center',[tline.Length/2, -portSpacing]); translate(antShape, [tline.Length, 0, 0]); antShape = antShape + t1 + t2; % Rebuild pcbStack with transformers included ant = pcbStack; ant.BoardThickness = h; ant.Layers = {antShape, d1, Gnd}; ant.BoardShape = Gnd; ant.FeedLocations = [0, portSpacing, 1, 3; 0, -portSpacing, 1, 3]; else ant = ant0; % inset-feed route would go here instead end

The length of the transmission lines for the impedance matching section has to be increased slightly beyond . This ensures we achieve good matching as well as lower axial ratio.
figure;
show(ant);
title('Dual-fed patch (with λ/4 transformers)'); 
4) Cascade Coupler, Quarter-Wave Transformer, and Antenna
Use the pcbcascade to join the coupler and the patch antenna. To obtain circular polarization, connect the isolated port on the branchline coupler to a matched load of 50 ohm. The isolated port feed location in FeedLocations property of the pcbStack is copied into the ViaLocations. The feed location on the isolated port is deleted. The lumpedElement object is used to create an impedance of 50 ohms and the location of the Lumped Element is given at the ViaLocations. Assign this lumpedElement to the Load property on the pcbStack and visualize the antenna.
pcbAntenna = pcbcascade(coupler, ant); pcbAntenna.ViaLocations = pcbAntenna.FeedLocations(2,:); % keep location for termination pcbAntenna.ViaDiameter = pcbAntenna.FeedDiameter; pcbAntenna.FeedLocations(2,:) = []; % remove the extra feed Riso = lumpedElement; Riso.Impedance = 50; Riso.Location = [pcbAntenna.ViaLocations(1:2), pcbAntenna.BoardThickness]; pcbAntenna.Load = Riso; figure; show(pcbAntenna); title('Coupler + Dual-fed Patch (isolated port terminated)');

5) Electromagnetic analysis
Run an electromagnetic(EM) analysis by calculating the scattering parameters first and a far-field realized gain radiation pattern thereafter.
5a.) S-parameters interpolating sweep
Prior to calculating the s-parameters, mesh the structure. Use the sparameters function to calculate the s-parameters of the structure by using an interpolating sweep. Plot the result using the rfplot function.
mesh(pcbAntenna,"MaxEdgeLength",.04,"MinEdgeLength",.0035,"GrowthRate",0.5)

[S,fsw] = sparameters(pcbAntenna, freq, 'SweepOption','interp'); figure; rfplot(S, 1, 1); grid on; title('S_{11} of Coupler-Patch Assembly');

The result shows that the antenna is matched in a narrowband around 2.4 GHz.
5b.) 3D pattern at f0
Use the pattern function to plot the 3D radiation pattern of the antenna. Since the goal was to build a patch with circular polarization(CP), we will use the Name-Value argument options available to plot both the Right-Hand Circular Polarization (RHCP) and Left-Hand Circular Polarization (LHCP) patterns. In addition we will plot the realized gain pattern since this captures losses from materials and effect of impedance mismatch.
figure; pattern(pcbAntenna, f0,'Type','realizedgain','Polarization','RHCP')

figure; pattern(pcbAntenna, f0,'Type','realizedgain','Polarization','LHCP')

The antenna is radiating an RHCP dominant pattern with a realized gain of 7.35 dBi.
5c.) Axial Ratio
The quality of the circular polarization achieved can be assessed by using the axial ratio. Use the axialRatio function to plot the axial ratio of the antenna at 2.45 GHz. For the circular polarization, the axial ratio must be less than 3 dB.
figure;
axialRatio(pcbAntenna, f0, 90, 0:5:180);
title('Axial Ratio (Az=90° Plane)');
figure;
axialRatio(pcbAntenna, freq, 0, 90);
title('Axial Ratio vs Frequency at boresight (φ=0^\circ, θ=90^\circ) ');
The result indicates that the axial ratio requirement for circular polarization(CP) is achieved at boresight. The frequency sweep also indicates the CP requirement is achieved for a narrow frequency band around 2.4 GHz.
function branchLineBalanceCheck(coupler,f0) % This is a helper function to calculate the amplitude balance and phase % error relative to 90 deg. between the through and coupled ports of the % branchline coupler. S_c = sparameters(coupler, f0); S21 = rfparam(S_c, 2, 1); % through S41 = rfparam(S_c, 4, 1); % coupled ampImbalance_dB = 20*log10(abs(S21)/abs(S41)); phiDiff_deg = rad2deg(angle(S21/S41)); % wrap to [-180, 180] phiDiff_deg = mod(phiDiff_deg + 180, 360) - 180; % error relative to +/- 90° phaseErr_deg = min(abs(phiDiff_deg - 90), abs(phiDiff_deg + 90)); fprintf('Coupler balance @%.2f GHz: AmpDiff = %.2f dB, PhaseErr ≈ %.1f° (target ~0 dB, 0°)\n',... f0/1e9, ampImbalance_dB, phaseErr_deg); end
Copyright 2026 The MathWorks, Inc.,