The Arcology Garden

3D printed bike basket boot

LifeTechEmacsTopicsArcology

I'd like to have the ability to attach a milk crate to the back of my bike sometimes. This 3D print is designed to attach to the bottom of a milk crate and sit snugly on Marra's rear pannier rack. Once sat, it is then bungee'd on to the frame and lower rack points. This plastic milk crate is big enough to hold two grocery bags securely, though it's a bit too tall for me to leave on all the time. That's fine because six bungee points is all it takes to remove it and bring it in to a restaurant or shop with me.

This is OpenSCAD:

Variables! so many magic numbers:

$inner_w = 88;  // width of the space between the two bars parallel to the travel direction
$inner_r = 10;  // this is the approximate inner radius of the welds on the rack
$bar_d = 10;    // diameter of the bars (and spacing between the sectors


$b_sector = 50;   // the length of the first of three "boots"
$m_sector = 103;  // the length of the middle boot
$f_sector = 97;   // the length of the boot closest to the seat

$boot_h = 15;     // the height of the boots which seat in to the rack
$seat_h = 5;      // the height of the base 

$fn=20;

$seat_w = $inner_w + $bar_d + $bar_d;
$full_w = $b_sector + $m_sector + $f_sector + (2*$bar_d);

$tie_spacing = 46;    // 50 mm between each tie cross
$tie_lr_spacing = 15; // 15 mm spacing between each side of the cross
$tie_hole_r = 3;      // size of the hole for zipties
$tie_margin = 30;     // inner margin of tie rows
$tie_margin_f = 20;   // front margin of tie rows
$tie_num = 7;         // number of ties in each row

so basically the boot is designed to seat in to the three large holes on the top of my bike rack; then to tighten it, i will use bungie cables down to the lower parts of the rack. This will block bag usage, but I might get some front racks and smaller bags to hold gallon bottles or so if I do Jitensha Ni Ocha with it? Mostly this is for shopping trips and park-sitting, so it needs to be removable yet secure..

module rounded_cube(x, y, z)
{
  //cube([x, y, z]);
  hull() {
    translate([$inner_r, $inner_r, 0])
      cylinder(r=$inner_r, h=z);
    translate([x-$inner_r, $inner_r, 0])
      cylinder(r=$inner_r, h=z);
    translate([x-$inner_r, y-$inner_r, 0])
      cylinder(r=$inner_r, h=z);
    translate([$inner_r, y-$inner_r, 0])
      cylinder(r=$inner_r, h=z);
  }
}

module base() {
  difference() {
    // boots + base
    translate([$bar_d,0,0]) {
      union() {
        rounded_cube($inner_w, $b_sector, $boot_h);
        // translate([0, $b_sector + $bar_d, 0])
        //   rounded_cube($inner_w, $m_sector, $boot_h);
        // translate([0, $b_sector + $bar_d + $m_sector + $bar_d, 0])
        //   rounded_cube($inner_w, $f_sector, $boot_h);
        // seat
        // translate([-$bar_d,0,$boot_h-0.1])
        //   rounded_cube($seat_w,
        //                $b_sector + $m_sector + $f_sector + (2*$bar_d),
        //                $seat_h);
        translate([-$bar_d,-$bar_d,$boot_h-0.1])
          rounded_cube($seat_w,
                       $b_sector + (2*$bar_d),
                       $seat_h);
      }
    }
    // ziptie holes
    translate([0, $tie_margin_f, 0]) {
      for ( i = [1 : $tie_spacing : ($tie_spacing * $tie_num)] ) {
        translate([0, i - (0.5*$tie_lr_spacing), 0]) {
          translate([$tie_margin, 0, -.1]) {
            cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
            translate([0, $tie_lr_spacing, 0]) {
              cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
            }
          }

          translate([$seat_w - $tie_margin, 0, -.1]) {
            cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
            translate([0, $tie_lr_spacing, 0]) {
              cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
            }
          }
        }
      }
    // perpendicular zip tie holes
      for ( i = [0 : ($tie_spacing) * 2 : $tie_spacing * ($tie_num - 1) ] ) {
        translate([(0.5 * $seat_w) - ($tie_lr_spacing * 0.5),
                   i + (($tie_spacing) / 2),
                   -.1]) {
          cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
          translate([$tie_lr_spacing, 0, 0]) {
            cylinder(r=$tie_hole_r, h=($boot_h + $seat_h + 2));
          }
        }
      }
    }
  }
}

module sliced(half=0) {
  if (half==0) {
    difference() {
      base();
      translate([-0.5,-0.1,-0.1])
        cube([$inner_w + (2*$bar_d) + 1, 
              $full_w / 2 + 0.1,
              $seat_h+$boot_h + 1]);
    }
  } else {
    difference() {
      base();
      translate([-0.5,$full_w/2 + 0.1,-0.1])
        cube([$inner_w + (2*$bar_d) + 1, 
              $full_w / 2,
              $seat_h+$boot_h + 1]);
    }

  }
}

The sliced function helps me fit the parts on my Ender 5 Pro. All the above code is loaded in to the OpenSCAD UI reified in to a two-color representation using the code below to show me the works in progress. To actually work it, click the linked elisp helper:

Compile both split halves

Keep this buffer open and hit gr in there to rebuild them after tangling. This produces a bike-crate-0.stl and bike-crate-1.stl.

use </home/rrix/Code/scad/bike-crate.scad> 

translate([120, 0, 0])
color("red") {
  sliced(half=1);
}

translate([0,10,0])
color("green") {
  sliced(half=0);
}
// base();