Jump to content

timeout in event structure


Recommended Posts

QUOTE(Eugen Graf @ Apr 17 2007, 05:55 PM)

Who can say why I get the timeout event in the first loop, after clicking on "Generate" button?

Because you should register the event for both event handlers independently...

EDIT: Event registrations are like mail boxes. In your loop you put two loops checking the same mailbox. I guess the timeout occurs because of race condition. Event handler starts to handle event but notices that it's already handled. If you register the event for both loops the timeout doesn't occur. Your upper loop is generating user events for itself in reponse to the same user events. This will not be very wise :)

Tomi

Link to comment

QUOTE(Tomi Maila @ Apr 17 2007, 04:58 PM)

Because you should register the event for both event handlers independently...

EDIT: Event registrations are like mail boxes. In your loop you put two loops checking the same mailbox. I guess the timeout occurs because of race condition. Event handler starts to handle event but notices that it's already handled. If you register the event for both loops the timeout doesn't occur. Your upper loop is generating user events for itself in reponse to the same user events. This will not be very wise :)

Tomi

Thanks, I know its not right to generate event if the same occures, so I will get neverending story in my programm. I want only to understand how user events work.

And I know too, that two event structures in one VI have to be avoided. But my second loop simulates only an another task (other VI, which will be started dynamically).

The aim was to register all events in the main task and handle them in other tasks, I want to commit only the registration refnum to other tasks, but you say its not possible, I have to register events in each task.

Eugen

Link to comment

As far as I understand the story goes as follows. You have event sources and event registration refnums. Event registration refnums are like mailboxes and event sources are like mass mailers. When an event occurs either a system event or user generated event, event source sends a message to each event registration refnum that has registered to that particular event source.

Now if you have two event handlers using the same event registration regnum then they both check for a single message. The one who finds the message first handles it and the other appears to generate a timeout. So you can share user events but you cannot share event ragistrations. You don't share you mailbox with your neighbourgh either ;)

EDIT: You can pass the event registration refnum around. You can use it to register and unregister events around your program. But you should not use it to handle events in more than one place. If you want one wire with multiple events, you can cluster user events and register them as event bundles. Try it up.

Link to comment

QUOTE(Eugen Graf @ Apr 17 2007, 06:36 PM)

I don't quite understand what is the problem. Events are based on queues (I guess). Each event registration refnum acts as a untyped queue. So queues should be faster and I'd use queues if I woudn't need the extra functionality provided by events. Events suit better to asyncrhonous messaging. First you can dynamically register and unregister events, not something you're able to do with queues. Second you can hundle multiple different message types with one event registration refnum and one event structure. With queues you cannot do this, at least not directly. The benefits of queues over event structures are ability to control queue content better. You can flush the queue and check the queue status etc. This functionality is not (by some obscure design decission) not available for events.

Tomi

Link to comment

QUOTE(Eugen Graf @ Apr 17 2007, 07:55 AM)

Your code does not make sense:

  1. In the top event structure, you are generating a user event.
  2. The bottom event structure responds to this and executes the <Command> case.
  3. The top loop is ALSO registered for the same event. It ALSO responds to the same event however it's too late, the message has already been removed from the queue from the bottom event structure. It then just iterates a timeout.

What is the purpose of your design? Multiple recipients? If so, then you need to use a different approach. See attached image:

QUOTE(Tomi Maila @ Apr 17 2007, 07:58 AM)

:)

Agreed.

QUOTE(Eugen Graf @ Apr 17 2007, 08:23 AM)

And I know too, that two event structures in one VI have to be avoided.

This is not true. You can have multiple event structures without problems as long as they are not using the same event registration refnum.

QUOTE(Eugen Graf @ Apr 17 2007, 08:23 AM)

Another option is to create the user events in the main task VI and pass this to the other tasks, however register the events at the task level.

QUOTE(Eugen Graf @ Apr 17 2007, 08:36 AM)

P.S. firstly I wanted to replace Queues in tasks with User Events, because I have this problem:

How do you think, what is better to use Queues or User Events? What is faster and eats less memory?

You are presenting multiple issues here. Are you trying to get speed and less memory, or are you trying to solve your problem? The reason I'm asking is because you don't need to switch to a completely different architecture to solve your problem. Queues are pretty powerful on their own and still viable for your situation. From what I can see, your problem is that you are mixing your communication mechanisms. Why use "Set Value Property" on top of queues? You already have the pipeline so utilize it. See:

Link to comment

Thank you very much for detailed answer.

QUOTE(Michael_Aivaliotis @ Apr 18 2007, 09:15 AM)

I know that my code doesnt make sany sense, my code is only to probe, what User Events can.

QUOTE(Michael_Aivaliotis @ Apr 18 2007, 09:15 AM)

I want both - to solve my problem & to decide if the mechanism with user events can replace the machanism with queues.

Your solution with cluster queue is interesting, but have a disadvantage. My question is: what happens if I only want to change the interface (if user changes program settings) without to send any message to visa?

Therefore I want to separate message from settings with user events. If settings changes by user I will send settings user event, if a message must be send to visa, I will use the message user event.

Eugen

Link to comment

Thanks Michael,

I will show your VI more detailed and answer later.

To your questions: there may be up to 8 devices (my biggest project) with different interfaces. The most are serial, but some of them TCP/IP and CAN, no GPIB.

Here an example of my older project (for two devices), you will see that I can't place all VIs on one display screen. And if there are much more devices, then the BD would be bigger. I can in fact hide more SubVIs into one, but I don't think my program will be well arranged.

Please no critic, I know the BD on the snippet have more programical errors, but think on I was a LV-beginner at those time.

Eugen

Link to comment

QUOTE(Michael_Aivaliotis @ Apr 18 2007, 06:40 PM)

Are your devices, serial? I think only serial devices really need to be closed to release the port for others to use. GPIB devices don't have to be opened or closed. At least not anymore. Other than Visa Open or Visa Close, I'm not sure what kind of instrument command you want to send.

Regardless. If this is still the case, you can do this with queues as well. Keep in mind that you will need different queues for different types of tasks. The example shown assumes that you are working with the instrument task queue. Also, I haven't used any subvi's to keep the example simple but I would suggest encapsulating the enqueue functionality into subvi's.

http://forums.lavag.org/index.php?act=attach&type=post&id=5546 (LabVIEW 8.0)

There are many solutions to your problem. User events can be used as well. However, I would even argue that you don't need parallel tasks anyway. Why can't you just do everything in the main state machine? I'm not sure of the benefit in your case. Perhaps data saving would be better off in parallel if you have lot's of data. What is the speed of the overall system?

Like I mentioned, there are others who will suggest solutions different to mine. I have also used user events and various GOOP frameworks, however this is all I have for now.

Hello Michael, your solution is realy good, I can understand it and thank you for.

Can you say me how to make it for reading task? Not so easy, I think.

It can be anything, but not locals, globals or references. And no timeouts in event sructure.

Thank you.

Eugen

Link to comment
  • 4 weeks later...

QUOTE(Michael_Aivaliotis @ Apr 18 2007, 06:40 PM)

Are your devices, serial? I think only serial devices really need to be closed to release the port for others to use. GPIB devices don't have to be opened or closed. At least not anymore. Other than Visa Open or Visa Close, I'm not sure what kind of instrument command you want to send.

Regardless. If this is still the case, you can do this with queues as well. Keep in mind that you will need different queues for different types of tasks. The example shown assumes that you are working with the instrument task queue. Also, I haven't used any subvi's to keep the example simple but I would suggest encapsulating the enqueue functionality into subvi's.

http://forums.lavag.org/index.php?act=attach&type=post&id=5546 (LabVIEW 8.0)

There are many solutions to your problem. User events can be used as well. However, I would even argue that you don't need parallel tasks anyway. Why can't you just do everything in the main state machine? I'm not sure of the benefit in your case. Perhaps data saving would be better off in parallel if you have lot's of data. What is the speed of the overall system?

Like I mentioned, there are others who will suggest solutions different to mine. I have also used user events and various GOOP frameworks, however this is all I have for now.

Dear Michael (or anybody else),

could you say me how I can implement your mechanism for read-tasks? Sorry, I can't guess it right. Your solution is really good, but fits IMHO only for write-tasks. The difference is: a write-task waits on commands from main, but a read-task shoud wait for data from interface AND for commands from main. How can I implement it.

Thank you. Eugen

Link to comment

QUOTE(tcplomp @ May 19 2007, 10:53 AM)

Hi Eugen,

you can do event driven data acquisition. Register for the DAQmx event 'number of samples' acquired!

Ton

Sorry, I don't understand you. How is my application related to DAQmx(I have never used it)?

I want to make a template for my projects.

My read-task should be universal, undependent from interface. And as I know DAQmx is created for analogue data aquisition and it doesn't support interfaces like serial, CAN or TCP/IP with NI-unknown protocolls.

Eugen

Link to comment

QUOTE(Eugen Graf @ May 18 2007, 03:42 PM)

Hi Eugen I am eavesdropping on your thread.

It looks OK to me except the data read must be stored somewhere no?

(In the diagram the data goes nowhere but I suspect you know this already and just make an example for discussion?)

John

QUOTE(Eugen Graf @ May 19 2007, 09:53 PM)

My read-task should be universal, undependent from interface. And as I know DAQmx is created for analogue data aquisition and it doesn't support interfaces like serial, CAN or TCP/IP with NI-unknown protocolls.

Eugen

Hi Eugen

I am intermediate LV programmer who is reading your threads with interest.

Making a universal read task function

I (think) that to get a universal read function would require some form inheritance OO (GOOP) where the parent would be an abstract class (HWdev) and the

children would do the actual implementation, (HWDev.Serial) (HWDev.GPIB) (HWdev.DAQ) etc..

But the child implementations would still have to be written and tested etc. Assuming all of this was done it should be (in principal) easy to

implement the read-task by pumping in the desired child object into the abstract parent function (lets call it "HWdev_readTask")

You probably already know this. Perhaps this is too off topic to your immediate concern.

On the events thing

I like the "possible" solution Michael uploaded. Thanks Michael for putting that (very nice) example up. :worship:

I do not know if this is tightly related to your issue but I work with serial devices too and wanted to add to discussion.

The thing about reading from an RS232 device is I do not know a way to have the device tell me (my LV APP ) that new data is available as an event.

Thus all I know how to do is poll the receive buffer for characters and extract them when they are available. But it is still polling and thus every so many milliseconds I have to use that resource to check.

I've never been able to figure out by myself how to have the serial device generate an event to LV when fresh data is available.

so I always have to poll the device serially to detect any change in the data. If the serial device is configured to send data contiuously into your receive buffer you still have to check the buffer to see if new data is available.

In your final example you are invoking the read from your UI no? I remember you asking before about getting events also from serial device as well as UI and how to do this. I also wish I knew. To anyone with a clue I offer my :worship: again..

Link to comment

QUOTE(Eugen Graf @ May 18 2007, 08:42 AM)

It's okey if my read-task triggers itself?

Eugen

Again, many ways to skin a cat. Your approach will work fine but there is no way to control the timing of the reads. They will happen asap which may or may not be desirable. I suggest you add a shift register with a timer value to control this better. Since the reads happen independantly from external commands, you need to put something that will trigger them. Some code in the timeout case of the bottom loop that sends a read command with a timer should do it.

Another issue I see is you don't have an associated Write before the Read. What Write command will tell the instrument to return data? Unless the instrument is always returning data then I guess it's fine. In that case my timer solution in the previous paragraph is not valid. You need to do a check bytes at port in order to see if a Read is necessary.

Link to comment

QUOTE(Eugen Graf @ May 19 2007, 11:53 PM)

Sorry,

I didn't really read the thread thoroughly.

QUOTE(Michael_Aivaliotis @ May 20 2007, 03:06 AM)

Some code in the timeout case of the bottom loop that sends a read command with a timer should do it.

I would add a high-speed (10 ms) seperate loop, and use the OpenG trigger VI to trigger the read action.

In this way you can add easily multiple speed triggers

Ton

Link to comment

Actually I use mixed form to communicate between tasks. I have some Queue, Notifier and User Event Tasks. All of them have advantages and disadvantages. Here the snipped of my Open Refnums VI.

http://forums.lavag.org/index.php?act=attach&type=post&id=5918

For communication I use Flatten/Unflatten binary String VI, it's seems to be better than Variant, because I can parse the remainig string after parsing the command.

http://forums.lavag.org/index.php?act=attach&type=post&id=5919

Generally is my construction like queued state machine in each task. Every state in every task can be set by own task AND by other tasks if it's allowed by program. Here snippets of my reading task.

http://forums.lavag.org/index.php?act=attach&type=post&id=5920

http://forums.lavag.org/index.php?act=attach&type=post&id=5921

And this one shows the state if I get new settings in my reading task if I get any from the main task. As you can see, I switch my reding task to the state "read data" after I got new settings.

http://forums.lavag.org/index.php?act=attach&type=post&id=5922

Any comments?

Thank to all replyers.

Eugen

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.