adding files

This commit is contained in:
2026-03-21 23:48:08 +01:00
parent eba2b73dec
commit 18f86cfd1e
105 changed files with 13770 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
Märkning I/O Beskrivning
----------------------------------------------------------------------------
P1
P2 X step
P3 X dir
P4 Y step
P5 Y dir
P6 Z step
P7 Z dir
R1 P8 (i/o-kort) Relä spindel CW
R2 P9 -"- Relä oljepump, spindel
M2 P14 -"- MOS-FET tryckluftsventil dimsmörjning
P16 -"- PWM spindel
M1 P17 -"- MOS-FET tryckluftsventil, spindel
P1 P10 -"- Z proximity sensor, home position
P2 P11 -"- Y proximity sensor, home and max position
P3 P12 -"- X proximity sensor, home and max position
P13
P15
brun/PHASE1(A) encoder phaseA+
grå/PHASE2(B) encoder phaseB+
röd/PHASE3(Z) encoder phaseZ+, index pulse
blå 5V supply encoder
2st vit GND encoder
#P4 X rotations sensor, per ledstångsvarvvarv
#P5 Y rotations sensor, per ledstångsvarvvarv
#P6 Z rotations sensor, per ledstångsvarvvarv
#COL1 P12 (i/o-kort) collector transistor1, downsampled phaseA
#COL2 P13 (i/o-kort) collector transistor2, downsampled phaseB
#COL3 P15 (i/o-kort) collector transistor3, pulse stretched phaseZ index
#BASE1 D3 (arduino) base transistor1, downsampled phaseA
#BASE2 D5 (arduino) base transistor2, downsampled phaseB
#BASE3 D7 (arduino) base transistor3, downsampled phaseZ index

BIN
my-emco/Misc/pid-tuning.ods Normal file

Binary file not shown.

137
my-emco/comms.py Normal file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env python
# 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('_' + 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

View File

@@ -0,0 +1,4 @@
#!/bin/bash
# file to turn on parport pin 17 to open the spindle air valve
halcmd setp parport.0.pin-17-out True
exit 0

View File

@@ -0,0 +1,4 @@
#!/bin/bash
# file to turn off parport pin 17 to open the spindle air valve
halcmd setp parport.0.pin-17-out False
exit 0

View File

@@ -0,0 +1,4 @@
#!/bin/bash
# axis reload after
axis-remote --reload
exit 0

View File

@@ -0,0 +1,19 @@
o<mychange> sub
o10 if [#<_current_tool> NE #<_selected_tool>]
;(DEBUG, current tool: #<_current_tool>, selected_tool: #<_selected_tool>)
#<saved_z> = [#<_z>] ; save position
#4999 = #<_selected_tool> ; store selected tool to use M61 at start-up
G53 G0 Z87 ; rapid to tool change location
M6
;G53 G0 Z50
;M101 ; engage spindle air blower
;G53 G0 Z35
;M102 ; disengage spindle air blower
;(DEBUG, saved-z: #<saved_z>)
G43
G0 Z[#<saved_z>] ; restore position
o10 else
(DEBUG, tool #<_selected_tool> already in spindle)
o10 endif
o<mychange> endsub
M2

View File

@@ -0,0 +1,9 @@
o<myspindlestart> sub
o10 if [#<_spindle_on> EQ 1]
M5
o10 else
S800
M3
o10 endif
o<myspindlestart> endsub
M2

View File

@@ -0,0 +1,30 @@
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 z axis)
o20 if [#<selected-axis> EQ 0]
G10 L20 P0 Z0
M103
(MSG, touch off z axis)
o20 endif
(touch off y axis)
o30 if [#<selected-axis> EQ 1]
G10 L20 P0 Y0
M103
(MSG, touch off y axis)
o30 endif
(touch off x axis)
o40 if [#<selected-axis> EQ 2]
G10 L20 P0 X0
M103
(MSG, touch off x axis)
o40 endif
o10 else
(DEBUG, didn't exist)
o10 endif
o<mytouch> endsub
M2

140
my-emco/custom.hal Normal file
View File

@@ -0,0 +1,140 @@
# Include your customized HAL commands here
# This file will not be overwritten when you run stepconf again
loadrt scale count=2 # 0 used to convert spindle rps-to-rpm, 1 used to scale jog-scale output from classicladder
loadrt near names=spindle-at-speed
loadrt pid names=spindle-speed-ctrl
loadrt limit2 names=spindle-ramp
loadrt not count=1 # used for ramping spindle speed
loadrt and2 count=3 # and2.0 used for MPG run-button, and2.1 for e-stop-chain, and2.2 for setting tool after homeing
loadrt classicladder_rt
loadrt conv_float_u32 # user in postgui for converting analog signal to integer
loadusr -Wn my-mpg python serialEventHandler.py --port=/dev/ttyUSB0 -c my-mpg mpg.xml
loadusr -Wn my-encoder python fake_encoder.py --port=/dev/ttyS0 -c my-encoder
loadusr classicladder test_ladder.clp --nogui
addf scale.0 servo-thread
addf scale.1 servo-thread
addf spindle-at-speed servo-thread
addf spindle-speed-ctrl.do-pid-calcs servo-thread
addf spindle-ramp servo-thread
addf not.0 servo-thread
addf and2.0 servo-thread
addf and2.1 servo-thread
addf and2.2 servo-thread
addf classicladder.0.refresh servo-thread
addf conv-float-u32.0 servo-thread
### spindel speed ramping
setp spindle-ramp.maxv 500
net spindle-cmd-rpm => spindle-ramp.in
net spindle-ramped <= spindle-ramp.out => pwmgen.0.value
net spindle-on not.0.in
net spindle-off not.0.out
net spindle-off spindle-ramp.load
net spindle-ramped => spindle-at-speed.in2
### spindle at speed monitoring ###
setp spindle-at-speed.scale 0.98
setp spindle-at-speed.difference 10
setp scale.0.gain 60 # rps to rpm
setp scale.0.offset 0
net spindle-velocity-rpm <= scale.0.out
net spindle-cmd-rpm => spindle-at-speed.in1
#net spindle-velocity-rpm => spindle-at-speed.in2
net spindle-ramped => spindle-at-speed.in2
net spindle-ready <= spindle-at-speed.out => spindle.0.at-speed
### encoder ###
net spindle-position my-encoder.position => spindle.0.revs
net spindle-velocity-rps my-encoder.velocity
net spindle-velocity-rps => spindle.0.speed-in
net spindle-velocity-rps => scale.0.in
net spindle-index-enable my-encoder.index-enable <=> spindle.0.index-enable
net watchdog-enable my-encoder.watchdog-enable # connected to checkbox in postgui
### PID ctrl ###
net spindle-cmd-rpm => spindle-speed-ctrl.command
setp spindle-speed-ctrl.Pgain 2.5
setp spindle-speed-ctrl.Igain 3
setp spindle-speed-ctrl.Dgain 2.3
setp spindle-speed-ctrl.FF0 0
setp spindle-speed-ctrl.FF1 1.5
setp spindle-speed-ctrl.maxoutput 4500
setp spindle-speed-ctrl.deadband 25
#setp spindle-speed-ctrl.maxerror 1000
setp spindle-speed-ctrl.enable 0
net spindle-velocity-rpm => spindle-speed-ctrl.feedback
#net spindle-speed-ctrl-out spindle-speed-ctrl.output => pwmgen.0.value
net spindle-on => spindle-speed-ctrl.enable #from spindle.0.on
net spindle-index-enable => spindle-speed-ctrl.index-enable
### mist coolant ctrl ###
net mist-cmd iocontrol.0.coolant-mist => parport.0.pin-14-out
### e-stop chain ###
net estop-internal <= iocontrol.0.user-enable-out
net estop-external <= parport.0.pin-13-in-not
net estop-internal => and2.1.in0
net estop-external => and2.1.in1
net estop-chain and2.1.out => iocontrol.0.emc-enable-in
## restoring tool after homing #################################################
# note, logic assumes z-axis homed first, when x and y axis' are
# homed, all axis are done
net x-homed halui.joint.0.is-homed and2.2.in0
net y-homed halui.joint.1.is-homed and2.2.in1
net xy-homed and2.2.out
net xy-homed halui.mdi-command-02
net xy-homed halui.mdi-command-03
### pendant ##########################################
# jog wheel connects to x, y, z axis
net mpg-jog-counts joint.0.jog-counts axis.x.jog-counts <= my-mpg.jog-counts
net mpg-jog-counts joint.1.jog-counts axis.y.jog-counts
net mpg-jog-counts joint.2.jog-counts axis.z.jog-counts
# axis selector connects to x, y, z axis enable
net jog-axis-sel classicladder.0.s32in-00
net jog-x-enable classicladder.0.out-00
net jog-y-enable classicladder.0.out-01
net jog-z-enable classicladder.0.out-02
net jog-axis-sel my-mpg.axis-selector
net jog-x-enable axis.x.jog-enable
net jog-y-enable axis.y.jog-enable
net jog-z-enable axis.z.jog-enable
# jog scale selector connects to x, y, z axis jog scale and jog velocity mode
setp scale.1.gain 0.01
setp scale.1.offset 0
net jog-scale-100 classicladder.0.floatout-00 scale.1.in
net jog-scale-sel classicladder.0.s32in-01
net jog-scale scale.1.out
net jog-scale-sel my-mpg.scale-selector
net jog-scale joint.0.jog-scale axis.x.jog-scale
net jog-scale joint.1.jog-scale axis.y.jog-scale
net jog-scale joint.2.jog-scale axis.z.jog-scale
net vel-mode-sel classicladder.0.out-03
net vel-mode-sel joint.0.jog-vel-mode axis.x.jog-vel-mode
net vel-mode-sel joint.1.jog-vel-mode axis.y.jog-vel-mode
net vel-mode-sel joint.2.jog-vel-mode axis.z.jog-vel-mode
### connect the buttons
# connect Func-button
net func-button my-mpg.func-btn #connected to gladevcp-component in postgui
# connect Run button
net run-button halui.mode.auto and2.0.in0 <= my-mpg.prog-run-btn
net program-run-ok and2.0.in1 <= halui.mode.is-auto
net remote-program-run halui.program.run <= and2.0.out
# connect E-Stop button
net estop-button halui.estop.activate <= my-mpg.estop-btn

View File

@@ -0,0 +1,38 @@
# Include your customized HAL commands here
# The commands in this file are run after the AXIS GUI (including PyVCP panel) starts
### virtual panel ##############################################################
## connect the frame-enable-signals
net xy-homed gladevcp.commands
net xy-homed gladevcp.tool
net xy-homed gladevcp.mpg
setp gladevcp.lube 1
## connect spindle frame
net spindle-cmd-rpm => gladevcp.spindle-ref-rpm
net spindle-velocity-rpm => gladevcp.spindle-curr-rpm
net spindle-velocity-rpm => gladevcp.spindle-rpm-hbar
#net spindle-duty pwmgen.0.curr-dc => pyvcp.spindle-pwm-duty
net spindle-ready => gladevcp.led-spindle-at-speed
net watchdog-enable gladevcp.wd-chkbtn
## connect command frame
net tc-pos halui.mdi-command-01 <= gladevcp.tc-button
net panel-rth-button halui.mdi-command-00 <= gladevcp.rth-button
## connect the current tool bumber
net current-tool-number iocontrol.0.tool-number => gladevcp.current-tool
#set the gladevcp-tool-combo to show current tool at start
net set-start-tool motion.analog-out-00 conv-float-u32.0.in
net start-tool-pin conv-float-u32.0.out gladevcp.saved-tool-pin
## connect the mpg frame
net func-button gladevcp.trigger_pin
## connect the luber frame
net luber-acc-dist gladevcp.acc-distance
net luber-cmd gladevcp.lube-cmd
net luber-ext-req gladevcp.lube-cmd-btn
net luber-reset gladevcp.lube-reset-btn

158
my-emco/emco-buttons.xml Normal file
View File

@@ -0,0 +1,158 @@
<pyvcp>
<labelframe text="EMCO VCM100">
<font>("Helvetica",16)</font>
<!-- buttons -->
<vbox>
<relief>RIDGE</relief>
<bd>3</bd>
<button>
<halpin>"rth-button"</halpin>
<text>"Rapid to Home"</text>
</button>
<button>
<halpin>"tc-button"</halpin>
<text>"Tool Change Pos"</text>
</button>
<button>
<halpin>"lube-on"</halpin>
<text>"Lube"</text>
</button>
</vbox>
<vbox>
<relief>RIDGE</relief>
<bd>3</bd>
<hbox>
<label>
<text>"Tool 1 "</text>
</label>
<button>
<halpin>"change-tool1"</halpin>
<text>"Change"</text>
</button>
</hbox>
<hbox>
<label>
<text>"Tool 2 "</text>
</label>
<button>
<halpin>"change-tool2"</halpin>
<text>"Change"</text>
</button>
</hbox>
<hbox>
<label>
<text>"Tool 3 "</text>
</label>
<button>
<halpin>"change-tool3"</halpin>
<text>"Change"</text>
</button>
</hbox>
<hbox>
<label>
<text>"Tool 4 "</text>
</label>
<button>
<halpin>"change-tool4"</halpin>
<text>"Change"</text>
</button>
</hbox>
<hbox>
<label>
<text>"Tool 5 "</text>
</label>
<button>
<halpin>"change-tool5"</halpin>
<text>"Change"</text>
</button>
</hbox>
<hbox>
<label>
<text>"Tool 6 "</text>
</label>
<button>
<halpin>"change-tool6"</halpin>
<text>"Change"</text>
</button>
</hbox>
</vbox>
<vbox>
<relief>RIDGE</relief>
<bd>3</bd>
<hbox>
<relief>RIDGE</relief>
<bd>2</bd>
<label>
<text>"Spindle cmd RPM"</text>
</label>
<number>
<halpin>"spindle-ref-rpm"</halpin>
<format>"+4.2f"</format>
</number>
</hbox>
<hbox>
<relief>RIDGE</relief>
<bd>2</bd>
<label>
<text>"Spindle actual RPM"</text>
</label>
<number>
<halpin>"spindle-curr-rpm"</halpin>
<format>"+4.2f"</format>
</number>
</hbox>
<hbox>
<relief>RIDGE</relief>
<bd>2</bd>
<label>
<text>"Spindle PWM Duty"</text>
</label>
<number>
<halpin>"spindle-pwm-duty"</halpin>
<format>"+4.2f"</format>
</number>
</hbox>
<hbox>
<relief>RIDGE</relief>
<bd>2</bd>
<label>
<text>"spindle at speed"</text>
</label>
<led>
<halpin>"led-spindle-at-speed"</halpin>
<on_color>"green"</on_color>
<off_color>"red"</off_color>
</led>
</hbox>
<hbox>
<relief>RIDGE</relief>
<bd>2</bd>
<label>
<text>"Current Tool"</text>
</label>
<s32>
<halpin>"current-tool"</halpin>
<format>"2d"</format>
</s32>
</hbox>
</vbox>
<vbox>
<label>
<text>"Spindle Feedback"</text>
</label>
<checkbutton>
<halpin>"wd-chkbtn"</halpin>
<text>"Watchdog Enable "</text>
<initval>1</initval>
</checkbutton>
</vbox>
</labelframe>
</pyvcp>

126
my-emco/fake_encoder.py Normal file
View File

@@ -0,0 +1,126 @@
#! /usr/bin/python
import sys
import comms
import hal
import getopt
import time
class FakeEncoder:
def __init__(self, dT, scale):
self._position = 0 # scaled value from count
self._velocity = 0 # units per sec, i.e. rps
self._dT = dT # delta time between samples [s]
self._scale = scale # nbr of pulses / rev
def clear(self):
self._position = 0
print 'FakeEncoder::clearing position data'
def handleEvent(self, event):
if (event.name == 'pos'):
self._velocity = float(event.data)/(self._scale*self._dT) #pos per dT to rps
self._position += float(event.data)/self._scale
def getVelocity(self):
return self._velocity
def getPosition(self):
return self._position
class HalAdapter:
def __init__(self, name, clear_cb):
self.h = hal.component(name)
self.clearCallback = clear_cb
self.h.newpin("velocity", hal.HAL_FLOAT, hal.HAL_OUT)
self.h.newpin("position", hal.HAL_FLOAT, hal.HAL_OUT)
self.h.newpin("index-enable", hal.HAL_BIT, hal.HAL_IO)
self.h.newpin("watchdog-enable", hal.HAL_BIT, hal.HAL_IN)
self.h.ready()
def update(self, vel, pos):
self.h['velocity'] = vel
self.h['position'] = pos
if self.h['index-enable'] == 1:
self.clearCallback()
self.h['position'] = 0
self.h['index-enable'] = 0
def isWatchdogEnabled(self):
return self.h['watchdog-enable']
class OptParser:
def __init__(self, argv):
self.name = 'my-encoder' # default name of component in HAL
self.port = '/dev/ttyUSB1' # default serial port to use
self._getOptions(argv)
def __repr__(self):
return 'name: ' + self.name + '\tport: ' + self.port
def _getOptions(self, argv):
if argv != []:
try:
opts, args = getopt.getopt(argv, "hp:c:", ["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 in ("-p", "--port"):
self.port = a
else:
print o, a
assert False, "unhandled option"
def getName(self):
return self.name
def getPort(self):
return self.port
def _usage(self):
""" print command line options """
print "usage serial_mpg.py -h -c <name> -p/--port= <serial port>\n"\
"-c <name> # name of component in HAL. 'mpg' default\n"\
"-p/--port= <serial port> # default serial port to use. '/dev/ttyS2' default\n"\
"-h # print this test"
def main():
optParser = OptParser(sys.argv[1:])
componentName = optParser.getName()
portName = optParser.getPort()
print optParser
fakeEncoder = FakeEncoder(0.05, 500)
speedCounter = comms.instrument(portName, fakeEncoder.handleEvent, False) #serial adaptor, watchdog disabled
halAdapter = HalAdapter(componentName, fakeEncoder.clear)
try:
while 1:
speedCounter.enableWatchdog(halAdapter.isWatchdogEnabled())
speedCounter.readMessages()
halAdapter.update(fakeEncoder.getVelocity(), fakeEncoder.getPosition())
time.sleep(0.05)
except KeyboardInterrupt:
raise SystemExit
if __name__ == '__main__':
main()

6
my-emco/func-btn.xml Normal file
View File

@@ -0,0 +1,6 @@
<mpg>
<function>Touch off selected axis<gcode>O&lt;mytouch&gt;call</gcode></function>
<function>Spindle Start/Stop<gcode>O&lt;myspindlestart&gt;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>

138
my-emco/gladevcp-handler.py Normal file
View File

@@ -0,0 +1,138 @@
#!/usr/bin/ python
import gtk
import gobject
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)]

120
my-emco/linuxcnc.var Normal file
View File

@@ -0,0 +1,120 @@
4999 7.000000
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 23.092490
5222 -2.040103
5223 -105.797929
5224 0.000000
5225 0.000000
5226 0.000000
5227 0.000000
5228 0.000000
5229 0.000000
5230 0.000000
5241 -6.758898
5242 32.897192
5243 -21.519200
5244 0.000000
5245 0.000000
5246 0.000000
5247 0.000000
5248 0.000000
5249 0.000000
5250 0.000000
5261 25.241102
5262 32.897192
5263 -21.519200
5264 0.000000
5265 0.000000
5266 0.000000
5267 0.000000
5268 0.000000
5269 0.000000
5270 0.000000
5281 57.241102
5282 32.897192
5283 -21.519200
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

16
my-emco/luber.hal Normal file
View File

@@ -0,0 +1,16 @@
loadusr -Wn my-luber python luber.py -c my-luber luber.xml
net x-vel joint.0.vel-cmd => my-luber.x-vel
net y-vel joint.1.vel-cmd => my-luber.y-vel
net z-vel joint.2.vel-cmd => my-luber.z-vel
setp my-luber.lube-level-ok 1
net iocontrol.0.lube-level <= my-luber.lube-level-alarm
net luber-reset my-luber.reset
net luber-cmd my-luber.lube-cmd => parport.0.pin-09-out
## create the gui signals
net luber-acc-dist my-luber.accumulated-distance
net luber-ext-req my-luber.lube-ext-req
net luber-reset my-luber.reset

234
my-emco/luber.py Normal file
View File

@@ -0,0 +1,234 @@
#! /usr/bin/python
import sys
import getopt
import xml.etree.ElementTree as ET
import hal
import time
from collections import namedtuple
class Pin:
""" Representation of a Pin and it's data"""
def __init__(self, type, dir):
self.val = 0 # current value of pin, e.g. 1 - on, 0 - off
self.type = type # type (string read from xml)
self.dir = dir
def __repr__(self):
return 'val: ' + str(self.val) + '\ttype: ' + self.type + '\tdir: ' + self.dir
class HalAdapter:
def __init__(self, name):
self.h = hal.component(name)
self.h.newpin("velocity", hal.HAL_FLOAT, hal.HAL_OUT)
self.h.newpin('x-vel', hal.HAL_FLOAT, hal.HAL_IN)
self.h.newpin('y-vel', hal.HAL_FLOAT, hal.HAL_IN)
self.h.newpin('z-vel', hal.HAL_FLOAT, hal.HAL_IN)
self.h.newpin('lube-level-ok',hal.HAL_BIT, hal.HAL_IN)
self.h.newpin('reset', hal.HAL_BIT, hal.HAL_IN)
self.h.newpin('lube-ext-req', hal.HAL_BIT, hal.HAL_IN)
self.h.newpin('lube-cmd', hal.HAL_BIT, hal.HAL_OUT)
self.h.newpin('lube-level-alarm', hal.HAL_BIT, hal.HAL_OUT)
self.h.newpin('accumulated-distance', hal.HAL_FLOAT, hal.HAL_OUT)
self.h.ready()
def __repr__(self):
tmp_str = ''
return tmp_str
def is_lube_level_ok(self):
return self.h['lube-level-ok']
def is_reset(self):
return self.h['reset']
def is_lube_ext_req(self):
return self.h['lube-ext-req']
def get_velocities(self):
velocities = namedtuple("velocities", ["x", "y", "z"])
return velocities(
self.h['x-vel'],
self.h['y-vel'],
self.h['z-vel'])
def set_lube_on(self, request):
if request >= 1:
self.h['lube-cmd'] = 1
else:
self.h['lube-cmd'] = 0
def set_lube_level_alarm(self, level_ok):
if level_ok >= 1:
self.h['lube-level-alarm'] = 1
else:
self.h['lube-level-alarm'] = 0
def set_accumulated_distance(self, d):
self.h['accumulated-distance'] = d
class parameterContainer:
def __init__(self, xml_file):
self.paramDict = {}
self._xmlFile = xml_file
self.tree = ET.parse(self._xmlFile)
self._parse()
def _parse(self):
root = self.tree.getroot()
for param in root.iter('parameter'):
#print param.attrib['name'], param.attrib['value']
self.paramDict[param.attrib['name']] = float(param.attrib['value'])
def getParam(self, name):
if name in self.paramDict:
return self.paramDict[name]
else:
return None
def getParams(self):
return self.paramDict
def writeToFile(self):
for parName in self.paramDict:
self._writeToTree(parName, self.paramDict[parName])
self.tree.write(self._xmlFile)
def writeParam(self, parName, value):
if parName in self.paramDict:
self.paramDict[parName] = value
def _writeToTree(self, parName, value):
"""update parameter in xml-tree"""
root = self.tree.getroot()
for param in root.iter('parameter'):
if param.attrib['name'] == parName:
param.attrib['value'] = str(round(value, 2))
break
class LubeControl:
def __init__(self, lube_on_time, accumulated_distance, distance_threshold, number_of_lubings):
self.lubeOnTime = lube_on_time # [sec]
self.total_distance = accumulated_distance # [mm]
self.distance_threshold = distance_threshold # [mm]
self.numberOfLubings = number_of_lubings
self.state = 'OFF'
self.lubeLevelOkOut = True
self._lubeLevelOkIn = True
self.prev_time = time.time()
def calc_dist_from_vel(self, v_x, v_y, v_z):
current_time = time.time()
time_delta = current_time - self.prev_time
self.total_distance += abs(v_x) * time_delta
self.total_distance += abs(v_y) * time_delta
self.total_distance += abs(v_z) * time_delta
self.prev_time = current_time
def runStateMachine(self, ext_req):
currentTime = time.time()
if self.total_distance >= self.distance_threshold or ext_req == True:
self.state = 'ON'
self.timeout = self.lubeOnTime + currentTime
self.total_distance = 0
self.numberOfLubings += 1
if self.state == 'ON':
if currentTime > self.timeout:
#check lube pressure sensor
self.lubeLevelOkOut = self._lubeLevelOkIn
self.state = 'OFF'
def setLubeLevelOK(self, levelOk):
self._lubeLevelOkIn = levelOk
def reset(self):
self.total_distance = 0
self.state = 'OFF'
self.lubeLevelOkOut = True
def _usage():
""" print command line options """
print "usage luber.py -h -c<name> <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. 'my-luber' default\n"\
"-h # Help test"
def main():
xmlFile = 'luber.xml'
#xmlFile = ''
name = 'my-luber' # default name of component in HAL
try:
opts, args = getopt.getopt(sys.argv[1:], "hc:", ["input="])
except getopt.GetoptError as err:
# print help information and exit:
print(err) # will print something like "option -a not recognized"
sys.exit(2)
for o, a in opts:
if o == "-h":
_usage()
sys.exit()
elif o == "-c":
name = a
elif o == "--input":
xmlFile = a
else:
print o
assert False, "unhandled option"
if xmlFile == '':
if len(sys.argv) < 2:
_usage()
sys.exit(2)
else:
xmlFile = sys.argv[-1]
p = parameterContainer(xmlFile)
h = HalAdapter(name)
totalDistance = p.getParam('totalDistance')
distanceThreshold = p.getParam('distanceThreshold')
lubeOnTime = p.getParam('lubePulseTime')
nbrOfLubings = p.getParam('numberOfLubings')
lubeCtrl = LubeControl(lubeOnTime, totalDistance, distanceThreshold, nbrOfLubings)
try:
while 1:
if h.is_reset():
lubeCtrl.reset()
lubeCtrl.setLubeLevelOK(h.is_lube_level_ok())
v = h.get_velocities()
lubing_external_request = h.is_lube_ext_req()
lubeCtrl.calc_dist_from_vel(v.x, v.y, v.z)
lubeCtrl.runStateMachine(lubing_external_request)
h.set_lube_on(lubeCtrl.state == 'ON')
h.set_lube_level_alarm(lubeCtrl.lubeLevelOkOut)
h.set_accumulated_distance(lubeCtrl.total_distance)
time.sleep(0.1)
except KeyboardInterrupt:
p.writeParam('totalDistance', lubeCtrl.total_distance)
p.writeParam('numberOfLubings', lubeCtrl.numberOfLubings)
p.writeToFile()
raise SystemExit
if __name__ == '__main__':
main()

6
my-emco/luber.xml Normal file
View File

@@ -0,0 +1,6 @@
<luber>
<parameter name="lubePulseTime" value="5.0" />
<parameter name="totalDistance" value="8621.49" />
<parameter name="distanceThreshold" value="10000.0" />
<parameter name="numberOfLubings" value="113.0" />
</luber>

8
my-emco/mpg.xml Normal file
View File

@@ -0,0 +1,8 @@
<mpg>
<halpin>"jog-counts"<event>jog</event><type>s32</type></halpin>
<halpin>"axis-selector"<event>sela</event><type>s32</type></halpin>
<halpin>"scale-selector"<event>sels</event><type>s32</type></halpin>
<halpin>"func-btn"<event>func</event><type>bit</type></halpin>
<halpin>"prog-run-btn"<event>run</event><type>bit</type></halpin>
<halpin>"estop-btn"<event>est</event><type>bit</type></halpin>
</mpg>

110
my-emco/my-emco.hal Normal file
View File

@@ -0,0 +1,110 @@
# Generated by stepconf 1.1 at Mon Nov 4 14:01:20 2019
# If you make changes to this file, they will be
# overwritten when you run stepconf again
loadrt [KINS]KINEMATICS
#autoconverted trivkins
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
loadrt hal_parport cfg="0 out"
setp parport.0.reset-time 5000
loadrt stepgen step_type=0,0,0
loadrt pwmgen output_type=0
addf parport.0.read base-thread
addf stepgen.make-pulses base-thread
addf pwmgen.make-pulses base-thread
addf parport.0.write base-thread
addf parport.0.reset base-thread
addf stepgen.capture-position servo-thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf stepgen.update-freq servo-thread
addf pwmgen.update servo-thread
net spindle-cmd-rpm <= spindle.0.speed-out
#net spindle-cmd-rpm pwmgen.0.value <= spindle.0.speed-out
net spindle-on <= spindle.0.on => pwmgen.0.enable
net spindle-pwm <= pwmgen.0.pwm
setp pwmgen.0.pwm-freq 100.0
setp pwmgen.0.scale 4500 #duty_cycle = (value/scale) + offset, with 1.0 meaning 100%
#setp pwmgen.0.offset 0.02
setp pwmgen.0.dither-pwm true
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 spindle-cw <= spindle.0.forward
net spindle-pwm => parport.0.pin-16-out
net xstep => parport.0.pin-02-out
setp parport.0.pin-02-out-reset 1
setp parport.0.pin-03-out-invert 1
net xdir => parport.0.pin-03-out
net ystep => parport.0.pin-04-out
setp parport.0.pin-04-out-reset 1
net ydir => parport.0.pin-05-out
net zstep => parport.0.pin-06-out
setp parport.0.pin-06-out-reset 1
setp parport.0.pin-07-out-invert 1
net zdir => parport.0.pin-07-out
net spindle-cw => parport.0.pin-08-out
net home-z <= parport.0.pin-10-in-not
net home-y <= parport.0.pin-11-in-not
net home-x <= parport.0.pin-12-in-not
#net max-home-y <= parport.0.pin-11-in-not
#net max-home-x <= parport.0.pin-12-in-not
setp stepgen.0.position-scale [JOINT_0]SCALE
setp stepgen.0.steplen 1
setp stepgen.0.stepspace 0
setp stepgen.0.dirhold 35000
setp stepgen.0.dirsetup 35000
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 xstep <= stepgen.0.step
net xdir <= stepgen.0.dir
net xenable joint.0.amp-enable-out => stepgen.0.enable
#net max-home-x => joint.0.home-sw-in
#net max-home-x => joint.0.pos-lim-sw-in
net home-x => joint.0.home-sw-in
setp stepgen.1.position-scale [JOINT_1]SCALE
setp stepgen.1.steplen 1
setp stepgen.1.stepspace 0
setp stepgen.1.dirhold 35000
setp stepgen.1.dirsetup 35000
setp stepgen.1.maxaccel [JOINT_1]STEPGEN_MAXACCEL
net ypos-cmd joint.1.motor-pos-cmd => stepgen.1.position-cmd
net ypos-fb stepgen.1.position-fb => joint.1.motor-pos-fb
net ystep <= stepgen.1.step
net ydir <= stepgen.1.dir
net yenable joint.1.amp-enable-out => stepgen.1.enable
#net max-home-y => joint.1.home-sw-in
#net max-home-y => joint.1.pos-lim-sw-in
net home-y => joint.1.home-sw-in
setp stepgen.2.position-scale [JOINT_2]SCALE
setp stepgen.2.steplen 1
setp stepgen.2.stepspace 0
setp stepgen.2.dirhold 35000
setp stepgen.2.dirsetup 35000
setp stepgen.2.maxaccel [JOINT_2]STEPGEN_MAXACCEL
net zpos-cmd joint.2.motor-pos-cmd => stepgen.2.position-cmd
net zpos-fb stepgen.2.position-fb => joint.2.motor-pos-fb
net zstep <= stepgen.2.step
net zdir <= stepgen.2.dir
net zenable joint.2.amp-enable-out => stepgen.2.enable
net home-z => joint.2.home-sw-in
# moved to custom.hal
#net estop-out <= iocontrol.0.user-enable-out
#net estop-out => 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/my-emco.ini Normal file
View File

@@ -0,0 +1,169 @@
# This config file was created 2021-03-08 20:17:44.282043 by the update_ini script
# The original config files may be found in the /home/johan/linuxcnc/configs/my-emco/my-emco.old directory
# Generated by stepconf 1.1 at Mon Nov 4 14:01:20 2019
# If you make changes to this file, they will be
# overwritten when you run stepconf again
[EMC]
# The version string for this INI file.
VERSION = 1.1
MACHINE = my-emco
DEBUG = 0
[DISPLAY]
DISPLAY = axis
EDITOR = gedit
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
ARCDIVISION = 64
GRIDS = 10mm 20mm 50mm 100mm
MAX_FEED_OVERRIDE = 1.2
MIN_SPINDLE_OVERRIDE = 0.5
MAX_SPINDLE_OVERRIDE = 1.2
DEFAULT_LINEAR_VELOCITY = 25.0
MIN_LINEAR_VELOCITY = 0
MAX_LINEAR_VELOCITY = 25.00
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
PROGRAM_PREFIX = /home/johan/linuxcnc/nc_files
INCREMENTS = 5mm 1mm .5mm .1mm .05mm .01mm .005mm
GLADEVCP= -u ./gladevcp-handler.py ./my-emco.ui
[FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Greyscale Depth Image
PROGRAM_EXTENSION = .py Python Script
png = image-to-gcode
gif = image-to-gcode
jpg = image-to-gcode
py = python
[RS274NGC]
PARAMETER_FILE=linuxcnc.var
SUBROUTINE_PATH=custom-m-codes
USER_M_PATH=custom-m-codes
REMAP=M6 modalgroup=6 ngc=mychange
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
BASE_PERIOD = 35000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[HAL]
HALUI = halui
HALFILE = my-emco.hal
HALFILE = custom.hal
HALFILE = luber.hal
POSTGUI_HALFILE = custom_postgui.hal
[HALUI]
# add halui MDI commands here (max 64)
MDI_COMMAND = G53 G0 X0 Y0 Z0 ;cmd 0 "return to home" used by MPG
MDI_COMMAND = G53 G0 Z88 ;cmd 1 "tool change position"
MDI_COMMAND = M61 Q#4999 G43 ;cmd 2 called after homing to set tool saved at last tool change
MDI_COMMAND = M68 E0 Q#4999 ;cmd 3 called after homing to output current tool on analog signal
[TRAJ]
COORDINATES = XYZ
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 25.0
MAX_LINEAR_VELOCITY = 25.00
DEFAULT_LINEAR_ACCELERATION = 150.0
MAX_LINEAR_ACCELERATION = 250.0
JOINTS = 3
HOME = 0 0 0
[EMCIO]
EMCIO = io
CYCLE_TIME = 0.100
TOOL_TABLE = tool.tbl
[KINS]
KINEMATICS = trivkins coordinates=XYZ
#This is a best-guess at the number of joints, it should be checked
JOINTS = 3
[AXIS_X]
MIN_LIMIT = -85.0
MAX_LIMIT = 92.0
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 250.0
# vi testar att sänka MAX_ACCELERATION = 750.0
[JOINT_0]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 250.0
STEPGEN_MAXACCEL = 300
#MAX_ACCELERATION = 750.0
#STEPGEN_MAXACCEL = 937.5
SCALE = 1000.0
FERROR = 1
MIN_FERROR = .25
MIN_LIMIT = -85.0
MAX_LIMIT = 92.0
HOME_OFFSET = 93.000000
HOME_SEARCH_VEL = 5.500000
HOME_LATCH_VEL = 0.500000
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 1
[AXIS_Y]
#tog bort givarna som ändlägesstopp, används bara vid homing
#kunde lägga till lite på pos-y...
#MIN_LIMIT = -45.0
#MAX_LIMIT = 45.0
MIN_LIMIT = -43.0
MAX_LIMIT = 61.0
MAX_VELOCITY = 23.75
#MAX_ACCELERATION = 750.0
MAX_ACCELERATION = 250.0
[JOINT_1]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 250.0
STEPGEN_MAXACCEL = 300
#MAX_ACCELERATION = 750.0
#STEPGEN_MAXACCEL = 937.5
SCALE = 1000.0
FERROR = 1
MIN_FERROR = 0.25
MIN_LIMIT = -43.0
MAX_LIMIT = 61.0
HOME_OFFSET = 46.000000
HOME_SEARCH_VEL = 5.500000
HOME_LATCH_VEL = 0.500000
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 1
[AXIS_Z]
MIN_LIMIT = -112.0
MAX_LIMIT = 88.0
MAX_VELOCITY = 5.0
MAX_ACCELERATION = 25.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 5.0
MAX_ACCELERATION = 25.0
STEPGEN_MAXACCEL = 31.25
SCALE = 1000.0
FERROR = 1
MIN_FERROR = .25
MIN_LIMIT = -112.0
MAX_LIMIT = 88.0
HOME_OFFSET = 0.0
HOME_SEARCH_VEL = 2.500000
HOME_LATCH_VEL = 0.500000
HOME_SEQUENCE = 0

508
my-emco/my-emco.ui Normal file
View File

@@ -0,0 +1,508 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gladevcp 0.0 -->
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<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>
<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="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<property name="homogeneous">True</property>
<child>
<object class="HAL_HBar" id="spindle-rpm-hbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="bg_color">#bebebebebebe</property>
<property name="max">6000</property>
<property name="target_width">1</property>
<property name="value">0.019999999552965164</property>
<property name="z0_border">0.69999998807907104</property>
<property name="z0_color">#0000ffff0000</property>
<property name="z1_border">0.89999997615814209</property>
<property name="z1_color">#ffffffff0000</property>
<property name="z2_color">#ffff00000000</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">3</property>
<property name="n_columns">2</property>
<child>
<object class="GtkLabel" id="spindle-cm">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Spindle cmd:</property>
</object>
</child>
<child>
<object class="HAL_Label" id="spindle-ref-rpm">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="label_pin_type">1</property>
<property name="text_template">%.1f rpm</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="spindle-actua">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Spindle actual:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="HAL_Label" id="spindle-curr-rpm">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="label_pin_type">1</property>
<property name="text_template">%.1f rpm</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="spindle-at-speed">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Spindle at Speed:</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="HAL_LED" id="led-spindle-at-speed">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="led_blink_rate">0</property>
<property name="pick_color_off">#ffff00000000</property>
<property name="pick_color_on">#0000ffff0000</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="HAL_CheckButton" id="wd-chkbtn">
<property name="label" translatable="yes">Spindle Feedback Watchdog Enable</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label1text">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Spindle&lt;/b&gt;</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>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
<object class="HAL_Table" id="tool">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<object class="GtkLabel" id="current-tool-lable">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Current Tool:</property>
</object>
</child>
<child>
<object class="HAL_Label" id="current-tool">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="set-tool">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Set Tool:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="HAL_ComboBox" id="tool-combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">0</property>
<property name="button_sensitivity">on</property>
<property name="column">0</property>
<signal name="changed" handler="on_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label2text">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Tool&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
<object class="HAL_HBox" id="commands">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">20</property>
<property name="homogeneous">True</property>
<child>
<object class="HAL_Button" id="rth-button">
<property name="label" translatable="yes">Goto Machine Zero</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="HAL_Button" id="tc-button">
<property name="label" translatable="yes">Goto Tool Change Position</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4text">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Commands&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<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="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
<object class="HAL_Table" id="mpg">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_columns">2</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>
</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="right_attach">2</property>
</packing>
</child>
</object>
</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">&lt;b&gt;MPG&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
<object class="HAL_Table" id="lube">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">3</property>
<property name="n_columns">2</property>
<property name="column_spacing">20</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="accumulated-distance">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Accumulated Distance:</property>
</object>
</child>
<child>
<object class="GtkLabel" id="lube-cmd-lable">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Lube Pump:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="HAL_Button" id="lube-reset-btn">
<property name="label" translatable="yes">Reset Saved Data</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="HAL_Label" id="acc-distance">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="label_pin_type">1</property>
<property name="text_template">%.2f mm</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="HAL_LED" id="lube-cmd">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="led_blink_rate">0</property>
<property name="pick_color_off">#ffff00000000</property>
<property name="pick_color_on">#0000ffff0000</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="HAL_Button" id="lube-cmd-btn">
<property name="label" translatable="yes">Lube</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label1text1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Lube&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,4 @@
# Include your customized HAL commands here
# The commands in this file are run after the AXIS GUI (including PyVCP panel) starts
sets spindle-at-speed true

View File

@@ -0,0 +1,281 @@
#! /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
class Pin:
""" Representation of a Pin and it's data"""
def __init__(self, name, type):
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)
def __repr__(self):
return 'pin name: ' + self.name + '\tval: ' + str(self.val) + '\ttype: ' + self.type
class ComponentWrapper:
def __init__(self, name):
self.pin_dict = {} # dictionary used to map event to pin
self.hal = hal.component(name) # instanciate the HAL-component
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, name):
if name in self.pin_dict:
return self.pin_dict[name].val
def __setitem__(self, name, val):
self.set_pin(name, val)
def add_pin(self, name, hal_name, type):
self.pin_dict[name] = Pin(hal_name, type)
self._add_hal_pin(hal_name, type)
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:
try:
self.pin_dict[event.name].val = self._type_saturate(self.pin_dict[event.name].type, int(event.data))
except ValueError:
print 'bad event'
def set_pin(self, name, value):
""" updates pin value with new data
input: pin name, set value'
output: nothing. """
if name in self.pin_dict:
try:
self.pin_dict[name].val = self._type_saturate(self.pin_dict[name].type, int(value))
except ValueError:
print 'bad event'
def setReady(self):
self.hal.ready()
def update_hal(self):
for key in self.pin_dict:
self.hal[self.pin_dict[key].name] = self.pin_dict[key].val
def _add_hal_pin(self, hal_name, type):
self.hal.newpin(hal_name, self._get_hal_type(type), hal.HAL_OUT) # create the user space HAL-pin
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 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"
class XmlParser:
def __init__(self, f):
self.tree = []
self.pin_dict = {}
self._parse_file(f)
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 get_parsed_data(self):
return self.pin_dict
def _parse_file(self, f):
self.tree = ET.parse(f)
root = self.tree.getroot()
for halpin in root.iter('halpin'):
type = halpin.find('type')
event = halpin.find('event')
# create the LinuxCNC hal pin and create mapping dictionary binding incomming events with data and the hal pins
if type is not None and event is not None:
if self._check_supported_HAL_type(type.text) == True:
self.pin_dict[event.text] = Pin(halpin.text.strip('"'), type.text)
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
class BrokeeContainer:
def __init__(self, handler, args):
self.handler = handler
self.args = args
class EventBroker:
def __init__(self):
self.brokee_dict = {}
self.received_event = comms.Message('')
def attach_handler(self, event_name, handler, args = ()):
self.brokee_dict[event_name] = BrokeeContainer(handler, args)
def handle_event(self, event):
self.received_event.copy(event)
if event.name in self.brokee_dict:
self.brokee_dict[event.name].handler(*self.brokee_dict[event.name].args)
################################################
def main():
optParser = OptParser(sys.argv[1:])
componentName = optParser.get_name()
portName = optParser.get_port()
xmlFile = optParser.get_XML_file()
print optParser
xmlParser = XmlParser(xmlFile)
c = ComponentWrapper(componentName) #HAL adaptor
eventBroker = EventBroker() #maps incomming events to the correct handler
serialEventGenerator = comms.instrument(portName, eventBroker.handle_event, True, 5, 1) #serial adaptor
# add/create the HAL-pins from parsed xml and attach them to the adaptor event handler
parsedXmlDict = xmlParser.get_parsed_data()
for key in parsedXmlDict:
c.add_pin(key, parsedXmlDict[key].name, parsedXmlDict[key].type)
eventBroker.attach_handler(key, c.event_set_pin, args = (eventBroker.received_event,))
# TODO eventBroker.attach_handler(key, c.set_pin, args = (eventBroker.received_event.name, eventBroker.received_event.data))
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()

301
my-emco/test_ladder.clp Normal file
View File

@@ -0,0 +1,301 @@
_FILES_CLASSICLADDER
_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/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/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
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 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-sections.csv
#VER=1.0
#NAME000=Prog1
000,0,-1,1,2,0
_/FILE-sections.csv
_FILE-counters.csv
0
0
0
0
0
0
0
0
0
0
_/FILE-counters.csv
_FILE-arithmetic_expressions.csv
#VER=2.0
0000,@310/0@=100
0002,@270/0@=2
0003,@270/0@=1
0004,@270/0@=0
0005,@270/1@=1
0006,@270/1@=2
0007,@270/1@=3
0008,@310/0@=100
0009,@310/0@=10
0010,@270/1@=0
0011,@310/0@=1
_/FILE-arithmetic_expressions.csv
_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-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-ioconf.csv
#VER=1.0
_/FILE-ioconf.csv
_FILE-modbusioconf.csv
#VER=1.0
_/FILE-modbusioconf.csv
_FILE-sequential.csv
#VER=1.0
_/FILE-sequential.csv
_FILE-symbols.csv
#VER=1.0
%I0,%func-btn,no signal connected
%I1,%f-disabl,
%I2,%f-enable,
%I3,%f-move1,
%I4,%f-move2,
%I5,%I5,
%I6,%I6,
%I7,%I7,
%I8,%I8,
%I9,%I9,
%I10,%I10,
%I11,%I11,
%I12,%I12,
%I13,%I13,
%I14,%I14,
%Q0,%x-axis,
%Q1,%y-axis,
%Q2,%z-axis,
%Q3,%vel-mode,
%Q4,%Q4,
%Q5,%Q5,
%Q6,%Q6,
%Q7,%Q7,
%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=1
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-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-rung_2.csv
#VER=2.0
#LABEL=
#COMMENT=
#PREVRUNG=1
#NEXTRUNG=-1
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
99-0-0/0 , 99-0-0/0 , 20-0-0/6 , 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/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/11
0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/0 , 0-0-0/10
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 , 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 , 99-1-0/0 , 99-0-0/0 , 60-0-0/0
_/FILE-rung_2.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
_/FILES_CLASSICLADDER

9
my-emco/tool.tbl Normal file
View File

@@ -0,0 +1,9 @@
T1 P1 Z-8.28607 D12 ;12mm end mill, 4 flutes
T2 P2 Z-13.3224 D6 ;6mm end mill alu, 3 flutes
T3 P3 Z-18.0309 D2.5 ;2.5mm dubhole drill
T4 P4 Z-4.83769 D1 ;1mm end mill
T5 P5 Z-11.5912 D2 ;2mm end mill, 3 flutes
T6 P6 Z0 D10 ;10mm end mill alu, 3 flutes
T8 P8 Z0 D3 ;engraver
T10 P10 Z0 D10 ;10 mm 4 flutes 20230820
T7 P7 Z0 D4 ;4mm alu

94
my-emco/watchdog.py Normal file
View File

@@ -0,0 +1,94 @@
#! /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():
print "Watchdog outside margin"
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()