Using bladeRF to find microwave cavity resonances

Working on something interesting? Share it with the community!

Moderator: robert.ghilduta

Post Reply
fdavies
Posts: 15
Joined: Wed Jul 15, 2015 6:52 pm

Using bladeRF to find microwave cavity resonances

Post by fdavies » Sat Aug 01, 2015 8:31 am

I have recently become fascinated with microwave resonant cavities and have made a resonant cavity with a small 1 quart pot as shown.
IMG_3195_s.png
IMG_3196_s.png
I connected up the bladeRF transmit and receive to two small loop antennas made from SMA connectors (P/N 142-0701-401). These are inserted into holes drilled in a piece of single sided unetched circuit board. I press this against the edges of the pot so that the copper sheet on the board forms a wall that closes off the pot making a resonant cavity.

The following is an example that shows TE111 and TM110 resonances.
s1.png
Here is the Octave script that I used:

Code: Select all

%  
% based on a file from https://github.com/Nuand/bladeRF/wiki/bladeRF-CLI-Tips-and-Tricks
%  modified
%

SAMPLE_RATE = 20e6;
NUM_SAMPLES = 131072;  % for tx, not rx
NUM_SECONDS = NUM_SAMPLES/SAMPLE_RATE;

START_FREQ_RAD = -5e6 * 2 * pi;  % it will be a complex frequency
STOP_FREQ_RAD = 5e6 * 2 * pi;

f_axis = linspace(-0.5 * SAMPLE_RATE, 0.5 * SAMPLE_RATE, NUM_SAMPLES);

DELTA= (1/2)*(STOP_FREQ_RAD - START_FREQ_RAD)/NUM_SECONDS;
t = [ 0 : (1/SAMPLE_RATE) : ((NUM_SECONDS) - 1/SAMPLE_RATE) ];
%env=(1/size(t,2))*[1:size(t,2)];
env=(t>NUM_SECONDS*0.1).*(t<NUM_SECONDS*0.9);
tx_signal = 0.90 .* exp(1j .* (START_FREQ_RAD+DELTA.*t) .* t);

save_sc16q11('/media/ramdisk/tx_waveform.sc16q11', tx_signal);

%  set up the bladeRF with a bunch of system command line calls
  system(["bladeRF-cli -e 'set samplerate rx ",num2str(SAMPLE_RATE),"'"]);
  system(["bladeRF-cli -e 'set bandwidth rx ",num2str(SAMPLE_RATE),"'"]);
  system(["bladeRF-cli -e 'set bandwidth tx ",num2str(SAMPLE_RATE),"'"]);
  system(["bladeRF-cli -e 'set samplerate tx ",num2str(SAMPLE_RATE),"'"]);
  system(["bladeRF-cli -e 'set lnagain 0'"]); % 0 3 6
  system(["bladeRF-cli -e 'set rxvga1 5'"]); % [5, 30]
  system(["bladeRF-cli -e 'set rxvga2 0'"]); % [0, 30]
  system(["bladeRF-cli -e 'set txvga1 -4'"]); %  [-35, -4]
  system(["bladeRF-cli -e 'set txvga2 25'"]); % [0, 25]
  system(["bladeRF-cli -e 'tx config delay=0'"]); %

result=[]; % for when I do many in a row
freq_result=[];
rx_signal=[];

%****************************************************************
%  set the range of frequencies to look at
%****************************************************************
freq_list = [0:10]*10e6+2600e6;  
%freq_list=[2620e6 2677.5e6 2680e6];

%%%   now for the loop
for f=freq_list
  % set the transmit and receive frequencies
  system(["bladeRF-cli -e 'set frequency rx ",num2str(f),"'"]);
  system(["bladeRF-cli -e 'set frequency tx ",num2str(f),"'"]);
  system("bladeRF-cli -s script_G_1.txt"); % see below for contents of script_D_1.txt
  f = fopen("/media/ramdisk/rx_sample", "r", "ieee-le");
  samples = fread(f, Inf, "int16");
  fclose(f);
  samples_i = samples(1:2:end, :);
  samples_q = samples(2:2:end, :);
  rx_signal = [rx_signal (samples_i + j * samples_q)'];
  spectrum=20*log10(abs(fftshift(fft(samples_i + j * samples_q)))/NUM_SAMPLES);
  result=[result spectrum(524288*0.25:524288*0.75)'];
  %pause(10);
endfor

fr2=min(freq_list)-5e6:(10e6+max(freq_list)-min(freq_list))/length(result):max(freq_list)+5e6;
fr=fr2(1:end-1);

clf;
h1=subplot(2,1,1);
rx1=downsample(real(rx_signal),100); % try to make plotting easier
h2=plot(real(rx1));
axis([1 length(rx1) min(rx1) max(rx1)]);
title('in phase (real) part of received waveform');
xlabel('Time');
ylabel('ADC counts');
grid on;
h3=subplot(2,1,2);
fr_d=downsample(fr,100);  % try to make plotting easier
res_d=downsample(result,100);
h4=plot(fr_d,res_d);
axis([fr_d(1) fr_d(end) -40 10]);
title('Spectrum assembled from pieces');
xlabel('Frequency');
ylabel('dB');
grid on;
and the script that it uses(script_G_1.txt):

Code: Select all

tx config delay=0
tx config file=/media/ramdisk/tx_waveform.sc16q11 format=bin
rx config file=/media/ramdisk/rx_sample n=524288
tx config repeat=1
rx start 
tx start
tx wait
rx wait
The resonant frequencies match up pleasingly with the frequencies calculated with following:

Code: Select all

% analytic solutions for a cylinder


function [frequ]=cyl_mode_freq(name,L,D)
  if (nargin != 3)
     usage ("cyl_mode_freq(name,L,D)");
  endif
gammaTE=[
   3.8317    7.0156   10.1735   13.3237   16.4706   19.6159   22.7601   25.9037;
    1.8412    5.3314    8.5363   11.7060   14.8636   18.0155   21.1644   24.3113;
    3.0542    6.7061    9.9695   13.1704   16.3475   19.5129   22.6716   25.8260;
    4.2012    8.0152   11.3459   14.5858   17.7887   20.9725   24.1449   27.3101;
    5.3176    9.2824   12.6819   15.9641   19.1960   22.4010   25.5898   28.7678;
    6.4156   10.5199   13.9872   17.3128   20.5755   23.8036   27.0103   30.2028;
    7.5013   11.7349   15.2682   18.6374   21.9317   25.1839   28.4098   31.6179;
    8.5778   12.9324   16.5294   19.9419   23.2681   26.5450   29.7907   33.0152];

gammaTM=[    
    2.4048    5.5201    8.6537   11.7915   14.9309   18.0711   21.2116   24.3525;
    3.8317    7.0156   10.1735   13.3237   16.4706   19.6159   22.7601   25.9037;
    5.1356    8.4172   11.6198   14.7960   17.9598   21.1170   24.2701   27.4206;
    6.3802    9.7610   13.0152   16.2235   19.4094   22.5827   25.7482   28.9084;
    7.5883   11.0647   14.3725   17.6160   20.8269   24.0190   27.1991   30.3710;
    8.7715   12.3386   15.7002   18.9801   22.2178   25.4303   28.6266   31.8117;
    9.9361   13.5893   17.0038   20.3208   23.5861   26.8202   30.0337   33.2330;
   11.0864   14.8213   18.2876   21.6415   24.9349   28.1912   31.4228   34.6371];
  % first decipher the name of the mode
  %if name(1)!="T"
  %  things to check:
  %    name should be exactly 5 characters
  %    the first character must be 'T'       name(1)=='T'
  %    the second character must be either 'E' or 'M'  name(2)=='E'|name(2)=='M'
  %    the third through 5th characters must be 0-9  isdigit(name(3))&isdigit(name(4))&isdigit(name(5))
  if (size(name,2) != 5)
    error ("mode name too long or short;  should be of format TExxx or TMxxx where each x is a digit");
  endif
  if !(name(1)=='T'&(name(2)=='E'|name(2)=='M')&(isdigit(name(3))&isdigit(name(4))&isdigit(name(5))))
    error ("mode name (first argument) should be of format TExxx or TMxxx where each x is a digit");
  endif
  % check that the list of points is in a good format

  %derivative of bessel function
  jp=@(l,x) real(besselj(l-1,x)-besselj(l+1,x))/2;

  % bessel function
  j=@(l,x) besselj(l,x);

  % now get the indices of the mode
  l=str2num(name(3));
  m=str2num(name(4));
  n=str2num(name(5));

%  for b=1:10 % gammaTM(l,m)= mth zero of j(l,x)
%    gammaTM(1,b)=fzero(inline('besselj(0,x)'),[(b-1) b]*pi);
%    for a=2:10  % which zero
%      gammaTM(a,b)=fzero(inline(strcat('besselj(',num2str(a-1),',x)')),[gammaTM(a-1,b) gammaTM(a-1,b)+pi]);
%    end
%  end

%  for b=1:10 % gammaTE(l,m)= mth zero of jp(l,x)
%    gammaTE(2,b)=fzero(inline('(besselj(0,x)-besselj(2,x))/2'),[(b-1) b]*pi);
%    gammaTE(1,b)=fzero(inline('(besselj(-1,x)-besselj(1,x))/2'),[gammaTE(2,b) gammaTE(2,b)+pi]);
%    for a=3:10
%      gammaTE(a,b)=fzero(inline(strcat('(besselj(',num2str(a-2),',x)-besselj(',num2str(a),',x))/2')),[gammaTE(a-1,b) gammaTE(a-1,b)+pi]);
%    end
%  end

%load gamma_table;  % get gammaTE and gammaTM from a file rather than recalculating each time

  mu = 1.2566370614E-6; % permeability of free space in SI units
  epsilon = 8.854187817620E-12; % permittivity of freee space in SI units
  Z0=sqrt(mu/epsilon);  % impedance of free space
  c = 1/sqrt(mu*epsilon);  % speed of light 

  if name(2)=='E' % TE modes
    k1= 2*gammaTE(l+1,m)/D; %gamma(l,m)= mth zero of jp(l,x) for TE modes
    k3=n*pi/L;
    k=sqrt(k1^2+k3^2);
    lambda = 2*pi/k;  % wavelength of wave in free space (in the same medium) at the modal frequency
  endif

  if name(2)=='M' % TM modes
    k1= 2*gammaTM(l+1,m)/D; % mth zero of j(l,x) for TM modes
    k3=n*pi/L;
    k=sqrt(k1^2+k3^2);
    lambda = 2*pi/k;  % wavelength of wave in free space (in the same medium) at the modal frequency
  endif

  frequ=c/lambda; % should return the frequency of the mode

endfunction;

The formulas in the above octave function came from a really great paper on cylindrical resonant cavities:
https://archive.org/details/bstj25-3-408
I.G. Wilson, C.W. Schramm, J.P. Kinzer, High Q resonant cavities for microwave testing. Bell Syst. Tech. J. 25(3), 408–434 (1946)

bpadalino
Posts: 303
Joined: Mon Mar 04, 2013 4:53 pm

Re: Using bladeRF to find microwave cavity resonances

Post by bpadalino » Sat Aug 01, 2015 7:31 pm

This is some really awesome stuff! Thanks for sharing this!

Post Reply