Tra gli esami previsti nel corso di studi di Ingegneria Medica presso l’Università degli Studi di Roma Tor Vergata c’è il corso di Wireless Electromagnetics Technologies. Il corso fornisce le basi per i servizi wireless attuali e di prossima generazione, tra cui trasmissione radio e video, tracciamento radar, comunicazioni mobili e personali, reti di sensori wireless, ricarica wireless, identificazione a radiofrequenza e collegamenti satellitari.
Durante le lezioni ho avuto l’opportunità di preparare, insieme ad altre due colleghe, un’esercitazione sugli array di antenne, per l’intera classe. L’esercitazione doveva essere implementata sfruttando Sensor Array Analyzer, un’applicazione per Matlab facente parte del tool Phased Array System Toolbox. Una lezione del corso è stata sostituita con questa esercitazione con lo scopo di mettere in risalto gli aspetti più importanti degli array lineari, ed eventualmente anche per array planari. A seguire riporto i punti salienti dell’esercitazione.
Sensor Array Analyzer
Sensor Array Analyzer è un’app sviluppata per Matlab fornite insieme al tool Phased Array System Toolbox. Tale tool fornisce algoritmi e app per la progettazione e la simulazione di sistemi di beamforming e di array di sensori per applicazioni di comunicazione wireless, radar, sonar, acustiche e di diagnostica per immagini. È possibile modellare e analizzare il comportamento di array attivi e passivi, inclusi subarray e geometrie arbitrarie. I segnali simulati possono essere trasmessi e ricevuti da questi array per la progettazione di algoritmi di beamforming e di elaborazione del segnale.
L’app ha una sua interfaccia grafica che consente di creare l’array, modificare alcune impostazioni e visualizzare i parametri più importanti senza ricorrere alla Command Windows. Può essere aperte dalla selezione Apps o tramite il comando sensorArrayAnalyzer
. La GUI è divisa in tre sezioni principali:
- Parameters
- Geometry
- Characteristcs
A cui si aggiunge la barra superiore tramite la quale è possibile attivare ulteriori funzionalità. In particolare, è conveniente attivare subito il 3D pattern, i pattern 2D di elevazione e azimutale e il diagramma di grating. È comodo disporli in una griglia 2×3 come nella figura seguente:

Quindi possiamo andare ad impostare alcuni parametri. Possiamo anche esportare la variabile e tenerla nel workspace di Matlab. Creiamo quindi un allineamento lineare di antenne isotropiche lasciando i parametri consigliati dal tool.
Array lineari
Consideriamo un array uniforme di antenne isotropiche. Possiamo impostare diverse variabili sia dalla GUI che andando ad interrogare le proprietà della variabile esportata. Salviamo l’array nella variabile ula
e dalla command windows possiamo chiedere le proprietà. A seguire riporto uno snippet con alcuni comandi utili, anche da lanciare singolarmente.
f=3e8 %3 MHz
lambda = physconst('LightSpeed')/f
array=ula;
L=(array.NumElements+1)*array.ElementSpacing
% to visualize windows
testelemnt=64;
wvtool(hamming(testelemnt)); %plot hamming window
wvtool(chebwin(testelemnt)); %plot chebyshev
ula.Taper %vector with taper coefficients
Conviene salvare la frequenza e la lunghezza d’onda in una variabile di lavoro. Sapendo la relazione che lega lunghezza d’onda e frequenza possiamo calcolarla facilmente (sarà utile per diverse considerazioni successive) sfruttando la velocità delle luce memorizzata dentro Matlab: physconst('LightSpeed')
.
\lambda ={c\over f}
Quindi assegniamo ad una variabile di comodo il pacchetto esportato dal tool (questo può essere comodo per creare un unico codice e aggiornarlo di volta in volta). Tra i parametri iniziali, da GUI ma editabili anche dal array.Properties
troviamo:
- Number of elements, contiene il numero di antenne e viene salvato nella variabile
array.NumElements
. - Element spacing, distanza tra gli elementi. Possiamo esprimerlo come
d
sia in metri che rispettoλ
. Viene salvato nella variabilearray.ElementSpacing
. - Axis, ovvero la direzione lungo cui sono disposte le antenne
- Taper, possibilità di pesare in maniera diversa le singole antenne. Noi ci limiteremo ad array uniformi ma è possibile usare diversi finestramenti. Ad esempio, nel codice sono presenti i comandi per visualizzare le finestre di Chebyshev e di Hamming. In tal caso
array.Taper
contiene il vettore con i coefficienti che vanno a pesare le singole antenne.
Radiazione
Possiamo vedere, nel tab Characteristics, alcuni parametri.
- Direttività
- Span, ovvero la lunghezza complessiva. Il software considera la lunghezza geometrica
d*N
diverso da quanto usato in teoriaL=(N+1)d
. DoveN+1
sono gli elementi, quindiN
gli spazi. - Numero di elementi
- First null beamdiwth
- Half power beamwith
- Side lobe level, rappresenta la differenza, in decibel, tra il mainlobe e il side lobe più grande.
In particolare, possiamo vedere la differenza tra i due beamwidth.

Possiamo quindi creare l’array nel tool ed esportarla nel workspace. Possiamo crearli lineari uniformi (ULA) e rettangolari uniformi (URA) sfruttando sua antenne isotropiche che antenne cosine. Sappiamo che l’antenna isotropica ha un pattern di radiazione isotropico, costituito da un toroide con il nullo allineato alla corrente, mentre la cosine antenna presenta una direttività maggiore, limitandosi però ad un solo lobo del dipolo a λ/2 (l’andamento della corrente è cosinusoidale).
Sappiamo che negli array l’effetto complessivo dei campi delle singole antenne che danno interferenza tra loro si riflette nel fattore di array che va a fare da filtro angolare al pattern della singola antenna. Inoltre, avendo visto antenne ominidirezionali (isotropica e λ/2) il contributo del pattern sarà governato dalla forma del fattore di array. Per array uniformi:
|F|=I_{0} \mid \frac{\sin \frac{N+1}{2}\left(u+u_{0}\right)}{\sin \frac{u+u_{0}}{2}}
Quindi, prendendone il modulo, otterremo il diagramma rettangolare che possiamo proiettare sul pattern di radiazione (diagramma polare). In particolare, ricordando che il coseno è una grandezza periodica ma limitata, otteniamo una finestra di visibilità limitata.
\left|\cos \psi \right|<1\Longrightarrow u_0-k_0d\leq u+u_0\leq u_0+k_d

Dove i due termini non sono altro che variabili di comodo rappresentando il termine angolare e il termine di fase:
u\triangleq k_d\cos \psi \\ u_0\triangleq \alpha d
Pattern
Possiamo visualizzare il pattern di radiazione 3D sia all’interno dell’app che richiamando da command window. Partendo da un array lineare di antenne isotropiche possiamo considerare il puntamento generico del fascio, legato al termine di fase.
\cos \psi =-{\alpha \over k_0}


Chiaramente l’effetto di direzionalità del fascio è poco visibile con un antenna che irradia su un cono. Si vedono meglio però altri effetti come la presenza del grating lobe qualora aumentassimo troppo lo spazio tra le antenne (o aumentassimo la frequenza di lavoro).


Questo effetto lo si vede ancora meglio andando a prendere il pattern 2D, precisamente il pattern azimutale.


Broadside ed endfire
È possibile richiamare queste figure anche dalla command windows.
%%plot 3D
pattern(Array, Freq3D , 'PropagationSpeed', PropagationSpeed,'Type','directivity', 'CoordinateSystem', format,'weights', w(:,1));
%%plot 2D
pattern(Array, Frequency, -180:180, cutAngle, 'PropagationSpeed', PropagationSpeed,'Type', 'directivity', 'CoordinateSystem', format ,'weights', w);
pattern(Array, Frequency, cutAngle, -90:90, 'PropagationSpeed', PropagationSpeed,'Type', 'directivity', 'CoordinateSystem', format ,'weights', w);
Una cosa molto interessante può essere fare un ciclo for
variando gli elementi, piuttosto che l’angolo di puntamento, piuttosto che lo spacing tra le diverse antenne.
Chiaramente si vedono bene i diversi effetti che legano la spaziatura alla presenza di grating lobe e la variazione del numero di lobi secondari.
Passando ad un antenna cosine, possiamo vedere meglio il discorso del puntamento. In particolare i due casi limite broadside ed endfire.
Array bidimensionali
Altrettanto interessanti sono gli array bidimensionali. Possiamo considerare questi array come array lineari di antenne dove queste singole antenne sono a loro volta array lineari di antenne. Questo è possibile ricordando il principio di moltiplicazione dei pattern dove il contributo finale deriva dal fattore di array e dalle singole altezze efficaci. Utilizzando poi un’illuminazione uniformi e le fasi separabili lungo riga e lungo la colonna andiamo a dividere i due fattori di array sulle righe e sulle colonne.
\underline E\propto F\cdot \underline h_0\Longrightarrow \begin{cases}F_x\\ F_y\end{cases}
Con alimentazione uniforme avremo un fattore di array che altro non è che la trasformata di Fourier bidimensionale di una rect. Essendo le rect() discretizzata nelle singole antenne abbiamo in realtà una serie che quindi si riflette sempre in una sinc(), ma periodica, arrivando a fornire il pattern rettangolare.
Possiamo studiare i comportamenti variando gli elementi sui due assi, le spaziature e il puntamento. Ad esempio possiamo vedere bene l’effetto della variazione degli elementi ciclando sul numero di elementi stesso:
vec=[4 10 24];
indice=[1 2 3 4; 5 6 7 8;9 10 11 12];
for i=1:numel(vec)
Array = phased.URA('Size',[vec(i) 4],'Lattice','Rectangular','ArrayNormal','x');
Array.ElementSpacing = [0.5 0.5];
rwind = ones(1,4).';
cwind = ones(1,vec(i)).';
taper = rwind*cwind.';
Array.Taper = taper.';
Elem = phased.CosineAntennaElement;
Elem.CosinePower = [1 1];
Elem.FrequencyRange = [0 300000000];
Array.Element = Elem;
Frequency = 300000000;
PropagationSpeed = 300000000;
SteeringAngles = [0;0];
subfigure(3,4,indice(i,1));
% Plot Array Geometry
viewArray(Array,'ShowNormal',false,...
'ShowTaper',false,'ShowIndex','None');
Freq3D = 300000000;
% Find the weights
w = ones(getNumElements(Array), length(Frequency));
subfigure(3,4,indice(i,2));
% Plot 3d graph
format = 'polar';
pattern(Array, Freq3D , 'PropagationSpeed', PropagationSpeed, 'Type','directivity', 'CoordinateSystem', format,'weights', w(:,1));
w = ones(getNumElements(Array), length(Frequency));
subfigure(3,4,indice(i,3));
format = 'polar';
cutAngle = 0;
pattern(Array, Frequency, -180:180, cutAngle, 'PropagationSpeed', PropagationSpeed,'Type', 'directivity', 'CoordinateSystem', format ,'weights', w);
w = ones(getNumElements(Array), length(Frequency));
subfigure(3,4,indice(i,4));
format = 'polar';
cutAngle = 0;
pattern(Array, Frequency, cutAngle, -90:90, 'PropagationSpeed', PropagationSpeed,'Type', 'directivity', 'CoordinateSystem', format ,'weights', w);
pause(0.2)
end
Oppure possiamo vedere bene l’effetto di puntamento del fascio che permette di scandagliare un angolo solido anche molto preciso.
Esempi di array
Questi concetti, che possono sembrare molto teorici e limitati al sotware, si riflettono rapidamente nella progettazione di array di antenne reali.




Codici
I codici completi sono disponibili su GitHub: