Parametric Dipole Antenna Generator

Parametric Dipole Antenna Generator

Parametric Dipole Antenna Generator for OpenSCAD

3D print your own dipole antenna mounts

I have been getting back into my radio hobby, so naturally, I needed to build some antennas. I wanted to start simple, with dipoles, and then go on from there. Having a 3D printer, I wondered if there was someone who created a simple dipole mount for higher-frequency dipoles, but I didn’t find anything that suited me. Seeing an opportunity to share a neat project, I broke out my handy tool of OpenSCAD.

OpenSCAD, if you are unfamiliar, is a program targeting software developers in helping them create mechanical devices in either 2D or 3D. For a software programmer, the interface is very familiar, and it’s relatively easy to get up to speed with the semantics of the language. I highly recommend it.
OpenSCAD outputs an STL file, which is imported to a 3D printing slicing program, such as Cura. Cura creates the G-code, which is then uploaded to the 3D printer.

I figured that it would be most helpful if I could create a dipole mount that had parametric element lengths depending on the center resonant frequency. Additionally, If the mount itself were modular, the elements could be interchanged depending on the frequency of interest. Finally, I wanted to be able to press the wire into the plastic part, which ensures that the wire is straight and the correct length. Here is the code, which does all of the above.

Note: this generator is only practical at frequencies above 100MHz.

include <roundedcube.scad>


frequency = 1090;

wirediameter = 1;

facets = 255;
dipoleconst = 234;
feet_to_mm = 304.8;
element_length=((dipoleconst / frequency)*feet_to_mm);
wallthickness = 3;
element_height=2;

mountlength = 30;
mountwidth = 100;
mountthickness = 5;

coaxdiameter = 5;

boltclearance = 5.5;
boltsideoffset = 5;

slotwidth = (mountlength/8);
slotlength = (mountwidth/2) ;
slotheight = 1.5;


module main(){
  
     echo("Element Length=", element_length);
    
     //color("Gainsboro",1) createelement((element_length / 2)+2,0,.85);
     //color("Gainsboro",1) createelement(-(element_length / 2)-2,0,.85);
     color("DimGray",1.0) mount();
}

module createelement(pos1=0,pos2=0,pos3=0){
    
    
    translate([pos1,pos2,pos3]){
        
        difference(){
        
            roundedcube(size = [element_length,wirediameter + wallthickness ,wirediameter+element_height], center = true, radius = 0.6, apply_to = "all");
            
            translate([0,0,1]){
                
                cube(size = [element_length+2,wirediameter ,wirediameter+element_height], center = true);
                
                //cube(size = [element_length/2,wirediameter + 2, wirediameter],center = true);
                
            }
            
        } 
        
         
         //t-slot
         translate([0,0,-slotheight*2.95]){ 
             
             cube(size = [element_length,slotwidth-0.5 ,slotheight-0.5], center = true);
             
         }
         
         translate([0,0,-slotwidth/1.5]){ 
             
             rotate([90,0,0]) cube(size = [element_length,slotwidth/2+1 ,slotheight-0.5], center = true);
             
         }
    }  
}

module mount(){
    
   translate([0,-5,-(mountlength/2)-1]){
        
        difference(){
            
            rotate([90,90,0]){ 
                
                roundedcube(size = [mountlength,mountwidth,mountthickness], center = true, radius = 0.6, apply_to = "all");
    
            }  
        //coax slot
        translate([0,(coaxdiameter/2)-.5,0]) cylinder(h=mountlength*2, d1=coaxdiameter, d2=coaxdiameter+.5, center=true, $fn = facets);
            
        //mount bolt 1
         translate([(mountwidth/2)-10-(boltclearance/2),0,-(mountlength/2)+boltsideoffset]) {
             
             rotate([90,0,0]) cylinder(h=mountthickness*2, d1=boltclearance, d2=boltclearance, center=true, $fn = facets);        
            
         } 
         //mount bolt 2
         translate([-(mountwidth/2)+10+(boltclearance/2),0,-(mountlength/2)+boltsideoffset]) {
             
             rotate([90,0,0]) cylinder(h=mountthickness*2, d1=boltclearance, d2=boltclearance, center=true, $fn = facets);        
            
         }
        //hollow
         translate([0,0,0]) {
             
             cube(size = [mountwidth-20,mountlength ,mountthickness*2], center = true);
             
         }
         translate([18,0,-10]) {
             
             cube(size = [mountwidth/2-22,mountthickness*2 ,4.5], center = true);
             
         }
         
         translate([-18,0,-10]) {
             
             cube(size = [mountwidth/2-22,mountthickness*2 ,4.5], center = true);
             
         }
    
        }  
        
        //mount block
        difference(){
        
            translate([0,mountwidth/20,mountwidth/8]){
             
             roundedcube(size = [mountwidth,(mountlength/4),mountthickness], center = true, radius = 0.6, apply_to = "all");
             
         }
         
         translate([0,(coaxdiameter/2)-.5,0]) cylinder(h=mountlength*2, d1=coaxdiameter+.5, d2=coaxdiameter+.5, center=true, $fn = facets); 
         
         //t-slot1
         translate([mountwidth/3.5,(mountwidth/20),(mountwidth/8)]){ 
             
             cube(size = [slotlength,slotwidth ,slotheight], center = true);
             
         }
         
         translate([mountwidth/3.5,(mountwidth/20),(mountwidth/6)-(slotwidth/2)]){ 
             
             rotate([90,0,0]) cube(size = [slotlength,slotwidth ,slotheight], center = true);
             
         }
         
         //t-slot2
         translate([-(mountwidth/3.5),(mountwidth/20),(mountwidth/8)]){ 
             
             cube(size = [slotlength,slotwidth ,slotheight], center = true);
             
         }
         
         translate([-mountwidth/3.5,(mountwidth/20),(mountwidth/6)-(slotwidth/2)]){ 
             
             rotate([90,0,0]) cube(size = [slotlength,slotwidth ,slotheight], center = true);
             
         }
         
        }  
    }  
}

main();

How to use Dipole Antenna Generator

  1. The first thing to do is to find the center frequency you’re interested in.
  2. Once you have the frequency, enter it as the “frequency” variable at the top of the main code.
  3. In OpenSCAD, press the “Render” button to render the model.
  4. Then, within the “Main” module, you need to comment out the elements when you want to generate the mount. When you want to generate the elements, comment out the mount. You comment in OpenSCAD by typing // before the line of code.
  5. Render the element and then press the STL button. Save the STL somewhere handy. Note: the elements are the same so you only have to render one of them, but you need to print two of them.
  6. Render the mount and press the STL button. Save the STL within the same directory as the elements.
  7. Open your slicing program, I use Cura, and set the quality to “Super” or 0.12mm layer height. This is more important for the elements than the mount itself. You will also need to generate supports “everywhere” so that the elements print properly.
  8. Generate the G-Code and upload to your printer.
  9. Once printed, the elements are the precise length that the wire needs to be. For the wire, I’m using 1.5mm² audio wire, which has an outer diameter of about 2.9mm. This wire pushes right into the plastic element, and sits tight. It is useful to strip one side of the wire before pushing it into the slot.
  10. Slide the T-slot of the element into the body–after you’ve cleaned the support from the part–and push it into the mount until it stops.
  11. Push the unstripped coax cable through the hole, strip the cable, and position the ground wire so it’s toward the bottom, and the center conductor is toward the top element.
  12. Solder the coax conductors to their respective elements.
  13. Push the coax into the run and secure it with a wire tie.\
  14. It may be useful to position a ferrite bead at the mount to act as a 1:1 balun.
  15. Connect the antenna to your transceiver and check the SWR. Trim if needed.
// Higher definition curves
$fs = 0.01;

module roundedcube(size = [1, 1, 1], center = false, radius = 0.5, apply_to = "all") {
	// If single value, convert to [x, y, z] vector
	size = (size[0] == undef) ? [size, size, size] : size;

	translate_min = radius;
	translate_xmax = size[0] - radius;
	translate_ymax = size[1] - radius;
	translate_zmax = size[2] - radius;

	diameter = radius * 2;

	module build_point(type = "sphere", rotate = [0, 0, 0]) {
		if (type == "sphere") {
			sphere(r = radius);
		} else if (type == "cylinder") {
			rotate(a = rotate)
			cylinder(h = diameter, r = radius, center = true);
		}
	}

	obj_translate = (center == false) ?
		[0, 0, 0] : [
			-(size[0] / 2),
			-(size[1] / 2),
			-(size[2] / 2)
		];

	translate(v = obj_translate) {
		hull() {
			for (translate_x = [translate_min, translate_xmax]) {
				x_at = (translate_x == translate_min) ? "min" : "max";
				for (translate_y = [translate_min, translate_ymax]) {
					y_at = (translate_y == translate_min) ? "min" : "max";
					for (translate_z = [translate_min, translate_zmax]) {
						z_at = (translate_z == translate_min) ? "min" : "max";

						translate(v = [translate_x, translate_y, translate_z])
						if (
							(apply_to == "all") ||
							(apply_to == "xmin" && x_at == "min") || (apply_to == "xmax" && x_at == "max") ||
							(apply_to == "ymin" && y_at == "min") || (apply_to == "ymax" && y_at == "max") ||
							(apply_to == "zmin" && z_at == "min") || (apply_to == "zmax" && z_at == "max")
						) {
							build_point("sphere");
						} else {
							rotate = 
								(apply_to == "xmin" || apply_to == "xmax" || apply_to == "x") ? [0, 90, 0] : (
								(apply_to == "ymin" || apply_to == "ymax" || apply_to == "y") ? [90, 90, 0] :
								[0, 0, 0]
							);
							build_point("cylinder", rotate);
						}
					}
				}
			}
		}
	}
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *