Run HAL operation once per input

More
25 Aug 2016 18:37 #79439 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
#!/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.

More
25 Aug 2016 19:41 - 25 Aug 2016 19:41 #79445 by Todd Zuercher
Maybe you need to debounce your button?
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.

More
25 Aug 2016 21:20 #79447 by Cpk_Rbt
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
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.

More
25 Aug 2016 21:34 #79449 by PCW
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

Please Log in or Create an account to join the conversation.

More
26 Aug 2016 12:31 - 26 Aug 2016 12:37 #79473 by Cpk_Rbt
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
Last edit: 26 Aug 2016 12:37 by Cpk_Rbt.

Please Log in or Create an account to join the conversation.

More
26 Aug 2016 14:29 - 26 Aug 2016 14:31 #79497 by PCW
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:
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.

More
26 Aug 2016 15:18 #79502 by Cpk_Rbt
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
#!/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.

More
25 Aug 2020 13:37 #179387 by serdigi
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 ...

Please Log in or Create an account to join the conversation.

Time to create page: 0.075 seconds
Powered by Kunena Forum