Search Results for: g-code source

MakerGear M2: Slic3r Start G-Code for PETG / V4 / 24 V / Whatever

The already ponderous chunk of G-Code that slic3r prepends to the outgoing file got a bit more complex with all the changes going on around here.

As it stands now, the starting G-Code looks like this:

;-- Slic3r Start G-Code for M2 starts --
;  Ed Nisley KE4NZU - 2015-03-07
;  Makergear V4 hot end
; Z-min switch at platform, must move nozzle to X=135 to clear
M140 S[first_layer_bed_temperature]	; start bed heating
G90				; absolute coordinates
G21				; millimeters
M83				; relative extrusion distance
M17				; enable steppers
G4 P500			;  ... wait for power up
G92 Z0			; set Z to zero, wherever it might be now
G1 Z10 F1000	; move platform downward to clear nozzle; may crash at bottom
G28 Y0			; home Y to clear plate, origin in middle
G92 Y-127
G28 X0			; home X, origin in middle
G92 X-100
G1 X130 Y0 F15000	; move off platform to right side, center Y
G28 Z0			; home Z to platform switch, with measured offset
G92 Z-2.10
G0 Z2.0			; get air under switch
G0 Y-127 F10000	; set up for priming, zig around corner
G0 X0			;  center X
G0 Y-125.0		; just over platform edge
G0 Z0 F500	; exactly at platform
M109 S[first_layer_temperature]	; set extruder temperature and wait
M190 S[first_layer_bed_temperature]	; wait for bed to finish heating
G1 E20 F300		; prime to get pressure, generate blob on edge
G0 Y-123 F500		; shear off blob
G1 X15 F15000	; jerk away from blob, move over surface
G4 P500			; pause to attach
G1 X45 F500		; slowly smear snot to clear nozzle
G1 Z1.0 F2000	; clear bed for travel
;-- Slic3r Start G-Code ends --

The blow-by-blow description…

Lines 9-10: Manually enable stepper drivers and wait half a second

Changing to a 24 V power supply for the motors doesn’t affect the winding current (because the drivers control that), but it does increase the current’s rate-of-change (because inductor voltage = L di/dt and the applied voltage is 26% higher) during each microstep. That means the motors snap to a whole-step position a bit faster when the Marlin firmware enables the drivers and the higher di/dt induces more glitch voltage in, say, the endstop cable, triggering a false contact sense (as the circuit depends on the Arduino’s 20+ kΩ internal pullup resistor). In any event, a half-second snooze avoids the problem.

Lines 18-19: Home Z-axis & set platform switch offset

The only way to set the offset accurately is to compare the actual height of a printed object (or the skirt around it) with the nominal value. I use 5 mm tall thinwall open boxes and, after setting the Extrusion Multiplier properly, they’re good test objects.

Lines 22-24: Extruder final heating

PETG tends to stick to the nozzle, so the nozzle now sits just over the edge of the glass plate and flush with the top surface, so that the initial drool forms a glob anchored to the side of the plate. It looks like this:

V4 PETG - preheat position

V4 PETG – preheat position

Notice the curl attached to the nozzle: I generally pick those off with a tweezer, but let this one remain to show how this mess works.

Line 31: Prime the extruder

With the hot end and platform temperatures stabilized, I ram 20 mm of filament into the extruder to refill it and stabilize its internal pressure. Because it’s been drooling ever since the plastic melted, not very much plastic comes out, but what does emerge enlarges the blob and bonds with the plastic stuck on the nozzle, thusly:

V4 PETG - extruder priming

V4 PETG – extruder priming

Lines 28-29: Detach the blob

Moving 2 mm onto the platform leaves most of the snot hanging on the edge of the glass, with just a bit on the far side of the nozzle. Doing that relatively slowly gives the plastic time to flow around the nozzle and remain with the blob, then zipping to X=15 encourages it to detach.

Lines 30-31: Wipe away what’s left

Pause for half a second to allow whatever’s left to attach to the platform, then slowly move to X=45, and watch the remaining snot leave a trail on the platform as it oozes off the nozzle.

Then hop up 1 mm to clear the platform and pass control to the rest of the G-Code with a clean nozzle!

That’s the ideal outcome, of course. Sometimes a recalcitrant blob hangs on, but it generally oozes off while the nozzle trudges around three skirt outlines…




Makergear M2: Slic3r Start and End G-Code Routines

Being that type of guy, my Start and End G-Code routines are somewhat more elaborate than usual…

The Start routine handles homing, which is more dangerous than you might think, and wiping the drool off the nozzle:

;-- Slic3r Start G-Code for M2 starts --
;  Ed Nisley KE4NZU - March 2013
M140 S[first_layer_bed_temperature]	; start bed heating
G90				; absolute coordinates
G21				; millimeters
M83				; relative extrusion distance
M84				; disable stepper current
G4 S3			; allow Z stage to freefall to the floor
G28 X0			; home X
G92 X-95		; set origin to 0 = center of plate
G1 X0 F30000    ; origin = clear clamps on Y
G28 Y0			; home Y
G92 Y-125		; set origin to 0 = center of plate
G1 Y-122 F30000    ; set up for prime near front edge
G28 Z0			; home Z
G92 Z1.0		; set origin to measured z offset
M190 S[first_layer_bed_temperature]	; wait for bed to finish heating
M109 S[first_layer_temperature]		; set extruder temperature and wait
G1 Z0.0 F2500	; plug extruder on plate
G1 E10 F300		; prime to get pressure
G1 Z5 F2500		; rise above blob
G1 Y-115 F30000	; move away
G1 Z0.0 F2500	; dab nozzle to remove outer snot
G4 P1			; pause to clear
G1 Z0.1			; clear bed for travel
;-- Slic3r Start G-Code ends --

The fundamental problem with homing is that you don’t know where the nozzle stands in relation to the build platform and the bulldog clips clamping the glass plate to the aluminum heater. If you simply home X and Y with Z unchanged, you will eventually plow the nozzle directly across a clip. Trust me on this, you do not want to do that.

So Line 7 disables the stepper motors. In an ideal world, the Z axis stage would then free-fall to the bottom of the chassis during the 4 second pause produced by the G4 S3 instruction. In the real world, that works most of the time, but the platform sometimes sticks where it is. You don’t want to home the Z axis to the top of its travel, because that will eventually crunch the nozzle into those clips, so I plan to add a bottom limit switch so I can drive the platform to a known location away from everything else.

The default M2 Start G-Code puts the XY origin at the front left side of the platform, following the RepRap convention. Maybe it’s just me, but having the origin in the middle of the platform makes more sense for my objects; most of my OpenSCAD models are more-or-less symmetric, so putting the XY origin at their center works well. Ultimately, it doesn’t matter as long as you’re consistent, but my Start G-Code doesn’t produce the same results as the Makergear setup.

Line 9 homes the X axis and Line 10 sets the coordinate to -95. The X axis home position is about 5 mm from the left edge of the glass plate, so the nozzle has about 195 mm of travel to the right edge of the 200 mm plate. The X=0 origin will be in the middle of the printable range, with -95 mm to the left limit (the home position) and +95 to the right edge; the nozzle can travel another 30 mm beyond the right edge to about +125. Line 11 puts the nozzle in the middle of its travel at X=0.

Line 12 homes the Y axis and Line 13 sets the coordinate to -125. The Y axis home position is almost exactly on the front edge of the 250 mm glass plate, so the Y=0 origin is centered on the plate. The nozzle can travel an additional 10 mm off the rear edge of the plate. Note that you must position the nozzle somewhere on the X axis that avoids the bulldog clips; any of X=±95 or X=0 will work. Line 14 puts the nozzle in the middle of the plate at Y=0; it’s already at X=0, so the plate is now centered.

Line 15 homes the Z axis. I’ve set the limit switch so that the home position leaves exactly 1.0 mm between the nozzle and the glass plate, which I find easier to measure than the Makergear suggestion of 0.1 mm. Of course, that’s because I have a Starret taper gauge in my tool cabinet. Use what you have, but use it consistently.

Line 16 sets the Z axis coordinate position to +1.0 mm, matching the measured height, so that Z=0 corresponds to the nozzle exactly kissing the glass plate. The Makergear defaults put Z=0 about 0.1 mm above the platform; I’d rather apply model- and material-dependent offsets to “natural” machine positions.

All of that ignores Z axis backlash. Some preliminary guesstimates put that around 0.1 mm, far better than my Sherline, but still large with respect to the layer thickness. I need more measurements of that, plus some measurements of the actual glass flatness. I think the glass bows upward by about 0.1 mm in the middle, but that requires better probing that will be easier under LinuxCNC control where I can do automated platform mapping.

With the nozzle parked 1.0 mm over the platform, the next two lines wait for everything to reach the proper temperature. I preheat the platform and crank up the extruder temperature before starting the program , so these steps don’t take too long.

However, the nozzle cools off as the drool contacts the much colder platform (it’s heated to 70 °C, but that’s cooler than 150-ish °C by a considerable margin) and the PID loop struggles to reheat it. I think that’s due to the default I term being only 0.1, which reduces integral windup during preheating, but also slows recovery from a sudden thermal load. It helps to preheat the nozzle about 10 °C over the desired temperature, then let it cool during this step.

M2 - Wipe blobs on glass platform

M2 – Wipe blobs on glass platform

Line 19 uses Nophead’s trick (which I cannot find now) of planting the nozzle on the plate at Z=0.0 to reduce drool, although I do that after the nozzle reaches extruding temperature. The drool forms a blob on the platform as the nozzle heats, but the nozzle punches directly through it on the way to Z=0.0.

Line 20 runs 10 mm of filament into the hot end to pressurize the extruder. Some of the molten goo oozes out around the nozzle, enlarging the blob on the glass plate. The object of the game is to leave all that behind: having a generous contact patch on the glass helps.

The larger blob on the left of the picture (at Y=-125) comes from that process.

Line 21 starts the wiping dance:

  • Raise the nozzle above the blob to Z=5 mm
  • Move away from the blob by 5 mm. I’ll probably change this to move in the +X direction.
  • Tap the nozzle on the platform, so (almost all of) the molten PLA slides away from the orifice
  • Get 0.1 mm of clearance from the platform, directly over the new blob
  • Scoot off to print a Skirt extrusion around the object

The smaller, rather flat, blob on the right comes from the nozzle tap. A thin hair may stretch from the blob to the start of the skirt, but it doesn’t amount to much.

Sometimes, of course, the blobs don’t adhere to the glass plate and accompany the nozzle to the start of the skirt. By the conservation of perversity, that’s also when the skirt starts on the far side of the origin, so the blob smears all over the object’s first layers. The Makergear wipe process extrudes the waste filament over the side of the plate, then shears it off as the nozzle returns to the surface; I’ll try blending that in with my startup sequence at some point.

My slic3r configuration extrudes at least 15 mm of filament into the skirt, giving the extruder plenty of time to reach a steady state before starting the actual object. Generally that’s far more than enough filament, but sometimes … well, it’s a good idea to watch what’s going on.

On the other end of the printing process, the End G-Code routine handles shutdown with the object on the platform:

;-- Slic3r End G-Code for M2 starts --
;  Ed Nisley KE4NZU - March 2013
M104 S0		; drop extruder temperature
M140 S0		; drop bed temperature
M106 S0		; bed fan off
G1 Z195	F2500	; lower bed
G1 X0 Y0 F30000	; center nozzle
M84     	; disable motors
;-- Slic3r End G-Code ends --

Line 3 begins turning the heaters and bed fan off. I’ve unplugged the fan for now, so Line 5 is just for completeness.

Line 6 lowers the bed to the bottom under power, because that’s faster that a free fall and it’s guaranteed to work.

With the object safely out of the way, Line 7 centers the nozzle over the platform.

Finally, Line 8 turns off the steppers off; the platform drops another few millimeters

Then everything cools down. Because I run the platform at well above PLA’s glass transition temperature, it must cool for quite a while until the object stiffens up.



G-Code and M-Code Grand Master List

Here’s a combined and sorted list of all the G-Code and M-Code commands for (as many of) the Free Software G-Code interpreters (that I could find) relevant to DIY 3D printing. With any luck, I now know:

  • What a given command does
  • What other interpreters do with that command

The short descriptions come from tables on the original source pages, perhaps with a bit of massaging to make things more uniform; I did as little rearranging and editing as possible.

If you see anything wrong or have another G-Code interpreter I should include, let me know…

3D Printer G-Code and M-Code Commands

27 Feb 2013
Ed Nisley - KE4ZNU

V3 - NIST RS274NGC V3-
LC - LinuxCNC -
RG - ReplicatorG - and /mcodes
JF - Jetty Firmware - at bottom
RR - RepRap - (cross-linked from many G-Code pages)
MF - Marlin Firmware dialect of RR (via Dan Newman)

G0  LC  Coordinated Straight Motion Rapid
G0  MF  same as G1
G0  RG  Rapid Motion
G0  RR  Rapid move
G0  V3  rapid positioning
G1  LC  Coordinated Straight Motion Feed Rate
G1  MF  Coordinated Movement X Y Z E
G1  RG  Coordinated Motion
G1  RR  Controlled move
G1  V3  linear interpolation
G2  LC  Coordinated Helical Motion Feed Rate
G2  RG  Arc - Clockwise
G2  V3  circular/helical interpolation (clockwise)
G3  LC  Coordinated Helical Motion Feed Rate
G3  RG  Arc - Counter Clockwise
G3  V3  circular/helical interpolation (counterclockwise)
G4  LC  Dwell
G4  MF  Dwell S<seconds> or P<milliseconds>
G4  RG  Dwell
G4  RR  Dwell
G4  V3  dwell
G5.1    LC  Quadratic B-Spline
G5.2    LC  NURBs Block Open
G5.3    LC  NURBs Block Close
G7  LC  Diameter Mode (lathe)
G8  LC  Radius Mode (lathe)
G10 LC  L10 Set Tool Table, Calculated, Workpiece
G10 LC  L11 Set Tool Table, Calculated, Fixture
G10 LC  L1  Set Tool Table Entry
G10 LC  L20 Coordinate System Origin Setting Calculated
G10 LC  L2  Coordinate System Origin Setting
G10 RG  Create Coordinate System Offset from the Absolute one
G10 RR  Head Offset
G10 V3  coordinate system origin setting
G17 LC  Arc plane XY
G17 RG  Select XY plane (default)
G17 V3  XY-plane selection
G17.1   LC  Arc plane UV
G18 LC  Arc plane ZX
G18 RG  Select XZ plane (not implemented)
G18 V3  XZ-plane selection
G18.1   LC  Arc plane WU
G19 LC  Arc plane YZ
G19 RG  Select YX plane (not implemented)
G19 V3  YZ-plane selection
G19.1   LC  Arc plane VW
G20 LC  Unit of Measure - inch
G20 RG  Inches as units
G20 RR  Set Units to Inches
G20 V3  inch system selection
G21 LC  Unit of Measure - millimeter
G21 RG  Millimeters as units
G21 RR  Set Units to Millimeters
G21 V3  millimeter system selection
G28 LC  Go to Predefined Position
G28 MF  Home all Axis
G28 RG  Home given Axes to maximum
G28 RR  Move to Origin
G28 V3  return to home
G28.1   LC  Store Predefined Position
G29-G32 RR  Bed probing
G30 LC  Go to Predefined Position
G30 RG  Go Home via Intermediate Point (not implemented)
G30 V3  return to secondary home
G30.1   LC  Store Predefined Position
G31 RG  Single probe (not implemented)
G32 RG  Probe area (not implemented)
G33 LC  Spindle Synchronized Motion
G33.1   LC  Rigid Tapping
G38.2   LC  Probe toward, stop on contact, error
G38.2   V3  straight probe
G38.3   LC  Probe toward, stop on contact
G38.4   LC  Probe away, stop on release, error
G38.5   LC  Probe away, stop on release
G40 LC  Cancel Cutter Compensation
G40 V3  cancel cutter radius compensation
G41 LC  Cutter Compensation - left
G41 V3  start cutter radius compensation left
G41.1   LC  Dynamic Cutter Compensation - left
G42 LC  Cutter Compensation - right
G42 V3  start cutter radius compensation right
G42.1   LC  Dynamic Cutter Compensation - right
G43 LC  Use Tool Length Offset from Tool Table
G43 V3  tool length offset (plus)
G43.1   LC  Dynamic Tool Length Offset
G49 LC  Cancel Tool Length Offset
G49 V3  cancel tool length offset
G53 LC  Motion in Machine Coordinate System
G53 RG  Set absolute coordinate system
G53 V3  motion in machine coordinate system
G54-G59 RG  Use coordinate system from G10 P0-5
G54 LC  Select Coordinate System 1
G54 V3  use preset work coordinate system 1
G55 LC  Select Coordinate System 2
G55 V3  use preset work coordinate system 2
G56 LC  Select Coordinate System 3
G56 V3  use preset work coordinate system 3
G57 LC  Select Coordinate System 4
G57 V3  use preset work coordinate system 4
G58 LC  Select Coordinate System 5
G58 V3  use preset work coordinate system 5
G59 LC  Select Coordinate System 6
G59 V3  use preset work coordinate system 6
G59.1   LC  Select Coordinate System 7
G59.1   V3  use preset work coordinate system 7
G59.2   LC  Select Coordinate System 8
G59.2   V3  use preset work coordinate system 8
G59.3   LC  Select Coordinate System 9
G59.3   V3  use preset work coordinate system 9
G61 LC  Path Control Mode - exact path
G61 V3  set path control mode: exact path
G61.1   LC  Path Control Mode - exact stop (same as G61)
G61.1   V3  set path control mode: exact stop
G64 LC  Path Control Mode - Optional Tolerance
G64 V3  set path control mode: continuous
G73 LC  Drilling Cycle with Chip Breaking
G76 LC  Multi-pass Threading Cycle (Lathe)
G80 LC  Cancel Motion Modes
G80 V3  cancel motion mode (including any canned cycle)
G81 LC  Drilling Cycle
G81 V3  canned cycle: drilling
G82 LC  Drilling Cycle with Dwell
G82 V3  canned cycle: drilling with dwell
G83 LC  Drilling Cycle with Peck
G83 V3  canned cycle: peck drilling
G84 V3  canned cycle: right hand tapping
G85 LC  Boring Cycle, No Dwell, Feed Out
G85 V3  canned cycle: boring, no dwell, feed out
G86 LC  Boring Cycle, Stop, Rapid Out
G86 V3  canned cycle: boring, spindle stop, rapid out
G87 V3  canned cycle: back boring
G88 V3  canned cycle: boring, spindle stop, manual out
G89 LC  Boring Cycle, Dwell, Feed Out
G89 V3  canned cycle: boring, dwell, feed out
G90 LC  G91 Distance Mode
G90 MF  Use Absolute Coordinates
G90 RG  Absolute Positioning
G90 RR  Set to Absolute Positioning
G90 V3  absolute distance mode
G90.1   LC  Arc Distance Mode - absolute IJK
G91 MF  Use Relative Coordinates
G91 RG  Relative Positioning
G91 RR  Set to Relative Positioning
G91 V3  incremental distance mode
G91.1   LC  Arc Distance Mode - incremental IJK
G92.1   V3  cancel offset coordinate systems and set parameters to zero
G92 LC  Coordinate System Offset
G92 MF  Set current position to cordinates given
G92 RG  Define current position on axes
G92 RR  Set Position
G92 V3  offset coordinate systems and set parameters
G92.1   LC  Cancel Coordinate System Offsets
G92.2   LC  Cancel Coordinate System Offsets
G92.2   V3  cancel offset coordinate systems but do not reset parameters
G92.3   LC  Restore Axis Offsets
G92.3   V3  apply parameters to offset coordinate systems
G93 LC  Feed Mode - Inverse time
G93 V3  inverse time feed rate mode
G94 LC  Feed Mode - Units per minute
G94 RG  Feed rate mode (not implemented)
G94 V3  units per minute feed rate mode
G95 LC  Feed Mode - Units per revolution
G96 LC  Constant Surface Speed
G97 LC  RPM Mode
G97 RG  Spindle speed rate
G98 LC  Canned Cycle Z Retract Mode
G98 V3  initial level return in canned cycles
G99 LC  Canned Cycle Z Retract Mode
G99 V3  R-point level return in canned cycles
G161    RG  Home negative
G162    RG  Home positive

M0  LC  Program Pause
M0  RG  Unconditional Halt (not supported on SD)
M0  RR  Stop
M0  V3  program stop
M1  LC  Program Pause - optional
M1  RG  Optional Halt (not supported on SD)
M1  RR  Sleep
M1  V3  optional program stop
M2  LC  Program End
M2  RG  End program
M2  V3  program end
M3  LC  Spindle Control - clockwise ON
M3  RG  spindle on, CW
M3  RR  Spindle On, Clockwise (CNC specific)
M3  V3  turn spindle clockwise
M4  LC  Spindle Control - counterclockwise ON
M4  RG  spindle on, CCW
M4  RR  Spindle On, Counter-Clockwise (CNC specific)
M4  V3  turn spindle counterclockwise
M5  LC  Spindle Control - OFF
M5  RG  spindle off
M5  RR  Spindle Off (CNC specific)
M5  V3  stop spindle turning
M6  LC  Tool Change
M6  RG  Tool change. This code waits until the toolhead is ready before proceeding. This is often used to wait for a toolhead to reach the its set temperature before beginning a print. ReplicatorG also supports giving a timeout with M6 P<secs>.
M6  V3  tool change
M7  LC  Coolant Control - mist ON
M7  RG  coolant A on (flood coolant)
M7  RR  Mist Coolant On (CNC specific)
M7  V3  mist coolant on
M8  LC  Coolant Control - flood ON
M8  RG  cooland B on (mist coolant)
M8  RR  Flood Coolant On (CNC specific)
M8  V3  flood coolant on
M9  LC  Coolant Control - OFF
M9  RG  all coolants off
M9  RR  Coolant Off (CNC specific)
M9  V3  mist and flood coolant off
M10 RG  close clamp
M10 RR  Vacuum On (CNC specific)
M11 RG  open clamp
M11 RR  Vacuum Off (CNC specific)
M13 RG  spindle CW and coolant A on
M14 RG  spindle CCW and coolant A on
M17 MF  Enable/Power all stepper motors
M17 RG  enable motor(s)
M17 RR  Enable/Power all stepper motors
M18 MF  Disable all stepper motors; same as M84
M18 RG  disable motor(s)
M18 RR  Disable all stepper motors
M20 MF  List SD card
M20 RR  List SD card
M21 MF  Init SD card
M21 RG  open collet
M21 RR  Initialize SD card
M22 MF  Release SD card
M22 RG  close collet
M22 RR  Release SD card
M23 MF  Select SD file (M23 filename.g)
M23 RR  Select SD file
M24 MF  Start/resume SD print
M24 RR  Start/resume SD print
M25 MF  Pause SD print
M25 RR  Pause SD print
M26 MF  Set SD position in bytes (M26 S12345)
M26 RR  Set SD position
M27 MF  Report SD print status
M27 RR  Report SD print status
M28 MF  Start SD write (M28 filename.g)
M28 RR  Begin write to SD card
M29 MF  Stop SD write
M29 RR  Stop writing to SD card
M30 LC  Program End - exchange pallet shuttles
M30 MF  Delete file from SD (M30 filename.g)
M30 RG  program rewind
M30 RR  Delete a file on the SD card
M30 V3  program end, pallet shuttle, and reset
M31 MF  Output time since last M109 or SD card start to serial
M40-M46 RG  change gear ratio (0 - 6)
M40 RR  Eject
M41 RR  Loop
M42 MF  Change pin status via gcode
M42 RR  Stop on material exhausted / Switch I/O pin
M43 RR  Stand by on material exhausted
M48 LC  Feed & Spindle Overrides - Enable
M48 V3  enable speed and feed overrides
M49 LC  Feed & Spindle Overrides - Disable
M49 V3  disable speed and feed overrides
M50 LC  Feed Override Control
M50 RG  read spindle speed
M51 LC  Spindle Override Control
M52 LC  Adaptive Feed Control
M53 LC  Feed Stop Control
M60 LC  Pallet Change Pause
M60 V3  pallet shuttle and program stop
M61 LC  Set Current Tool Number
M62 LC  Output Control - synchronized ON
M63 LC  Output Control - synchronized OFF
M64 LC  Output Control - immediate ON
M65 LC  Output Control - immediate OFF
M66 LC  Input Control - wait
M67 LC  Analog Output Control - synchronized
M68 LC  Analog Output Control - immediate
M70 RG  Display message on machine, with optional timeout specified by P-code in seconds
M71 RG  Pause activity and display message, resuming build on button push. Optional timeout specified by P-code in seconds. If timeout is specified and no button is pushed, machine should shut down or reset.
M72 RG  Play a song or tone defined by the machine, by a P-code specifying a song type. Default songs are Error Sound (P0), a Ta-da sound (P1), and a warning sound (P2). all other sounds are user or machine specific, with P2 the default for unknown sounds.
M73 RG  Manually set build percentage. Valid P values are 0 to 100, values over 100 are rounded down to 100
M80 MF  Turn on Power Supply
M80 RR  ATX Power On
M81 MF  Turn off Power Supply
M81 RR  ATX Power Off
M82 MF  Set E codes absolute (default)
M82 RR  set extruder to absolute mode
M83 MF  Set E codes relative while in Absolute Coordinates (G90) mode
M83 RR  set extruder to relative mode
M84 MF  Disable steppers until next move, or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.
M84 RR  Stop idle hold
M85 MF  Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
M92 MF  Set axis_steps_per_unit - same syntax as G92
M92 RR  Set axis_steps_per_unit
M98 RR  Get axis_hysteresis_mm
M99 RR  Set axis_hysteresis_mm
M100    LC  through M199   User Defined M codes
M101    RR  Extruder on, fwd
M101    RR  Turn extruder 1 on Forward / Undo Extruder Retraction
M102    RR  Extruder on, reverse
M102    RR  Turn extruder 1 on Reverse
M103    RR  Extruder off
M103    RR  Turn all extruders off / Extruder Retraction
M104    MF  Set extruder target temp
M104    RR  Set Extruder Temperature
M104    RR  Snn set temperature in degrees Celsius
M105    MF  Read current temp
M105    RR  get extruder temperature
M105    RR  Get Extruder Temperature
M106    MF  Fan on
M106    RR  Fan On
M106    RR  turn fan on
M107    MF  Fan off
M107    RR  Fan Off
M107    RR  turn fan off
M108    RR  Set Extruder's Max Speed (Rnnn = RPM, Pnnn = PWM)
M108    RR  Set Extruder Speed
M109    MF  Wait for extruder current temp to reach target temp.
M109    RR  Set Extruder Temperature and Wait
M109    RR  Snnn set build platform temperature in degrees Celsuis
M110    RR  Set Current Line Number
M110    RR  Snnn set chamber temperature in degrees Celsius
M111    RR  Set Debug Level
M112    RR  Emergency Stop
M113    RR  Set Extruder PWM
M114    MF  Display current position
M114    MF  Output current position to serial port
M114    RR  Get Current Position
M115    MF  Capabilities string
M115    RR  Get Firmware Version and Capabilities
M116    RR  Wait
M117    MF  display message
M117    RR  Get Zero Position
M118    RR  Negotiate Features
M119    MF  Output Endstop status to serial port
M119    RR  Get Endstop Status
M120    RR  M121, M122 Snnn set the PID gain for the temperature regulator (not currently supported by ReplicatorG)
M123    RR  M124 Snnn set iMax and iMin windup guard for the PID controller (not currently supported by ReplicatorG)
M126    JF  use acceleration for subsequent instructions
M126    RG  valve open (acceleration on for subsequent instructions in the Jetty Firmware)
M126    RR  Open Valve
M127    JF  disable acceleration for subsequent instructions
M127    RG  valve close (acceleration off for subsequent instructions in the Jetty Firmware)
M127    RR  Close Valve
M128    RR  Extruder Pressure PWM
M128    RR  get position
M129    RR  Extruder pressure off
M129    RR  get range (not currently supported by ReplicatorG)
M130    RR  Set PID P value
M130    RR  set range (not currently supported by ReplicatorG)
M131    RR  Set PID I value
M132    RR  Set PID D value
M133    RR  Set PID I limit value
M134    RR  Write PID values to EEPROM
M136    RR  Print PID settings to host
M140    MF  Set bed target temp
M140    RR  Bed Temperature (Fast)
M141    RR  Chamber Temperature (Fast)
M142    RR  Holding Pressure
M143    RR  Maximum hot-end temperature
M160    RR  Number of mixed materials
M190    MF  Wait for bed current temp to reach target temp.
M190    RR  Wait for bed temperature to reach target temp
M200    JF  reset (to pick up changes)
M200    MF  Set filament diameter
M200    RR  reset driver
M200    RR  Set filament diameter / Get Endstop Status
M201    JF  set maximum rates of acceleration/deceleration
M201    MF  Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
M201    RR  Set max printing acceleration
M202    MF  Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
M202    RR  clear buffer (not currently supported by ReplicatorG)
M202    RR  Set max travel acceleration
M203    JF  set maximum feed rates
M203    MF  Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
M203    RR  Set maximum feedrate
M204    JF  set default rates of acceleration
M204    MF  Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2  also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate
M204    RR  Set default acceleration
M205    JF  set minimum feed rates and planner speed
M205    MF   advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E=maximum E jerk
M205    RR  advanced settings
M206    JF  set extruded noodle diameter, extruder maximum reverse feed rate, extruder deprime, slowdown limit, and direction of extruder feed
M206    MF  set additional homeing offset
M206    RR  set home offset
M207    JF  set JKN Advance parameters K and K2
M207    RR  calibrate z axis by detecting z max length
M208    JF  set extruder steps per millimeter
M208    RR  set axis max travel
M209    JF  turn acceleration planner on or off; enable or disable override of gcode temperature settings
M209    RR  enable automatic retract
M215    JF  set steps per millimeter for each axis
M216    JF  set maximum speed changes for each axis
M220    MF  S<factor in percent> set speed factor override percentage
M220    RR  Set speed factor override percentage
M221    MF  S<factor in percent> set extrude factor override percentage
M221    RR  set extrude factor override percentage
M226    RR  Gcode Initiated Pause
M227    RR  Enable Automatic Reverse and Prime
M228    RR  Disable Automatic Reverse and Prime
M229    RR  Enable Automatic Reverse and Prime
M230    RR  Disable / Enable Wait for Temperature Change
M240    MF  Trigger a camera to take a photograph
M240    RR  Start conveyor belt motor / Echo off
M241    RR  Stop conveyor belt motor / echo on
M245    RR  Start cooler
M246    RR  Stop cooler
M300    RR  Play beep sound
M300    RR  Snnn set servo 1 position
M301    MF  Set PID parameters P I and D
M301    RR  Set PID parameters - Hot End
M301    RR  Snnn set servo 2 position
M302    MF  Allow cold extrudes
M303    MF  PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
M304    RR  Set PID parameters - Bed
M310    RG  (filepath) logging
M311    RG  stop logging
M312    RG  (message) log message
M320    RG  acceleration on for subsequent instructions
M321    RG  acceleration off for subsequent instructions
M400    MF  Finish all moves
M420    RR  Set RGB Colors as PWM
M500    MF  stores paramters in EEPROM
M500    RR  stores paramters in EEPROM
M501    MF  reads parameters from EEPROM (if you need reset them after you changed them temporarily).
M501    RR  reads parameters from EEPROM
M502    MF  reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
M502    RR  reverts to the default "factory settings".
M503    MF  print the current settings (from memory not from eeprom)
M503    RR  Print settings
M999    MF  Restart after being stopped by error

, , ,


OpenSCAD vs. Skeinforge 40: Bogus G-Code

My first pass at the NEMA 17 motor mount bracket used additive modeling, glomming together several blocks made from cube primitives:

  • The motor mounting plate, less five holes
  • Two side struts to stiffen the motor plate
  • The baseplate, minus two mounting holes

Makes perfect sense to me; perhaps I’m an additive kind of guy. That produced an OpenSCAD model with positive surfaces for the various parts and negative surfaces inside the holes:

NEMA 17 Mount - additive model

NEMA 17 Mount - additive model

Compile that through CGAL, export as STL, inhale into RepG 25, and you (well, I) get what looks to be a fine object in the preview pane:

NEMA 17 RepG preview - additive

NEMA 17 RepG preview - additive

Then run it through Skeinforge 40, which emits a flurry of messages along these lines:

[19:11:08] Warning, the triangle mesh slice intersects itself in getLoopsFromCorrectMesh in triangle_mesh.
[19:11:08] Something will still be printed, but there is no guarantee that it will be the correct shape.
[19:11:08] Once the gcode is saved, you should check over the layer with a z of:
[19:11:09] 0.165

The usual searching suggested that sometimes Skeinforge has problems with coincident surfaces, such as between the motor mount plate and the struts and the base, or coincident edges where two blocks abut. Judging from the messages, the problem ran all the way to the top of the struts. Oddly, Skeinview didn’t show any problems, so the G-Code was (presumably) OK.

Error messages tend to make me twitchy, though. I modified the OpenSCAD code to extend the struts 0.1 mm inside the base and ran that model through the software stack, which produced not a single complaint about anything, anywhere.


However, painful experience has caused me to review the G-Code for every single object with the Skeinlayer plugin, which, right on cue, revealed this interesting anomaly:

NEMA 17 Mount - Skeinview - Bad gcode

NEMA 17 Mount - Skeinview - Bad gcode

That happened for every layer in the square motor mount plate: the lower right corner is fine, the upper left seems to be the negative of the actual solid model. The holes are filled, the plate is empty. The Skirt outline ignores the smaller holes, goes around the large one, and continues on its merry way.

I putzed around for a while and discovered that the failure seems acutely sensitive to the side strut thickness. Yeah, like that makes any sense.

Any variations along those lines that I tried generated either:

  • A flurry of mesh error messages, with seemingly good G-Code
  • No error messages whatsoever, with totally bogus G-Code

Running the STL files through netfabb Cloud Service produced the same diagnostic for both:

Number of holes: 3
Number of shells: 2
Mesh is not manifold and oriented.
 We unfortunately have not yet enough experience with the occuring server loads, that we can securely enable shell merging at the moment.

However, the repaired STL files produce correct G-Code: evidently OpenSCAD spits out bogus STL data. The fact that RepG/SF treats the two files differently suggests improved diagnostics would be in order, but that’s in the nature of fine tuning.

So I junked the additive model and went subtractive, chewing the recesses out of one huge block:

NEMA 17 Stepper Mount - solid model

NEMA 17 Stepper Mount - solid model

That worked:

Number of holes: 0
Number of shells: 1
Mesh is manifold and oriented.

I like processes that don’t emit error messages or result in mysterious failures, although it’s not obvious that subtractive modeling will always produce correct results. Heck, I’m not sure I can think in terms of negative volumes all that well.

The OpenSCAD code for the additive model, with a highlight on the conditional that will trigger the two errors:

// NEMA 17 stepper motor mount
// Ed Nisley KE4ZNU August 2011

include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>

//-- Layout Control

Layout = "Build";				// Build Show None

Examine = "None";				// Mount Stand None

//-- Extrusion parameters

ThreadThick = 0.33;
ThreadWT = 2.0;
ThreadWidth = ThreadThick * ThreadWT;

HoleWindage = 0.3;			// enlarge hole dia by this amount

function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);

//-- Useful sizes

Tap2_56 = 0.070 * inch;
Clear2_56 = 0.082 * inch;
Head2_56 = 0.156 * inch;
Head2_56Thick = 0.055 * inch;
Nut2_56Dia = 0.204 * inch;
Nut2_56Thick = 0.065 * inch;

Tap3_48 = 0.079 * inch;
Clear3_48 = 0.096 * inch;
Head3_48 = 0.184 * inch;
Head3_48Thick = 0.058 * inch;
Nut3_48Dia = 0.201 * inch;
Nut3_48Thick = 0.073 * inch;

Tap4_40 = 0.089 * inch;
Clear4_40 = 0.110 * inch;
Head4_40 = 0.211 * inch;
Head4_40Thick = 0.065 * inch;
Nut4_40Dia = 0.228 * inch;
Nut4_40Thick = 0.086 * inch;

Tap10_32 = 0.159 * inch;
Clear10_32 = 0.190 * inch;
Head10_32 = 0.373 * inch;
Head10_32Thick = 0.110 * inch;
Nut10_32Dia = 0.433 * inch;
Nut10_32Thick = 0.130 * inch;

NEMA17_ShaftDia = 5.0;
NEMA17_ShaftLength = 24.0;
NEMA17_PilotDia = 0.866 * inch;
NEMA17_PilotLength = 0.080 * inch;
NEMA17_BCD = 1.725 * inch;
NEMA17_BoltDia = 3.5;
NEMA17_BoltOC = 1.220 * inch;

//-- Mount Sizes

MountSide = IntegerMultiple(NEMA17_BCD,ThreadWidth);
MountThick = IntegerMultiple(8.0,ThreadThick);

MountBoltDia = 3.0;

StrutThick = IntegerMultiple(5.0,ThreadWidth);
StrutHeight = MountSide;

StandThick = IntegerMultiple(4.0,ThreadWidth);

UprightLength = IntegerMultiple(MountSide + 2*StrutThick,5);

StandBoltAllowance = IntegerMultiple(Head10_32,5);
StandBoltOC = UprightLength + 2*StandBoltAllowance;

StandLength = IntegerMultiple(StandBoltOC + 2*StandBoltAllowance,ThreadWidth);
StandWidth = IntegerMultiple(2*StandBoltAllowance,ThreadThick);

echo(str("Stand Base: ",StandLength," x ",StandWidth));
echo(str("Stand Bolt OC: ",StandBoltOC));

//-- Convenience values

Protrusion = 0.1;		// make holes look good and joints intersect properly

BuildOffset = 3 * ThreadWidth;

// Useful routines

module PolyCyl(Dia,Height,ForceSides=0) {			// based on nophead's polyholes

  Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);

  FixDia = Dia / cos(180/Sides);

  cylinder(r=(FixDia + HoleWindage)/2,

module ShowPegGrid(Space = 10.0,Size = 1.0) {

  Range = floor(50 / Space);

	for (x=[-Range:Range])
	  for (y=[-Range:Range])


// Motor Mount plate

module MotorMount() {

  difference() {
if (true) {
	  PolyCyl(NEMA17_PilotDia,(MountThick + 2*Protrusion));
else {
	translate([0,0,MountThick - NEMA17_PilotLength])
	  PolyCyl(NEMA17_PilotDia,(NEMA17_PilotLength + Protrusion));
	  PolyCyl(1.5*NEMA17_ShaftDia,(MountThick + 2*Protrusion));
	for (x=[-1,1])
	  for (y=[-1,1])
		  PolyCyl(MountBoltDia,(MountThick + 2*Protrusion));


// Stand to support the plate

module Stand() {

  difference() {

	union() {
	  for (x=[-1,1])						// side support struts
if (true)	// this causes bizarre negative rendering and a diagonal negative section
		translate([(x*((MountSide + StrutThick)/2)),0,
				  (StandThick + StrutHeight/2 - Protrusion/2)])
		  cube([StrutThick,StandWidth,(StrutHeight + Protrusion)],center=true);
else	// this generates "triangle slice mesh intersects iself"
		translate([(x*((MountSide + StrutThick)/2)),0,
				  (StandThick + StrutHeight/2)])

	for (x=[-1,1])
		PolyCyl(Clear10_32,StandThick + 2*Protrusion);

// Combined for single build

module Combined() {

//  union() {


//  }

// Lash everything together


if (Examine == "Mount")

if (Examine == "Stand")

if (Layout == "Build" && Examine == "None") {

if ((Layout == "Show") && Examine == "None") {

OpenSCAD depends on CGAL for all the 3D heavy lifting, which puts any STL export problems further upstream.  I suppose I could open Yet Another RepG ticket to get better diagnostics, but the others haven’t gotten much attention so far and I suppose it’s not really their problem anyway.



Thing-O-Matic: Z-Minimum Probe G-Code

The G-Code in start.gcode homes all three axes, but now I have two limit switches on the Z axis: the MBI Z-Maximum at the top and a new Z-Minimum on the platform. The Z axis platform can’t miss the switch at the top, but I must position the nozzle directly over the Z-Minimum switch on the platform before probing for it. Homing the stage at the top of the Z axis makes sure the nozzle starts more-or-less at the right height over the switch, which then provides an exact adjustment.

For the home switches on my Sherline CNC milling machine, the EMC2 homing routines proceed in two stages: a fast slew to find the switch, then a slow approach to ensure the axis doesn’t overrun the switch. That seemed like a good way to ensure that the X and Y stages would home repeatably enough to hit a 2 mm button with a 1 mm nozzle every time.

I recycled the default home sequence for coarse homing, albeit with the speeds cranked up a bit:

(- coarse home axes -)
G162 Z F1000	(home Z to get nozzle out of danger zone)
G161 Y F4000	(retract Y to get X out of front opening)
G161 X F4000	(now safe to home X)
G92 X-53.0 Y-59.0 Z117.0	(set XYZ coordinate zeros)

Then the fine homing sequence backs off a few millimeters and bumps the switches very slowly:

(- fine home axes)
G0 X-51 Y-57 Z115 F400	(back off switches)
G161 Y F200
G161 X F200
G162 Z F200
G92 X-53.0 Y-59.0 Z117.0	(re-set XYZ coordinate zeros)

You could set relative motion mode with G91; that might be cleaner all around.

I discovered experimentally that you must set all three axes in the G92 command, because any missing axes get set to 0.0: probably not what you want. It’s not what I expected, either, but this isn’t the EMC2 G-Code dialect I’m more familiar with.

In normal use, the extruder has been heating for quite a while and there’s no pressure inside. There’s most likely a long strand of filament hanging off the end that will interfere with the switch, so a preliminary wipe is in order. I first pause the nozzle over the middle of the platform as a visual indication that everything started up OK, then make a dogleg around the wiper blade to the front of the wipe station:

(- manual nozzle wipe)
G0 X0 Y0 Z10	    (pause at center to build confidence)
G4 P500
G0 X40 Y-57.0 Z10	(move to front, avoid wiper blade)
G0 X56            (to wipe station)
G0 Z6.0           (down to wipe level)
M6 T0			        (wait for temperature settling)
G1 Y-40	F1000		  (slowly wipe nozzle)

With the dry wipe done, move to the Z-Min switch and poke it very very slowly:

(- home Z downward to platform switch)
G0 X55.9 Y8 Z3	      (get over build platform switch)
G161 Z0 F50	          (home downward very slowly)
G92 X55.7 Y8 Z1.45	  (set Z for actual switch trip height)
G0 Z6.0			          (back off switch to wipe level)

I had to determine the actual height of the trip point experimentally, by doing some test extrusions and adjusting that Z1.45 to make the answer come out right. I’m sure that will change as things settle into their final places.

Ditto for the exact XY location of the Z-Min switch, which I found by using a very slow G1 move to Z2.0 in place of the G161 probe.

Note that you increase the Z value in G92 to lower the initial nozzle position and vice versa. It helps to draw some diagrams and work through the whole thing to be sure you understand it; that’s what I had to do, anyway.

Then return the nozzle to the wipe station by running over the blade again to dislodge any gunk on the front side, crank up the extruder to build up pressure, and wipe again to get rid of the snot ball:

(- start extruder and re-wipe)
G0 X56 Y-40     (set up for wipe from rear)
G1 Y-57.0 F1000 (wipe to front)
M108 R2.0	      (set stepper extruder speed)
M101		        (Extruder on, forward)
G4 P4000  	    (take up slack, get pressure)
M103		        (Extruder off)
G4 P4000  	    (Wait for filament to stop oozing)
G1 Y-40	F1000		(slowly wipe nozzle again)
G0 X0           (get away from wiper blade)

Running the extruder here ensures that, no matter what, the molten ABS in the hot end begins the print in a consistent state every time. The extruded length varies from a few millimeters to a real string, so there’s obviously plenty of variation.

Then I put a manual splodge turd at the middle of the front edge of the platform. This is unnecessary now that SF40 shuts off the extruder before zipping off to the first Skirt, so I’ll probably junk it in the near future:

(- manual splodge)
G0 X0 Y-58		  (to front center)
G0 Z0.5 		    (just over surface)
M108 R2.0	      (set stepper extruder speed)
M101            (start extruder)
G4 P2000        (build up a turd)

Putting all that together with some odds & ends gives the complete current version of start.gcode:

(---- start.gcode begins ----)
(MakerBot Thing-O-Matic with aluminum HBP and Z-min platform switch)
(Tweaked for TOM 286 - Ruttmeister MK5 stepper extruder mod)
(Ed Nisley - KE4ZNU - May 2011)
(- set initial conditions -)
G21		(set units to mm)
G90		(set positioning to absolute)
(- begin heating -)
M104 S210 T0	(extruder head)
M109 S120 T0	(HBP)
(- coarse home axes -)
G162 Z F1000	(home Z to get nozzle out of danger zone)
G161 Y F4000	(retract Y to get X out of front opening)
G161 X F4000	(now safe to home X)
G92 X-53.0 Y-59.0 Z117.0	(set XYZ coordinate zeros)
(- fine home axes)
G0 X-51 Y-57 Z115 F400	(back off switches)
G161 Y F200
G161 X F200
G162 Z F200
G92 X-53.0 Y-59.0 Z117.0	(re-set XYZ coordinate zeros)
(- manual nozzle wipe)
G0 X0 Y0 Z10	    (pause at center to build confidence)
G4 P500
G0 X40 Y-57.0 Z10	(move to front, avoid wiper blade)
G0 X56            (to wipe station)
G0 Z6.0           (down to wipe level)
M6 T0			        (wait for temperature settling)
G1 Y-40	F1000		  (slowly wipe nozzle)
(- home Z downward to platform switch)
G0 X55.9 Y8 Z3	      (get over build platform switch)
G161 Z0 F50	          (home downward very slowly)
G92 X55.7 Y8 Z1.45	  (set Z for actual switch trip height)
G0 Z6.0			          (back off switch to wipe level)
(- start extruder and re-wipe)
G0 X56 Y-40     (set up for wipe from rear)
G1 Y-57.0 F1000 (wipe to front)
M108 R2.0	      (set stepper extruder speed)
M101		        (Extruder on, forward)
G4 P4000  	    (take up slack, get pressure)
M103		        (Extruder off)
G4 P4000  	    (Wait for filament to stop oozing)
G1 Y-40	F1000		(slowly wipe nozzle again)
G0 X0           (get away from wiper blade)
(- manual splodge)
G0 X0 Y-58		  (to front center)
G0 Z0.5 		    (just over surface)
M108 R2.0	      (set stepper extruder speed)
M101            (start extruder)
G4 P2000        (build up a turd)
(---- start.gcode ends ----)

Then I did a bunch of measurements to see how it worked…

, ,


G-code and Suchlike

A place for CNC & machine shop files of general interest… and so I can find them again.

Update: This page became inactive after Wordpress introduced the source code tag, so I could include the code with the post text: search for Arduino source code, OpenSCAD source code, G-Code sourcePython source code, and so forth to find them. When the WP editors began destroying the source code formatting, I moved the code snippets to my GitHub gists; the same search strings find the posts.

The Y-axis leadscrew cover template for Sherline milling machines, originally from There’s also an A4 version. Attach with double-sided sticky tape!

I cooked up an improved version of the bellows, with color-coded folds and taping hints. Separate versions for the front and back bellows, with one fewer pleat so they fit on both Letter and A4 paper sizes.

A HAL file that uses a Logitech Dual Action Gamepad as a pendant, with axis lockout on the joystick knobs: Logitech Dual Action Gamepad – joystick axis lockout – custom_postgui.hal. More details there and there, including the other files you must tweak to use this one. It’s an OpenOffice document, so you must re-save it as a text document and then chop it up with your favorite text editor.

Milling a post in a sheet of acrylic plastic: Postmill.ngc.odt. I used this to make colon dots for a digital clock. Save the file as text and feed it into EMC2.

The inverse problem of milling a circular recess: Circular Recess Milling.ngc.

An Eagle ULP file (EMC-Sherline-drillingulp.odt) that extracts the holes from a PCB layout, sorts them by drill size, then visits each one in nearest-neighbor order. It’s way faster than the usual random walk and much faster than raster-scanning the board. Touches each hole with a center drill, which probably isn’t necessary. This is embedded inside an OpenOffice file; just do a Save As to ASCII text (EMC-Sherline-drilling.ulp) in whatever folder Eagle uses for ulp routines on your system and it’ll work fine.

An Eagle CAM file (twosided-pscam.odt) that creates Postscript files for the top & bottom & silkscreen layers of circuit boards. It’s embedded inside an OpenOffice file; Save As to ASCII text ( in whatever folder Eagle uses for cam routines on your system and it’ll work fine.


Makergear M2: CNC Platform Corner Clips

The CNC version of the corner clips looks much better than the prototypes:

M2 glass retaining clip

M2 glass retaining clip

Tightening the screws until the clip just flattens puts enough force on the glass + heat spreader stack to hold it firmly against the balls in the bottom pad. The solid rubber L-shaped bumpers and screws hold the glass in position against XY forces… and the whole affair looks much better than the original (and perfectly serviceable) bulldog clips. These clips free up the entire surface of the glass plate, minus four 12 mm triangles that you could, if you were desperate, print right over.

Although it’d be easier to just hack out an angular clip, I wrote a bit of G-Code to put a nice radius on each corner. The clip sits atop the rubber bumper with a 0.5 mm margin to keep the metal edges away from fingers; they’re smooth, but it’s still a strip of 6 mil (= 0.15 mm) phosphor bronze and feels a lot like a knife edge if you press hard enough.

The radius on the three outside corners is a special-case solution of the general circle-through-three-points problem, taking advantage of the symmetry and right-triangle-ness of the corners. This sketch shows the details:

M2 Platform Clip Doodles 4 - corner fairing with margin

M2 Platform Clip Doodles 4 – corner fairing with margin

The two corners on the bevel over the glass plate have a fixed radius. I reworked my original fairing arc solution for outside cutting and doodled it up for this situation:

M2 Platform Clip Doodles 5 - bevel full solution

M2 Platform Clip Doodles 5 – bevel full solution

The outside corner radius worked out to 5 mm and I set the bevel radius at 3 mm. I think the latter made those corners a bit too sharp, but it’s Good Enough for my simple needs.

Drilling and machining the clips required a fixture:

M2 platform clips - milling edges

M2 platform clips – milling edges

That’s a story for another day.

I used cutter diameter compensation to mill the edges, starting oversize by 1.5 mm and working downward by 0.5 mm on each pass to the actual diameter. That gradually trimmed off the edges without any excitement, so I could start with rough-trimmed stock and not worry about precision hand trimming.

I thought climb milling (CW around the part) would produce better results, but it tended to smear the phosphor bronze against the fixture:

M2 Corner Clips - Climb milling tool paths

M2 Corner Clips – Climb milling tool paths

Conventional milling (CCW around the part) actually worked, but it required fancier entry and exit moves:

M2 Corner Clips - Conventional milling tool paths

M2 Corner Clips – Conventional milling tool paths

This part is the kind and size of machining perfectly suited to a Sherline CNC mill…

The LinuxCNC G-Code source:

( M2 Build Platform Corner Clips )
( Ed Nisley - KE4ZNU - July 2013 )
( Fixture origin at right-front corner pip )

( Flow Control )
#<_Do_Drill> = 0		( Drill two holes in clip )
#<_Do_Mill> = 1			( Mill clip outline )
#<_Climb_Mill> = 0		( 0 = conventional 1 = climb)

( Fixture info )
#<_Drill_X_Fixture> = 5.0	( Drill station origin )
#<_Drill_Y_Fixture> = 5.0

#<_Drill_Num> = 30			( Drill number in tool table)
#<_Drill_Retract> = 15
#<_Drill_Depth> = -1.0
#<_Drill_Feed> = 300
#<_Drill_Speed> = 3000

#<_Mill_X_Fixture> = 40.0	( Mill station origin )
#<_Mill_Y_Fixture> = 5.0

#<_Mill_Num> = 3			( Mill number in tool table)
#<_Mill_Dia> = 4.60			( actual tool diameter)
#<_Mill_Dia_Incr> = 0.50
#<_Mill_Dia_Steps> = 3
#<_Mill_Retract> = 15
#<_Mill_Depth> = -0.5
#<_Mill_Feed> = 300
#<_Mill_Speed> = 8000


(  Initialize first tool length at probe switch )
(     Assumes G59.3 is still in machine units, returns in G54 )
(  ** Must set these constants to match G20 / G21 condition! )

#<_Probe_Speed>     = 400            ( set for something sensible in mm or inch )
#<_Probe_Retract>   =   1            ( ditto )

O<Probe_Tool> SUB

G49                     ( clear tool length compensation )
G30                     ( move above probe switch )
G59.3                   ( coord system 9 )

G38.2 Z0 F#<_Probe_Speed>           ( trip switch on the way down )
G0 Z[#5063 + #<_Probe_Retract>]     ( back off the switch )
G38.2 Z0 F[#<_Probe_Speed> / 10]    ( trip switch slowly )

#<_ToolZ> = #5063                    ( save new tool length )

G43.1 Z[#<_ToolZ> - #<_ToolRefZ>]    ( set new length )

G54                     ( coord system 0 )
G30                     ( return to safe level )

O<Probe_Tool> ENDSUB

(-- Initialize first tool length at probe switch )

O<Probe_Init> SUB

#<_ToolRefZ> = 0.0      ( set up for first call )

O<Probe_Tool> CALL

#<_ToolRefZ> = #5063    ( save trip point )

G43.1 Z0                ( tool entered at Z=0, so set it there )

O<Probe_Init> ENDSUB

(-- Mill one pass around outline with tool diameter passed in #1 )

O<MillOutline> SUB

#<X_Size> = 22.0		( size of support spider pad = nominal clip size )
#<Y_Size> = 22.0
#<Base_Bevel> = 3.2		( X or Y length of corners clipped from spider pad )

#<Bevel_Size> = 9.0		( remaining part of trimmed edges on clip )
#<Bevel_Radius> = 3.0	( fairing radius at bevel corners on clip)

#<R_Div_Root2> = [#<Bevel_Radius> / SQRT[2]]
#<R_1M_Recip_R2> = [#<Bevel_Radius> * [1 - 1/SQRT[2]]]
#<R_Root2_M1> = [#<Bevel_Radius> * [SQRT[2] - 1]]

#<Margin> = 0.5			( recess inside of nominal )

#<X_Min> = [#<Margin>]
#<X_Max> = [#<X_Size> - #<Margin>]

#<Y_Min> = [#<Margin>]
#<Y_Max> = [#<Y_Size> - #<Margin>]

#<Corner_Rad> = [[#<Margin> * [1 - SQRT[2]] + [#<Base_Bevel> / SQRT[2]]] / [SQRT[2] - 1]]

O<Climb> IF [#<_Climb_Mill>]

G0 X#<X_Min> Y[#<Y_Max> + 3*#<_Mill_Dia>]
G1 Z#<_Mill_Depth> F#<_Mill_Feed>

G41.1 D#1

G3 X[#<X_Min>] Y#<Y_Max> I0 J[0-1.5*#<_Mill_Dia>]	( cutter comp on: entry move)

G1 X[#<Bevel_Size> - #<R_Root2_M1>]
G2 X[#<Bevel_Size> + #<R_1M_Recip_R2>] Y[#<Y_Max> - #<R_1M_Recip_R2>] J[0-#<Bevel_Radius>]

G1 X[#<X_Max> - #<R_1M_Recip_R2>] Y[#<Bevel_Size> + #<R_1M_Recip_R2>]
G2 X#<X_Max> Y[#<Bevel_Size> - #<R_Root2_M1>] I[0-#<R_Div_Root2>] J[0-#<R_Div_Root2>]

G1 Y[#<Y_Min> + #<Corner_Rad>]
G2 X[#<X_Max> - #<Corner_Rad>] Y#<Y_Min> I[0-#<Corner_Rad>] J0

G1 X[#<X_Min> + #<Corner_Rad>]
G2 X#<X_Min> Y[#<Y_Min> + #<Corner_Rad>] I0 J#<Corner_Rad>

G1 Y[#<Y_Max> - #<Corner_Rad>]
G2 X[#<X_Min> + #<Corner_Rad>] Y#<Y_Max> I#<Corner_Rad> J0


G0 X#<X_Min> Y[#<Y_Max> + 3*#<_Mill_Dia>]
(G3 X#<Bevel_Size> Y[#<Y_Max> + 3*#<_Mill_Dia>] I0 J[1.5*#<_Mill_Dia>])	( cutter comp off: safe exit)

G0 X#<X_Min>			( return to start)

O<Climb> ELSE

G0 X#<X_Size> Y[#<Y_Size> + #1/2]

G1 Z#<_Mill_Depth> F#<_Mill_Feed>

G42.1 D#1

G1 X#<Bevel_Size> Y[#<Y_Max>]	( cutter comp on: entry move)

G1 X[#<X_Min> + #<Corner_Rad>]
G3 X#<X_Min> Y[#<Y_Max> - #<Corner_Rad>] I0 J[0-#<Corner_Rad>]

G1 Y[#<Y_Min> + #<Corner_Rad>]
G3 X[#<X_Min> + #<Corner_Rad>] Y[#<Y_Min>] I#<Corner_Rad> J0

G1 X[#<X_Max> - #<Corner_Rad>]
G3 X[#<X_Max>] Y[#<Y_Min> + #<Corner_Rad>] I0 J#<Corner_Rad>

G1 Y[#<Bevel_Size> - #<R_Root2_M1>]
G3 X[#<X_Max> - #<R_1M_Recip_R2>] Y[#<Bevel_Size> + #<R_1M_Recip_R2>] I[-#<Bevel_Radius>]

G1 X[#<Bevel_Size> + #<R_1M_Recip_R2>] Y[#<Y_Max> - #<R_1M_Recip_R2>]
G3 X[#<Bevel_Size> - #<R_Root2_M1>] Y#<Y_Max> I[-#<R_Div_Root2>] J[-#<R_Div_Root2>]

G2 Y[#<Y_Max> + 3*#<_Mill_Dia>] J[#<_Mill_Dia>*1.5]		( get away from corner)

G0 X#<X_Size>					( cutter comp off: safe exit)
G0 Y[#<Y_Size> + #1/2]			( return to start)

O<Climb> ENDIF

O<MillOutline> ENDSUB

( Start machining... )

G17 G40 G49 G54 G80 G90 G94 G99	( reset many things )

G21								( metric! )
G91.1 							( incremental arc centers)

(msg,Verify: G30.1 position in G54 above tool change switch? )
(msg,Verify: fixture origin XY touched off? )
(msg,Verify: Current tool Z=0 touched off? )

( Set up probing)
O<Probe_Init> CALL
T0 M6

(---- Drill holes)

O<DoDrill> IF [#<_Do_Drill>]

(debug,Insert drill tool = #<_Drill_Num>)
T#<_Drill_Num> M6
O<Probe_Tool> CALL
(debug,Set spindle to #<_Drill_Speed> rpm )

G0 X#<_Drill_X_Fixture> Y#<_Drill_Y_Fixture>
G0 Z#<_Drill_Retract>

G10 L20 P2 X0 Y0 Z#<_Drill_Retract>	( P2 = G55)
G55					( drill station coordinates )

G81 X5.0 Y15.0 Z#<_Drill_Depth> R#<_Drill_Retract> F#<_Drill_Feed>

G81 X15.0 Y5.0


O<DoDrill> ENDIF

(---- Mill outline )
( Start with large diameter and end with actual diameter to trim in stages)

O<DoMill> IF [#<_Do_Mill>]

(debug,Insert mill tool = #<_Mill_Num>)
T#<_Mill_Num> M6
O<Probe_Tool> CALL
(debug,Set spindle to #<_Mill_Speed> rpm )

G0 X#<_Mill_X_Fixture> Y#<_Mill_Y_Fixture>
G0 Z#<_Mill_Retract>

G10 L20 P2 X0 Y0 Z#<_Mill_Retract>	( P2 = G55)
G55					( mill station coordinates )

#<PassCount> = 0

O<MillLoop> DO
#<Diameter> = [#<_Mill_Dia> + [#<_Mill_Dia_Steps> - #<PassCount>]*#<_Mill_Dia_Incr>]

O<MillOutline> CALL [#<Diameter>]

#<PassCount> = [#<PassCount> + 1]
O<MillLoop> WHILE [#<PassCount> LE #<_Mill_Dia_Steps>]

( Finishing pass with zero cut )
O<MillOutline> CALL [#<Diameter>]

G0 Z#<_Mill_Retract>




The rest of the doodles, which don’t match up with the final G-Code because they represent the earliest versions of the layout:

M2 Platform Clip Doodles 1 - overall layout

M2 Platform Clip Doodles 1 – overall layout

M2 Platform Clip Doodles 2 - bevel

M2 Platform Clip Doodles 2 – bevel

M2 Platform Clip Doodles 3 - corner fairing without margin

M2 Platform Clip Doodles 3 – corner fairing without margin

, , ,