User component: Event-based rather than polling?
25 May 2023 05:19 - 25 May 2023 05:39 #272138
by swarren
User component: Event-based rather than polling? was created by swarren
I am writing a custom user component that will detect changes to a HAL pin (which are in turn triggered by a custom M code that sets the pin to 1 or 0), and send messages to a different system to control my dust extractor. I have a couple of questions about how to implement the component:
- All the component examples that I've found run a "forever/while True" loop that reads the pin, processes the value, then sleeps and repeats. This is polling. Is there a way to have an event-based component instead, i.e. block on a pipe/signal/... rather than polling?
- How efficient is the polling; is reading a pin implemented behind-the-scenes in some efficient way such as reading shared memory, or does it involve actively sending messages to HAL and making it do work to process them and respond? I'm wondering how fast/often a pin value can be polled by a component before it has impacts (on other software) beyond plain CPU usage in the component itself.
Thanks!
Last edit: 25 May 2023 05:39 by swarren. Reason: Add link to example I've looked at.
Please Log in or Create an account to join the conversation.
25 May 2023 06:22 #272140
by rodw
Replied by rodw on topic User component: Event-based rather than polling?
If you used M62/M63 You could turn a motion.digital-out.nn pin off in real time. If you need to do anything fancy, you can write a custom components In C and use halcompile to compile and install it..
Please Log in or Create an account to join the conversation.
27 May 2023 05:21 - 27 May 2023 05:38 #272246
by zdenek
Replied by zdenek on topic User component: Event-based rather than polling?
Your intuition and observation is spot on, polling appears to be the only way stuff is done in the existing examples. I think it's time to change that . Event based handling is clearly missing and would be quite useful in more than one place within linuxcnc. So far my first solution is an RT component that watches arbitrary HAL signals and sends events to the user space via a SYSV IPC queue to an arbitrary linux program.
Caveat Emptor: The code below uses a kernel communication mechanism that, to my knowledge, no other linuxcnc component utilizes. It should work fine, and I have been running it on a couple of machines without any problem. Please let me know if you see any issues.
The python code is obviously just to get an idea; all you need is:
import sysv_ipc
q = sysv_ipc.MessageQueue(...)
while True:
data = q.receive() # sleep until you get an event
Caveat Emptor: The code below uses a kernel communication mechanism that, to my knowledge, no other linuxcnc component utilizes. It should work fine, and I have been running it on a couple of machines without any problem. Please let me know if you see any issues.
The python code is obviously just to get an idea; all you need is:
import sysv_ipc
q = sysv_ipc.MessageQueue(...)
while True:
data = q.receive() # sleep until you get an event
Last edit: 27 May 2023 05:38 by zdenek. Reason: learning how to use the forum platform
The following user(s) said Thank You: tommylight, Aciera
Please Log in or Create an account to join the conversation.
28 May 2023 07:11 #272320
by swarren
Replied by swarren on topic User component: Event-based rather than polling?
Thanks, that looks neat. From what I can tell, the RT component is still polling/recalculating all the time? I'm not familiar with RT components yet; is the model for RT that it's a big super-loop that always recalculates every value all the time anyway? At least this avoids the need for the user-space component to poll too, which is great.
In the end, it turns out that my user-space component does need to send status to the dust extractor periodically anyway, so the polling worked out OK (albeit the signal is polled far more often than the periodic updates to avoid delays, an update is sent on change or if no update has been sent in 10s), That said, maybe I could combine the SysV IPC read with a 10s timeout to make sure the periodic messages are sent but without the need for rapid polling to quickly detect changes.
In the end, it turns out that my user-space component does need to send status to the dust extractor periodically anyway, so the polling worked out OK (albeit the signal is polled far more often than the periodic updates to avoid delays, an update is sent on change or if no update has been sent in 10s), That said, maybe I could combine the SysV IPC read with a 10s timeout to make sure the periodic messages are sent but without the need for rapid polling to quickly detect changes.
Please Log in or Create an account to join the conversation.
28 May 2023 07:58 #272322
by rodw
RT Components either from the linuxcnc core or ones you write are called in turn when that thread fires. Say it takes 200 usecs to service all the components and the linuxcnc core, the thread will sleep for 800 usec until it's scheduled to fire again. That's roughly what we observed with a kernel trace. While it sleeps, it's not consuming any resources.
I have never bothered with Python user space components. I just write them in C and run them in real time... I'm not fond of Python...
Replied by rodw on topic User component: Event-based rather than polling?
Think of the servo thread as being triggered by a timer interrupt that happens every 1 millisecond (1000 usec).Thanks, that looks neat. From what I can tell, the RT component is still polling/recalculating all the time? I'm not familiar with RT components yet; is the model for RT that it's a big super-loop that always recalculates every value all the time anyway? At least this avoids the need for the user-space component to poll too, which is great.
RT Components either from the linuxcnc core or ones you write are called in turn when that thread fires. Say it takes 200 usecs to service all the components and the linuxcnc core, the thread will sleep for 800 usec until it's scheduled to fire again. That's roughly what we observed with a kernel trace. While it sleeps, it's not consuming any resources.
I have never bothered with Python user space components. I just write them in C and run them in real time... I'm not fond of Python...
Please Log in or Create an account to join the conversation.
29 May 2023 06:55 #272406
by zdenek
Replied by zdenek on topic User component: Event-based rather than polling?
Yes, the HAL thread is pretty analogous to the concept of a super-loop, only the former does it to implement a discrete DSP-like algorithm with the loop period implementing the dt, whereas the latter is usually deployed due to the lack of proper OS/scheduler.
Your solution is right -- suspend until either a change or a timeout.
Implementing timeouts like that in python threads is not always easy, I often generate dummy events to work around the python limitations.
Your solution is right -- suspend until either a change or a timeout.
Implementing timeouts like that in python threads is not always easy, I often generate dummy events to work around the python limitations.
Please Log in or Create an account to join the conversation.
Time to create page: 0.085 seconds