ConicLogSpiral

From NebarnixWiki
Revision as of 21:41, 30 April 2017 by NebarnixWikiSysop (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Problem Statement

I like antennas. I also like soviet spacecraft. In the photo of Lunakhod-1 there is a strange looking white antenna on the left side of the rover, with a black spiral. I wanted to know what this antenna was, why it was used, and maybe how hard it would be to make.

Extensive googling turned up the antenna design, a directional, extremely broadband, circularly polarized, traveling wave antenna referred to as the Conical Log Spiral Antenna. This antenna is commonly used as a feed on radio telescopes due to the extreme bandwidth and configurable directionality. This sounds amazing. I want to make one.

Biggest Problem: Though I can find many analyses of the performance of the antenna, I cannot find any calculators, generators, or other design tools. This is a tricky geometry to create, and I want to fabricate in 2D, then fold into 3D. I decided the best way to go about this was to design such a tool myself. The matlab code is listed below, though I would like to create a php version as an online realtime calculator with pdf results downloadable.

Maths

%flattened cone
clear all;
baseRadius=2;
%tipRadius = 0.1591; %starting radius, determined by the starting radius
tipRadius = baseRadius/10; %starting radius, determined by the starting radius

%Pick one code block
%Height=10;
%AspectRatio=Height/baseRadius;
%HalfAngle = pi/2-atan(AspectRatio);

%or pick the other code block
HalfAngle = degtorad(10);
AspectRatio = tan(HalfAngle);
Height = baseRadius/AspectRatio;
tipHeight = tipRadius/AspectRatio;

stripWidth = pi/2; %this is sometime called signal, and is an ANGLE in RADIANS
pitchAngleDesired = 60;

sideLength = sqrt(Height^2+baseRadius^2); %or Height/cos(HalfAngle)!
tipSideLength = sqrt(tipHeight^2+tipRadius^2); %or Height/cos(HalfAngle)!
CircumpherenceBottom = 2*pi*baseRadius;
CircumpherenceFlat = 2*pi*sideLength;
GapAngle = (CircumpherenceFlat - CircumpherenceBottom)/sideLength;
radtodeg(GapAngle)

%% Polar coordinates, 2D cone
%rho = a*e^(b*theta)
%x=r*cos(theta);
%y=r*sin(theta);

pitchAngle=atand(tand(pitchAngleDesired)*(sideLength/baseRadius));%Correction factor for the pitch angle due to conal distortion ((sideLength/baseRadius) is the scale factor)

a=tipRadius;
b=tand(90-pitchAngle);
minRadians = log(tipRadius/a)/b;
maxRadians = log(baseRadius/a)/b;
theta = minRadians:pi/100:maxRadians;
windingAngle = radtodeg(maxRadians-minRadians); %not sure what use this is
rho = a.*exp(b.*theta);
%polar(rho,theta);

%first leg, with a width
x1a=rho.*cos(theta);
y1a=rho.*sin(theta);
x1b=rho.*cos(theta+stripWidth);
y1b=rho.*sin(theta+stripWidth);

%Second leg, with a width
x2a=rho.*cos(theta+pi);
y2a=rho.*sin(theta+pi);
x2b=rho.*cos(theta+stripWidth+pi);
y2b=rho.*sin(theta+stripWidth+pi);

plot([0 0],[-tipRadius -baseRadius],x1a,y1a,'bl',x1b,y1b,'bl',x2a,y2a,'r',x2b,y2b,'r',tipRadius*cos(0:0.01:2*pi),tipRadius*sin(0:0.01:2*pi),baseRadius*cos(0:0.01:2*pi),baseRadius*sin(0:0.01:2*pi));

grid on;
%max_value = max(abs([x1a y1a ]));
axis([-baseRadius baseRadius -baseRadius baseRadius]);
pbaspect([1 1 1]);

%% 3D spiral
%rho = a*e^(b*theta)
%x=r*cos(theta);
%y=r*sin(theta);

pitchAngle=atand(tand(pitchAngleDesired)*(sideLength/baseRadius));%Correction factor for the pitch angle due to conal distortion ((sideLength/baseRadius) is the scale factor)
%pitchAngle = 60*atand(tand(45)*sideLength);

a=tipRadius;
b=tand(90-pitchAngle);
minRadians = log(tipRadius/a)/b;
maxRadians = log(baseRadius/a)/b; %this doesn't quite give us max radius?
theta = minRadians:pi/200:maxRadians;
windingAngle = radtodeg(maxRadians-minRadians); %not sure what use this is
rho = a.*exp(b.*theta);
%rho now stands for distance down ALONG cone surface, not outward

z = Height-(Height/baseRadius)*(rho);%

x1a=rho.*cos(theta);
y1a=rho.*sin(theta);
x1b=rho.*cos(theta+stripWidth);
y1b=rho.*sin(theta+stripWidth);


%Second leg, with a width
x2a=rho.*cos(theta+pi);
y2a=rho.*sin(theta++pi);

x2b=rho.*cos(theta+stripWidth+pi);
y2b=rho.*sin(theta+stripWidth+pi);
%z=Height-z;
plot3([0 0],[0 -baseRadius],[Height 0],x1a,y1a,z,'bl',x1b,y1b,z,'bl',x2a,y2a,z,'r',x2b,y2b,z,'r',tipRadius*cos(0:0.01:2*pi),tipRadius*sin(0:0.01:2*pi),Height-tipHeight * ones(numel(0:0.01:2*pi),1),baseRadius*cos(0:0.01:2*pi),baseRadius*sin(0:0.01:2*pi),zeros(numel(0:0.01:2*pi),1));
view(90,0);
%view(90,radtodeg(HalfAngle));
grid on;
max_value = max(abs([tipRadius baseRadius Height z]));
axis([-max_value max_value -max_value max_value -max_value*1.5 max_value*1.5]);
pbaspect([1 1 1]);

%% Convert to flat disc
numPtsPerRev = numel(find(theta<2*pi));
radiansPerPtOut = (2*pi-GapAngle)/numPtsPerRev;
clear idxList1a idxList1b idxList2a idxList2b;

thetaCount1a = 0;
thetaCount1b = stripWidth / (2*pi/(2*pi-GapAngle))-radiansPerPtOut;
thetaCount2a = pi / (2*pi/(2*pi-GapAngle))-radiansPerPtOut;
thetaCount2b = (stripWidth+pi) / (2*pi/(2*pi-GapAngle))-radiansPerPtOut;

for i=1:numel(theta)
    %z = Height-(Height/baseRadius)*(rho(i));%
    rhoOut(i) = rho(i)/sin(HalfAngle);
    
    thetaCount1a = thetaCount1a+radiansPerPtOut;
    thetaCount1b = thetaCount1b+radiansPerPtOut;
    thetaCount2a = thetaCount2a+radiansPerPtOut;
    thetaCount2b = thetaCount2b+radiansPerPtOut;
    
    wrapTheta=mod(theta(i),2*pi);
    if  wrapTheta == 0 %this controls the reset point
        if exist('idxList1a','var')
            idxList1a(end+1)=i;
        else
            idxList1a=i;
        end
        thetaCount1a = 0;
    end
    
    wrapTheta=mod(theta(i)+stripWidth,2*pi);
    if  wrapTheta == 0 %this controls the reset point
        if exist('idxList1b','var')
            idxList1b(end+1)=i;
        else
            idxList1b=i;
        end
        thetaCount1b = 0;
    end
    
    wrapTheta=mod(theta(i)+pi,2*pi);
    if  wrapTheta == 0 %this controls the reset point
        if exist('idxList2a','var')
            idxList2a(end+1)=i;
        else
            idxList2a=i;
        end
        thetaCount2a = 0;
    end
    
    wrapTheta=mod(theta(i)+pi+stripWidth,2*pi);
    if  wrapTheta == 0 %this controls the reset point
        if exist('idxList2b','var')
            idxList2b(end+1)=i;
        else
            idxList2b=i;
        end
        thetaCount2b = 0;
    end
    
    thetaOut1a(i) = thetaCount1a;
    thetaOut1b(i) = thetaCount1b;
    thetaOut2a(i) = thetaCount2a;
    thetaOut2b(i) = thetaCount2b;
    %rhoOut(i) = (Height-z(i))+0.0175;
    
end

xf1a=rhoOut.*cos(thetaOut1a);
yf1a=rhoOut.*sin(thetaOut1a);

xf1b=rhoOut.*cos(thetaOut1b);
yf1b=rhoOut.*sin(thetaOut1b);

xf2a=rhoOut.*cos(thetaOut2a);
yf2a=rhoOut.*sin(thetaOut2a);

xf2b=rhoOut.*cos(thetaOut2b);
yf2b=rhoOut.*sin(thetaOut2b);

%insert nans to keep matlab from connecting points
[xf1a,yf1a] = insertValues(xf1a,yf1a,idxList1a);
[xf1b,yf1b] = insertValues(xf1b,yf1b,idxList1b);
[xf2a,yf2a] = insertValues(xf2a,yf2a,idxList2a);
[xf2b,yf2b] = insertValues(xf2b,yf2b,idxList2b);

plot([tipSideLength sideLength],[0 0],[tipSideLength*cos(2*pi-GapAngle) sideLength*cos(2*pi-GapAngle)],[tipSideLength*sin(2*pi-GapAngle) sideLength*sin(2*pi-GapAngle)],tipSideLength*cos(0:0.01:2*pi-GapAngle),tipSideLength*sin(0:0.01:2*pi-GapAngle),sideLength*cos(0:0.01:2*pi-GapAngle),sideLength*sin(0:0.01:2*pi-GapAngle),xf1a,yf1a,'bl',xf1b,yf1b,'bl',xf2a,yf2a,'r',xf2b,yf2b,'r');
axis([-sideLength sideLength -sideLength sideLength]);
pbaspect([1 1 1]);

This script depends on a single function, insertValues, which inserts NaN numbers into an array, at the locations specified in a second array.

function [outputArrayX, outputArrayY]=insertValues(inputArrayX,inputArrayY,idxList)
idx2 = 1;
for i=1:numel(inputArrayX)
    
    outputArrayX(idx2) = inputArrayX(i);
    outputArrayY(idx2) = inputArrayY(i);
    
    if max(i == idxList-1)
        idx2 = idx2+1;
        outputArrayX(idx2) = NaN;
        outputArrayY(idx2) = NaN;
        
    end
    idx2 = idx2+1;
end
end