The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Tag: M2

Using and tweaking a Makergear M2 3D printer

  • Makergear M2 vs. LinuxCNC: Project Overview

    M2 - cushwa Owl - half scale
    M2 – cushwa Owl – half scale

    During the course of my Makerbot Thing-O-Matic experience, I concluded:

    • Enthusiasm may get a product out, but engineering makes it work
    • Plywood and plastic do not produce a stable 3D printer
    • Measurements matter
    • 8-bit microcontrollers belong in the dustbin of history

    With that in mind, I’ve long thought that LinuxCNC (formerly EMC2) would provide a much better basis for the control software required for a 3D printer than the current crop of Arduino-based microcontrollers. LinuxCNC provides:

    • Hard real time motion control with proven performance
    • A robust, well-defined hardware interface layer
    • Ladder-logic machine control
    • Isolated userspace programming
    • Access to a complete Linux distro’s wealth of programs / utilities
    • Access to an x86 PC’s wealth of hardware gadgetry

    Rather than (try to) force-fit new functions in an Arduino microcontroller, I decided it would be interesting to retrofit a DIY 3D printer with a LinuxCNC controller, improve the basic hardware control and sensing, instrument the extruder, then take measurements that might shed some light on DIY 3D printing’s current shortcomings.

    The overall plan looks like this:

    • Start with a Makergear M2
    • See what the stock hardware can do
    • Replace the RAMBo controller with LinuxCNC
    • See what the hardware can do with better drivers
    • Adapt the G-Code / M-Code processing to use more-or-less stock Marlin G-Code
    • Add useful controllers along the lines of the Joggy Thing
    • Improve the platform height / level sensing
    • Rebuild the extruder with temperature and force sensors
    • Start taking measurements!

    My reasons for choosing the Makergear M2 as the basis for this project should be obvious:

    • All metal: no plywood, no acrylic (albeit a plastic filament drive)
    • Decent stepper motors (with one notable exception)
    • Reasonable hot end design
    • Good reputation

    The first step of the overall plan included a meticulously documented M2 build that I figured would take a month or two, what with the usual snafus and gotchas that accompany building any complex mechanism. Quite by coincidence, a huge box arrived on my birthday (the Thing-O-Matic arrived on Christmas Eve, so perhaps this is a tradition), the day when I learned that Mad Phil had entered his final weeks of life.

    As the Yiddish proverb puts it: If you wish to hear G*d laugh, tell him of your plans.

    So I converted a box of parts into a functional M2 3D printer over the course of four intense days, alternating between our living room floor and a card table in Phil’s home office, showing him how things worked, getting his advice & suggestions, and swapping “Do you remember when?” stories. Another few days sufficed for software installation, configuration, and basic tuneup; I managed to show him some shiny plastic doodads just before he departed consensus reality; as nearly as I can tell, we both benefited from the distractions.

    Which means I don’t have many pictures or much documentation of the in-process tweakage that produced a functional printer. The next week or so of posts should cover the key points in enough detail to be useful.

    Not to spoil the plot or anything: a stock M2 works wonderfully well.

    Owl - half size - left
    Owl – half size – left

    For example, a half-scale cushwa owl printed in PLA at 165 °C with no bed cooling and these Slic3r parameters:

    • 500 mm/s move
    • 300 mm/s infill
    • 200 mm/s solid infill
    • 100 mm/s internal perimeter
    • 50 mm/s bottom layer
    • 30 mm/s external perimeter
    • 1 mm retract @ 300 mm/s

    The beak came out slightly droopy and each downward-pointing feather dangles a glittery drop. There’s room for improvement, but that’s pretty good a week after opening a box o’ parts…

  • 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- http://www.nist.gov/manuscript-publication-search.cfm?pub_id=823374
    LC - LinuxCNC - http://www.linuxcnc.org/docs/
    RG - ReplicatorG - http://replicat.org/gcodes and /mcodes
    JF - Jetty Firmware - http://replicat.org/mcodes at bottom
    RR - RepRap - http://reprap.org/wiki/G_codes (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  MF  CW ARC
    G2  RG  Arc - Clockwise
    G2  V3  circular/helical interpolation (clockwise)
    G3  LC  Coordinated Helical Motion Feed Rate
    G3  MF  CCW ARC
    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
    
  • HAL Pin Names for an Arduino Leonardo Knockoff

    Going through the usual dance to reveal the HAL pin names for an Arduino Leonardo knockoff shows that it is, indeed, both a mouse and a keyboard.

    Arduino Leonardo knockoff - LinuxCNC box
    Arduino Leonardo knockoff – LinuxCNC box

    Pawing through less /proc/bus/input/devices reveals:

    I: Bus=0003 Vendor=2341 Product=8036 Version=0101
    N: Name="Arduino LLC Arduino Leonardo"
    P: Phys=usb-0000:00:1d.0-1/input2
    S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.2/input/input3
    U: Uniq=
    H: Handlers=kbd mouse1 event3
    B: EV=100017
    B: KEY=70000 0 0 0 0 e080ffdf 1cfffff ffffffff fffffffe
    B: REL=103
    B: MSC=10
    

    Tweaking the permissions:

    sudo chgrp users /dev/input/event3
    sudo chgrp users /dev/input/mouse1
    sudo chmod g+w /dev/input/event3
    sudo chmod g+w /dev/input/mouse1
    

    The output of lsusb shows something interesting:

    Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 004 Device 006: ID 06f2:0011 Emine Technology Co. KVM Switch Keyboard
    Bus 004 Device 005: ID 046d:c401 Logitech, Inc. TrackMan Marble Wheel
    Bus 004 Device 004: ID 04d9:1203 Holtek Semiconductor, Inc. MC Industries Keyboard
    Bus 004 Device 003: ID 046d:c216 Logitech, Inc. Dual Action Gamepad
    Bus 004 Device 002: ID 0451:2046 Texas Instruments, Inc. TUSB2046 Hub
    Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 002 Device 002: ID 2341:8036
    Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    

    For whatever reason, this board doesn’t report a device name. It’s plugged into the same USB port as that mouse, so it gets the same Bus and Device numbers, which helps confirm that’s the board.

    Querying the attributes with udevadm produces the all-important product string:

    udevadm info --query=all --attribute-walk --name=/dev/bus/usb/002/002
    ... snippage ...
      looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1':
        KERNEL=="2-1"
        SUBSYSTEM=="usb"
        DRIVER=="usb"
        ATTR{configuration}==""
        ATTR{bNumInterfaces}==" 3"
        ATTR{bConfigurationValue}=="1"
        ATTR{bmAttributes}=="80"
        ATTR{bMaxPower}=="500mA"
        ATTR{urbnum}=="17"
        ATTR{idVendor}=="2341"
        ATTR{idProduct}=="8036"
        ATTR{bcdDevice}=="0100"
        ATTR{bDeviceClass}=="02"
        ATTR{bDeviceSubClass}=="00"
        ATTR{bDeviceProtocol}=="00"
        ATTR{bNumConfigurations}=="1"
        ATTR{bMaxPacketSize0}=="64"
        ATTR{speed}=="12"
        ATTR{busnum}=="2"
        ATTR{devnum}=="2"
        ATTR{version}==" 2.00"
        ATTR{maxchild}=="0"
        ATTR{quirks}=="0x0"
        ATTR{authorized}=="1"
        ATTR{manufacturer}=="Arduino LLC"
        ATTR{product}=="Arduino Leonardo"
    

    Then we know enough to discover what it can do:

    halrun
    halcmd: loadusr -W hal_input -KRAL Leo
    halcmd: show all
    Loaded HAL Components:
    ID      Type  Name                                      PID   State
         5  User  hal_input                                 11265 ready
         3  User  halcmd11264                               11264 ready
    
    Component Pins:
    Owner   Type  Dir         Value  Name
         5  bit   OUT         FALSE  input.0.btn-middle
         5  bit   OUT          TRUE  input.0.btn-middle-not
         5  bit   OUT         FALSE  input.0.btn-mouse
         5  bit   OUT          TRUE  input.0.btn-mouse-not
         5  bit   OUT         FALSE  input.0.btn-right
         5  bit   OUT          TRUE  input.0.btn-right-not
         5  bit   OUT         FALSE  input.0.key-0
         5  bit   OUT          TRUE  input.0.key-0-not
         5  bit   OUT         FALSE  input.0.key-1
         5  bit   OUT          TRUE  input.0.key-1-not
         5  bit   OUT         FALSE  input.0.key-102nd
         5  bit   OUT          TRUE  input.0.key-102nd-not
         5  bit   OUT         FALSE  input.0.key-2
         5  bit   OUT          TRUE  input.0.key-2-not
         5  bit   OUT         FALSE  input.0.key-3
         5  bit   OUT          TRUE  input.0.key-3-not
         5  bit   OUT         FALSE  input.0.key-4
         5  bit   OUT          TRUE  input.0.key-4-not
         5  bit   OUT         FALSE  input.0.key-5
         5  bit   OUT          TRUE  input.0.key-5-not
         5  bit   OUT         FALSE  input.0.key-6
         5  bit   OUT          TRUE  input.0.key-6-not
         5  bit   OUT         FALSE  input.0.key-7
         5  bit   OUT          TRUE  input.0.key-7-not
         5  bit   OUT         FALSE  input.0.key-8
         5  bit   OUT          TRUE  input.0.key-8-not
         5  bit   OUT         FALSE  input.0.key-9
         5  bit   OUT          TRUE  input.0.key-9-not
         5  bit   OUT         FALSE  input.0.key-a
         5  bit   OUT          TRUE  input.0.key-a-not
         5  bit   OUT         FALSE  input.0.key-apostrophe
         5  bit   OUT          TRUE  input.0.key-apostrophe-not
         5  bit   OUT         FALSE  input.0.key-b
         5  bit   OUT          TRUE  input.0.key-b-not
         5  bit   OUT         FALSE  input.0.key-backslash
         5  bit   OUT          TRUE  input.0.key-backslash-not
         5  bit   OUT         FALSE  input.0.key-backspace
         5  bit   OUT          TRUE  input.0.key-backspace-not
         5  bit   OUT         FALSE  input.0.key-c
         5  bit   OUT          TRUE  input.0.key-c-not
         5  bit   OUT         FALSE  input.0.key-capslock
         5  bit   OUT          TRUE  input.0.key-capslock-not
         5  bit   OUT         FALSE  input.0.key-comma
         5  bit   OUT          TRUE  input.0.key-comma-not
         5  bit   OUT         FALSE  input.0.key-compose
         5  bit   OUT          TRUE  input.0.key-compose-not
         5  bit   OUT         FALSE  input.0.key-d
         5  bit   OUT          TRUE  input.0.key-d-not
         5  bit   OUT         FALSE  input.0.key-delete
         5  bit   OUT          TRUE  input.0.key-delete-not
         5  bit   OUT         FALSE  input.0.key-dot
         5  bit   OUT          TRUE  input.0.key-dot-not
         5  bit   OUT         FALSE  input.0.key-down
         5  bit   OUT          TRUE  input.0.key-down-not
         5  bit   OUT         FALSE  input.0.key-e
         5  bit   OUT          TRUE  input.0.key-e-not
         5  bit   OUT         FALSE  input.0.key-end
         5  bit   OUT          TRUE  input.0.key-end-not
         5  bit   OUT         FALSE  input.0.key-enter
         5  bit   OUT          TRUE  input.0.key-enter-not
         5  bit   OUT         FALSE  input.0.key-equal
         5  bit   OUT          TRUE  input.0.key-equal-not
         5  bit   OUT         FALSE  input.0.key-esc
         5  bit   OUT          TRUE  input.0.key-esc-not
         5  bit   OUT         FALSE  input.0.key-f
         5  bit   OUT          TRUE  input.0.key-f-not
         5  bit   OUT         FALSE  input.0.key-f1
         5  bit   OUT          TRUE  input.0.key-f1-not
         5  bit   OUT         FALSE  input.0.key-f10
         5  bit   OUT          TRUE  input.0.key-f10-not
         5  bit   OUT         FALSE  input.0.key-f11
         5  bit   OUT          TRUE  input.0.key-f11-not
         5  bit   OUT         FALSE  input.0.key-f12
         5  bit   OUT          TRUE  input.0.key-f12-not
         5  bit   OUT         FALSE  input.0.key-f2
         5  bit   OUT          TRUE  input.0.key-f2-not
         5  bit   OUT         FALSE  input.0.key-f3
         5  bit   OUT          TRUE  input.0.key-f3-not
         5  bit   OUT         FALSE  input.0.key-f4
         5  bit   OUT          TRUE  input.0.key-f4-not
         5  bit   OUT         FALSE  input.0.key-f5
         5  bit   OUT          TRUE  input.0.key-f5-not
         5  bit   OUT         FALSE  input.0.key-f6
         5  bit   OUT          TRUE  input.0.key-f6-not
         5  bit   OUT         FALSE  input.0.key-f7
         5  bit   OUT          TRUE  input.0.key-f7-not
         5  bit   OUT         FALSE  input.0.key-f8
         5  bit   OUT          TRUE  input.0.key-f8-not
         5  bit   OUT         FALSE  input.0.key-f9
         5  bit   OUT          TRUE  input.0.key-f9-not
         5  bit   OUT         FALSE  input.0.key-g
         5  bit   OUT          TRUE  input.0.key-g-not
         5  bit   OUT         FALSE  input.0.key-grave
         5  bit   OUT          TRUE  input.0.key-grave-not
         5  bit   OUT         FALSE  input.0.key-h
         5  bit   OUT          TRUE  input.0.key-h-not
         5  bit   OUT         FALSE  input.0.key-home
         5  bit   OUT          TRUE  input.0.key-home-not
         5  bit   OUT         FALSE  input.0.key-i
         5  bit   OUT          TRUE  input.0.key-i-not
         5  bit   OUT         FALSE  input.0.key-insert
         5  bit   OUT          TRUE  input.0.key-insert-not
         5  bit   OUT         FALSE  input.0.key-j
         5  bit   OUT          TRUE  input.0.key-j-not
         5  bit   OUT         FALSE  input.0.key-k
         5  bit   OUT          TRUE  input.0.key-k-not
         5  bit   OUT         FALSE  input.0.key-kp0
         5  bit   OUT          TRUE  input.0.key-kp0-not
         5  bit   OUT         FALSE  input.0.key-kp1
         5  bit   OUT          TRUE  input.0.key-kp1-not
         5  bit   OUT         FALSE  input.0.key-kp2
         5  bit   OUT          TRUE  input.0.key-kp2-not
         5  bit   OUT         FALSE  input.0.key-kp3
         5  bit   OUT          TRUE  input.0.key-kp3-not
         5  bit   OUT         FALSE  input.0.key-kp4
         5  bit   OUT          TRUE  input.0.key-kp4-not
         5  bit   OUT         FALSE  input.0.key-kp5
         5  bit   OUT          TRUE  input.0.key-kp5-not
         5  bit   OUT         FALSE  input.0.key-kp6
         5  bit   OUT          TRUE  input.0.key-kp6-not
         5  bit   OUT         FALSE  input.0.key-kp7
         5  bit   OUT          TRUE  input.0.key-kp7-not
         5  bit   OUT         FALSE  input.0.key-kp8
         5  bit   OUT          TRUE  input.0.key-kp8-not
         5  bit   OUT         FALSE  input.0.key-kp9
         5  bit   OUT          TRUE  input.0.key-kp9-not
         5  bit   OUT         FALSE  input.0.key-kpasterisk
         5  bit   OUT          TRUE  input.0.key-kpasterisk-not
         5  bit   OUT         FALSE  input.0.key-kpdot
         5  bit   OUT          TRUE  input.0.key-kpdot-not
         5  bit   OUT         FALSE  input.0.key-kpenter
         5  bit   OUT          TRUE  input.0.key-kpenter-not
         5  bit   OUT         FALSE  input.0.key-kpminus
         5  bit   OUT          TRUE  input.0.key-kpminus-not
         5  bit   OUT         FALSE  input.0.key-kpplus
         5  bit   OUT          TRUE  input.0.key-kpplus-not
         5  bit   OUT         FALSE  input.0.key-kpslash
         5  bit   OUT          TRUE  input.0.key-kpslash-not
         5  bit   OUT         FALSE  input.0.key-l
         5  bit   OUT          TRUE  input.0.key-l-not
         5  bit   OUT         FALSE  input.0.key-left
         5  bit   OUT          TRUE  input.0.key-left-not
         5  bit   OUT         FALSE  input.0.key-leftalt
         5  bit   OUT          TRUE  input.0.key-leftalt-not
         5  bit   OUT         FALSE  input.0.key-leftbrace
         5  bit   OUT          TRUE  input.0.key-leftbrace-not
         5  bit   OUT         FALSE  input.0.key-leftctrl
         5  bit   OUT          TRUE  input.0.key-leftctrl-not
         5  bit   OUT         FALSE  input.0.key-leftmeta
         5  bit   OUT          TRUE  input.0.key-leftmeta-not
         5  bit   OUT         FALSE  input.0.key-leftshift
         5  bit   OUT          TRUE  input.0.key-leftshift-not
         5  bit   OUT         FALSE  input.0.key-m
         5  bit   OUT          TRUE  input.0.key-m-not
         5  bit   OUT         FALSE  input.0.key-minus
         5  bit   OUT          TRUE  input.0.key-minus-not
         5  bit   OUT         FALSE  input.0.key-n
         5  bit   OUT          TRUE  input.0.key-n-not
         5  bit   OUT         FALSE  input.0.key-numlock
         5  bit   OUT          TRUE  input.0.key-numlock-not
         5  bit   OUT         FALSE  input.0.key-o
         5  bit   OUT          TRUE  input.0.key-o-not
         5  bit   OUT         FALSE  input.0.key-p
         5  bit   OUT          TRUE  input.0.key-p-not
         5  bit   OUT         FALSE  input.0.key-pagedown
         5  bit   OUT          TRUE  input.0.key-pagedown-not
         5  bit   OUT         FALSE  input.0.key-pageup
         5  bit   OUT          TRUE  input.0.key-pageup-not
         5  bit   OUT         FALSE  input.0.key-pause
         5  bit   OUT          TRUE  input.0.key-pause-not
         5  bit   OUT         FALSE  input.0.key-q
         5  bit   OUT          TRUE  input.0.key-q-not
         5  bit   OUT         FALSE  input.0.key-r
         5  bit   OUT          TRUE  input.0.key-r-not
         5  bit   OUT         FALSE  input.0.key-right
         5  bit   OUT          TRUE  input.0.key-right-not
         5  bit   OUT         FALSE  input.0.key-rightalt
         5  bit   OUT          TRUE  input.0.key-rightalt-not
         5  bit   OUT         FALSE  input.0.key-rightbrace
         5  bit   OUT          TRUE  input.0.key-rightbrace-not
         5  bit   OUT         FALSE  input.0.key-rightctrl
         5  bit   OUT          TRUE  input.0.key-rightctrl-not
         5  bit   OUT         FALSE  input.0.key-rightmeta
         5  bit   OUT          TRUE  input.0.key-rightmeta-not
         5  bit   OUT         FALSE  input.0.key-rightshift
         5  bit   OUT          TRUE  input.0.key-rightshift-not
         5  bit   OUT         FALSE  input.0.key-s
         5  bit   OUT          TRUE  input.0.key-s-not
         5  bit   OUT         FALSE  input.0.key-scrolllock
         5  bit   OUT          TRUE  input.0.key-scrolllock-not
         5  bit   OUT         FALSE  input.0.key-semicolon
         5  bit   OUT          TRUE  input.0.key-semicolon-not
         5  bit   OUT         FALSE  input.0.key-slash
         5  bit   OUT          TRUE  input.0.key-slash-not
         5  bit   OUT         FALSE  input.0.key-space
         5  bit   OUT          TRUE  input.0.key-space-not
         5  bit   OUT         FALSE  input.0.key-sysrq
         5  bit   OUT          TRUE  input.0.key-sysrq-not
         5  bit   OUT         FALSE  input.0.key-t
         5  bit   OUT          TRUE  input.0.key-t-not
         5  bit   OUT         FALSE  input.0.key-tab
         5  bit   OUT          TRUE  input.0.key-tab-not
         5  bit   OUT         FALSE  input.0.key-u
         5  bit   OUT          TRUE  input.0.key-u-not
         5  bit   OUT         FALSE  input.0.key-up
         5  bit   OUT          TRUE  input.0.key-up-not
         5  bit   OUT         FALSE  input.0.key-v
         5  bit   OUT          TRUE  input.0.key-v-not
         5  bit   OUT         FALSE  input.0.key-w
         5  bit   OUT          TRUE  input.0.key-w-not
         5  bit   OUT         FALSE  input.0.key-x
         5  bit   OUT          TRUE  input.0.key-x-not
         5  bit   OUT         FALSE  input.0.key-y
         5  bit   OUT          TRUE  input.0.key-y-not
         5  bit   OUT         FALSE  input.0.key-z
         5  bit   OUT          TRUE  input.0.key-z-not
         5  s32   OUT             0  input.0.rel-wheel-counts
         5  float OUT             0  input.0.rel-wheel-position
         5  bit   IN          FALSE  input.0.rel-wheel-reset
         5  float IN              1  input.0.rel-wheel-scale
         5  s32   OUT             0  input.0.rel-x-counts
         5  float OUT             0  input.0.rel-x-position
         5  bit   IN          FALSE  input.0.rel-x-reset
         5  float IN              1  input.0.rel-x-scale
         5  s32   OUT             0  input.0.rel-y-counts
         5  float OUT             0  input.0.rel-y-position
         5  bit   IN          FALSE  input.0.rel-y-reset
         5  float IN              1  input.0.rel-y-scale
    

    That’s a pretty decent assortment of directly usable names and features, even without keyboard LEDs. The mouse pins could be repurposed for general sensor values:

    • counts = integer = accumulated encoder wheel ticks
    • position = float = count / scale (why divided? I don’t know)
    • scale = float = turns counts into position
    • reset = bit = resets position or maybe count (not sure)

    I think you could use count to transfer a bare ADC reading from the Leonardo, then use scale to get the actual voltage in “position”. In that situation, reset wouldn’t be at all useful.

    The keyboard pins could transfer Boolean sensors.

    You’d want to give HAL exclusive control of the Leonardo-is-not-a-mouse, because the incoming data would make hash of the, ah, LinuxCNC UI experience in short order. I’m not sure how to control that; the Leonardo advice boils down to “be careful” and “use a physical switch”.

    I have *no* idea where the names come from, but apparently the OS / kernel / something has a HID layer that translates bare USB capability bits into strings. How that relates to a particular device, what the choices might be, how one could add / replace the names for a given device, and all that, I don’t know yet.

  • Stepper Motor Thermal Coefficient vs. Thermal Compound and Forced Air

    Prompted by that comment, a bit more data emerges.

    This unsteady ziggurat barely supports the aluminum CPU heatsink atop a PC CPU exhaust duct; the two came from different PCs and have no relation to each other.  The vise in the background keeps the whole affair from falling over. The fan sucks air through the heatsink and exhausts it out the front.

    NEMA 17 Stepper - Heatsink with Fan
    NEMA 17 Stepper – Heatsink with Fan

    Throughout all this, the stepper driver runs at a bit over 10 k step/sec, tuned to avoid the howling mechanical resonances in that stack. At 1/8 microstepping, that’s 6.25 rev/s = 375 RPM, which would drive the Thing-O-Matic at 210 mm/s and the M2 at 225 mm/s. Your speed will vary, of course, depending on the pulley diameter / number of teeth / belt pitch, etc.

    Under the same conditions as before (i.e., no thermal compound, fan off), the stepper stabilized at 143 °F = 62 °C in the 57 °F = 14 °C Basement Laboratory ambient, with 1.91 A peak current (I don’t believe that second decimal place, either) and a 6.6 °C/W case-to-ambient coefficient. That’s close enough to the 63 °C and 6.7 °C/W coefficient from the earlier test, so the conditions seem roughly the same.

    Smoothing a thin layer of heatsink compound on the butt of the motor, then squishing it firmly atop the heatsink, cut the temperature to 130 °F = 53 °C without the fan. That suggests the case-to-ambient coefficient is now 5.3 °C/W: the thermal compound helps by 1.3 °C/W.

    Turning on the fan drops the case temperature to 84 °F = 29 °C, which works out to a coefficient of 2.1 °C/W. Obviously, moving air over that heatsink helps the cooling a lot: the heatsink felt cold to the touch and the motor case was barely warm.

    Increasing the current to 2.37 A dissipates 11.2 W, which would be scary without the heatsink and air flow. The temperature stabilized at 91 °F = 33 °C, for a coefficient of 1.7 °C/W.

    At 2.83 A = 16 W, the temperature rises to 100 °F = 38 °C, with a coefficient of 1.5 °C/W. While it’s not unstoppable with that much current, the motor has plenty of torque! The motor becomes pleasantly warm, the heatsink stays just above cool, and all seems right with the world. I suspect the windings get a bit toasty in there, but they can’t possibly be worse off than inside a case at boiling-water temperatures.

    Using the original insulated-motor coefficient of 19 °C/W, 16 W would cook the motor at 320 °C. Perhaps the case would make a nice extruder heater after it stopped being a motor?

    [Update: See the comments for the results of just blowing air over the motor case.]

  • Stepper Motor Thermal Coefficient

    You’ve probably seen this exchange on whatever DIY 3D printing forum you monitor:

    1. My stepper motors get scorching hot, what should I do?
    2. Turn down the current!
    3. That worked great, but …
    4. … now all my objects have a shift in the middle.
    5. Your motor is losing steps: turn up the current!
    6. Uh, right.
    NEMA 17 Stepper on cloth
    NEMA 17 Stepper on cloth

    So, with that setup on the bench, I ran a simple experiment with current, temperature, and heat transfer. Most DIY 3D printers have stepper motors attached to a plywood chassis or plastic holder, so the first data point comes from a motor with no mechanical thermal path to the outside world (which is the Basement Laboratory at 14 °C ambient).

    Running at about 1200 step/s with a winding current of 1 A peak from a 24 A supply, the motor stabilized at 52 °C = 125 °F after half an hour.

    Both windings have a 2 Ω resistance and carry 1 A peak = 0.7 A rms, so the total power dissipation is:

    2 × [(1 A / √2)2 × 2 Ω] = 2 W

    That’s the same power produced with the motor stopped at a full step position, where the peak current flows in a single winding and the other winding carries zero current:

    (1 A)2 × 2 Ω = 2 W

    The temperature rise suggests a thermal coefficient of about 19 °C/W = (52 °C – 14 °C) / 2 W.

    The next current setting on the driver is 1.46 A, which doubles the power dissipation to 4.3 W. Assuming a large number of linearities, that would cook the motor at 82 °C = 180 °F above ambient. Even though the motor could probably withstand that temperature, for what should be obvious reasons I didn’t go there.

    Instead, I parked the motor atop a big CPU heatsink harvested from an obsolete PC, sans thermal compound, mechanical fitting, and anything more secure than gravity holding it in place:

    NEMA 17 Stepper on Heatsink
    NEMA 17 Stepper on Heatsink

    The results:

    Ambient 14 °C
    Winding 2 ohm
    A pk A rms Power W Case °C °C/W amb °C/W incr
    1.00 0.71 2.0 28 7.0 7.0
    1.46 1.03 4.3 42 6.6 6.2
    1.91 1.35 7.3 63 6.7 6.9

    The thermal coefficients represent the combination of all interfaces from motor case to ambient, but the case and heatsink stabilized to about the same temperature, so the main limit (as always) will be heat transfer to ambient air. Obviously, the heatsink sits in the wrong orientation with little-to-no air flow, not to mention that the butt end of a stepper motor isn’t precisely machined and has plenty of air between the two surfaces. Improving all that would be in the nature of fine tuning and should substantially lower the coefficient.

    What’s of interest: just perching the motor on a big chunk of aluminum dropped the case temperature 24 °C without no further effort.

    Blowing air over the case (probably) won’t be nearly as effective. Epoxy-ing a liquid-cooled cold plate to the end cap would improve the situation beyond all reasonable bounds, plus confer extreme geek cred.

    Hmmm, the Warehouse Wing does have some copper tubing…

  • Stepper Driver Waveforms: Current Control

    A bit more data from this setup:

    HB-415M Driver - test setup
    HB-415M Driver – test setup

    As you saw earlier the low-speed waveform looked reasonably good, although the HB-415M driver produces only 71% of its rated current (so it’s actually 1 A peak, not the 1.5 A in the caption):

    HB-415M 8-step 1.5A 20V
    HB-415M 8-step 1.5A 20V

    The driver runs in 1/8 microstep mode, which means 1 revolution = 8 × 200 step = 1600 steps. Each cycle of that stepped sine wave has 32 microsteps  = 4 full steps/cycle × 8 microsteps. One cycle is about 27 ms, so 1 step = 840 µs → 1200 step/s → 0.74 rev/s → 44 rpm. The Thing-O-Matic runs at 47 step/mm → 34 mm/rev, so this speed corresponds to travel at 25 mm/s, roughly the usual printing pace.

    Admittedly, that hairball on the bench isn’t a realistic arrangement, because the motor runs with no load. On the other paw, assuming you’ve done a good job eliminating mechanical binding, then it’s probably pretty close to what you’d see during constant-speed travel.

    Cranking the pulse generator to 6400 step/s = 133 mm/s produces this waveform:

    HB-415M 1A 8step 24V
    HB-415M 1A 8step 24V

    The power supply was 24 V, but there was no visible difference at 20 V. The driver evidently can’t control the winding current on the downward side of the waveform. Adding some frictional torque by grabbing the yellow interrupter wheel improved the situation, but not by much.

    A box of 2M542 drivers just arrived from a nominally reputable supplier, although they were actually labeled M542ES. Under the same conditions, they produce this waveform:

    M542ES 1A 8step 24V
    M542ES 1A 8step 24V

    So there’s something to be said for larger drivers; the HB-415M drivers were operating at their upper limit and the M542ES at their lower limit, both producing close to 1 A peak.

  • HAL Pin Names for a Bone-Stock USB Mouse

    I’ve always wondered what the LinuxCNC HAL pin names would be for an ordinary mouse, particularly nowadays when an Arduino Leonardo can become a USB HID gadget without much effort at all. If one had a Leonardo and l337 programming skillz, one might receive far more interesting data than just fast-twitch muscle movement…

    Logitech Optical Mouse - LinuxCNC box
    Logitech Optical Mouse – LinuxCNC box

    So. We begin…

    From less /proc/bus/input/devices:

    ... snippage ...
    I: Bus=0003 Vendor=046d Product=c077 Version=0111
    N: Name="Logitech USB Optical Mouse"
    P: Phys=usb-0000:00:1d.0-1/input0
    S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/input/input10
    U: Uniq=
    H: Handlers=mouse3 event10
    B: EV=17
    B: KEY=ff0000 0 0 0 0 0 0 0 0
    B: REL=143
    B: MSC=10
    

    From ll /dev/input:

    ... snippage ...
    crw-r-----   1 root root 13, 74 2013-02-23 07:46 event10
    ... snippage ...
    crw-r-----   1 root root 13, 35 2013-02-23 07:46 mouse3
    

    Manually beat the permissions into shape, because this is a one-off affair:

    sudo chgrp users /dev/input/event10
    sudo chgrp users /dev/input/mouse3
    sudo chmod g+w /dev/input/event10
    sudo chmod g+w /dev/input/mouse3
    

    Find the USB address from lsusb:

    Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 004 Device 006: ID 06f2:0011 Emine Technology Co. KVM Switch Keyboard
    Bus 004 Device 005: ID 046d:c401 Logitech, Inc. TrackMan Marble Wheel
    Bus 004 Device 004: ID 04d9:1203 Holtek Semiconductor, Inc. MC Industries Keyboard
    Bus 004 Device 003: ID 046d:c216 Logitech, Inc. Dual Action Gamepad
    Bus 004 Device 002: ID 0451:2046 Texas Instruments, Inc. TUSB2046 Hub
    Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 002 Device 002: ID 046d:c077 Logitech, Inc.
    Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    

    Query the attributes with udevadm:

    udevadm info --query=all --attribute-walk --name=/dev/bus/usb/002/002
    ... snippage ...
      looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1':
        KERNEL=="2-1"
        SUBSYSTEM=="usb"
        DRIVER=="usb"
        ATTR{configuration}==""
        ATTR{bNumInterfaces}==" 1"
        ATTR{bConfigurationValue}=="1"
        ATTR{bmAttributes}=="a0"
        ATTR{bMaxPower}==" 98mA"
        ATTR{urbnum}=="13"
        ATTR{idVendor}=="046d"
        ATTR{idProduct}=="c077"
        ATTR{bcdDevice}=="6700"
        ATTR{bDeviceClass}=="00"
        ATTR{bDeviceSubClass}=="00"
        ATTR{bDeviceProtocol}=="00"
        ATTR{bNumConfigurations}=="1"
        ATTR{bMaxPacketSize0}=="8"
        ATTR{speed}=="1.5"
        ATTR{busnum}=="2"
        ATTR{devnum}=="2"
        ATTR{version}==" 2.00"
        ATTR{maxchild}=="0"
        ATTR{quirks}=="0x0"
        ATTR{authorized}=="1"
        ATTR{manufacturer}=="Logitech"
        ATTR{product}=="USB Optical Mouse"
    

    Fire up halrun, load hal_input, and dump the pins:

    halrun
    halcmd: loadusr -W hal_input -KRAL Optical
    halcmd: show all
    Loaded HAL Components:
    ID      Type  Name                                      PID   State
         5  User  hal_input                                  1693 ready
         3  User  halcmd1692                                 1692 ready
    
    Component Pins:
    Owner   Type  Dir         Value  Name
         5  bit   OUT         FALSE  input.0.btn-back
         5  bit   OUT          TRUE  input.0.btn-back-not
         5  bit   OUT         FALSE  input.0.btn-extra
         5  bit   OUT          TRUE  input.0.btn-extra-not
         5  bit   OUT         FALSE  input.0.btn-forward
         5  bit   OUT          TRUE  input.0.btn-forward-not
         5  bit   OUT         FALSE  input.0.btn-middle
         5  bit   OUT          TRUE  input.0.btn-middle-not
         5  bit   OUT         FALSE  input.0.btn-mouse
         5  bit   OUT          TRUE  input.0.btn-mouse-not
         5  bit   OUT         FALSE  input.0.btn-right
         5  bit   OUT          TRUE  input.0.btn-right-not
         5  bit   OUT         FALSE  input.0.btn-side
         5  bit   OUT          TRUE  input.0.btn-side-not
         5  bit   OUT         FALSE  input.0.btn-task
         5  bit   OUT          TRUE  input.0.btn-task-not
         5  s32   OUT             0  input.0.rel-hwheel-counts
         5  float OUT             0  input.0.rel-hwheel-position
         5  bit   IN          FALSE  input.0.rel-hwheel-reset
         5  float IN              1  input.0.rel-hwheel-scale
         5  s32   OUT             0  input.0.rel-wheel-counts
         5  float OUT             0  input.0.rel-wheel-position
         5  bit   IN          FALSE  input.0.rel-wheel-reset
         5  float IN              1  input.0.rel-wheel-scale
         5  s32   OUT             0  input.0.rel-x-counts
         5  float OUT             0  input.0.rel-x-position
         5  bit   IN          FALSE  input.0.rel-x-reset
         5  float IN              1  input.0.rel-x-scale
         5  s32   OUT             0  input.0.rel-y-counts
         5  float OUT             0  input.0.rel-y-position
         5  bit   IN          FALSE  input.0.rel-y-reset
         5  float IN              1  input.0.rel-y-scale
    ... snippage ...
    

    Hmmm, that was interesting…