How to design and make a cyclone separator.
There is a number of pages on the Internet describing the process of building a cyclonic separator. Some of them even provide some maths and a quite detailed plan if you need a unit capable of taking you to the Moon. If, however, you'd like a small unit that can help prevent your home vacuum clenaer from clogging while you drill a hole to hang a painting, you may feel a little deserted. I did too. I wanted to know how much material I needed to build the thing and to check if a slightly resized design still fits the sheet I had. Last but not least, I wanted a nice flat template to cut out the inlet which, if you think about it, is a strange shape. So I took my tools and started hacking.
1 The shape
First I created an OpenSCAD script to visualise a hollow cone.
/* -*- mode: scad; c-basic-offset: 4; c-file-style: "k&r"; indent-tabs-mode: nil -*- */
/* All measurements are in milimeters */
top_diameter=200;
bottom_diameter=100;
height=300;
inlet_diameter = 40;
/* internal variables */
$fn=50;
inlet_radius = inlet_diameter / 2;
top_radius = top_diameter / 2;
bottom_radius = bottom_diameter / 2;
tga = (top_radius - bottom_radius) / height;
total_height = top_radius / tga;
bottom_height = total_height - height;
/* inlet position */
inlet_vertical_position = total_height-inlet_diameter * 1.5 ;
inlet_horizontal_position = inlet_vertical_position * tga - inlet_radius*1.1;
inlet_position = [0,inlet_horizontal_position,inlet_vertical_position];
inlet_angle = 80;
difference() {
/* the cyclone */
translate([0,0,bottom_height])
cylinder(r1=bottom_radius, r2=top_radius, h=height);
/* remove the inside */
translate([0,0,4])
cylinder(r1=0, r2=top_radius, h=total_height);
/* cut in half at y = 0 and x > 0 */
rotate([0,0,0])
translate([-top_radius - 10,-0.5,-10])
cube([top_radius + 10,1,total_height+20]);
/* the inlet */
translate(inlet_position)
rotate([0,inlet_angle,0])
cylinder(r=inlet_radius, h=top_diameter);
}
The cone of cyclonic separator.
Looks nice but still does not help much in cutting. Let's iron it.
2 The template
With the above design exported as STL file we can start trying to
make it flat. STL is a very simple file format and luckily there is
a great script by nophead to parse it. Once parsed the shape needs
to be transformed so that the surface of the cone becomes flat. This
is what the conexform()
function in the code below is for.
Remember to copy actual dimensions of the cone used in the scad file
or the transformation may yeild quite weird results.
#!/usr/bin/env python
#
# Transform the 3D cyclone model as exported from cyclone.scad into a
# flat shape for conversion into DXF.
#
import sys
class Vertex:
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
self.key = (float(x), float(y), float(z))
def transform(self, f):
x, y, z = f(self.x, self.y, self.z)
self.x, self.y, self.z = x, y, z
self.key = (float(x), float(y), float(z))
class Normal:
def __init__(self, dx, dy, dz):
self.dx, self.dy, self.dz = dx, dy, dz
class Facet:
def __init__(self, normal, v1, v2, v3):
self.normal = normal
if v1.key < v2.key:
if v1.key < v3.key:
self.vertices = (v1, v2, v3) #v1 is the smallest
else:
self.vertices = (v3, v1, v2) #v3 is the smallest
else:
if v2.key < v3.key:
self.vertices = (v2, v3, v1) #v2 is the smallest
else:
self.vertices = (v3, v1, v2) #v3 is the smallest
def key(self):
return (self.vertices[0].x, self.vertices[0].y, self.vertices[0].z,
self.vertices[1].x, self.vertices[1].y, self.vertices[1].z,
self.vertices[2].x, self.vertices[2].y, self.vertices[2].z)
def transform(self, f):
for v in self.vertices:
v.transform(f)
class STL:
def __init__(self, fname):
self.facets = []
f = open(fname)
words = [s.strip() for s in f.read().split()]
f.close()
if words[0] == 'solid':
i = words.index('facet')
self.name = " ".join(words[1:i])
while words[i] == 'facet':
norm = Normal(words[i + 2], words[i + 3], words[i + 4])
v1 = Vertex(words[i + 8], words[i + 9], words[i + 10])
v2 = Vertex(words[i + 12], words[i + 13], words[i + 14])
v3 = Vertex(words[i + 16], words[i + 17], words[i + 18])
i += 21
self.facets.append(Facet(norm, v1, v2, v3))
else:
print "Not an OpenSCAD ascii STL file"
sys.exit(1)
def canonicalise(self):
self.facets.sort(key = Facet.key)
def transform(self, f):
for facet in self.facets:
facet.transform(f)
def write(self, fname):
f = open(fname,"wt")
print >> f,'solid ' + self.name
for facet in self.facets:
print >> f, ' facet normal %s %s %s' % (facet.normal.dx, facet.normal.dy, facet.normal.dz)
print >> f, ' outer loop'
for vertex in facet.vertices:
print >> f, ' vertex %s %s %s' % (vertex.x, vertex.y, vertex.z)
print >> f, ' endloop'
print >> f, ' endfacet'
print >> f, 'endsolid ' + self.name
f.close()
import math
from math import pi,sqrt
top_diameter=200.;
bottom_diameter=120.;
height=400.;
top_radius = top_diameter / 2;
bottom_radius = bottom_diameter / 2;
tga = (top_radius - bottom_radius) / height;
total_height = top_radius / tga;
bottom_height = total_height - height;
side_length = sqrt(total_height*total_height + top_radius*top_radius)
flat_a = 2*pi * top_radius / side_length
sina = top_radius / side_length
def conexform(x, y, z):
x, y, z = float(x), float(y), float(z)
nx, ny, nz = 0.0, 0.0, 0.0
r1 = math.sqrt(x*x + y*y)
r2 = r1 / sina
phi = flat_a * (math.atan2(y,x) ) / (2*pi)
nx = r2 * math.cos(phi)
ny = r2 * math.sin(phi)
nz = (z * top_radius/total_height) - r1
nx, ny, nz = str(nx), str(ny), str(nz)
return (nx, ny, nz)
def deconify(fname):
stl = STL(fname)
stl.transform(conexform)
stl.canonicalise()
stl.write("flat-" + fname)
if __name__ == '__main__':
if len(sys.argv) == 2:
deconify(sys.argv[1])
else:
print "usage: deconify file"
sys.exit(1)
When a "flat" stl file is ready. We need to import it to OpenSCAD once again to convert it to DXF for further work. This is quite a simple task
projection(cut=true)
translate([-153,0,-0.2])
rotate([0,0,29.59181771496431])
import(file="flat-cyclone.stl");
The numeric arguments for rotation and translation above match the
values used to create the cone. If you change cones size you need to
adjust them. After pressing F6
in OpenSCAD we get a nice 2D shape
that can be exported as DXF.
A flat surface of the cone ready to be cut.