Week 9 & 10: Machine Week – “Fruity Secret Messenger”

Weekly Summary

Machine Week! As Asano-san and myself are the only current students at FabLab Kamakura, we created an simple, entertaining, and - we hope funny - machine. The Fruity Secret Messenger.

The machine is the implementation of a simple, silly idea we had on the first weekend session. Let's create (another!) drawing machine, but with a twist! Can we use lemon (lime, orange, grapefruit, etc) juice as a drawing liquid? And can we use a heat-bed to make the invisible drawing visible?

Group Assignment

The Group Assignment is to: design a machine that includes mechanism+actuation+automation, build the mechanical parts and operate it manually, document the group project and your individual contribution, and programming environments as possible, actuate and automate your machine, document the group project and your individual contribution.

Here is the link to the Group Assignment page.

And our 1 min presentation video!

1:00min, 10.4MB, H.264, Average Bitrate 1200 kbits/sec

Time Constraints & Time Planning

The time for this assignment was two weeks, on the first week's lab session we brainstormed ideas and arrived - as we are only 2 students in our group - at a doable, and possibly funny project.

The Idea

The idea is a variation on the tested and well-done project of a drawing machine. XY actuation, a visible out. But our idea has a twist. Instead of using ink, we will use citric acid (lemon juice!) as an invisible ink to write a secret message.

Our initial idea - and hope - was to use the heat bed of a 3D printer to make the invisible ink visible.

Prototyping

Fruit Parade

"I got a Lemon Pen"

I got a...

Testing the Lemon Pen

... Lemon Pen!

Heating the Heatbed

Heatbed

The heatbed is heating up, currently at 112ยบC, but it will not reach 135ยบC.

Results

Using Gas Range to create the heat necessary for making the invisible ink visible. Not recommended. Especially if your FabLab is made from wood.

Results
Heating with the Extruder Header
Juice Collection Test

Manually actuating the Machine

Test the Machine with manual actuation.

Machine Sketches

Machine Sketches

Machine Vision

That's how it should look at the end.

Machine Vision

Individual Contribution: Modelling the Juice Extruder

Sketches

Sketches

I set myself the goal to model the extruder in OpenSCAD. Why OpenSCAD? The extruder is fairly symmetric.

Usually I don't include longer code, but I think OpenSCAD is worth an exception. You can also download the code from the files section below.

echo(version=version());

// number of fragments, set number of faces, global
$fn=200;

// colors
alpha = 0.75;
green = [0, 0.5, 0, alpha];
yellow = [1, 0.75, 0, alpha];
red = [1, 0, 0, alpha];
blue = [0, 0, 1, alpha];

// * hides object
// % makes in semi-transpartent?

// rotate_extrude() rotates a 2D shape around the Z axis.
// Note that the 2D shape must be either completely on the
// positive or negative side of the X axis.
*color([1,1,0, 0.1])
  rotate_extrude()
    translate([10, 0])
      square(50 );

// Using a shape that touches the X axis is allowed and produces
// 3D objects that don't have a hole in the center.
height = 80;
radius = 7.5;
wall = 3;

cubeWidth = 10;
cube2Width = 8;

function cyl(h, r, w) =
  [[r-w,0],[r,0],[r,h],[r-w,h]];

color(yellow) {
  translate([0, 0, height/2 - 10]) {

    difference() { // Tube x Crown

      // Tube
      difference() {
        rotate_extrude()
          translate([0, -height/2, 0])
            polygon( points=cyl(height, radius, wall));
        *union() {
          cylinder(height+10, radius-wall, radius-wall, true);
          rotate(-90) {
            translate([-cubeWidth/2, 10, 0]) {
              cube([cubeWidth, 2, 20]);
            }
              translate([-cube2Width/2, 0, 2]) {
                cube([cube2Width, 12, 15]);
             }
          }
        }
      }

      // Crown
      crownThickness = 2;
      steps = 4;
      crownHeight = 7.5;
      color(green) {
        union() { // Union for Crown Elements
          for (angle = [0 : 180/steps : 180-180/steps]) {
            rotate([0, 0, angle+45/2]) {
              translate([-radius*2, -crownThickness/2, 6]) {
                cube([100, crownThickness, crownHeight]);
              }
            }
          }
        }
        union() { // Union for Crown Elements
          for (angle = [0 : 180/steps : 180-180/steps]) {
            rotate([0, 0, angle+45/2]) {
              translate([-radius*2, -crownThickness/2, 25]) {
                cube([100, crownThickness, 100]);
              }
            }
          }
        }
      }

    } // end difference Tube x Crown
  }
}

// connection plate
connectorWidth = 40;
r = 5;
cw = connectorWidth - r*2;
cw2 = cw/2;

connectorHeight = 5/2;
ch = connectorHeight;

// Plate
color(green) {
  difference(){
    color("blue")
      translate([-cw2, -cw2, 0]) {
        minkowski() {
          cube([cw, cw, ch]);
          cylinder(ch, r, r);
        }
      }

    // Small Holes
    /* ----------- */
    holeDiameter = 3; // M3 inter diameter
    holeOffsetFromCenter = 12;
    /* ----------- */

    holeRadius = holeDiameter/2;
    hr = holeRadius;

    holeOffset = cw2 - holeOffsetFromCenter;
    ho = holeOffset;

    color("red") {
      translate([-cw2+ho, -cw2+ho, -1]) {
        cylinder(ch*3, hr, hr);
      }
      translate([+cw2-ho, -cw2+ho, -1]) {
        cylinder(ch*3, hr, hr);
      }
      translate([+cw2-ho, +cw2-ho, -1]) {
        cylinder(ch*3, hr, hr);
      }
      translate([-cw2+ho, +cw2-ho, -1]) {
        cylinder(ch*3, hr, hr);
      }
    }
    // Central Hole
    color("red") {
      translate([0, 0, -1]) {
        cylinder(ch*3, radius, radius);
      }
    }
  } // end diff
} // end color

// Collector
color(blue) {
  r = 30;
  z = 43.5 + r;
  translate([0, 0, z-40+r]) {
    difference() {
      sphere(r);                        // Outer Sphere
      sphere(r - 3);                    // Inner Sphere
      translate([-r, -r, -r+r/3]) {     // Diff Sphere with Cube
        cube([r*2, r*2, r*2]);
      }
      translate([0, 0, -r]) {           // Central Hole
        cylinder(10, radius, radius);
      }
    } // end diff
  }
}

// Scaffolding
translate([0, 0, 0]) {
  color(red) {
    thickness = 2;
    steps = 2;
    height = 43.5;
    difference() {
      union() {
        for (angle = [0 : 180/steps : 180-180/steps]) {
          rotate([0, 0, angle]) {
            translate([-radius*2, -thickness/2, 0]) {
              cube([radius*4, thickness, height]);
            }
          }
        }
      }
      translate([0, 0, -r]) {           // Central Hole
        cylinder(100, radius, radius);
      }
    }
  }
}

echo ("height", height);
Video, Modelling in OpenSCAD

Print Attempt 1

Printing

Learning: Don't print horizontal.

Inkscape G-code Export

Exporting G-code from Inkscape

We are using an extension called Gcodetools to export G-Code from Inkscape.

About G-Code Tools
Inkscape > Extensions > Gcodetools > Path to Gcode...

Cleaning and Modifying G-code in Python

We repurposed the extruder servo to twist our fruits:

add_e_values_to_gcode.py

#!/usr/bin/env python3

inputFile = open("kamakura_0001.ngc", "r")
outputFile = open("kamakura_e.ngc", "w")
# add E values
a = list(range(10))
b = list(range(9))
b.reverse()
l = a + b

lineNr = 0
for line in inputFile:
  values = line.split()
  i = 0
  for v in values:
    firstLetter = v[0].upper()

    # remove Z values at 3
    if (i == 3 and firstLetter == 'Z'):
      values[i] = ''

    # remove F values at 6
    if (i == 6 and firstLetter == 'F'):
      values[i] = ''

    # increment
    i = i + 1

  # add E to end
  if len(values) > 0:
    if (values[0][:3] == 'G02'):
      e = l[lineNr % len(l)]
      values.append('E' + str(e))
      lineNr = lineNr + 1

  # filter empty list entries
  newValues = list(filter(None, values))

  # join list to string
  newValues = ' '.join(newValues) + "\n"

  # print to console
  #print(newValues)

  #write to output file
  outputFile.writelines(newValues)

Instructions

Executing the Clean-up Script.

Time Management

Perfect Time Management. Sponsored by Casio.

Well execute time management. We left on Sunday at 17:58, having completed all our tasks!

And it was great fun!

Producing the Video

Directors at work.
Raw Footage, Lime, 1.1M
Raw Footage, Orange, 2.2M
Editing in After Effects

Producing the Video was a nice exercise with sliders and bokeh. The repetitive motion of the writing machine did lend itself to a series of takes with different fruits. I spend quite a lot of time getting the right shots - and cutting the video to 1min. Here is it again:

Hero Video

1:00min, 10.4MB, H.264, Average Bitrate 1200 kbits/sec

Files