1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
# xhc-hb04.tcl: HALFILE for xhc-hb04 pendant
# Usage:
# In ini file, include:
# [HAL]
# HALFILE = existing halfiles
# ...
# HALFILE = xhc-hb04.tcl
#
# [XHC-HB04_CONFIG]
# layout = 2 (required: 1|2 are supported)
# coords = x y z a (any unique four of xyzabcuvw)
# coefs = 1 1 1 1 (optional, filter coefs, 0 < coef < 1, not usually reqd)
# scales = 1 1 1 1 (optional)
# threadname = servo-thread (optional)
# sequence = 1 (optional: 1|2)
# jogmode = normal (optional: normal|vnormal|plus-minus)
# require_pendant = yes (optional: yes|no)
# [XHC-HB04_BUTTONS]
# name = pin (connect button to hal pin)
# name = "" (no connect button)
# special cases:
# start-pause = std_start_pause (for usual behavior)
# step = xhc-hb04.stepsize-up (for usual behavior)
# (see ini files for more exanples)
# Notes:
# 1) the 'start-pause' pin can be set to "std_start_pause" to
# implement default behavior
# 2) the 'step' pin is normally connected to xhc-hb04.stepsize-up
# 3) non-root access to the usb device requires an additional
# udev rule. Typically, create /etc/udev/rules.d/90-xhc.rules:
# SYSFS{idProduct}=="eb70", SYSFS{idVendor}=="10ce", MODE="666", OWNER="root", GROUP="users"
# or (for ubuntu12 and up):
# ATTR{idProduct}=="eb70", ATTR{idVendor}=="10ce", MODE="666", OWNER="root", GROUP="users"
# 4) For jogmode==vnormal (man motion -- see axis.N.jog-vel-mode),
# the max movement is limited by the machine velocity and acceleration limits
# such that delta_x = 0.5 * vmax**2/accelmx
# so for sim example:
# inch: vmax= 1.2 accelmax= 20 delta_x=0.036
# mm: vmax=30.48 acclemax=508 delta_x=0.9144
# Typically:
# (-s1) sequence 1 (1,10,100,1000) is ok for mm-based machines
# (-s2) sequence 2 (1,5,10,20) is ok for inch-based machines
# 4) jogmode==plus-minus implements halui plus-minus jogging which
# seems to work in both joint and world modes
# (tested on git master branch before integration of joints_axesN branch)
#
# 5) 19feb2014 notes for future work
# jogging non-trivkins machines in world mode
#
# jogmode==plus-minus-increment reserved for halui plus-minus-increment jogging
# incremental, world-mode jogging is not working in current git master
# (at this date, current git master has not merged a joint_axesN branch)
#
# see:
# http://www.linuxcnc.org/docs/html/man/man9/gantrykins.9.html
# Joint-mode (aka Free mode) supports continuous and incremental jogging.
# World-mode (aka Teleop mode) only supports continuous jogging.
#-----------------------------------------------------------------------
# Copyright: 2014
# Author: Dewey Garrett <dgarrett@panix.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#-----------------------------------------------------------------------
proc is_uniq {list_name} {
set tmp(xxxxxxxx) "" ;# make an array first
foreach item $list_name {
if {[array names tmp $item] == $item} {
return 0 ;# not unique
}
set tmp($item) $item
}
return 1 ;# unique
} ;# is_uniq
proc pin_exists {name} {
set line [lindex [split [show pin $name] \n] 2]
if {"$line" == ""} {
return 0 ;# fail
}
if [catch {scan $line "%d %s %s %s%s" owner type dir value pinname} msg] {
return 0 ;# fail
} else {
#puts stderr "OK:$owner $type $dir $value $pinname"
return 1 ;# ok
}
} ;# pin_exists
proc connect_pins {} {
foreach bname [lsort [array names ::XHC_HB04_BUTTONS]] {
set thepin $::XHC_HB04_BUTTONS($bname)
set thepin [lindex $thepin 0]
if {"$thepin" == "\"\""} {
#puts stderr "$::progname: no pin defined for <$bname>"
continue
}
# this pin is can specify std behavior
if { ([string tolower $bname] == "start-pause")
&& ([string tolower $thepin] == "std_start_pause")
} {
std_start_pause_button
puts stderr "$::progname: using std_start_pause_button"
continue
}
# these are warnings in the ini file examples but aren't real pins
if {[string tolower "$thepin"] == "caution"} {
puts stderr "$::progname: skipping button $bname marked <$thepin>"
continue
}
set fullbname xhc-hb04.button-$bname
if ![pin_exists $fullbname] {
puts stderr "$::progname: !!! <$fullbname> pin does not exist, continuing"
continue
}
if ![pin_exists $thepin] {
puts stderr "$::progname: !!! <$thepin> target pin does not exist, continuing"
continue
}
net pendant:$bname $fullbname => $thepin
}
} ;# connect_pins
proc wheel_setup {jogmode} {
# defaults if not in inifile:
set ::XHC_HB04_CONFIG(coef,0) 1.0
set ::XHC_HB04_CONFIG(coef,1) 1.0
set ::XHC_HB04_CONFIG(coef,2) 1.0
set ::XHC_HB04_CONFIG(coef,3) 1.0
if [info exists ::XHC_HB04_CONFIG(coefs)] {
set idx 0
foreach g $::XHC_HB04_CONFIG(coefs) {
set g1 $g
if {$g < 0} {
set g [expr -1 * $g]
puts stderr "$::progname: coef #$idx must be positive was:$g1, is:$g"
}
if {$g > 1} {
set g .5
puts stderr "$::progname: coef #$idx must < 1 coef was:$g1, is:$g"
}
set ::XHC_HB04_CONFIG(coef,$idx) $g
incr idx
}
}
# defaults if not in inifile:
set ::XHC_HB04_CONFIG(scale,0) 1.0
set ::XHC_HB04_CONFIG(scale,1) 1.0
set ::XHC_HB04_CONFIG(scale,2) 1.0
set ::XHC_HB04_CONFIG(scale,3) 1.0
if [info exists ::XHC_HB04_CONFIG(scales)] {
set idx 0
foreach g $::XHC_HB04_CONFIG(scales) {
set ::XHC_HB04_CONFIG(scale,$idx) $g
incr idx
}
}
net pendant:jog-scale <= xhc-hb04.jog.scale
net pendant:jog-counts <= xhc-hb04.jog.counts
net pendant:jog-counts-neg <= xhc-hb04.jog.counts-neg
set anames {x y z a}
# xhc-hb04.cc hardcodes pin names as: x y z a
# herein: Use names in order of the [XHC_HB04_CONFIG]coords
# specification in the inifile.
# These pin names will be a little confusing when
# using alternate axis sequences but the signal
# names will align correctly.
# With this method, any coord (xyzabcuvw) can be
# controlled by the wheel (providing it exists)
#
set idx 0
foreach coord $::XHC_HB04_CONFIG(coords) {
set axno $::XHC_HB04_CONFIG($coord,axno)
setp pendant_util.coef$idx $::XHC_HB04_CONFIG(coef,$idx)
setp pendant_util.scale$idx $::XHC_HB04_CONFIG(scale,$idx)
set acoord [lindex $anames $idx]
net pendant:pos-$coord halui.axis.$axno.pos-feedback \
=> xhc-hb04.$acoord.pos-absolute
net pendant:pos-rel-$coord halui.axis.$axno.pos-relative \
=> xhc-hb04.$acoord.pos-relative
net pendant:jog-scale => axis.$axno.jog-scale
net pendant:jog-counts => pendant_util.in$idx
net pendant:jog-counts-$coord-filtered <= pendant_util.out$idx \
=> axis.$axno.jog-counts
switch $jogmode {
normal - vnormal {
net pendant:jog-$coord xhc-hb04.jog.enable-$acoord \
=> axis.$axno.jog-enable
}
plus-minus {
# connect halui plus,minus pins
net pendant:jog-plus-$coord xhc-hb04.jog.plus-$acoord \
=> halui.jog.$axno.plus
net pendant:jog-minus-$coord xhc-hb04.jog.minus-$acoord \
=> halui.jog.$axno.minus
}
}
switch $jogmode {
vnormal {
setp axis.$axno.jog-vel-mode 1
}
}
incr idx
}
switch $jogmode {
normal - vnormal {
net pendant:jog-speed <= halui.max-velocity.value
# not used: xhc-hb04.jog.velocity
# not used: xhc-hb04.jog.max-velocity
}
plus-minus {
# Note: the xhc-hb04 driver manages xhc-hb04.jog.velocity
net pendant:jog-max-velocity <= halui.max-velocity.value
net pendant:jog-max-velocity => xhc-hb04.jog.max-velocity
net pendant:jog-speed <= xhc-hb04.jog.velocity
net pendant:jog-speed => halui.jog-speed
}
}
setp halui.feed-override.scale 0.01
net pendant:jog-counts => halui.feed-override.counts
setp halui.spindle-override.scale 0.01
net pendant:jog-counts => halui.spindle-override.counts
net pendant:jog-feed halui.feed-override.count-enable \
<= xhc-hb04.jog.enable-feed-override
net pendant:jog-feed2 halui.feed-override.value \
=> xhc-hb04.feed-override
net pendant:jog-spindle halui.spindle-override.count-enable
net pendant:jog-spindle <= xhc-hb04.jog.enable-spindle-override
net pendant:jog-spindle2 halui.spindle-override.value \
=> xhc-hb04.spindle-override
net pendant:spindle-rps motion.spindle-speed-cmd-rps \
=> xhc-hb04.spindle-rps
} ;# wheel_setup
proc std_start_pause_button {} {
# hardcoded setup for button-start-pause
net pendant:start-or-pause <= xhc-hb04.button-start-pause \
=> pendant_util.start-or-pause
net pendant:is-idle <= halui.program.is-idle \
=> pendant_util.is-idle
net pendant:is-paused <= halui.program.is-paused \
=> pendant_util.is-paused
net pendant:is-running <= halui.program.is-running \
=> pendant_util.is-running
net pendant:program-resume pendant_util.resume => halui.program.resume
net pendant:program-pause pendant_util.pause => halui.program.pause
net pendant:program-run pendant_util.run => halui.program.run
net pendant:program-run => halui.mode.auto
} ;# std_start_pause_button
proc popup_msg {msg} {
puts stderr "$msg"
if [catch {package require Tk
wm withdraw .
tk_messageBox \
-title "$::progname: loadusr" \
-type ok \
-message "$msg"
destroy .
} msg] {
puts stderr "$msg"
}
} ;# popup_msg
proc err_exit {msg} {
puts stderr "\n$::progname: $msg\n"
exit 1
} ;# err_exit
# begin------------------------------------------------------------------------
set ::progname "xhc-hb04.tcl"
set cfg xhc-hb04-layout2.cfg ;# default
foreach name [array names ::XHC_HB04_CONFIG] {
set ::XHC_HB04_CONFIG($name) [string trim $::XHC_HB04_CONFIG($name) "{}"]
}
if [info exists ::XHC_HB04_CONFIG(layout)] {
switch ${::XHC_HB04_CONFIG(layout)} {
1 {set cfg xhc-hb04-layout1.cfg}
2 {set cfg xhc-hb04-layout2.cfg}
default {
set msg "Unknown layout:<$::XHC_HB04_CONFIG(layout)>"
set msg "$msg\ntrying: $cfg"
popup_msg "$msg"
# keep going
}
}
}
if ![file exists $cfg] {
set msg "Cannot find file: <$cfg>\nCannot configure pendant\n"
set msg "$msg\nContinuing without xhc-hb04"
popup_msg "$msg"
return ;# not an exit
}
# require_pendant==yes: use -x, dont create pins unless connected
# require_pendant==no: create pins if not connected
if ![info exists ::XHC_HB04_CONFIG(require_pendant)] {
set ::XHC_HB04_CONFIG(require_pendant) yes ;# default
}
set dashx -x
switch $::XHC_HB04_CONFIG(require_pendant) {
no {set dashx ""}
}
if [info exists ::XHC_HB04_CONFIG(sequence)] {
set dashs "-s $::XHC_HB04_CONFIG(sequence)"
} else {
set dashs ""
}
set cmd "loadusr -W xhc-hb04 $dashx $dashs -I $cfg -H"
if [catch {eval $cmd} msg] {
set msg "\n$::progname: loadusr xhc-hb04:\n<$msg>\n\n"
set msg "$msg Is it plugged in?\n\n"
set msg "$msg Are permissions correct?\n\n"
set msg "$msg Continuing without xhc-hb04\n"
set msg "$msg \nFailing cmd:\n$cmd"
popup_msg "$msg"
return ;# not an exit
}
# jogmodes:
# normal: use motion pins:
# axis.N.jog-counts
# axis.N.jog-enable
# axis.N.jog-scale (machine units per count)
# plus-minus: use halui pins:
# halui.jog.N.plus (jog in + dir at jog-speed)
# halui.jog.N.minus (jog in - dir at jog-speed)
# halui.jog-speed (applies to plus-minus jogging only)
#
if ![info exists ::XHC_HB04_CONFIG(jogmode)] {
set ::XHC_HB04_CONFIG(jogmode) normal ;# default
}
set jogmode $::XHC_HB04_CONFIG(jogmode)
switch $jogmode {
normal {}
vnormal {}
plus-minus {}
default {
set ::XHC_HB04_CONFIG(jogmode) normal
set msg "Unkknown jogmode <$jogmode>"
set msg "$msg Using $::XHC_HB04_CONFIG(jogmode)"
popup_msg "$msg"
}
}
set ct 0; foreach coord {x y z a b c u v w} {
set ::XHC_HB04_CONFIG($coord,axno) $ct; incr ct
}
if [info exists ::XHC_HB04_CONFIG(coords)] {
if ![is_uniq $::XHC_HB04_CONFIG(coords)] {
err_exit "coords must be unique, not: <$::XHC_HB04_CONFIG(coords)>"
}
} else {
set ::XHC_HB04_CONFIG(coords) {x y z a} ;# default
}
if ![info exists ::XHC_HB04_CONFIG(threadname)] {
set ::XHC_HB04_CONFIG(threadname) "servo-thread" ;# default
}
loadrt xhc_hb04_util names=pendant_util
addf pendant_util $::XHC_HB04_CONFIG(threadname)
connect_pins ;# per ini file items: [XHC_HB04_BUTTONS]buttonname=pin
wheel_setup $::XHC_HB04_CONFIG(jogmode)
# jog wheel per ini file items:
# [XHC_HB04_CONFIG]coords,coefs,scales
#parray ::XHC_HB04_CONFIG
|