diff --git a/src/emc/nml_intf/emc.cc b/src/emc/nml_intf/emc.cc index 59fdabe..cdba7ed 100644 --- a/src/emc/nml_intf/emc.cc +++ b/src/emc/nml_intf/emc.cc @@ -1838,6 +1838,7 @@ void EMC_TRAJ_STAT::update(CMS * cms) cms->update(probeval); cms->update(kinematics_type); cms->update(motion_type); + cms->update(motion_heartbeat); } @@ -2261,4 +2262,4 @@ void EMC_MOTION_ADAPTIVE::update(CMS * cms) void EMC_MOTION_CMD_MSG::update(CMS * cms) { -} \ No newline at end of file +} diff --git a/src/emc/nml_intf/emc_nml.hh b/src/emc/nml_intf/emc_nml.hh index 2d5e61e..8c713b7 100644 --- a/src/emc/nml_intf/emc_nml.hh +++ b/src/emc/nml_intf/emc_nml.hh @@ -834,6 +834,7 @@ class EMC_TRAJ_STAT:public EMC_TRAJ_STAT_MSG { //bool spindle_override_enabled; moved to SPINDLE_STAT bool adaptive_feed_enabled; bool feed_hold_enabled; + uint32_t motion_heartbeat; // native motion-controller servo-cycle counter StateTag tag; }; diff --git a/src/emc/task/emctaskmain.cc b/src/emc/task/emctaskmain.cc index 6d5ebd5..d215e2e 100644 --- a/src/emc/task/emctaskmain.cc +++ b/src/emc/task/emctaskmain.cc @@ -3490,6 +3490,11 @@ int main(int argc, char *argv[]) // since emcStatus was passed to the WM init functions, it // will be updated in the _update() functions above. There's // no need to call the individual functions on all WM items. + // EMC_TASK_STAT_MSG::heartbeat is the native task-cycle oracle used by + // external clients. Keep it monotonic and publish it with this cycle's + // status image so a reader can identify every task tick without relying on + // wall-clock sampling. + emcStatus->task.heartbeat++; emcStatusBuffer->write(emcStatus); // wait on timer cycle, if specified, or calculate actual diff --git a/src/emc/task/taskintf.cc b/src/emc/task/taskintf.cc index 36fbd97..b3ae2aa 100644 --- a/src/emc/task/taskintf.cc +++ b/src/emc/task/taskintf.cc @@ -1612,6 +1612,7 @@ int emcTrajUpdate(EMC_TRAJ_STAT * stat) stat->feed_override_enabled = enables & FS_ENABLED; stat->adaptive_feed_enabled = enables & AF_ENABLED; stat->feed_hold_enabled = enables & FH_ENABLED; + stat->motion_heartbeat = emcmotStatus.heartbeat; if (new_config) { stat->cycleTime = emcmotConfig.trajCycleTime; diff --git a/src/emc/usr_intf/axis/extensions/emcmodule.cc b/src/emc/usr_intf/axis/extensions/emcmodule.cc index b43f041..96f12a2 100644 --- a/src/emc/usr_intf/axis/extensions/emcmodule.cc +++ b/src/emc/usr_intf/axis/extensions/emcmodule.cc @@ -409,6 +409,9 @@ static PyMemberDef Stat_members[] = { {(char*)"echo_serial_number", T_INT, O(echo_serial_number), READONLY}, {(char*)"echo_serial_number", T_INT, O(echo_serial_number), READONLY}, {(char*)"state", T_INT, O(status), READONLY}, + {(char*)"task_heartbeat", T_UINT, O(task.heartbeat), READONLY, + "Native EMC task-loop heartbeat. This counter is incremented by the " + "LinuxCNC task thread and is suitable for identifying native status ticks."}, // task {(char*)"task_mode", T_INT, O(task.mode), READONLY}, @@ -473,6 +476,8 @@ static PyMemberDef Stat_members[] = { {(char*)"feed_override_enabled", T_BOOL, O(motion.traj.feed_override_enabled), READONLY}, {(char*)"adaptive_feed_enabled", T_BOOL, O(motion.traj.adaptive_feed_enabled), READONLY}, {(char*)"feed_hold_enabled", T_BOOL, O(motion.traj.feed_hold_enabled), READONLY}, + {(char*)"motion_heartbeat", T_UINT, O(motion.traj.motion_heartbeat), READONLY, + "Native motion-controller servo-cycle counter."}, {(char*)"num_extrajoints", T_INT, O(motion.numExtraJoints), READONLY},