[etherlab-users] Knowing when the packet has finished cycle

Shahbaz Yousefi shabbyx at gmail.com
Fri Oct 14 15:54:04 CEST 2011


Richard,

Thanks for the prompt reply. I understood what you mean and I understood
where my idea was wrong. There is however a question that still needs to be
answered.

Imagine you have one domain that contains two types of pdo entries. You have
two threads that each work on this same domain although on different
sections of it. (The reason they are two in one domain is that (if I
understood correctly) having more domains means more overhead in the
network, so we are grouping entries that have the same data rate in one
domain)

So, the threads go: calculate; exchange I/O; wait (therefore, get input;
calculate; write output; wait)

Now, imagine this sequence:
1. Thread 1 finishes calculation and writes output
2. Slightly after, Thread 2 finishes calculation and writes output on the
SAME domain
3. After Thread1 wakes up, it receives the input
4. Slightly after, Thread 2 wakes up and wants to receive input from the
SAME domain.

First question is, would this work with EtherLab? (So, does EtherLab itself
understand that at step 2, the exchange data of this domain is in progress
and would automatically ignore this step?)

I am assuming this won't work. Even if it does though, a solution such as
the following makes more sense to me:

function: ethercat manager - write output
  if domain data exchange in progress
    ignore (because data is already being exchanged)
  else
    domain_queue
    master_send

function: ethercat manager - read input
  if last write already read
    ignore (and use the latest available data)
  else if domain data exchange in progress
    ignore (if data exchange in progress, it means the other thread has
issued data exchange recently)
  else
    master_receive
    domain_process

Now each thread goes: ethercat manager - read input; calculate; ethercat
manager - write output; wait

This way the previous scenario would be like this:
1. Thread 1 finishes calculation and writes output
2. Slightly after, Thread 2 finishes calculation and write output is ignored
by the ethercat manager
3. After Thread1 wakes up, it receives the input
4. Slightly after, Thread 2 wakes up and uses the same results

Now, however another problem arises. What if Thread 1's read is ignored
because data is still being exchanged, and then while Thread 1 is performing
"calculate", Thread 2 performs a successful read and changes the data,
ruining Thread 1's work?

The second question is, regardless of the solution of the mentioned problem,
how do you check "domain data exchange is in progress" to implement the
ethercat manager functions in the first place? (That is, when you issue a
write output, how can you be sure when the read input is issued, the data
HAS actually finished exchanging?)

Thank you very much for your attention,
Shahbaz

P.S. The delay of one cycle is not a problem. That had been a
misunderstanding on my side.

P.S.2. I have been considering separating the pdo entries in more domains so
that different threads won't share domains. That however, would be the last
resort. If it is possible to have two threads working with the same domain,
I would be happier with that solution. If it is impossible, tell me and I'll
simply make sure no two threads use data from the same domain.

On Fri, Oct 14, 2011 at 10:01 AM, Richard Hacker <ha at igh-essen.com> wrote:

> Hi,
>
> I am not sure why you want to go through all this trouble. Of coarse, if
> your
> calculation is so long that there is no time to exchange IO, you have
> trouble
> looming anyway!
>
> So what do you want to do with the data if you receive it in the same cycle
> instead of waiting till your next call? For me, there is no point of busily
> waiting till your packet arrives, instead of being relaxed and receiving
> the
> packet next cycle.
>
> The normal run of a control program is:
> calculate; exchange io; wait; calculate; exchange io; wait; etc.
> where exchange io means: write output and get new inputs. Master receive
> and
> domain process simply fetches and processes the data that was transmitted
> with
> master_send at the end of you pseudo code examples.
>
> Now, exchange io is done in the background by the network card. This means,
> that you could call exchange io right at the start of your cycle and
> subsequently calculate. In this case your calculation and exchange io runs
> in
> parallel. This is useful when your calculation is long and you have a lot
> of
> data to exchange, i.e.
> exchange io; calculate; wait; exchange io; calculate wait; etc.
>
> The drawback is that your propagation time from input change to output
> reaction is 2 cycles, instead of only 1. That is the price to pay if you
> have
> lots of data and a long calculation - there is no free lunch!!!
>
> I do not think that you have a problem. Draw your operations on a time line
> and convince yourself that once you are in in the loop, you have max 1
> cycle
> delay from input to output. If that is too long for you, then ethercat is
> not
> your solution. Then you need direct IO like that of microcontrollers and
> the
> like.
>
> - Richard
>
> On Thursday 13 October 2011 17:12:46 Shahbaz Yousefi wrote:
> > Hi,
> >
> > I have been working with etherlab recently and got ethercat working up
> and
> > everything is fine.
> >
> > There is a delay issue however that I'm concerned about. As seen in the
> > examples, the way you read from the network is like this (imagine you are
> > interested in reading sensor values):
> >
> > while (running)
> > {
> >   master receive
> >   domain process
> >
> >   read data
> >
> >   domain queue
> >   master send
> >
> >   rt wait period
> > }
> >
> > in which case you assume that the task period is long enough to be sure
> >  that the packet sent in the bottom of the loop has returned when the
> loop
> >  starts again and so you can receive the data.
> >
> > However, I was wondering if it is possible to, instead of taking an upper
> > bound of the time, simply check to see whether the data has arrived or
> not.
> > After some research, I got to this code:
> >
> > while (running)
> > {
> >   domain queue
> >   master send
> >
> >   do
> >   {
> >     sleep a little
> >
> >     master receive
> >     domain process
> >
> >     ecrt_domain_state(domain, &state);
> >
> >   } while (state.wc_state != EC_WC_COMPLETE && !timeout)
> >
> >   read data
> >
> >   rt wait period
> > }
> >
> > This way, after sending the packet, you would read the data as soon as
> they
> > arrive.
> >
> > The problem with this was that, besides the fact that early calls to
> > master_receive (or domain_process) generated a huge amount of warning
> about
> > working counter changing to 0/1 and back to 1/1 again, the kernel started
> >  to at some point keep crashing.
> >
> > I would like to know, how can I detect when the packet has arrived
> without
> > knowing an upper bound about it and wait blindly by that much?
> >
> > Note: This is most useful for me for this reason:
> >
> > I may have different threads requesting data from a domain which includes
> > different sensors. Each type of sensor produces data at a different rate
> >  and I would like to read the data at different rates to. I don't want to
> >  (and I don't think is even possible) to have different threads
> requesting
> >  data from the same domain (because they may send the packet while the
> one
> >  for the previous thread hasn't yet arrived). So what I want to is this:
> >
> > ethercat coordinator:
> >
> > domain_updating = no
> >
> > send_request_for_domain
> > {
> >   if (domain_updating == no)
> >   {
> >     domain_updating = yes
> >     domain queue
> >     master send
> >   }
> >   // else, do nothing, it is being updated!
> > }
> >
> > receive_from_domain()
> > {
> >   while (ecrt_domain_data_not_yet_received) // this is the function I
> need
> >     wait
> >   domain_updating = no
> >   // data available
> > }
> >
> > and then, each thread that wants something from the domain would look
> like
> > this:
> >
> > thread:
> >   send_request_for_domain
> >   receive_from_domain
> >   read data
> >
> > This way, if two threads call send_request_for_domain at the same time,
> >  only one of them would actually do the
> >
> > domain queue
> > master send
> >
> > and both of them use the result.
> >
> > I would appreciate it if you could shed some light on this matter.
> > Shahbaz
> >
>
> Mit freundlichem Gruß
>
> Richard Hacker
>
> --
> ------------------------------------------------------------------------
>
> Richard Hacker M.Sc.
> richard.hacker at igh-essen.com
> Tel.: +49 201 / 36014-16
>
> Ingenieurgemeinschaft IgH
> Gesellschaft für Ingenieurleistungen mbH
> Heinz-Bäcker-Str. 34
> D-45356 Essen
> Amtsgericht Essen HRB 11500
> USt-Id.-Nr.: DE 174 626 722
> Geschäftsführung:
> - Dr.-Ing. S. Rotthäuser,
> - Dr.-Ing. T. Finke,
> - Dr.-Ing. W. Hagemeister
> Tel.: +49 201 / 360-14-0
> http://www.igh-essen.com
>
> ------------------------------------------------------------------------
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20111014/817776b8/attachment-0004.htm>


More information about the Etherlab-users mailing list