Run HAL operation once per input

More
10 years 2 months ago #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
Code:
#!/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
Code:
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 to join the conversation.

More
10 years 2 months ago #79445 by Todd Zuercher
Maybe you need to debounce your button?
linuxcnc.org/docs/html/man/man9/debounce.9.html

Please Log in to join the conversation.

More
10 years 2 months ago #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
Code:
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 to join the conversation.

More
10 years 2 months ago #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 to join the conversation.

More
10 years 2 months ago #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

Please Log in to join the conversation.

More
10 years 2 months ago #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:
Code:
if record_pin = true and old_record_pin = false then record_one_sample endif old_record_pin <= record_pin

Please Log in to join the conversation.

More
10 years 2 months ago #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
Code:
#!/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
Code:
loadusr -W train net save-position input.0.btn-tr train.record

Please Log in to join the conversation.

More
6 years 2 months ago #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 to join the conversation.

Time to create page: 0.103 seconds
Powered by Kunena Forum