Machine Design

Objectives of the week

  • Group assignment
    • Actuate and automate your machine
    • Document the group project and your individual

What I did

  • I played a little bit with mods, tested the machine, and made a video!

What I learned

  • The elegance of mods
  • How to use a video editor

If I had the time to go further...

  • We would have a better working machine

Files and resources

Step 1: organizing the work

As for the mechanical design, we used Gitlab to share the work. Axel took the main part, i.e. integrating the 4xiDraw and the syrunge pump. My job was to adapt mods and to allow to use it as interface.

Step 2: playing with mods

This week was the occasion for me to discover mods a little bit further. Thanks to Axel’s help, we used a modified version of the program machines->G-code->mill 2D svg/png. More precisely, we modified only one module: the path to G-cade module.

Basically, Axel modified the lines to control the servo (changed the Z commands toM3S commands), and to enable and disable the Coolant (M8 and M9 commands). Indeed, Axel used the coolant command of the CNC shield as input signal for a custom board controlling the syringe pump. This is documented on the group page and on Axel’s page.

Since we used less parameters than in the basic mods module, I made a little bit of aesthetics, and modified the parameters widgets and the default values of the module. This also allowed me to code a little bit of javascript for the first time. Here is the final modified javascript

//
// path to G-code
//
// Neil Gershenfeld
// (c) Massachusetts Institute of Technology 2018
//
// Updated: Steven Chew
// Date:    Feb 20 2019
// Comments: Added option to output in inch or mm
//
// Updated: Axel Cornu & Gilles Decroly 20/05/2019 - adapted for syringe machine
//
// This work may be reproduced, modified, distributed, performed, and
// displayed for any purpose, but must acknowledge the mods
// project. Copyright is retained and must be preserved. The work is
// provided as is; no warranty is provided, and users accept all
// liability.
//
// closure
//
(function(){
//
// module globals
//
var mod = {}
//
// name
//
var name = 'Syringe path to G-code'
//
// initialization
//
var init = function() {
   mod.cutspeed.value = '1500'
   //mod.plungespeed.value = '1500'
   //mod.jogspeed.value = '1500'
   mod.jogheight.value = '200'
   //mod.spindlespeed.value = '10000'
   //mod.tool.value = '1'
   //mod.coolanton.checked = false
   }
//
// inputs
//
var inputs = {
   path:{type:'',
      event:function(evt){
         mod.name = evt.detail.name
         mod.path = evt.detail.path
         mod.dpi = evt.detail.dpi
         mod.width = evt.detail.width
         mod.height = evt.detail.height
         make_path()
         }}}
//
// outputs
//
var outputs = {
   file:{type:'',
      event:function(str){
         obj = {}
         obj.name = mod.name+".nc"
         obj.contents = str
         mods.output(mod,'file',obj)
         }}}
//
// interface
//
var interface = function(div){
   mod.div = div
   //
   // cut speed
   //
   div.appendChild(document.createTextNode('syringe speed: '))
   var input = document.createElement('input')
      input.type = 'text'
      input.size = 6
      div.appendChild(input)
      mod.cutspeed = input
   div.appendChild(document.createTextNode(' (mm/s)'))
   div.appendChild(document.createElement('br'))
   //
   // jog height
   //
   div.appendChild(document.createTextNode('jog height: '))
   var input = document.createElement('input')
      input.type = 'text'
      input.size = 6
      div.appendChild(input)
      mod.jogheight = input
   div.appendChild(document.createTextNode(' (mm)'))
   div.appendChild(document.createElement('br'))
   //
   // Inch or mm
   //
   div.appendChild(document.createTextNode('format:'))
   var input = document.createElement('input')
      input.type = 'radio'
      input.name = mod.div.id+'format'
      input.id = mod.div.id+'formatInch'
      div.appendChild(input)
      mod.formatInch = input
   div.appendChild(document.createTextNode('inch'))
   var input = document.createElement('input')
      input.type = 'radio'
      input.name = mod.div.id+'format'
      input.id = mod.div.id+'formatMm'
      input.checked = true
      div.appendChild(input)
      mod.formatMm = input
   div.appendChild(document.createTextNode('mm'))
   }
//
// local functions
//
function make_path() {
   var dx = 25.4*mod.width/mod.dpi
   var cut_speed = parseFloat(mod.cutspeed.value)
   //var plunge_speed = parseFloat(mod.plungespeed.value)
   //var jog_speed = parseFloat(mod.jogspeed.value)
   var jog_height = parseFloat(mod.jogheight.value)
   var nx = mod.width
   var scale = dx/(nx-1)
   var in_mm_scale = 1
   if (mod.formatInch.checked) {
      dx /= 25.4
      scale /= 25.4
      cut_speed /= 25.4
      //plunge_speed /= 25.4
      //jog_speed /= 25.4
      jog_height /= 25.4
   }
   //var spindle_speed = parseFloat(mod.spindlespeed.value)
   //var tool = parseInt(mod.tool.value)
   str = "%\n" // tape start
   str += "G17\n" // xy plane
   if (mod.formatInch.checked)
      str += "G20\n" // inches
   if (mod.formatMm.checked)
      str += "G21\n" // mm
   str += "G54\n" // coordinate system 1
   str += "G80\n" // cancel canned cycles
   str += "G90\n" // absolute coordinates
   str += "G94\n" // feed/minute units
   str += "F"+cut_speed.toFixed(4)+"\n" // feed rate
   //
   // follow segments
   //
   for (var seg = 0; seg < mod.path.length; ++seg) {
      //
      // move up to starting point
      //
      x = scale*mod.path[seg][0][0]
      y = scale*mod.path[seg][0][1]
      str += "M3 S"+jog_height.toFixed(4)+"\n"
      str += "G00X"+x.toFixed(4)+"Y"+y.toFixed(4)+"M3 S"+jog_height.toFixed(4)+"\n"
      str += "M09\n"// S"+jog_height.toFixed(4)+"\n"
      str += "G00X"+x.toFixed(4)+"Y"+y.toFixed(4)+"M09 M3 S"+jog_height.toFixed(4)+"\n"
      //
      // move down
      //
      z = scale*mod.path[seg][0][2]
      str += "G01 M3 S"+z.toFixed(4)+"\n"
      str += "M8 M3 S"+z.toFixed(4)+"\n"
      str += "F"+cut_speed.toFixed(4)+"\n" //restore xy feed rate
      for (var pt = 1; pt < mod.path[seg].length; ++pt) {
         //
         // move to next point
         //
         x = scale*mod.path[seg][pt][0]
         y = scale*mod.path[seg][pt][1]
         z = scale*mod.path[seg][pt][2]
         str += "G01X"+x.toFixed(4)+"Y"+y.toFixed(4)+"M08 M3 S"+z.toFixed(4)+"\n"
         }
      }
   //
   // finish
   //
str += "M09\n"
   str += "M3 S"+jog_height.toFixed(4)+"\n" // move up before stopping spindle
   str += "G01 X0Y0\n" //go back to origin
   str += "M30\n" // program end and reset
   str += "%\n" // tape end
   //
   // output file
   //
   outputs.file.event(str)
   }
//
// return values
//
return ({
   mod:mod,
   name:name,
   init:init,
   inputs:inputs,
   outputs:outputs,
   interface:interface
   })
}())

Step 3: testing the machine and making a video

We could finally test the machine, and it worked! The physics is not perfectly mastered, but the machine is modular and allow multiple types of use, and was not the limitation in our case! Additionally to the specification, we could imagine to use the machine to make soft robots as the octobot.

Axel, again, has a lot of good material to take quality pictures and video. We could take a lot of rush of the machine working, and I was charged to make the video. Greta focused on making the doc.

To make the video (I had never done this before), I tested quickly three programs: Windows movie maker, Avidemux, and Shotcut. Very quickly, the third solution showed to be the best: the easier to use and offering a lot of possibilities! I played a little bit with it and its easy interface, and used some filter, as to add text, to modify the speed, and to add pictures. The final video can be found at the top of this page!