Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

1
configs/sim/axis/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
axis.profile

24
configs/sim/axis/README Normal file
View File

@@ -0,0 +1,24 @@
Axis is a modern, GL-based interface coded in python
The principal Axis gui sim ini files:
axis.ini basic demo (in)
axis_9axis.ini 9 axes
axis_mm.ini basic demo (mm)
canterp.ini demo for a non-gcode interpreter
histogram_demo.ini hal-histogram examples
historical_lathe.ini configured with 3 joints (XYZ with Y unused)
ini_hal_demo.ini ini hal pins demo
lathe.ini lathe demo
ldelta.ini linear delta robot
ldelta_demo.ini linear delta with jog guis
minimal_xyz.ini minimal set of config items
profile_axis.ini profiling
random_tc.ini random tool changer
rdelta.ini rotary delta robot
Select one of these if you have no functional machine but want to edit some basic configuration stuff or play with one of the LinuxCNC displays.
Additional configurations are provided in subdirectories.
These configurations demonstrate LinuxCNC functionality using the axis gui as the interface. (The functionality demonstrated may be available in other guis also)

View File

@@ -0,0 +1,15 @@
pin+anglejog.enable-in
pin+anglejog.enable-out
pin+anglejog.active
pin+anglejog.scale-in
pin+anglejog.current-scale
pin+anglejog.current-scale-out
pin+anglejog.angle-degrees-in
pin+anglejog.current-angle-degrees
pin+anglejog.counts-in
pin+anglejog.coscounts
pin+anglejog.sincounts
pin+anglejog.cos-accel-fraction
pin+anglejog.sin-accel-fraction
pin+anglejog.current-mag
pin+anglejog.current-vel

View File

@@ -0,0 +1,80 @@
[EMC]
VERSION = 1.1
MACHINE = LATHE-Anglejog
[DISPLAY]
OPEN_FILE = ''
DISPLAY = axis
PYVCP = anglejog.xml
LATHE = 1
CYCLE_TIME = 0.100
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
PROGRAM_PREFIX = .
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
[RS274NGC]
PARAMETER_FILE = anglejog.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
BASE_PERIOD = 100000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl -no_sim_spindle -no_use_hal_manualtoolchange
# all provisions for anglejog:
POSTGUI_HALFILE = anglejog_postgui.hal
[TRAJ]
NO_FORCE_HOMING = 1
COORDINATES = X Z
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
DEFAULT_LINEAR_ACCELERATION = 10.0
MAX_LINEAR_VELOCITY = 10.0
MAX_LINEAR_ACCELERATION = 100.0
[EMCIO]
TOOL_TABLE = anglejog.tbl
[KINS]
KINEMATICS = trivkins coordinates=xz
JOINTS = 2
# Note: immediate joint homing
[JOINT_0]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.0
MAX_ACCELERATION = 10.0
HOME_SEQUENCE = 0
[JOINT_1]
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 1.0
MAX_ACCELERATION = 10.0
HOME_SEQUENCE = 0
[AXIS_X]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.0
MAX_ACCELERATION = 10.0
[AXIS_Z]
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 1.0
MAX_ACCELERATION = 10.0

View File

@@ -0,0 +1,14 @@
anglejog -- demonstrate jogging at an
angle for a lathe (xz) configuration.
Usage:
1) F1 (Estop Off)
2) F2 (Machine On)
3) Ctrl-HOME (Home All)
4) pyvcp panel: Set to Enable
5) pyvcp panel: change MPG counts
and note jogging at current angle
6) pyvcp panel: Set to Disable
7) pyvcp panel: alter Angle or Scale
8) repeat from 4)

View File

@@ -0,0 +1,203 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<label>
<text>"ANGLE JOG"</text>
<anchor>"w"</anchor>
</label>
<label>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
<text>"NOTE:\nDisable required to change\nScale or Angle"</text>
</label>
<hbox>
<checkbutton>
<halpin>"enable"</halpin>
<text>""</text>
<initval>0</initval>
</checkbutton>
<label>
<anchor>"w"</anchor>
<text>"Enable/Disable"</text>
</label>
</hbox>
<hbox>
<led>
<halpin>"enabled"</halpin>
<on_color>"light green"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Enabled"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<led>
<halpin>"active"</halpin>
<on_color>"blue"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" active"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"max-vel"</halpin>
<width>10</width>
<initval>1.0</initval>
<resolution>.1</resolution>
<format>"10.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Max vel"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"max-accel"</halpin>
<width>10</width>
<initval>10.0</initval>
<resolution>.1</resolution>
<format>"10.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Max accel"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"accel-fraction"</halpin>
<width>10</width>
<initval>1.0</initval>
<resolution>.1</resolution>
<format>"10.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Accel fraction"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"scale-in"</halpin>
<width>10</width>
<initval>0.001</initval>
<resolution>0.001</resolution>
<format>"10.4f"</format>
<font>"bold"</font>
<max_>0.1</max_>
<min_>0.0001</min_>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Scale"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<number>
<halpin>"current-scale"</halpin>
<format>"10.8f"</format>
<width>"13"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"current-scale"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"current-scale-out"</halpin>
<format>"10.8f"</format>
<width>"13"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"current-scale-out"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"angle-degrees"</halpin>
<min_>-90.0</min_>
<max_>90.0</max_>
<width>10</width>
<initval>30</initval>
<resolution>5</resolution>
<format>"10.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Angle"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<number>
<halpin>"current-angle-degrees"</halpin>
<format>"10.3f"</format>
<width>"13"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"Current angle"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<scale>
<width>"25"</width>
<halpin>"mpg"</halpin>
<param_pin>1</param_pin>
<resolution>1</resolution>
<orient>HORIZONTAL</orient>
<initval>0</initval>
<min_>-500</min_>
<max_> 500</max_>
</scale>
<label>
<text>"MPG counts"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<vbox>
<button>
<halpin>"mpgreset"</halpin>
<text>"MPG Reset"</text>
<bd>4</bd>
<justify>"center"</justify>
</button>
</vbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1,90 @@
loadrt anglejog names=anglejog
addf anglejog servo-thread
#--------------------------------------------------------------
# Connections TO anglejog component
net :ajog_enable <= pyvcp.enable
net :ajog_enable => anglejog.enable-in
net :ajog_enable => pyvcp.enabled
net :ajog_counts <= pyvcp.mpg-i
net :ajog_counts => anglejog.counts-in
net :ajog_accel-fraction-in <= pyvcp.accel-fraction
net :ajog_accel-fraction-in => anglejog.accel-fraction-in
net :ajog-angle-degrees <= pyvcp.angle-degrees
net :ajog-angle-degrees => anglejog.angle-degrees-in
net :ajog-scale-in <= pyvcp.scale-in
net :ajog-scale-in => anglejog.scale-in
net :ajog_max-vel <= pyvcp.max-vel
net :ajog_max-vel => anglejog.max-vel
net :ajog_max-accel <= pyvcp.max-accel
net :ajog_max-accel => anglejog.max-accel
#--------------------------------------------------------------
# Connections FROM anglejog component
net :ajog_enable-out <= anglejog.enable-out
net :ajog_enable-out => axis.x.jog-enable
net :ajog_enable-out => axis.z.jog-enable
net :ajog_enable-out => joint.0.jog-enable
net :ajog_enable-out => joint.1.jog-enable
net :ajog_scale-out <= anglejog.current-scale-out
net :ajog_scale-out => axis.x.jog-scale
net :ajog_scale-out => axis.z.jog-scale
net :ajog_scale-out => joint.0.jog-scale
net :ajog_scale-out => joint.1.jog-scale
net :ajog_scale-out => pyvcp.current-scale-out
net :ajog_x <= anglejog.coscounts
net :ajog_x => axis.x.jog-counts
net :ajog_x => joint.0.jog-counts
net :ajog_z <= anglejog.sincounts
net :ajog_z => axis.z.jog-counts
net :ajog_z => joint.1.jog-counts
net :ajog_xfraction <= anglejog.cos-accel-fraction
net :ajog_xfraction => axis.x.jog-accel-fraction
net :ajog_xfraction => joint.0.jog-accel-fraction
net :ajog_zfraction <= anglejog.sin-accel-fraction
net :ajog_zfraction => axis.z.jog-accel-fraction
net :ajog_zfraction => joint.1.jog-accel-fraction
#--------------------------------------------------------------
# panel info-only items from anglejog component:
net :vcp_active <= anglejog.active
net :vcp_active => pyvcp.active
net :vcp-current-scale <= anglejog.current-scale
net :vcp-current-scale => pyvcp.current-scale
net :vcp_current-angle-degrees <= anglejog.current-angle-degrees
net :vcp_current-angle-degrees => pyvcp.current-angle-degrees
#--------------------------------------------------------------
# MPG simulation items
loadrt mux_generic config=ff2
addf mux-gen.00 servo-thread
# for reset, set >0 and < Scale widget resolution:
setp mux-gen.00.in-float-00 .1
net :vcp_scale-val <= mux-gen.00.out-float
net :vcp_scale-val => pyvcp.scale.0.param_pin
net :vcp_scale-reset <= pyvcp.mpgreset
net :vcp_scale-reset => mux-gen.00.sel-bit-00
#--------------------------------------------------------------
# halshow
loadusr halshow --noprefs --fformat %8.5f ./anglejog.halshow

223
configs/sim/axis/axis.ini Normal file
View File

@@ -0,0 +1,223 @@
# 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.1
# Name of machine, for use with display, etc.
MACHINE = LinuxCNC-HAL-SIM-AXIS
# 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., axis
DISPLAY = axis
# 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
MAX_LINEAR_VELOCITY = 5
DEFAULT_LINEAR_VELOCITY = .25
DEFAULT_SPINDLE_SPEED = 200
# Prefix to be used
PROGRAM_PREFIX = ../../nc_files/
# Introductory graphic
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
#EDITOR = geany
TOOL_EDITOR = tooledit
#Prevent tool mark disappearing with small tool diameter in g-code preview widget
GCODE_VIEW_TOOL_MIN_DIA = 0.08
INCREMENTS = 1 in, 0.1 in, 10 mil, 1 mil, 1mm, .1mm, 1/8000 in
[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 = python3
# Task controller 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 --------------------------------------------
[RS274NGC]
# File containing interpreter variables
PARAMETER_FILE = sim.var
# Motion control section ------------------------------------------------------
[EMCMOT]
EMCMOT = motmod
# Timeout for comm to emcmot, in seconds
COMM_TIMEOUT = 1.0
# BASE_PERIOD is unused in this configuration but specified in core_sim.hal
BASE_PERIOD = 0
# Servo task period, in nano-seconds
SERVO_PERIOD = 1000000
# section for main IO controller parameters -----------------------------------
[EMCIO]
# tool table file
TOOL_TABLE = sim.tbl
TOOL_CHANGE_POSITION = 0 0 0
TOOL_CHANGE_QUILL_UP = 1
# Hardware Abstraction Layer 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 = sim_spindle_encoder.hal
HALFILE = axis_manualtoolchange.hal
HALFILE = simulated_home.hal
HALFILE = check_xyz_constraints.hal
HALFILE = cooling.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 = test_postgui.hal
HALUI = halui
# Trajectory planner section --------------------------------------------------
[TRAJ]
COORDINATES = X Y Z
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
MAX_LINEAR_VELOCITY = 5
DEFAULT_LINEAR_ACCELERATION = 100
MAX_LINEAR_ACCELERATION = 100
POSITION_FILE = position.txt
[KINS]
KINEMATICS = trivkins
JOINTS = 3
# Axes sections ---------------
[AXIS_X]
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
[AXIS_Y]
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
[AXIS_Z]
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -8.0
MAX_LIMIT = 0.12
# Joints sections -------------
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 5
MAX_ACCELERATION = 50.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
FERROR = 0.050
MIN_FERROR = 0.010
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 1
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 5
MAX_ACCELERATION = 50.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
FERROR = 0.050
MIN_FERROR = 0.010
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 1
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 5
MAX_ACCELERATION = 50.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -8.0
# Normally the Z max should be 0.000!
# The only reason it's greater than 0 here is so that the splash screen
# gcode will run.
MAX_LIMIT = 0.12
FERROR = 0.050
MIN_FERROR = 0.010
HOME_OFFSET = 1.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,198 @@
[EMC]
VERSION = 1.1
MACHINE = LinuxCNC-sim-9axis
DEBUG = 0
[DISPLAY]
DISPLAY = axis
CYCLE_TIME = 0.100
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
PROGRAM_PREFIX = ../../nc_files/
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
#EDITOR = geany
INCREMENTS = 1 mm, .01 in, .1mm, 1 mil, .1 mil, 1/8000 in
GEOMETRY = XYZABCUVW
[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 = python3
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim-9axis.var
[EMCMOT]
# joint4 is locked rotary
# create hal pins: joint4.unlock, joint.4.is-locked
# JOINTS_AXES specify joint4 with mask:
EMCMOT = motmod unlock_joints_mask=0x10
COMM_TIMEOUT = 1.0
SERVO_PERIOD = 1000000
[EMCIO]
TOOL_TABLE = sim.tbl
TOOL_CHANGE_POSITION = 0 0 2
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl
HALFILE = locking_indexer.hal
[TRAJ]
COORDINATES = X Y Z A B C U V W
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
DEFAULT_LINEAR_ACCELERATION = 20.0
DEFAULT_ANGULAR_VELOCITY = 45.0
MAX_LINEAR_VELOCITY = 1.2
MAX_LINEAR_ACCELERATION = 20.0
MAX_ANGULAR_VELOCITY = 90.0
POSITION_FILE = position9.txt
[KINS]
KINEMATICS = trivkins
JOINTS = 9
[AXIS_X]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
[AXIS_Y]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
[AXIS_Z]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
[AXIS_A]
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
[AXIS_B]
# JOINTS_AXES specify the joint number
# JOINTS_AXES also mask: motmod unlock_joints_mask=0x10
LOCKING_INDEXER_JOINT = 4
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
[AXIS_C]
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
[AXIS_U]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
[AXIS_V]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
[AXIS_W]
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
[JOINT_0]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 5.0
HOME_LATCH_VEL = 1.0
HOME_SEQUENCE = 1
HOME_USE_INDEX = 1
[JOINT_1]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 5.0
HOME_LATCH_VEL = 1.0
HOME_SEQUENCE = 1
HOME_USE_INDEX = 1
[JOINT_2]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
HOME_SEARCH_VEL = 5.0
HOME_LATCH_VEL = 1.0
HOME_SEQUENCE = 0
HOME_USE_INDEX = 1
[JOINT_3]
TYPE = ANGULAR
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 1
[JOINT_4]
TYPE = ANGULAR
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 1
# joints_axes: for homing
LOCKING_INDEXER = 1
[JOINT_5]
TYPE = ANGULAR
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 1
[JOINT_6]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 0
[JOINT_7]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 0
[JOINT_8]
TYPE = LINEAR
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
HOME_SEARCH_VEL = 0.0
HOME_LATCH_VEL = 0.0
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,27 @@
loadrt trivkins coordinates=XYZABCUVW
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=9 num_dio=10 num_aio=10 num_spindles=1
addf motion-command-handler servo-thread
addf motion-controller servo-thread
net x-pos-fb joint.0.motor-pos-fb <= joint.0.motor-pos-cmd
net y-pos-fb joint.1.motor-pos-fb <= joint.1.motor-pos-cmd
net z-pos-fb joint.2.motor-pos-fb <= joint.2.motor-pos-cmd
net a-pos-fb joint.3.motor-pos-fb <= joint.3.motor-pos-cmd
net b-pos-fb joint.4.motor-pos-fb <= joint.4.motor-pos-cmd
net c-pos-fb joint.5.motor-pos-fb <= joint.5.motor-pos-cmd
net u-pos-fb joint.6.motor-pos-fb <= joint.6.motor-pos-cmd
net v-pos-fb joint.7.motor-pos-fb <= joint.7.motor-pos-cmd
net w-pos-fb joint.8.motor-pos-fb <= joint.8.motor-pos-cmd
setp iocontrol.0.emc-enable-in 1

View File

@@ -0,0 +1,402 @@
# ========================================================
# S-CURVE MOTION PLANNING CONFIGURATION EXAMPLE
# ========================================================
#
# This file demonstrates how to configure S-curve (jerk-limited)
# motion planning in LinuxCNC. S-curve planning produces smoother
# acceleration profiles that can reduce machine vibration and
# improve surface finish.
#
# IMPORTANT: S-curve planning is OPTIONAL.
# Traditional trapezoidal acceleration is used when:
# - PLANNER_TYPE = 0, OR
# - MAX_LINEAR_JERK = 0
#
# NOTE: If MAX_LINEAR_JERK is not specified, it defaults to 1e9 (1 billion),
# which effectively disables jerk limiting while still using S-curve calculations.
# This produces motion similar to trapezoidal but not identical.
#
# ========================================================
[EMC]
VERSION = 1.1
MACHINE = scurve_9axis_example
DEBUG = 0
[DISPLAY]
JOG_AXES = XYZABCUVW
GEOMETRY = XYZABCUVW
DISPLAY = axis
CYCLE_TIME = 0.200
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 2.0
PROGRAM_PREFIX = M-Codes
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
EDITOR = gedit
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
COMM_WAIT = 0.010
BASE_PERIOD = 150000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[HAL]
HALUI = halui
HALFILE = axis_9axis_scurve.hal
[TRAJ]
# --------------------------------------------------------
# S-curve Planner Configuration
# --------------------------------------------------------
# PLANNER_TYPE: Select the acceleration profile shape
# 0 = Trapezoidal (traditional - constant acceleration)
# 1 = S-curve (smoother - limited jerk/derivative of acceleration)
# Default: 0 (trapezoidal)
#
# NOTE: This parameter can be changed at RUNTIME via HAL pin:
# ini.traj_planner_type (allows switching on-the-fly)
PLANNER_TYPE = 1
# MAX_LINEAR_JERK: Maximum rate of change of acceleration
# Units: machine-units/second^3 (e.g., mm/s^3 or inch/s^3)
#
# Setting this to 0 disables S-curve planning regardless of PLANNER_TYPE
# If not specified, defaults to 1e9 (effectively no jerk limiting)
# Maximum allowed value is 1e9 (values above are automatically clamped)
#
# Recommended starting values (adjust based on your machine):
# - Light/rigid machines: 1000-10000
# - Heavy/flexible machines: 100-1000
# - Very rigid machines: 10000-100000
#
# Higher values = sharper acceleration changes (closer to trapezoidal)
# Lower values = smoother acceleration changes (more gradual)
#
# NOTE: This parameter can be changed at RUNTIME via HAL pin:
# ini.traj_max_jerk (allows tuning on-the-fly)
MAX_LINEAR_JERK = 10000.0
# --------------------------------------------------------
# Standard TRAJ parameters (still required with S-curve)
# --------------------------------------------------------
COORDINATES = X Y Z A B C U V W
LINEAR_UNITS = mm
ANGULAR_UNITS = deg
CYCLE_TIME = 0.010
DEFAULT_LINEAR_VELOCITY = 100.0
MAX_LINEAR_VELOCITY = 300.0
DEFAULT_LINEAR_ACCELERATION = 500.0
MAX_LINEAR_ACCELERATION = 1000.0
# to be able to run gcodes and MDI without homing
NO_FORCE_HOMING = 1
ARC_BLEND_ENABLE = 1
ARC_BLEND_FALLBACK_ENABLE = 0
ARC_BLEND_OPTIMIZATION_DEPTH = 50
ARC_BLEND_RAMP_FREQ = 20
ARC_BLEND_GAP_CYCLES = 4
[EMCIO]
EMCIO = io
CYCLE_TIME = 0.100
[KINS]
# 9-axis configuration
KINEMATICS = trivkins
JOINTS = 9
[RS274NGC]
# File containing interpreter variables
PARAMETER_FILE = scurve_example.var
# ========================================================
# JOINT CONFIGURATION
# ========================================================
# Each joint can have its own jerk limit. If not specified,
# the joint uses the axis/trajectory jerk limits.
[JOINT_0]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
HOME_SEQUENCE = 0
# MAX_JERK: Maximum jerk for this joint
# Units: machine-units/second^3
# Default: 0.0 (disabled, uses trapezoidal)
#
# This should match or be higher than the trajectory jerk
# to avoid limiting coordinated motion.
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
# ========================================================
# HOMING CONFIGURATION FOR S-CURVE
# ========================================================
# WARNING: When using S-curve motion (PLANNER_TYPE=1), you MUST set
# HOME_SEARCH_VEL and HOME_LATCH_VEL significantly SLOWER than you
# would with trapezoidal motion planning.
#
# S-curve motion requires MORE DISTANCE to decelerate due to the
# jerk-limited acceleration profile. If homing velocities are too
# high, the axis may overshoot and hit hard limits or sensor limits.
#
# RECOMMENDED: Start with 50% or less of the velocities you would
# use with trapezoidal planning, then increase cautiously.
#
# Example homing configuration (adjust for your machine):
#HOME_SEARCH_VEL = 5.0 # Velocity for initial limit switch search
#HOME_LATCH_VEL = 1.0 # Velocity for precise homing (slower)
#HOME_OFFSET = 0.0 # Distance from switch to home position
#HOME_USE_INDEX = NO # Use encoder index pulse for homing
#HOME_IGNORE_LIMITS = NO # Ignore limit switches during homing move
# ========================================================
[JOINT_1]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
# See JOINT_0 for detailed homing configuration examples.
#HOME_SEARCH_VEL = 5.0
#HOME_LATCH_VEL = 1.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
#MIN_LIMIT = -100.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 100.0 #disabled to give more space for testing g-codes
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
# See JOINT_0 for detailed homing configuration examples.
#HOME_SEARCH_VEL = 4.0
#HOME_LATCH_VEL = 0.8
[JOINT_3]
TYPE = ANGULAR
HOME = 0.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 3.0
#HOME_LATCH_VEL = 0.6
[JOINT_4]
TYPE = ANGULAR
HOME = 0.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 3.0
#HOME_LATCH_VEL = 0.6
[JOINT_5]
TYPE = ANGULAR
HOME = 0.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 3.0
#HOME_LATCH_VEL = 0.6
[JOINT_6]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0
#MAX_LIMIT = 200.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 5.0
#HOME_LATCH_VEL = 1.0
[JOINT_7]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0
#MAX_LIMIT = 200.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 5.0
#HOME_LATCH_VEL = 1.0
[JOINT_8]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
#MIN_LIMIT = -100.0
#MAX_LIMIT = 100.0
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
#HOME_SEARCH_VEL = 4.0
#HOME_LATCH_VEL = 0.8
# ========================================================
# AXIS CONFIGURATION
# ========================================================
[AXIS_X]
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
# MAX_JERK: Maximum jerk for coordinated motion on this axis
# Units: machine-units/second^3
# Default: 0.0 (disabled)
MAX_JERK = 10000.0
[AXIS_Y]
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
[AXIS_Z]
#MIN_LIMIT = -100.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 100.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
[AXIS_A]
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
[AXIS_B]
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
[AXIS_C]
#MIN_LIMIT = -360.0
#MAX_LIMIT = 360.0
MAX_VELOCITY = 180.0
MAX_ACCELERATION = 600.0
MAX_JERK = 10000.0
[AXIS_U]
#MIN_LIMIT = -200.0
#MAX_LIMIT = 200.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
[AXIS_V]
#MIN_LIMIT = -200.0
#MAX_LIMIT = 200.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
[AXIS_W]
#MIN_LIMIT = -100.0
#MAX_LIMIT = 100.0
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
# ========================================================
# TUNING GUIDELINES
# ========================================================
#
# 1. START WITH TRAPEZOIDAL (PLANNER_TYPE=0)
# - Verify your machine works correctly with traditional planning
# - Note any vibration or resonance issues
#
# 2. ENABLE S-CURVE WITH CONSERVATIVE VALUES
# - Set PLANNER_TYPE = 1
# - Start with low MAX_LINEAR_JERK (e.g., 100-500)
# - Jerk should typically be 10-100x your acceleration value
#
# 3. GRADUALLY INCREASE JERK
# - Increase MAX_LINEAR_JERK in steps of 2-3x
# - Test with simple moves and observe:
# * Motor current/torque
# * Vibration levels
# * Following errors
# * Surface finish quality
#
# 4. FIND OPTIMAL VALUE
# - Too low: Motion becomes sluggish, cycle time increases
# - Too high: Approaches trapezoidal behavior, loses smoothness
# - Optimal: Smooth motion without excessive deceleration
#
# 5. VERIFY COORDINATED MOTION
# - Test circular interpolation (G2/G3)
# - Check complex 3D toolpaths
# - Verify axis jerk limits don't constrain trajectory jerk
#
# ========================================================
# TROUBLESHOOTING
# ========================================================
#
# SYMPTOM: No difference between PLANNER_TYPE=0 and PLANNER_TYPE=1
# SOLUTION: Verify MAX_LINEAR_JERK > 0 and MAX_JERK > 0 for all joints/axes
#
# SYMPTOM: Motion is too slow with S-curve enabled
# SOLUTION: Increase MAX_LINEAR_JERK value
#
# SYMPTOM: Following errors increase with S-curve
# SOLUTION: Decrease MAX_LINEAR_JERK or increase PID I-gain
#
# SYMPTOM: Vibration/resonance at certain speeds
# SOLUTION: Adjust MAX_LINEAR_JERK to avoid resonant frequencies
# Consider using different jerk values for different axes
#
# ========================================================

View File

@@ -0,0 +1,210 @@
# 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.1
# Name of machine, for use with display, etc.
MACHINE = LinuxCNC-HAL-SIM-AXIS
# 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., axis
DISPLAY = axis
# 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/
# Introductory graphic
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
#EDITOR = geany
#Prevent tool mark disappearing with small tool diameter in g-code preview widget
GCODE_VIEW_TOOL_MIN_DIA = 2.0
INCREMENTS = 1 mm, .01 in, .1mm, 1 mil, .1 mil, 1/8000 in
[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 = python3
# Task controller 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 --------------------------------------------
[RS274NGC]
# File containing interpreter variables
PARAMETER_FILE = sim_mm.var
# Motion control section ------------------------------------------------------
[EMCMOT]
EMCMOT = motmod
# Timeout for comm to emcmot, in seconds
COMM_TIMEOUT = 1.0
# BASE_PERIOD is unused in this configuration but specified in core_sim.hal
BASE_PERIOD = 0
# Servo task period, in nano-seconds
SERVO_PERIOD = 1000000
# section for main IO controller parameters -----------------------------------
[EMCIO]
# tool table file
TOOL_TABLE = sim_mm.tbl
TOOL_CHANGE_POSITION = 0 0 50.8
# Hardware Abstraction Layer 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 = sim_spindle_encoder.hal
HALFILE = axis_manualtoolchange.hal
HALFILE = simulated_home.hal
HALFILE = cooling.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 = test_postgui.hal
HALUI = halui
# Trajectory planner section --------------------------------------------------
[TRAJ]
COORDINATES = X Y Z
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 30.48
MAX_LINEAR_VELOCITY = 53.34
DEFAULT_LINEAR_ACCELERATION = 508
MAX_LINEAR_ACCELERATION = 508
POSITION_FILE = position_mm.txt
[KINS]
KINEMATICS = trivkins
JOINTS = 3
# Axes sections ---------------
[AXIS_X]
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
MIN_LIMIT = -254
MAX_LIMIT = 254
[AXIS_Y]
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
MIN_LIMIT = -254
MAX_LIMIT = 254
[AXIS_Z]
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
MIN_LIMIT = -50.8
MAX_LIMIT = 101.6
# Joints sections -------------
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
BACKLASH = 0.000
INPUT_SCALE = 157.48
OUTPUT_SCALE = 1.000
MIN_LIMIT = -254
MAX_LIMIT = 254
FERROR = 1.27
MIN_FERROR = .254
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 127
HOME_LATCH_VEL = 25.4
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 1
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
BACKLASH = 0.000
INPUT_SCALE = 157.48
OUTPUT_SCALE = 1.000
MIN_LIMIT = -254
MAX_LIMIT = 254
FERROR = 1.27
MIN_FERROR = .254
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 127
HOME_LATCH_VEL = 25.4
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 1
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 30.48
MAX_ACCELERATION = 508
BACKLASH = 0.000
INPUT_SCALE = 157.48
OUTPUT_SCALE = 1.000
MIN_LIMIT = -50.8
MAX_LIMIT = 101.6
FERROR = 1.27
MIN_FERROR = .254
HOME_OFFSET = 25.4
HOME_SEARCH_VEL = 127
HOME_LATCH_VEL = 25.4
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = NO
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,17 @@
loadrt trivkins coordinates=XYZ
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=3 num_dio=10 num_aio=10 num_spindles=1
addf motion-command-handler servo-thread
addf motion-controller servo-thread
net x-pos-fb joint.0.motor-pos-fb <= joint.0.motor-pos-cmd
net y1-pos-fb joint.1.motor-pos-fb <= joint.1.motor-pos-cmd
net z-pos-fb joint.2.motor-pos-fb <= joint.2.motor-pos-cmd
setp iocontrol.0.emc-enable-in 1

View File

@@ -0,0 +1,276 @@
# ========================================================
# S-CURVE MOTION PLANNING CONFIGURATION EXAMPLE
# ========================================================
#
# This file demonstrates how to configure S-curve (jerk-limited)
# motion planning in LinuxCNC. S-curve planning produces smoother
# acceleration profiles that can reduce machine vibration and
# improve surface finish.
#
# IMPORTANT: S-curve planning is OPTIONAL.
# Traditional trapezoidal acceleration is used when:
# - PLANNER_TYPE = 0, OR
# - MAX_LINEAR_JERK = 0
#
# NOTE: If MAX_LINEAR_JERK is not specified, it defaults to 1e9 (1 billion),
# which effectively disables jerk limiting while still using S-curve calculations.
# This produces motion similar to trapezoidal but not identical.
#
# ========================================================
[EMC]
VERSION = 1.1
MACHINE = scurve_example
DEBUG = 0
[DISPLAY]
JOG_AXES = XYZ
GEOMETRY = XYZ
DISPLAY = axis
CYCLE_TIME = 0.200
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 2.0
PROGRAM_PREFIX = M-Codes
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
EDITOR = gedit
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
COMM_WAIT = 0.010
BASE_PERIOD = 150000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[HAL]
HALUI = halui
HALFILE = axis_mm_scurve.hal
[TRAJ]
# --------------------------------------------------------
# S-curve Planner Configuration
# --------------------------------------------------------
# PLANNER_TYPE: Select the acceleration profile shape
# 0 = Trapezoidal (traditional - constant acceleration)
# 1 = S-curve (smoother - limited jerk/derivative of acceleration)
# Default: 0 (trapezoidal)
#
# NOTE: This parameter can be changed at RUNTIME via HAL pin:
# ini.traj_planner_type (allows switching on-the-fly)
PLANNER_TYPE = 1
# MAX_LINEAR_JERK: Maximum rate of change of acceleration
# Units: machine-units/second^3 (e.g., mm/s^3 or inch/s^3)
#
# Setting this to 0 disables S-curve planning regardless of PLANNER_TYPE
# If not specified, defaults to 1e9 (effectively no jerk limiting)
# Maximum allowed value is 1e9 (values above are automatically clamped)
#
# Recommended starting values (adjust based on your machine):
# - Light/rigid machines: 1000-10000
# - Heavy/flexible machines: 100-1000
# - Very rigid machines: 10000-100000
#
# Higher values = sharper acceleration changes (closer to trapezoidal)
# Lower values = smoother acceleration changes (more gradual)
#
# NOTE: This parameter can be changed at RUNTIME via HAL pin:
# ini.traj_max_jerk (allows tuning on-the-fly)
MAX_LINEAR_JERK = 10000.0
# --------------------------------------------------------
# Standard TRAJ parameters (still required with S-curve)
# --------------------------------------------------------
COORDINATES = X Y Z
LINEAR_UNITS = mm
ANGULAR_UNITS = deg
CYCLE_TIME = 0.010
DEFAULT_LINEAR_VELOCITY = 100.0
MAX_LINEAR_VELOCITY = 300.0
DEFAULT_LINEAR_ACCELERATION = 500.0
MAX_LINEAR_ACCELERATION = 1000.0
# to be able to run gcodes and MDI without homing
NO_FORCE_HOMING = 1
ARC_BLEND_ENABLE = 1
ARC_BLEND_FALLBACK_ENABLE = 0
ARC_BLEND_OPTIMIZATION_DEPTH = 50
ARC_BLEND_RAMP_FREQ = 20
ARC_BLEND_GAP_CYCLES = 4
[EMCIO]
EMCIO = io
CYCLE_TIME = 0.100
[KINS]
# 5axiskins misnomer 1 more joint for W
KINEMATICS = trivkins
JOINTS = 3
[RS274NGC]
# File containing interpreter variables
PARAMETER_FILE = scurve_example.var
# ========================================================
# JOINT CONFIGURATION
# ========================================================
# Each joint can have its own jerk limit. If not specified,
# the joint uses the axis/trajectory jerk limits.
[JOINT_0]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
HOME_SEQUENCE = 0
# MAX_JERK: Maximum jerk for this joint
# Units: machine-units/second^3
# Default: 0.0 (disabled, uses trapezoidal)
#
# This should match or be higher than the trajectory jerk
# to avoid limiting coordinated motion.
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
# ========================================================
# HOMING CONFIGURATION FOR S-CURVE
# ========================================================
# WARNING: When using S-curve motion (PLANNER_TYPE=1), you MUST set
# HOME_SEARCH_VEL and HOME_LATCH_VEL significantly SLOWER than you
# would with trapezoidal motion planning.
#
# S-curve motion requires MORE DISTANCE to decelerate due to the
# jerk-limited acceleration profile. If homing velocities are too
# high, the axis may overshoot and hit hard limits or sensor limits.
#
# RECOMMENDED: Start with 50% or less of the velocities you would
# use with trapezoidal planning, then increase cautiously.
#
# Example homing configuration (adjust for your machine):
#HOME_SEARCH_VEL = 5.0 # Velocity for initial limit switch search
#HOME_LATCH_VEL = 1.0 # Velocity for precise homing (slower)
#HOME_OFFSET = 0.0 # Distance from switch to home position
#HOME_USE_INDEX = NO # Use encoder index pulse for homing
#HOME_IGNORE_LIMITS = NO # Ignore limit switches during homing move
# ========================================================
[JOINT_1]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
# See JOINT_0 for detailed homing configuration examples.
#HOME_SEARCH_VEL = 5.0
#HOME_LATCH_VEL = 1.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
#MIN_LIMIT = -100.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 100.0 #disabled to give more space for testing g-codes
HOME_SEQUENCE = 0
# WARNING: S-curve homing requires SLOWER velocities than trapezoidal!
# See JOINT_0 for detailed homing configuration examples.
#HOME_SEARCH_VEL = 4.0
#HOME_LATCH_VEL = 0.8
# ========================================================
# AXIS CONFIGURATION
# ========================================================
[AXIS_X]
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
# MAX_JERK: Maximum jerk for coordinated motion on this axis
# Units: machine-units/second^3
# Default: 0.0 (disabled)
MAX_JERK = 10000.0
[AXIS_Y]
#MIN_LIMIT = -200.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 200.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 300.0
MAX_ACCELERATION = 1000.0
MAX_JERK = 10000.0
[AXIS_Z]
#MIN_LIMIT = -100.0 #disabled to give more space for testing g-codes
#MAX_LIMIT = 100.0 #disabled to give more space for testing g-codes
MAX_VELOCITY = 200.0
MAX_ACCELERATION = 800.0
MAX_JERK = 10000.0
# ========================================================
# TUNING GUIDELINES
# ========================================================
#
# 1. START WITH TRAPEZOIDAL (PLANNER_TYPE=0)
# - Verify your machine works correctly with traditional planning
# - Note any vibration or resonance issues
#
# 2. ENABLE S-CURVE WITH CONSERVATIVE VALUES
# - Set PLANNER_TYPE = 1
# - Start with low MAX_LINEAR_JERK (e.g., 100-500)
# - Jerk should typically be 10-100x your acceleration value
#
# 3. GRADUALLY INCREASE JERK
# - Increase MAX_LINEAR_JERK in steps of 2-3x
# - Test with simple moves and observe:
# * Motor current/torque
# * Vibration levels
# * Following errors
# * Surface finish quality
#
# 4. FIND OPTIMAL VALUE
# - Too low: Motion becomes sluggish, cycle time increases
# - Too high: Approaches trapezoidal behavior, loses smoothness
# - Optimal: Smooth motion without excessive deceleration
#
# 5. VERIFY COORDINATED MOTION
# - Test circular interpolation (G2/G3)
# - Check complex 3D toolpaths
# - Verify axis jerk limits don't constrain trajectory jerk
#
# ========================================================
# TROUBLESHOOTING
# ========================================================
#
# SYMPTOM: No difference between PLANNER_TYPE=0 and PLANNER_TYPE=1
# SOLUTION: Verify MAX_LINEAR_JERK > 0 and MAX_JERK > 0 for all joints/axes
#
# SYMPTOM: Motion is too slow with S-curve enabled
# SOLUTION: Increase MAX_LINEAR_JERK value
#
# SYMPTOM: Following errors increase with S-curve
# SOLUTION: Decrease MAX_LINEAR_JERK or increase PID I-gain
#
# SYMPTOM: Vibration/resonance at certain speeds
# SOLUTION: Adjust MAX_LINEAR_JERK to avoid resonant frequencies
# Consider using different jerk values for different axes
#
# ========================================================

View File

@@ -0,0 +1,110 @@
[EMC]
MACHINE = Canterp Example
VERSION = 1.1
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
INTERPRETER = canterp.so
[DISPLAY]
OPEN_FILE = ./canterp_example.can
DISPLAY = axis
CYCLE_TIME = 0.100
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
MAX_LINEAR_VELOCITY = 1.2
DEFAULT_LINEAR_VELOCITY = .25
PROGRAM_PREFIX = ../../nc_files/
#EDITOR = geany
TOOL_EDITOR = tooledit
INCREMENTS = 1mm, .1mm
[RS274NGC]
PARAMETER_FILE = canterp.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
BASE_PERIOD = 0
SERVO_PERIOD = 1000000
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl
[TRAJ]
NO_FORCE_HOMING = 1
COORDINATES = X Y Z
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.2
MAX_LINEAR_VELOCITY = 1.2
[KINS]
KINEMATICS = trivkins
JOINTS = 3
[AXIS_X]
HOME = 0.000
MIN_LIMIT = -9999.0
MAX_LIMIT = 9999.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -9999
MAX_LIMIT = 9999
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 1
[AXIS_Y]
HOME = 0.000
MIN_LIMIT = -9999
MAX_LIMIT = 9999
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -9999
MAX_LIMIT = 9999
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 1
[AXIS_Z]
HOME = 0.0
MIN_LIMIT = -9999
MAX_LIMIT = 9999
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 100.0
MIN_LIMIT = -9999
MAX_LIMIT = 9999
HOME_OFFSET = 1.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 0
[EMCIO]
TOOL_TABLE = sim.tbl
TOOL_CHANGE_POSITION = 0 0 0
TOOL_CHANGE_QUILL_UP = 1

View File

@@ -0,0 +1,30 @@
xx xxxxx COMMENT(this is a comment)
xx xxxxx COMMENT(first two columns are ignored)
xx xxxxx COMMENT(see canterp.cc for possible commands)
00 N____ USE_LENGTH_UNITS(CANON_UNITS_MM)
00 N____ SET_FEED_REFERENCE(CANON_XYZ)
00 N____ MIST_OFF()
00 N____ FLOOD_OFF()
00 N____ SET_FEED_RATE(50.0)
00 N____ SET_SPINDLE_SPEED(0, 3000)
00 N____ START_SPINDLE_CLOCKWISE(0)
00 N____ STRAIGHT_TRAVERSE( 5 5 5 0 0 0 0 0 0)
00 N____ STRAIGHT_TRAVERSE( 0 0 0 0 0 0 0 0 0)
00 N____ MIST_OFF()
00 N____ FLOOD_OFF()
00 N____ SET_FEED_RATE(50.0)
00 N____ SET_SPINDLE_SPEED(0, 3000)
00 N____ START_SPINDLE_CLOCKWISE(0)
00 N____ STRAIGHT_FEED(10 00 00 0 0 0 0 0 0)
00 N____ STRAIGHT_FEED(10 10 00 0 0 0 0 0 0)
00 N____ STRAIGHT_FEED(10 10 10 0 0 0 0 0 0)
00 N____ STRAIGHT_FEED(10 10 10 0 0 0 0 0 0)
00 N____ STRAIGHT_FEED(10 10 00 0 0 0 0 0 0)
00 N____ STRAIGHT_FEED(10 00 00 0 0 0 0 0 0)
00 N____ COMMENT(lines below not working)
00 N____ COMMENT(ARC_FEED(1.0704, 3.3450, 2.0000, 2.0000, 1, 1.6875)))

View File

@@ -0,0 +1,5 @@
This config is a simulated stepper machine with the addition of ClassicLadder connections to some of the LinuxCNC IO.
The initial ladder program includes several possible estop arrangements and a timed lube coil. The lube ladder includes a sense run that watches lube level or lube pressure and warns of a lube condition failure.
This ladder integration with the HAL will allow you to expand the IO interface to a minimill with spindle and tool changer controls.

View File

@@ -0,0 +1,20 @@
# first load realtime portion of classicladder, and create a 1mS thread
loadrt classicladder_rt period=1000000
# hook functions to realtime thread
addf classicladder.0.refresh classicladder.thread 1
# create some I/O signals
# connect I/O signals to classicladder
net I0 => classicladder.0.in-00
net I1 => classicladder.0.in-01
net I2 => classicladder.0.in-02
net Q0 <= classicladder.0.out-00
net Q1 <= classicladder.0.out-01
net Q2 <= classicladder.0.out-02
# set the input signals
sets I0 0
sets I1 0
sets I2 0

View File

@@ -0,0 +1,167 @@
_FILES_CLASSICLADDER
_FILE-rung_1.csv
#VER=2.0
#LABEL=Rung 1
#COMMENT=Stepper Estop Chain
#PREVRUNG=0
#NEXTRUNG=2
0-0-50/0 , 1-0-50/0 , 9-0-50/0 , 9-0-50/1 , 9-0-0/0 , 9-0-0/0 , 9-0-60/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/0
0-0-0/0 , 2-0-50/1 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-50/2 , 9-0-0/0 , 9-0-0/0 , 0-1-60/1
0-0-50/0 , 1-0-50/0 , 2-0-50/1 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/1 , 9-0-0/0 , 0-1-60/1
9-0-0/0 , 1-0-50/0 , 2-0-50/1 , 1-0-60/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 0-1-0/0
0-0-60/1 , 0-0-0/0 , 0-0-0/0 , 1-1-50/2 , 0-1-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-60/6
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
_/FILE-rung_1.csv
_FILE-symbols.csv
#VER=1.0
%I0,GUI-E,
%I1,EXT-E,
%I2,E-RESET,
%I3,Lube_on,
%I4,sensor,
%I5,I5,
%I6,I6,
%I7,I7,
%I8,I8,
%I9, ,
%Q0,EMC-E,
%Q1,toggle,
%Q2,Lube_low,
%Q3,Q3,
%Q4,Q4,
%Q5,Q5,
%Q6,Q6,
%Q7,Q7,
%Q8,Q8,
%Q9,Q9,
%T0,Time-on,Time lube pump is on
%T1,Time-off,Time lube pump is off
%T2,Time-warn,Time before low lube warning
%B0,reset,reset off timer
_/FILE-symbols.csv
_FILE-rung_2.csv
#VER=2.0
#LABEL=
#COMMENT=Intermittent Lube
#PREVRUNG=1
#NEXTRUNG=-1
9-0-0/0 , 1-0-50/3 , 2-0-0/0 , 99-0-0/0 , 10-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 53-0-60/1
0-0-0/0 , 0-0-0/0 , 0-1-0/0 , 99-1-0/0 , 99-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 52-0-60/1
0-0-0/0 , 0-0-0/0 , 2-1-60/1 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 10-0-0/1 , 0-0-60/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-1-0/0 , 0-0-0/0 , 0-0-0/0 , 99-1-0/0 , 99-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-0/0
0-0-0/0 , 0-0-0/0 , 1-1-50/4 , 99-0-0/0 , 10-0-0/2 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-60/9
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 99-1-0/0 , 99-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/2
_/FILE-rung_2.csv
_FILE-modbusioconf.csv
#VER=1.0
_/FILE-modbusioconf.csv
_FILE-com_params.txt
MODBUS_MASTER_SERIAL_PORT=
MODBUS_MASTER_SERIAL_SPEED=9600
MODBUS_MASTER_SERIAL_DATABITS=8
MODBUS_MASTER_SERIAL_STOPBITS=1
MODBUS_MASTER_SERIAL_PARITY=0
MODBUS_ELEMENT_OFFSET=0
MODBUS_MASTER_SERIAL_USE_RTS_TO_SEND=0
MODBUS_MASTER_TIME_INTER_FRAME=100
MODBUS_MASTER_TIME_OUT_RECEIPT=500
MODBUS_MASTER_TIME_AFTER_TRANSMIT=0
MODBUS_DEBUG_LEVEL=0
MODBUS_MAP_COIL_READ=0
MODBUS_MAP_COIL_WRITE=0
MODBUS_MAP_INPUT=0
MODBUS_MAP_HOLDING=0
MODBUS_MAP_REGISTER_READ=0
MODBUS_MAP_REGISTER_WRITE=0
_/FILE-com_params.txt
_FILE-timers_iec.csv
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
1,0,0
_/FILE-timers_iec.csv
_FILE-timers.csv
1,10
1,20
0,20
2,1
2,5
1,0
1,0
1,0
1,0
1,0
_/FILE-timers.csv
_FILE-counters.csv
0
0
0
0
0
0
0
0
0
0
_/FILE-counters.csv
_FILE-sections.csv
#VER=1.0
#NAME000=Prog1
000,0,-1,1,2,0
_/FILE-sections.csv
_FILE-arithmetic_expressions.csv
#VER=2.0
_/FILE-arithmetic_expressions.csv
_FILE-rung_0.csv
#VER=2.0
#LABEL=
#COMMENT=
#PREVRUNG=0
#NEXTRUNG=1
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
_/FILE-rung_0.csv
_FILE-ioconf.csv
#VER=1.0
_/FILE-ioconf.csv
_FILE-monostables.csv
1,10
1,20
1,0
1,0
1,0
1,0
1,0
1,0
1,0
1,0
_/FILE-monostables.csv
_FILE-sequential.csv
#VER=1.0
_/FILE-sequential.csv
_FILE-general.txt
PERIODIC_REFRESH=100
SIZE_NBR_RUNGS=100
SIZE_NBR_BITS=500
SIZE_NBR_WORDS=100
SIZE_NBR_TIMERS=10
SIZE_NBR_MONOSTABLES=10
SIZE_NBR_COUNTERS=10
SIZE_NBR_TIMERS_IEC=10
SIZE_NBR_PHYS_INPUTS=15
SIZE_NBR_PHYS_OUTPUTS=25
SIZE_NBR_ARITHM_EXPR=100
SIZE_NBR_SECTIONS=10
SIZE_NBR_SYMBOLS=100
_/FILE-general.txt
_/FILES_CLASSICLADDER

View File

@@ -0,0 +1,45 @@
# HAL config file for using classic ladder
# The core_sim.hal file sets up motion, stepgen and other common items
# Remove core_sim.hal connections for the following pins and implement
# using classic latter functionality instead:
unlinkp iocontrol.0.user-enable-out
unlinkp iocontrol.0.emc-enable-in
# This file adds:
# the possibility of an external momentary or sustained NC estop button
# and includes intermittent lube pump and pressure or level sensing.
# (load the realtime portion)
# these classicladder parameters need to be optimized after ladder completion
loadrt classicladder_rt numRungs=12 numBits=20 numWords=4 numTimers=5 numMonostables=2 numPhysInputs=10 numPhysOutputs=10 numArithmExpr=4 numSections=4
# We kick ladder into a thread at the slower servo rate rather than base rate
addf classicladder.0.refresh servo-thread 1
# invoke the user part of CL to silently load the program
# later we will need to add the clp file mentioned below
# to the ini file so that we do not need to hardcode it here.
loadusr -w classicladder --nogui demo_sim_cl.clp
# three axis motion allows 6 other outputs on pins 8,9,1,14,16,17
# five additional input pins are available 10,11,12,13,15
# these are setup by the work they perform below
# estop signals
# signal is the internal or gui estop command from EMC
net gui-estop iocontrol.0.user-enable-out classicladder.0.in-00
# one-shot on timer when signal above goes high.
net estop-strobe iocontrol.0.user-request-enable classicladder.0.in-02
# this bit is an external estop button connected to parport pin 11 and ground
net ext-estop classicladder.0.in-01
# This bit signal is command to estop from CL to EMC
net estop-all-ok iocontrol.0.emc-enable-in classicladder.0.out-00
# lube signals
# lube run command from emc to CL
# for ease of reading we will make a new signal lube-run
net lube-run classicladder.0.out-01
# The lube sense stuff runs from an external pin, through CL to iocontrol in
# lube-up is the signal between the parport and cl
net lube-up classicladder.0.in-04

View File

@@ -0,0 +1,111 @@
[EMC]
VERSION = 1.1
MACHINE = LinuxCNC-DEMO-SIM-CL
# Debug level, 0 means no messages. See src/emc/nml_int/emcglb.h for others
DEBUG = 0
[DISPLAY]
DISPLAY = axis
CYCLE_TIME = 0.200
HELP_FILE = tklinuxcnc.txt
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
PROGRAM_PREFIX = ../../nc_files/
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 2
#EDITOR = geany
[RS274NGC]
PARAMETER_FILE = demo_sim_cl.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
BASE_PERIOD = 50000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[HAL]
HALFILE = core_sim.hal
HALFILE = demo_sim_cl.hal
HALFILE = simulated_home.hal
[TRAJ]
COORDINATES = X Y Z
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 0.0167
MAX_LINEAR_VELOCITY = 1.2
DEFAULT_LINEAR_ACCELERATION = 15.0
MAX_LINEAR_ACCELERATION = 20.0
[EMCIO]
TOOL_TABLE = demo_sim_cl.tbl
[KINS]
KINEMATICS = trivkins
JOINTS = 3
[AXIS_X]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 21.0
SCALE = 4000
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 1
[AXIS_Y]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 21.0
SCALE = 4000
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 1
[AXIS_Z]
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 21.0
SCALE = 4000
MIN_LIMIT = -2.0
MAX_LIMIT = 4.0
HOME_OFFSET = 1.0
HOME_SEARCH_VEL = 20.0
HOME_LATCH_VEL = 20.0
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,4 @@
T1 P1 D0.125000 Z+0.511000 ;1/8 end mill
T2 P2 D0.062500 Z+0.100000 ;1/16 end mill
T3 P3 D0.201000 Z+1.273000 ;#7 tap drill
T99999 P99999 Z+0.100000 ;big tool number

View File

@@ -0,0 +1,5 @@
# Fake the existence of coolant options
loadrt and2 count=2
addf and2.0 servo-thread
net flood iocontrol.0.coolant-flood => and2.0.in0
net mist iocontrol.0.coolant-mist => and2.0.in1

View File

@@ -0,0 +1,104 @@
# 3joint_xyz.hal
# This halfile loads modules and makes connections
# for use of any kinematics using xyz coordinates
# implemented with 3 joints. Such configs include:
# [KINS]KINEMATICS = trivkins coordinates=xyz
# [KINS]KINEMATICS = corexykins
# Notes:
# 1) stepgens are implemented but no connections are
# included for hardware
# 2) home switches are simulated
#----------------------------------------------------------
loadrt [KINS]KINEMATICS
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD \
servo_period_nsec=[EMCMOT]SERVO_PERIOD \
num_joints=[KINS]JOINTS
loadrt stepgen step_type=0,0,0
# simulated home switches:
loadrt sim_home_switch names=j0home,j1home,j2home
#----------------------------------------------------------
setp stepgen.0.position-scale [JOINT_0]SCALE
setp stepgen.0.maxaccel [JOINT_0]STEPGEN_MAXACCEL
setp stepgen.0.steplen 5000
setp stepgen.0.stepspace 5000
setp stepgen.0.dirhold 35000
setp stepgen.0.dirsetup 35000
setp stepgen.1.position-scale [JOINT_1]SCALE
setp stepgen.1.maxaccel [JOINT_1]STEPGEN_MAXACCEL
setp stepgen.1.steplen 5000
setp stepgen.1.stepspace 5000
setp stepgen.1.dirhold 35000
setp stepgen.1.dirsetup 35000
setp stepgen.2.position-scale [JOINT_2]SCALE
setp stepgen.2.maxaccel [JOINT_2]STEPGEN_MAXACCEL
setp stepgen.2.steplen 5000
setp stepgen.2.stepspace 5000
setp stepgen.2.dirhold 35000
setp stepgen.2.dirsetup 35000
#----------------------------------------------------------
# simulated home motor positions:
setp j0home.home-pos 0.2
setp j1home.home-pos 0.2
setp j2home.home-pos 0.1
#----------------------------------------------------------
addf stepgen.make-pulses base-thread
addf stepgen.capture-position servo-thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf stepgen.update-freq servo-thread
addf j0home servo-thread
addf j1home servo-thread
addf j2home servo-thread
#----------------------------------------------------------
net j0enable <= joint.0.amp-enable-out
net j0enable => stepgen.0.enable
net j0pos-cmd <= joint.0.motor-pos-cmd
net j0pos-cmd => stepgen.0.position-cmd
net j0pos-cmd => j0home.cur-pos
net j0pos-fb <= stepgen.0.position-fb
net j0pos-fb => joint.0.motor-pos-fb
net j0step <= stepgen.0.step
net j0dir <= stepgen.0.dir
net j0homesw <= j0home.home-sw
net j0homesw => joint.0.home-sw-in
net j1enable <= joint.1.amp-enable-out
net j1enable => stepgen.1.enable
net j1pos-cmd <= joint.1.motor-pos-cmd
net j1pos-cmd => stepgen.1.position-cmd
net j1pos-cmd => j1home.cur-pos
net j1pos-fb <= stepgen.1.position-fb
net j1pos-fb => joint.1.motor-pos-fb
net j1step <= stepgen.1.step
net j1dir <= stepgen.1.dir
net j1homesw <= j1home.home-sw
net j1homesw => joint.1.home-sw-in
net j2enable <= joint.2.amp-enable-out
net j2enable => stepgen.2.enable
net j2pos-cmd <= joint.2.motor-pos-cmd
net j2pos-cmd => stepgen.2.position-cmd
net j2pos-cmd => j2home.cur-pos
net j2pos-fb <= stepgen.2.position-fb
net j2pos-fb => joint.2.motor-pos-fb
net j2step <= stepgen.2.step
net j2dir <= stepgen.2.dir
net j2homesw <= j2home.home-sw
net j2homesw => joint.2.home-sw-in
#----------------------------------------------------------
net estop-out <= iocontrol.0.user-enable-out
net estop-out => iocontrol.0.emc-enable-in
net tool-change-loopback <= iocontrol.0.tool-change
net tool-change-loopback => iocontrol.0.tool-changed
net tool-prepare-loopback <= iocontrol.0.tool-prepare
net tool-prepare-loopback => iocontrol.0.tool-prepared

View File

@@ -0,0 +1,24 @@
corexy examples:
corexy_by_kins.ini
Demonstrates corexykins kinematics
(Note: using corexykins kinematics
on real hardware requires home
switches triggered by motor
positions)
corexy_by_hal.ini
Demonstrates use of trivkins with
corexy kinematics implemented by a
hal component
(Notes: this method supports
home switches aligned with x,y
coordinates)
Notes:
1) The configurations share common ini
file settings from corey_base.inc
2) Home switches are simulated
3) stepgens are configured but no
connections to hardware are
included.

View File

@@ -0,0 +1,22 @@
pin+corexy_by_hal.j0-motor-pos-cmd
pin+corexy_by_hal.j1-motor-pos-cmd
pin+corexy_by_hal.j0-motor-pos-fb
pin+corexy_by_hal.j1-motor-pos-fb
pin+corexy_by_hal.alpha-cmd
pin+corexy_by_hal.beta-cmd
pin+corexy_by_hal.alpha-fb
pin+corexy_by_hal.beta-fb
pin+joint.0.motor-pos-cmd
pin+joint.1.motor-pos-cmd
pin+joint.0.motor-pos-fb
pin+joint.1.motor-pos-fb
pin+joint.0.motor-offset
pin+joint.1.motor-offset
pin+stepgen.0.position-cmd
pin+stepgen.1.position-cmd
pin+stepgen.0.position-fb
pin+stepgen.1.position-fb

View File

@@ -0,0 +1,91 @@
# Notes:
# 1) this is an INCLUDE file for common settings
# for demonstration configs
# 2) INCLUDING file must supply the sections for:
# [EMC],[KINS],[HAL]
[APPLICATIONS]
APP = halshow --fformat "%.3f" corexy.halshow
[DISPLAY]
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
DEFAULT_LINEAR_VELOCITY = 1.0
MIN_LINEAR_VELOCITY = 0
MAX_LINEAR_VELOCITY = 1.0
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
PROGRAM_PREFIX = ../../nc_files/
INCREMENTS = .1in .01in .001in
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[RS274NGC]
PARAMETER_FILE = linuxcnc.var
[EMCMOT]
EMCMOT = motmod
BASE_PERIOD = 250000
SERVO_PERIOD = 1000000
[TRAJ]
COORDINATES = XYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
MAX_LINEAR_VELOCITY = 1.0
[EMCIO]
TOOL_TABLE = tool.tbl
[AXIS_X]
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
MIN_LIMIT = -0.1
MAX_LIMIT = 10.0
[AXIS_Y]
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
MIN_LIMIT = -0.1
MAX_LIMIT = 10.0
[AXIS_Z]
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
MIN_LIMIT = -5.0
MAX_LIMIT = 0.5
[JOINT_0]
TYPE = LINEAR
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 25.0
SCALE = 8000.0
HOME_SEARCH_VEL = 1
HOME_LATCH_VEL = 1
HOME_SEQUENCE = 0
[JOINT_1]
TYPE = LINEAR
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 25.0
SCALE = 8000.0
HOME_SEARCH_VEL = 1
HOME_LATCH_VEL = 1
HOME_SEQUENCE = 1
[JOINT_2]
TYPE = LINEAR
MAX_VELOCITY = 2.0
MAX_ACCELERATION = 20.0
STEPGEN_MAXACCEL = 25.0
SCALE = 8000.0
HOME_SEARCH_VEL = 1
HOME_LATCH_VEL = 1
HOME_SEQUENCE = 2

View File

@@ -0,0 +1,57 @@
# corexy_by_hal.hal
# This halfile adapts a configuration using trvikins
# to implement corexy kinematics using the hal
# component: corexy_by_hal.
# This corexy method allows home switches to operate
# along the Cartesian X and Y coordinate motion.
# By contrast, when using corexykins kinematics, home
# switches operate according to motor positions for
# joints 0 and 1.
# show original signals for joints 0,1
show sig j0pos-cmd j1pos-cmd
show sig j0pos-fb j1pos-fb
# remove original signals that connect
# pins for stepgens 0,1:
delsig j0pos-cmd
delsig j1pos-cmd
delsig j0pos-fb
delsig j1pos-fb
# implement corexy kinematics with hal component:
loadrt corexy_by_hal names=corexy_by_hal
addf corexy_by_hal servo-thread
net :j0motor-cmd <= joint.0.motor-pos-cmd
net :j0motor-cmd => corexy_by_hal.j0-motor-pos-cmd
net :j0motor-cmd => j0home.cur-pos
net :j1motor-cmd <= joint.1.motor-pos-cmd
net :j1motor-cmd => corexy_by_hal.j1-motor-pos-cmd
net :j1motor-cmd => j1home.cur-pos
net :j0motor-fb <= corexy_by_hal.j0-motor-pos-fb
net :j0motor-fb => joint.0.motor-pos-fb
net :j1motor-fb <= corexy_by_hal.j1-motor-pos-fb
net :j1motor-fb => joint.1.motor-pos-fb
# new signals connecting pins for stepgens 0,1:
net :alpha-cmd <= corexy_by_hal.alpha-cmd
net :alpha-cmd => stepgen.0.position-cmd
net :beta-cmd => corexy_by_hal.beta-cmd
net :beta-cmd <= stepgen.1.position-cmd
net :alpha-fb <= stepgen.0.position-fb
net :alpha-fb => corexy_by_hal.alpha-fb
net :beta-fb <= stepgen.1.position-fb
net :beta-fb => corexy_by_hal.beta-fb
# show new signals:
show sig :*alpha*
show sig :*beta*

View File

@@ -0,0 +1,18 @@
# basic configuration items:
#INCLUDE corexy_base.inc
[EMC]
MACHINE = corexy_by_hal
VERSION = 1.1
[KINS]
JOINTS = 3
KINEMATICS = trivkins coordinates=XYZ kinstype=b
[HAL]
# default connections for a 3joint xyz config:
HALFILE = 3joint_xyz.hal
# update connections for trivkins to implement
# corexy kinematics in hal
HALFILE = corexy_by_hal.hal

View File

@@ -0,0 +1,11 @@
corexy_by_hal.ini
CoreXY simulation using the
trivkins kinematics module
with the corexy_by_hal
hal component
This hal method supports home switches
that are aligned with the X and Y
coordinates instead of the joint 0,1
motor positions.

View File

@@ -0,0 +1,14 @@
# basic configuration items:
#INCLUDE corexy_base.inc
[EMC]
MACHINE = corexy_by_kins
VERSION = 1.1
[KINS]
JOINTS = 3
KINEMATICS = corexykins
[HAL]
# default connections for a 3joint xyz config:
HALFILE = 3joint_xyz.hal

View File

@@ -0,0 +1,22 @@
corexy_by_kins.ini
CoreXY simulation using the
corexykins kinematics module
$ man kins for more info
Notes:
1) Using corexykins requires home
switches operating on motor
positions for joints 0 and 1
2) An alternative method for coreXY
kinematics uses trivkins kinematics
with a hal component:
(corexy_by_hal.comp)
This method allows use of home
switches aligned to x,y coordinate
motion.
See the demo: corexy_by_hal.ini

View File

@@ -0,0 +1,58 @@
db_ran.ini random_toolchanger
db_nonran.ini nonrandom_toolchanger
Each config starts with:
tool numbers 10--19
A number of tools are set with identical
tool diameters to demonstrate tool selection
based on accrued tool time.
The config runs separate tasks to
a) modify a tool parameter
b) add/remove tool numbers
Usage (for db_nonran.ini):
1) In a terminal, start as
$ linuxcnc ./db_nonran.ini
F1 --------- Estop off
F2 --------- Machine On
Ctrl-Home -- Home All
R ---------- Run program
You can also experiment with MDI for the relevant
commands (TnM6, T0M6, G10L0, G10L1, G10L10, M61)
The default program runs a loop that a) loads tool
T10 and applies its offset (G43), b) displays the
zoffset, c) pauses, d) unloads the tool, e)
reloads the tool data.
The display will show different zoffsets at each
tool change since the tool data includes several
tools with the same diameter but different
zoffsets and the applied database rule selects the
tool with the minimum time usage. Since the pause
time is nominally the same for each tool offered,
the database will select different tools for T10
with each reload.
To watch the tool data changes and tool usage time
accrual, use the following command in a separate
terminal (source rip_environment for RIP builds):
$ watch -n 0.2 cat /tmp/db_nonran_file
or
$ watch -n 0.2 cat /tmp/db_ran_file
The M parameter in the /tmp/db_nonran_file
accounts for tool time measured in minutes
To get more information (stdout):
1) export DB_SHOW=
show 'g' (get) command
2) export DB_DEBUG=
show more database info

View File

@@ -0,0 +1,87 @@
#-----------------------------------------
# include file for common stanzas
[DISPLAY]
OPEN_FILE=./base.ngc
POSITION_OFFSET=RELATIVE
POSITION_FEEDBACK=ACTUAL
DISPLAY = axis
MAX_LINEAR_VELOCITY = 1
# placeholder for a user supplied editor for a db_program:
TOOL_EDITOR = ./db_editor.tcl
PYVCP = ./db_panel.xml
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[EMCMOT]
EMCMOT = motmod
SERVO_PERIOD = 1000000
[HAL]
HALUI=halui
HALFILE = LIB:basic_sim.tcl -no_use_hal_manualtoolchange
POSTGUI_HALFILE = db_postgui.hal
[TRAJ]
NO_FORCE_HOMING = 1
# Note:allow all coords for testing
COORDINATES = XYZABCUVW
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
MAX_ANGULAR_VELOCITY=1000
[KINS]
JOINTS = 9
KINEMATICS = trivkins coordinates=XYZABCUVW
[JOINT_0]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_1]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_2]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_3]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_4]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_5]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_6]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_7]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0
[JOINT_8]
TYPE = LINEAR
MAX_VELOCITY=1e99
MAX_ACCELERATION=1e99
HOME_SEQUENCE=0

View File

@@ -0,0 +1,17 @@
%
#<toolno> = 10
#<ct> = 0
#<howmany> = 5
g49
o100 while [[#<ct> lt #<howmany>] and [#<_task> ne 0]]
#<ct> = [#<ct> +1]
t#<toolno> m6 g43
(debug,ct=#<ct> zoff=#5403)
g4p[0.05*60] ;approx 0.05 minutes
t0m6
g10l0 ; reload tooldata (apply_db_rules)
o100 endwhile
g49
(debug, fini)
%

831
configs/sim/axis/db_demo/db.py Executable file
View File

@@ -0,0 +1,831 @@
#!/usr/bin/python3
# Note: '#!/usr/bin/python3' is used instead of
# '#!/usr/bin/env python3'
# since it allows ps and pidof to show/find
# using the script name
# Example [EMCIO]DB_PROGRAM:
# Demonstrate LinuxCNC interface for a database of tools
# with tool time usage monitoring
# ini file examples:
# [EMCIO]DB_PROGRAM=./db_nonran.py [nonran_filename]
# [EMCIO]DB_PROGRAM=./db_ran.py [ran_filename]
# defaults for *_filename:
db_ran_savefile = "/tmp/db_ran_file" # db flatfile
db_nonran_savefile = "/tmp/db_nonran_file" # db flatfile
#-----------------------------------------------------------
import os
import sys
import time
import signal
import threading
import getopt
import linuxcnc
#-----------------------------------------------------------
# LinuxCNC tooldb module for low-level interface:
from tooldb import tooldb_callbacks # functions (g,p,l,u)
from tooldb import tooldb_tools # list of tool numbers
from tooldb import tooldb_loop # main loop
#-----------------------------------------------------------
# Notes
# 1) Uses the LinuxCNC provided tooldb module: so all
# writes to stdout are piped to LinuxCNC host.
# Use stderr for debug prints in this file.
# 2) tool usage time is computed based on
# loads/unloads. Tool must be unloaded
# when LinuxCNC is stopped.
# 3) a database savefile will be created at
# startup if it does not exist applying
# rules for a simulation setup.
# 4) startup/tooltimer
# a) random toolchanger: both LinuxCNC and database
# know if there is a loaded tool at startup so
# if a tool is loaded, timer is started
# b) nonrandom toolchanger: LinuxCNC is not
# aware of loaded tool at startup so timer is
# not started. (use m61qn to specify tool
# and start timer)
# c) best practice: operator always unloads tool
# when stopping LinuxCNC
# 5) The cmd_loop() function is executed in a thread
# so that concurrent tasks can be demonstrated.
# 6) Worker tasks demonstrate changes to database
# with synchronization to the LinuxCNC host:
# a) tool_modify_task: change a tool parameter
# b) tool_update_task add/remove tool no.s
# The tasks are executed in threads concurrent
# to the primary task that executes tooldb_loop().
# to illustrate methods for db_program guis that
# update and synchronize tooldata with LinuxCNC.
# 7) The periodic_task updates tool time usage.
# 8) A single mutex is used to protect all activity
# than can read/write tools[] and db_*_savefile
# The mutex is acquired and held by
# a) each tooldb interface routine specified
# by the call to tooldb_callbacks()
# b) the periodic_task
# c) each worker demonstration task:
# tool_modify_task()
# tool_update_task()
# 9) Monitor tool data updates by using shell watch
# command in a terminal. Examples:
# $ watch -d -n 1 cat /tmp/db_ran_file
# $ watch -d -n 1 cat /tmp/db_nonran_file
# 10) export environmental variables DB_SHOW, DB_DEBUG
# to print operational details from LinuxCNC
# 11) If LinuxCNC is not running, use is limited to basic
# command line testing for commands g,p,l,u.
# Use Ctrl-C to exit
# Example (simple non random toolchanger):
# $ ./db_nonran.py [debug]
# g (g: get all tools)
# p t11 p111 d.3 (p: put t11 for received update)
# g (g: note changes from p cmd)
# l t14 p0 (l: load tool 14)
# u t0 p0 (u: unload tool 14)
# Example (more complicated random toolchanger):
# $ ./db_ran.py [debug]
# $ g (g: get all tools)
# $ u t0 p114 (u: first of pair to load t14)
# $ l t14 p0 (l: second of pair to load t14)
# 12) problem: unexpected termination (like a power
# failure) is not detected by LinuxCNC so tool
# time data and tool-in-spindle status may be
# corrupted for such events. A database application
# may be able to detect and notify for some anomalies.
#-----------------------------------------------------------
# globals init
prog = sys.argv[0] # this program
toollist = [] # list of tool numbers
tools = dict() # tools[tno]: dict of text toollines
spindle_tool = -1 # no tool in spindle is indicated by:
# nonran:-1, ran:-1|0
nonran_from_pocket = dict()# use to restore pocket in db
start_time = -1 # neg means timer not active
elapsed_time = 0 # tool time usage
mfmt = "%.3f" # format for M letter usage time
sync_fail_reason = "" # why sync failed
cmdline_only = 0 # 1: for cmdline debugging
history = []; # history logging
history_max_ct = 10 # history logging
period_minutes = 1 # default for periodic_task
mutex = threading.Lock() # lock for all threads
disconnect_evt = threading.Event() # set at disconnect
# tletters: interface to LinuxCNC
tletters = ['T','P', 'D','X','Y','Z','A','B','C','U','V','W','I','J','Q']
# aux_letters: augment db usage
aux_letters = ['M'] # M for operating Minutes
all_letters = tletters + aux_letters
alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#-----------------------------------------------------------
# messages to stderr (stdout is piped to LinuxCNC)
def msg(txt): sys.stderr.write("%s: %s\n"%(prog,txt))
def umsg(txt): msg("UNEXPECTED: %s"%txt) # debug usage
try: # environ override default period_minutes for testing:
period_minutes = float(os.environ['DB_PERIOD_MINUTES'])
msg("period_minutes=%f"%period_minutes)
except Exception as e: pass
#-----------------------------------------------------------
# LinuxCNC interface for status & syncing
linuxcnc_stat = linuxcnc.stat()
linuxcnc_tool_sync = linuxcnc.command().load_tool_table
try: linuxcnc_stat.poll() # test if LinuxCNC running
except Exception as e:
msg("e=%s"%e)
msg("LinuxCNC not active, cmdline debugging")
cmdline_only = 1
#-----------------------------------------------------------
def ctrlc_handler(signo, frame):
sys.stderr.write(" Caught signo=%d Ctrl-C bye\n"%signo)
sys.exit(0)
if cmdline_only: signal.signal(signal.SIGINT, ctrlc_handler)
# defer handler until ready to avoid signal to io process
def notready_for_signal(signo, frame): umsg("notready_for_signal %d"%signo)
signal.signal(signal.SIGUSR1,notready_for_signal)
signal.signal(signal.SIGUSR2,notready_for_signal)
#-----------------------------------------------------------
# Simulation initial tool number and pocket number setups
toolno_min = 10
toolno_max = 19
pocket_offset = 100
n_extra_pockets = 5 # for add/remove demo
n_pockets = (toolno_max - toolno_min + 1) + n_extra_pockets
pockets_base = toolno_min + pocket_offset # start of pocket numbering
available_pockets = []
for i in range(n_pockets): available_pockets.append(pockets_base + i)
#-----------------------------------------------------------
def start_db_program():
global db_savefile, period_minutes, random_toolchanger
# Default: support random_toolchanger
# Use symbolic link with "nonran" in its name to implement
# a nonrandom_toolchanger
if sys.argv[0].find("nonran")>=0:
msg("starting(nonrandom_toolchanger)")
random_toolchanger = 0
db_savefile = db_nonran_savefile # default file
else:
msg("starting(random_toolchanger) n_pockets = %d"%n_pockets)
random_toolchanger = 1
db_savefile = db_ran_savefile # default file
# handle options and args:
try: opts,remainder = getopt.getopt(sys.argv[1:]
,shortopts='hp:'
,longopts=['help','period_minutes=']
)
except getopt.GetoptError as emsg:
msg("GetoptError:%s"%emsg)
sys.exit(1)
for opt,arg in opts:
if opt in ('-p','--period_minutes'):
period_minutes=float(arg)
msg("period_minutes=%f"%period_minutes)
if opt in ('-h','--help'):
msg("""
Usage: %s [Options] [flat_filename]
Default flat_filename = %s
Options:
-h|--help (and exit)
-p|--period_minutes value (default=%f)
bye!"""%(prog,db_savefile,period_minutes))
sys.exit(1)
if remainder:
db_savefile = remainder[0] # superseded default
msg("db_savefile = %s"%db_savefile)
if len(remainder) >1:
msg("Unknown arguments %s"%remainder[1:])
sys.exit(1)
#-----------------------------------------------------------
# functions
def toolline_to_list(line): return line.upper().split()
def toolline_to_dict(line,letters):
# line: "Tt Pp Dd Xx Yy Zz ..."
# dict: D["T"]=tno, D["P"]="p", D["D"]=d, ...
D = dict()
# use leading ';' to denote comment line
line_nocomment = line.upper().split(';')[0]
for item in line_nocomment.split():
for l in letters:
if l in item: D[l]=item.lstrip(l).lstrip('+')
return D
def dict_to_toolline(D,letters):
toolline = str()
for l in letters:
if l in D: toolline = toolline + " " + l + D[l]
toolline = toolline.strip()
return toolline
def save_tools_to_file(fname,comment=""):
f = open(fname,"w")
for tno in tools:
if debug: msg("@@Save: tno=%d %s"%(tno,tools[tno]))
D = toolline_to_dict(tools[tno],all_letters)
for l in all_letters:
if l == "T" or l == "P": continue # always include
if l in D and D[l] == "0": del D[l] # drop zero entries
tools[tno] = dict_to_toolline(D,all_letters)
for i in sorted(tools,key=tools.get):
f.write(tools[i] + " ;" + tool_comment(i) + "\n")
global history
if comment: history.append(comment)
if len(history) > history_max_ct: history=history[1:]
if len(history):
f.write("\n; Recent (last %d) db history:\n"%history_max_ct)
for i in range(len(history)):
f.write("; %s\n"%history[i])
f.close()
def nonran_pno(tno): # simulation rule:
return tno+pocket_offset # make startup pocket number different than tool number
# to avoid assumptions about tno and pno
def nonran_restore_pocket(tno):
if not tno in nonran_from_pocket:
umsg("nonran_restore_pocket tno=%d not in dict: %s"%(tno,nonran_from_pocket))
D = toolline_to_dict(tools[tno],all_letters)
D['P'] = nonran_from_pocket[tno]
tools[tno] = dict_to_toolline(D,all_letters)
#msg("Restore pocket tno:%d pno %s"%(tno,int(D['P'])))
del nonran_from_pocket[tno]
def assign_pocket(tno):
global available_pockets
if not random_toolchanger:
return nonran_pno(tno)
if not len(available_pockets):
umsg("assign_pocket: no pockets available") # expect error
available_pockets.sort()
pno = available_pockets[0]
available_pockets.remove(pno)
return pno
def release_pocket(pno):
global available_pockets
if not random_toolchanger: return # not applicable
if pno in available_pockets: umsg("pno=%d was already available"%pno)
available_pockets.append(pno)
available_pockets.sort()
return
def init_tools(tfirst,tlast):
# set tool parameters for all tools
global tools
msg("init_tools(): tfirst=%d tlast=%d"%(tfirst,tlast))
for tno in range(tfirst,tlast+1):
if random_toolchanger:
pno = assign_pocket(tno)
tools[tno] = "T%-3d P%-3d Z0.%d D0.%d"%(tno,pno,tno,tno)
tools[0] = "T0 P0 ; Empty pocket"
else:
tools[tno] = "T%-3d P%-3d Z0.%d D0.%d"%(tno,nonran_pno(tno),tno,tno)
# for testing tool time usage computations:
# T11,T12 have same diameter as T10
D = toolline_to_dict(tools[11],all_letters)
D['D'] = "D0.10"
tools[11] = dict_to_toolline(D,all_letters)
D = toolline_to_dict(tools[12],all_letters)
D['D'] = "D0.10"
tools[12] = dict_to_toolline(D,all_letters)
save_tools_to_file(db_savefile,"Created %s (init_tools)"%db_savefile)
return
def make_tools(tfirst,tlast):
global tools,spindle_tool
try: f = open(db_savefile,"r")
except IOError:
init_tools(tfirst,tlast)
initialtoollist = list(range(toolno_min,toolno_max+1))
if random_toolchanger: initialtoollist.append(0) # T0 provision
return initialtoollist
except Exception as e:
msg("make_tools: e=%s"%e)
# use preexisting file:
savedtoollist = []
while True:
line = f.readline().strip()
if not line: break
if line[0] == ';': continue
D = toolline_to_dict(line,all_letters)
tno = int(D["T"])
savedtoollist.append(tno)
if random_toolchanger:
pno = int(D["P"])
if pno != 0: available_pockets.remove(pno)
if not random_toolchanger:
#Note: nonran toolchanger:
# database may indicate tool is loaded at startup
# but LinuxCNC does not have this info
# so: timer is not started, use nonran_pno
if D["P"] == "0":
msg("nonran toolchanger was stopped with loaded tool %d"%tno)
D["P"] = str(nonran_pno(tno))
tools[tno] = dict_to_toolline(D,all_letters)
if debug: msg("@@tno=%d line=%s"%(tno,line))
if random_toolchanger and D['P'] == "0":
spindle_tool = tno
start_tool_timer(spindle_tool)
f.close()
save_tools_to_file(db_savefile
,"Using preexisting db file: %s (make_tools)"%db_savefile)
return savedtoollist
def sync_allowed():
global sync_fail_reason
try:
linuxcnc_stat.poll()
if linuxcnc_stat.interp_state != linuxcnc.INTERP_IDLE:
sync_fail_reason = "interp not idle"
return 0 # fail
except Exception as e:
msg("sync_allowed fail:%s"%e)
sync_fail_reason = e
return 0 # fail
sync_fail_reason = ""
return 1 # success
def add_dbtool(tno,**kwargs):
# kwargs specify parameters in tletters
# example usage: add_dbtool(tno,Ppvalue Zzvalue Ddvalue Xxvalue ...)
global toollist,tools
for k in kwargs.keys():
if k != k.upper():
msg("!!!add_dbtool ERR: unexpected lower case param: %s"%k)
if not k in tletters:
msg("!!!add_dbtool ERR: unknown param letter: %s"%k)
return 0 # fail
if not sync_allowed():
msg("add_dbtool: DISALLOWED tno=%d (%s)"%(tno,sync_fail_reason))
return 0 #fail
parms=""
for l in tletters:
if l in kwargs:
if l == 'P': umsg("add_dbtool tno=%d P%s"%(tno,kwargs[l]))
parms = parms + " %s%s"%(l,kwargs[l])
pno = assign_pocket(tno)
tools[tno] = "T%d"%tno + " P%d"%pno + parms
toollist.append(tno)
save_tools_to_file(db_savefile,"tno:%3d added (add_dbtool)"%tno)
tooldb_tools(toollist); linuxcnc_tool_sync()
msg("add_dbtool: ADD tno=%d pno=%d"%(tno,pno))
return 1 # success
def rm_dbtool(tno):
if not tno in toollist:
msg(" rm_dbtool: ERR tno=%d not in toollist"%tno)
return 0 # fail
if tno == spindle_tool:
msg(" rm_dbtool: ERR tno=%d is loaded to spindle"%tno)
return 0 # fail
D = toolline_to_dict(tools[tno],tletters)
pno = int(D['P'])
if not sync_allowed():
msg(" rm_dbtool: DISALLOWED tno=%d (%s)"%(tno,sync_fail_reason))
return 0 #fail
del tools[tno]
toollist.remove(tno)
save_tools_to_file(db_savefile,"tno:%3d removed (rm_dbtool)"%tno)
tooldb_tools(toollist); linuxcnc_tool_sync()
msg(" rm_dbtool: RM tno=%d pno=%d"%(tno,pno))
return 1 # success
def handle_disconnect(fname):
global disconnect_evt
if spindle_tool > 0:
stop_tool_timer(spindle_tool)
msg("!!!Stopped with loaded tool: %d"%spindle_tool)
if not random_toolchanger:
nonran_restore_pocket(spindle_tool)
save_tools_to_file(fname,"tno:%3d in spindle at termination"%spindle_tool)
msg("disconnected")
disconnect_evt.set()
def start_tool_timer(tno):
global start_time, elapsed_time, spindle_tool
if tno != spindle_tool:
umsg("start_tool_timer tno %d != spindle_tool %d"%(tno,spindle_tool))
if start_time >= 0:
umsg("start_tool_timer: tno:%d spindle_tool:%d start_time=%f"%(tno,spindle_tool,start_time))
start_time = time.time()
def update_tool_time(tno):
global start_time, elapsed_time
now = time.time()
if tno == 0: umsg("update_tool_time with no tool")
if start_time < 0 and spindle_tool > 0:
umsg("update_tool_time spindle_tool=%d start_time=%f"%(spindle_tool,start_time))
start_time = now
return
elapsed_time = now - start_time
start_time = now
D = toolline_to_dict(tools[tno],all_letters)
if not 'M' in D:
D['M'] = mfmt%(elapsed_time/60.0)
else:
tot_time_m = float(D['M'].strip('M')) + elapsed_time/60.0
D['M'] = mfmt%(tot_time_m)
tools[tno] = dict_to_toolline(D,all_letters)
save_tools_to_file(db_savefile)
def stop_tool_timer(tno):
global start_time, elapsed_time, spindle_tool
if start_time < 0 and random_toolchanger and tno != 0:
# ran_tc and starting with tool in spindle
msg("NOTE: Tool %d was not unloaded in prior run"%tno)
return
if spindle_tool <= 0: umsg("stop_tool_timer with no loaded tool")
update_tool_time(spindle_tool)
start_time = -1 # negative means timer not active
def update_tool_params(tno,update_line):
D = toolline_to_dict(tools[tno],all_letters)
for item in toolline_to_list(update_line):
for l in tletters:
if l in item: D[l]=item.lstrip(l) #supersede by update_line
if not random_toolchanger and spindle_tool == tno:
D['P'] = '0' # unload uses nonran_from_pocket[]
tools[tno] = dict_to_toolline(D,all_letters)
def apply_db_rules():
# Apply database rules
# typically: when a tooldata reload requested
# alternately: ater a tool is unloaded
# Rule: For tools having identical diameter (within diameter_epsilon),
# lowest tool number is assigned to the pocket/parameters for
# the tool with the lowest operating time (in minutes).
#
# So if t10diameter==t11diameter==t12diameter,
# t10 will select tool with lowest operating minutes
# ...
# t12 will select tool with most operating minutes
#
# NOTE: Tooldata must be reloaded for retrieval of updates.
# Use gui reload buttons or G10L0 in mdi or gcode programs
#msg("APPLY_DB_RULES================================")
diameter_epsilon = 0.001
if spindle_tool > 0: # not allowed with G10L0 but gui may attempt
msg("DISALLOW: apply_db_rules with tool %d loaded"%spindle_tool)
return
for tno in toollist:
if tno == 0: continue
CUR = toolline_to_dict(tools[tno],all_letters)
diam = float(CUR["D"])
if not 'M' in CUR: CUR['M'] = "0"
# find tools after tno in toollist with same diameter:
for tryno in toollist[toollist.index(tno)+1:]:
if tryno == 0: continue
TRY = toolline_to_dict(tools[tryno],all_letters)
if abs(diam - float(TRY["D"])) > diameter_epsilon: continue
# found equal diameters
if not 'M' in TRY: TRY['M'] = "0"
#msg("diameter match: tno=%d tryno=%d diam=%f trydiam=%s"
# %(tno,tryno,diam,TRY["D"]))
if float(TRY['M']) < float(CUR['M']):
# swap tool data so that tno has fewest minutes:
CUR['T'] = str(tryno)
TRY['T'] = str(tno)
tools[tno] = dict_to_toolline(TRY,all_letters)
tools[tryno] = dict_to_toolline(CUR,all_letters)
CUR = toolline_to_dict(tools[tno],all_letters)
save_tools_to_file(db_savefile,
"tno:%3d diam=%f NEWpno=%s minutes=%s (apply_db_rules)"
%(tno,diam,CUR['P'],CUR['M']))
def check_params(tno,params):
if (tno != 0) and (not tno in tools): # expect NAK
umsg("Attempt to use tno=%d not in db"%tno)
for l in params.upper():
if l in alphabet and not l in tletters:
umsg("unknown param letter:%s in %s"%(l,params))
def tool_comment(tno):
from datetime import datetime as dt
return "Tool_%2d %s"%(tno,dt.today().strftime("%d%b%y:%H.%M.%S"))
#-----------------------------------------------------------
# Interface (callback) functions
# 'g' interface command (ran or nonran)
def user_get_tool(tno):
mutex.acquire() # blocking
# detect tool data reload (gui or with G10L0) and apply db rules:
if tno == toollist[0]: apply_db_rules()
if debug: msg("@@user_get_tool: %s"%tools[tno])
ans = "" # line formatted for LinuxCNC db interface
for item in toolline_to_list(tools[tno]):
for l in tletters:
if l in item: ans = ans + " " + item
mutex.release()
ans = ans + " ;" + tool_comment(tno)
return ans.strip()
# 'p' interface command (ran or nonran toolchanger)
def user_put_tool(tno,params):
mutex.acquire() # blocking
check_params(tno,params)
update_tool_params(tno,params.upper() )
save_tools_to_file(db_savefile,"tno:%3d updated (user_put_tool)"%tno)
mutex.release()
# 'l' interface command (nonran toolchanger)
def user_load_spindle_nonran_tc(tno,params):
mutex.acquire() # blocking
global spindle_tool
#msg("user_load_spindle_nonran_tc 'l %s'"%params)
check_params(tno,params)
if tno == spindle_tool:
# a tool reload may be requested (gui, worker task, etc.) using:
# emcmodule.cc:load_tool_table()
# --> EMC_TOOL_LOAD_TOOL_TABLE
# --> ioControl.cc:reload_tool_number()
# Note: the redundant reload is done for nonrandom toolchanger only
#msg("user_load_spindle_nonran_tc: redundant load for tno=%d"%tno)
mutex.release()
return
TMP = toolline_to_dict(params,['T','P'])
if TMP['P'] != "0": umsg("user_load_spindle_nonran_tc P=%s"%TMP['P'])
if tno == 0: umsg("user_load_spindle_nonran_tc tno=%d"%tno)
D = toolline_to_dict(tools[tno],all_letters)
# save nonran_from_pocket as pocket may have been altered by apply_db_rules()
nonran_from_pocket[tno] = D['P']
if spindle_tool > 0 and spindle_tool != tno: # accrue time for prior tool:
stop_tool_timer(spindle_tool)
nonran_restore_pocket(spindle_tool)
spindle_tool = tno
D['T'] = str(tno)
D['P'] = "0"
start_tool_timer(spindle_tool)
tools[tno] = dict_to_toolline(D,all_letters)
save_tools_to_file(db_savefile,"tno:%3d ( load to spindle)"%tno)
mutex.release()
# 'u' interface command (nonran toolchanger)
def user_unload_spindle_nonran_tc(tno,params):
mutex.acquire() # blocking
global spindle_tool
#msg("user_unload_spindle_nonran_tc spindle_tool=%d restore=%s'u %s'"%
# (spindle_tool,nonran_from_pocket,params))
check_params(tno,params)
if spindle_tool == -1: # no tool in spindle
pass # ignore
else:
TMP = toolline_to_dict(params,['T','P'])
if tno != 0: umsg("user_unload_spindle_nonran_tc tno=%d"%tno)
if TMP['P'] != "0": umsg("user_unload_spindle_nonran_tc P=%s"%TMP['P'])
stop_tool_timer(spindle_tool)
nonran_restore_pocket(spindle_tool)
spindle_tool = -1 # indicate no tool in spindle
save_tools_to_file(db_savefile,"tno:%3d (unload from spindle)(empty)"%tno)
mutex.release()
# 'l' interface command (ran toolchanger)
def user_load_spindle_ran_tc(tno,params):
mutex.acquire() # blocking
global spindle_tool
#msg("user_load_spindle_ran_tc 'l %s' (spindle_tool=%d)"%(params,spindle_tool))
check_params(tno,params)
D = toolline_to_dict(tools[tno],all_letters)
TMP = toolline_to_dict(params,['T','P'])
D['T'] = TMP['T']
D['P'] = TMP['P']
if spindle_tool != -1: # unexpected: no tool in spindle
stop_tool_timer(spindle_tool)
umsg("user_load_spindle_ran_tc spindle_tool=%d"%spindle_tool)
spindle_tool = tno
if tno != 0: start_tool_timer(spindle_tool)
tools[tno] = dict_to_toolline(D,all_letters)
pno = int(D['P'])
txt = "tno:%3d --> pno:%3d ( load to spindle)"%(tno,pno)
if tno==0 and pno==0:
txt = "tno:%3d --> pno:%3d ( load t0 spindle)(empty)"%(tno,pno)
save_tools_to_file(db_savefile,txt)
mutex.release()
# 'u' interface command (ran toolchanger)
def user_unload_spindle_ran_tc(tno,params):
mutex.acquire() # blocking
global spindle_tool
#msg("user_unload_spindle_ran_tc 'u %s' (spindle_tool=%d)"%(params,spindle_tool))
check_params(tno,params)
TMP = toolline_to_dict(params,['T','P'])
if spindle_tool == -1: # no tool in spindle
if tno != 0:
umsg("user_unload_spindle_ran_tc spindle_tool=%d tno=%d"%(spindle_tool,tno))
D = dict()
D['T'] = TMP['T']
D['P'] = TMP['P']
tools[0] = dict_to_toolline(D,['T','P'])
else:
if spindle_tool != 0: stop_tool_timer(spindle_tool)
D = toolline_to_dict(tools[spindle_tool],all_letters)
D['T'] = TMP['T']
D['P'] = TMP['P']
tools[tno] = dict_to_toolline(D,all_letters)
spindle_tool = -1 # indicate no tool in spindle
pno = int(D['P'])
txt="tno:%3d --> pno:%3d (unload from spindle)"%(tno,pno)
if tno==0:
txt="tno:%3d --> pno:%3d (unload from spindle)(notool)"%(tno,pno)
save_tools_to_file(db_savefile,txt)
mutex.release()
#-----------------------------------------------------------
start_db_program() # handle random/nonrandom toolchanger, args
# begin interface to LinuxCNC
debug = 0 # debug var for command line testing
if (len(sys.argv) > 1 and sys.argv[1] == 'debug'): debug = 1
toollist = make_tools(toolno_min,toolno_max)
if random_toolchanger: tooldb_callbacks(user_get_tool,
user_put_tool,
user_load_spindle_ran_tc,
user_unload_spindle_ran_tc)
else: tooldb_callbacks(user_get_tool,
user_put_tool,
user_load_spindle_nonran_tc,
user_unload_spindle_nonran_tc)
tooldb_tools(toollist)
#-----------------------------------------------------------
# start task threads
active_threads=[]
def start_thread(tname):
name = tname.__name__
if name in active_threads:
umsg("start_thread: %s already running"%name)
return
active_threads.append(name)
msg("**Start: %s"%name)
msg("**Active threads:%s"%active_threads)
thd = threading.Thread(target=tname,args=(disconnect_evt,),daemon=0)
thd.start()
return thd
def cmd_loop(*args):
try:
tooldb_loop() # loop forever, use callbacks
except BrokenPipeError:
handle_disconnect(db_savefile)
except Exception as e:
if sys.stdin.isatty():
msg(("Exception=%s"%str(e)))
else: pass # avoid messages at termination
# start cmd_loop thread (primary interface to LinuxCNC):
threading.Thread(target=cmd_loop,args=(disconnect_evt,),daemon=1).start()
# task to demonstrate periodic updates to database
def periodic_task(fini):
if fini.is_set(): return # end task
global start_time, elapsed_time, spindle_tool
while 1:
time.sleep(period_minutes*60)
mutex.acquire() # blocking
if spindle_tool > 0: update_tool_time(spindle_tool)
mutex.release()
threading.Thread(target=periodic_task,args=(disconnect_evt,),daemon=1).start()
#-----------------------------------------------------------
# begin worker demo tasks
def demo_add_or_rm_dbtool(tno):
# remove tool if it is in toollist
# add tool if it is not in toollist
if tno in toollist:
D = toolline_to_dict(tools[tno],tletters)
pno = int(D['P'])
if rm_dbtool(tno):
release_pocket(pno)
return 1 # success
else:
# supply some dummy parameter values based on tno
if add_dbtool(tno,Z=tno/100,D=tno/1000): return 1 # success
return 0 # fail
# tool_update_task: demonstrate addition/removal of toolno.s
def tool_update_task(fini):
ct_max = 2
wait_secs = 5 # interval between adds/removes
begin_tno = 40 # start of extra tool numbers
tno = begin_tno; ct = 0; waited = 0 ; delta_secs = 1
msg("**Begin tool_update_task begin_tno=%d ct_max=%d wait_secs=%d"%
(begin_tno,ct_max,wait_secs))
while ct < ct_max: # loop adding/removing some tool no.s
if fini.is_set(): return # end task
time.sleep(delta_secs); waited += delta_secs
if waited < wait_secs: continue
if not mutex.acquire(timeout=1):
msg("tool_update_task ct=%d waiting for mutex"%ct)
continue
demo_add_or_rm_dbtool(tno)
mutex.release()
ct += 1; waited = 0
tno = begin_tno + ct%n_extra_pockets
active_threads.remove('tool_update_task')
msg("**End tool_update_task ct=%d"%ct)
# tool_modify_task: demonstrate changing a tool parameter
def tool_modify_task(fini):
ct_max = 2
wait_secs = 5 # interval between tool modifications
letter = 'A'
modify_tnos = [15,16]
if not hasattr(tool_modify_task,"ct"): tool_modify_task.ct=0
tno = modify_tnos[tool_modify_task.ct]
tool_modify_task.ct = (tool_modify_task.ct +1)%len(modify_tnos);
ct = 0; waited = 0 ; delta_secs = 1
msg("**Begin tool_modify_task tno=%d letter=%s ct_max=%d wait_secs=%d"%
(tno,letter,ct_max,wait_secs))
while ct < ct_max: # loop adding/removing some tool no.s
if fini.is_set(): return # end task
time.sleep(delta_secs); waited += delta_secs
if waited < wait_secs: continue
waited = 0
if not sync_allowed():
msg("tool_modify_task: DISALLOWED tno=%d (%s)"%(tno,sync_fail_reason))
continue
if not mutex.acquire(timeout=1):
msg("tool_modify_task ct=%d waiting for mutex"%ct)
continue
D = toolline_to_dict(tools[tno],all_letters)
if spindle_tool != tno:
D[letter] = "0.1%02d"%ct # modify letter parameter
tools[tno] = dict_to_toolline(D,all_letters)
save_tools_to_file(db_savefile,"tno:%3d modified param %s=%s"%(tno,letter,D[letter]))
msg("tool_modify_task: tno=%d %s=%s"%(tno,letter,D[letter]));
linuxcnc_tool_sync()
ct += 1
else:
msg("tool_modify_task: DISALLOWED tno=%d (%s)"%(tno,"tool is loaded"))
mutex.release()
active_threads.remove('tool_modify_task')
msg("**End tool_modify_task ct=%d"%ct)
#-----------------------------------------------------------
# start worker tasks
time.sleep(1) # wait for startup messages from LinuxCNC and gui to pass
if cmdline_only: # for gui, start worker threads:
msg("cmdline debug (CTRL-C to exit)")
else:
msg("\n\nNOTE: Terminal command to monitor database file:\n $ watch -c -n 1 cat %s\n"%db_savefile)
thd1 = start_thread(tool_modify_task)
thd1.join() # comment this to make tasks concurrent
thd2 = start_thread(tool_update_task)
#-----------------------------------------------------------
# After all worker threads started, allow signals to start tasks.
# typ: kill -USR[12] $(pidof -x db_nonran.py)
def start_m_thread(*args):start_thread(tool_modify_task)
def start_u_thread(*args):start_thread(tool_update_task)
signal.signal(signal.SIGUSR1, start_m_thread)
signal.signal(signal.SIGUSR2, start_u_thread)
#-----------------------------------------------------------
disconnect_evt.wait()
msg("bye")

View File

@@ -0,0 +1,8 @@
#!/usr/bin/tclsh
package require Tk
wm withdraw .
tk_messageBox \
-title "Placeholder" \
-type ok \
-message "Specify a\n\n\[DISPLAY\]TOOL_EDITOR\n\napplicable for the\n\n\[EMCIO\]DB_PROGRAM"
exit 0

View File

@@ -0,0 +1,17 @@
#INCLUDE base.inc
[EMC]
VERSION = 1.1
MACHINE = db_nonran NONRANDOM toolchanger
[RS274NGC]
PARAMETER_FILE = db_nonran.var
SUBROUTINE_PATH = .
[EMCIO]
RANDOM_TOOLCHANGER = 0
DB_PROGRAM = ./db_nonran.py
# alternate spec using args:
# DB_PROGRAM = ./db_nonran.py --period_minutes=10 /tmp/db_nonran_special
# TOOL_TABLE= is not used with DB_PROGRAM

View File

@@ -0,0 +1 @@
db.py

View File

@@ -0,0 +1,252 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<led>
<halpin>"tool-prepare"</halpin>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" tool-prepare"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<s32>
<halpin>"tool-prep-index"</halpin>
<format>"4d"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</s32>
<label>
<text>"tool-prep-index"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<s32>
<halpin>"tool-prep-number"</halpin>
<format>"4d"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</s32>
<label>
<text>"tool-prep-number"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<s32>
<halpin>"tool-prep-pocket"</halpin>
<format>"4d"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</s32>
<label>
<text>"tool-prep-pocket"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<led>
<halpin>"tool-prepared"</halpin>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" tool-prepared"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<led>
<halpin>"tool-change"</halpin>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" tool-change"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<led>
<halpin>"tool-changed"</halpin>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" tool-changed"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<s32>
<halpin>"tool-number"</halpin>
<format>"4d"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</s32>
<label>
<text>"tool-number"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<s32>
<halpin>"tool-from-pocket"</halpin>
<format>"4d"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</s32>
<label>
<text>"tool-from-pocket"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooldiam"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooldiameter"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.x"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.x"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.y"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.y"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.z"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.z"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.a"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.a"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.b"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.b"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.c"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.c"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.u"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.u"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.v"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.v"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"tooloffset.w"</halpin>
<format>"6.3f"</format>
<width>"6"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
</number>
<label>
<text>"tooloffset.w"</text>
<anchor>"w"</anchor>
</label>
</hbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1,94 @@
# display iocontrol tool prepare/change pins
# and simulate an automatic toolchanger
delsig tool:change-loop # remove basic_sim.tcl loops
delsig tool:prep-loop # remove basic_sim.tcl loops
loadrt oneshot names=prepare_time,prepare_pulse,change_time,change_pulse
addf prepare_time servo-thread
addf prepare_pulse servo-thread
addf change_time servo-thread
addf change_pulse servo-thread
setp prepare_time.width 2.0 # simulate changer
setp prepare_pulse.width 1 # (resets at tool-change)
setp prepare_pulse.rising 0
setp prepare_pulse.falling 1
setp change_time.width 0.5 # simulate changer
setp change_pulse.width 1 # (resets at tool-prepare)
setp change_pulse.rising 0
setp change_pulse.falling 1
#==========================================================
# simulate tool prepare,tool change
net db:tool-prepare <= iocontrol.0.tool-prepare
net db:tool-prepare => change_pulse.reset
net db:tool-prepare => prepare_time.in
net db:tool-prepare => pyvcp.tool-prepare
net db:start_prepare_pulse <= prepare_time.out
net db:start_prepare_pulse => prepare_pulse.in
net db:tool-prepared <= prepare_pulse.out
net db:tool-prepared => iocontrol.0.tool-prepared
net db:tool-prepared => pyvcp.tool-prepared
net db:tool-change <= iocontrol.0.tool-change
net db:tool-change => prepare_pulse.reset
net db:tool-change => change_time.in
net db:tool-change => pyvcp.tool-change
net db:start_change_pulse <= change_time.out
net db:start_change_pulse => change_pulse.in
net db:tool-changed <= change_pulse.out
net db:tool-changed => iocontrol.0.tool-changed
net db:tool-changed => pyvcp.tool-changed
net db:tool-number <= iocontrol.0.tool-number
net db:tool-number => pyvcp.tool-number
net db:tool-prep-index <= iocontrol.0.tool-prep-index
net db:tool-prep-index => pyvcp.tool-prep-index
net db:tool-prep-number <= iocontrol.0.tool-prep-number
net db:tool-prep-number => pyvcp.tool-prep-number
net db:tool-prep-pocket <= iocontrol.0.tool-prep-pocket
net db:tool-prep-pocket => pyvcp.tool-prep-pocket
net db:tool-from-pocket <= iocontrol.0.tool-from-pocket
net db:tool-from-pocket => pyvcp.tool-from-pocket
#==========================================================
# tooloffsets
net db:tooloffset.x <= motion.tooloffset.x
net db:tooloffset.x => pyvcp.tooloffset.x
net db:tooloffset.y <= motion.tooloffset.y
net db:tooloffset.y => pyvcp.tooloffset.y
net db:tooloffset.z <= motion.tooloffset.z
net db:tooloffset.z => pyvcp.tooloffset.z
net db:tooloffset.a <= motion.tooloffset.a
net db:tooloffset.a => pyvcp.tooloffset.a
net db:tooloffset.b <= motion.tooloffset.b
net db:tooloffset.b => pyvcp.tooloffset.b
net db:tooloffset.c <= motion.tooloffset.c
net db:tooloffset.c => pyvcp.tooloffset.c
net db:tooloffset.u <= motion.tooloffset.u
net db:tooloffset.u => pyvcp.tooloffset.u
net db:tooloffset.v <= motion.tooloffset.v
net db:tooloffset.v => pyvcp.tooloffset.v
net db:tooloffset.w <= motion.tooloffset.w
net db:tooloffset.w => pyvcp.tooloffset.w
net db:tooldiam <= halui.tool.diameter
net db:tooldiam => pyvcp.tooldiam

View File

@@ -0,0 +1,21 @@
#INCLUDE base.inc
[EMC]
VERSION = 1.1
MACHINE = db_ran RANDOM toolchanger
[RS274NGC]
PARAMETER_FILE = db_ran.var
SUBROUTINE_PATH = .
[EMCIO]
RANDOM_TOOLCHANGER = 1
DB_PROGRAM = ./db_ran.py
# alternate spec using args:
# DB_PROGRAM = ./db_nonran.py --period_minutes=10 /tmp/db_ran_special
# TOOL_TABLE= is not required for DB_PROGRAM
# For random toolchangers, a file named:
# db_spindle.tbl
# is automatically created to track tool in spindle

View File

@@ -0,0 +1 @@
db.py

View File

@@ -0,0 +1,5 @@
#!/bin/bash
halcmd setp axisui.notifications-clear-info 1
sleep .1
halcmd setp axisui.notifications-clear-info 0
exit 0

View File

@@ -0,0 +1,4 @@
eoffset_demo.ini ----- Basic demo (XYZ)
jwp_z.ini ------------ Jog while paused (Z) demo
dynamic_offsets.ini -- Z offset waveforms demo
opa.ini -------------- Offset per Angle (XZC) demo

View File

@@ -0,0 +1,43 @@
(info: Multiple circles at radius R, use 0 for current val)
;Notes:
; 1) z axis not altered (remains at current z)
; 2) for inside polygon cutting (fnum==0):
; start with rfraction negative
; and gradually increase rfraction to zero as program runs
; multiple circles
; 3) for outside polygon cutting (fnum==1):
; start with rfraction positive
; and gradually decrease to zero as program runs multiple
; circles
;
; Alternate method for polygons:
; 1) use #<radius>=0 and jog to safe starting position
; 2) use #<revs>=1, run program for one revolution
; 3) Run program repeatedly and manually jog x (radius)
; before each program start to increase/decrease
; current radius for inside/outside polygon respectively
o<circles> sub
#<radius> = #1 (= 1 R 0==>current)
#<aspeed> = #2 (= 8 aspeed: RPM)
#<lspeed> = #3 (= 10 lspeed: units/sec)
#<revs> = #4 (= 1 +/- Revolutions)
#<c> = #<_c> ;starting value
#<ctarget> = [#<c> + #<revs> * 360]
#<arate> = [#<aspeed> * 360]
m111 ;clear prior info messages
o<if1> if [#<radius> EQ 0]
#<ref_radius> = #<_x> ;use current x
o<if1> else
#<ref_radius> = #<radius>
f#<lspeed> g1 x#<ref_radius>
o<if1> endif
(debug, ref_radius=#<ref_radius>)
m68 e0 q#<ref_radius> ; set ref_radius for eoffsets
f#<arate> g1 c#<ctarget> ; circles at arate
o<circles> endsub

View File

@@ -0,0 +1,33 @@
#<xmax> = 9
#<ymax> = 4
#<zmax> = 3
#<rct> = 100
#<feed> = 100
#<x1> = #<xmax>
#<y1> = 0
#<z1> = [#<zmax> * 0.5]
#<x2> = #<xmax>
#<y2> = #<ymax>
#<z2> = 0
#<x3> = 0
#<y3> = #<ymax>
#<z3> = #<zmax>
m111 ;clear notifications
g61
g0 x0 y0 z0
o<rpt> repeat [#<rct>]
f #<feed>
g0 x 0 y 0 z 0
g1 x #<x1> y #<y1> z #<z1>
g1 x #<x2> y #<y2> z #<z2>
g1 x #<x3> y #<y3> z #<z3>
g1 x 0 y 0 z 0
o<rpt> endrepeat
m111 ;clear notifications
m2

View File

@@ -0,0 +1,27 @@
THREAD servo-thread
MAXCHAN 8
HMULT 4
HZOOM 1
HPOS 5.186916e-01
CHAN 1
SIG E:z-offset
VSCALE -1
VPOS 0.398564
VOFF 0.000000e+00
CHAN 2
SIG G:waveform
VSCALE -1
VPOS 0.398564
VOFF 0.000000e+00
CHAN 4
SIG G:reset
VSCALE 2
VPOS 0.961120
VOFF 0.000000e+00
CHAN 3
PIN joint.2.motor-pos-cmd
VSCALE 0
VPOS 0.900000
VOFF 0.000000e+00
TMODE 0
RMODE 0

View File

@@ -0,0 +1,83 @@
[APPLICATIONS]
# delay because some items are done in postgui
DELAY = 5
APP = halscope -i dynamic_offsets.halscope
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl -no_sim_spindle
POSTGUI_HALFILE = dynamic_offsets_panel.hal
[EMC]
MACHINE = Dynamic External Offsets
VERSION = 1.1
[DISPLAY]
PYVCP = dynamic_offsets_panel.xml
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_LINEAR_VELOCITY = 2
OPEN_FILE = ./dyn_demo.ngc
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
USER_M_PATH = .
PARAMETER_FILE = sim.var
[EMCMOT]
EMCMOT = motmod
SERVO_PERIOD = 1000000
[TRAJ]
COORDINATES = XYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[KINS]
JOINTS = 3
KINEMATICS = trivkins coordinates=XYZ
[AXIS_X]
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
MIN_LIMIT = -1
MAX_LIMIT = 10
[AXIS_Y]
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
MIN_LIMIT = -1
MAX_LIMIT = 10
[AXIS_Z]
# Note:give half to external_offsets:
OFFSET_AV_RATIO = 0.5
# Note: modified in pyvcp panel:
MAX_VELOCITY = 2
MAX_ACCELERATION = 50
MIN_LIMIT = -5
MAX_LIMIT = 5
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 50

View File

@@ -0,0 +1,32 @@
dynamic_offsets
A sinewave is applied to the Z coordinate external offset
The waveform amplitdude and frequency are set by pyvcp panel spinboxes.
The Z coordinate max acceleration and max velocity settings (from the ini file) can be modified with pyvcp panel spinboxes.
Usage:
1) Estop OFF (F1)
2) Machine ON (F2)
3) HOME All (Ctrl-Home)
4) A halscope application is started to
show the offset waveforms and the
z coordinate response
5) Enable the dynamic offset waveform
with the panel 'Z enable' checkbox
5) Use the panel to adjust:
Waveform: amplitude, frequency
Z Coordinate: max accel, max vel
Notes:
The dynamic waveform is applied with and without
running a program.
MDI cannot be started with non-zero external
offsets -- disable the Z offsets and toggle
the machine On/Off to zero offsets.
Changes to the Z max accel, max vel are not
made while a program or mdi move is in progress.

View File

@@ -0,0 +1,37 @@
dynamic_offsets
Se aplica una onda sinusoidal al desplazamiento externo de la coordenada Z
El amplitud y frecuencia de la forma de onda se establecen mediante spinboxes de un panel pyvcp.
La configuración de aceleración máxima y velocidad máxima de coordenadas Z (del archivo ini) se puede modificar con los spinboxes del panel pyvcp.
Uso:
1) Estop OFF (F1)
2) Máquina ON (F2)
3) HOME Todo (Ctrl-Inicio)
4) Se inicia una aplicación de halscope
para mostrar los offsets de formas
de onda y la respuesta de
la coordenada z
5) Habilitar la forma de onda de
offset dinamico con la casilla 'Habilitar Z'
del panel
6) Use el panel para ajustar:
Forma de onda: amplitud, frecuencia
Coordenada Z: max accel, max vel
Notas:
La forma de onda dinámica se aplica
con y sin ejecutar un programa.
MDI no puede iniciarse con offsets
externos que no sean cero: deshabilite
los offsets Z y active/desactive la
máquina para offsets cero.
Los cambios en max accel y max vel
de Z no se realizan mientras
un programa o movimiento mdi esté
en progreso.

View File

@@ -0,0 +1,46 @@
loadrt siggen names=gen
loadrt scale names=scalea
loadrt conv_float_s32 names=cvt
loadrt not names=nota
loadrt or2 names=or2a
addf gen.update servo-thread
addf scalea servo-thread
addf cvt servo-thread
addf nota servo-thread
addf or2a servo-thread
setp gen.offset 0.0
# scaling -----------------------------------------------------------
# these should be reciprocals:
# 1 unit (inch) --> 10000 counts
setp axis.z.eoffset-scale 0.0001
setp scalea.gain 10000
net E:amplitude <= pyvcp.gen-amplitude => gen.amplitude
net E:frequency <= pyvcp.gen-frequency => gen.frequency
# can also use sawtooth (others inappropriate on a reset)
net G:waveform <= gen.sine => scalea.in
net G:swaveform <= scalea.out => cvt.in
net G:counts <= cvt.out => axis.z.eoffset-counts
net E:enable <= pyvcp.z-enable => axis.z.eoffset-enable
net E:enable => nota.in
net E:disable <= nota.out => or2a.in1
net E:z-offset <= axis.z.eoffset => pyvcp.z-offset-f
net E:limited <= motion.eoffset-limited => pyvcp.eoffset-limited
net E:active <= motion.eoffset-active => pyvcp.eoffset-active
net E:reset <= pyvcp.reset => or2a.in0
net E:ini-accel <= pyvcp.ini-accel => ini.z.max_acceleration
net E:ini-vel <= pyvcp.ini-vel => ini.z.max_velocity
net G:reset <= or2a.out => axis.z.eoffset-clear
net G:reset => gen.reset

View File

@@ -0,0 +1,166 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<label>
<relief>"ridge"</relief>
<bd>4</bd>
<text>"Z-Eoffset"</text>
<font>"bold"</font>
</label>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<checkbutton>
<anchor>"w"</anchor>
<halpin>"z-enable"</halpin>
<text>"Z enable offsets"</text>
<initval>0</initval>
</checkbutton>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-limited"</halpin>
<size>15</size>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Offset Limited"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-active"</halpin>
<size>15</size>
<on_color>"gold"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" OffsetActive"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"z-offset-f"</halpin>
<format>"+8.4f"</format>
<width>"13"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<label>
<relief>"ridge"</relief>
<bd>4</bd>
<text>"INI A/V"</text>
<font>"bold"</font>
</label>
</vbox>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<anchor>"w"</anchor>
<text>"Accel:"</text>
<font>"monospace,bold"</font>
</label>
<spinbox>
<halpin>"ini-accel"</halpin>
<width>6</width>
<font>"bold"</font>
<format>"8.2f"</format>
<max_>386.0</max_>
<min_>1</min_>
<resolution>1.0</resolution>
<initval>40</initval>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>" Vel:"</text>
<font>"monospace,bold"</font>
</label>
<spinbox>
<halpin>"ini-vel"</halpin>
<width>6</width>
<font>"bold"</font>
<format>"8.2f"</format>
<min_>0.2</min_>
<max_>100</max_>
<resolution>.1</resolution>
<initval>2</initval>
<param_pin>1</param_pin>
</spinbox>
</hbox>
</vbox>
<label>
<text>"Generator"</text>
<relief>"ridge"</relief>
<bd>4</bd>
<font>"bold"</font>
</label>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<anchor>"w"</anchor>
<text>" Freq:"</text>
<font>"monospace,bold"</font>
</label>
<spinbox>
<halpin>"gen-frequency"</halpin>
<width>6</width>
<font>"bold"</font>
<format>"8.2f"</format>
<max_>10.0</max_>
<min_>0.0</min_>
<resolution>0.1</resolution>
<initval>1.0</initval>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>" Hgt:"</text>
<font>"monospace,bold"</font>
</label>
<spinbox>
<halpin>"gen-amplitude"</halpin>
<width>6</width>
<font>"bold"</font>
<format>"8.2f"</format>
<min_>0.0</min_>
<max_>2.0</max_>
<resolution>0.1</resolution>
<initval>0.2</initval>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<button>
<halpin>"reset"</halpin>
<bd>3</bd>
<width>1</width>
<text>"ResetGen"</text>
<font>"bold",10</font>
</button>
</vbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1 @@
T1 P1 D0.125 Z0.5

View File

@@ -0,0 +1,16 @@
#---------------------------------------------------------------
# note: axis.L.eoffset-enables are controlled by pyvcp panel
# external offset input scale:
setp axis.x.eoffset-scale 0.1
setp axis.y.eoffset-scale 0.1
setp axis.z.eoffset-scale 0.1
#---------------------------------------------------------------
# convenience signals for use with eoffsets_monitor.tcl:
net e:xcounts => axis.x.eoffset-counts
net e:ycounts => axis.y.eoffset-counts
net e:zcounts => axis.z.eoffset-counts
#---------------------------------------------------------------
# for pyvcp panel
net e:limited <= motion.eoffset-limited

View File

@@ -0,0 +1,104 @@
# Notes:
# 1) [AXIS_n]OFFSET_AV_RATIO= controls external offsets a,v
# Allowed values are 0.0 <= OFFSET_AV_RATIO <= 0.9
# Value of 0.0 disables external offsets
# Disallowed values are superseded with msg to stdout
# 2) Immediate homing herein
# ([JOINT_*]HOME_SEQUENCE=0, other HOME_* items omitted)
# 3) uncomment [JOINT_0]HOME_SEARCH_VEL,HOME_LATCH_VEL
# to demonstrate non-zero joint.0.motor-offset
[APPLICATIONS]
APP = sim_pin --title "MPG Simulator" \
e:xcounts \
e:ycounts \
e:zcounts
# make sure [xyz]:ecounts are zero if machine off:
APP = eoffsets_monitor.tcl
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl -no_use_hal_manualtoolchange
HALFILE = eoffsets.hal
POSTGUI_HALFILE = eoffsets_panel.hal
[EMC]
MACHINE = External Offsets Demo
VERSION = 1.1
[DISPLAY]
PYVCP = eoffsets_panel.xml
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_LINEAR_VELOCITY = 2
OPEN_FILE = ./eoffsets.ngc
TKPKG = Ngcgui 1.0
NGCGUI_FONT = Helvetica -12 normal
NGCGUI_SUBFILE = queuebuster.ngc
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
SUBROUTINE_PATH = .
USER_M_PATH = .
PARAMETER_FILE = sim.var
[EMCIO]
TOOL_TABLE = eoffset.tbl
[EMCMOT]
EMCMOT = motmod
SERVO_PERIOD = 1000000
[TRAJ]
COORDINATES = XYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[KINS]
JOINTS = 3
KINEMATICS = trivkins coordinates=XYZ
[AXIS_X]
OFFSET_AV_RATIO = 0.2
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
MIN_LIMIT = -0.1
MAX_LIMIT = 10
[AXIS_Y]
OFFSET_AV_RATIO = 0.2
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
MIN_LIMIT = -0.1
MAX_LIMIT = 5
[AXIS_Z]
OFFSET_AV_RATIO = 0.2
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
MIN_LIMIT = -1
MAX_LIMIT = 1
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20

View File

@@ -0,0 +1,35 @@
#<xmax> = 9
#<ymax> = 4
#<zdepth> = 0
#<feed> = 20
#<x1> = [0.25 * #<xmax>]
#<y1> = [0.66 * #<ymax>]
#<z1> = 0
#<x2> = [0.50 * #<xmax>]
#<y2> = 0
#<z2> = -.5
#<x3> = [0.75 * #<xmax>]
#<y3> = 0
#<z3> = 0
#<x4> = #<x3>
#<y4> = #<y1>
#<z4> = 0
m111 ;clear notifications
g61
g0x0y0z0
f #<feed>
g1 x #<x1> y #<y1> z #<z1>
g1 x #<x2> y #<y2> z #<z2>
g1 x #<x3> y #<y3> z #<z3>
g1 x #<x4> y #<y4> z #<z4>
g1 x #<xmax> y #<ymax>
g0x0y0z0
m111 ;clear notifications
m2

View File

@@ -0,0 +1,26 @@
eoffsets.ini
Usage:
1) Estop OFF (F1)
2) Machine ON (F2)
3) HOME All (Ctrl-Home)
4) Explore external offset functionality
using the sim_pin gui to alter the
per-axis hal pins:
e:xcounts (sig to => axis.x.eoffset-counts)
e:ycounts (sig to => axis.y.eoffset-counts)
e:zcounts (sig to => axis.z.eoffset-counts)
e:clearall (sig to => axis.*.eoffset-clear)
-------------------------------------------
Note: The external offset interface is
similar to the interface for wheel jogging:
Input hal pins:
axis.L.eoffset-enable (bit)
axis.L.eoffset-clear (bit)
axis.L.eoffset-scale (float)
axis.L.eoffset-counts (s32)
Requested offset == counts*scale

View File

@@ -0,0 +1,26 @@
eoffsets.ini
Uso:
1) Estop OFF (F1)
2) Máquina ON (F2)
3) HOME Todo (Ctrl-Home)
4) Explorar funcionalidad de offset
externos usando gui sim_pin para
alterar los pines hal por eje:
e:xcounts (señal a => axis.x.eoffset-counts)
e:ycounts (señal a=> axis.y.eoffset-counts)
e:zcounts (señal a=> axis.z.eoffset-counts)
e:clearall (señal a=> axis.*.eoffset-clear)
-------------------------------------------
Note: El interface de offsets externos es
similar al de jog por volante:
Pines Input hal:
axis.L.eoffset-enable (bit)
axis.L.eoffset-clear (bit)
axis.L.eoffset-scale (float)
axis.L.eoffset-counts (s32)
Offset solicitado == counts*scale

View File

@@ -0,0 +1,27 @@
#!/usr/bin/tclsh
# script to ensure e:[xyz]counts are zero if machine off
package require Hal
set ::prog [file tail [info script]]
set ::periodic_delay_ms 200
proc monitor_ecounts {} {
catch {after cancel $::a_id}
if { ![hal getp halui.machine.is-on]
&& ( 0 != [hal gets e:xcounts]
|| 0 != [hal gets e:ycounts]
|| 0 != [hal gets e:zcounts]) } {
# handle deferred connection to signal
if [catch { hal sets e:xcounts 0
hal sets e:ycounts 0
hal sets e:zcounts 0
} msg] {
puts stderr msg=$msg
puts stderr "$::prog exiting"
exit 1
}
}
set ::a_id [after $::periodic_delay_ms monitor_ecounts]
}
monitor_ecounts
vwait ::forever

View File

@@ -0,0 +1,49 @@
# existing (basic_sim.tcl) signals for display:
net J0:pos-cmd => pyvcp.motor-pos-cmd.0-f
net J1:pos-cmd => pyvcp.motor-pos-cmd.1-f
net J2:pos-cmd => pyvcp.motor-pos-cmd.2-f
# motor-offset (display only):
net E:motor-offset.0 <= joint.0.motor-offset => pyvcp.motor-offset.0-f
net E:motor-offset.1 <= joint.1.motor-offset => pyvcp.motor-offset.1-f
net E:motor-offset.2 <= joint.2.motor-offset => pyvcp.motor-offset.2-f
# controls for demo (from sim_pin setp, no pin source):
# note these are teleop pos-cmds (not coord motion)
net E:x-pos-cmd => axis.x.pos-cmd => pyvcp.x-pos-cmd-f
net E:y-pos-cmd => axis.y.pos-cmd => pyvcp.y-pos-cmd-f
net E:z-pos-cmd => axis.z.pos-cmd => pyvcp.z-pos-cmd-f
# eoffset (display only):
net E:x-offset <= pyvcp.x-offset-f => axis.x.eoffset
net E:y-offset <= pyvcp.y-offset-f => axis.y.eoffset
net E:z-offset <= pyvcp.z-offset-f => axis.z.eoffset
# offset-request (display only):
net E:x-offset-request <= axis.x.eoffset-request
net E:x-offset-request => pyvcp.x-offset-request-f
net E:y-offset-request <= axis.y.eoffset-request
net E:y-offset-request => pyvcp.y-offset-request-f
net E:z-offset-request <= axis.z.eoffset-request
net E:z-offset-request => pyvcp.z-offset-request-f
# enables
net E:x-enable <= pyvcp.x-enable => axis.x.eoffset-enable
net E:y-enable <= pyvcp.y-enable => axis.y.eoffset-enable
net E:z-enable <= pyvcp.z-enable => axis.z.eoffset-enable
# scale factors
net E:x-scale <= pyvcp.x-scale => axis.x.eoffset-scale
net E:y-scale <= pyvcp.y-scale => axis.y.eoffset-scale
net E:z-scale <= pyvcp.z-scale => axis.z.eoffset-scale
# clears
net E:clearall <= pyvcp.clearall
net E:clearall => axis.x.eoffset-clear
net E:clearall => axis.y.eoffset-clear
net E:clearall => axis.z.eoffset-clear
# pyvcp led:
net e:limited <= motion.eoffset-limited => pyvcp.limited

View File

@@ -0,0 +1,382 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<label>
<text>"Motor-pos-cmd"</text>
<font>"bold"</font>
</label>
</vbox>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<text>"J0:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-pos-cmd.0-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"J1:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-pos-cmd.1-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"J2:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-pos-cmd.2-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"cyan"</fg>
<font>"bold"</font>
</number>
</hbox>
</vbox>
<vbox>
<label>
<text>"Motor-offset"</text>
<font>"bold"</font>
</label>
</vbox>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<text>"J0:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-offset.0-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"white"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"J1:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-offset.1-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"white"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"J2:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"motor-offset.2-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"white"</fg>
<font>"bold"</font>
</number>
</hbox>
</vbox>
<vbox>
<label>
<text>"Axis-pos-cmd"</text>
<font>"bold"</font>
</label>
</vbox>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<text>" X:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"x-pos-cmd-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"greenyellow"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>" Y:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"y-pos-cmd-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"greenyellow"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>" Z:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"z-pos-cmd-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"greenyellow"</fg>
<font>"bold"</font>
</number>
</hbox>
</vbox>
<vbox>
<label>
<text>"Eoffsets(act/req)"</text>
<font>"bold"</font>
</label>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<padx>5</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"limited"</halpin>
<size>15</size>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Offset Limited"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<text>"Xa:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"x-offset-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"Ya:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"y-offset-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"Za:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"z-offset-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"Xr:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"x-offset-request-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"orange"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"Yr:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"y-offset-request-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"orange"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<text>"Zr:"</text>
<font>"monospace"</font>
<anchor>"w"</anchor>
</label>
<number>
<halpin>"z-offset-request-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"orange"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>"Xenable"</text>
</label>
<checkbutton>
<anchor>"w"</anchor>
<halpin>"x-enable"</halpin>
<text>""</text>
<initval>0</initval>
</checkbutton>
<label>
<anchor>"w"</anchor>
<text>""</text>
<padx>0</padx>
</label>
<spinbox>
<halpin>"x-scale"</halpin>
<min_> 0.1</min_>
<max_>10.0</max_>
<width>4</width>
<initval>0.1</initval>
<resolution>0.1</resolution>
<format>"4.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>"Yenable"</text>
</label>
<checkbutton>
<anchor>"w"</anchor>
<halpin>"y-enable"</halpin>
<text>""</text>
<padx>0</padx>
<initval>0</initval>
</checkbutton>
<label>
<anchor>"w"</anchor>
<text>""</text>
</label>
<spinbox>
<halpin>"y-scale"</halpin>
<min_> 0.1</min_>
<max_>10.0</max_>
<width>4</width>
<initval>0.1</initval>
<resolution>0.1</resolution>
<format>"4.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>"Zenable"</text>
</label>
<checkbutton>
<anchor>"w"</anchor>
<halpin>"z-enable"</halpin>
<text>""</text>
<padx>0</padx>
<initval>0</initval>
</checkbutton>
<label>
<anchor>"w"</anchor>
<text>""</text>
</label>
<spinbox>
<halpin>"z-scale"</halpin>
<min_> 0.1</min_>
<max_>10.0</max_>
<width>4</width>
<initval>0.1</initval>
<resolution>0.1</resolution>
<format>"4.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<button>
<halpin>"clearall"</halpin>
<bd>3</bd>
<width>1</width>
<text>"ClearOffsets"</text>
<font>"bold",10</font>
</button>
</vbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1,86 @@
# Notes:
# 1) [AXIS_n]OFFSET_AV_RATIO= controls external offsets a,v
# Allowed values are 0.0 <= OFFSET_AV_RATIO <= 0.9
# Value of 0.0 disables external offsets
# Disallowed values are superseded with msg to stdout
# 2) Immediate homing herein
# ([JOINT_*]HOME_SEQUENCE=0, other HOME_* items omitted)
# 3) uncomment [JOINT_0]HOME_SEARCH_VEL,HOME_LATCH_VEL
# to demonstrate non-zero joint.0.motor-offset
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl
POSTGUI_HALFILE = jwp_z_panel.hal
[EMC]
MACHINE = Jog-While-Pause Z Demo
VERSION = 1.1
[DISPLAY]
PYVCP = jwp_z_panel.xml
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_LINEAR_VELOCITY = 2
OPEN_FILE = ./jwp_z.ngc
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
USER_M_PATH = .
PARAMETER_FILE = sim.var
[EMCMOT]
EMCMOT = motmod
SERVO_PERIOD = 1000000
[TRAJ]
COORDINATES = XYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[KINS]
JOINTS = 3
KINEMATICS = trivkins coordinates=XYZ
[AXIS_X]
MIN_LIMIT = -1
MAX_LIMIT = 11
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[AXIS_Y]
MIN_LIMIT = -1
MAX_LIMIT = 5
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[AXIS_Z]
# Note: low OFFSET_AV_RATIO:
OFFSET_AV_RATIO = 0.05
MIN_LIMIT = -1
MAX_LIMIT = 1
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 2
MAX_ACCELERATION = 20

View File

@@ -0,0 +1,35 @@
#<xmax> = 10
#<ymax> = 5
#<zsafe> = 0.5
#<feed> = 100
#<x1> = [0.25 * #<xmax>]
#<y1> = [0.66 * #<ymax>]
#<x2> = [0.50 * #<xmax>]
#<y2> = [0.33 * #<ymax>]
#<x3> = [0.75 * #<xmax>]
#<y3> = [0.33 * #<ymax>]
m111 ;clear notifications
g61
g0 x0 y0 z#<zsafe>
(debug, Enter offsets only when paused, s to continue)
m0
m111
f #<feed>
g0 z0
g1 x #<x1> y #<y1>
g1 x #<x2> y #<y2>
g1 x #<x3> y #<y3>
g1 x #<xmax> y #<ymax>
g0 z#<zsafe>
(debug, Program End: Clear offsets, s to continue)
m0
g0 x0 y0
m111 ;clear notifications
m2

View File

@@ -0,0 +1,16 @@
jwp_z.ini
Usage:
1) Estop OFF (F1)
2) Machine ON (F2)
3) HOME All (Ctrl-Home)
4) Run program (R)
5) initial pause:
adjust z offset (+Incr/-Decr)
6) Resume (S)
7) Pause (P)
adjust z offset (+Incr/-Decr)
8) Resume (R)
9) Final pause
return offset to zero (+Incr/-Decr)
or Clear

View File

@@ -0,0 +1,16 @@
jwp_z.ini
Uso:
1) Estop OFF (F1)
2) Máquina ON (F2)
3) HOME Todo (Ctrl-Home)
4) Correr programa (R)
5) pausa inicial:
ajuste z offset (+Incr/-Decr)
6) Reanudar (S)
7) Pausa (P)
ajuste z offset (+Incr/-Decr)
8) Reanudar (R)
9) Pausa final
volver offset a zero (+Incr/-Decr)
o borrar

View File

@@ -0,0 +1,17 @@
loadrt updown names=zctr
addf zctr servo-thread
net E:z-plus <= pyvcp.z-plus => zctr.countup
net E:z-minus <= pyvcp.z-minus => zctr.countdown
net E:z-counts <= zctr.count => axis.z.eoffset-counts
net E:z-scale <= pyvcp.z-scale => axis.z.eoffset-scale
net E:z-offset <= axis.z.eoffset => pyvcp.z-offset-f
net E:limited <= motion.eoffset-limited => pyvcp.limited
net E:active <= motion.eoffset-active => pyvcp.eoffset-active
net E:paused <= halui.program.is-paused => axis.z.eoffset-enable
net E:paused => pyvcp.paused
net E:clearall <= pyvcp.clearall
net E:clearall => axis.x.eoffset-clear
net E:clearall => axis.y.eoffset-clear
net E:clearall => axis.z.eoffset-clear

View File

@@ -0,0 +1,112 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<label>
<text>"Eoffsets"</text>
<font>"bold"</font>
</label>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"paused"</halpin>
<size>15</size>
<on_color>"springgreen"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Paused"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"limited"</halpin>
<size>15</size>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Offset Limited"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-active"</halpin>
<size>15</size>
<on_color>"gold"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" OffsetActive"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<number>
<halpin>"z-offset-f"</halpin>
<format>"+8.4f"</format>
<width>"13"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>"Scale:"</text>
<font>"bold"</font>
</label>
<spinbox>
<halpin>"z-scale"</halpin>
<min_>0.0</min_>
<max_>1.0</max_>
<width>6</width>
<initval>0.01</initval>
<resolution>0.01</resolution>
<format>"8.2f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
</hbox>
<button>
<halpin>"z-plus"</halpin>
<text>"+ Incr"</text>
<bd>4</bd>
<font>"bold",10</font>
</button>
<button>
<halpin>"z-minus"</halpin>
<bd>4</bd>
<width>1</width>
<text>"- Decr"</text>
<font>"bold",10</font>
</button>
<button>
<halpin>"clearall"</halpin>
<bd>4</bd>
<width>1</width>
<text>"Clear"</text>
<font>"bold",10</font>
</button>
</vbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1,47 @@
loadrt eoffset_per_angle names=xo
setp xo.k 10000
setp xo.fnum 2
addf xo servo-thread
#-----------------------------------------------------------
# required standard connections to xo
net E:angle <= axis.c.pos-cmd
net E:angle => xo.angle
net E:is-on <= halui.machine.is-on
net E:is-on => xo.is-on
net E:active <= motion.eoffset-active
net E:active => xo.active
net E:radius-ref <= motion.analog-out-00
net E:radius-ref => xo.radius-ref
#-----------------------------------------------------------
# required standard connections from xo
net E:eoffset-enable <= xo.enable-out
net E:eoffset-enable => axis.x.eoffset-enable
net E:clear <= xo.clear
net E:clear => axis.x.eoffset-clear
net E:scale <= xo.kreciprocal
net E:scale => axis.x.eoffset-scale
net E:kcounts <= xo.kcounts
net E:kcounts => axis.x.eoffset-counts
#-----------------------------------------------------------
# signals with sink elsewhere (sim: opa_panel.hal)
net E:x-eoffset <= axis.x.eoffset
# convenience pin, use as required:
net E:is-off <= xo.is-off
#-----------------------------------------------------------
# signals with source elsewhere (sim: opa_panel.hal)
net E:enable-in => xo.enable-in
net E:fnum => xo.fnum
net E:rfraction => xo.rfraction
net E:fmult => xo.fmult
net E:start-angle => xo.start-angle

View File

@@ -0,0 +1,87 @@
[APPLICATIONS]
DELAY = 3
# For assessing system accel/vel:
# (particularly when using func3 square wave modulation)
APP = sim_pin ini.x.max_acceleration ini.x.max_velocity
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl
HALFILE = opa.hal
POSTGUI_HALFILE = opa_panel.hal
[EMC]
MACHINE = External Offset(X) per Angle(C) Demo
VERSION = 1.1
[DISPLAY]
PYVCP = opa_panel.xml
DISPLAY = axis
OPEN_FILE = opa_demo.ngc
GEOMETRY = !CXZ
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_LINEAR_VELOCITY = 2
MAX_ANGULAR_VELOCITY = 60
TKPKG = Ngcgui 1.0
NGCGUI_FONT = Helvetica -12 normal
NGCGUI_SUBFILE = circles.ngc
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
SUBROUTINE_PATH = .
USER_M_PATH = .
PARAMETER_FILE = sim.var
[EMCIO]
TOOL_TABLE = eoffset.tbl
[EMCMOT]
EMCMOT = motmod
SERVO_PERIOD = 1000000
[TRAJ]
COORDINATES = XZC
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[KINS]
JOINTS = 3
KINEMATICS = trivkins coordinates=XZC
[AXIS_X]
OFFSET_AV_RATIO = 0.5
MAX_VELOCITY = 5
# increase MAX_ACCELERATION to improve
# waveform tracking:
MAX_ACCELERATION = 50
[AXIS_Z]
MAX_VELOCITY = 5
MAX_ACCELERATION = 10
[AXIS_C]
MAX_VELOCITY = 60
MAX_ACCELERATION = 600
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 5
MAX_ACCELERATION = 50
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 5
MAX_ACCELERATION = 10
[JOINT_2]
TYPE = ANGULAR
HOME_SEQUENCE = 0
MAX_VELOCITY = 60
MAX_ACCELERATION = 600

View File

@@ -0,0 +1,41 @@
opa.ini Offset per Angle
Demonstrates external offsets using the
hal component: eoffset_per_angle.
A simulation for an XZC machine offsets
the transverse (X) coordinate based on
the rotary coordinate (C) angle.
($ man eoffset_per_angle for more info)
Usage:
1) Estop OFF (F1)
2) Machine ON (F2)
3) HOME All (Ctrl-Home)
4) Run (R)
5) Enable/Disable offsets using pyvcp
panel On/Off buttons
6) Select parameters:
Astart ----- starting angle
fmult ------ frequency multiplier
rfraction -- amplitude (radius fraction)
func ------- function
0 polygon (inside)
1 polygon (outside)
2 sine wave
3 square wave
Notes:
1) The effective radius used for computing
external offsets is set using the
motion.analog-out-00 hal pin and
controlled by the sample program or
by MDI ( M68 E0 Q some_radius_value )
2) Offset fidelity is dependent upon inifile
settings for [AXIS_X] items:
MAX_VELOCITY
MAX_ACCELERATION
OFFSET_AV_RATIO

View File

@@ -0,0 +1,15 @@
; opa_demo.ngc:
; invoke subroutine circles.ngc for multiple circles (#<revs>)
; with:
; x = #<radius>
; z = #<_z>
#<radius> = 1
#<z> = #<_z> ; current value
#<aspeed> = 8 ; angular speed (RPM)
#<lspeed> = 10 ; linear speed (units/minute)
#<revs> = 100
g0 x#<radius> z#<z>
o<circles> call [#<radius>][#<aspeed>][#<lspeed>][#<revs>]
m2

View File

@@ -0,0 +1,45 @@
opa.ini Offset por Ángulo
Demuestra offsets externos utilizando
el componente hal: eoffset_per_angle.
Una simulación para una máquina XZC
desplaza la coordenada transversal
(X) basada en el ángulo de la
coordenada giratoria (C).
($ man eoffset_per_angle)
Uso:
1) Estop OFF (F1)
2) Máquina ON (F2)
3) HOME Todo (Ctrl-Inicio)
4) Ejecutar (R)
5) Activar/Desactivar offsets usando
los botones de encendido/apagado
del panel pyvcp
6) Seleccionar parámetros:
Ainicio --- ángulo de inicio
fmult ----- multiplicador de frecuencia
rfracción - amplitud (fracción de radio)
func ------ función
0 polígono (dentro)
1 polígono (exterior)
2 ondas sinusoidales
Onda cuadrada 3
Notas:
1) El radio efectivo utilizado para
calcular los offsets externos se
establece utilizando el pin de
movimiento motion.analog-out-00
y controlado por el programa de
muestra o por MDI (M68 E0 Q valor_radio)
2) La fidelidad del offset depende de
la configuración de archivos para
los elementos de [AXIS_X]:
MAX_VELOCITY
MAX_ACCELERATION
OFFSET_AV_RATIO

View File

@@ -0,0 +1,31 @@
loadrt flipflop names=ff1
addf ff1 servo-thread
setp ff1.data 0
net P:wave-start <= pyvcp.wave-start
net P:wave-start => ff1.set
net P:wave-stop <= pyvcp.wave-stop
net P:wave-stop => ff1.clk
net P:limited <= motion.eoffset-limited
net P:limited => pyvcp.eoffset-limited
net P:paused <= halui.program.is-paused
net P:paused => pyvcp.paused
#----------------------------------------------
# signals created in opa.hal
net E:enable-in <= ff1.out
net E:enable-in => pyvcp.waveon
net E:fnum <= pyvcp.fnum-i
net E:rfraction <= pyvcp.rfraction
net E:fmult <= pyvcp.fmult
net E:start-angle <= pyvcp.start-angle
net E:is-off => ff1.reset
net E:eoffset-enable => pyvcp.eoffset-enable
net E:x-eoffset => pyvcp.x-offset-f
net E:radius-ref => pyvcp.radius-ref
net E:active => pyvcp.eoffset-active

View File

@@ -0,0 +1,231 @@
<?xml version='1.0' encoding='UTF-8'?>
<pyvcp>
<vbox>
<relief>"ridge"</relief>
<bd>5</bd>
<label>
<text>"X Offset"</text>
<font>"bold"</font>
</label>
<label>
<text>"per"</text>
<font>"bold"</font>
</label>
<label>
<text>"C Angle"</text>
<font>"bold"</font>
</label>
<vbox>
<relief>"sunken"</relief>
<bd>3</bd>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
<text>"o"</text>
</label>
<number>
<halpin>"x-offset-f"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"gold"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
<text>"r"</text>
</label>
<number>
<halpin>"radius-ref"</halpin>
<format>"+10.4f"</format>
<width>"10"</width>
<bg>"black"</bg>
<fg>"skyblue"</fg>
<font>"bold"</font>
</number>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-limited"</halpin>
<size>15</size>
<on_color>"red"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Offset Limit"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-enable"</halpin>
<size>15</size>
<on_color>"gold"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" OffsetOn"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"eoffset-active"</halpin>
<size>15</size>
<on_color>"gold"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" OffsetActive"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"paused"</halpin>
<size>15</size>
<on_color>"springgreen"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" Paused"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<label>
<padx>0</padx>
<font>"monospace"</font>
</label>
<led>
<halpin>"waveon"</halpin>
<size>15</size>
<on_color>"cyan"</on_color>
<off_color>"#d9d9d9"</off_color>
</led>
<label>
<text>" WaveOn"</text>
<anchor>"w"</anchor>
</label>
</hbox>
<hbox>
<button>
<halpin>"wave-start"</halpin>
<text>"On"</text>
<width>"3"</width>
<bd>3</bd>
</button>
<button>
<halpin>"wave-stop"</halpin>
<text>"Off"</text>
<width>"3"</width>
<bd>3</bd>
</button>
</hbox>
<hbox>
<spinbox>
<halpin>"start-angle"</halpin>
<min_>-90.0</min_>
<max_>90.0</max_>
<width>4</width>
<initval>0</initval>
<resolution>5</resolution>
<format>"3.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"Astart"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"fmult"</halpin>
<min_>1.0</min_>
<max_>20.0</max_>
<width>4</width>
<initval>6</initval>
<resolution>1</resolution>
<format>"3.1f"</format>
<font>"bold"</font>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"fmult"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"rfraction"</halpin>
<min_>-0.9</min_>
<max_>0.9</max_>
<width>4</width>
<initval>0.0</initval>
<resolution>.1</resolution>
<format>"3.1f"</format>
<font>"bold"</font>
<param_pin>1</param_pin>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"rfraction"</text>
<font>"bold"</font>
</label>
</hbox>
<hbox>
<label>
<anchor>"w"</anchor>
<text>" fnum:"</text>
<font>"bold"</font>
</label>
<scale>
<font>"monospace"</font>
<width>"10"</width>
<halpin>"fnum"</halpin>
<resolution>1</resolution>
<orient>VERTICAL</orient>
<initval>0</initval>
<min_>0</min_>
<max_>3</max_>
<param_pin>1</param_pin>
</scale>
</hbox>
</vbox>
</vbox>
</pyvcp>

View File

@@ -0,0 +1,45 @@
o<queuebuster> sub
#<xmax> = #1 (=9)
#<ymax> = #2 (=3)
#<feed> = #3 (=100)
#<ct> = #4 (=100)
#<use_m6> = #5 (=0)
#<use_m66> = #6 (=0)
#<use_m38> = #7 (=0)
#<pauseatend> = #8 (=1)
g20 g61 g90 ;inches, exactpath,absolute
g0 x0y0z0
f#<feed>
o<loop> repeat [#<ct>]
m111
g1 x#<xmax> y0
o<um6> if [#<use_m6> GT 0]
(debug, m6 queuebuster follows)
t1m6 ;QB toolchange
o<um6> endif
o<um66> if [#<use_m66> GT 0]
(debug, m66 queuebuster follows)
m66p0l0 ;QB wait on input l0=immediate
o<um66> endif
o<um38> if [#<use_m38> GT 0]
(debug, g38.3 queuebuster follows)
g38.3z-.2 ; QB probe
g1 z0
o<um38> endif
g1 y#<ymax>
g1 x0
g1 x0 y0
o<pas> if [#<pauseatend> GT 0]
(debug, Paused, s to continue)
m0
o<pas> endif
o<loop> endrepeat
o<queuebuster> endsub
; bad: t0m6 g38.3
; ok: m66

View File

@@ -0,0 +1,223 @@
[EMC]
MACHINE = 12extrajoints
VERSION = 1.1
[APPLICATIONS]
APP = halshow --fformat %.6f extrajoints.halshow
# joint4 example:
APP = sim_pin --title "j4 extrajoint" \
j4.limit3.min \
j4.limit3.max \
j4.limit3.maxv \
j4.limit3.maxa \
j4.limit3.in
[KINS]
JOINTS = 16
#NOTE: 4 conventional joints, 12 extra (motmod) total=16
KINEMATICS = trivkins coordinates=XYYZ kinstype=both
[EMCMOT]
EMCMOT = motmod num_extrajoints=12
SERVO_PERIOD = 1000000
[HAL]
TWOPASS = on
HALFILE = LIB:basic_sim.tcl
HALFILE = ./extrajoints.tcl
HALUI = halui
[DISPLAY]
DISPLAY = axis
MAX_LINEAR_VELOCITY = 1
PROGRAM_PREFIX = .
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim.var
[TRAJ]
COORDINATES = XYYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_3]
TYPE = LINEAR
HOME_SEQUENCE = 2
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_4]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 3
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_5]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 4
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_6]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 5
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_7]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 6
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_8]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 7
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_9]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 8
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_10]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 9
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_11]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 10
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_12]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 11
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_13]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 12
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_14]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 13
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_15]
# Uses IMMEDIATE homing
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 14
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100

View File

@@ -0,0 +1,61 @@
# 1extrajoint demo
# immediate homing -- jog joint4 to make a motor-offset before homing
loadrt [KINS]KINEMATICS
loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
addf motion-command-handler servo-thread
addf motion-controller servo-thread
net estop-loop iocontrol.0.user-enable-out iocontrol.0.emc-enable-in
net J0:loop <= joint.0.motor-pos-cmd
net J0:loop => joint.0.motor-pos-fb
net J1:loop <= joint.1.motor-pos-cmd
net J1:loop => joint.1.motor-pos-fb
net J2:loop <= joint.2.motor-pos-cmd
net J2:loop => joint.2.motor-pos-fb
net J3:loop <= joint.3.motor-pos-cmd
net J3:loop => joint.3.motor-pos-fb
#--------------------------------------------
# extra joint (joint4)
# For simulation just connect pos-cmd to pos-fb:
net J4:loop <= joint.4.motor-pos-cmd
net J4:loop => joint.4.motor-pos-fb
# NOTE: For a stepgen in position control mode:
# net J4:loop <= joint.4.motor-pos-cmd
# net J4:loop => joint.4.motor-pos-fb
# net J4:loop => stepgen_position_command
# NOTE: A stepgen can be also used in velocity control mode
# with a PID loop but it is not necessarily required
# and position mode control is much simpler
# NOTE: For a pid motor controller (motor/amplifier/encoder):
# net J4:cmd <= joint.4.motor-pos-cmd
# net J4:cmd => pid_command_input
# net J4:fb <= encoder_measurement_output
# net J4:fb => joint.4.motor-pos-fb
#-----------------------------------------------------------
# motion planner for extra joint (joint4)
loadrt limit3 names=j4.limit3
# These constraints apply to homing managed by
# LinuxCNC and post-homing managed by the limit3 component:
setp j4.limit3.min [JOINT_4]MIN_LIMIT
setp j4.limit3.max [JOINT_4]MAX_LIMIT
setp j4.limit3.maxv [JOINT_4]MAX_VELOCITY
setp j4.limit3.maxa [JOINT_4]MAX_ACCELERATION
addf j4.limit3 servo-thread
net J4:out <= j4.limit3.out
net J4:out => joint.4.posthome-cmd
net J4:enable <= joint.4.homed
net J4:enable => j4.limit3.enable

View File

@@ -0,0 +1,82 @@
# This sim config uses 'immediate' homing
# To demonstrate motor-offsets:
# jog the extra joint(4) away from its turn-on position
# then home-all
[EMC]
MACHINE = 1extrajoint
VERSION = 1.1
[APPLICATIONS]
APP = halshow --fformat %.6f extrajoints.halshow
APP = sim_pin --title "j4 extrajoint" \
j4.limit3.min \
j4.limit3.max \
j4.limit3.maxv \
j4.limit3.maxa \
j4.limit3.in
[KINS]
JOINTS = 5
# NOTE: 4 kinematic joints + 1 extra (motmod) total=5
KINEMATICS = trivkins coordinates=XYYZ kinstype=both
[EMCMOT]
EMCMOT = motmod num_extrajoints=1
SERVO_PERIOD = 1000000
[HAL]
HALFILE = 1extrajoint.hal
HALUI = halui
[DISPLAY]
DISPLAY = axis
MAX_LINEAR_VELOCITY = 1
PROGRAM_PREFIX = .
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim.var
[TRAJ]
COORDINATES = XYYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 1
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = -2
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = -2
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_3]
TYPE = LINEAR
HOME_SEQUENCE = 3
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_4]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 0
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100

View File

@@ -0,0 +1,37 @@
1extrajoint demo
Demo of the motmod num_extrajoints= parameter
a) XYYZ correspond one-to-one to
joints 0123
b) Joint4 is an 'extra joint' that is
not related to any axis letter but
is managed independently by a limit3
component.
c) All joints use 'immediate homing'
d) Using extra joints requires
NON-identity kinematics and all
joints (including joint4) must be
homed before switching to world
mode.
e) A halshow app is opened to display
key pin values
f) A sim_pin app is opened to set key
pin values
Usage:
1) F1 (Estop Off)
2) F2 (Machine On)
3) jog joint4 to create a small offset
4) Ctrl-HOME (Home all)
5) demonstrate joint.4 movement using
the provided M144 mdi command:
M144 P4 Q1.23 ;move joint.4 to 1.23
M144 P4 Q3.21 ;move joint.4 to 3.21
6) Alternately, demonstrate joint.[45]
movement using sim_pin settings:
j4.limit3.min min value
j4.limit3.max max value
j4.limit3.maxv max velocity
j4.limit3.maxa max acceleration
j4.limit3.in requested value

View File

@@ -0,0 +1,30 @@
# use limit3 for motion planning:
loadrt limit3 names=j4.limit3,j5.limit3
# These constraints apply to homing managed by
# LinuxCNC and post-homing managed by the limit3 component:
setp j4.limit3.min [JOINT_4]MIN_LIMIT
setp j4.limit3.max [JOINT_4]MAX_LIMIT
setp j4.limit3.maxv [JOINT_4]MAX_VELOCITY
setp j4.limit3.maxa [JOINT_4]MAX_ACCELERATION
addf j4.limit3 servo-thread
net J4:out <= j4.limit3.out
net J4:out => joint.4.posthome-cmd
net J4.enable <= joint.4.homed
net J4.enable => j4.limit3.enable
setp j5.limit3.min [JOINT_5]MIN_LIMIT
setp j5.limit3.max [JOINT_5]MAX_LIMIT
setp j5.limit3.maxv [JOINT_5]MAX_VELOCITY
setp j5.limit3.maxa [JOINT_5]MAX_ACCELERATION
addf j5.limit3 servo-thread
net J5:out <= j5.limit3.out
net J5:out => joint.5.posthome-cmd
net J5.enable <= joint.5.homed
net J5.enable => j5.limit3.enable

View File

@@ -0,0 +1,107 @@
[EMC]
MACHINE = 2extrajoints
VERSION = 1.1
[APPLICATIONS]
APP = halshow --fformat %.6f extrajoints.halshow
APP = sim_pin --title "j4 extrajoint" \
j4.limit3.min \
j4.limit3.max \
j4.limit3.maxv \
j4.limit3.maxa \
j4.limit3.in
APP = sim_pin --title "j5 extrajoints" \
j5.limit3.min \
j5.limit3.max \
j5.limit3.maxv \
j5.limit3.maxa \
j5.limit3.in
[KINS]
JOINTS = 6
#NOTE: 4 conventional joints, 2 extra (motmod) total=6
KINEMATICS = trivkins coordinates=XYYZ kinstype=both
[EMCMOT]
EMCMOT = motmod num_extrajoints=2
SERVO_PERIOD = 1000000
[HAL]
HALFILE = LIB:basic_sim.tcl
HALFILE = ./2extrajoints.hal
HALUI = halui
[DISPLAY]
DISPLAY = axis
MAX_LINEAR_VELOCITY = 1
PROGRAM_PREFIX = .
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim.var
[TRAJ]
COORDINATES = XYYZ
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
[JOINT_0]
TYPE = LINEAR
HOME_SEQUENCE = 1
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_1]
TYPE = LINEAR
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_2]
TYPE = LINEAR
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_3]
TYPE = LINEAR
HOME_SEQUENCE = 3
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
[JOINT_4]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100
[JOINT_5]
# this 'extra' joint is managed by a
# limit3 component after homing
TYPE = LINEAR
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = 20
HOME_LATCH_VEL = 20
MIN_LIMIT = -10
MAX_LIMIT = 10
MAX_VELOCITY = 5
MAX_ACCELERATION = 100

View File

@@ -0,0 +1,46 @@
2extrajoints demo
Demo of the motmod num_extrajoints= parameter
a) XYYZ correspond one-to-one to
joints 0123
b) joint.4 and joint.5 are 'extra'
joints not related to any axis
letter but managed independently by
limit3 components.
c) The configuration uses basic_sim.tcl
and simulates home switches for all
joints.
d) Using extra joints requires
NON-identity kinematics and all
joints (including joint4) must be
homed before switching to world
mode.
e) A halshow app is opened to display
key pin values
f) A sim_pin app is opened to set key
pin values
Usage:
1) F1 (Estop Off)
2) F2 (Machine On)
3) optionally jog joint.4 and joint.5
prior to homing to observe motor
offset
4) Ctrl-HOME (Home all)
5) demonstrate joint.[45] movement
using the provided M144 mdi
command:
M144 P4 Q1.23 move joint.4 to 1.23
M144 P4 Q4.56 move joint.4 to 4.56
M144 P5 Q3.21 move joint.5 to 3.21
M144 P5 Q2.22 move joint.5 to 2.22
etc.
6) Alternately, demonstrate joint.[45]
movement using sim_pin settings:
j4.limit3.min min value
j4.limit3.max max value
j4.limit3.maxv max velocity
j4.limit3.maxa max acceleration
j4.limit3.in requested value
similar for j5

View File

@@ -0,0 +1,35 @@
#!/usr/bin/tclsh
# M144 demo for extra joints
# Usage: M144 [Pjoint_num] [Qposition]
# Mcodes substitute "-1.000000" for omitted p,q values
# so these are handled as special cases
# Note: this also disallows a q value of -1 (sigh)
set min_joint_num 4
set max_joint_num 15
proc fail {msg} {
puts "\nFAIL: $::argv0 $msg"
puts "Usage: $::argv0 P<jointnumber> Q<position>"
exit 1
}
set p [lindex $::argv 0]
set q [lindex $::argv 1]
if {"$p" == "-1.000000"} {fail "Missing Pvalue"}
if {"$q" == "-1.000000"} {fail "Missing Qvalue (or -1)"}
set p [expr int($p)]
if {$p < $min_joint_num || $p > $max_joint_num} {
fail "Bad Pvalue (extra joint number) <$p>"
}
set cmd "halcmd setp j${p}.limit3.in $q"
if [catch {eval exec $cmd} msg] {
fail "Command:$cmd\n$msg"
}
puts "\nOK: $::argv0: $cmd"
exit 0

View File

@@ -0,0 +1,18 @@
extrajoints demos
1extrajoint
5 joints total
1 extra joint (joint.4)
immediate homing
(jog joint4 before homing to
create a small motor offset)
2extrajoints
6 joints total
2 extra joints (joint.4,5)
simulated home switches
12extrajoints
16 joints total
12 extra joints (joint.4-15)
simulated home switches

View File

@@ -0,0 +1,28 @@
pin+j4.limit3.in
pin+j4.limit3.out
pin+joint.4.posthome-cmd
pin+joint.4.homed
pin+joint.4.motor-pos-cmd
pin+joint.4.motor-pos-fb
pin+joint.4.motor-offset
pin+j4.limit3.max
pin+j4.limit3.min
pin+j4.limit3.maxv
pin+j4.limit3.maxa
pin+j5.limit3.in
pin+j5.limit3.out
pin+joint.5.posthome-cmd
pin+joint.5.homed
pin+joint.5.motor-pos-cmd
pin+joint.5.motor-pos-fb
pin+joint.5.motor-offset
pin+j5.limit3.max
pin+j5.limit3.min
pin+j5.limit3.maxv
pin+j5.limit3.maxa

View File

@@ -0,0 +1,35 @@
# extrajoints.tcl (requires [HAL]TWOPASS
# create limit3 and signals for all extra joints
set script [file tail [info script]]
set min_joint_num 0 ;# first possible extra joint
set max_joint_num 15 ;# last possible extra joint
for {set j $min_joint_num} {$j <= $max_joint_num} {incr j} {
if [catch {getp joint.${j}.posthome-cmd} msg] {
#puts "$::argv0: skip $j"
continue
} else {
if [::tp::passnumber] {
puts "$script: Create limit3 for extra joint $j"
}
}
catch {
# use limit3 for motion planning:
loadrt limit3 names=j${j}.limit3
addf j${j}.limit3 servo-thread
# These constraints apply to homing managed by
# LinuxCNC and post-homing managed by the limit3 component:
setp j${j}.limit3.min [set ::JOINT_[set j](MIN_LIMIT)]
setp j${j}.limit3.max [set ::JOINT_[set j](MAX_LIMIT)]
setp j${j}.limit3.maxv [set ::JOINT_[set j](MAX_VELOCITY)]
setp j${j}.limit3.maxa [set ::JOINT_[set j](MAX_ACCELERATION)]
net J${j}:out <= j${j}.limit3.out
net J${j}:out => joint.${j}.posthome-cmd
net J${j}.enable <= joint.${j}.homed
net J${j}.enable => j${j}.limit3.enable
}
}

View File

@@ -0,0 +1,126 @@
[EMC]
VERSION = 1.1
MACHINE = LinuxCNC-HAL-SIM-AXIS
DEBUG = 0
[DISPLAY]
DISPLAY = axis
CYCLE_TIME = 0.100
HELP_FILE = doc/help.txt
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
PROGRAM_PREFIX = ../../nc_files/
OPEN_FILE = ./foam.ngc
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
#EDITOR = geany
INCREMENTS = 1 mm, .01 in, .1mm, 1 mil, .1 mil, 1/8000 in
GEOMETRY = XY;UV
FOAM = 1
[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 = python3
[RS274NGC]
PARAMETER_FILE = foam.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALUI = halui
HALFILE = LIB:basic_sim.tcl
[TRAJ]
NO_FORCE_HOMING = 1
COORDINATES = X Y U V
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
DEFAULT_ANGULAR_VELOCITY = 45.0
MAX_LINEAR_VELOCITY = 1.2
MAX_ANGULAR_VELOCITY = 90.0
[EMCIO]
TOOL_TABLE = sim.tbl
TOOL_CHANGE_POSITION = 0 0 2
[KINS]
KINEMATICS = trivkins coordinates=xyuv
JOINTS = 4
[AXIS_X]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 0.0
HOME_SEQUENCE = 0
[AXIS_Y]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 0.0
HOME_SEQUENCE = 0
[AXIS_U]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
HOME_SEARCH_VEL = 0.0
HOME_SEQUENCE = 0
[AXIS_V]
MIN_LIMIT = -10.0
MAX_LIMIT = 10.0
MAX_VELOCITY = 1.2
MAX_ACCELERATION = 20.0
[JOINT_3]
TYPE = ANGULAR
HOME = 0.0
MAX_VELOCITY = 90.0
MAX_ACCELERATION = 1200.0
HOME_SEARCH_VEL = 0.0
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,24 @@
(test this with axis_9axis sim machine )
G17 G21 G90 G61 G54
(AXIS,XY_Z_POS,5)
(AXIS,UV_Z_POS,30)
(AXIS,GRID,5)
G0 x0 y0 u0 v0
(square uv 45 deg turned offset 10mm to zero )
G0 x5 y5
G0 x10 y10 u22.5 v22.5
G1 x10 y35 u10 v35 F200
G1 x10 y60 u22.5 v47.5
G1 x35 y60 u35 v60
G2 r25 x60 y35 u60 v35
G1 x60 y10 u47.5 v22.5
G1 x35 y10 u35 v10
G1 X10 Y10 u22.5 v22.5
G1 X5 Y5 U5 V5
G0 x0 u0
G0 x0 y0 u0 v0
M30
%

View File

@@ -0,0 +1,13 @@
Axis gui sim configs for gantry applications
using 2 joints for the Y coordinate.
Use trivkins coordinates=XYYZ kinstype=BOTH
X: joint0
Y: joint1 and joint2
Z: joint3
gantry.ini basic gantry demo (in)
gantry_mm.ini basic gantry demo (mm)
gantry_jjog.ini demo for jogging joint1 and joint3 (in)

View File

@@ -0,0 +1,146 @@
[KINS]
JOINTS = 4
KINEMATICS = trivkins coordinates=XYZY kinstype=BOTH
# Notes:
# KINEMATICS coordinates=value MUST agree with [TRAJ]COORDINATES
#
# X: JOINT_0
# Y: JOINT_1 and JOINT_3
# Z: JOINT_2
#
# kinstype=BOTH specifies non-identity kinematics
#
# HOME ALL sequence:
# HOME_SEQUENCE 0 (first) JOINT_0 (coordinate X)
# HOME_SEQUENCE -1 (second) JOINT_1 and JOINT_3 (coordinate Y)
# HOME_SEQUENCE 2 (third) JOINT_2 (coordinate Z)
# The negative (-1) sequence indicates synchronization of
# the final move for all joints in the sequence
[EMC]
VERSION = 1.1
MACHINE = LinuxCNC-GANTRY-SIM-AXIS
# Debug level, 0 means no messages. See src/emc/nml_int/emcglb.h for others
DEBUG = 0
[DISPLAY]
DISPLAY = axis
CYCLE_TIME = 0.100
HELP_FILE = tklinuxcnc.txt
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
PROGRAM_PREFIX = ../../nc_files/
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
INCREMENTS = 0.100 in, 0.010 in, 0.001 in, 0.0001 in
GEOMETRY = XYZ
[FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
PROGRAM_EXTENSION = .dxf 3D Polygon Model
PROGRAM_EXTENSION = .py Python Script
png = image-to-gcode.py
gif = image-to-gcode.py
jpg = image-to-gcode.py
dxf = toolpaths.py
py = python3
[RS274NGC]
PARAMETER_FILE = sim.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALFILE = gantrysim.hal
HALFILE = sim_spindle_encoder.hal
HALFILE = simulated-gantry-home.hal
[TRAJ]
# These two variables are a bit weird for gantry machines.
# The gantry machine that this sim config describes has only three axes (X,
# Y, and Z), but it uses two joints to implement the Y axis.
# The [TRAJ]COORDINATES variable only lists the axis names
# that are accepted in incoming G-code, and duplicate names here have no
# effect.
COORDINATES = XYZY
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
MAX_LINEAR_VELOCITY = 58
[EMCIO]
TOOL_TABLE = sim.tbl
[AXIS_X]
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_0]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = -10
HOME_LATCH_VEL = 5
HOME_OFFSET = -0.1
[AXIS_Y]
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_1]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = -0.1
HOME_LATCH_VEL = 0.05
HOME_OFFSET = -0.1
[AXIS_Z]
MIN_LIMIT = -50.0
MAX_LIMIT = 0.01
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_2]
TYPE = LINEAR
MIN_LIMIT = -50.0
MAX_LIMIT = 0.01
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = 2
HOME_SEARCH_VEL = 0.1
HOME_LATCH_VEL = -0.05
HOME_OFFSET = 0.1
[JOINT_3]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = -0.1
HOME_LATCH_VEL = 0.05
HOME_OFFSET = -0.1

View File

@@ -0,0 +1,27 @@
THREAD servo-thread
MAXCHAN 4
HMULT 1
HZOOM 1
HPOS 5.000000e-01
CHAN 1
PIN joint.0.pos-cmd
VSCALE -3
VPOS 0.200000
VOFF 0.000000e+00
CHAN 2
PIN joint.1.pos-cmd
VSCALE -3
VPOS 0.400000
VOFF 0.000000e+00
CHAN 3
PIN joint.2.pos-cmd
VSCALE -3
VPOS 0.600000
VOFF 0.000000e+00
CHAN 4
PIN joint.3.pos-cmd
VSCALE -3
VPOS 0.800000
VOFF 0.000000e+00
TMODE 0
RMODE 0

View File

@@ -0,0 +1,151 @@
[APPLICATIONS]
APP = halscope -i gantry_jjog.halscope
[KINS]
JOINTS = 4
KINEMATICS = trivkins coordinates=XYZY kinstype=BOTH
# Notes:
# KINEMATICS coordinates=value MUST agree with [TRAJ]COORDINATES
#
# X: JOINT_0
# Y: JOINT_1 and JOINT_3
# Z: JOINT_2
#
# kinstype=BOTH specifies non-identity kinematics
#
# HOME ALL sequence:
# HOME_SEQUENCE 0 (first) JOINT_0 (coordinate X)
# HOME_SEQUENCE -1 (second) JOINT_1 and JOINT_3 (coordinate Y)
# HOME_SEQUENCE 2 (third) JOINT_2 (coordinate Z)
# The negative (-1) sequence indicates synchronization of
# the final move for all joints in the sequence
[EMC]
VERSION = 1.1
MACHINE = gantry_jjog-sim
# Debug level, 0 means no messages. See src/emc/nml_int/emcglb.h for others
DEBUG = 0
[DISPLAY]
PYVCP = gantry_panel.xml
DISPLAY = axis
CYCLE_TIME = 0.100
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
PROGRAM_PREFIX = ../../nc_files/
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
INCREMENTS = 0.100 in, 0.010 in, 0.001 in, 0.0001 in
GEOMETRY = XYZ
[FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
PROGRAM_EXTENSION = .dxf 3D Polygon Model
PROGRAM_EXTENSION = .py Python Script
png = image-to-gcode.py
gif = image-to-gcode.py
jpg = image-to-gcode.py
dxf = toolpaths.py
py = python3
[RS274NGC]
PARAMETER_FILE = sim.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALFILE = gantrysim.hal
HALFILE = sim_spindle_encoder.hal
HALFILE = simulated-gantry-home.hal
POSTGUI_HALFILE = gantry_panel.hal
[TRAJ]
# These two variables are a bit weird for gantry machines.
# The gantry machine that this sim config describes has only three axes (X,
# Y, and Z), but it uses two joints to implement the Y axis.
# The [TRAJ]COORDINATES variable only lists the axis names
# that are accepted in incoming G-code, and duplicate names here have no
# effect.
COORDINATES = XYZY
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.0
MAX_LINEAR_VELOCITY = 58
[EMCIO]
TOOL_TABLE = sim.tbl
[AXIS_X]
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_0]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = -10
HOME_LATCH_VEL = 5
HOME_OFFSET = -0.1
[AXIS_Y]
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_1]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50.0
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = -0.1
HOME_LATCH_VEL = 0.05
HOME_OFFSET = -0.1
[AXIS_Z]
MIN_LIMIT = -50.0
MAX_LIMIT = 0.01
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
[JOINT_2]
TYPE = LINEAR
MIN_LIMIT = -50.0
MAX_LIMIT = 0.01
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = 2
HOME_SEARCH_VEL = 0.1
HOME_LATCH_VEL = -0.05
HOME_OFFSET = 0.1
[JOINT_3]
TYPE = LINEAR
MIN_LIMIT = -0.01
MAX_LIMIT = 50
MAX_VELOCITY = 39
MAX_ACCELERATION = 120.0
HOME = 0.0
HOME_SEQUENCE = -1
HOME_SEARCH_VEL = -0.1
HOME_LATCH_VEL = 0.05
HOME_OFFSET = -0.1

View File

@@ -0,0 +1,50 @@
gantry_jjog sim config
o Default configs that synchronize the
final homing move for multiple joints disallow
individual jogging of such joints since
such jogs invite operator error and gantry
racking. This more complex config demonstrates:
Individual joint mode jogging for joint1 and joint3
Synchronized joint mode jogging for joint1 and joint3
Example Procedure:
1) Estop-off (F1)
2) Machine-on (F2)
3) Set halscope to "Roll" and resize
4) Panel "J1,3 JOGGING": set ENABLE to ON
to allow jogging for joint1 and joint3
5) use COUNTS to jog both joint1 and joint3
SYNCHRONOUSLY in realtim
6) use axisgui jog number radiobuttons
and the plus(+) and minus(-) pushbuttons
to jog any joint INDIVIDUALLY.
NOTE: this would RACK a two-motor gantry
7) Panel "J1,3 JOGGING": set ENABLE to OFF
to allow homing
8) HOME All (Ctrl-HOME) to home all joints
(it may be necessary to first move all joints
close to zero to properly simulate home switches)
9) Use axisgui X,Y,Z radiobuttons
and the plus(+) and minus(-) pushbuttons
to jog any coordinate
10) Return to joint mode using the $ key
Notes:
a) Uses trivkins coordinates=XYZY kinstype=BOTH
b) The "J1,3 JOGGING" panel makes hal connections to
alter ini.[13].home_sequence and motion.homing-inhibit
settings to allow jogging of joints that use synchronized
homing provisions.
c) The "J1,3 JOGGING" COUNTS widget simulates
the counts which would normally be supplied
by an Manual-Pulse-Generator (MPG or wheel jog).
d) The "J1,3 JOGGING" SCALE widget sets the distance
in machine units for each count
e) In joint mode, the axis gui displays joint numbers
and joint positions correctly but the graphical
interpretation may be misleading.

View File

@@ -0,0 +1,56 @@
Configuracion sim gantry_jjog
o Configuración predeterminada que sincroniza el
movimiento final de homing para múltiples articulaciones
no permitiendo jog individual de tales articulaciones ya
que tales movimientos invitan al operador al error y a
desviaciones del pórtico. Esta configuración más
compleja demuestra:
Jogging individual en modo articulación para joint1
y joint3
Jogging sincronizado en modo articulación para joint1
y joint3
Procedimiento de ejemplo:
1) Estop-Off (F1)
2) Máquina-On (F2)
3) Establecer halscope en "Roll" y redimensionar.
4) Panel "J1,3 JOGGING": establecer ENABLE en ON
para permitir jogging de joint1 y joint3
5) usar COUNTS para jog tanto de joint1 y
joint3 SINCRÓNICAMENTE en tiempo real
6) usar los botones radio del número de jog de
axisgui y los botones más (+) y menos (-) para
jog INDIVIDUAL de cualquier articulación.
NOTA: esto DESVIARA un pórtico de motores tandem.
7) Panel "J1,3 JOGGING": establezca ENABLE en OFF
para permitir homing
8) HOME Todos (Ctrl-Inicio) para dar home a todas
las articulaciones (puede ser necesario mover
primero todas las articulaciones cerca de cero para
simular correctamente los interruptores home)
9) Usar los botones radio axisgui X, Y, Z
y los botones más (+) y menos (-)
para jog a cualquier coordenada
10) Regrese al modo articulacion usando la tecla $
Notas:
a) Utilice trivkins coordinates=XYZY kinstype=BOTH
b) El panel "J1,3 JOGGING" hace conexiones hal y
altera la configuracion de ini.[13].home_sequence y
motion.homing-inhibit para permitir el jogging de
articulaciones que usan homing sincronizado.
c) El widget "J1,3 JOGGING" COUNTS simula
los recuentos que normalmente se proporcionarían
por un generador de pulso manual (MPG o volante de jog).
d) El widget SCALE "J1,3 JOGGING" establece la distancia
en unidades de máquina para cada recuento
e) En el modo articulacion, la interfaz gráfica de usuario
Axis muestra los números y las posiciones de articulaciones
correctamente, pero la interpretación gráfica puede
ser engañosa.

View File

@@ -0,0 +1,23 @@
# 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 servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
# add motion controller functions to servo thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
# 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
# loop position commands back to motion module feedback
net Xpos joint.0.motor-pos-cmd => joint.0.motor-pos-fb
net Ypos joint.1.motor-pos-cmd => joint.1.motor-pos-fb
net Y2pos joint.2.motor-pos-cmd => joint.2.motor-pos-fb
net Zpos joint.3.motor-pos-cmd => joint.3.motor-pos-fb

View File

@@ -0,0 +1,125 @@
[EMC]
VERSION = 1.1
MACHINE = EMC-HAL-SIM-GANTRY
# Debug level, 0 means no messages. See src/emc/nml_int/emcglb.h for others
DEBUG = 0
[DISPLAY]
DISPLAY = axis
CYCLE_TIME = 0.100
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
PROGRAM_PREFIX = ../../nc_files/
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
#EDITOR = geany
INCREMENTS = 1 mm, .01 in, .1mm, 1 mil, .1 mil, 1/8000 in
[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 = python3
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = gantry_mm.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
SERVO_PERIOD = 1000000
[HAL]
HALFILE = gantry_mm.hal
HALUI = halui
[KINS]
KINEMATICS = trivkins coordinates=xyyz kinstype=BOTH
JOINTS = 4
[TRAJ]
COORDINATES = X Y Y Z
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 100
MAX_LINEAR_VELOCITY = 100
DEFAULT_LINEAR_ACCELERATION = 800
MAX_LINEAR_ACCELERATION = 800
NO_FORCE_HOMING = 1
[EMCIO]
TOOL_TABLE = gantry_mm.tbl
[AXIS_X]
MAX_VELOCITY = 30
MAX_ACCELERATION = 200
MIN_LIMIT = 0
MAX_LIMIT = 400
[AXIS_Y]
MAX_VELOCITY = 30
MAX_ACCELERATION = 200
MIN_LIMIT = 0
MAX_LIMIT = 2000
[AXIS_Z]
MAX_VELOCITY = 30
MAX_ACCELERATION = 200
MIN_LIMIT = 0
MAX_LIMIT = 100
[JOINT_0]
TYPE = LINEAR
MAX_VELOCITY = 100
MAX_ACCELERATION = 900
MIN_LIMIT = 0
MAX_LIMIT = 400
HOME = 0.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
HOME_SEQUENCE = 1
[JOINT_1]
TYPE = LINEAR
MAX_VELOCITY = 200
MAX_ACCELERATION = 1000
MIN_LIMIT = 0
MAX_LIMIT = 2000
HOME = 0.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
HOME_SEQUENCE = -2
[JOINT_2]
TYPE = LINEAR
MAX_VELOCITY = 200
MAX_ACCELERATION = 1000
MIN_LIMIT = 0
MAX_LIMIT = 2000
HOME = 0.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
HOME_SEQUENCE = -2
[JOINT_3]
TYPE = LINEAR
MAX_VELOCITY = 50
MAX_ACCELERATION = 500
MIN_LIMIT = 0
MAX_LIMIT = 100
HOME = 100
HOME_OFFSET = 100
HOME_SEARCH_VEL = 0
HOME_LATCH_VEL = 0
HOME_SEQUENCE = 0

View File

@@ -0,0 +1,6 @@
TOOLNO POCKET LENGTH DIAMETER COMMENT
1 1 +0.511000 0.125000 1/8 end mill
2 2 +0.100000 0.062500 1/16 end mill
3 3 +1.273000 0.201000 #7 tap drill
99999 99999 +0.100000 0.000000 big tool number

View File

@@ -0,0 +1,83 @@
# gantry_panel.hal -- must be a postgui halfile since
# ini.* hal pins are not available until milltask is
# started. Ref: $ man milltask
# Joints 1 and 3 use a negative home_sequence to
# synchronize the final home move. This synchronization
# disallows individual jogging of joints 1 and 3 in order
# to prevent inadvertent racking of the gantry.
# Joint jogging is enabled by an checkbox widget on the
# pyvcp panel. Setting the enable changes the home_sequence
# for joints 1 and 3 from -1 (home syncing) to 1 (no
# home syncing). When the home_sequence is set to 1, these
# joints can be jogged individually using the axis gui jog
# buttons (racking hazard). Non-synced homing is disabled
# by asserting the motion.homing-inhibit pin.
# Joints 1 and 3 can be jogged synchronously using the
# facilities for realtime jogging provided for
# Manual-Pulse-Generators (MPGs). The pyvcp panel
# provides controls to set jog counts and the scale
# factor (machine-units per count).
loadrt mux2 names=home_sequence_mux,jjog_counts_mux
loadrt conv_float_s32 names=home_sequence_s32
loadrt oneshot names=pulse_on_jjdisable
# synchronized homing, no joint1,3 jogging:
setp home_sequence_mux.in0 -1
# no synchronized homing, allow joint1,3 jogging:
setp home_sequence_mux.in1 1
# use oneshot to return jjog_counts to zero when changing
# from enable to disable:
setp jjog_counts_mux.in0 0
setp jjog_counts_mux.in1 0.0000001
# non-zero value needed to pulse the
# pyvcp.scale.0.param_pin is ok since
# the truncated s32 pin pyvcp.jj_counts-i
# is used for joint.N.jog-counts pins
setp pulse_on_jjdisable.rising 0
setp pulse_on_jjdisable.falling 1
setp pulse_on_jjdisable.retriggerable 0
setp pulse_on_jjdisable.width 0.1
addf home_sequence_mux servo-thread
addf jjog_counts_mux servo-thread
addf home_sequence_s32 servo-thread
addf pulse_on_jjdisable servo-thread
net home_seq_float <= home_sequence_mux.out
net home_seq_float => home_sequence_s32.in
net home_seq_s32 <= home_sequence_s32.out
net home_seq_s32 => ini.1.home_sequence
net home_seq_s32 => ini.3.home_sequence
# set counts to zero using param_pin upon disable:
net jjog_counts_value <= jjog_counts_mux.out
net jjog_counts_value => pyvcp.scale.0.param_pin
net jjog_counts_reset <= pulse_on_jjdisable.out
net jjog_counts_reset => jjog_counts_mux.sel
net hsequence_select <= pyvcp.jj_enable
net hsequence_select => home_sequence_mux.sel
net hsequence_select => joint.1.jog-enable
net hsequence_select => joint.3.jog-enable
net hsequence_select => motion.homing-inhibit
net hsequence_select => pulse_on_jjdisable.in
# counts for synchronized realtime MPG joint jogging:
net j13counts <= pyvcp.jj_counts-i
net j13counts => joint.1.jog-counts joint.3.jog-counts
# MPG scaling:
net j13scale <= pyvcp.jj_scale
net j13scale => joint.1.jog-scale joint.3.jog-scale
# preferred jog-vel-mode:
setp joint.1.jog-vel-mode 1
setp joint.3.jog-vel-mode 1

View File

@@ -0,0 +1,63 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Demo panel for synchronized joint jogging
For real hardware, one typically uses a manual-pulse-generator
(MPG) to generate the counts input
-->
<pyvcp>
<vbox>
<label>
<text>"J1,3 JOGGING"</text>
<font>"bold"</font>
</label>
</vbox>
<vbox>
<hbox>
<checkbutton>
<anchor>"w"</anchor>
<halpin>"jj_enable"</halpin>
<text>""</text>
<initval>0</initval>
</checkbutton>
<label>
<anchor>"w"</anchor>
<text>"ENABLE"</text>
</label>
</hbox>
<hbox>
<spinbox>
<halpin>"jj_scale"</halpin>
<min_> 0.01</min_>
<max_>10.0</max_>
<width>4</width>
<initval>0.01</initval>
<resolution>0.01</resolution>
<format>"5.2f"</format>
</spinbox>
<label>
<anchor>"w"</anchor>
<text>"scale"</text>
</label>
</hbox>
<hbox>
<scale>
<halpin>"jj_counts"</halpin>
<resolution>0.1</resolution>
<orient>VERTICAL</orient>
<initval>0</initval>
<resolution>"1"</resolution>
<min_>-100</min_>
<max_>100</max_>
<param_pin>1</param_pin>
</scale>
<label>
<anchor>"w"</anchor>
<text>"COUNTS"</text>
</label>
</hbox>
</vbox>
</pyvcp>

Some files were not shown because too many files have changed in this diff Show More