/* [Siren General Parameters] */ siren_diameter = 125; // Base diameter - 121 for rotor to fit original siren siren_height = 45; // Height of the rotor - 60 for rotor to fit original siren number_of_ports = 3; // Number of ports vertical_tolerance = 2; // Tolerance between stator and rotor radial_tolerance = 1.5; fit_reduction = 0.2; pressure_zone = 0.5; // Percentage of diameter round_radius = 4; // Rounding of top/bottom $fn = $preview ? 32 : 128; // Number of fragments /* [Stator Parameters] */ stator_wall_thickness = 8; // Stator wall thickness number_of_mounting_holes = 4; // Number of mounting holes screw_diameter = 3.2; // Diameter of screws - M3 clearance hole (3.2mm diameter) screw_bore_diameter = 6.5; screw_insert_diameter = 4.5; screw_bore_depth = 2.5; screw_length = 10 - (stator_wall_thickness - screw_bore_depth); stator_screw_offset = siren_diameter/2 - stator_wall_thickness/2; //distance to screws /* [Rotor Parameters] */ rotor_wall_thickness = 3; // Rotor wall thickness hub_height = 3; hub_diameter = 12; blade_angle = 8; rotor_height = siren_height - (vertical_tolerance * 2); port_height = siren_height - (rotor_wall_thickness * 2) - (vertical_tolerance * 2); // Height of the port /* [Motor Parameters] */ motor_shaft_diameter = 8; // Diameter of the motor body motor_frame_diameter = 60; motor_diameter = 28; // Diameter of the motor body motor_height = 24; magnet_diameter = 7; motor_screw_x_offset = 9.5; motor_screw_y_offset = 8; motor_screw_offset = 8; motor_frame_screw_offset = motor_frame_diameter/2 - stator_wall_thickness/2; //distance to screws /* [Base Parameters] */ leg_screw_offset = motor_frame_diameter / 2 + 5; leg_height = motor_height + 10; // helper functions module ports(diameter, height, ports, r_offset = 0) { radius = diameter / 2; angle = (180 / ports) - (r_offset * 6); rotate([0, 0, 180 / ports]) for (i = [0:360/ports:360]) { rotate([0, 0, i + (r_offset * 6 / 2)]) linear_extrude(height) polygon(concat( [[0, 0]], // Center point [for (j = [0 : $fn]) [radius * cos(angle * j / $fn), radius * sin(angle * j / $fn)]] )); } } module column(outer_diameter, inner_diameter, height, z_offset = 0) { difference(){ // Outer cylinder cylinder(d = outer_diameter, h = height); // Subtract inner cylinder translate([0, 0, z_offset]) cylinder(d = inner_diameter, h = height - z_offset); } } module rounded_column(outer_diameter, inner_diameter, height, z_offset = 0){ difference() { // Rounded top intersection() { // Unrounded full cylinder cylinder(d = outer_diameter, h = height); // Add Minkowski rounded version minkowski() { cylinder(h = height - round_radius, d = outer_diameter - round_radius * 2); sphere(r = round_radius); } } // Subtract inner cylinder translate([0, 0, z_offset]) cylinder(d = inner_diameter, h = height); } } module counter_bored_holes(screw_offset){ // Subtract mounting holes for stator for (i = [0:360/number_of_mounting_holes:360]) { // Subtract screw hole rotate([0, 0, i]) translate([screw_offset, 0, -1]) // Adjusted position cylinder(d = screw_diameter, h = stator_wall_thickness + 2); // Subtract counterbore rotate([0, 0, i]) translate([screw_offset, 0, stator_wall_thickness - screw_bore_depth]) // Adjusted position cylinder(d = screw_bore_diameter, h = stator_wall_thickness); } } module mounting_holes(screw_offset){ for (i = [0:360/number_of_mounting_holes:360]) { rotate([0, 0, i]) translate([screw_offset, 0, 0]) cylinder(d = screw_insert_diameter, h = screw_length); } } // Linear Interpolation function lerp(a, b, t) = a * (1 - t) + b * t; // Arc between points function function arc_between_points(p1, p2, height, steps=20) = [for(t = [0:1/steps:1]) let( x = lerp(p1.x, p2.x, t), y = lerp(p1.y, p2.y, t), // Parabolic arc height calculation arc_height = height * (1 - pow(2*t-1, 2)) ) [x, y + arc_height] ]; function bezier_curve(t, p0, p1, p2, p3, p4) = pow(1-t, 4) * p0 + 4 * pow(1-t, 3) * t * p1 + 6 * pow(1-t, 2) * pow(t, 2) * p2 + 4 * (1-t) * pow(t, 3) * p3 + pow(t, 4) * p4; function curved_polygon(points, steps, x_shift, y_shift) = let( left_curve = [for (t = [0 : 1/steps : 1]) bezier_curve(t, points[0], points[1], points[2], points[3], points[4]) ], right_curve = [for (pt = left_curve) [pt[0] + x_shift, pt[1] + y_shift] ] ) concat(left_curve, [for (i = [len(right_curve)-1 : -1 : 0]) right_curve[i]]); module stator() { difference() { // Create column column(siren_diameter, siren_diameter - (stator_wall_thickness * 2), siren_height); // Subtract ports translate([0, 0, (siren_height - port_height) / 2]) ports(siren_diameter, port_height, number_of_ports); mounting_holes(stator_screw_offset); translate([0, 0, siren_height - screw_length]) mounting_holes(stator_screw_offset); } } module impeller_blade(radius, rotor_height){ // Generate points points1 = arc_between_points([0, -hub_diameter / 2], [radius, 0], -blade_angle); points2 = [for(p = [len(points1)-1:-1:0]) points1[p] - [0, -rotor_wall_thickness]]; // Create the blade by combining top and bottom points linear_extrude(height = rotor_height) polygon(concat(points1, points2)); } module impeller_blades_curved(radius, rotor_height){ difference() { union() { // Rotate and create blades for (i = [0:360/number_of_ports:360]) { rotate([0, 0, i]) impeller_blade(radius, rotor_height); } } top_rounding_radius = 5; bottom_rounding_radius = rotor_height / 2 - 1; //bottom_rounding_radius = rotor_height / 2 - 10; // this needs to be adjusted based on the rotor diameter and height top_diameter = (siren_diameter * pressure_zone) + (top_rounding_radius * 2); bottom_diameter = (siren_diameter * pressure_zone) - (2 * bottom_rounding_radius); top_height = top_rounding_radius + 10; bottom_height = rotor_height - bottom_rounding_radius - (top_rounding_radius * 2) + 2; translate([0, 0, rotor_height - top_rounding_radius]) union(){ difference() { // Column cylinder(d = top_diameter, h = top_height); // Top torus rotate_extrude() translate([top_diameter / 2, 0, 0]) circle(r = top_rounding_radius); } rotate([180, 0, 0]) minkowski() { // Original cylinder, reduced by twice the rounding radius cylinder(d = bottom_diameter, h = bottom_height); // Sphere for rounding sphere(r = bottom_rounding_radius); } } } } module rotor() { rotor_diameter = siren_diameter - (stator_wall_thickness * 2) - (radial_tolerance * 2); rotor_inner_diameter = rotor_diameter - (rotor_wall_thickness * 2); difference() { union(){ difference() { column(rotor_diameter, rotor_inner_diameter, rotor_height, rotor_wall_thickness); // Subtract ports translate([0, 0, (rotor_height - port_height) / 2]) ports(rotor_diameter, port_height, number_of_ports); } // Add blades impeller_blades_curved(rotor_inner_diameter / 2, rotor_height); } translate([0, 0, 0]) hub_attachment(fit_reduction); } } module hub(aug = 0) { height = (rotor_wall_thickness * 2) + hub_height; difference(){ union(){ hub_attachment(aug); cylinder(d = motor_shaft_diameter + 2, h = height); } intersection(){ cylinder(d = motor_shaft_diameter, h = height); cube([motor_shaft_diameter, motor_shaft_diameter-1, height * 2], center = true); }; cylinder(d = motor_shaft_diameter, h = 2); } } module hub_attachment(aug = 0) { insert_width = 2; outer_diameter = hub_diameter + (insert_width * 6) + (aug * 2); mid_diameter = hub_diameter + (insert_width * 2) + (aug * 2); inner_diameter = outer_diameter - (insert_width * 2) - (aug * 4); difference(){ column(outer_diameter, inner_diameter, rotor_wall_thickness); //translate([0, 0, -10]) ports(outer_diameter, rotor_wall_thickness, number_of_ports, aug * 2); } translate([0, 0, rotor_wall_thickness]) cylinder(d = outer_diameter, rotor_wall_thickness); cylinder(d = mid_diameter, rotor_wall_thickness * 2); } module stator_top() { difference(){ rounded_column( siren_diameter, siren_diameter * pressure_zone, stator_wall_thickness ); counter_bored_holes(stator_screw_offset); } } module stator_bottom() { //rotate([180, 0, 0]) difference() { rounded_column( siren_diameter, motor_diameter + (radial_tolerance * 2), stator_wall_thickness ); counter_bored_holes(stator_screw_offset); // Subtract mounting holes for motor frame rotate([180, 0, 0]) translate([0, 0, -stator_wall_thickness]) counter_bored_holes(motor_frame_screw_offset); rotate([180, 0, 0]) translate([0, 0, -stator_wall_thickness]) counter_bored_holes(leg_screw_offset); translate([0, 0, stator_wall_thickness]) rotate([0, 0, -45/2 - 0.6]) for (i = [0:360/number_of_mounting_holes:360]) { rotate([0, 0, i]) { leg(fit_reduction); } } } } module motor_frame() { //rotate([180, 0, 0]) //translate([0, 0, -stator_wall_thickness]) motor_frame_height = motor_height - stator_wall_thickness - vertical_tolerance; difference(){ union(){ inner_diameter = motor_frame_diameter - (stator_wall_thickness * 2); difference(){ rounded_column( motor_frame_diameter, inner_diameter, motor_frame_height + stator_wall_thickness, -stator_wall_thickness ); translate([0, 0, stator_wall_thickness]) ports(inner_diameter, motor_frame_height, number_of_mounting_holes); //translate([0, 0, -stator_wall_thickness]) //rotate([0, 0, -45/2]) ports(motor_frame_diameter, motor_frame_height, number_of_mounting_holes); rotate([0, 0, 45/2]) mounting_holes(motor_frame_screw_offset); } translate([0, 0, motor_frame_height]) column(motor_screw_x_offset * 2 + (radial_tolerance * 2) , magnet_diameter + (radial_tolerance * 2), stator_wall_thickness); } // Subtract mounting holes for motor translate([0, 0, motor_frame_height]) rotate([0, 0, 45/2]) for (i = [0:360/number_of_mounting_holes:360]) { rotate([0, 0, i]) { // Use modulo to alternate between x and y offsets motor_screw_offset = (floor(i / (360/number_of_mounting_holes)) % 2 == 0) ? motor_screw_x_offset : motor_screw_y_offset; translate([motor_screw_offset, 0, 0]) cylinder(d = screw_diameter, h = stator_wall_thickness); } } translate([0, 0, motor_frame_height]) cylinder(d = magnet_diameter + (radial_tolerance * 2), h = stator_wall_thickness); } } module leg(aug = 0) { motor_spacing = 15; points = [ [leg_screw_offset + 10, leg_height], [leg_screw_offset + 5, leg_height-5], [leg_screw_offset + 0, leg_height / 2], [leg_screw_offset + 5, 5], [leg_screw_offset + 10, 0] ]; rotate_extrude(angle = 360/8) { polygon(curved_polygon( points, steps = 100, x_shift = -stator_wall_thickness / 2, y_shift = 0 )); } rotate([0, 0, 12 - (aug / 2)]) translate([0, 0, -1]) difference(){ rotate_extrude(angle = 360/16 + aug) { translate([leg_screw_offset - ((screw_insert_diameter + radial_tolerance) / 2) - aug, 0, 0]) square([screw_insert_diameter + radial_tolerance + aug * 2, leg_height + 2]); } if(aug == 0){ rotate([0, 0, 45/4 - aug]) //translate([0, 0, -2]) mounting_holes(leg_screw_offset); rotate([0, 0, 45/4 - aug]) translate([0, 0, leg_height - screw_length + 2]) mounting_holes(leg_screw_offset); } } } module base() { difference(){ rounded_column( siren_diameter, (leg_screw_offset - ((screw_diameter + radial_tolerance) / 2)) * 2 - 5, stator_wall_thickness ); counter_bored_holes(stator_screw_offset); translate([0, 0, stator_wall_thickness]) rotate([180, 0, 0]) //counter_bored_holes(leg_screw_offset - ((screw_diameter + tolerance) / 2)); //rotate([0, 0, -45/2]) counter_bored_holes(leg_screw_offset); translate([0, 0, stator_wall_thickness]) rotate([0, 0, -45/2 - 0.6]) for (i = [0:360/number_of_mounting_holes:360]) { rotate([0, 0, i]) { leg(fit_reduction); } } } } //rotate([0, 0, 0]) //translate([0, 0, 0]) //rotor(); //motor_shaft_diameter = 8.2; hub(0.1); //stator(); //base(); //stator_bottom(); //rotate([0, 0, 0]) //translate([siren_diameter, 0, vertical_tolerance]) //rotor(); //stator_bottom(); //rotate([0, 0, 67.5]) //motor_frame(); //rotate([0, 0, 0]) //translate([0, 0, siren_height + 2]) //stator_top(); //rotate([180, 0, 0]) //translate([0, 0, 2]) //stator_bottom(); //rotate([180, 0, 45]) //translate([0, 0, stator_wall_thickness + 5]) //motor_frame(); //leg(); //base(); /* rotate([0, 0, 0]) translate([0, 0, -leg_height - 15 - stator_wall_thickness - 2]) base(); rotate([0, 0, -45/2]) translate([0, 0, -leg_height - 15]) for (i = [0:360/number_of_mounting_holes:360]) { rotate([0, 0, i]) { leg(); } } */ /* //translate([0, 0, 2]) intersection(){ //color("red") rotor(); cylinder(d = 30, h = 10); } translate([040, 0, 0]) hub(); */