Difference between revisions of "UltrasonicSensorServoMount"

From BITPlan Wiki
Jump to navigation Jump to search
(Created page with "<!DOCTYPE html> <html><head> <script src="https://risacher.org/OpenJsCad/lightgl.js"></script> <script src="https://risacher.org/OpenJsCad/csg.js"></script> <script src...")
 
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
<!DOCTYPE html>
+
{{jscad|code=
 +
//Parametric.
 +
//Oktay Gülmez, 23/2/2016.
 +
// converted to OpenJSCAD by Wolfgang Fahl 2019-06-09
 +
//GNU_GPL_V3
  
<html><head>
+
// include("Bezier.jscad")
  <script src="https://risacher.org/OpenJsCad/lightgl.js"></script>
 
  <script src="https://risacher.org/OpenJsCad/csg.js"></script>
 
  <script src="https://risacher.org/OpenJsCad/openjscad.js"></script>
 
  <style>
 
  
body {
+
/**
  font: 14px/20px 'Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, Arial, sans-serif;
+
* create front Plate
  max-width: 820px;
+
*/
  margin: 0 auto;
+
function frontPlate(thickness, eyes_width, eyes_diameter) {
  padding: 10px;
+
   safety = 0.6;
}
+
   radius = eyes_diameter+2;
 
+
   radius2 = 5;
pre, code, textarea {
+
   var parts = [];
  font: 12px/20px Monaco, monospace;
 
  border: 1px solid #CCC;
 
  border-radius: 3px;
 
  background: #F9F9F9;
 
  padding: 0 3px;
 
  color: #555;
 
}
 
pre, textarea {
 
  padding: 10px;
 
  width: 100%;
 
}
 
textarea {
 
  height: 200px;
 
}
 
textarea:focus {
 
  outline: none;
 
}
 
 
 
canvas { cursor: move; }
 
 
 
  </style>
 
<link rel="stylesheet" href="openjscad.css" type="text/css">
 
 
 
<script>
 
 
 
var gProcessor=null;
 
 
 
// Show all exceptions to the user:
 
OpenJsCad.AlertUserOfUncaughtExceptions();
 
 
 
function onload()
 
{
 
  let viewer = document.getElementById("viewer");
 
  gProcessor = new OpenJsCad.Processor(viewer);
 
  updateSolid();
 
}
 
 
 
function updateSolid()
 
{
 
  gProcessor.setJsCad(document.getElementById('code').value);
 
}
 
</script>
 
<title>OpenJsCad demo: Parametric Lamp Shade</title>
 
</head>
 
<body onload="onload()">
 
  <h1>OpenJsCad demo: Parametric Lamp Shade</h1>
 
<div id="viewer"></div>
 
  <h2>Source code</h2>
 
Below is the OpenJsCad script for this demo. To build your own models, create a .jscad script
 
and use the <a href="processfile.html"><b>OpenJsCad parser</b></a>. For more information see the
 
<a href="index.html">OpenJsCad documentation</a>.
 
<br><br>
 
<textarea id="code" style="height: 500px">
 
function main(params)
 
{
 
  CSG.defaultResolution2D = (params.quality == "DRAFT")? 8:32;
 
 
 
  var bottomradius = params.bottomdiameter/2;
 
  var topradius = params.topdiameter/2;
 
  var height = params.height;
 
  var numfaces = params.numfaces;
 
  var thickness = params.thickness;
 
  var topholeradius = params.topholediameter/2;
 
  var cutterRadius = params.cutterdiameter / 2;
 
 
 
  var solid = CSG.cube({radius: [1000, 1000, height/2]});
 
 
 
  var plane = CSG.Plane.fromPoints([bottomradius, 0, -height/2], [bottomradius, 10, -height/2], [topradius, 0, height/2]);
 
   for(var i = 0; i < numfaces; i++)
 
  {
 
    solid = solid.cutByPlane(plane.rotateZ(i * 360 / numfaces));
 
   }
 
 
 
  var plates = solidToOuterShellPlates(solid, thickness);
 
  plates = removePlateWithNormal(plates, [0,0,-1]);
 
  plates = removePlateWithNormal(plates, [0,0,1]);
 
 
 
  for(var i = 1; i < numfaces; i++)
 
  {
 
    plates[i] = plates[0].rotateZ(i * 360 / numfaces);
 
  }
 
 
 
  var topplate = getStockPlate(1000,1000,thickness)
 
    .subtract(CSG.cylinder({start: [0,0,-thickness], end:[ 0,0,thickness], radius: topholeradius}))
 
    .translate([0,0,height/2-thickness/2-10]);
 
  topplate = topplate.intersect(solid);
 
   topplate = fixPlate(topplate, thickness);
 
 
 
   var fingerjointoptions = {
 
    margin: 0, cutterRadius: cutterRadius, fingerWidth: 25
 
  };
 
  plates = fingerJoint(plates,fingerjointoptions);
 
  plates = fingerJointAdd(plates, topplate, fingerjointoptions);
 
 
 
  if(params.type == "TOPPLATE")
 
  {
 
    return plateCSGToCAG(plates[numfaces]);
 
  }
 
  else
 
  {
 
    var plate2d = plateCSGToCAG(plates[0]);
 
    plate2d = addRandomHoles(plate2d);
 
    if(params.type == "SIDEPLATE")
 
    {
 
      return plate2d;
 
    }
 
    else
 
    {
 
      for(var i = 0; i < numfaces; i++)
 
      {
 
        var plate3d =  plateCAGToCSG(plate2d, plates[i].properties.platebasis, thickness);
 
        plates[i] = plate3d;
 
      }
 
      var result = new CSG().union(plates);
 
      result = result.rotateX(90);
 
      return result;
 
    }
 
  }
 
}
 
 
 
function addRandomHoles(plate)
 
{
 
  var distancefromedge = 8;
 
  var distancebetweenholes = 10;
 
  var mindiameter = 10;
 
  var maxdiameter = 25;
 
  // maskarea: the 'forbidden' area for holes:
 
  var maskarea = plate.contract(distancefromedge, 4);
 
  var bounds = maskarea.getBounds();
 
  var maskarea = maskarea.flipped();
 
 
   var holes = [];
 
   var holes = [];
   var existingholecenters = [];
+
   //Front plate:
   var existingholeradii = [];
+
   parts.push(linear_extrude({
  for(var i = 0; i < 10; i++)
+
    height: thickness,
  {
+
     convexity: 10,
     for(var tryindex = 0; tryindex < 10; tryindex++)
+
     fn: 60
     {
+
  }, hull(
      var holeradius = (mindiameter + Math.random() * (maxdiameter - mindiameter))/2;
+
    translate([-eyes_width / 2, 0, 0], circle({
       var x = bounds[0].x + holeradius + (bounds[1].x - bounds[0].x - holeradius*2) * Math.random();
+
      r: radius,
      var y = bounds[0].y + holeradius + (bounds[1].y - bounds[0].y - holeradius*2) * Math.random();
+
       center: true
       var holecenter = new CSG.Vector2D(x,y);
+
    })),
       var valid = true;
+
    translate([eyes_width / 2, 0, 0], circle({
       // check if the hole is too close to one of the existing holes:
+
      r: radius,
       var numexistingholes = existingholecenters.length;
+
      center: true
      for(var i2 = 0; i2 < numexistingholes; i2++)
+
    }))
      {
+
  )));
        var d = holecenter.minus(existingholecenters[i2]).length();
+
  parts.push(linear_extrude({
        if(d < holeradius+existingholeradii[i2] + distancebetweenholes)
+
    height: thickness,
        {
+
    convexity: 10,
          valid = false;
+
    fn: 60
          break;
+
  }, hull(
        }
+
    translate([-eyes_width / 2, 0, 0], circle({
      }
+
       r: radius,
      if(valid)
+
       center: true
      {
+
    })),
        // check if the hole is not too close to the edges:
+
    translate([-8, -30, 0], circle({
        var hole = CAG.circle({radius: holeradius, center: holecenter});
+
       r: radius2,
        var testarea = maskarea.intersect(hole);
+
       center: true
        if(testarea.sides.length != 0) valid = false;
+
    }))
       }
+
  )));
       if(valid)
+
  parts.push(linear_extrude({
      {
+
    height: thickness,
        existingholeradii.push(holeradius);
+
    convexity: 10,
        existingholecenters.push(holecenter);
+
    fn: 60
        holes.push(hole);
+
  }, hull(
        break;
+
    translate([eyes_width / 2, 0, 0], circle({
       }
+
      r: radius,
     }
+
      center: true
 +
    })),
 +
    translate([8, -30, 0], circle({
 +
       r: radius2,
 +
       center: true
 +
    }))
 +
  )));
 +
  parts.push(translate([-8, -35, 0], cube([16, 35, thickness])));
 +
  //Transducers holes:
 +
  for (fx = -1; fx <= 1; fx += 2) {
 +
    holes.push(translate([fx * eyes_width / 2, 0, thickness / 2], cylinder({
 +
      h: thickness + 2,
 +
      r: eyes_diameter / 2 + safety,
 +
      fn: 50,
 +
       center: true
 +
     })));
 
   }
 
   }
   return plate.subtract(holes);
+
   return difference(union(parts), union(holes));
 
}
 
}
  
function plateCSGToCAG(plate)
+
//Servo mounting bracket
{
+
function servoBracket() {
   if(!("platebasis" in plate.properties))
+
  radius = 8;
   {
+
  radius2 = 5;
     throw new Error("Plates should be created using getStockPlate()");
+
   return translate([0, -35, 0], rotate([-90, -90, 0], linear_extrude({
  }
+
    height: 6,
   var plate2d = plate.projectToOrthoNormalBasis(plate.properties.platebasis);
+
    convexity: 10
  return plate2d;
+
   }, hull(
 +
     translate([0, 0, 0], circle({
 +
      r: radius,
 +
      center: true
 +
    })),
 +
    translate([23, 0, 0], circle({
 +
      r: radius2,
 +
      center: true
 +
    }))
 +
   ))));
 
}
 
}
  
function plateCAGToCSG(plate2d, platebasis, thickness)
+
function tabsPCB_Mounting(length,width) {
{
+
  //Sensor PCB mounting tabs:
   var basisinversematrix = platebasis.getInverseProjectionMatrix();
+
   var parts = [];
   var plate_reprojected = plate2d.extrude({offset: [0,0,thickness]}).translate([0,0,-thickness/2]);
+
   var holes = [];
   plate_reprojected = plate_reprojected.transform(basisinversematrix);
+
   height = 3.5;
   plate_reprojected.properties.platebasis = platebasis;
+
   outer = 3;
   return plate_reprojected;
+
   inner = 1;
}
+
  for (fx = -1; fx <= 1; fx += 2) {
 
+
    for (fy = -1; fy <= 1; fy += 2) {
function fixPlate(plate, thickness)
+
      parts.push(translate([fx *length / 2, fy * width / 2, 0], cylinder({
{
+
        h: thickness + height,
  return plateCAGToCSG(plateCSGToCAG(plate), plate.properties.platebasis, thickness);
+
        r: outer
}
+
      })));
 
+
      //Sensor PCB mounting screws holes:
function removePlateWithNormal(plates, normalvector)
+
      holes.push(translate([fx * length / 2, fy * width / 2, 1], cylinder({
{
+
        h: thickness + height,
  normalvector = new CSG.Vector3D(normalvector);
+
        r: inner
  var result = [];
+
       })));
  plates.map(function(plate){
 
    if(!("platebasis" in plate.properties))
 
    {
 
       throw new Error("Plates should be created using getStockPlate()");
 
 
     }
 
     }
    if(plate.properties.platebasis.plane.normal.dot(normalvector) < 0.9999)
 
    {
 
      result.push(plate);
 
    }
 
  });
 
  return result;
 
}
 
 
function getStockPlate(width, height, thickness)
 
{
 
  var result = CSG.cube({radius: [width/2, height/2, thickness/2]});
 
  result.properties.platebasis = CSG.OrthoNormalBasis.Z0Plane();
 
  return result;
 
}
 
 
function fingerJointAdd(plates, newplate, options)
 
{
 
  var result = plates.slice(0);
 
  var numplates = plates.length;
 
  for(var plateindex1 = 0; plateindex1 < numplates; plateindex1++)
 
  {
 
    var joined = fingerJointTwo(result[plateindex1], newplate, options);
 
    result[plateindex1] = joined[0];
 
    newplate = joined[1];
 
 
   }
 
   }
   result.push(newplate);
+
   return difference(union(parts), union(holes));
  return result;
 
 
}
 
}
  
// Finger joint between multiple plates:
+
function servoHead() {
function fingerJoint(plates, options)
+
   var parts = [];
{
+
   //Servo head placement:
   var result = plates.slice(0);
+
   parts.push(translate([0, -35, 8], rotate([-90, 0, 0], cylinder({
   var numplates = plates.length;
+
    h: 2.5,
   var maxdelta = Math.floor(numplates/2);
+
    r: 3.8
  for(var delta=1; delta <= maxdelta; delta++)
+
   }))));
  {
+
   parts.push(translate([0, -35 - 1, 8], rotate([-90, 0, 0], cylinder({
    for(var plateindex1 = 0; plateindex1 < numplates; plateindex1++)
+
    h: 8,
    {
+
     r: 1.25
      var plateindex2 = plateindex1 + delta;
+
   }))));
      if(plateindex2 >= numplates) plateindex2 -= numplates;
+
   parts.push(translate([0, -35 + 4.5, 8], rotate([-90, 0, 0], cylinder({
 
+
     h: 3,
      var joined = fingerJointTwo(result[plateindex1], result[plateindex2], options);
+
     r: 3
      result[plateindex1] = joined[0];
+
  }))));
      result[plateindex2] = joined[1];
+
  parts.push(translate([0, -35 - 1, 23], rotate([-90, 0, 0], cylinder({
      if(delta*2 >= numplates)
+
     h: 8,
      {
+
     r: 1
        // numplates is even
+
  }))));
        if(plateindex1*2 >= numplates)
 
        {
 
          // and we've done the first half: we're done
 
          break;
 
        }
 
      }
 
    }
 
   }
 
   return result;
 
}
 
 
 
function fingerJointTwo(plate1, plate2, options)
 
{
 
  if(!options) options = {};
 
  if(!("platebasis" in plate1.properties))
 
  {
 
     throw new Error("Plates should be created using getStockPlate()");
 
   }
 
  if(!("platebasis" in plate2.properties))
 
  {
 
    throw new Error("Plates should be created using getStockPlate()");
 
   }
 
  // get the intersection solid of the 2 plates:
 
  var intersection = plate1.intersect(plate2);
 
  if(intersection.polygons.length == 0)
 
  {
 
    // plates do not intersect. Return unmodified:
 
    return [plate1, plate2];
 
  }
 
  else
 
  {
 
     var plane1 = plate1.properties.platebasis.plane;
 
    var plane2 = plate2.properties.platebasis.plane;
 
    // get the intersection line of the 2 center planes:
 
     var jointline = plane1.intersectWithPlane(plane2);
 
    // Now we need to find the two endpoints on jointline (the points at the edges of intersection):
 
    // construct a plane perpendicular to jointline:
 
    var plane1 = CSG.Plane.fromNormalAndPoint(jointline.direction, jointline.point);
 
    // make the plane into an orthonormal basis:
 
    var basis1 = new CSG.OrthoNormalBasis(plane1);
 
    // get the projection matrix for the orthobasis:
 
    var matrix = basis1.getProjectionMatrix();
 
    // now transform the intersection solid:
 
    var intersection_transformed = intersection.transform(matrix);
 
    var bounds = intersection_transformed.getBounds();
 
    // now we know the two edge points. The joint line runs from jointline_origin, in the
 
    // direction jointline_direction and has a length jointline_length (jointline_length >= 0)
 
    var jointline_origin = jointline.point.plus(jointline.direction.times(bounds[0].z));
 
     var jointline_direction = jointline.direction;
 
     var jointline_length = bounds[1].z - bounds[0].z;
 
 
 
    var fingerwidth = options.fingerWidth || (jointline_length / 4);
 
    var numfingers=Math.round(jointline_length / fingerwidth);
 
    if(numfingers < 2) numfingers=2;
 
    fingerwidth = jointline_length / numfingers;
 
  
    var margin = options.margin || 0;
+
  parts.push(translate([0, -35, 8], rotate([-90, -90, 0], linear_extrude({
     var cutterRadius = options.cutterRadius || 0;
+
     height: 2.5,
     var results = [];
+
     convexity: 10
    for(var plateindex = 0; plateindex < 2; plateindex++)
+
  }, hull(
     {
+
     translate([0, 0, 0], circle({
      var thisplate = (plateindex == 1)? plate2:plate1;
+
       r: 3.5,
      // var otherplate = (plateindex == 1)? plate1:plate2;
+
       center: true
       // create a new orthonormal basis for this plate, such that the joint line runs in the positive x direction:
+
    })),
      var platebasis = new CSG.OrthoNormalBasis(thisplate.properties.platebasis.plane, jointline_direction);
+
    translate([15, 0, 0], circle({
       // get the 2d shape of our plate:
+
       r: 2,
      var plate2d = thisplate.projectToOrthoNormalBasis(platebasis);
+
      center: true
      var jointline_origin_2d = platebasis.to2D(jointline_origin);
+
    }))
      matrix = platebasis.getProjectionMatrix();
+
  )))));
      intersection_transformed = intersection.transform(matrix);
+
  return union(parts);
      bounds = intersection_transformed.getBounds();
 
      var maxz = bounds[1].z;
 
      var minz = bounds[0].z;
 
      var maxy = bounds[1].y + margin/2;
 
      var miny = bounds[0].y - margin/2;
 
 
 
      var cutouts2d = [];
 
      for(var fingerindex = 0; fingerindex < numfingers; fingerindex++)
 
       {
 
        if( (plateindex == 0) && ((fingerindex & 1)==0) ) continue;
 
        if( (plateindex == 1) && ((fingerindex & 1)!=0) ) continue;
 
        var minx = jointline_origin_2d.x + fingerindex * fingerwidth - margin/2;
 
        var maxx = minx + fingerwidth + margin;
 
        var cutout = createRectCutoutWithCutterRadius(minx, miny, maxx, maxy, cutterRadius, plate2d);
 
        cutouts2d.push(cutout);
 
      }
 
      var cutout2d = new CAG().union(cutouts2d);
 
      var cutout3d = cutout2d.extrude({offset: [0,0,maxz-minz]}).translate([0,0,minz]);
 
      cutout3d = cutout3d.transform(platebasis.getInverseProjectionMatrix());
 
      var thisplate_modified = thisplate.subtract(cutout3d);
 
      results[plateindex] = thisplate_modified;
 
    }
 
    return results;
 
  }
 
 
}
 
}
  
// Create a rectangular cutout in 2D
+
/**
// minx, miny, maxx, maxy: boundaries of the rectangle
+
* create a smile
// cutterRadius: if > 0, add extra cutting margin at the corners of the rectangle
+
*/
// plate2d is the 2d shape from which the cutout will be subtracted
+
function smile(thickness) {
// it is tested at the corners of the cutout rectangle, to see if do need to add the extra margin at that corner
+
   /*bezier = BezierFactory.create(0,0);
function createRectCutoutWithCutterRadius(minx, miny, maxx, maxy, cutterRadius, plate2d)
+
  bezier.append([
{
+
    [0,15],
   var deltax = maxx-minx;
+
    [15,15]
  var deltay = maxy-miny;
+
   ]);
  var cutout = CAG.rectangle({radius: [(maxx-minx)/2, (maxy-miny)/2], center: [(maxx+minx)/2, (maxy+miny)/2]});
+
   return rotate([0,0,135],bezier.spline(thickness)).translate([10,0,0]);
  var cornercutouts = [];
+
   */
  if(cutterRadius > 0)
 
  {
 
    var extracutout = cutterRadius * 0.2;
 
    var hypcutterradius = cutterRadius / Math.sqrt(2.0);
 
    var halfcutterradius = 0.5 * cutterRadius;
 
    var dcx, dcy;
 
    if(deltax > 3*deltay)
 
    {
 
      dcx = cutterRadius + extracutout/2;
 
      dcy = extracutout / 2;
 
    }
 
    else if(deltay > 3*deltax)
 
    {
 
      dcx = extracutout / 2;
 
      dcy = cutterRadius + extracutout/2;
 
    }
 
    else
 
    {
 
      dcx = hypcutterradius-extracutout/2;
 
      dcy = hypcutterradius-extracutout/2;
 
    }
 
    for(var corner = 0; corner < 4; corner++)
 
    {
 
      var cutoutcenterx = (corner & 2)? (maxx-dcx):(minx+dcx);
 
      var cutoutcentery = (corner & 1)? (maxy-dcy):(miny+dcy);
 
      var cornercutout = CAG.rectangle({radius: [cutterRadius+extracutout/2, cutterRadius+extracutout/2], center: [cutoutcenterx, cutoutcentery]});
 
      var testrectacenterx = (corner & 2)? (maxx-halfcutterradius):(minx+halfcutterradius);
 
      var testrectbcenterx = (corner & 2)? (maxx+halfcutterradius):(minx-halfcutterradius);
 
      var testrectacentery = (corner & 1)? (maxy+halfcutterradius):(miny-halfcutterradius);
 
      var testrectbcentery = (corner & 1)? (maxy-halfcutterradius):(miny+halfcutterradius);
 
      var testrecta = CAG.rectangle({radius: [halfcutterradius, halfcutterradius], center: [testrectacenterx, testrectacentery]});
 
      var testrectb = CAG.rectangle({radius: [halfcutterradius, halfcutterradius], center: [testrectbcenterx, testrectbcentery]});
 
      if( (plate2d.intersect(testrecta).sides.length > 0)
 
      && (plate2d.intersect(testrectb).sides.length > 0) )
 
      {
 
        cornercutouts.push(cornercutout);
 
      }
 
    }
 
   }
 
  if(cornercutouts.length > 0)
 
  {
 
    cutout = cutout.union(cornercutouts);
 
  }
 
   return cutout;
 
}
 
 
 
function solidToOuterShellPlates(csg, thickness)
 
{
 
  csg = csg.canonicalized();
 
  var bounds = csg.getBounds();
 
  var csgcenter = bounds[1].plus(bounds[0]).times(0.5);
 
  var csgradius = bounds[1].minus(bounds[0]).length();
 
  var plane2polygons = {};
 
  csg.polygons.map(function(polygon){
 
    var planetag = polygon.plane.getTag();
 
    if(!(planetag in plane2polygons))
 
    {
 
      plane2polygons[planetag] = [];
 
    }
 
    plane2polygons[planetag].push(polygon);
 
  });
 
  var plates = [];
 
  for(var planetag in plane2polygons)
 
  {
 
    var polygons = plane2polygons[planetag];
 
    var plane = polygons[0].plane;
 
    var shellcenterplane = new CSG.Plane(plane.normal, plane.w - thickness/2);
 
    var basis = new CSG.OrthoNormalBasis(shellcenterplane);
 
    var inversebasisprojection = basis.getInverseProjectionMatrix();
 
    var csgcenter_projected = basis.to2D(csgcenter);
 
    var plate = getStockPlate(csgradius, csgradius, thickness).translate([csgcenter_projected.x, csgcenter_projected.y, 0]);
 
    plate = plate.transform(inversebasisprojection);
 
    plate = plate.intersect(csg);
 
    plates.push(plate);
 
   }
 
  return plates;
 
 
}
 
}
  
function getParameterDefinitions()
+
/**
{
+
* create a parametric ultrasonic sensor
   return [
+
*/
    {name: 'topdiameter', type: 'float', default: 160, caption: "Top diameter:"},
+
function main() {
    {name: 'bottomdiameter', type: 'float', default: 300, caption: "Bottom diameter:"},
+
   BezierFactory();
    {name: 'height', type: 'float', default: 170, caption: "Height:"},
+
  //Parameters:
    {name: 'numfaces', type: 'int', default: 5, caption: "Number of faces:"},
+
  //The diameter of the transducer in mm.: 16mm. mostly.
    {name: 'thickness', type: 'float', default: 4, caption: "Thickness of stock material:"},
+
  eyes_diameter = 16;
    {name: 'topholediameter', type: 'float', default: 42, caption: "Diameter of top hole:"},
+
  //Distance between centers of transducers in mm.: 25.4mm for HC-SR04.
    {name: 'cutterdiameter', type: 'float', default: 3.2, caption: "Diameter of CNC cutter / laser beam:"},
+
  width = 41.5
 +
  eyes_width = 25.4;
  
    {
+
  //Sensor PCB mounting holes in mm.: 41.4x17 for HC-SR04.
      name: 'type',
+
  mount_length = 42.35;
      type: 'choice',
+
  mount_width = 17.4;
      values: ["ASSEMBLED", "TOPPLATE", "SIDEPLATE"],              // these are the values that will be supplied to your script
+
  //Desired thickness in mm.: Maximum 5mm.
      captions: ["Assembled", "Top plate (DXF output)", "Side plate (DXF output)"],  // optional, these values are shown in the listbox
+
  thickness = 2.5;
                                                  // if omitted, the items in the 'values' array are used
+
  //Decorations: "1" smile, "2" teeth, "3" vampire, "4" mustage, "5" O, other for none.
      caption: 'Show:',                          // optional, displayed left of the input field
+
  face = 1;
      default: "ASSEMBLED",                              // optional, default selected value
 
                                                  // if omitted, the first item is selected by default
 
    },
 
    {
 
      name: 'quality',
 
      type: 'choice',
 
      values: ["DRAFT", "HIGH"],               // these are the values that will be supplied to your script
 
      captions: ["Draft", "High"],  // optional, these values are shown in the listbox
 
                                                  // if omitted, the items in the 'values' array are used
 
      caption: 'Quality:',                          // optional, displayed left of the input field
 
      default: "DRAFT",                             // optional, default selected value
 
                                                  // if omitted, the first item is selected by default
 
    },
 
  
 
+
  fn = 20;
 
+
  var parts = [];
   ];
+
  var holes = [];
 +
  parts.push(frontPlate(thickness, eyes_width, eyes_diameter));
 +
  parts.push(servoBracket());
 +
  parts.push(tabsPCB_Mounting(mount_length,mount_width));
 +
   // holes.push(smile(thickness).translate([0, -20, 0]));
 +
  holes.push(servoHead())
 +
  //Cleaning overhang:
 +
  holes.push(translate([-10, -35, -10], cube([20, 10, 10])));
 +
  return difference(union(parts), union(holes));
 
}
 
}
</textarea><br>
+
}}
<input type="submit" value="Update" onclick="updateSolid(); return false;">
 
<br><br>
 
</body>
 
</html>
 

Latest revision as of 09:05, 10 June 2019

The preview below currently only works for older JSCad code using the CSG syntax. See OpenJsCad Issue 448 <jscad>//Parametric. //Oktay Gülmez, 23/2/2016. // converted to OpenJSCAD by Wolfgang Fahl 2019-06-09 //GNU_GPL_V3

// include("Bezier.jscad")

/**

* create front Plate
*/

function frontPlate(thickness, eyes_width, eyes_diameter) {

 safety = 0.6;
 radius = eyes_diameter+2;
 radius2 = 5;
 var parts = [];
 var holes = [];
 //Front plate:
 parts.push(linear_extrude({
   height: thickness,
   convexity: 10,
   fn: 60
 }, hull(
   translate([-eyes_width / 2, 0, 0], circle({
     r: radius,
     center: true
   })),
   translate([eyes_width / 2, 0, 0], circle({
     r: radius,
     center: true
   }))
 )));
 parts.push(linear_extrude({
   height: thickness,
   convexity: 10,
   fn: 60
 }, hull(
   translate([-eyes_width / 2, 0, 0], circle({
     r: radius,
     center: true
   })),
   translate([-8, -30, 0], circle({
     r: radius2,
     center: true
   }))
 )));
 parts.push(linear_extrude({
   height: thickness,
   convexity: 10,
   fn: 60
 }, hull(
   translate([eyes_width / 2, 0, 0], circle({
     r: radius,
     center: true
   })),
   translate([8, -30, 0], circle({
     r: radius2,
     center: true
   }))
 )));
 parts.push(translate([-8, -35, 0], cube([16, 35, thickness])));
 //Transducers holes:
 for (fx = -1; fx <= 1; fx += 2) {
   holes.push(translate([fx * eyes_width / 2, 0, thickness / 2], cylinder({
     h: thickness + 2,
     r: eyes_diameter / 2 + safety,
     fn: 50,
     center: true
   })));
 }
 return difference(union(parts), union(holes));

}

//Servo mounting bracket function servoBracket() {

 radius = 8;
 radius2 = 5;
 return translate([0, -35, 0], rotate([-90, -90, 0], linear_extrude({
   height: 6,
   convexity: 10
 }, hull(
   translate([0, 0, 0], circle({
     r: radius,
     center: true
   })),
   translate([23, 0, 0], circle({
     r: radius2,
     center: true
   }))
 ))));

}

function tabsPCB_Mounting(length,width) {

 //Sensor PCB mounting tabs:
 var parts = [];
 var holes = [];
 height = 3.5;
 outer = 3;
 inner = 1;
 for (fx = -1; fx <= 1; fx += 2) {
   for (fy = -1; fy <= 1; fy += 2) {
     parts.push(translate([fx *length / 2, fy * width / 2, 0], cylinder({
       h: thickness + height,
       r: outer
     })));
     //Sensor PCB mounting screws holes:
     holes.push(translate([fx * length / 2, fy * width / 2, 1], cylinder({
       h: thickness + height,
       r: inner
     })));
   }
 }
 return difference(union(parts), union(holes));

}

function servoHead() {

 var parts = [];
 //Servo head placement:
 parts.push(translate([0, -35, 8], rotate([-90, 0, 0], cylinder({
   h: 2.5,
   r: 3.8
 }))));
 parts.push(translate([0, -35 - 1, 8], rotate([-90, 0, 0], cylinder({
   h: 8,
   r: 1.25
 }))));
 parts.push(translate([0, -35 + 4.5, 8], rotate([-90, 0, 0], cylinder({
   h: 3,
   r: 3
 }))));
 parts.push(translate([0, -35 - 1, 23], rotate([-90, 0, 0], cylinder({
   h: 8,
   r: 1
 }))));
 parts.push(translate([0, -35, 8], rotate([-90, -90, 0], linear_extrude({
   height: 2.5,
   convexity: 10
 }, hull(
   translate([0, 0, 0], circle({
     r: 3.5,
     center: true
   })),
   translate([15, 0, 0], circle({
     r: 2,
     center: true
   }))
 )))));
 return union(parts);

}

/**

* create a smile
*/

function smile(thickness) {

 /*bezier = BezierFactory.create(0,0);
 bezier.append([
   [0,15],
   [15,15]
 ]);
 return rotate([0,0,135],bezier.spline(thickness)).translate([10,0,0]);
 */

}

/**

* create a parametric ultrasonic sensor
*/

function main() {

 BezierFactory();
 //Parameters:
 //The diameter of the transducer in mm.: 16mm. mostly.
 eyes_diameter = 16;
 //Distance between centers of transducers in mm.: 25.4mm for HC-SR04.
 width = 41.5
 eyes_width = 25.4;
 //Sensor PCB mounting holes in mm.: 41.4x17 for HC-SR04.
 mount_length = 42.35;
 mount_width = 17.4;
 //Desired thickness in mm.: Maximum 5mm.
 thickness = 2.5;
 //Decorations: "1" smile, "2" teeth, "3" vampire, "4" mustage, "5" O, other for none.
 face = 1;
 fn = 20;
 var parts = [];
 var holes = [];
 parts.push(frontPlate(thickness, eyes_width, eyes_diameter));
 parts.push(servoBracket());
 parts.push(tabsPCB_Mounting(mount_length,mount_width));
 // holes.push(smile(thickness).translate([0, -20, 0]));
 holes.push(servoHead())
 //Cleaning overhang:
 holes.push(translate([-10, -35, -10], cube([20, 10, 10])));
 return difference(union(parts), union(holes));

}</jscad>

Source code

Just cut&paste the source code below to https://www.openjscad.org/

//Parametric.
//Oktay Gülmez, 23/2/2016.
// converted to OpenJSCAD by Wolfgang Fahl 2019-06-09
//GNU_GPL_V3

// include("Bezier.jscad")

/**
 * create front Plate
 */
function frontPlate(thickness, eyes_width, eyes_diameter) {
  safety = 0.6;
  radius = eyes_diameter+2;
  radius2 = 5;
  var parts = [];
  var holes = [];
  //Front plate:
  parts.push(linear_extrude({
    height: thickness,
    convexity: 10,
    fn: 60
  }, hull(
    translate([-eyes_width / 2, 0, 0], circle({
      r: radius,
      center: true
    })),
    translate([eyes_width / 2, 0, 0], circle({
      r: radius,
      center: true
    }))
  )));
  parts.push(linear_extrude({
    height: thickness,
    convexity: 10,
    fn: 60
  }, hull(
    translate([-eyes_width / 2, 0, 0], circle({
      r: radius,
      center: true
    })),
    translate([-8, -30, 0], circle({
      r: radius2,
      center: true
    }))
  )));
  parts.push(linear_extrude({
    height: thickness,
    convexity: 10,
    fn: 60
  }, hull(
    translate([eyes_width / 2, 0, 0], circle({
      r: radius,
      center: true
    })),
    translate([8, -30, 0], circle({
      r: radius2,
      center: true
    }))
  )));
  parts.push(translate([-8, -35, 0], cube([16, 35, thickness])));
  //Transducers holes:
  for (fx = -1; fx <= 1; fx += 2) {
    holes.push(translate([fx * eyes_width / 2, 0, thickness / 2], cylinder({
      h: thickness + 2,
      r: eyes_diameter / 2 + safety,
      fn: 50,
      center: true
    })));
  }
  return difference(union(parts), union(holes));
}

//Servo mounting bracket
function servoBracket() {
  radius = 8;
  radius2 = 5;
  return translate([0, -35, 0], rotate([-90, -90, 0], linear_extrude({
    height: 6,
    convexity: 10
  }, hull(
    translate([0, 0, 0], circle({
      r: radius,
      center: true
    })),
    translate([23, 0, 0], circle({
      r: radius2,
      center: true
    }))
  ))));
}

function tabsPCB_Mounting(length,width) {
  //Sensor PCB mounting tabs:
  var parts = [];
  var holes = [];
  height = 3.5;
  outer = 3;
  inner = 1;
  for (fx = -1; fx <= 1; fx += 2) {
    for (fy = -1; fy <= 1; fy += 2) {
      parts.push(translate([fx *length / 2, fy * width / 2, 0], cylinder({
        h: thickness + height,
        r: outer
      })));
      //Sensor PCB mounting screws holes:
      holes.push(translate([fx * length / 2, fy * width / 2, 1], cylinder({
        h: thickness + height,
        r: inner
      })));
    }
  }
  return difference(union(parts), union(holes));
}

function servoHead() {
  var parts = [];
  //Servo head placement:
  parts.push(translate([0, -35, 8], rotate([-90, 0, 0], cylinder({
    h: 2.5,
    r: 3.8
  }))));
  parts.push(translate([0, -35 - 1, 8], rotate([-90, 0, 0], cylinder({
    h: 8,
    r: 1.25
  }))));
  parts.push(translate([0, -35 + 4.5, 8], rotate([-90, 0, 0], cylinder({
    h: 3,
    r: 3
  }))));
  parts.push(translate([0, -35 - 1, 23], rotate([-90, 0, 0], cylinder({
    h: 8,
    r: 1
  }))));

  parts.push(translate([0, -35, 8], rotate([-90, -90, 0], linear_extrude({
    height: 2.5,
    convexity: 10
  }, hull(
    translate([0, 0, 0], circle({
      r: 3.5,
      center: true
    })),
    translate([15, 0, 0], circle({
      r: 2,
      center: true
    }))
  )))));
  return union(parts);
}

/**
 * create a smile
 */
function smile(thickness) {
  /*bezier = BezierFactory.create(0,0);
  bezier.append([
    [0,15],
    [15,15]
  ]);
  return rotate([0,0,135],bezier.spline(thickness)).translate([10,0,0]);
  */
}

/**
 * create a parametric ultrasonic sensor
 */
function main() {
  BezierFactory();
  //Parameters:
  //The diameter of the transducer in mm.: 16mm. mostly.
  eyes_diameter = 16;
  //Distance between centers of transducers in mm.: 25.4mm for HC-SR04.
  width = 41.5
  eyes_width = 25.4;

  //Sensor PCB mounting holes in mm.: 41.4x17 for HC-SR04.
  mount_length = 42.35;
  mount_width = 17.4;
  //Desired thickness in mm.: Maximum 5mm.
  thickness = 2.5;
  //Decorations: "1" smile, "2" teeth, "3" vampire, "4" mustage, "5" O, other for none.
  face = 1;

  fn = 20;
  var parts = [];
  var holes = [];
  parts.push(frontPlate(thickness, eyes_width, eyes_diameter));
  parts.push(servoBracket());
  parts.push(tabsPCB_Mounting(mount_length,mount_width));
  // holes.push(smile(thickness).translate([0, -20, 0]));
  holes.push(servoHead())
  //Cleaning overhang:
  holes.push(translate([-10, -35, -10], cube([20, 10, 10])));
  return difference(union(parts), union(holes));
}