adding files
This commit is contained in:
140
my-emco-compact-5/comms.py
Normal file
140
my-emco-compact-5/comms.py
Normal file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
# list available ports with 'python -m serial.tools.list_ports'
|
||||
import serial
|
||||
import watchdog
|
||||
|
||||
## Default values ##
|
||||
BAUDRATE = 38400
|
||||
"""Default value for the baudrate in Baud (int)."""
|
||||
|
||||
PARITY = 'N' #serial.PARITY_NONE
|
||||
"""Default value for the parity. See the pySerial module for documentation. Defaults to serial.PARITY_NONE"""
|
||||
|
||||
BYTESIZE = 8
|
||||
"""Default value for the bytesize (int)."""
|
||||
|
||||
STOPBITS = 1
|
||||
"""Default value for the number of stopbits (int)."""
|
||||
|
||||
TIMEOUT = 0.05
|
||||
"""Default value for the timeout value in seconds (float)."""
|
||||
|
||||
CLOSE_PORT_AFTER_EACH_CALL = False
|
||||
"""Default value for port closure setting."""
|
||||
|
||||
|
||||
class Message:
|
||||
"""'container for messages. keeps two strings <message> and <value>"""
|
||||
def __init__(self, name = '', data = ''):
|
||||
self.name = name
|
||||
self.data = data
|
||||
|
||||
def __repr__(self):
|
||||
return 'msg: ' + self.name + ' val: ' + self.data
|
||||
|
||||
def copy(self, msg):
|
||||
self.name = msg.name
|
||||
self.data = msg.data
|
||||
|
||||
class instrument:
|
||||
"""rs232 port"""
|
||||
|
||||
def __init__(self,
|
||||
port,
|
||||
msg_handler,
|
||||
watchdog_enabled = False,
|
||||
watchdog_timeout = 2,
|
||||
watchdog_periodicity = 0.5):
|
||||
self.serial = serial.Serial()
|
||||
self.serial.port = port
|
||||
self.serial.baudrate = BAUDRATE
|
||||
self.serial.parity = PARITY
|
||||
self.serial.bytesize = BYTESIZE
|
||||
self.serial.stopbits = STOPBITS
|
||||
self.serial.xonxoff = False # disable software flow control
|
||||
self.serial.timeout = TIMEOUT
|
||||
self.portOpened = False
|
||||
self.msg_hdlr = msg_handler
|
||||
|
||||
self.watchdog_daemon = watchdog.WatchDogDaemon(watchdog_timeout,
|
||||
watchdog_timeout,
|
||||
watchdog_enabled)
|
||||
self.watchdog_daemon.reset = self._watchdogClose #register watchdog reset function
|
||||
self.closed_by_watchdog = False
|
||||
|
||||
self.open()
|
||||
|
||||
def open(self):
|
||||
try:
|
||||
self.serial.open()
|
||||
self.portOpened = True
|
||||
print('comms::opening port')
|
||||
except serial.SerialException:
|
||||
self.portOpened = False
|
||||
print('unable to open port...')
|
||||
|
||||
def close(self):
|
||||
self.serial.close()
|
||||
self.portOpened = False
|
||||
print('comms::closeing port')
|
||||
|
||||
def dataReady(self):
|
||||
if self.portOpened:
|
||||
return self.serial.in_waiting
|
||||
else:
|
||||
return False
|
||||
|
||||
def readMessages(self):
|
||||
"""reads serial port. creates an array of events
|
||||
output: array of events:
|
||||
"""
|
||||
if self.closed_by_watchdog:
|
||||
self.closed_by_watchdog = False
|
||||
self.open()
|
||||
|
||||
while self.dataReady():
|
||||
msg_str = self._read().split('_', 1)
|
||||
|
||||
if msg_str[0] != '':
|
||||
self.msg_hdlr(Message(*msg_str))
|
||||
self.watchdog_daemon.ping()
|
||||
|
||||
def generateEvent(self, name, data = ''):
|
||||
self.writeMessage(Message(name, data))
|
||||
|
||||
def writeMessage(self, m):
|
||||
self._write(m.name)
|
||||
if m.data != '':
|
||||
#self._write(m.data)
|
||||
self._write('_' + str(m.data))
|
||||
|
||||
self._write('\n')
|
||||
|
||||
def enableWatchdog(self, enable):
|
||||
self.watchdog_daemon.setEnabled(enable)
|
||||
|
||||
def _write(self, str):
|
||||
if self.portOpened == True:
|
||||
#serial expects a byte-array and not a string
|
||||
self.serial.write(''.join(str).encode('utf-8', 'ignore'))
|
||||
|
||||
def _read(self):
|
||||
""" returns string read from serial port """
|
||||
b = ''
|
||||
if self.portOpened == True:
|
||||
b = self.serial.read_until() #blocks until '\n' received or timeout
|
||||
|
||||
return b.decode('utf-8', 'ignore') #convert byte array to string
|
||||
|
||||
def _watchdogClose(self):
|
||||
self.closed_by_watchdog = True
|
||||
self.close()
|
||||
|
||||
def _is_number(self, s):
|
||||
""" helper function to evaluate if input text represents an integer or not """
|
||||
try:
|
||||
int(s)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
4
my-emco-compact-5/custom-m-codes/M103
Normal file
4
my-emco-compact-5/custom-m-codes/M103
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# axis reload after
|
||||
axis-remote --reload
|
||||
exit 0
|
||||
5
my-emco-compact-5/custom-m-codes/M199
Normal file
5
my-emco-compact-5/custom-m-codes/M199
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# set spindle speed gain corresponding to selected motor-spindle-belt-wheel
|
||||
halcmd setp scale.1.gain $1
|
||||
halcmd setp scale.1.offset $2
|
||||
exit 0
|
||||
37
my-emco-compact-5/custom-m-codes/extend_m0.ngc
Normal file
37
my-emco-compact-5/custom-m-codes/extend_m0.ngc
Normal file
@@ -0,0 +1,37 @@
|
||||
; extend M0 to:
|
||||
; turn off spindle, flood, mist if optional stop = 1 and block delete is off
|
||||
;
|
||||
; on cycle restart:
|
||||
; turn on spindle
|
||||
; turn mist on if it was on before the m1
|
||||
; turn flood on if it was on before the m1
|
||||
|
||||
o<extend_m0> sub
|
||||
;(debug, extend_m0:)
|
||||
|
||||
; record whether mist/flood were on
|
||||
#<mist> = #<_mist>
|
||||
#<flood> = #<_flood>
|
||||
#<spindle_on> = #<_spindle_on>
|
||||
|
||||
M5 M9 ; stop spindle, mist+flood off
|
||||
|
||||
m0 (refer to builtin m0)
|
||||
|
||||
; restore mist, flood setting
|
||||
o100 if [#<mist>]
|
||||
m7
|
||||
o100 endif
|
||||
|
||||
o200 if [#<flood>]
|
||||
m8
|
||||
o200 endif
|
||||
|
||||
o300 if [#<spindle_on>]
|
||||
m3 ; spindle on
|
||||
o300 endif
|
||||
|
||||
;(debug, extend_m0 done)
|
||||
|
||||
o<extend_m0> endsub
|
||||
m2
|
||||
34
my-emco-compact-5/custom-m-codes/extend_m1.ngc
Normal file
34
my-emco-compact-5/custom-m-codes/extend_m1.ngc
Normal file
@@ -0,0 +1,34 @@
|
||||
; extend M1 to:
|
||||
; turn off spindle, flood, mist if optional stop = 1 and block delete is off
|
||||
;
|
||||
; on cycle restart:
|
||||
; turn on spindle
|
||||
; turn mist on if it was on before the m1
|
||||
; turn flood on if it was on before the m1
|
||||
|
||||
o<extend_m1> sub
|
||||
(debug, extend_m1:)
|
||||
|
||||
; record whether mist/flood were on
|
||||
#<mist> = #<_mist>
|
||||
#<flood> = #<_flood>
|
||||
|
||||
/M5 M9 ; stop spindle, mist+flood off
|
||||
|
||||
/m1 (refer to builtin m1)
|
||||
|
||||
; restore mist, flood setting
|
||||
/o100 if [#<mist>]
|
||||
/ m7
|
||||
/o100 endif
|
||||
|
||||
/o200 if [#<flood>]
|
||||
/ m8
|
||||
/o200 endif
|
||||
|
||||
/M3 ; spindle on
|
||||
|
||||
(debug, extend_m1 done)
|
||||
|
||||
o<extend_m1> endsub
|
||||
m2
|
||||
31
my-emco-compact-5/custom-m-codes/mysetspeed.ngc
Normal file
31
my-emco-compact-5/custom-m-codes/mysetspeed.ngc
Normal file
@@ -0,0 +1,31 @@
|
||||
o<mysetspeed> sub
|
||||
(DEBUG, S#<speed> setspeed)
|
||||
o10 if [#<speed> LE 950]
|
||||
o11 if [#4997 NE 1]
|
||||
(MSG, Set spindle speed selection belt in AC1 position)
|
||||
O<myspindlegain> call [0.48483] [20.16466]
|
||||
#4997 = 1
|
||||
o11 endif
|
||||
o10 else
|
||||
o20 if [#<speed> LE 1500]
|
||||
o21 if [#4997 NE 2]
|
||||
(MSG, Set spindle speed selection belt in AC2 position)
|
||||
O<myspindlegain> call [0.32571] [-8.05714]
|
||||
#4997 = 2
|
||||
o21 endif
|
||||
o20 else
|
||||
o30 if [#<speed> LE 2400]
|
||||
o31 if [#4997 NE 3]
|
||||
(MSG, Set spindle speed selection belt in AC3 position)
|
||||
O<myspindlegain> call [0.20098] [22.64117]
|
||||
#4997 = 3
|
||||
o31 endif
|
||||
o30 else
|
||||
(MSG, Unsupported spindle speed. will continue anyway. Safest is probably to abort and regenerate program)
|
||||
o30 endif
|
||||
o20 endif
|
||||
o10 endif
|
||||
S#<speed>
|
||||
M0
|
||||
o<mysetspeed> endsub [1]
|
||||
M2
|
||||
6
my-emco-compact-5/custom-m-codes/myspindlegain.ngc
Normal file
6
my-emco-compact-5/custom-m-codes/myspindlegain.ngc
Normal file
@@ -0,0 +1,6 @@
|
||||
o<myspindlegain> sub
|
||||
M199 P#1 Q#2
|
||||
#4998 = #1
|
||||
#4999 = #2
|
||||
o<myspindlegain> endsub
|
||||
M2
|
||||
12
my-emco-compact-5/custom-m-codes/myspindlespeeddown.ngc
Normal file
12
my-emco-compact-5/custom-m-codes/myspindlespeeddown.ngc
Normal file
@@ -0,0 +1,12 @@
|
||||
o<myspindlespeeddown> sub
|
||||
o10 if [#<_spindle_on> EQ 1]
|
||||
O20 if [#<_rpm> GT 100]
|
||||
#<speed-cmd> = [#<_rpm> - 100]
|
||||
O20 else
|
||||
#<speed-cmd> = 0
|
||||
M5
|
||||
O20 endif
|
||||
S#<speed-cmd>
|
||||
o10 endif
|
||||
o<myspindlespeeddown> endsub
|
||||
M2
|
||||
11
my-emco-compact-5/custom-m-codes/myspindlespeedup.ngc
Normal file
11
my-emco-compact-5/custom-m-codes/myspindlespeedup.ngc
Normal file
@@ -0,0 +1,11 @@
|
||||
o<myspindlespeedup> sub
|
||||
;o10 if [#<_spindle_on> EQ 1]
|
||||
#<speed-cmd> = [#<_rpm>+100]
|
||||
O10 if [#<speed-cmd> GT 4500]
|
||||
#<speed-cmd> = 4500
|
||||
O10 endif
|
||||
S#<speed-cmd>
|
||||
M3
|
||||
;o10 endif
|
||||
o<myspindlespeedup> endsub
|
||||
M2
|
||||
10
my-emco-compact-5/custom-m-codes/myspindlestart.ngc
Normal file
10
my-emco-compact-5/custom-m-codes/myspindlestart.ngc
Normal file
@@ -0,0 +1,10 @@
|
||||
o<myspindlestart> sub
|
||||
o10 if [#<_spindle_on> EQ 1]
|
||||
M5
|
||||
o10 else
|
||||
S800
|
||||
M3
|
||||
o10 endif
|
||||
;M103
|
||||
o<myspindlestart> endsub
|
||||
M2
|
||||
23
my-emco-compact-5/custom-m-codes/mytouch.ngc
Normal file
23
my-emco-compact-5/custom-m-codes/mytouch.ngc
Normal file
@@ -0,0 +1,23 @@
|
||||
o<mytouch> sub
|
||||
o10 if [EXISTS[#<_hal[jog-axis-sel]>]]
|
||||
#<selected-axis> = #<_hal[jog-axis-sel]>
|
||||
;(DEBUG, my-mpg.axis-selector: #<selected-axis>)
|
||||
|
||||
(touch off)
|
||||
o20 if [#<selected-axis> EQ 0]
|
||||
G10 L20 P0 X0
|
||||
M103
|
||||
(MSG, touch off x axis)
|
||||
o20 endif
|
||||
|
||||
(touch off z axis)
|
||||
o30 if [#<selected-axis> EQ 1]
|
||||
G10 L20 P0 Z0
|
||||
M103
|
||||
(MSG, touch off z axis)
|
||||
o30 endif
|
||||
o10 else
|
||||
(DEBUG, didn't exist)
|
||||
o10 endif
|
||||
o<mytouch> endsub
|
||||
M2
|
||||
127
my-emco-compact-5/custom.hal
Normal file
127
my-emco-compact-5/custom.hal
Normal file
@@ -0,0 +1,127 @@
|
||||
# Include your custom HAL commands here
|
||||
# This file will not be overwritten when you run stepconf again
|
||||
loadrt near names=spindle-at-speed
|
||||
loadrt siggen num_chan=1 #spincle speed control
|
||||
loadrt and2 count=4 # 0 used in e-stop chain,
|
||||
# 1,2,3 used för connecting spindle speed gain selection
|
||||
loadrt classicladder_rt
|
||||
loadrt timedelay count=1
|
||||
|
||||
addf spindle-at-speed servo-thread
|
||||
addf scale.1 servo-thread
|
||||
addf scale.2 servo-thread
|
||||
addf scale.3 servo-thread
|
||||
addf scale.4 servo-thread
|
||||
addf siggen.0.update servo-thread
|
||||
addf and2.0 servo-thread
|
||||
addf and2.1 servo-thread
|
||||
addf and2.2 servo-thread
|
||||
addf and2.3 servo-thread
|
||||
addf classicladder.0.refresh servo-thread
|
||||
addf timedelay.0 servo-thread
|
||||
|
||||
loadusr -Wn my-mpg python3 serialEventHandler.py --port=/dev/ttyUSB0 -c my-mpg mpg.xml
|
||||
loadusr classicladder test_ladder.clp --nogui
|
||||
#loadusr classicladder test_ladder.clp
|
||||
|
||||
### spindle at speed monitoring ###
|
||||
setp spindle-at-speed.scale 0.98
|
||||
setp spindle-at-speed.difference 10
|
||||
net spindle-cmd-rpm => spindle-at-speed.in1
|
||||
#net spindle-rpm-filtered-low-res => spindle-at-speed.in2 # moved to postgui
|
||||
|
||||
### temp... until encoder works...
|
||||
#net spindle-ready <= spindle-at-speed.out => spindle.0.at-speed
|
||||
net spindle-ready => spindle.0.at-speed
|
||||
sets spindle-ready 1
|
||||
###
|
||||
|
||||
### spindle cw start/stop ###
|
||||
net spindle-cw <= spindle.0.forward
|
||||
net spindle-cw => parport.0.pin-14-out # turn on spindle
|
||||
### spindle ccw start/stop ###
|
||||
net spindle-ccw <= spindle.0.reverse
|
||||
net spindle-ccw => parport.0.pin-17-out # turn on spindle ccw
|
||||
|
||||
### spindle speed ctrl ###
|
||||
# gain and offset is set via M199/O<myspindlegain> when homed
|
||||
#setp scale.1.gain 0.473
|
||||
#setp scale.1.offset 26.5
|
||||
setp siggen.0.amplitude 1
|
||||
setp siggen.0.offset 0
|
||||
|
||||
net spindle-cmd-rpm-abs => scale.1.in
|
||||
net scaled-spindle-cmd scale.1.out => siggen.0.frequency
|
||||
net spindle-freq siggen.0.clock => parport.0.pin-16-out
|
||||
|
||||
|
||||
### e-stop chain ###
|
||||
net estop-internal <= iocontrol.0.user-enable-out
|
||||
#estop-external connected to parport.0.pin-11-in-not
|
||||
|
||||
net estop-internal => and2.0.in0
|
||||
net estop-external => and2.0.in1
|
||||
net estop-chain and2.0.out => iocontrol.0.emc-enable-in
|
||||
|
||||
|
||||
### pendant ##########################################
|
||||
|
||||
# mpg spindle speed control
|
||||
net spindle-rpm-cmd-up classicladder.0.out-08 halui.mdi-command-00
|
||||
net spindle-rpm-cmd-down classicladder.0.out-09 halui.mdi-command-01
|
||||
|
||||
# axis selector connects to x, z axis enable
|
||||
net jog-axis-sel my-mpg.axis-selector
|
||||
net jog-axis-sel classicladder.0.s32in-00
|
||||
|
||||
net jog-x-enable classicladder.0.out-00
|
||||
net jog-z-enable classicladder.0.out-01
|
||||
net jog-x-enable halui.axis.x.select
|
||||
net jog-z-enable halui.axis.z.select
|
||||
|
||||
# jog scale selector/velocity mode
|
||||
setp scale.2.gain 0.01
|
||||
setp scale.2.offset 0
|
||||
net jog-scale-sel my-mpg.scale-selector
|
||||
net jog-scale-sel classicladder.0.s32in-01
|
||||
net jog-increment-100 classicladder.0.floatout-00 scale.2.in
|
||||
net jog-increment halui.axis.selected.increment scale.2.out
|
||||
|
||||
# jogging plus and minus
|
||||
setp halui.axis.jog-speed 800
|
||||
net mpg-jog-plus-in my-mpg.jog-pos-btn => classicladder.0.in-00
|
||||
net mpg-jog-minus-in my-mpg.jog-neg-btn => classicladder.0.in-01
|
||||
|
||||
net mpg-jog-plus-inc classicladder.0.out-04 => halui.axis.selected.increment-plus
|
||||
net mpg-jog-minus-inc classicladder.0.out-06 => halui.axis.selected.increment-minus
|
||||
net mpg-jog-plus classicladder.0.out-05 => halui.axis.selected.plus
|
||||
net mpg-jog-minus classicladder.0.out-07 => halui.axis.selected.minus
|
||||
|
||||
# connect Func-button
|
||||
net func-button my-mpg.func-btn halui.mdi-command-02
|
||||
|
||||
# connect E-Stop button
|
||||
net estop-button halui.estop.activate <= my-mpg.estop-btn
|
||||
|
||||
# joystic
|
||||
setp scale.3.gain 0.01
|
||||
setp scale.3.offset 0
|
||||
setp scale.4.gain 0.01
|
||||
setp scale.4.offset 0
|
||||
net joystick-x my-mpg.joystick-x scale.3.in
|
||||
net joystick-x-scaled scale.3.out halui.axis.x.analog
|
||||
|
||||
net joystick-z my-mpg.joystick-z scale.4.in
|
||||
net joystick-z-scaled scale.4.out halui.axis.z.analog
|
||||
|
||||
### Misc #################################################
|
||||
|
||||
# all-homed used to enable some of the panels and trigger some other stuff
|
||||
net all-homed motion.is-all-homed
|
||||
|
||||
# set the saved spindle speed selection gain
|
||||
#setp timedelay.0.on-delay 1
|
||||
net all-homed timedelay.0.in
|
||||
net all-homed-delayed timedelay.0.out
|
||||
net all-homed-delayed halui.mdi-command-06
|
||||
|
||||
18
my-emco-compact-5/custom_postgui.hal
Normal file
18
my-emco-compact-5/custom_postgui.hal
Normal file
@@ -0,0 +1,18 @@
|
||||
# Include your custom_postgui HAL commands here
|
||||
# This file will not be overwritten when you run stepconf again
|
||||
|
||||
# Filtering and scaling...
|
||||
setp encoder.1.counter-mode true
|
||||
setp encoder.1.position-scale 1
|
||||
setp scale.0.gain 60
|
||||
setp lowpass.0.gain .07
|
||||
net spindle-index encoder.1.phase-A
|
||||
net spindle-vel-rps-low-res encoder.1.velocity => lowpass.0.in
|
||||
|
||||
net spindle-rps-filtered-low-res lowpass.0.out scale.0.in
|
||||
net spindle-rpm-filtered-low-res scale.0.out
|
||||
net spindle-rpm-filtered-low-res gmoccapy.spindle_feedback_bar
|
||||
|
||||
net spindle-rpm-filtered-low-res => spindle-at-speed.in2
|
||||
net spindle-ready => gmoccapy.spindle_at_speed_led
|
||||
|
||||
16
my-emco-compact-5/emcopos.txt
Normal file
16
my-emco-compact-5/emcopos.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
0.00000000000000000
|
||||
5
my-emco-compact-5/func-btn.xml
Normal file
5
my-emco-compact-5/func-btn.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<mpg>
|
||||
<function>Touch off selected axis<gcode>O<mytouch>call</gcode></function>
|
||||
<function>Return to safe Z<gcode>G53 G0 Z0</gcode></function>
|
||||
<function>Return to home<gcode>G53 G0 X0 Y0 Z0</gcode></function>
|
||||
</mpg>
|
||||
141
my-emco-compact-5/gladevcp-handler.py
Normal file
141
my-emco-compact-5/gladevcp-handler.py
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/ python3
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
|
||||
from gi.repository import Gtk
|
||||
import linuxcnc
|
||||
import hal
|
||||
import hal_glib
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
debug = 0
|
||||
|
||||
"""class ToolTableParser:
|
||||
def __init__(self, f):
|
||||
self.f = open(f, 'r')
|
||||
self.list = Gtk.ListStore(int, str, str)
|
||||
self._parse_file()
|
||||
self.f.close()
|
||||
|
||||
def __repr__(self):
|
||||
ret_str = ''
|
||||
for l in self.list:
|
||||
ret_str += str(l) + '\n'
|
||||
return ret_str
|
||||
|
||||
def get_parsed_data(self):
|
||||
return self.list
|
||||
|
||||
def _parse_file(self):
|
||||
lines = self.f.readlines()
|
||||
|
||||
i = 0
|
||||
for line in lines:
|
||||
tool_nbr = line.split(' ')[0]
|
||||
tool_descr = tool_nbr + ' ' + line.split(';')[1]
|
||||
self.list.append([i, tool_descr, tool_nbr])
|
||||
i = i+1
|
||||
"""
|
||||
|
||||
class XmlParser:
|
||||
def __init__(self, f):
|
||||
self.tree = []
|
||||
self.list = Gtk.ListStore(int, str, str)
|
||||
|
||||
self._parse_file(f)
|
||||
|
||||
def get_parsed_data(self):
|
||||
return self.list
|
||||
|
||||
def _parse_file(self, f):
|
||||
self.tree = ET.parse(f)
|
||||
root = self.tree.getroot()
|
||||
|
||||
i = 0
|
||||
for func in root.iter('function'):
|
||||
gcode = func.find('gcode')
|
||||
|
||||
# create the LinuxCNC hal pin and create mapping dictionary binding incomming events with data and the hal pins
|
||||
if gcode is not None:
|
||||
self.list.append([i, func.text, gcode.text])
|
||||
i = i+1
|
||||
|
||||
class HandlerClass:
|
||||
|
||||
def on_destroy(self,obj,data=None):
|
||||
print("on_destroy, combobox active=%d" %(self.combo.get_active()))
|
||||
self.halcomp.exit() # avoid lingering HAL component
|
||||
Gtk.main_quit()
|
||||
|
||||
"""def on_changed(self, combobox, data=None):
|
||||
if self.tool_combo_initiated:
|
||||
model = combobox.get_model()
|
||||
tool_change_cmd = 'M6' + ' ' + model[combobox.get_active()][2] + ' ' + 'G43'
|
||||
self._send_mdi(tool_change_cmd)
|
||||
print(tool_change_cmd)"""
|
||||
|
||||
def __init__(self, halcomp, builder, useropts):
|
||||
self.linuxcnc_status = linuxcnc.stat()
|
||||
self.linuxcnc_cmd = linuxcnc.command()
|
||||
self.halcomp = halcomp
|
||||
self.builder = builder
|
||||
self.useropts = useropts
|
||||
|
||||
self.trigger1 = hal_glib.GPin(halcomp.newpin('trigger_pin', hal.HAL_BIT, hal.HAL_IN))
|
||||
self.trigger1.connect('value-changed', self._trigger_change)
|
||||
|
||||
#self.trigger2 = hal_glib.GPin(halcomp.newpin('saved-tool-pin', hal.HAL_U32, hal.HAL_IN))
|
||||
#self.trigger2.connect('value-changed', self._init_tool_combo)
|
||||
|
||||
func_list = XmlParser('func-btn.xml').get_parsed_data()
|
||||
self.func_combo = self.builder.get_object('func-btn-combo')
|
||||
self.func_combo.set_model(func_list)
|
||||
self.func_combo.set_entry_text_column(1)
|
||||
self.func_combo.set_active(0)
|
||||
|
||||
#tool_list = ToolTableParser('tool.tbl').get_parsed_data()
|
||||
#self.tool_combo = self.builder.get_object('tool-combo')
|
||||
#self.tool_combo.set_model(tool_list)
|
||||
#self.tool_combo.set_entry_text_column(2)
|
||||
#self.tool_combo.set_active(0)
|
||||
|
||||
renderer_text = Gtk.CellRendererText()
|
||||
self.func_combo.pack_start(renderer_text, True)
|
||||
#self.tool_combo.pack_start(renderer_text, True)
|
||||
#self.tool_combo_initiated = False
|
||||
|
||||
def _trigger_change(self, pin, userdata = None):
|
||||
#setp gladevcp.trigger_pin 1
|
||||
#print "pin value changed to: " + str(pin.get())
|
||||
#print "pin name= " + pin.get_name()
|
||||
#print "pin type= " + str(pin.get_type())
|
||||
#print "active " + str(self.combo.get_active())
|
||||
if pin.get() is True:
|
||||
model = self.func_combo.get_model()
|
||||
self._send_mdi(model[self.func_combo.get_active()][2])
|
||||
|
||||
#def _init_tool_combo(self, pin, userdata = None):
|
||||
#setp gladevcp.saved_tool_pin 2
|
||||
# self.tool_combo.set_active(pin.get())
|
||||
# self.tool_combo_initiated = True
|
||||
|
||||
|
||||
def _ok_for_mdi(self):
|
||||
self.linuxcnc_status.poll()
|
||||
return not self.linuxcnc_status.estop and self.linuxcnc_status.enabled and (self.linuxcnc_status.homed.count(1) == self.linuxcnc_status.joints) and (self.linuxcnc_status.interp_state == linuxcnc.INTERP_IDLE)
|
||||
|
||||
def _send_mdi(self, mdi_cmd_str):
|
||||
if self._ok_for_mdi():
|
||||
self.linuxcnc_cmd.mode(linuxcnc.MODE_MDI)
|
||||
self.linuxcnc_cmd.wait_complete() # wait until mode switch executed
|
||||
self.linuxcnc_cmd.mdi(mdi_cmd_str)
|
||||
|
||||
def get_handlers(halcomp, builder, useropts):
|
||||
|
||||
global debug
|
||||
for cmd in useropts:
|
||||
exec(cmd in globals())
|
||||
|
||||
return [HandlerClass(halcomp, builder, useropts)]
|
||||
|
||||
122
my-emco-compact-5/linuxcnc.var
Normal file
122
my-emco-compact-5/linuxcnc.var
Normal file
@@ -0,0 +1,122 @@
|
||||
4997 1.000000
|
||||
4998 0.484830
|
||||
4999 20.164660
|
||||
5161 0.000000
|
||||
5162 0.000000
|
||||
5163 0.000000
|
||||
5164 0.000000
|
||||
5165 0.000000
|
||||
5166 0.000000
|
||||
5167 0.000000
|
||||
5168 0.000000
|
||||
5169 0.000000
|
||||
5181 0.000000
|
||||
5182 0.000000
|
||||
5183 0.000000
|
||||
5184 0.000000
|
||||
5185 0.000000
|
||||
5186 0.000000
|
||||
5187 0.000000
|
||||
5188 0.000000
|
||||
5189 0.000000
|
||||
5210 0.000000
|
||||
5211 0.000000
|
||||
5212 0.000000
|
||||
5213 0.000000
|
||||
5214 0.000000
|
||||
5215 0.000000
|
||||
5216 0.000000
|
||||
5217 0.000000
|
||||
5218 0.000000
|
||||
5219 0.000000
|
||||
5220 1.000000
|
||||
5221 -8.934820
|
||||
5222 0.000000
|
||||
5223 8.596005
|
||||
5224 0.000000
|
||||
5225 0.000000
|
||||
5226 0.000000
|
||||
5227 0.000000
|
||||
5228 0.000000
|
||||
5229 0.000000
|
||||
5230 0.000000
|
||||
5241 0.000000
|
||||
5242 0.000000
|
||||
5243 0.000000
|
||||
5244 0.000000
|
||||
5245 0.000000
|
||||
5246 0.000000
|
||||
5247 0.000000
|
||||
5248 0.000000
|
||||
5249 0.000000
|
||||
5250 0.000000
|
||||
5261 0.000000
|
||||
5262 0.000000
|
||||
5263 0.000000
|
||||
5264 0.000000
|
||||
5265 0.000000
|
||||
5266 0.000000
|
||||
5267 0.000000
|
||||
5268 0.000000
|
||||
5269 0.000000
|
||||
5270 0.000000
|
||||
5281 0.000000
|
||||
5282 0.000000
|
||||
5283 0.000000
|
||||
5284 0.000000
|
||||
5285 0.000000
|
||||
5286 0.000000
|
||||
5287 0.000000
|
||||
5288 0.000000
|
||||
5289 0.000000
|
||||
5290 0.000000
|
||||
5301 0.000000
|
||||
5302 0.000000
|
||||
5303 0.000000
|
||||
5304 0.000000
|
||||
5305 0.000000
|
||||
5306 0.000000
|
||||
5307 0.000000
|
||||
5308 0.000000
|
||||
5309 0.000000
|
||||
5310 0.000000
|
||||
5321 0.000000
|
||||
5322 0.000000
|
||||
5323 0.000000
|
||||
5324 0.000000
|
||||
5325 0.000000
|
||||
5326 0.000000
|
||||
5327 0.000000
|
||||
5328 0.000000
|
||||
5329 0.000000
|
||||
5330 0.000000
|
||||
5341 0.000000
|
||||
5342 0.000000
|
||||
5343 0.000000
|
||||
5344 0.000000
|
||||
5345 0.000000
|
||||
5346 0.000000
|
||||
5347 0.000000
|
||||
5348 0.000000
|
||||
5349 0.000000
|
||||
5350 0.000000
|
||||
5361 0.000000
|
||||
5362 0.000000
|
||||
5363 0.000000
|
||||
5364 0.000000
|
||||
5365 0.000000
|
||||
5366 0.000000
|
||||
5367 0.000000
|
||||
5368 0.000000
|
||||
5369 0.000000
|
||||
5370 0.000000
|
||||
5381 0.000000
|
||||
5382 0.000000
|
||||
5383 0.000000
|
||||
5384 0.000000
|
||||
5385 0.000000
|
||||
5386 0.000000
|
||||
5387 0.000000
|
||||
5388 0.000000
|
||||
5389 0.000000
|
||||
5390 0.000000
|
||||
339
my-emco-compact-5/macros/LICENSE
Normal file
339
my-emco-compact-5/macros/LICENSE
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
3057
my-emco-compact-5/macros/LatheMacro.svg
Normal file
3057
my-emco-compact-5/macros/LatheMacro.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 4.8 MiB |
77
my-emco-compact-5/macros/README
Normal file
77
my-emco-compact-5/macros/README
Normal file
@@ -0,0 +1,77 @@
|
||||
This folder contains a number of simulated lathe configs.
|
||||
|
||||
the "lathemacro" config offers a number of simple macros to perform
|
||||
the most common lathe operations.
|
||||
|
||||
The GUI that controls the macros can be viewed by clicking the "Cycles"
|
||||
tab top left of the graphical preview window.
|
||||
|
||||
There are two load-time options to control the tab behaviour:
|
||||
1) norun will hide the action button, use this if you want to use only
|
||||
a physical button (connected to gladevcp.cycle-start) to start the macros
|
||||
(Strongly recommended, especially with Touchy)
|
||||
2) notouch will allow keyboard editing of the spinboxes. Otherwise the
|
||||
custom numeric keyboard will be shown.
|
||||
|
||||
An example loadrt line, as used here in the Gmoccapy demo is:
|
||||
|
||||
[DISPLAY]
|
||||
EMBED_TAB_COMMAND = halcmd loadusr -Wn gladevcp gladevcp -c gladevcp -U notouch=1 -U norun=0 -u lathehandler.py -x {XID} lathemacro.ui
|
||||
|
||||
The window will resize slowly if you grab the corner and move the mouse
|
||||
inside the window. It's not as bad as it was, but still needs work.
|
||||
You may need to click the unmaximise button in the toolbar to get a
|
||||
window border to be able to use the resize handles.
|
||||
|
||||
To relocate the files outside of the config directory (i.e. the direcrory containing the INI file) use, for example,
|
||||
"macros/lathehandeler.py" and "macros/lathemacro.ui" in the EMBED_TAB_COMMAND above. The system will look for the
|
||||
LatheMacro.svg file in the same path as the lathehandler.py file. If you need to relocate or rename this file then
|
||||
use "-U svgfile=/full/path/to/svgfile.svg" in the embed command.
|
||||
|
||||
Notes on the keyboard:
|
||||
As well as the obvious functions and unit conversions, it can be used to
|
||||
enter fractions. For example if you type 1.1/2 it will automatically
|
||||
update to display 1.5000 and 16.17/64 will show 16.2656.
|
||||
This can be used in a limited way to halve the onscreen value eg for
|
||||
entering radius instead of diameter.
|
||||
However it only works for whole numbers: 100/2 will become 50 but
|
||||
3.14149/2 is interpreted as 3 and 14 thousand halves so won't work.
|
||||
|
||||
Notes on adding your own cycles:
|
||||
Create a new G-code subroutine in the same format as the existing ones.
|
||||
In Glade add a new tab to the 'tabs1' notebook and give it a name matching
|
||||
the new cycle.
|
||||
Edit the action button (inside an eventbox) to call the new G-code sub.
|
||||
Rename the action button to match the tab name and append '.action' eg
|
||||
MyCycle.action
|
||||
|
||||
Create new artwork. I used Fusion360, the models are here:
|
||||
https://a360.co/3uFPZNv
|
||||
and the drawings are here:
|
||||
https://a360.co/3uFPZNv
|
||||
Esport the drawing page as PDF and import into the lathemacro.svg file in
|
||||
Inkscape. You will need to resize. Add your own arrows and annotations.
|
||||
|
||||
Save the new layer in a layer named "layerN" (lower case) where N is the
|
||||
tab number, starting at zero. You will need to invoke the XML editor for
|
||||
this (Shift-Cmd-X on Mac)
|
||||
|
||||
The entry boxes are positioned relative to a 1500 x 1000 image; the
|
||||
original size of the SVG. So you can hover your mouse over the image in
|
||||
Inkscape to determine the coordinates.
|
||||
In the in the case of on-drawing controls the coordinates are entered as
|
||||
an XML comment in the Tooltip for the control in x,y format (The surface speed,
|
||||
tool and coolant do not need this, they are in a fixed table)
|
||||
|
||||
An example:
|
||||
|
||||
<!--300,711->Peck distance
|
||||
|
||||
Make sure the comment has "use markup" selected for the tooltip.
|
||||
Also ensure that the control has the "show_keyb" function allocated for
|
||||
the Widget->button_press event. If you copy-paste a tab and copy-paste
|
||||
extra controls this should be automatic.
|
||||
_All_ your new spinboxes will need their own new Adjustment, or they will
|
||||
change value when you alter the original spinbox that they are a copy of.
|
||||
|
||||
|
||||
BIN
my-emco-compact-5/macros/__pycache__/lathehandler.cpython-37.pyc
Normal file
BIN
my-emco-compact-5/macros/__pycache__/lathehandler.cpython-37.pyc
Normal file
Binary file not shown.
64
my-emco-compact-5/macros/boring.ngc
Normal file
64
my-emco-compact-5/macros/boring.ngc
Normal file
@@ -0,0 +1,64 @@
|
||||
;boring
|
||||
|
||||
O<boring> sub
|
||||
|
||||
G8 ; Radius mode (easier maths)
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
G91.1 ; but not for arcs
|
||||
|
||||
M6 T#8 G43
|
||||
|
||||
#1 = [#1 / 2] ; because of radius mode
|
||||
|
||||
#14 = [#<_x>] (starting X)
|
||||
#13 = #<_z> (starting Z)
|
||||
|
||||
#20 = [#6 * SIN[#7]]
|
||||
#21 = [-#6 * COS[#7]]
|
||||
#22 = [#6 / COS[#7]]
|
||||
#23 = [#5 + #6 - #20]
|
||||
#24 = [[#23 - #13] * TAN[#7]]
|
||||
|
||||
|
||||
G96 D2500 S#2 ; Constant Surface Speed Mode
|
||||
m3 ;Start Spindle
|
||||
g95 F#4 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#9 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
g4p1 ; Wait to reach speed
|
||||
|
||||
(debug, Turning finish dia #1 start dia #14 start length #13 finish length #5 coolant #9)
|
||||
O100 WHILE [#14 LT [#1 - #3]]
|
||||
g0 X #14
|
||||
#14=[#14 + #3]
|
||||
G1 X #14
|
||||
G1 Z #23 X[#14 + #24]
|
||||
O101 IF [#6 GT 0]
|
||||
G3 Z#5 X[#14 + #24 + #21] I#21 K#20
|
||||
G1 X[#14 + #24 + #21 - #3]
|
||||
O101 ELSE
|
||||
G1 X[#14 + #24 - [#3 * 1.5]]
|
||||
O101 ENDIF
|
||||
G0 Z[#13]
|
||||
O100 ENDWHILE
|
||||
|
||||
G0 x#1
|
||||
G1 Z #23 X[#1 + #24]
|
||||
O102 IF [#6 GT 0]
|
||||
G3 Z#5 X[#1 + #24 + #21] I#21 K#20
|
||||
G1 X[#1 + #24 + #21 - #3]
|
||||
O102 ELSE
|
||||
G1 X[#1 + #24 - #3]
|
||||
O102 ENDIF
|
||||
G0 Z #13
|
||||
G0 X #1 ; For touch-off
|
||||
M5 M9
|
||||
G7
|
||||
O<boring> endsub
|
||||
|
||||
M2
|
||||
77
my-emco-compact-5/macros/chamfer.ngc
Normal file
77
my-emco-compact-5/macros/chamfer.ngc
Normal file
@@ -0,0 +1,77 @@
|
||||
;chamfer
|
||||
|
||||
O<chamfer> sub
|
||||
|
||||
G8 ; Lathe radius Mode
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
|
||||
|
||||
M6 T#6 G43
|
||||
|
||||
#1 = [#1 / 2] ; because of radius mode
|
||||
|
||||
#14 = [#<_x>] (starting X)
|
||||
#13 = [#<_z>] (starting Z)
|
||||
|
||||
G96 D1500 S#2 ; Constant Surface Speed Mode
|
||||
M3
|
||||
g95 F0.1 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#12 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
#20 = 0
|
||||
O101 if [#9 GT 0.5] ; front outside
|
||||
o100 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 - #20] z#13
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 - #20]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o100 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 - #8]
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 - #8]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 elseif [#10 GT 0.5] ; front inside
|
||||
o102 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 + #20] z#13
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 - #20]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o102 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 + #8]
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 - #8]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 elseif [#11 GT 0.5] ; back outside
|
||||
o103 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 - #20] z#13
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 + #20]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o103 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 - #8]
|
||||
g1 z#5
|
||||
g1 x#1 z[#5 + #8]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 endif
|
||||
M5 M9
|
||||
G7
|
||||
O<chamfer> endsub
|
||||
m2
|
||||
%
|
||||
49
my-emco-compact-5/macros/drilling.ngc
Normal file
49
my-emco-compact-5/macros/drilling.ngc
Normal file
@@ -0,0 +1,49 @@
|
||||
;drilling
|
||||
|
||||
; Use T = 0 for tailstock drilling, then this just sets speed
|
||||
|
||||
O<drilling> SUB
|
||||
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
G91.1 ; but not for arcs
|
||||
|
||||
#10 = [#2 * 1000 / [ #1 * 3.141592]]
|
||||
(debug, #10)
|
||||
O90 IF [#7 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
O100 IF [#6 LT 0.5]
|
||||
G97 M3 S#10
|
||||
O<drilling> RETURN
|
||||
O100 ENDIF
|
||||
|
||||
M6 T#6 G43
|
||||
G0 X0
|
||||
|
||||
O83 IF [#5 GT 0] ; Pecking
|
||||
G17
|
||||
G95 F#3 ; Feed-Per-Rev Mode
|
||||
G97 M3 S#10
|
||||
G98
|
||||
G83 R#<_z> Q#5 Z#4
|
||||
M5 M9 G18
|
||||
O<drilling> RETURN
|
||||
O83 ENDIF
|
||||
|
||||
O82 IF [1]; not pecking
|
||||
G17
|
||||
G95 F#3 ; Feed-Per-Rev Mode
|
||||
G97 M3 S#10
|
||||
G98
|
||||
G82 R#<_z> P0.5 Z#4
|
||||
M5 M9 G18
|
||||
O82 ENDIF
|
||||
|
||||
O<drilling> ENDSUB
|
||||
|
||||
O<drilling> call [10] [100] [0.03] [0] [2] [0] [1]
|
||||
|
||||
M2
|
||||
45
my-emco-compact-5/macros/facing.ngc
Normal file
45
my-emco-compact-5/macros/facing.ngc
Normal file
@@ -0,0 +1,45 @@
|
||||
;Facing
|
||||
O<facing> sub
|
||||
|
||||
G7 ; Lathe Diameter Mode
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
|
||||
M6 T#7 G43
|
||||
|
||||
O90 IF [#8 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
O10 IF [#6 NE 0]
|
||||
(MSG, Angled facing isn't supported yet)
|
||||
O10 ENDIF
|
||||
|
||||
#14 = [#<_x> * 2] (starting X)
|
||||
#13 = #<_z> (starting Z)
|
||||
|
||||
G96 D2500 S#2 ; Constant Surface Speed Mode
|
||||
M3
|
||||
g95 F#4 ; Feed-Per-Rev Mode
|
||||
|
||||
g4p1 ; Wait to reach speed
|
||||
|
||||
O200 WHILE [#13 GT #5 + #3]
|
||||
|
||||
#13=[#13-#3]
|
||||
G1 Z#13
|
||||
G1 X#1
|
||||
G0 Z[#13+#3]
|
||||
G0 X#14
|
||||
G0 Z#13
|
||||
O200 ENDWHILE
|
||||
|
||||
G1 Z#5
|
||||
G1 X#1
|
||||
G0 Z[#13+#3]
|
||||
G0 X[#14+#3]
|
||||
G0 Z#5 ; For touch-off
|
||||
M5 M9
|
||||
O<facing> endsub
|
||||
M2
|
||||
32
my-emco-compact-5/macros/grooving.ngc
Normal file
32
my-emco-compact-5/macros/grooving.ngc
Normal file
@@ -0,0 +1,32 @@
|
||||
;grooving
|
||||
|
||||
O<grooving> sub
|
||||
|
||||
G8 ; Radius mode (easier maths)
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
G91.1 ; but not for arcs
|
||||
|
||||
M6 T#4 G43
|
||||
|
||||
#1 = [#1 / 2] ; because of radius mode
|
||||
|
||||
#14 = [#<_x>] (starting X)
|
||||
|
||||
G96 D1500 S#2 ; Constant Surface Speed Mode
|
||||
m3 ;Start Spindle
|
||||
g95 F#3 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#5 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
g4p1 ; Wait to reach speed
|
||||
G1 F#3 X#1
|
||||
G0 X#14
|
||||
M5 M9
|
||||
G7
|
||||
O<grooving> endsub
|
||||
|
||||
M2
|
||||
165
my-emco-compact-5/macros/lathe_macros.ini
Normal file
165
my-emco-compact-5/macros/lathe_macros.ini
Normal file
@@ -0,0 +1,165 @@
|
||||
# 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 = 1.1
|
||||
MACHINE = gmoccapy_lathe
|
||||
#DEBUG = 0x7FFFFFFF
|
||||
DEBUG = 0
|
||||
|
||||
# for details see nc_files/subroutines/maco_instructions.txt
|
||||
[DISPLAY]
|
||||
DISPLAY = gmoccapy
|
||||
LATHE = 1
|
||||
BACK_TOOL_LATHE = 0
|
||||
|
||||
# Cycle time, in milliseconds, that display will sleep between polls
|
||||
CYCLE_TIME = 100
|
||||
|
||||
# Highest value that will be allowed for feed override, 1.0 = 100%
|
||||
MAX_FEED_OVERRIDE = 1.5
|
||||
MAX_SPINDLE_OVERRIDE = 1.2
|
||||
MIN_SPINDLE_OVERRIDE = .5
|
||||
|
||||
|
||||
# Prefix to be used
|
||||
PROGRAM_PREFIX = ../../nc_files/:./
|
||||
|
||||
# Introductory graphic
|
||||
INTRO_GRAPHIC = linuxcnc.gif
|
||||
INTRO_TIME = 5
|
||||
|
||||
# list of selectable jog increments
|
||||
INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm
|
||||
|
||||
EMBED_TAB_NAME = Cycles
|
||||
EMBED_TAB_LOCATION = ntb_preview
|
||||
#EMBED_TAB_LOCATION = ntb_user_tabs
|
||||
EMBED_TAB_COMMAND = halcmd loadusr -Wn gladevcp gladevcp -c gladevcp -U notouch=1 -U norun=0 -u lathehandler.py -x {XID} lathemacro.ui
|
||||
|
||||
[FILTER]
|
||||
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
|
||||
PROGRAM_EXTENSION = .py Python Script
|
||||
png = image-to-gcode
|
||||
gif = image-to-gcode
|
||||
jpg = image-to-gcode
|
||||
py = python
|
||||
|
||||
# Task controller section -----------------------------------------------------
|
||||
[RS274NGC]
|
||||
RS274NGC_STARTUP_CODE = G18 G21 G40 G49 G54 G80 G90 G94 G8 M9 M5 G64 P0.005
|
||||
PARAMETER_FILE = sim.var
|
||||
SUBROUTINE_PATH = macros:./
|
||||
|
||||
# Motion control section ------------------------------------------------------
|
||||
[EMCMOT]
|
||||
EMCMOT = motmod
|
||||
COMM_TIMEOUT = 1.0
|
||||
BASE_PERIOD = 100000
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
# Hardware Abstraction Layer section --------------------------------------------------
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.001
|
||||
|
||||
# Part program interpreter section --------------------------------------------
|
||||
[HAL]
|
||||
HALFILE = core_sim_lathe.hal
|
||||
HALFILE = spindle_sim.hal
|
||||
HALFILE = simulated_home_lathe.hal
|
||||
|
||||
# Single file that is executed after the GUI has started.
|
||||
#POSTGUI_HALFILE = gmoccapy_postgui.hal
|
||||
|
||||
HALUI = halui
|
||||
|
||||
# Trajectory planner section --------------------------------------------------
|
||||
[HALUI]
|
||||
#No Content
|
||||
|
||||
[TRAJ]
|
||||
COORDINATES = X Z
|
||||
LINEAR_UNITS = mm
|
||||
ANGULAR_UNITS = degree
|
||||
DEFAULT_LINEAR_VELOCITY = 50
|
||||
MAX_LINEAR_VELOCITY = 234
|
||||
POSITION_FILE = position.txt
|
||||
#NO_FORCE_HOMING = 1
|
||||
|
||||
# First axis
|
||||
[EMCIO]
|
||||
EMCIO = io
|
||||
CYCLE_TIME = 0.100
|
||||
|
||||
# tool table file
|
||||
TOOL_TABLE = lathe.tbl
|
||||
|
||||
[KINS]
|
||||
KINEMATICS = trivkins coordinates=XZ
|
||||
JOINTS = 2
|
||||
|
||||
[AXIS_X]
|
||||
MIN_LIMIT = -50.0
|
||||
MAX_LIMIT = 200.0
|
||||
MAX_VELOCITY = 166
|
||||
MAX_ACCELERATION = 1500.0
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
MAX_VELOCITY = 166
|
||||
MAX_ACCELERATION = 1500.0
|
||||
BACKLASH = 0.000
|
||||
INPUT_SCALE = 4000
|
||||
OUTPUT_SCALE = 1.000
|
||||
MIN_LIMIT = -50.0
|
||||
MAX_LIMIT = 200.0
|
||||
FERROR = 0.050
|
||||
MIN_FERROR = 0.010
|
||||
HOME_OFFSET = 0.0
|
||||
HOME = 10
|
||||
HOME_SEARCH_VEL = 200.0
|
||||
HOME_LATCH_VEL = 20.0
|
||||
HOME_USE_INDEX = NO
|
||||
HOME_IGNORE_LIMITS = NO
|
||||
HOME_SEQUENCE = 1
|
||||
HOME_IS_SHARED = 1
|
||||
|
||||
# Third axis
|
||||
[AXIS_Z]
|
||||
MIN_LIMIT = -75.0
|
||||
MAX_LIMIT = 1000.0
|
||||
MAX_VELOCITY = 166
|
||||
MAX_ACCELERATION = 1500.0
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
MAX_VELOCITY = 166
|
||||
MAX_ACCELERATION = 1500.0
|
||||
BACKLASH = 0.000
|
||||
INPUT_SCALE = 4000
|
||||
OUTPUT_SCALE = 1.000
|
||||
MIN_LIMIT = -75.0
|
||||
MAX_LIMIT = 1000.0
|
||||
FERROR = 0.050
|
||||
MIN_FERROR = 0.010
|
||||
HOME_OFFSET = 1.0
|
||||
HOME = -10
|
||||
HOME_SEARCH_VEL = 200.0
|
||||
HOME_LATCH_VEL = 20.0
|
||||
HOME_USE_INDEX = NO
|
||||
HOME_IGNORE_LIMITS = NO
|
||||
HOME_SEQUENCE = 0
|
||||
HOME_IS_SHARED = 1
|
||||
|
||||
# section for main IO controller parameters -----------------------------------
|
||||
[MACROS]
|
||||
MACRO = i_am_lost
|
||||
MACRO = halo_world
|
||||
MACRO = jog_around
|
||||
MACRO = increment xinc yinc
|
||||
MACRO = go_to_position X-pos Y-pos Z-pos
|
||||
|
||||
|
||||
219
my-emco-compact-5/macros/lathehandler.py
Normal file
219
my-emco-compact-5/macros/lathehandler.py
Normal file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python3
|
||||
# vim: sts=4 sw=4 et
|
||||
# This is a component of EMC
|
||||
# savestate.py copyright 2013 Andy Pugh
|
||||
# based on code from
|
||||
# probe.py Copyright 2010 Michael Haberler
|
||||
#
|
||||
#
|
||||
# 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''''''
|
||||
|
||||
import os,sys
|
||||
from gladevcp.persistence import IniFile,widget_defaults,set_debug,select_widgets
|
||||
import hal
|
||||
import hal_glib
|
||||
import glib
|
||||
import linuxcnc
|
||||
import cairo
|
||||
import signal
|
||||
import re
|
||||
import gi
|
||||
gi.require_version('Rsvg', '2.0')
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Pango
|
||||
from gi.repository import Rsvg
|
||||
from gi.repository import GdkPixbuf
|
||||
debug = 0
|
||||
notouch = 0
|
||||
norun = 0
|
||||
svgfile = os.path.join(os.path.dirname(__file__), "LatheMacro.svg")
|
||||
|
||||
class HandlerClass:
|
||||
active = False
|
||||
tab_num = 0
|
||||
|
||||
def on_expose(self,nb,data=None):
|
||||
tab_num = nb.get_current_page()
|
||||
tab = nb.get_nth_page(tab_num)
|
||||
alloc = tab.get_allocation()
|
||||
x, y, w, h = (alloc.x, alloc.y, alloc.width, alloc.height)
|
||||
pixbuf = self.svg.get_pixbuf_sub(f'#layer{tab_num}').scale_simple(w-10, h-10, GdkPixbuf.InterpType.BILINEAR)
|
||||
im = self.builder.get_object(f'Image{tab_num}')
|
||||
im.set_from_pixbuf(pixbuf)
|
||||
for c in im.get_parent().get_children():
|
||||
if c.get_has_tooltip():
|
||||
m = re.findall(r'<!--(\d+),(\d+)-->', c.get_tooltip_markup())
|
||||
if len(m) > 0:
|
||||
x1 = int(m[0][0]); y1 = int(m[0][1])
|
||||
c.set_margin_left(max(0, w * x1/1500))
|
||||
c.set_margin_top(max(0, h * y1/1000))
|
||||
|
||||
|
||||
# decide if our window is active to mask the cycle-start hardware button
|
||||
# FIXME: This is probably not as reliable as one might wish.
|
||||
def event(self,w,event):
|
||||
if w.is_active():
|
||||
if w.has_toplevel_focus() :
|
||||
self.active = True
|
||||
else:
|
||||
self.active = False
|
||||
|
||||
# Capture notify events
|
||||
def on_map_event(self, widget, data=None):
|
||||
top = widget.get_toplevel()
|
||||
top.connect('notify', self.event)
|
||||
|
||||
def on_destroy(self,obj,data=None):
|
||||
self.ini.save_state(self)
|
||||
|
||||
def on_restore_defaults(self,button,data=None):
|
||||
'''
|
||||
example callback for 'Reset to defaults' button
|
||||
currently unused
|
||||
'''
|
||||
self.ini.create_default_ini()
|
||||
self.ini.restore_state(self)
|
||||
|
||||
def __init__(self, halcomp,builder,useropts):
|
||||
self.halcomp = halcomp
|
||||
self.builder = builder
|
||||
self.ini_filename = 'savestate.sav'
|
||||
self.defaults = { IniFile.vars: dict(),
|
||||
IniFile.widgets : widget_defaults(select_widgets(self.builder.get_objects(),
|
||||
hal_only=False,output_only = True))
|
||||
}
|
||||
self.ini = IniFile(self.ini_filename,self.defaults,self.builder)
|
||||
self.ini.restore_state(self)
|
||||
|
||||
# A pin to use a physical switch to start the cycle
|
||||
self.cycle_start = hal_glib.GPin(halcomp.newpin('cycle-start', hal.HAL_BIT, hal.HAL_IN))
|
||||
self.cycle_start.connect('value-changed', self.cycle_pin)
|
||||
|
||||
# This catches the signal from Touchy to say that the tab is exposed
|
||||
t = self.builder.get_object('macrobox')
|
||||
t.connect('map-event',self.on_map_event)
|
||||
t.add_events(Gdk.EventMask.STRUCTURE_MASK)
|
||||
|
||||
self.cmd = linuxcnc.command()
|
||||
|
||||
# This connects the expose event to re-draw and scale the SVG frames
|
||||
t = self.builder.get_object('tabs1')
|
||||
t.connect_after("draw", self.on_expose)
|
||||
t.connect("destroy", Gtk.main_quit)
|
||||
t.add_events(Gdk.EventMask.STRUCTURE_MASK)
|
||||
print(svgfile)
|
||||
self.svg = Rsvg.Handle().new_from_file(svgfile)
|
||||
self.active = True
|
||||
|
||||
# handle Useropts
|
||||
if norun:
|
||||
for c in range(0,6):
|
||||
print(c)
|
||||
print( f'tab{c}.action')
|
||||
self.builder.get_object(f'tab{c}.action').set_visible(False)
|
||||
|
||||
def show_keyb(self, obj, data=None):
|
||||
if notouch: return False
|
||||
self.active_ctrl = obj
|
||||
self.keyb = self.builder.get_object('keyboard')
|
||||
self.entry = self.builder.get_object('entry1')
|
||||
self.entry.modify_font(Pango.FontDescription("courier 42"))
|
||||
self.entry.set_text("")
|
||||
resp = self.keyb.run()
|
||||
return True
|
||||
|
||||
def keyb_prev_click(self, obj, data=None):
|
||||
self.entry.set_text(self.active_ctrl.get_text())
|
||||
|
||||
def keyb_number_click(self, obj, data=None):
|
||||
data = self.entry.get_text()
|
||||
data = data + obj.get_label()
|
||||
if any( x in data for x in [ '/2', '/4', '/8', '/16', '/32', '/64', '/128']):
|
||||
v = [0] + [float(x) for x in data.replace('/','.').split('.')]
|
||||
data = f'{v[-3] + v[-2]/v[-1]:6.7}'
|
||||
self.entry.set_text(data)
|
||||
|
||||
def keyb_pm_click(self, obj, data=None):
|
||||
data = self.entry.get_text()
|
||||
if data[0] == '-':
|
||||
data = data[1:]
|
||||
else:
|
||||
data = '-' + data
|
||||
self.entry.set_text(data)
|
||||
|
||||
def keyb_convert_click(self, obj, data=None):
|
||||
v = float(self.entry.get_text())
|
||||
op = obj.get_label()
|
||||
if op == 'in->mm':
|
||||
self.entry.set_text(f'{v * 25.4:6.4}')
|
||||
elif op == 'mm->in':
|
||||
self.entry.set_text(f'{v / 25.4:6.4}')
|
||||
elif op == 'tpi->pitch':
|
||||
self.entry.set_text(f'{25.4 / v:6.4}')
|
||||
elif op == 'pitch->tpi':
|
||||
self.entry.set_text(f'{25.4 / v:6.4}')
|
||||
|
||||
def keyb_del_click(self, obj, data=None):
|
||||
data = self.entry.get_text()
|
||||
data = data[:-1]
|
||||
self.entry.set_text(data)
|
||||
|
||||
def keyb_clear_click(self, obj, data=None):
|
||||
self.entry.set_text('')
|
||||
|
||||
def keyb_cancel_click(self, obj, data=None):
|
||||
self.keyb.hide()
|
||||
|
||||
def keyb_ok_click(self, obj, data=None):
|
||||
if self.entry.get_text() != '':
|
||||
self.active_ctrl.set_value(float(self.entry.get_text()))
|
||||
self.keyb.hide()
|
||||
|
||||
def set_alpha(self, obj, data = None):
|
||||
cr = obj.get_property('window').cairo_create()
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
|
||||
|
||||
def cycle_pin(self, pin, data = None):
|
||||
if pin.get() == 0:
|
||||
return
|
||||
if self.active:
|
||||
nb = self.builder.get_object('tabs1')
|
||||
print('current tab', nb.get_current_page())
|
||||
c = self.builder.get_object(f"tab{nb.get_current_page()}.action")
|
||||
if c is not None:
|
||||
self.cmd.abort()
|
||||
self.cmd.mode(linuxcnc.MODE_MDI)
|
||||
self.cmd.wait_complete()
|
||||
c.emit('clicked')
|
||||
print(c.get_name(), "clicked")
|
||||
|
||||
def testing(self, obj, data = None):
|
||||
print('event', data)
|
||||
|
||||
def get_handlers(halcomp,builder,useropts):
|
||||
|
||||
global debug
|
||||
for cmd in useropts:
|
||||
print(cmd)
|
||||
exec(cmd, globals())
|
||||
|
||||
set_debug(debug)
|
||||
return [HandlerClass(halcomp,builder,useropts)]
|
||||
|
||||
|
||||
|
||||
2937
my-emco-compact-5/macros/lathemacro.ui
Normal file
2937
my-emco-compact-5/macros/lathemacro.ui
Normal file
File diff suppressed because it is too large
Load Diff
76
my-emco-compact-5/macros/radius.ngc
Normal file
76
my-emco-compact-5/macros/radius.ngc
Normal file
@@ -0,0 +1,76 @@
|
||||
;radius
|
||||
|
||||
O<radius> sub
|
||||
|
||||
G8 ; Lathe radius Mode
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
|
||||
|
||||
M6 T#6 G43
|
||||
|
||||
#1 = [#1 / 2] ; because of radius mode
|
||||
#14 = [#<_x>] (starting X)
|
||||
#13 = [#<_z>] (starting Z)
|
||||
|
||||
G96 D2400 S#2 ; Constant Surface Speed Mode
|
||||
M3
|
||||
g95 F0.1 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#12 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
#20 = 0
|
||||
O101 if [#9 GT 0.5] ; Front outside
|
||||
o100 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 - #20] z#13
|
||||
g1 z#5
|
||||
g3 x#1 z[#5 - #20] K[-#20]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o100 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 - #8]
|
||||
g1 z#5
|
||||
g3 x#1 z[#5 - #8] K[-#8]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 elseif [#10 GT 0.5] ; front inside
|
||||
o102 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 + #20] z#13
|
||||
g1 z#5
|
||||
g2 x#1 z[#5 - #20] K[-#20]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o102 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 + #8]
|
||||
g1 z#5
|
||||
g2 x#1 z[#5 - #8] K[-#8]
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 elseif [#11 GT 0.5] ; back outside
|
||||
o103 while [[#20 + #3] lt #8]
|
||||
#20 = [#20 + #3]
|
||||
g0 x[#1 - #20] z#13
|
||||
g1 z#5
|
||||
g2 x#1 z[#5 + #20] K#20
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
o103 endwhile
|
||||
g0 x#14 z#13
|
||||
g0 x[#1 - #8]
|
||||
g1 z#5
|
||||
g2 x#1 z[#5 + #8] K#8
|
||||
g1 x #14
|
||||
g0 z#13
|
||||
O101 endif
|
||||
M5 M9
|
||||
G7
|
||||
O<radius> endsub
|
||||
m2
|
||||
%
|
||||
59
my-emco-compact-5/macros/threading.ngc
Normal file
59
my-emco-compact-5/macros/threading.ngc
Normal file
@@ -0,0 +1,59 @@
|
||||
;threading
|
||||
|
||||
O<threading> sub
|
||||
|
||||
G7 ; Lathe Diameter Mode
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
|
||||
|
||||
M6 T#3 G43
|
||||
|
||||
#14 = [#<_x> * 2] (starting X)
|
||||
#13 = #<_z> (starting Z)
|
||||
|
||||
G96 D200 S#2 ; Constant Surface Speed Mode
|
||||
M3
|
||||
g95 F0.25 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#8 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
|
||||
g4p1 ; Wait to reach speed
|
||||
|
||||
;Threading
|
||||
O51 IF [#6 GT 0.5]
|
||||
#<OD> = [#1]
|
||||
#<ID> = [#1 - 1.3 * #4]
|
||||
;g1X [#<ID> - 1] ;thread truncation
|
||||
;g0 Z #13
|
||||
;g1 X #<ID>
|
||||
;g1 Z #5
|
||||
G0 X[#<ID> - 1]
|
||||
g0 Z #13
|
||||
#3 = [#4 * 1.3]
|
||||
(debug, INTERNAL Threading thread dia-#1 start-#13 finish-#5 Pitch-#4 Depth-#3)
|
||||
g1X [#<ID> - 1]
|
||||
g76 p#4 z#5 i1 j1 k#3 h3 r1.5 q29.5 e0 l0
|
||||
|
||||
O51 ELSE
|
||||
#<OD> = [#1 - 0.108 * #4]
|
||||
#<ID> = [#1 - 1.0825 * #4]
|
||||
(debug, EXTERNAL Threading OD = #<OD> ID = #<ID>)
|
||||
#3 = [#4 * 1.0825]
|
||||
g1X [#<OD> + 1] ;final thread truncation
|
||||
g0 z#13
|
||||
g1 X #<OD>
|
||||
g1 Z #5
|
||||
G0 X[#<OD> +1]
|
||||
G0 Z #13
|
||||
g76 p#4 z#5 i-1 j1 k#3 h3 r1.5 q29.5 e0 l0
|
||||
|
||||
O51 ENDIF
|
||||
G0 Z #13
|
||||
m5 M9
|
||||
O<threading> endsub
|
||||
|
||||
M2
|
||||
66
my-emco-compact-5/macros/turning.ngc
Normal file
66
my-emco-compact-5/macros/turning.ngc
Normal file
@@ -0,0 +1,66 @@
|
||||
;Turning
|
||||
|
||||
O<turning> sub
|
||||
|
||||
G8 ; Radius mode (easier maths)
|
||||
G18 ; XZ Plane
|
||||
G21 ; Metric Units
|
||||
G90 ; Absolute Distance
|
||||
G91.1 ; but not for arcs
|
||||
|
||||
M6 T#8 G43
|
||||
|
||||
#1 = [#1 / 2] ; because of radius mode
|
||||
#14 = [#<_x>] (starting X)
|
||||
#13 = #<_z> (starting Z)
|
||||
|
||||
#20 = [#6 * SIN[#7]]
|
||||
#21 = [#6 * COS[#7]]
|
||||
#22 = [#6 / COS[#7]]
|
||||
#23 = [#5 + #6 - #20]
|
||||
#24 = [[#13 - #23] * TAN[#7]]
|
||||
|
||||
G96 D2500 S#2 ; Constant Surface Speed Mode
|
||||
m3 ;Start Spindle
|
||||
g95 F#4 ; Feed-Per-Rev Mode
|
||||
|
||||
O90 IF [#9 GT 0.5]
|
||||
M8
|
||||
O90 ENDIF
|
||||
g4p1 ; Wait to reach speed
|
||||
|
||||
O100 WHILE [#14 GT [#1 + #3 / 2]]
|
||||
g0 X #14
|
||||
#14=[#14-#3 / 2]
|
||||
G1 X #14
|
||||
G1 Z #23 X[#14 + #24]
|
||||
O101 IF [#6 GT 0]
|
||||
G2 Z#5 X[#14 + #24 + #21] I#21 K#20
|
||||
G1 X[#14 + #24 + #21 + #3/2]
|
||||
O101 ELSE
|
||||
G1 X[#14 + #24 + [#3 * .6]]
|
||||
O101 ENDIF
|
||||
O104 IF [#7 LT 0]
|
||||
G0 X#14
|
||||
O104 ENDIF
|
||||
G0 Z[#13]
|
||||
O100 ENDWHILE
|
||||
|
||||
G0 x#1
|
||||
G1 Z #23 X[#1 + #24]
|
||||
O102 IF [#6 GT 0]
|
||||
G2 Z#5 X[#1 + #24 + #21] I#21 K#20
|
||||
G1 X[#1 + #24 + #21 + #3]
|
||||
O102 ELSE
|
||||
G1 X[#1 + #24 + #3]
|
||||
O102 ENDIF
|
||||
O106 IF [#7 LT 0]
|
||||
G0 X#14
|
||||
O106 ENDIF
|
||||
M9
|
||||
G0 Z #13
|
||||
G0 X #1 ; For touch-off
|
||||
M5
|
||||
G7
|
||||
O<turning> endsub
|
||||
M2
|
||||
82
my-emco-compact-5/mpg.glade
Normal file
82
my-emco-compact-5/mpg.glade
Normal file
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.0"/>
|
||||
<requires lib="gladevcp" version="0.0"/>
|
||||
<object class="EMC_Action_MDI" id="hal_action_mdi1">
|
||||
<property name="label" translatable="yes">Goto Machine Zero</property>
|
||||
<property name="command">G53 G0 X0 Y0 Z0</property>
|
||||
</object>
|
||||
<object class="EMC_Action_MDI" id="hal_action_mdi2">
|
||||
<property name="command">G53 G0 Z88</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<child>
|
||||
<object class="HAL_Table" id="mpg">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="column_spacing">35</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="mpg-func-btn">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Func Button:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HAL_ComboBox" id="func-btn-combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="column">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderertext1"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>MPG</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
1
my-emco-compact-5/mpg.hal
Normal file
1
my-emco-compact-5/mpg.hal
Normal file
@@ -0,0 +1 @@
|
||||
net all-homed mpg.mpg
|
||||
10
my-emco-compact-5/mpg.xml
Normal file
10
my-emco-compact-5/mpg.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<mpg>
|
||||
<halpin>"axis-selector"<event>sela</event><type>s32</type></halpin>
|
||||
<halpin>"scale-selector"<event>sels</event><type>s32</type></halpin>
|
||||
<halpin>"jog-pos-btn"<event>jpos</event><type>bit</type></halpin>
|
||||
<halpin>"jog-neg-btn"<event>jneg</event><type>bit</type></halpin>
|
||||
<halpin>"estop-btn"<event>est</event><type>bit</type></halpin>
|
||||
<halpin>"func-btn"<event>func</event><type>bit</type></halpin>
|
||||
<halpin>"joystick-x"<event>x</event><type>float</type></halpin>
|
||||
<halpin>"joystick-z"<event>z</event><type>float</type></halpin>
|
||||
</mpg>
|
||||
101
my-emco-compact-5/my-emco-compact-5.hal
Normal file
101
my-emco-compact-5/my-emco-compact-5.hal
Normal file
@@ -0,0 +1,101 @@
|
||||
# Generated by stepconf 1.1 at Mon Mar 14 20:22:34 2022
|
||||
# If you make changes to this file, they will be
|
||||
# overwritten when you run stepconf again
|
||||
loadrt [KINS]KINEMATICS
|
||||
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
|
||||
loadrt encoder num_chan=2 # 0 used for native speed sense, 1 used for testing new encoder
|
||||
loadrt hal_parport cfg="0 out"
|
||||
setp parport.0.reset-time 5000
|
||||
loadrt stepgen step_type=6,6
|
||||
loadrt lowpass
|
||||
loadrt scale count=5 # 0 used to convert spindle speed from rps to rpm,
|
||||
# 1 used in cusom.hal to adjust spindle set-speed fequency
|
||||
# 2 used in cusom.hal for mpg scale/increment selection
|
||||
# 3 & 4 used in custom.hal for mgp joystic
|
||||
|
||||
addf parport.0.read base-thread
|
||||
addf encoder.update-counters base-thread
|
||||
addf stepgen.make-pulses base-thread
|
||||
addf parport.0.write base-thread
|
||||
addf parport.0.reset base-thread
|
||||
|
||||
addf stepgen.capture-position servo-thread
|
||||
addf encoder.capture-position servo-thread
|
||||
addf motion-command-handler servo-thread
|
||||
addf motion-controller servo-thread
|
||||
addf lowpass.0 servo-thread
|
||||
addf scale.0 servo-thread
|
||||
addf stepgen.update-freq servo-thread
|
||||
|
||||
net spindle-cmd-rpm <= spindle.0.speed-out
|
||||
net spindle-cmd-rpm-abs <= spindle.0.speed-out-abs
|
||||
net spindle-cmd-rps <= spindle.0.speed-out-rps
|
||||
net spindle-cmd-rps-abs <= spindle.0.speed-out-rps-abs
|
||||
|
||||
net xphasea => parport.0.pin-02-out
|
||||
net xphaseb => parport.0.pin-03-out
|
||||
net xphasec => parport.0.pin-04-out
|
||||
net xphased => parport.0.pin-05-out
|
||||
|
||||
net zphasea => parport.0.pin-06-out
|
||||
net zphaseb => parport.0.pin-07-out
|
||||
net zphasec => parport.0.pin-08-out
|
||||
net zphased => parport.0.pin-09-out
|
||||
|
||||
setp parport.0.pin-01-out-invert 1
|
||||
setp parport.0.pin-01-out-reset true
|
||||
setp parport.0.pin-01-out true # 74ls374 clock pin
|
||||
|
||||
# spindle encoder stuff
|
||||
setp encoder.0.counter-mode true
|
||||
setp encoder.0.position-scale 100
|
||||
net spindle-index parport.0.pin-12-in-not
|
||||
net spindle-ppr parport.0.pin-10-in-not
|
||||
net spindle-ppr encoder.0.phase-A
|
||||
net spindle-index encoder.0.phase-Z
|
||||
net spindle-pos spindle.0.revs encoder.0.position-interpolated
|
||||
net spindle-index-enable spindle.0.index-enable encoder.0.index-enable
|
||||
net spindle-vel encoder.0.velocity spindle.0.speed-in
|
||||
|
||||
# Filtering and scaling... moved to custom_postgui
|
||||
#setp scale.0.gain 60
|
||||
#setp lowpass.0.gain .07
|
||||
#net spindle-vel lowpass.0.in
|
||||
#net spindle-rps-filtered lowpass.0.out scale.0.in
|
||||
#net spindle-rpm-filtered scale.0.out
|
||||
|
||||
net estop-external <= parport.0.pin-11-in-not
|
||||
|
||||
setp stepgen.0.position-scale [JOINT_0]SCALE
|
||||
setp stepgen.0.steplen 20000
|
||||
setp stepgen.0.dirdelay 20000
|
||||
setp stepgen.0.maxaccel [JOINT_0]STEPGEN_MAXACCEL
|
||||
net xpos-cmd joint.0.motor-pos-cmd => stepgen.0.position-cmd
|
||||
net xpos-fb stepgen.0.position-fb => joint.0.motor-pos-fb
|
||||
net xphasea <= stepgen.0.phase-A
|
||||
net xphaseb <= stepgen.0.phase-B
|
||||
net xphasec <= stepgen.0.phase-C
|
||||
net xphased <= stepgen.0.phase-D
|
||||
net xenable joint.0.amp-enable-out => stepgen.0.enable
|
||||
|
||||
setp stepgen.1.position-scale [JOINT_1]SCALE
|
||||
setp stepgen.1.steplen 20000
|
||||
setp stepgen.1.dirdelay 20000
|
||||
setp stepgen.1.maxaccel [JOINT_1]STEPGEN_MAXACCEL
|
||||
net zpos-cmd joint.1.motor-pos-cmd => stepgen.1.position-cmd
|
||||
net zpos-fb stepgen.1.position-fb => joint.1.motor-pos-fb
|
||||
net zphasea <= stepgen.1.phase-A
|
||||
net zphaseb <= stepgen.1.phase-B
|
||||
net zphasec <= stepgen.1.phase-C
|
||||
net zphased <= stepgen.1.phase-D
|
||||
net zenable joint.1.amp-enable-out => stepgen.1.enable
|
||||
|
||||
# moved to custom.hal
|
||||
#net estop-out <= iocontrol.0.user-enable-out
|
||||
#net estop-ext => iocontrol.0.emc-enable-in
|
||||
|
||||
loadusr -W hal_manualtoolchange
|
||||
net tool-change iocontrol.0.tool-change => hal_manualtoolchange.change
|
||||
net tool-changed iocontrol.0.tool-changed <= hal_manualtoolchange.changed
|
||||
net tool-number iocontrol.0.tool-prep-number => hal_manualtoolchange.number
|
||||
net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared
|
||||
169
my-emco-compact-5/my-emco-compact-5.ini
Normal file
169
my-emco-compact-5/my-emco-compact-5.ini
Normal file
@@ -0,0 +1,169 @@
|
||||
# Generated by stepconf 1.1 at Mon Mar 14 20:22:34 2022
|
||||
# If you make changes to this file, they will be
|
||||
# overwritten when you run stepconf again
|
||||
|
||||
[EMC]
|
||||
MACHINE = my-emco-compact-5
|
||||
DEBUG = 0
|
||||
VERSION = 1.1
|
||||
|
||||
[DISPLAY]
|
||||
DISPLAY = gmoccapy
|
||||
EDITOR = gedit
|
||||
POSITION_OFFSET = RELATIVE
|
||||
POSITION_FEEDBACK = ACTUAL
|
||||
ARCDIVISION = 64
|
||||
GRIDS = 10mm 20mm 50mm 100mm 1in 2in 5in 10in
|
||||
MAX_FEED_OVERRIDE = 1.2
|
||||
MIN_SPINDLE_OVERRIDE = 0.5
|
||||
MAX_SPINDLE_OVERRIDE = 1.2
|
||||
DEFAULT_LINEAR_VELOCITY = 1.25
|
||||
MIN_LINEAR_VELOCITY = 0
|
||||
MAX_LINEAR_VELOCITY = 12.50
|
||||
INTRO_GRAPHIC = linuxcnc.gif
|
||||
INTRO_TIME = 5
|
||||
PROGRAM_PREFIX = /home/johan/linuxcnc/nc_files
|
||||
INCREMENTS = 1mm .1mm .01mm
|
||||
#INCREMENTS = 5mm 1mm .5mm .1mm .05mm .01mm
|
||||
LATHE = 1
|
||||
MIN_ANGULAR_VELOCITY = 0.1
|
||||
MAX_ANGULAR_VELOCITY = 3600
|
||||
DEFAULT_ANGULAR_VELOCITY = 360
|
||||
DEFAULT_SPINDLE_SPEED = 200
|
||||
CYCLE_TIME = 150
|
||||
DEFAULT_SPINDLE_0_SPEED = 200
|
||||
MIN_SPINDLE_0_SPEED = 100
|
||||
MAX_SPINDLE_0_SPEED = 2500
|
||||
MAX_SPINDLE_0_OVERRIDE = 1
|
||||
MIN_SPINDLE_0_OVERRIDE = 0.5
|
||||
|
||||
EMBED_TAB_NAME = Spindle Speed Selection
|
||||
EMBED_TAB_LOCATION = ntb_preview
|
||||
EMBED_TAB_COMMAND = gladevcp -H spindle_speed_selector.hal -x {XID} spindle_speed_selector.glade
|
||||
|
||||
EMBED_TAB_NAME = Macro
|
||||
EMBED_TAB_LOCATION = ntb_preview
|
||||
EMBED_TAB_COMMAND = halcmd loadusr -Wn gladevcp gladevcp -c gladevcp -U notouch=1 -U norun=0 -u macros/lathehandler.py -x {XID} macros/lathemacro.ui
|
||||
|
||||
EMBED_TAB_NAME = MPG
|
||||
EMBED_TAB_LOCATION = ntb_preview
|
||||
EMBED_TAB_COMMAND = gladevcp -u gladevcp-handler.py -H mpg.hal -x {XID} mpg.glade
|
||||
|
||||
[PYTHON]
|
||||
TOPLEVEL=python/toplevel.py
|
||||
PATH_APPEND=python
|
||||
#TOPLEVEL=/home/johan/linuxcnc/configs/sim.gmoccapy.lathe_configs/python/toplevel.py
|
||||
#PATH_APPEND=/home/johan/linuxcnc/configs/sim.gmoccapy.lathe_configs/python
|
||||
|
||||
[FILTER]
|
||||
PROGRAM_EXTENSION = .png,.gif,.jpg Greyscale Depth Image
|
||||
PROGRAM_EXTENSION = .py Python Script
|
||||
PROGRAM_EXTENSION = .nc,.tap G-Code File
|
||||
png = image-to-gcode
|
||||
gif = image-to-gcode
|
||||
jpg = image-to-gcode
|
||||
py = python
|
||||
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.010
|
||||
|
||||
[RS274NGC]
|
||||
PARAMETER_FILE = linuxcnc.var
|
||||
RS274NGC_STARTUP_CODE = G7 G18
|
||||
SUBROUTINE_PATH=custom-m-codes
|
||||
USER_M_PATH=custom-m-codes
|
||||
REMAP=S prolog=setspeed_prolog ngc=mysetspeed epilog=setspeed_epilog
|
||||
REMAP=M0 modalgroup=4 ngc=extend_m0
|
||||
REMAP=M1 modalgroup=4 ngc=extend_m1
|
||||
|
||||
[EMCMOT]
|
||||
# base freq = 20kHz
|
||||
# servo freq = 1kHz
|
||||
EMCMOT = motmod
|
||||
COMM_TIMEOUT = 1.0
|
||||
#BASE_PERIOD = 35000
|
||||
BASE_PERIOD = 50000
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
[HAL]
|
||||
HALUI = halui
|
||||
HALFILE = my-emco-compact-5.hal
|
||||
HALFILE = custom.hal
|
||||
POSTGUI_HALFILE = custom_postgui.hal
|
||||
|
||||
[HALUI]
|
||||
# add halui MDI commands here (max 64)
|
||||
MDI_COMMAND = O<myspindlespeedup> call [100] ;0, connected to mpg button
|
||||
MDI_COMMAND = O<myspindlespeeddown> call [100] ;1, connected to mpg button
|
||||
MDI_COMMAND = O<mytouch> call ;2, connected to mpg button
|
||||
MDI_COMMAND = O<myspindlegain> call [0.48483] [20.16466] ;3, spindle speed selection AC1
|
||||
MDI_COMMAND = O<myspindlegain> call [0.32571] [-8.05714] ;4, spindle speed selection AC2
|
||||
MDI_COMMAND = O<myspindlegain> call [0.20098] [22.64117] ;5, spindle speed selection AC3
|
||||
MDI_COMMAND = O<myspindlegain> call [#4998] [#4999] ;6, called to set saved spindle
|
||||
; speed selection after homing
|
||||
|
||||
[KINS]
|
||||
KINEMATICS = trivkins coordinates=XZ
|
||||
JOINTS = 2
|
||||
|
||||
[TRAJ]
|
||||
COORDINATES = X Z
|
||||
LINEAR_UNITS = mm
|
||||
ANGULAR_UNITS = degree
|
||||
DEFAULT_LINEAR_VELOCITY = 2.5
|
||||
MAX_LINEAR_VELOCITY = 18
|
||||
NO_FORCE_HOMING = 1
|
||||
DEFAULT_LINEAR_ACCELERATION = 50.0
|
||||
POSITION_FILE = emcopos.txt
|
||||
|
||||
[EMCIO]
|
||||
EMCIO = io
|
||||
CYCLE_TIME = 0.100
|
||||
TOOL_TABLE = tool.tbl
|
||||
|
||||
[AXIS_X]
|
||||
MIN_LIMIT = -2500.0
|
||||
MAX_LIMIT = 2500.0
|
||||
MAX_VELOCITY = 12.5
|
||||
MAX_ACCELERATION = 500
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 12.5
|
||||
MAX_ACCELERATION = 500
|
||||
STEPGEN_MAXACCEL = 625
|
||||
|
||||
#steps/rev = 72, 0.125 mm/9 steps => 72*(0.125/9) mm/rev
|
||||
#scale = 72/[72*0.125/9] = 72/(72/72) = 72 steps/mm
|
||||
SCALE = 72
|
||||
|
||||
FERROR = 1.0
|
||||
MIN_FERROR = 0.25
|
||||
MIN_LIMIT = -2500.0
|
||||
MAX_LIMIT = 2500.0
|
||||
HOME_OFFSET = 0.0
|
||||
|
||||
[AXIS_Z]
|
||||
MIN_LIMIT = -2500.0
|
||||
MAX_LIMIT = 2500.0
|
||||
MAX_VELOCITY = 12.5
|
||||
MAX_ACCELERATION = 500
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 12.5
|
||||
MAX_ACCELERATION = 500
|
||||
STEPGEN_MAXACCEL = 625
|
||||
|
||||
#steps/rev = 72, 0.125 mm/9 steps => 72*(0.125/9) mm/rev
|
||||
#scale = 72/[72*0.125/9] = 72 steps/mm
|
||||
SCALE = 72
|
||||
|
||||
FERROR = 1.0
|
||||
MIN_FERROR = 0.25
|
||||
MIN_LIMIT = -2500.0
|
||||
MAX_LIMIT = 2500.0
|
||||
HOME_OFFSET = 0.0
|
||||
85
my-emco-compact-5/my-emco-compact-5.pref
Normal file
85
my-emco-compact-5/my-emco-compact-5.pref
Normal file
@@ -0,0 +1,85 @@
|
||||
[DEFAULT]
|
||||
dro_digits = 3
|
||||
dro_size = 28
|
||||
abs_color = #0000FF
|
||||
rel_color = #000000
|
||||
dtg_color = #FFFF00
|
||||
homed_color = #00FF00
|
||||
unhomed_color = #FF0000
|
||||
enable_dro = False
|
||||
scale_jog_vel = 7.5
|
||||
scale_spindle_override = 1
|
||||
scale_feed_override = 1
|
||||
scale_rapid_override = 1
|
||||
spindle_bar_min = 0.0
|
||||
spindle_bar_max = 6000.0
|
||||
turtle_jog_factor = 20
|
||||
hide_turtle_jog_button = False
|
||||
unlock_code = 123
|
||||
toggle_readout = True
|
||||
spindle_start_rpm = 300.0
|
||||
view = y
|
||||
blockheight = 0.0
|
||||
open_file =
|
||||
screen1 = window
|
||||
x_pos = 40
|
||||
y_pos = 30
|
||||
width = 979
|
||||
height = 750
|
||||
use_toolmeasurement = False
|
||||
gtk_theme = Follow System Theme
|
||||
grid_size = 1.0
|
||||
mouse_btn_mode = 4
|
||||
hide_cursor = False
|
||||
system_name_tool = Tool
|
||||
system_name_g5x = G5x
|
||||
system_name_rot = Rot
|
||||
system_name_g92 = G92
|
||||
system_name_g54 = G54
|
||||
system_name_g55 = G55
|
||||
system_name_g56 = G56
|
||||
system_name_g57 = G57
|
||||
system_name_g58 = G58
|
||||
system_name_g59 = G59
|
||||
system_name_g59.1 = G59.1
|
||||
system_name_g59.2 = G59.2
|
||||
system_name_g59.3 = G59.3
|
||||
jump_to_dir = /home/johan
|
||||
show_keyboard_on_offset = False
|
||||
show_keyboard_on_tooledit = False
|
||||
show_keyboard_on_edit = False
|
||||
show_keyboard_on_mdi = False
|
||||
x_pos_popup = 45.0
|
||||
y_pos_popup = 55
|
||||
width_popup = 250.0
|
||||
max_messages = 10
|
||||
message_font = sans 10
|
||||
use_frames = True
|
||||
reload_tool = False
|
||||
blockdel = False
|
||||
show_offsets = False
|
||||
show_dtg = False
|
||||
view_tool_path = True
|
||||
view_dimension = True
|
||||
run_from_line = no_run
|
||||
unlock_way = use
|
||||
show_preview_on_offset = False
|
||||
use_keyboard_shortcuts = False
|
||||
tool_in_spindle = 3
|
||||
radius offset_axis_x = 0
|
||||
offset_axis_x = 19.25
|
||||
offset_axis_z = 0.0
|
||||
hide_tooltips = False
|
||||
diameter offset_axis_x = 0
|
||||
kbd_height = 250
|
||||
kbd_width = 880
|
||||
kbd_set_height = False
|
||||
kbd_set_width = False
|
||||
hide_titlebar = False
|
||||
icon_theme = classic
|
||||
gcode_theme = classic
|
||||
audio_enabled = True
|
||||
audio_alert = /usr/share/sounds/freedesktop/stereo/dialog-warning.oga
|
||||
audio_error = /usr/share/sounds/freedesktop/stereo/dialog-error.oga
|
||||
show_keyboard_on_file_selection = False
|
||||
|
||||
6
my-emco-compact-5/postgui_call_list.hal
Normal file
6
my-emco-compact-5/postgui_call_list.hal
Normal file
@@ -0,0 +1,6 @@
|
||||
# These files are loaded post GUI, in the order they appear
|
||||
# Generated by stepconf 1.1 at Mon Mar 14 20:22:34 2022
|
||||
# If you make changes to this file, they will be
|
||||
# overwritten when you run stepconf again
|
||||
|
||||
source custom_postgui.hal
|
||||
1
my-emco-compact-5/python/remap.py
Normal file
1
my-emco-compact-5/python/remap.py
Normal file
@@ -0,0 +1 @@
|
||||
from stdglue import *
|
||||
672
my-emco-compact-5/python/stdglue.py
Normal file
672
my-emco-compact-5/python/stdglue.py
Normal file
@@ -0,0 +1,672 @@
|
||||
#NOTE:
|
||||
# The legacy names *selected_pocket* and *current_pocket* actually reference
|
||||
# a sequential tooldata index for tool items loaded from a tool
|
||||
# table ([EMCIO]TOOL_TABLE) or via a tooldata database ([EMCIO]DB_PROGRAM)
|
||||
|
||||
# stdglue - canned prolog and epilog functions for the remappable builtin codes (T,M6,M61,S,F)
|
||||
#
|
||||
# we dont use argspec to avoid the generic error message of the argspec prolog and give more
|
||||
# concise ones here
|
||||
|
||||
# cycle_prolog,cycle_epilog: generic code-independent support glue for oword sub cycles
|
||||
#
|
||||
# these are provided as starting point - for more concise error message you would better
|
||||
# write a prolog specific for the code
|
||||
#
|
||||
# Usage:
|
||||
#REMAP=G84.3 modalgroup=1 argspec=xyzqp prolog=cycle_prolog ngc=g843 epilog=cycle_epilog
|
||||
|
||||
import emccanon
|
||||
from interpreter import *
|
||||
from emccanon import MESSAGE
|
||||
throw_exceptions = 1
|
||||
|
||||
# used so screens can get info.
|
||||
# add this to toplevel to call it:
|
||||
|
||||
# import remap
|
||||
# def __init__(self):
|
||||
# if self.task:
|
||||
# remap.build_hal(self)
|
||||
|
||||
def build_hal(self):
|
||||
import hal
|
||||
try:
|
||||
h=hal.component('remapStat')
|
||||
h.newpin("tool", hal.HAL_S32, hal.HAL_OUT)
|
||||
h.newpin("wear", hal.HAL_S32, hal.HAL_OUT)
|
||||
h.ready()
|
||||
self.hal_tool_comp = h
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
# REMAP=S prolog=setspeed_prolog ngc=setspeed epilog=setspeed_epilog
|
||||
# exposed parameter: #<speed>
|
||||
|
||||
def setspeed_prolog(self,**words):
|
||||
try:
|
||||
c = self.blocks[self.remap_level]
|
||||
if not c.s_flag:
|
||||
self.set_errormsg("S requires a value")
|
||||
return INTERP_ERROR
|
||||
self.params["speed"] = c.s_number
|
||||
except Exception as e:
|
||||
self.set_errormsg("S/setspeed_prolog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
return INTERP_OK
|
||||
|
||||
def setspeed_epilog(self,**words):
|
||||
try:
|
||||
if not self.value_returned:
|
||||
r = self.blocks[self.remap_level].executing_remap
|
||||
self.set_errormsg("the %s remap procedure %s did not return a value"
|
||||
% (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
|
||||
return INTERP_ERROR
|
||||
if self.return_value < -TOLERANCE_EQUAL: # 'less than 0 within interp's precision'
|
||||
self.set_errormsg("S: remap procedure returned %f" % (self.return_value))
|
||||
return INTERP_ERROR
|
||||
if self.blocks[self.remap_level].builtin_used:
|
||||
pass
|
||||
#print "---------- S builtin recursion, nothing to do"
|
||||
else:
|
||||
self.speed[0] = self.params["speed"]
|
||||
emccanon.enqueue_SET_SPINDLE_SPEED(self.speed[0])
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
self.set_errormsg("S/setspeed_epilog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
return INTERP_OK
|
||||
|
||||
# REMAP=F prolog=setfeed_prolog ngc=setfeed epilog=setfeed_epilog
|
||||
# exposed parameter: #<feed>
|
||||
|
||||
def setfeed_prolog(self,**words):
|
||||
try:
|
||||
c = self.blocks[self.remap_level]
|
||||
if not c.f_flag:
|
||||
self.set_errormsg("F requires a value")
|
||||
return INTERP_ERROR
|
||||
self.params["feed"] = c.f_number
|
||||
except Exception as e:
|
||||
self.set_errormsg("F/setfeed_prolog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
return INTERP_OK
|
||||
|
||||
def setfeed_epilog(self,**words):
|
||||
try:
|
||||
if not self.value_returned:
|
||||
r = self.blocks[self.remap_level].executing_remap
|
||||
self.set_errormsg("the %s remap procedure %s did not return a value"
|
||||
% (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
|
||||
return INTERP_ERROR
|
||||
if self.blocks[self.remap_level].builtin_used:
|
||||
pass
|
||||
#print "---------- F builtin recursion, nothing to do"
|
||||
else:
|
||||
self.feed_rate = self.params["feed"]
|
||||
emccanon.enqueue_SET_FEED_RATE(self.feed_rate)
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
self.set_errormsg("F/setfeed_epilog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
return INTERP_OK
|
||||
|
||||
# REMAP=T prolog=prepare_prolog ngc=prepare epilog=prepare_epilog
|
||||
# exposed parameters: #<tool> #<pocket>
|
||||
|
||||
def prepare_prolog(self,**words):
|
||||
try:
|
||||
cblock = self.blocks[self.remap_level]
|
||||
if not cblock.t_flag:
|
||||
self.set_errormsg("T requires a tool number")
|
||||
return INTERP_ERROR
|
||||
tool = cblock.t_number
|
||||
if tool:
|
||||
(status, pocket) = self.find_tool_pocket(tool)
|
||||
if status != INTERP_OK:
|
||||
self.set_errormsg("T%d: pocket not found" % (tool))
|
||||
return status
|
||||
else:
|
||||
pocket = -1 # this is a T0 - tool unload
|
||||
self.params["tool"] = tool
|
||||
self.params["pocket"] = pocket
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
self.set_errormsg("T%d/prepare_prolog: %s" % (int(words['t']), e))
|
||||
return INTERP_ERROR
|
||||
|
||||
def prepare_epilog(self, **words):
|
||||
try:
|
||||
if not self.value_returned:
|
||||
r = self.blocks[self.remap_level].executing_remap
|
||||
self.set_errormsg("the %s remap procedure %s did not return a value"
|
||||
% (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
|
||||
return INTERP_ERROR
|
||||
if self.blocks[self.remap_level].builtin_used:
|
||||
#print "---------- T builtin recursion, nothing to do"
|
||||
return INTERP_OK
|
||||
else:
|
||||
if self.return_value > 0:
|
||||
self.selected_tool = int(self.params["tool"])
|
||||
self.selected_pocket = int(self.params["pocket"])
|
||||
emccanon.SELECT_TOOL(self.selected_tool)
|
||||
return INTERP_OK
|
||||
else:
|
||||
self.set_errormsg("T%d: aborted (return code %.1f)" % (int(self.params["tool"]),self.return_value))
|
||||
return INTERP_ERROR
|
||||
except Exception as e:
|
||||
self.set_errormsg("T%d/prepare_epilog: %s" % (tool,e))
|
||||
return INTERP_ERROR
|
||||
|
||||
# REMAP=M6 modalgroup=6 prolog=change_prolog ngc=change epilog=change_epilog
|
||||
# exposed parameters:
|
||||
# #<tool_in_spindle>
|
||||
# #<selected_tool>
|
||||
# #<current_pocket>
|
||||
# #<selected_pocket>
|
||||
|
||||
def change_prolog(self, **words):
|
||||
try:
|
||||
# this is relevant only when using iocontrol-v2.
|
||||
if self.params[5600] > 0.0:
|
||||
if self.params[5601] < 0.0:
|
||||
self.set_errormsg("Toolchanger hard fault %d" % (int(self.params[5601])))
|
||||
return INTERP_ERROR
|
||||
print("change_prolog: Toolchanger soft fault %d" % int(self.params[5601]))
|
||||
|
||||
if self.selected_pocket < 0:
|
||||
self.set_errormsg("M6: no tool prepared")
|
||||
return INTERP_ERROR
|
||||
if self.cutter_comp_side:
|
||||
self.set_errormsg("Cannot change tools with cutter radius compensation on")
|
||||
return INTERP_ERROR
|
||||
self.params["tool_in_spindle"] = self.current_tool
|
||||
self.params["selected_tool"] = self.selected_tool
|
||||
self.params["current_pocket"] = self.current_pocket
|
||||
self.params["selected_pocket"] = self.selected_pocket
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
self.set_errormsg("M6/change_prolog: %s" % (e))
|
||||
return INTERP_ERROR
|
||||
|
||||
def change_epilog(self, **words):
|
||||
try:
|
||||
if not self.value_returned:
|
||||
r = self.blocks[self.remap_level].executing_remap
|
||||
self.set_errormsg("the %s remap procedure %s did not return a value"
|
||||
% (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
|
||||
yield INTERP_ERROR
|
||||
# this is relevant only when using iocontrol-v2.
|
||||
if self.params[5600] > 0.0:
|
||||
if self.params[5601] < 0.0:
|
||||
self.set_errormsg("Toolchanger hard fault %d" % (int(self.params[5601])))
|
||||
yield INTERP_ERROR
|
||||
print("change_epilog: Toolchanger soft fault %d" % int(self.params[5601]))
|
||||
|
||||
if self.blocks[self.remap_level].builtin_used:
|
||||
#print "---------- M6 builtin recursion, nothing to do"
|
||||
yield INTERP_OK
|
||||
else:
|
||||
if self.return_value > 0.0:
|
||||
# commit change
|
||||
self.selected_pocket = int(self.params["selected_pocket"])
|
||||
emccanon.CHANGE_TOOL(self.selected_pocket)
|
||||
self.current_pocket = self.selected_pocket
|
||||
self.selected_pocket = -1
|
||||
self.selected_tool = -1
|
||||
# cause a sync()
|
||||
self.set_tool_parameters()
|
||||
self.toolchange_flag = True
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
else:
|
||||
# yield to print any messages from the NGC program
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
self.set_errormsg("M6 aborted (return code %.1f)" % (self.return_value))
|
||||
yield INTERP_ERROR
|
||||
except Exception as e:
|
||||
self.set_errormsg("M6/change_epilog: %s" % (e))
|
||||
yield INTERP_ERROR
|
||||
|
||||
# REMAP=M61 modalgroup=6 prolog=settool_prolog ngc=settool epilog=settool_epilog
|
||||
# exposed parameters: #<tool> #<pocket>
|
||||
|
||||
def settool_prolog(self,**words):
|
||||
try:
|
||||
c = self.blocks[self.remap_level]
|
||||
if not c.q_flag:
|
||||
self.set_errormsg("M61 requires a Q parameter")
|
||||
return INTERP_ERROR
|
||||
tool = int(c.q_number)
|
||||
if tool < -TOLERANCE_EQUAL: # 'less than 0 within interp's precision'
|
||||
self.set_errormsg("M61: Q value < 0")
|
||||
return INTERP_ERROR
|
||||
(status,pocket) = self.find_tool_pocket(tool)
|
||||
if status != INTERP_OK:
|
||||
self.set_errormsg("M61 failed: requested tool %d not in table" % (tool))
|
||||
return status
|
||||
self.params["tool"] = tool
|
||||
self.params["pocket"] = pocket
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
self.set_errormsg("M61/settool_prolog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
|
||||
def settool_epilog(self,**words):
|
||||
try:
|
||||
if not self.value_returned:
|
||||
r = self.blocks[self.remap_level].executing_remap
|
||||
self.set_errormsg("the %s remap procedure %s did not return a value"
|
||||
% (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
|
||||
return INTERP_ERROR
|
||||
|
||||
if self.blocks[self.remap_level].builtin_used:
|
||||
#print "---------- M61 builtin recursion, nothing to do"
|
||||
return INTERP_OK
|
||||
else:
|
||||
if self.return_value > 0.0:
|
||||
self.current_tool = int(self.params["tool"])
|
||||
self.current_pocket = int(self.params["pocket"])
|
||||
emccanon.CHANGE_TOOL_NUMBER(self.current_pocket)
|
||||
# cause a sync()
|
||||
self.tool_change_flag = True
|
||||
self.set_tool_parameters()
|
||||
else:
|
||||
self.set_errormsg("M61 aborted (return code %.1f)" % (self.return_value))
|
||||
return INTERP_ERROR
|
||||
except Exception as e:
|
||||
self.set_errormsg("M61/settool_epilog: %s)" % (e))
|
||||
return INTERP_ERROR
|
||||
|
||||
# educational alternative: M61 remapped to an all-Python handler
|
||||
# demo - this really does the same thing as the builtin (non-remapped) M61
|
||||
#
|
||||
# REMAP=M61 modalgroup=6 python=set_tool_number
|
||||
|
||||
def set_tool_number(self, **words):
|
||||
try:
|
||||
c = self.blocks[self.remap_level]
|
||||
if c.q_flag:
|
||||
toolno = int(c.q_number)
|
||||
else:
|
||||
self.set_errormsg("M61 requires a Q parameter")
|
||||
return status
|
||||
(status,pocket) = self.find_tool_pocket(toolno)
|
||||
if status != INTERP_OK:
|
||||
self.set_errormsg("M61 failed: requested tool %d not in table" % (toolno))
|
||||
return status
|
||||
if words['q'] > -TOLERANCE_EQUAL: # 'greater equal 0 within interp's precision'
|
||||
self.current_pocket = pocket
|
||||
self.current_tool = toolno
|
||||
emccanon.CHANGE_TOOL_NUMBER(pocket)
|
||||
# cause a sync()
|
||||
self.tool_change_flag = True
|
||||
self.set_tool_parameters()
|
||||
return INTERP_OK
|
||||
else:
|
||||
self.set_errormsg("M61 failed: Q=%4" % (toolno))
|
||||
return INTERP_ERROR
|
||||
except Exception as e:
|
||||
self.set_errormsg("M61/set_tool_number: %s" % (e))
|
||||
return INTERP_ERROR
|
||||
|
||||
_uvw = ("u","v","w","a","b","c")
|
||||
_xyz = ("x","y","z","a","b","c")
|
||||
# given a plane, return sticky words, incompatible axis words and plane name
|
||||
# sticky[0] is also the movement axis
|
||||
_compat = {
|
||||
emccanon.CANON_PLANE_XY : (("z","r"),_uvw,"XY"),
|
||||
emccanon.CANON_PLANE_YZ : (("x","r"),_uvw,"YZ"),
|
||||
emccanon.CANON_PLANE_XZ : (("y","r"),_uvw,"XZ"),
|
||||
emccanon.CANON_PLANE_UV : (("w","r"),_xyz,"UV"),
|
||||
emccanon.CANON_PLANE_VW : (("u","r"),_xyz,"VW"),
|
||||
emccanon.CANON_PLANE_UW : (("v","r"),_xyz,"UW")}
|
||||
|
||||
# extract and pass parameters from current block, merged with extra parameters on a continuation line
|
||||
# keep tjose parameters across invocations
|
||||
# export the parameters into the oword procedure
|
||||
def cycle_prolog(self,**words):
|
||||
# self.sticky_params is assumed to have been initialized by the
|
||||
# init_stgdlue() method below
|
||||
global _compat
|
||||
try:
|
||||
# determine whether this is the first or a subsequent call
|
||||
c = self.blocks[self.remap_level]
|
||||
r = c.executing_remap
|
||||
if c.g_modes[1] == r.motion_code:
|
||||
# first call - clear the sticky dict
|
||||
self.sticky_params[r.name] = dict()
|
||||
|
||||
self.params["motion_code"] = c.g_modes[1]
|
||||
|
||||
(sw,incompat,plane_name) =_compat[self.plane]
|
||||
for (word,value) in list(words.items()):
|
||||
# inject current parameters
|
||||
self.params[word] = value
|
||||
# record sticky words
|
||||
if word in sw:
|
||||
if self.debugmask & 0x00080000: print("%s: record sticky %s = %.4f" % (r.name,word,value))
|
||||
self.sticky_params[r.name][word] = value
|
||||
if word in incompat:
|
||||
return "%s: Cannot put a %s in a canned cycle in the %s plane" % (r.name, word.upper(), plane_name)
|
||||
|
||||
# inject sticky parameters which were not in words:
|
||||
for (key,value) in list(self.sticky_params[r.name].items()):
|
||||
if not key in words:
|
||||
if self.debugmask & 0x00080000: print("%s: inject sticky %s = %.4f" % (r.name,key,value))
|
||||
self.params[key] = value
|
||||
|
||||
if not "r" in self.sticky_params[r.name]:
|
||||
return "%s: cycle requires R word" % (r.name)
|
||||
else:
|
||||
if self.sticky_params[r.name]['r'] <= 0.0:
|
||||
return "%s: R word must be > 0 if used (%.4f)" % (r.name, words["r"])
|
||||
|
||||
if "l" in words:
|
||||
# checked in interpreter during block parsing
|
||||
# if l <= 0 or l not near an int
|
||||
self.params["l"] = words["l"]
|
||||
|
||||
if "p" in words:
|
||||
p = words["p"]
|
||||
if p < 0.0:
|
||||
return "%s: P word must be >= 0 if used (%.4f)" % (r.name, p)
|
||||
self.params["p"] = p
|
||||
|
||||
if self.feed_rate == 0.0:
|
||||
return "%s: feed rate must be > 0" % (r.name)
|
||||
if self.feed_mode == INVERSE_TIME:
|
||||
return "%s: Cannot use inverse time feed with canned cycles" % (r.name)
|
||||
if self.cutter_comp_side:
|
||||
return "%s: Cannot use canned cycles with cutter compensation on" % (r.name)
|
||||
return INTERP_OK
|
||||
|
||||
except Exception as e:
|
||||
raise
|
||||
return "cycle_prolog failed: %s" % (e)
|
||||
|
||||
# make sure the next line has the same motion code, unless overridden by a
|
||||
# new G-code
|
||||
def cycle_epilog(self,**words):
|
||||
try:
|
||||
c = self.blocks[self.remap_level]
|
||||
self.motion_mode = c.executing_remap.motion_code # retain the current motion mode
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
return "cycle_epilog failed: %s" % (e)
|
||||
|
||||
# this should be called from TOPLEVEL __init__()
|
||||
def init_stdglue(self):
|
||||
self.sticky_params = dict()
|
||||
|
||||
#####################################
|
||||
# pure python remaps
|
||||
#####################################
|
||||
|
||||
# REMAP=M6 python=ignore_m6
|
||||
#
|
||||
# m5 silently ignored
|
||||
#
|
||||
def ignore_m6(self,**words):
|
||||
try:
|
||||
return INTERP_OK
|
||||
except Exception as e:
|
||||
return "Ignore M6 failed: %s" % (e)
|
||||
|
||||
# REMAP=T python=index_lathe_tool_with_wear
|
||||
#
|
||||
# uses T101 for tool 1, wear 1 no M6 needed
|
||||
# tool offsets for tool 1 and tool 10001 are added together.
|
||||
#
|
||||
def index_lathe_tool_with_wear(self,**words):
|
||||
# only run this if we are really moving the machine
|
||||
# skip this if running task for the screen
|
||||
if not self.task:
|
||||
yield INTERP_OK
|
||||
try:
|
||||
# check there is a tool number from the Gcode
|
||||
cblock = self.blocks[self.remap_level]
|
||||
if not cblock.t_flag:
|
||||
self.set_errormsg("T requires a tool number")
|
||||
yield INTERP_ERROR
|
||||
tool_raw = int(cblock.t_number)
|
||||
|
||||
# interpret the raw tool number into tool and wear number
|
||||
# If it's less then 100 someone forgot to add the wear #, so we added it automatically
|
||||
# separate out tool number (tool) and wear number (wear), add 10000 to wear number
|
||||
if tool_raw <100:
|
||||
tool_raw=tool_raw*100
|
||||
tool = int(tool_raw/100)
|
||||
wear = 10000 + tool_raw % 100
|
||||
|
||||
# uncomment for debugging
|
||||
#print'***tool#',cblock.t_number,'toolraw:',tool_raw,'tool split:',tool,'wear split',wear
|
||||
if tool:
|
||||
# check for tool number entry in tool file
|
||||
(status, pocket) = self.find_tool_pocket(tool)
|
||||
if status != INTERP_OK:
|
||||
self.set_errormsg("T%d: tool entry not found" % (tool))
|
||||
yield status
|
||||
else:
|
||||
tool = -1
|
||||
pocket = -1
|
||||
wear = -1
|
||||
self.params["tool"] = tool
|
||||
self.params["pocket"] = pocket
|
||||
self.params["wear"] = wear
|
||||
try:
|
||||
self.hal_tool_comp['tool']= tool_raw
|
||||
self.hal_tool_comp['wear']= wear
|
||||
except:
|
||||
pass
|
||||
# index tool immediately to tool number
|
||||
self.selected_tool = int(self.params["tool"])
|
||||
self.selected_pocket = int(self.params["pocket"])
|
||||
emccanon.SELECT_TOOL(self.selected_tool)
|
||||
if self.selected_pocket < 0:
|
||||
self.set_errormsg("T0 not valid")
|
||||
yield INTERP_ERROR
|
||||
if self.cutter_comp_side:
|
||||
self.set_errormsg("Cannot change tools with cutter radius compensation on")
|
||||
yield INTERP_ERROR
|
||||
self.params["tool_in_spindle"] = self.current_tool
|
||||
self.params["selected_tool"] = self.selected_tool
|
||||
self.params["current_pocket"] = self.current_pocket
|
||||
self.params["selected_pocket"] = self.selected_pocket
|
||||
|
||||
# change tool
|
||||
try:
|
||||
self.selected_pocket = int(self.params["selected_pocket"])
|
||||
emccanon.CHANGE_TOOL(self.selected_pocket)
|
||||
self.current_pocket = self.selected_pocket
|
||||
self.selected_pocket = -1
|
||||
self.selected_tool = -1
|
||||
# cause a sync()
|
||||
self.set_tool_parameters()
|
||||
self.toolchange_flag = True
|
||||
except:
|
||||
self.set_errormsg("T change aborted (return code %.1f)" % (self.return_value))
|
||||
yield INTERP_ERROR
|
||||
|
||||
# add tool offset
|
||||
self.execute("g43 h%d"% tool)
|
||||
# if the wear offset is specified, add it's offset
|
||||
try:
|
||||
if wear>10000:
|
||||
self.execute("g43.2 h%d"% wear)
|
||||
yield INTERP_OK
|
||||
except:
|
||||
self.set_errormsg("Tool change aborted - No wear %d entry found in tool table" %wear)
|
||||
yield INTERP_ERROR
|
||||
except:
|
||||
self.set_errormsg("Tool change aborted (return code %.1f)" % (self.return_value))
|
||||
yield INTERP_ERROR
|
||||
|
||||
|
||||
# REMAP=M6 modalgroup=10 python=tool_probe_m6
|
||||
#
|
||||
# auto tool probe on m6
|
||||
# move to tool change position for toolchange
|
||||
# wait for acknowledge of tool change
|
||||
# move to tool setter probe position
|
||||
# probe tool on tool setter
|
||||
# move back to tool change position
|
||||
# set offsets
|
||||
# based on Versaprobe remap
|
||||
#
|
||||
# param 5000 holds the work piece height
|
||||
# param 4999 should be set to 1 if the
|
||||
# machine is based in imperial
|
||||
#
|
||||
# required INI settings
|
||||
# (Abs coordinates/ machine based units)
|
||||
#
|
||||
#[CHANGE_POSITION]
|
||||
#X = 5
|
||||
#Y = 0
|
||||
#Z = 0
|
||||
|
||||
#[TOOLSENSOR]
|
||||
#X = 5.00
|
||||
#Y = -1
|
||||
#Z = -1
|
||||
#PROBEHEIGHT = 2.3
|
||||
#MAXPROBE = -3
|
||||
#SEARCH_VEL = 20
|
||||
#PROBE_VEL = 5
|
||||
|
||||
def tool_probe_m6(self, **words):
|
||||
|
||||
# only run this if we are really moving the machine
|
||||
# skip this if running task for the screen
|
||||
if not self.task:
|
||||
yield INTERP_OK
|
||||
|
||||
IMPERIAL_BASED = not(bool(self.params['_metric_machine']))
|
||||
|
||||
try:
|
||||
# we need to be in machine based units
|
||||
# if we aren't - switch
|
||||
# remember so we can switch back later
|
||||
switchUnitsFlag = False
|
||||
if bool(self.params["_imperial"]) != IMPERIAL_BASED:
|
||||
print ("not right Units: {}".format(bool(self.params["_imperial"])))
|
||||
if IMPERIAL_BASED:
|
||||
print ("switched Units to imperial")
|
||||
self.execute("G20")
|
||||
else:
|
||||
print ("switched Units to metric")
|
||||
self.execute("G21")
|
||||
switchUnitsFlag = True
|
||||
|
||||
self.params["tool_in_spindle"] = self.current_tool
|
||||
self.params["selected_tool"] = self.selected_tool
|
||||
self.params["current_pocket"] = self.current_pocket
|
||||
self.params["selected_pocket"] = self.selected_pocket
|
||||
|
||||
# cancel tool offset
|
||||
self.execute("G49")
|
||||
|
||||
# change tool where ever we are
|
||||
# user sets toolchange position prior to toolchange
|
||||
# we will return here after
|
||||
|
||||
try:
|
||||
self.selected_pocket = int(self.params["selected_pocket"])
|
||||
emccanon.CHANGE_TOOL(self.selected_pocket)
|
||||
self.current_pocket = self.selected_pocket
|
||||
self.selected_pocket = -1
|
||||
self.selected_tool = -1
|
||||
# cause a sync()
|
||||
self.set_tool_parameters()
|
||||
self.toolchange_flag = True
|
||||
except InterpreterException as e:
|
||||
self.set_errormsg("tool_probe_m6 remap error: %s" % (e))
|
||||
yield INTERP_ERROR
|
||||
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
|
||||
# record current position; probably should record every axis
|
||||
self.params[4999] = emccanon.GET_EXTERNAL_POSITION_X()
|
||||
self.params[4998] = emccanon.GET_EXTERNAL_POSITION_Y()
|
||||
self.params[4997] = emccanon.GET_EXTERNAL_POSITION_Z()
|
||||
|
||||
try:
|
||||
# move to tool probe position (from INI)
|
||||
self.execute("G90")
|
||||
self.execute("G53 G0 X[#<_ini[TOOLSENSOR]X>] Y[#<_ini[TOOLSENSOR]Y>]")
|
||||
self.execute("G53 G0 Z[#<_ini[TOOLSENSOR]Z>]")
|
||||
|
||||
# set incremental mode
|
||||
self.execute("G91")
|
||||
|
||||
# course probe
|
||||
self.execute("F [#<_ini[TOOLSENSOR]SEARCH_VEL>]")
|
||||
self.execute("G38.2 Z [#<_ini[TOOLSENSOR]MAXPROBE>]")
|
||||
|
||||
# Wait for results
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
|
||||
# FIXME if there is an error it never comes back
|
||||
# which leaves linuxcnc in g91 state
|
||||
if self.params[5070] == 0 or self.return_value > 0.0:
|
||||
self.execute("G90")
|
||||
self.set_errormsg("tool_probe_m6 remap error:")
|
||||
yield INTERP_ERROR
|
||||
|
||||
# rapid up off trigger point to do it again
|
||||
if bool(self.params["_imperial"]):
|
||||
f = 0.25
|
||||
else:
|
||||
f = 4.0
|
||||
self.execute("G0 Z{}".format(f))
|
||||
|
||||
self.execute("F [#<_ini[TOOLSENSOR]PROBE_VEL>]")
|
||||
self.execute("G38.2 Z-0.5")
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
|
||||
# FIXME if there is an error it never comes back
|
||||
# which leaves linuxcnc in g91 state
|
||||
if self.params[5070] == 0 or self.return_value > 0.0:
|
||||
self.execute("G90")
|
||||
self.set_errormsg("tool_probe_m6 remap error:")
|
||||
yield INTERP_ERROR
|
||||
|
||||
# set back absolute state
|
||||
self.execute("G90")
|
||||
|
||||
# return to recorded tool change position
|
||||
self.execute("G53 G0 Z[#4997]")
|
||||
yield INTERP_EXECUTE_FINISH
|
||||
self.execute("G53 G0 X[#4999] Y[#4998]")
|
||||
|
||||
# adjust tool offset from calculations
|
||||
proberesult = self.params[5063]
|
||||
probeheight = self.params["_ini[TOOLSENSOR]PROBEHEIGHT"]
|
||||
workheight = self.params[5000]
|
||||
|
||||
adj = proberesult - probeheight + workheight
|
||||
self.execute("G10 L1 P#<selected_tool> Z{}".format(adj))
|
||||
|
||||
# apply tool offset
|
||||
self.execute("G43")
|
||||
|
||||
# if we switched units for tool change - switch back
|
||||
if switchUnitsFlag:
|
||||
if IMPERIAL_BASED:
|
||||
self.execute("G21")
|
||||
print ("switched Units back to metric")
|
||||
else:
|
||||
self.execute("G20")
|
||||
print ("switched Units back to imperial")
|
||||
|
||||
except InterpreterException as e:
|
||||
msg = "%d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
|
||||
print (msg)
|
||||
yield INTERP_ERROR
|
||||
|
||||
except:
|
||||
self.set_errormsg("tool_probe_m6 remap error." )
|
||||
yield INTERP_ERROR
|
||||
|
||||
|
||||
|
||||
1
my-emco-compact-5/python/toplevel.py
Normal file
1
my-emco-compact-5/python/toplevel.py
Normal file
@@ -0,0 +1 @@
|
||||
import remap
|
||||
347
my-emco-compact-5/serialEventHandler.py
Normal file
347
my-emco-compact-5/serialEventHandler.py
Normal file
@@ -0,0 +1,347 @@
|
||||
#! /usr/bin/python
|
||||
"""usage serialEventHanlder.py -h -c <name> -d/--debug= <level> -p/--port= <serial port> <path/>in_file.xml
|
||||
in_file - input xml-file describing what knobs and/or button are on the pendant
|
||||
-c <name> # name of component in HAL. 'my-mpg' default
|
||||
-d/--debug= <level> # debug level, default 0
|
||||
-p/--port= <serial port> # serial port to use. '/dev/ttyUSB0' default
|
||||
-h # Help
|
||||
python serialEventHandler.py -w mpg_pendant/config/mpg.xml
|
||||
"""
|
||||
|
||||
### https://docs.python.org/2/library/xml.etree.elementtree.html
|
||||
|
||||
import time
|
||||
import getopt
|
||||
import sys
|
||||
import comms
|
||||
import xml.etree.ElementTree as ET
|
||||
import hal
|
||||
from collections import namedtuple
|
||||
|
||||
class Pin:
|
||||
""" General representation of a Pin and it's data"""
|
||||
def __init__(self, name, type, observer = None):
|
||||
self.name = name # HAL pin name
|
||||
self.val = 0 # current value of pin, e.g. 1 - on, 0 - off
|
||||
self.type = type # type (string read from xml)
|
||||
self.observer = None
|
||||
|
||||
if observer != None:
|
||||
self.attach(observer)
|
||||
|
||||
def __repr__(self):
|
||||
return 'pin name: ' + self.name + '\tval: ' + str(self.val) + '\ttype: ' + self.type
|
||||
|
||||
def attach(self, observer):
|
||||
self.observer = observer
|
||||
|
||||
def _notify(self):
|
||||
if self.observer != None:
|
||||
self.observer.update(self.name, self.val)
|
||||
|
||||
def update_hal(self, v):
|
||||
""" to be overriden in child-class"""
|
||||
pass
|
||||
|
||||
def set(self, v):
|
||||
pass
|
||||
|
||||
def _type_saturate(self, type, val):
|
||||
""" helper function to convert type read from xml to HAL-type """
|
||||
retVal = 0
|
||||
|
||||
if type == 'bit':
|
||||
if val >= 1:
|
||||
retVal = 1
|
||||
|
||||
if type == 'float':
|
||||
retVal = val
|
||||
|
||||
if type == 's32':
|
||||
retVal = val
|
||||
|
||||
if type == 'u32':
|
||||
retVal = val
|
||||
|
||||
return retVal
|
||||
|
||||
def _get_hal_type(self, str):
|
||||
""" helper function to convert type read from xml to HAL-type """
|
||||
retVal = ''
|
||||
|
||||
if str == 'bit':
|
||||
retVal = hal.HAL_BIT
|
||||
|
||||
if str == 'float':
|
||||
retVal = hal.HAL_FLOAT
|
||||
|
||||
if str == 's32':
|
||||
retVal = hal.HAL_S32
|
||||
|
||||
if str == 'u32':
|
||||
retVal = hal.HAL_U32
|
||||
|
||||
return retVal
|
||||
|
||||
class InPin(Pin):
|
||||
""" Specialization of Pin-class"""
|
||||
def __init__(self, hal_ref, name, type, observer = None):
|
||||
Pin.__init__(self, name, type, observer)
|
||||
|
||||
hal_ref.newpin(name, self._get_hal_type(type), hal.HAL_IN) # create the user space HAL-pin
|
||||
|
||||
def __repr__(self):
|
||||
return 'Input pin ' + Pin.__repr__(self)
|
||||
|
||||
def update_hal(self, hal):
|
||||
if self.val != hal[self.name]:
|
||||
self.val = hal[self.name]
|
||||
self._notify()
|
||||
|
||||
class OutPin(Pin):
|
||||
""" Specialization of Pin-class"""
|
||||
def __init__(self, hal_ref, name, type, observer = None):
|
||||
Pin.__init__(self, name, type, observer)
|
||||
|
||||
hal_ref.newpin(name, self._get_hal_type(type), hal.HAL_OUT) # create the user space HAL-pin
|
||||
|
||||
def __repr__(self):
|
||||
return 'Output pin ' + Pin.__repr__(self)
|
||||
|
||||
def update_hal(self, hal):
|
||||
hal[self.name] = self.val
|
||||
|
||||
def set(self, v):
|
||||
try:
|
||||
self.val = self._type_saturate(self.type, int(v))
|
||||
except ValueError:
|
||||
print('OutPin::set() value error catched on: ' + self.name)
|
||||
|
||||
class Observer:
|
||||
""" container for notification-function """
|
||||
def __init__(self, update_cb):
|
||||
self.update_cb = update_cb
|
||||
|
||||
def update(self, name, val):
|
||||
#pass
|
||||
try:
|
||||
#print 'observer::update name: ' + name + ' val: ' + str(val)
|
||||
self.update_cb(name, val)
|
||||
except ValueError:
|
||||
print('Observer::notify() value error catched on: ' + self.name)
|
||||
|
||||
class HALComponentWrapper:
|
||||
def __init__(self, name):
|
||||
self.pin_dict = {} # dictionary used to map event to pin
|
||||
self.hal = hal.component(name) # instanciate the HAL-component
|
||||
self.observer = None
|
||||
|
||||
def __repr__(self):
|
||||
tmp_str = ''
|
||||
for k in self.pin_dict:
|
||||
tmp_str += 'event: ' + k + '\t' + str(self.pin_dict[k]) + '\n'
|
||||
return tmp_str
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key in self.pin_dict:
|
||||
return self.pin_dict[key].val
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
self.set_pin(key, val)
|
||||
|
||||
def add_pin(self, event_name, hal_name, type, direction = 'out'):
|
||||
self.pin_dict[event_name] = self._createPin(hal_name, type, direction)
|
||||
|
||||
def event_set_pin(self, event):
|
||||
""" updates pin value with new data
|
||||
input: pin name, set value'
|
||||
output: nothing. """
|
||||
if event.name in self.pin_dict:
|
||||
self.pin_dict[event.name].set(event.data)
|
||||
|
||||
def set_pin(self, key, value):
|
||||
""" updates pin value with new data
|
||||
input: event name, set value'
|
||||
output: nothing. """
|
||||
if key in self.pin_dict:
|
||||
self.pin_dict[key].set(value)
|
||||
|
||||
def setReady(self):
|
||||
self.hal.ready()
|
||||
|
||||
def update_hal(self):
|
||||
for key in self.pin_dict:
|
||||
self.pin_dict[key].update_hal(self.hal)
|
||||
|
||||
def attach(self, observer):
|
||||
self.observer = observer
|
||||
|
||||
def _createPin(self, hal_name, type, direction):
|
||||
""" factory function to create pin"""
|
||||
if direction == 'in':
|
||||
return InPin(self.hal, hal_name, type, Observer(self.notify))
|
||||
|
||||
if direction == 'out':
|
||||
return OutPin(self.hal, hal_name, type)
|
||||
|
||||
def notify(self, hal_name, val):
|
||||
# convert pin-name to event-name
|
||||
for key in self.pin_dict:
|
||||
if self.pin_dict[key].name == hal_name and self.observer != None:
|
||||
self.observer.update(key, val)
|
||||
|
||||
class OptParser:
|
||||
def __init__(self, argv):
|
||||
self.xml_file = '' # input xml-file describing what knobs and/or button are on the pendant
|
||||
self.name = 'my-mpg' # default name of component in HAL
|
||||
self.port = '/dev/ttyUSB0' # default serial port to use
|
||||
self.watchdog_reset = False
|
||||
|
||||
self._get_options(argv)
|
||||
|
||||
def __repr__(self):
|
||||
return 'xml_file: ' + self.xml_file + '\tname: ' + self.name + '\tport: ' + self.port
|
||||
|
||||
def _get_options(self, argv):
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "hwp:c:", ["input=", "port="])
|
||||
except getopt.GetoptError as err:
|
||||
# print help information and exit:
|
||||
print(err) # will print something like "option -a not recognized"
|
||||
sys.exit(2)
|
||||
|
||||
### parse input command line
|
||||
for o, a in opts:
|
||||
if o == "-h":
|
||||
self._usage()
|
||||
sys.exit()
|
||||
if o == "-c":
|
||||
self.name = a
|
||||
elif o == "--input":
|
||||
self.xml_file = a
|
||||
elif o in ("-p", "--port"):
|
||||
self.port = a
|
||||
elif o == "-w":
|
||||
self.watchdog_reset = True
|
||||
else:
|
||||
print(o, a)
|
||||
assert False, "unhandled option"
|
||||
|
||||
if self.xml_file == '':
|
||||
if len(sys.argv) < 2:
|
||||
self._usage()
|
||||
sys.exit(2)
|
||||
else:
|
||||
self.xml_file = argv[-1]
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_port(self):
|
||||
return self.port
|
||||
|
||||
def get_XML_file(self):
|
||||
return self.xml_file
|
||||
|
||||
def get_watchdog_reset(self):
|
||||
return self.watchdog_reset
|
||||
|
||||
def _usage(self):
|
||||
""" print command line options """
|
||||
print("usage serialEventHandler.py -h -c <name> -d/--debug=<level> -p/--port= <serial port> <path/>in_file.xml\n"\
|
||||
"in_file - input xml-file describing what knobs and/or button are on the pendant\n"\
|
||||
"-c <name> # name of component in HAL. 'mpg' default\n"\
|
||||
"-p/--port= <serial port> # default serial port to use. '/dev/ttyS2' default\n"\
|
||||
"-w # start watchdog deamon" \
|
||||
"-h # Help test")
|
||||
|
||||
""" Parser data container"""
|
||||
HalPin = namedtuple("HalPin", ['name', 'event', 'type', 'direction'])
|
||||
|
||||
class XmlParser:
|
||||
def __init__(self, f):
|
||||
self.tree = []
|
||||
self.parsed_data = [] #array of named tuples (HalPin)
|
||||
|
||||
self._parse_file(f)
|
||||
|
||||
def __repr__(self):
|
||||
tmp_str = ''
|
||||
|
||||
for element in self.parsed_data:
|
||||
tmp_str += 'name: ' + element.name + '\t' + 'event: ' + element.event + '\t' + 'type: ' + element.type + '\n'
|
||||
return tmp_str
|
||||
|
||||
def get_parsed_data(self):
|
||||
return self.parsed_data
|
||||
|
||||
def _parse_file(self, f):
|
||||
self.tree = ET.parse(f)
|
||||
root = self.tree.getroot()
|
||||
|
||||
for halpin in root.iter('halpin'):
|
||||
name = halpin.text.strip('"')
|
||||
type = 'u32' if halpin.find('type') is None else halpin.find('type').text
|
||||
event = name if halpin.find('event') is None else halpin.find('event').text
|
||||
direction = 'out' if halpin.find('direction') is None else halpin.find('direction').text
|
||||
|
||||
if self._check_supported_HAL_type(type) and self._check_supported_HAL_direction(direction):
|
||||
self.parsed_data.append(HalPin(name, event, type, direction))
|
||||
|
||||
def _check_supported_HAL_type(self, str):
|
||||
""" helper function to check if type is supported """
|
||||
retVal = False
|
||||
|
||||
if str == 'bit' or str == 'float' or str == 's32' or str == 'u32':
|
||||
retVal = True
|
||||
|
||||
return retVal
|
||||
|
||||
def _check_supported_HAL_direction(self, str):
|
||||
""" helper function to check if direction is supported """
|
||||
retVal = False
|
||||
|
||||
if str == 'in' or str == 'out':
|
||||
retVal = True
|
||||
|
||||
return retVal
|
||||
|
||||
################################################
|
||||
def main():
|
||||
optParser = OptParser(sys.argv[1:])
|
||||
componentName = optParser.get_name()
|
||||
portName = optParser.get_port()
|
||||
xmlFile = optParser.get_XML_file()
|
||||
watchdogEnabled = optParser.get_watchdog_reset()
|
||||
print(optParser)
|
||||
|
||||
xmlParser = XmlParser(xmlFile)
|
||||
|
||||
c = HALComponentWrapper(componentName) #HAL adaptor, takes care of mapping incomming events to actual hal-pin
|
||||
serialEventGenerator = comms.instrument(portName, c.event_set_pin, watchdogEnabled, 5, 1) #serial adaptor
|
||||
c.attach(Observer(serialEventGenerator.generateEvent))
|
||||
|
||||
# add/create the HAL-pins from parsed xml and attach them to the adaptor event handler
|
||||
parsed_data = xmlParser.get_parsed_data()
|
||||
for pin in parsed_data:
|
||||
c.add_pin(pin.event, pin.name, pin.type, pin.direction)
|
||||
|
||||
print(c)
|
||||
|
||||
# ready signal to HAL, component and it's pins are ready created
|
||||
c.setReady()
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
try:
|
||||
while 1:
|
||||
serialEventGenerator.readMessages() #blocks until '\n' received or timeout
|
||||
c.update_hal()
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
BIN
my-emco-compact-5/speeds.png
Normal file
BIN
my-emco-compact-5/speeds.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
114
my-emco-compact-5/spindle_speed_selector.glade
Normal file
114
my-emco-compact-5/spindle_speed_selector.glade
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<requires lib="gladevcp" version="0.0"/>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">spindle speed selection:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="img1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixbuf">speeds.png</property>
|
||||
<property name="icon_size">3</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HAL_Table" id="table1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="HAL_RadioButton" id="radio2">
|
||||
<property name="label" translatable="yes">AC2</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="margin_top">15</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">radio1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HAL_RadioButton" id="radio3">
|
||||
<property name="label" translatable="yes">AC3</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="margin_top">15</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">radio1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HAL_RadioButton" id="radio1">
|
||||
<property name="label" translatable="yes">AC1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="margin_top">15</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
12
my-emco-compact-5/spindle_speed_selector.hal
Normal file
12
my-emco-compact-5/spindle_speed_selector.hal
Normal file
@@ -0,0 +1,12 @@
|
||||
net all-homed spindle_speed_selector.table1
|
||||
net all-homed and2.1.in0
|
||||
net all-homed and2.2.in0
|
||||
net all-homed and2.3.in0
|
||||
|
||||
net spindle-speed-selector-panel-radio1 spindle_speed_selector.radio1 and2.1.in1
|
||||
net spindle-speed-selector-panel-radio2 spindle_speed_selector.radio2 and2.2.in1
|
||||
net spindle-speed-selector-panel-radio3 spindle_speed_selector.radio3 and2.3.in1
|
||||
|
||||
net and2-1-out and2.1.out halui.mdi-command-03
|
||||
net and2-2-out and2.2.out halui.mdi-command-04
|
||||
net and2-3-out and2.3.out halui.mdi-command-05
|
||||
9
my-emco-compact-5/sync-files.sh
Normal file
9
my-emco-compact-5/sync-files.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
find . -type f -name "*.py"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.ngc"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.hal"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.ini"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.sh"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.clp"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.tbl"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.var"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
find . -type f -name "*.xml"|xargs python3 ~/git-clones/linuxcnc-configs/sync-file.py -p -d -c ~/git-clones/linuxcnc-configs/my-emco-compact-5
|
||||
334
my-emco-compact-5/test_ladder.clp
Normal file
334
my-emco-compact-5/test_ladder.clp
Normal file
@@ -0,0 +1,334 @@
|
||||
_FILES_CLASSICLADDER
|
||||
_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.csv
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
_/FILE-timers.csv
|
||||
_FILE-rung_0.csv
|
||||
#VER=2.0
|
||||
#LABEL=
|
||||
#COMMENT=
|
||||
#PREVRUNG=4
|
||||
#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
|
||||
1-0-50/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/20 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/0 , 50-0-60/4
|
||||
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 9-1-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/9 , 50-0-60/5
|
||||
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
|
||||
1-0-50/1 , 99-0-0/0 , 99-0-0/0 , 20-0-0/21 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/11 , 50-0-60/6
|
||||
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 9-1-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/13 , 50-0-60/7
|
||||
_/FILE-rung_0.csv
|
||||
_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-ioconf.csv
|
||||
#VER=1.0
|
||||
_/FILE-ioconf.csv
|
||||
_FILE-sections.csv
|
||||
#VER=1.0
|
||||
#NAME000=Prog1
|
||||
000,0,-1,1,0,0
|
||||
_/FILE-sections.csv
|
||||
_FILE-arithmetic_expressions.csv
|
||||
#VER=2.0
|
||||
0000,@270/1@<3
|
||||
0001,@270/0@=1
|
||||
0002,@270/0@=0
|
||||
0003,@270/0@=3
|
||||
0004,@270/0@=2
|
||||
0005,@270/1@=0
|
||||
0006,@310/0@=10
|
||||
0007,@270/1@=1
|
||||
0008,@310/0@=1
|
||||
0009,@270/1@=3
|
||||
0010,@270/1@=2
|
||||
0011,@270/1@<3
|
||||
0012,@310/0@=100
|
||||
0013,@270/1@=3
|
||||
0020,@270/0@<2
|
||||
0021,@270/0@<2
|
||||
0022,@270/0@=2
|
||||
0024,@270/0@=2
|
||||
_/FILE-arithmetic_expressions.csv
|
||||
_FILE-counters.csv
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
_/FILE-counters.csv
|
||||
_FILE-rung_2.csv
|
||||
#VER=2.0
|
||||
#LABEL=
|
||||
#COMMENT=
|
||||
#PREVRUNG=1
|
||||
#NEXTRUNG=4
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/5 , 9-0-0/5 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 60-0-0/8
|
||||
0-0-0/0 , 0-0-0/0 , 0-0-0/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/9
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/7 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 60-0-0/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/13
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/10 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/12 , 60-0-60/12
|
||||
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_2.csv
|
||||
_FILE-rung_4.csv
|
||||
#VER=2.0
|
||||
#LABEL=
|
||||
#COMMENT=
|
||||
#PREVRUNG=2
|
||||
#NEXTRUNG=0
|
||||
1-0-50/0 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/22 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/8
|
||||
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
|
||||
1-0-50/1 , 9-0-0/0 , 99-0-0/0 , 99-0-0/0 , 20-0-0/24 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/9
|
||||
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/23 , 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_4.csv
|
||||
_FILE-rung_1.csv
|
||||
#VER=2.0
|
||||
#LABEL=
|
||||
#COMMENT=
|
||||
#PREVRUNG=2
|
||||
#NEXTRUNG=2
|
||||
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
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/2 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/0
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/1 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/1
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/4 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/2
|
||||
99-0-0/0 , 99-0-0/0 , 20-0-0/3 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 9-0-0/0 , 50-0-60/3
|
||||
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-monostables.csv
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
1,0
|
||||
_/FILE-monostables.csv
|
||||
_FILE-symbols.csv
|
||||
#VER=1.0
|
||||
%I0,%jog-plus,no signal connected
|
||||
%I1,%jog-minu,
|
||||
%I2,%sp-sel1,
|
||||
%I3,%sp-sel2,
|
||||
%I4,%sp-sel3,
|
||||
%I5,%I5,
|
||||
%I6,%I6,
|
||||
%I7,%I7,
|
||||
%I8,%I8,
|
||||
%I9,%I9,
|
||||
%I10,%I10,
|
||||
%I11,%I11,
|
||||
%I12,%I12,
|
||||
%I13,%I13,
|
||||
%I14,%I14,
|
||||
%Q0,%x-axis,
|
||||
%Q1,%z-axis,
|
||||
%Q2,%s-ctrl,
|
||||
%Q3,%t-ctrl,
|
||||
%Q4,%jog-inc+,
|
||||
%Q5,%jog+,
|
||||
%Q6,%jog-inc-,
|
||||
%Q7,%jog-,
|
||||
%Q8,%Q8,
|
||||
%Q9,%Q9,
|
||||
%Q10,%Q10,
|
||||
%Q11,%Q11,
|
||||
%Q12,%Q12,
|
||||
%Q13,%Q13,
|
||||
%Q14,%Q14,
|
||||
%B0,%B0,
|
||||
%B1,%B1,
|
||||
%B2,%B2,
|
||||
%B3,%B3,
|
||||
%B4,%B4,
|
||||
%B5,%B5,
|
||||
%B6,%B6,
|
||||
%B7,%B7,
|
||||
%B8,%B8,
|
||||
%B9,%B9,
|
||||
%B10,%B10,
|
||||
%B11,%B11,
|
||||
%B12,%B12,
|
||||
%B13,%B13,
|
||||
%B14,%B14,
|
||||
%B15,%B15,
|
||||
%B16,%B16,
|
||||
%B17,%B17,
|
||||
%B18,%B18,
|
||||
%B19,%B19,
|
||||
%W0,%W0,
|
||||
%W1,%W1,
|
||||
%W2,%W2,
|
||||
%W3,%W3,
|
||||
%W4,%W4,
|
||||
%W5,%W5,
|
||||
%W6,%W6,
|
||||
%W7,%W7,
|
||||
%W8,%W8,
|
||||
%W9,%W9,
|
||||
%W10,%W10,
|
||||
%W11,%W11,
|
||||
%W12,%W12,
|
||||
%W13,%W13,
|
||||
%W14,%W14,
|
||||
%W15,%W15,
|
||||
%W16,%W16,
|
||||
%W17,%W17,
|
||||
%W18,%W18,
|
||||
%W19,%W19,
|
||||
%IW0,%sel-a,
|
||||
%IW1,%sel-s,
|
||||
%IW2,%IW2,
|
||||
%IW3,%IW3,
|
||||
%IW4,%IW4,
|
||||
%IW5,%IW5,
|
||||
%IW6,%IW6,
|
||||
%IW7,%IW7,
|
||||
%IW8,%IW8,
|
||||
%IW9,%IW9,
|
||||
%QW0,%QW0,
|
||||
%QW1,%QW1,
|
||||
%QW2,%QW2,
|
||||
%QW3,%QW3,
|
||||
%QW4,%QW4,
|
||||
%QW5,%QW5,
|
||||
%QW6,%QW6,
|
||||
%QW7,%QW7,
|
||||
%QW8,%QW8,
|
||||
%QW9,%QW9,
|
||||
%IF0,%IF0,
|
||||
%IF1,%IF1,
|
||||
%IF2,%IF2,
|
||||
%IF3,%IF3,
|
||||
%IF4,%IF4,
|
||||
%IF5,%IF5,
|
||||
%IF6,%IF6,
|
||||
%IF7,%IF7,
|
||||
%IF8,%IF8,
|
||||
%IF9,%IF9,
|
||||
%QF0,%scale,
|
||||
%QF1,%QF1,
|
||||
%QF2,%QF2,
|
||||
%QF3,%QF3,
|
||||
%QF4,%QF4,
|
||||
%QF5,%QF5,
|
||||
%QF6,%QF6,
|
||||
%QF7,%QF7,
|
||||
%QF8,%QF8,
|
||||
%QF9,%QF9,
|
||||
%T0,%T0,Old Timer
|
||||
%T1,%T1,Old Timer
|
||||
%T2,%T2,Old Timer
|
||||
%T3,%T3,Old Timer
|
||||
%T4,%T4,Old Timer
|
||||
%T5,%T5,Old Timer
|
||||
%T6,%T6,Old Timer
|
||||
%T7,%T7,Old Timer
|
||||
%T8,%T8,Old Timer
|
||||
%T9,%T9,Old Timer
|
||||
%TM0,%TM0,New Timer
|
||||
%TM1,%TM1,New Timer
|
||||
%TM2,%TM2,New Timer
|
||||
%TM3,%TM3,New Timer
|
||||
%TM4,%TM4,New Timer
|
||||
%TM5,%TM5,New Timer
|
||||
%TM6,%TM6,New Timer
|
||||
%TM7,%TM7,New Timer
|
||||
%TM8,%TM8,New Timer
|
||||
%TM9,%TM9,New Timer
|
||||
%M0,%M0,One-shot
|
||||
%M1,%M1,One-shot
|
||||
%M2,%M2,One-shot
|
||||
%M3,%M3,One-shot
|
||||
%M4,%M4,One-shot
|
||||
%M5,%M5,One-shot
|
||||
%M6,%M6,One-shot
|
||||
%M7,%M7,One-shot
|
||||
%M8,%M8,One-shot
|
||||
%M9,%M9,One-shot
|
||||
%C0,%C0,Counter
|
||||
%C1,%C1,Counter
|
||||
%C2,%C2,Counter
|
||||
%C3,%C3,Counter
|
||||
%C4,%C4,Counter
|
||||
%C5,%C5,Counter
|
||||
%C6,%C6,Counter
|
||||
%C7,%C7,Counter
|
||||
%C8,%C8,Counter
|
||||
%C9,%C9,Counter
|
||||
%E0,%E0,Error Flag Bit
|
||||
%E1,%E1,Error Flag Bit
|
||||
%E2,%E2,Error Flag Bit
|
||||
%E3,%E3,Error Flag Bit
|
||||
%E4,%E4,Error Flag Bit
|
||||
%E5,%E5,Error Flag Bit
|
||||
%E6,%E6,Error Flag Bit
|
||||
%E7,%E7,Error Flag Bit
|
||||
%E8,%E8,Error Flag Bit
|
||||
%E9,%E9,Error Flag Bit
|
||||
_/FILE-symbols.csv
|
||||
_FILE-general.txt
|
||||
PERIODIC_REFRESH=50
|
||||
SIZE_NBR_RUNGS=100
|
||||
SIZE_NBR_BITS=20
|
||||
SIZE_NBR_WORDS=20
|
||||
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=15
|
||||
SIZE_NBR_ARITHM_EXPR=100
|
||||
SIZE_NBR_SECTIONS=10
|
||||
SIZE_NBR_SYMBOLS=160
|
||||
_/FILE-general.txt
|
||||
_FILE-modbusioconf.csv
|
||||
#VER=1.0
|
||||
_/FILE-modbusioconf.csv
|
||||
_FILE-sequential.csv
|
||||
#VER=1.0
|
||||
_/FILE-sequential.csv
|
||||
_/FILES_CLASSICLADDER
|
||||
4
my-emco-compact-5/tool.tbl
Normal file
4
my-emco-compact-5/tool.tbl
Normal file
@@ -0,0 +1,4 @@
|
||||
T1 P1 X0.0 Y0.0 Z0.0 A0.0 B0.0 C0.0 U0.0 V0.0 W0.0 D0.4 I87.0 J32.0 Q2.0 ;Right hand
|
||||
T2 P2 X0.0 Y0.0 Z0.0 A0.0 B0.0 C0.0 U0.0 V0.0 W0.0 D0.4 I93.0 J148.0 Q1.0 ;Left hand
|
||||
T3 P3 X0.0 Y0.0 Z0.0 A0.0 B0.0 C0.0 U0.0 V0.0 W0.0 D0.4 I117.0 J63.0 Q6.0 ;Neutral
|
||||
T4 P4 X0.0 Y0.0 Z0.0 A0.0 B0.0 C0.0 U0.0 V0.0 W0.0 D0.1 I0.0 J0.0 Q6.0 ;Stick
|
||||
93
my-emco-compact-5/watchdog.py
Normal file
93
my-emco-compact-5/watchdog.py
Normal file
@@ -0,0 +1,93 @@
|
||||
#! /usr/bin/python
|
||||
import time
|
||||
import threading
|
||||
import sys
|
||||
|
||||
class WatchDog():
|
||||
def __init__(self, timeout):
|
||||
self.timeout = timeout
|
||||
self.last_ping_time = time.time()
|
||||
|
||||
def ping(self):
|
||||
self.last_ping_time = time.time()
|
||||
|
||||
def check(self):
|
||||
if time.time() - self.last_ping_time > self.timeout:
|
||||
self.last_ping_time = time.time() #reset tick time
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def insideMargin(self):
|
||||
if time.time() - self.last_ping_time <= self.timeout:
|
||||
return True
|
||||
else:
|
||||
self.last_ping_time = time.time() #reset tick time
|
||||
return False
|
||||
|
||||
|
||||
class WatchDogDaemon(threading.Thread):
|
||||
def __init__(self, timeout, periodicity, enable = True):
|
||||
self.wd = WatchDog(timeout)
|
||||
self.periodicity = periodicity
|
||||
self.enabled = enable
|
||||
self._start()
|
||||
|
||||
def _start(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def ping(self):
|
||||
self.wd.ping()
|
||||
|
||||
def run(self):
|
||||
print("Starting watchdog deamon...")
|
||||
while(self.enabled):
|
||||
time.sleep(self.periodicity)
|
||||
|
||||
if not self.wd.insideMargin():
|
||||
self.reset()
|
||||
|
||||
print("stopping watchdog deamon...")
|
||||
|
||||
def setEnabled(self, enabled):
|
||||
if self.enabled == False and enabled == True:
|
||||
self.enabled = True
|
||||
self.wd.ping() # reset tick time
|
||||
self._start()
|
||||
|
||||
if enabled == False:
|
||||
self.enabled = False
|
||||
|
||||
def reset(self):
|
||||
"""to be overriden by client"""
|
||||
pass
|
||||
|
||||
|
||||
def reset():
|
||||
print('reset')
|
||||
|
||||
def main():
|
||||
i = 0
|
||||
wdd = WatchDogDaemon(2, 0.5, False)
|
||||
wdd.reset = reset
|
||||
try:
|
||||
while 1:
|
||||
time.sleep(1)
|
||||
print('main_' + str(i))
|
||||
print(wdd.is_alive())
|
||||
i = i+1
|
||||
|
||||
if i == 5 or i == 15:
|
||||
wdd.setEnabled(True)
|
||||
if i == 10:
|
||||
wdd.setEnabled(False)
|
||||
|
||||
wdd.ping()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user