Run HAL operation once per input
25 Aug 2016 18:37 #79439
by Cpk_Rbt
Run HAL operation once per input was created by Cpk_Rbt
I have a controller set up to jog my machine, and a button set up that saves the current position to a file.
It works great, it just triggers multiple times each time the trigger pin goes high. I added a oneshot function and it reduced the repetition, but hasn't eliminated it.
I get ~45 lines written each time I push the button (all duplicates of the same position)
If anyone has a suggestion, I'd love to hear it!
train.py
postgui.hal
It works great, it just triggers multiple times each time the trigger pin goes high. I added a oneshot function and it reduced the repetition, but hasn't eliminated it.
I get ~45 lines written each time I push the button (all duplicates of the same position)
If anyone has a suggestion, I'd love to hear it!
train.py
#!/usr/bin/python
"""Usage:
python train.py
You must ". scripts/emc-environment" before running this script, if you use
run-in-place.
"""
# 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 hal
import sys
import linuxcnc
s = linuxcnc.stat()
def get_cart():
s.poll()
position = "G01 X%-8.4f Y%-8.4f Z%-8.4f A%-8.4f B%-8.4f C%-8.4f\n" % ( s.position[0], s.position[1], s.position[2], s.position[3], s.position[4], s.position[5] )
return position
h = hal.component("train")
h.newpin ("record", hal.HAL_BIT, hal.HAL_IN)
outfile = "train.ngc"
h.ready()
try:
while 1:
if h["record"] == 1:
f = open(outfile, 'a')
pos = get_cart()
f.write(pos)
f.close()
except KeyboardInterrupt:
raise SystemExit
postgui.hal
loadusr -W train
loadrt oneshot
addf oneshot.0 servo-thread
setp oneshot.0.width 0.0001
net save-ons input.0.btn-tr oneshot.0.in
net save-position oneshot.0.out train.record
Please Log in or Create an account to join the conversation.
- Todd Zuercher
- Offline
- Platinum Member
Less
More
- Posts: 5007
- Thank you received: 1441
25 Aug 2016 19:41 - 25 Aug 2016 19:41 #79445
by Todd Zuercher
Replied by Todd Zuercher on topic Run HAL operation once per input
Maybe you need to debounce your button?
linuxcnc.org/docs/html/man/man9/debounce.9.html
linuxcnc.org/docs/html/man/man9/debounce.9.html
Last edit: 25 Aug 2016 19:41 by Todd Zuercher.
Please Log in or Create an account to join the conversation.
25 Aug 2016 21:20 #79447
by Cpk_Rbt
Replied by Cpk_Rbt on topic Run HAL operation once per input
Todd,
Thanks for the suggestion!
I haven't used the debounce function before, but I think I understand how it works. If I set the debounce delay to 200, it will only send an output value after seeing the input value for 200 cycles, instead of instantly when the button is pressed. 200 cycles on a 1000000ns thread is 0.2 seconds, so it will only send an output every 0.2 seconds that the button is being pressed.
I tried the following code with multiple values for the delay
debounce 200 > 10k lines in file
debounce 100 > 8k lines
debounce 50 > 6k lines
Am I misunderstanding debounce?
Thanks for the suggestion!
I haven't used the debounce function before, but I think I understand how it works. If I set the debounce delay to 200, it will only send an output value after seeing the input value for 200 cycles, instead of instantly when the button is pressed. 200 cycles on a 1000000ns thread is 0.2 seconds, so it will only send an output every 0.2 seconds that the button is being pressed.
I tried the following code with multiple values for the delay
debounce 200 > 10k lines in file
debounce 100 > 8k lines
debounce 50 > 6k lines
loadrt debounce cfg=1
addf debounce.0 servo-thread
setp debounce.0.delay 200
## DEBOUNCE
net save-deb input.0.btn-tr debounce.0.0.in
net save-position debounce.0.0.out train.record
Am I misunderstanding debounce?
Please Log in or Create an account to join the conversation.
25 Aug 2016 21:34 #79449
by PCW
Replied by PCW on topic Run HAL operation once per input
if "train.record" records when true (rather than once per edge) you probably want
to use a debounced button followed by a 1 servo cycle (1 ms) oneshot, that is
pushbutton --> debounce --> 1 ms oneshot
to use a debounced button followed by a 1 servo cycle (1 ms) oneshot, that is
pushbutton --> debounce --> 1 ms oneshot
Please Log in or Create an account to join the conversation.
26 Aug 2016 12:31 - 26 Aug 2016 12:37 #79473
by Cpk_Rbt
Replied by Cpk_Rbt on topic Run HAL operation once per input
It does record when true rather than once per edge, is there a way I could change it so it only records once per edge? That would be preferable to "record when true". I'm rather new to custom HAL components (though not to programming). I'm not sure how to go about using HAL functions in a component of my own.
The best result I've gotten so far is using a oneshot (with or without debounce)
The fewest output lines is still ~40.
The period of the servo-thread is 1 000 000. I added a second thread with a period of 100 000 and started seeing 2 lines of output (down from 40). Dropped it to 50 000 and now I only get one line. This certainly isn't the most elegant solution, and as far as the robustness of the train function goes, I think it would still be beneficial to rewrite it to run once per true rather than run while true
The best result I've gotten so far is using a oneshot (with or without debounce)
The fewest output lines is still ~40.
The period of the servo-thread is 1 000 000. I added a second thread with a period of 100 000 and started seeing 2 lines of output (down from 40). Dropped it to 50 000 and now I only get one line. This certainly isn't the most elegant solution, and as far as the robustness of the train function goes, I think it would still be beneficial to rewrite it to run once per true rather than run while true
Last edit: 26 Aug 2016 12:37 by Cpk_Rbt.
Please Log in or Create an account to join the conversation.
26 Aug 2016 14:29 - 26 Aug 2016 14:31 #79497
by PCW
Replied by PCW on topic Run HAL operation once per input
If you want a edge triggered input to your HAL component you simply record the previous
input state and use the current and previous input states to detect the edge,
here's some pseudo-code for a rising edge (false to true) trigger:
input state and use the current and previous input states to detect the edge,
here's some pseudo-code for a rising edge (false to true) trigger:
if record_pin = true and old_record_pin = false then
record_one_sample
endif
old_record_pin <= record_pin
Last edit: 26 Aug 2016 14:31 by PCW.
The following user(s) said Thank You: Cpk_Rbt
Please Log in or Create an account to join the conversation.
26 Aug 2016 15:18 #79502
by Cpk_Rbt
Replied by Cpk_Rbt on topic Run HAL operation once per input
That logic worked like a charm!
It works perfectly, and now I don't need to use the debounce/oneshot functions. It's really slick.
Thanks for your help!
Here's my new train.py
postgui.hal
It works perfectly, and now I don't need to use the debounce/oneshot functions. It's really slick.
Thanks for your help!
Here's my new train.py
#!/usr/bin/python
"""Usage:
python train.py
You must ". scripts/emc-environment" before running this script, if you use
run-in-place.
"""
# 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 hal
import sys
import linuxcnc
s = linuxcnc.stat()
def get_cart():
s.poll()
position = "G01 X%-8.4f Y%-8.4f Z%-8.4f A%-8.4f B%-8.4f C%-8.4f\n" % ( s.position[0], s.position[1], s.position[2], s.position[3], s.position[4], s.position[5] )
return position
h = hal.component("train")
h.newpin ("record", hal.HAL_BIT, hal.HAL_IN)
outfile = "train.ngc"
record_pin = 0
old_record_pin = 0
h.ready()
try:
while 1:
old_record_pin = record_pin
record_pin = h["record"]
if record_pin == 1 and old_record_pin == 0:
f = open(outfile, 'a')
pos = get_cart()
f.write(pos)
f.close()
except KeyboardInterrupt:
raise SystemExit
postgui.hal
loadusr -W train
net save-position input.0.btn-tr train.record
The following user(s) said Thank You: serdigi
Please Log in or Create an account to join the conversation.
25 Aug 2020 13:37 #179387
by serdigi
Replied by serdigi on topic Run HAL operation once per input
Hello to everyone
Hello Cpk_Rbt.
Thanks for the valuable tip. I am using linuxcnc 2.7.15. When I want to run this build;
Traceback (most recent call last):
File "train.py", line 36, in <module>
pos = get_cart ()
File "train.py", line 17, in get_cart
s.poll ()
linuxcnc.error: emcStatusBuffer invalid err = 3
gives his error.
Please help me ...
Best Regards ...
Hello Cpk_Rbt.
Thanks for the valuable tip. I am using linuxcnc 2.7.15. When I want to run this build;
Traceback (most recent call last):
File "train.py", line 36, in <module>
pos = get_cart ()
File "train.py", line 17, in get_cart
s.poll ()
linuxcnc.error: emcStatusBuffer invalid err = 3
gives his error.
Please help me ...
Best Regards ...
Please Log in or Create an account to join the conversation.
Time to create page: 0.075 seconds