<p dir="ltr">Hi Raz,</p>
<p dir="ltr">thanks for the information and the benchmark you made.<br>
Yes, I know, the shorter interval we have, the better the algorithm for the time offset in the current etherlab master works. But why should the accuracy for the offset suffer when we have a larger interval? And I believe we can improve the algorithm to have a much better accuracy regardless of the interval :)</p>

<div class="gmail_quote">Am 02.01.2014 16:48 schrieb "Raz" <<a href="mailto:raziebe@gmail.com">raziebe@gmail.com</a>>:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div><div><div>Hey Jun<br><br></div>If you look deep into the Documentation you notice that they say that dc sync is influenced by the number of packets sent. Here are my benchmarks<br>for a 6 slaves system when powering it up.<br>



<br>
1. 1ms sent_interval for Op_thread with 4ms transmit interval  . 33 seconds <br></div><div>2. 500us sent_interval for op_therad with 500us transmit interval. 6 seconds<br></div><div>4. 100us sent_interval for op_thread with 100us transmit interval. 2.5 seconds.<br>



<br></div><div>I believe the reason is the accuracy which is better in shorter intervals.<br><br><br></div><div><br>
</div></div><div> </div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jan 1, 2014 at 11:19 PM, Jun Yuan <span dir="ltr"><<a href="mailto:j.yuan@rtleaders.com" target="_blank">j.yuan@rtleaders.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Raz,<br>
<br>
there have been many people raised the same kind of questions like you<br>
did. Some of them asked in the mailing list, some of them wrote to me<br>
directly, worrying about those warnings like slave didn't sync after 5<br>
seconds. For the past two years, I kept answering, that I didn't know<br>
about the DC sync mechanism very much, that by examining the register<br>
0x092c, it can be confirmed the DCs get perfectly synchronized in the<br>
end anyway, that my customers could get used to obey my rules that<br>
they must wait several minutes doing nothing until the DCs on the<br>
EtherCAT bus get synchronized/converged, that maybe it is the slaves’<br>
fault to have such a slow convergence for their DC.<br>
<br>
Frankly speaking, I hate my answers, they are like excuses. So I<br>
decided to fight them back, and took some time digging into this<br>
problem for the last two days.<br>
<br>
The first thing to do would be learning how the DC sync mechanism<br>
works. I don't have any official EtherCAT documents, and would be<br>
appreciate if anyone could send me some of the specifications from<br>
EtherCAT. On the internet I did find a paper "On the Accuracy of the<br>
Distributed Clock Mechanism in EtherCAT" and a PPT "Accurate<br>
Synchronization of EtherCAT Systems Using Distributed Clocks" by<br>
Joseph E Stubbs. Those two files helped me a lot.<br>
<br>
The other obstacle is, I don't have any EtherCAT slave devices at<br>
hand. Occasionally I receive a project to develop an interface for a<br>
new sort of slaves using EtherLab Master. Those slaves usually stay<br>
with me for about two to three weeks, and after that, they will be<br>
shipped with my software to our customers. The chance to have a slave<br>
in my office is 1/12, not to mention the deadline pressure from those<br>
projects. I remember I still owe Florian an apology, as he once asked<br>
me to test a new feature of the master, but since then I haven't given<br>
him a reply, because I've been waiting for a slave, expecting that the<br>
next opportunity to have a slave will come soon, but this didn't<br>
happen. So I am lack of a testing environment, which could make my<br>
vision of EtherCAT quite narrowed, and I can’t test my thoughts<br>
myself.<br>
<br>
Alright, here is something I would like to share.<br>
<br>
I. The problem with "No app_time received up to now, but master already active."<br>
I've been always having this error if I don't call<br>
ecrt_master_application_time() before my realtime cycle loop. I've<br>
also tried giving a garbage value to the first call of this function<br>
outside my loop, and it didn't hurt my system at all. This phenomenon<br>
was recored in my last mails to the mailing list, and the reply from<br>
Florian is, I shouldn't do that. Well, he is right, because in the<br>
first call, the app_time will be saved as app_start_time, and then be<br>
used to calculate the "remainder" correction to the DC start time. By<br>
calling ecrt_master_application_time() prior to the cycle loop, we<br>
will give a wrong starting point for DC cyclic operation on the slave.<br>
I think the end effect will be something like we play with the<br>
sync0->shift_time, that is, set a shift time to the DC sync0. Although<br>
this won't hurt us for the most of time, it is not the right way to do<br>
so.<br>
<br>
Where does this warning come from?<br>
When a master application is running, there would be two threads in<br>
the system. One is the user realtime cycle loop, the other is the<br>
EtherCAT-OP thread. These two thread however, are not synchronized<br>
with each other.<br>
<br>
After calling ecrt_master_activate(), the master goes into<br>
ec_master_operation_thread, which execute further the FSM(finite state<br>
machine) of the master repeatedly. The cycle time of the EtherCAT-OP<br>
thread on my machine is 4ms, my linux kernel is running at 250Hz. And<br>
the function ec_fsm_master_enter_write_system_times will get called<br>
after several ms, which could be something around 4 to 8 ms, I guess.<br>
<br>
If the ecrt_master_application_time() is not be called within that<br>
time, the master would fail to have a app_time in time, and such an<br>
error "No app_time" would occur.<br>
<br>
In my case, my realtime thread happens to have a cycle time of 4ms.<br>
And since my loop is like<br>
<br>
// first doing some initialization job, which costs 10ms<br>
while () {<br>
    wait_for_4_ms();<br>
    master_receive();<br>
    ...<br>
    master_application_time()<br>
    master_send();<br>
}<br>
<br>
This means, after ecrt_master_activate(), there would be at least 14ms<br>
passed away before the first master_application_time() in my loop get<br>
called. The chance for me to have a "No app_time" warning is<br>
reasonable quite high.<br>
<br>
To resolve this problem properly, I can offer two options:<br>
<br>
The first option is to change your code: Reduce the initialization<br>
time, making the time interval between master_activate() and your<br>
cycle loop as small as possible.<br>
<br>
But what if we have a large cycle time, say 16ms? Our cycle loop will<br>
wait 16 ms anyway before the first master_application_time() get<br>
called, which could be too late  for the EtherCAT-OP thread. So my<br>
second option is, to change the code of EtherCAT master. And the<br>
simplest way for me to do so, is to add a "return;" after the line<br>
            EC_MASTER_WARN(master, "No app_time received up to now,"<br>
                    " but master already active.\n");<br>
in master/fsm_master.c. This would force the master FSM to wait until<br>
it has got an app_time.<br>
<br>
Note that I don't have the possibility to do the test. So please<br>
change your etherlab master code, check it out on your system, and<br>
give everybody a feedback if it works.<br>
<br>
<br>
II. The problem with "Slave did not sync after 5000 ms"<br>
This is a little bit more complicated. In short, IMHO, it is the<br>
master who should take the responsibility to this problem.<br>
<br>
Concerning the DC sync, there are 3 phases.<br>
Phase 1. Measure the transmission delays t_delay to each slave.<br>
Phase 2. Calculate the system time offset t_offset for each slave.<br>
Phase 3. Drift compensation, where the slave will adjust their local<br>
DC to have dt = (t_local + t_offset - t_delay) -<br>
t_received_system_time go to 0.<br>
<br>
The first phase will be executed during the bus scanning in the<br>
function ec_fsm_master_state_scan_slave() -> ec_master_calc_dc() -><br>
ec_master_calc_transmission_delays() -> ec_slave_calc_port_delays().<br>
It seems that the EtherLab master measure this for only once. Well we<br>
could argue that, measuring the transmission delay for several times<br>
and get its average could generate a better estimation. Until now, my<br>
experiences tell me these values don’t vary much, and it seems the<br>
EtherLab master is doing good. But I will be appreciate if anyone<br>
would like to do the „bus rescan“ thing many times on the same set of<br>
EtherCAT bus, check if the delay_to_next_dc of all the slaves change<br>
too much each times of the bus scan. If it is so, changes must be made<br>
to have several measurements instead of only one in the source of<br>
etherLab master.<br>
<br>
At the beginning of the year 2013, I encountered a phenomenon, which<br>
has been written in my last emails, when I tried to correct it but<br>
failed in the end. This phenomenon in my observation one year ago, is<br>
that, after the bus has reached a stable state for all the DCs, a<br>
restart of the master application would cause a wrongly change of<br>
approx. 4ms to the system_time_offset of the ref clock, and later  the<br>
ec_fsm_slave_config_state_dc_sync_check() of the ref slave shows that<br>
there are around 4ms errors between the master clock to the slave<br>
clock at the beginning. This certainly demonstrates the weakness of<br>
the current EtherLab master in the second phase, that the calculation<br>
of the t_offset is not alright.<br>
<br>
Since the t_offset is given wrongly to the slaves by the master, the<br>
difference dt = (t_local + t_offset - t_delay) -<br>
t_received_system_time for the drift compensation becomes too large at<br>
its beginning. In my humble opinion, the EtherLab master might have<br>
abused the functionality of the drift compensation mechanism to<br>
compensate its failure in the accurate calculation of the system time<br>
offset t_offset.<br>
<br>
What is the matter with the time offset?<br>
Let’s have look at the procedure of time offset calculation:<br>
1. The master FSM prepares a ec_datagram_fprd(fsm->datagram,<br>
fsm->slave->station_address,                    0x0910, 24) to read<br>
out the system time of the slave.<br>
2. The user realtime cycle loop sends out the datagram while calling<br>
ecrt_master_send.<br>
3. The next ecrt_master_receive fetches the answer.<br>
4. The master FSM read the datagram and calculate the time offset.<br>
<br>
Take an example, we have a master FMS EtherCAT-OP thread running in a<br>
loop of 4ms, and a user realtime application thread running at 1ms.<br>
Let’s define the time the step 1 happens is x ms. And the user loop<br>
runs 0.5ms after the EtherCAT-OP.<br>
<br>
The following would happen:<br>
Time : Event<br>
x    ms: Step 1, FSM prepares an FPRD datagram to 0x0910<br>
x+0.5ms: Step 2, user loop sets a new app_time; the FPRD datagram gets<br>
sent out, the sending timestamp jiffies is stored in<br>
datagram->jiffies_sent;<br>
x+1.5ms: Step 3, user loop sets a new app_time; the datagram is<br>
received, the receiving timestamp jiffies is stored in<br>
datagram->jiffies_received;<br>
x+2.5ms: user loop sets a new app_time;<br>
x+3.5ms: user loop sets a new app_time;<br>
x+4  ms: Step 4, FSM calculate the time offset.<br>
<br>
And here is the source code in ec_fsm_master_dc_offset64()<br>
<br>
    // correct read system time by elapsed time since read operation<br>
    correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000;<br>
    system_time += correction;<br>
    time_diff = fsm->slave->master->app_time - system_time;<br>
<br>
The jiffies is a counter in Linux kernel which get increased by 1 in a<br>
frequency defined by HZ. I have a 250 Hz linux system, so the 1<br>
jiffies means 4 ms. As jiffies_sent was taken when the master clock is<br>
x+0.5ms, and the current jiffies value is taken at x+4ms. We have a<br>
possibility of 0.5/4 = 12.5% that the jiffies don’t increase itself<br>
during that 3.5ms time, and 87.5% possibility that the jiffies has<br>
been increased by 1. This means the value „correction“ would have a<br>
typical value of 4000000ns, occasionally being 0 ns.<br>
<br>
Let’s assume that the slave DC has been perfectly synchronized with<br>
the master app time. So the system_time from the slave equals to<br>
0.5ms(the time the FPRD datagram was sent). With correction added,<br>
system_time = x+4.5ms or x+0.5ms.<br>
<br>
The app_time is x+3.5ms at the time of the Step 4..<br>
<br>
time_diff = app_time - system_time = -1000000ns for the most of the<br>
time, and around 2000000ns occasionally, depending on the correction .<br>
<br>
See, the time_diff should actually be 0, not -1ms or 2ms, as we said,<br>
the slave DC is perfectly synchronized with the master app time.<br>
<br>
You may argue that the -1ms error isn’t that too much, but this error<br>
will typically goes to around -4ms if the user realtime cycle loop is<br>
running every 4ms, as in my case one year ago.<br>
<br>
Where comes the error in the calculation?<br>
Two reasons:<br>
1. jiffies have a bad resolution of 4ms in a linux system of 250Hz.<br>
2. app_time is not the time when Step 4 is executed.<br>
<br>
While using get_cycles() instead of jiffies could be able to improve<br>
the accuracy of the correction, the fact that app_time is not the<br>
current master system time would still drags errors into time offset.<br>
<br>
Why do we need "correction" here at all? Because the app_time in Step<br>
4 is not the app_time of the slave system time reading.<br>
<br>
The key is to have the correct app_time the FPRD datagram 0x0910 is<br>
sent, and use that app_time to calculate the time_diff, without any<br>
correction any more of course.<br>
<br>
I know, it is easier said than done. Right now I have two ideas for the master.<br>
The first idea: add a new variable app_time_sent to the ec_datagram_t<br>
struct. write down the app_time when each datagram get sent. time_diff<br>
= datagram->app_time_sent - system_time(0x0910);<br>
<br>
The second solution is a little bit tricky: triggers the calculation<br>
by the user realtime cycle loop. i.e. we may check the fsm_datagram in<br>
ecrt_master_receive() or even in ecrt_master_application_time() when<br>
the last app_time is still there. If we find out it is a FPRD 0x0910<br>
datagram, we do the calculation right away using the old app_time.<br>
<br>
I think the first idea would be easier to implement.<br>
<br>
<br>
Besides the inaccurate calculation of the time offset, the other issue<br>
in the EtherLab master that bothers me is, it seems to me that the<br>
drift compensation is working at the same time when the new system<br>
time offset is<br>
calculated and sent to the slaves, as the drift compensation is in the<br>
user realtime cycle loop and the t_offset calculation is the<br>
EtherCAT-OP. Shouldn’t we get the offset calculation be done first,<br>
before sending ref_sync_datagram to the ref clock and sync_datagram to<br>
the other slaves? Won’t the drift compensation algorithm of the slaves<br>
have any effects on its local DC time (by slowing or fastening the<br>
clock), which then effects the t_offset calculation? Since phase 2 and<br>
3 happens simultaneously, won’t the sudden change of the<br>
t_offset(which causes a sudden change of dt) causes some sort of<br>
disturbance to the drift compensation algorithm on the slave?<br>
<br>
I think we may need a boolean, set by the FSM to tell the user thread<br>
whether phase 2 is done, the user thread only calls<br>
ecrt_master_sync_reference_clock(master) and<br>
ecrt_master_sync_slave_clocks(master) when the correct system time<br>
offset for each slaves have been sent to the slaves.<br>
<br>
<br>
<br>
Sorry to have written such a long email, I hope I’ve made my thoughts<br>
clear.  I could be wrong in many different places, I’ll be very happy<br>
if somebody could change the EtherLab master code the way as I<br>
mentioned and test it for me.<br>
<br>
<br>
Wish all of you a Happy New Year!<br>
<br>
Jun<br>
<div><div><br>
On Mon, Dec 30, 2013 at 2:32 PM, Raz <<a href="mailto:raziebe@gmail.com" target="_blank">raziebe@gmail.com</a>> wrote:<br>
> Hey<br>
><br>
> At the moment it takes a long time to calibrate the dc. aprox 5 seconds<br>
> for each slave.  I am setting up a system which is supposed to control<br>
> over 12 axes and the calibration duration reaches a minute.<br>
><br>
> Is it possible to reduce this time ?<br>
><br>
><br>
> --<br>
> <a href="https://sites.google.com/site/ironspeedlinux/" target="_blank">https://sites.google.com/site/ironspeedlinux/</a><br>
><br>
</div></div>> _______________________________________________<br>
> etherlab-users mailing list<br>
> <a href="mailto:etherlab-users@etherlab.org" target="_blank">etherlab-users@etherlab.org</a><br>
> <a href="http://lists.etherlab.org/mailman/listinfo/etherlab-users" target="_blank">http://lists.etherlab.org/mailman/listinfo/etherlab-users</a><br>
><br>
<br>
<br>
<br>
--<br>
Jun Yuan<br>
[Aussprache: Djün Üän]<br>
<br>
Robotics Technology Leaders GmbH<br>
Am Loferfeld 58, D-81249 München<br>
Tel: <a href="tel:%2B49%2089%20189%200465%2024" value="+4989189046524" target="_blank">+49 89 189 0465 24</a><br>
Mobile: <a href="tel:%2B49%20176%202176%205238" value="+4917621765238" target="_blank">+49 176 2176 5238</a><br>
Fax: <a href="tel:%2B49%2089%20189%200465%2011" value="+4989189046511" target="_blank">+49 89 189 0465 11</a><br>
mailto: <a href="mailto:j.yuan@rtleaders.com" target="_blank">j.yuan@rtleaders.com</a><br>
<br>
Umlautregel in der chinesischen Lautschrift Pinyin: Nach den Anlauten<br>
y, j, q, und x wird u als ü ausgesprochen, z.B. yu => ü,  ju => dschü,<br>
 qu => tschü,  xu => schü.<br>
</blockquote></div><br><br clear="all"><br>-- <br><div dir="ltr"><div><a href="https://sites.google.com/site/ironspeedlinux/" target="_blank">https://sites.google.com/site/ironspeedlinux/</a></div></div>
</div></div>
</blockquote></div>