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:

array analyzer

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 variabile array.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 teoria L=(N+1)d. Dove N+1 sono gli elementi, quindi N 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.

array pattern 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
array pattern

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}
array pattern
Broadside
array pattern
45°

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

array pattern
300 MHz
array pattern
3 GHz

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

array pattern
300 MHz
array pattern
800 MHz

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: