[etherlab-users] Distributed Clocks
Richard Hacker
ha at igh.de
Thu Mar 3 20:59:04 CET 2016
Hi,
we use CLOCK_MONOTONIC for ecrt_master_application_time(), in fact we
use it thoughout. Probably not the solution, but worth a try.
- Richard
On 03.03.2016 17:08, Thomas Bitsky Jr wrote:
>
> [snip]
> Are you using the dc_clock_adjust to modify your sleep time? ie.
> something like
> [/snip]
>
>
> I’ve been trying, but the results are all over the place and I’m obviously not understanding what needs to be done with the clock.
>
> My latest attempt is has the scan time ticking from anywhere between 3930 and 4100 scans per second (reported by ethercat master command) and does nothing to eliminate skipped datagrams. I don’t think I’m fundamentally understanding what needs to be done.
>
> My latest code is below. If anyone has any insights, it would be greatly appreciated.
>
> ========
>
> int64_t dc_adjust_ns = 0 ;
> int32_t dc_diff_ns = 0;
>
>
>
> void calculateClockDrift(void) {
> uint32_t ref_time = 0;
> uint64_t prev_app_time = dc_time_ns;
>
> dc_time_ns = system_time_ns();
> // get reference clock time to synchronize master cycle
> ecrt_master_reference_clock_time(master_, & ref_time);
> dc_diff_ns = (uint32_t) prev_app_time - ref_time;
> // calc drift (via un-normalised time diff)
> int32_t delta = dc_diff_ns - prev_dc_diff_ns;
> prev_dc_diff_ns = dc_diff_ns;
>
>
> dc_diff_ns =
> ((dc_diff_ns + (cycle_ns_ / 2)) % cycle_ns_) - (cycle_ns_ / 2);
>
> }
>
>
> #define TIMESPEC_ADD_NS(TS, NS)\
> (TS).tv_nsec += (NS);\
> while ((TS).tv_nsec >= NANOS_PER_SEC) {\
> (TS).tv_nsec -= NANOS_PER_SEC;\
> (TS).tv_sec++;
> }
>
> #define TIMESPEC2NSEPOCH2000(T)\
> ((uint64_t)(((T).tv_sec - 946684800 ULL) * 1000000000 ULL) + (T).tv_nsec)
>
> # define TON struct timespec# define TON_ENDTIME(MS)\
> time_add_ns((MS) * NANOS_PER_MILLISEC)
>
>
> static TON clockSyncTon_;
>
>
> int
> TON_ISDONE(struct timespec ts) {
> struct timespec now;
> clock_gettime(CLOCK_MONOTONIC, & now);
> if (now.tv_sec > ts.tv_sec)
> return 1;
> else if (now.tv_sec == ts.tv_sec && now.tv_nsec >= ts.tv_nsec)
> return 1;
> else
> return 0;
> }
>
>
> static bool
> wait_period(RtaiMain * inst) {
>
> int rc;
> bool done = false;
> while (!done && inst - > doScan && runAll_) {
> rc = clock_nanosleep(CLOCK_MONOTONIC,
> TIMER_ABSTIME, & inst - > wakeupTime,
> NULL);
>
>
> if (rc == EFAULT) {
> return false;
> } else if (rc == EINTR) {
> continue;
> } else if (rc == EINVAL) {
> return false;
> } else {
> done = 1;
> }
> }
> TIMESPEC_ADD_NS(inst->wakeupTime,
> inst->cycleNs + dc_diff_ns );
> return true;
>
> }
>
>
> static void
> cyclic_task(RtaiMain * inst) {
>
> clock_gettime(CLOCK_MONOTONIC, & (inst - > wakeupTime));
> /* start after one second */
> inst - > wakeupTime.tv_sec++;
> wait_period(inst);
> while (runAll_ && inst - > doScan) {
> //
> // Trigger Fieldbus RX here.
> //
> //
> ecrt_master_receive(master_);
>
> // record the time we received the data so other parts of the program
> // have an accurate time reading
> globalTickTimeNs = ton_get_ns();
>
> ecrt_domain_process(lrwDomainMgr_.domain);
> ecrt_domain_process(noLrwWriteDomainMgr_.domain);
> ecrt_domain_process(noLrwReadDomainMgr_.domain);
>
> if (counter_) {
>
> counter_—;
> } else {
> counter_ = 4000;
>
> // check for master state
> check_master_state();
> }
>
>
> …
> tick sub systems
>
>
> //
> // Trigger Fieldbus TX. This should be the last step
> //
> //
> ecrt_domain_queue(lrwDomainMgr_.domain);
> ecrt_domain_queue(noLrwWriteDomainMgr_.domain);
> ecrt_domain_queue(noLrwReadDomainMgr_.domain);
> clock_gettime(CLOCK_REALTIME, & dcTime_);
> ecrt_master_application_time(
> master_,
> TIMESPEC2NSEPOCH2000(dcTime_));
>
>
> if (TON_ISDONE(clockSyncTon_)) {
> ecrt_master_sync_reference_clock(master_);
> clockSyncTon_ = TON_ENDTIME(10); // milliseconds
> }
> ecrt_master_sync_slave_clocks(master_);
>
> // send EtherCAT data
> ecrt_master_send(master_);
>
> calculateClockDrift();
>
>
> if (!wait_period(inst)) {
> PRINT("%s Error with waiting! Stopping cyclic_task.\n",
> __FUNCTION__);
> inst - > doScan = false;
> }
> }
>
> }
>
More information about the Etherlab-users
mailing list