Main Content

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');

Figure contains an axes object. The axes object with title Quadrature Coupler, xlabel x (mm), ylabel y (mm) contains 8 objects of type patch, surface. These objects represent PEC, feed, Teflon.

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)

Figure contains an axes object and an object of type uicontrol. The axes object with title Metal-Dielectric, xlabel x (m), ylabel y (m) contains 6 objects of type patch, surface. These objects represent PEC, feed.

Remesh this structure and calculate the balance across the coupler output ports again.

mesh(coupler,'MinEdgeLength',coupler.PortLineWidth/2)

Figure contains an axes object and an object of type uicontrol. The axes object with title Metal-Dielectric, xlabel x (m), ylabel y (m) contains 6 objects of type patch, surface. These objects represent PEC, feed.

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]);

Figure contains an axes object. The axes object with xlabel x (mm), ylabel y (mm) contains 2 objects of type patch. These objects represent PEC, mypolygon.

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)');

Figure contains an axes object. The axes object with title Dual-fed patch (pre-transformer), xlabel x (mm), ylabel y (mm) contains 7 objects of type patch, surface. These objects represent PEC, feed, Teflon.

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

Figure contains an axes object. The axes object with xlabel x (mm), ylabel y (mm) contains 2 objects of type patch. These objects represent PEC, mypolygon.

The length of the transmission lines for the impedance matching section has to be increased slightly beyond λ4. This ensures we achieve good matching as well as lower axial ratio.

figure; 
show(ant); 
title('Dual-fed patch (with λ/4 transformers)'); 

Figure contains an axes object. The axes object with title Dual-fed patch (with λ/4 transformers), xlabel x (mm), ylabel y (mm) contains 7 objects of type patch, surface. These objects represent PEC, feed, Teflon.

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)');

Figure contains an axes object. The axes object with title Coupler + Dual-fed Patch (isolated port terminated), xlabel x (mm), ylabel y (mm) contains 7 objects of type patch, surface. These objects represent PEC, feed, Teflon, load.

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)

Figure contains an axes object and an object of type uicontrol. The axes object with title Metal-Dielectric, xlabel x (m), ylabel y (m) contains 3 objects of type patch, surface. These objects represent PEC, feed.

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

Figure contains an axes object. The axes object with title S indexOf 11 baseline of Coupler-Patch Assembly, xlabel Frequency (GHz), ylabel Magnitude (dB) contains an object of type line. This object represents dB(S_{11}).

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 contains 2 axes objects and other objects of type uicontrol. Axes object 1 contains 6 objects of type patch, surface. This object represents Teflon. Hidden axes object 2 contains 18 objects of type surface, line, text, patch. This object represents Teflon.

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

Figure contains 2 axes objects and other objects of type uicontrol. Axes object 1 contains 6 objects of type patch, surface. This object represents Teflon. Hidden axes object 2 contains 18 objects of type surface, line, text, patch. This object represents Teflon.

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 contains an axes object. The axes object with title Axial Ratio (Az=90° Plane), xlabel Elevation (degree), ylabel Axial Ratio (dB) contains an object of type line.

figure; 
axialRatio(pcbAntenna, freq, 0, 90);
title('Axial Ratio vs Frequency at boresight (φ=0^\circ, θ=90^\circ) ');

Figure contains an axes object. The axes object with title Axial Ratio vs Frequency at boresight (φ= 0 toThePowerOf degree baseline , θ= 90 toThePowerOf degree baseline ), xlabel Frequency (GHz), ylabel Axial Ratio (dB) contains an object of type line.

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