Skip to content

Commit

Permalink
Add support for multiple spindles
Browse files Browse the repository at this point in the history
    This commit adds support for up to 8 spindles
    G-code commands that interact with a spindle now take an extra parameter
    E to determine which spindle to work with.
    The exception is G76 which already used E.
    The spindle control pins are changed
    from motion.spindle.thing to spindle.N.thing to match the axis and joint
    naming conventions (which don't mention that they belong to motion)

    A demo config can be found in sim/axis/lathe_multispindle

Signed-off-by: andypugh <andy@bodgesoc.org>
  • Loading branch information
andypugh committed Sep 29, 2018
1 parent 1823903 commit e3caa92
Show file tree
Hide file tree
Showing 57 changed files with 2,056 additions and 1,064 deletions.
1 change: 1 addition & 0 deletions configs/sim/axis/axis_mm.ini
Expand Up @@ -130,6 +130,7 @@ MAX_LINEAR_VELOCITY = 53.34
DEFAULT_LINEAR_ACCEL = 508
MAX_LINEAR_ACCEL = 508
POSITION_FILE = position_mm.txt
SPINDLES = 2

[KINS]
KINEMATICS = trivkins
Expand Down
24 changes: 24 additions & 0 deletions configs/sim/axis/lathe_multispindle/README
@@ -0,0 +1,24 @@
This is a simulation of a 2-spindle lathe to demonstrate the multispindle patch.

up to 8 spindles are supported, set by [TRAJ]SPINDLES in the INI and a
num_spindles modparam to motmod. These _must_ agree with each other.

There are still some things to shake-down regarding default behaviours if no
spindle is selected.

Most spindle-related commands now take an extra "E" word to say which spindle
to apply them to. The exception is G76 which already used E, so now uses D for
spindle.

The docs in this branch have not been updated to reflect new behaviour.

Examples

S1000 E1 - set the speed of spindle 1 to 1000
M3 S100 E0 - set the speed of spindle 0 to 100

G33 X10 K1.5 E1 - make a move synchronised to spindle 1
G33.2 Z-1 K1 E0 - rigid tap synchronised to spindle 0.

M51 P0 E6 - disable speed override on spindle 6. M48 and M49 operate on all.

51 changes: 51 additions & 0 deletions configs/sim/axis/lathe_multispindle/core_sim.hal
@@ -0,0 +1,51 @@
# core HAL config file for simulation

# first load all the RT modules that will be needed
# kinematics
loadrt [KINS]KINEMATICS
# motion controller, get name and thread periods from ini file
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS num_spindles=[TRAJ]SPINDLES
# load 6 differentiators (for velocity and accel signals
loadrt ddt names=ddt_x,ddt_xv,ddt_y,ddt_yv,ddt_z,ddt_zv
# load additional blocks
loadrt hypot names=vel_xy,vel_xyz

# add motion controller functions to servo thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
# link the differentiator functions into the code
addf ddt_x servo-thread
addf ddt_xv servo-thread
addf ddt_y servo-thread
addf ddt_yv servo-thread
addf ddt_z servo-thread
addf ddt_zv servo-thread
addf vel_xy servo-thread
addf vel_xyz servo-thread

# create HAL signals for position commands from motion module
# loop position commands back to motion module feedback
net Xpos joint.0.motor-pos-cmd => joint.0.motor-pos-fb ddt_x.in
net Ypos joint.1.motor-pos-cmd => joint.1.motor-pos-fb ddt_y.in
net Zpos joint.2.motor-pos-cmd => joint.2.motor-pos-fb ddt_z.in

# send the position commands thru differentiators to
# generate velocity and accel signals
net Xvel ddt_x.out => ddt_xv.in vel_xy.in0
net Xacc <= ddt_xv.out
net Yvel ddt_y.out => ddt_yv.in vel_xy.in1
net Yacc <= ddt_yv.out
net Zvel ddt_z.out => ddt_zv.in vel_xyz.in0
net Zacc <= ddt_zv.out

# Cartesian 2- and 3-axis velocities
net XYvel vel_xy.out => vel_xyz.in1
net XYZvel <= vel_xyz.out

# estop loopback
net estop-loop iocontrol.0.user-enable-out iocontrol.0.emc-enable-in

# create signals for tool loading loopback
net tool-prep-loop iocontrol.0.tool-prepare iocontrol.0.tool-prepared
net tool-change-loop iocontrol.0.tool-change iocontrol.0.tool-changed

109 changes: 109 additions & 0 deletions configs/sim/axis/lathe_multispindle/lathe.hal
@@ -0,0 +1,109 @@
# counting the spindle encoder in software
loadrt encoder names=encoder_0,encoder_1
# simulate the encoder
loadrt sim_encoder names=sim_encoder_0,sim_encoder_1
loadrt limit2 names=limit_speed

addf limit_speed servo-thread

#######################################################
# Beginning of threading related stuff
#######################################################

# spindle speed control
net spindle.0.cmd spindle.0.speed-out => sim_encoder_0.speed
net spindle.1.cmd spindle.1.speed-out => sim_encoder_1.speed

# simulate spindle mass
setp limit_speed.maxv 500.0 # rpm/second

# spindle encoder 0
# connect encoder signals to encoder counter
net spindle-phase-A sim_encoder_0.phase-A => encoder_0.phase-A
net spindle-phase-B sim_encoder_0.phase-B => encoder_0.phase-B
net spindle-phase-Z sim_encoder_0.phase-Z => encoder_0.phase-Z

# assume 120 ppr = 480 counts/rev for the spindle
setp sim_encoder_0.ppr 120
# iocontrol output is in rpm, but sim-encoder speed is rps
setp sim_encoder_0.scale 60
# scale encoder output to read in revolutions
# (that way thread pitches can be straightforward,
# a 20 tpi thread would multiply the encoder output
# by 1/20, etc)
setp encoder_0.position-scale 480

# encoder reset control
# hook up motion controller's sync output
net spindle-index-enable spindle.0.index-enable <=> encoder_0.index-enable

# report our revolution count to the motion controller
net spindle.0.pos encoder_0.position => spindle.0.revs

# spindle encoder 1
# connect encoder signals to encoder counter
net spindle-phase-A1 sim_encoder_1.phase-A => encoder_1.phase-A
net spindle-phase-B1 sim_encoder_1.phase-B => encoder_1.phase-B
net spindle-phase-Z1 sim_encoder_1.phase-Z => encoder_1.phase-Z

# assume 120 ppr = 480 counts/rev for the spindle
setp sim_encoder_1.ppr 120
# iocontrol output is in rpm, but sim-encoder speed is rps
setp sim_encoder_1.scale 60
# scale encoder output to read in revolutions
# (that way thread pitches can be straightforward,
# a 20 tpi thread would multiply the encoder output
# by 1/20, etc)
setp encoder_1.position-scale 480

# encoder reset control
# hook up motion controller's sync output
net spindle-index-enable spindle.1.index-enable <=> encoder_0.index-enable

# report our revolution count to the motion controller
net spindle.1.pos encoder_1.position => spindle.1.revs

# for spindle velocity estimate
loadrt lowpass names=lowpass_velocity.0,lowpass_velocity.1
loadrt scale names=scale_to_rpm.0,scale_to_rpm.1
net spindle-rps-raw.0 encoder_0.velocity lowpass_velocity.0.in
net spindle-rps-filtered.0 lowpass_velocity.0.out scale_to_rpm.0.in spindle.0.speed-in
net spindle-rpm-filtered.0 scale_to_rpm.0.out
setp scale_to_rpm.0.gain 60
setp lowpass_velocity.0.gain .07
addf lowpass_velocity.0 servo-thread
addf scale_to_rpm.0 servo-thread

net spindle-rps-raw.1 encoder_1.velocity lowpass_velocity.1.in
net spindle-rps-filtered.1 lowpass_velocity.1.out scale_to_rpm.1.in spindle.1.speed-in
net spindle-rpm-filtered.1 scale_to_rpm.1.out
setp scale_to_rpm.1.gain 60
setp lowpass_velocity.1.gain .07
addf lowpass_velocity.1 servo-thread
addf scale_to_rpm.1 servo-thread

# for at-speed detection
loadrt near names=near_speed.0,near_speed.1
addf near_speed.0 servo-thread
setp near_speed.0.scale 1.1
setp near_speed.0.difference 10
net spindle.0.cmd => near_speed.0.in1
net spindle-rpm-filtered.0 => near_speed.0.in2
net spindle-at-speed.0 near_speed.0.out spindle.0.at-speed
net spindle.0-fwd <= spindle.0.forward

addf near_speed.1 servo-thread
setp near_speed.1.scale 1.1
setp near_speed.1.difference 10
net spindle.1.cmd => near_speed.1.in1
net spindle-rpm-filtered.1 => near_speed.1.in2
net spindle-at-speed.1 near_speed.1.out spindle.1.at-speed

net spindle.1-fwd <= spindle.1.forward

addf encoder.capture-position servo-thread
addf sim-encoder.update-speed servo-thread

addf sim-encoder.make-pulses base-thread
addf encoder.update-counters base-thread

204 changes: 204 additions & 0 deletions configs/sim/axis/lathe_multispindle/lathe.ini
@@ -0,0 +1,204 @@
# EMC controller parameters for a simulated machine.

# General note: Comments can either be preceded with a # or ; - either is
# acceptable, although # is in keeping with most linux config files.

# General section -------------------------------------------------------------
[EMC]
# Version of this INI file
VERSION = 1.0

# Name of machine, for use with display, etc.
MACHINE = LinuxCNC-HAL-SIM-LATHE

# Debug level, 0 means no messages. See src/emc/nml_int/emcglb.h for others
# DEBUG = 0x7FFFFFFF
DEBUG = 0

# Sections for display options ------------------------------------------------
[DISPLAY]

# Name of display program, e.g., xlinuxcnc
DISPLAY = axis
PYVCP = lathe.xml
LATHE = 1
EDITOR = gedit

# Cycle time, in seconds, that display will sleep between polls
CYCLE_TIME = 0.100

# Path to help file
HELP_FILE = doc/help.txt

# Initial display setting for position, RELATIVE or MACHINE
POSITION_OFFSET = RELATIVE

# Initial display setting for position, COMMANDED or ACTUAL
POSITION_FEEDBACK = ACTUAL

# Highest value that will be allowed for feed override, 1.0 = 100%
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
# Prefix to be used
PROGRAM_PREFIX = ../../nc_files
OPEN_FILE = ../../nc_files/examples/lathe_pawn.ngc

# Introductory graphic
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5

USER_COMMAND_FILE = ~/.axisrc
[FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
PROGRAM_EXTENSION = .py Python Script

png = image-to-gcode
gif = image-to-gcode
jpg = image-to-gcode
py = python

# Task controller section -----------------------------------------------------
[RS274NGC]

# File containing interpreter variables
PARAMETER_FILE = sim-lathe.var

# Motion control section ------------------------------------------------------
[EMCMOT]

EMCMOT = motmod

# Timeout for comm to emcmot, in seconds
COMM_TIMEOUT = 1.0

# Interval between tries to emcmot, in seconds
COMM_WAIT = 0.010

# Base task period, in nano-seconds - this is the fastest thread in the machine
BASE_PERIOD = 50000
# Servo task period, in nano-seconds - will be rounded to an integer multiple
# of BASE_PERIOD
SERVO_PERIOD = 1000000

# Hardware Abstraction Layer section --------------------------------------------------
[TASK]

# Name of task controller program, e.g., milltask
TASK = milltask

# Cycle time, in seconds, that task controller will sleep between polls
CYCLE_TIME = 0.001

# Part program interpreter section --------------------------------------------
[HAL]

# The run script first uses halcmd to execute any HALFILE
# files, and then to execute any individual HALCMD commands.
#

# list of hal config files to run through halcmd
# files are executed in the order in which they appear
HALFILE = core_sim.hal
HALFILE = axis_manualtoolchange.hal
HALFILE = simulated_home.hal
HALFILE = lathe.hal

# list of halcmd commands to execute
# commands are executed in the order in which they appear
#HALCMD = save neta

# Single file that is executed after the GUI has started. Only supported by
# AXIS at this time (only AXIS creates a HAL component of its own)
POSTGUI_HALFILE = lathe_postgui.hal

[TRAJ]
SPINDLES = 2
COORDINATES = X Z
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
CYCLE_TIME = 0.010
DEFAULT_VELOCITY = 1.0
MAX_VELOCITY = 3.333334
DEFAULT_ACCELERATION = 20.0
MAX_ACCELERATION = 20.0
NO_FORCE_HOMING = 1
# Axes sections ---------------------------------------------------------------

# First axis
[EMCIO]

# Name of IO controller program, e.g., io
EMCIO = io

# cycle time, in seconds
CYCLE_TIME = 0.100

# tool table file
TOOL_TABLE = lathe.tbl
TOOL_CHANGE_POSITION = 2 0 1
TOOL_CHANGE_WITH_SPINDLE_ON = 1

[KINS]
KINEMATICS = trivkins
JOINTS = 3

[AXIS_X]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 3.333334
MAX_ACCELERATION = 20.0

[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 3.333334
MAX_ACCELERATION = 20.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
FERROR = 0.050
MIN_FERROR = 0.010
HOME_OFFSET = 1.0
HOME_SEARCH_VEL = 5.0
HOME_LATCH_VEL = 1.0
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 0
HOME_IS_SHARED = 1

[AXIS_Z]
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 3.333334
MAX_ACCELERATION = 20.0

[JOINT_1]
# JOINT_1: not used, home immediately:
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
HOME_USE_INDEX = NO
HOME_SEQUENCE = 0

[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 3.333334
MAX_ACCELERATION = 20.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
FERROR = 0.050
MIN_FERROR = 0.010
HOME_OFFSET = 1.0
HOME_SEARCH_VEL = 5.0
HOME_LATCH_VEL = 1.0
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 1
HOME_IS_SHARED = 1

# section for main IO controller parameters -----------------------------------

0 comments on commit e3caa92

Please sign in to comment.