diff --git a/asibfm700/asibfm700_configfile.h b/asibfm700/asibfm700_configfile.h index aa62e9b..f0995aa 100644 --- a/asibfm700/asibfm700_configfile.h +++ b/asibfm700/asibfm700_configfile.h @@ -238,6 +238,21 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple( std::chrono::milliseconds(100), {"mount axes rate calculation interval in millisecs"}}, + simple_config_record_t{"PIDMaxDt", + std::chrono::milliseconds(1000), + {"maximal PID refresh time interval in millisecs", + "NOTE: if PID data will be refreshed with interval longer than this value (e.g. user polls " + "encoder data too rarely)", + "then the PID 'expired' data will be cleared and new computing loop is started"}}, + + simple_config_record_t{"PIDRefreshDt", std::chrono::milliseconds(100), {"PID refresh interval"}}, + + simple_config_record_t{"PIDCycleDt", + std::chrono::milliseconds(5000), + {"PID I cycle time (analog of 'RC' for PID on opamps)"}}, + + + // X-axis coordinate PID P,I,D-params simple_config_record_t{"XPIDC", std::vector{0.8, 0.1, 0.3}, {"X-axis coordinate PID P,I,D-params"}}, @@ -485,6 +500,16 @@ public: secs = getValue("EncoderSpeedInterval").value_or(std::chrono::milliseconds{}); hw_cfg.devConfig.EncoderSpeedInterval = secs.count(); + secs = getValue("PIDMaxDt").value_or(std::chrono::milliseconds{1000}); + hw_cfg.devConfig.PIDMaxDt = secs.count(); + + secs = getValue("PIDRefreshDt").value_or(std::chrono::milliseconds{100}); + hw_cfg.devConfig.PIDRefreshDt = secs.count(); + + secs = getValue("PIDCycleDt").value_or(std::chrono::milliseconds{5000}); + hw_cfg.devConfig.PIDCycleDt = secs.count(); + + std::vector pid = getValue>("XPIDC").value_or(std::vector{}); if (pid.size() > 2) { hw_cfg.devConfig.XPIDC.P = pid[0]; diff --git a/asibfm700/asibfm700_mount.cpp b/asibfm700/asibfm700_mount.cpp index d7383d6..5146ff1 100644 --- a/asibfm700/asibfm700_mount.cpp +++ b/asibfm700/asibfm700_mount.cpp @@ -126,6 +126,9 @@ Asibfm700Mount::error_t Asibfm700Mount::initMount() logInfo(" MountReqInterval: {}", to_msecs(hw_cfg.devConfig.MountReqInterval)); logInfo(" EncoderReqInterval: {}", to_msecs(hw_cfg.devConfig.EncoderReqInterval)); logInfo(" EncoderSpeedInterval: {}", to_msecs(hw_cfg.devConfig.EncoderSpeedInterval)); + logInfo(" PIDMaxDt: {}", to_msecs(hw_cfg.devConfig.PIDMaxDt)); + logInfo(" PIDRefreshDt: {}", to_msecs(hw_cfg.devConfig.PIDRefreshDt)); + logInfo(" PIDCycleDt: {}", to_msecs(hw_cfg.devConfig.PIDCycleDt)); logInfo(" XPIDC: [P: {}, I: {}, D: {}]", hw_cfg.devConfig.XPIDC.P, hw_cfg.devConfig.XPIDC.I, hw_cfg.devConfig.XPIDC.D); @@ -186,6 +189,44 @@ Asibfm700Mount::error_t Asibfm700Mount::initMount() mpars.brakingAccelX = 0.165806; // Sidereal defines HA-axis as Y-axis mpars.brakingAccelY = 0.219911; // Sidereal defines DEC-axis as X-axis } + + auto max_dt_intvl = _mountConfig.getValue("PIDMaxDt").value_or({}); + auto min_dt_intvl = _mountConfig.getValue("PIDRefreshDt").value_or({}); + + // check for polling interval consistency + auto intvl = mpars.slewingTelemetryInterval; + if (intvl > max_dt_intvl) { + mpars.slewingTelemetryInterval = max_dt_intvl; + logWarn( + " slewingTelemetryInterval user value ({} ms) is greater than allowed! Set it to maximal " + "allowed one: {} ms", + intvl.count(), max_dt_intvl.count()); + } + if (intvl < min_dt_intvl) { + mpars.slewingTelemetryInterval = min_dt_intvl; + logWarn( + " slewingTelemetryInterval user value ({} ms) is lesser than allowed! Set it to minimal allowed " + "one: {} ms", + intvl.count(), min_dt_intvl.count()); + } + + intvl = mpars.trackingTelemetryInterval; + if (intvl > max_dt_intvl) { + mpars.trackingTelemetryInterval = max_dt_intvl; + logWarn( + " trackingTelemetryInterval user value ({} ms) is greater than allowed! Set it to maximal " + "allowed one: {} ms", + intvl.count(), max_dt_intvl.count()); + } + if (intvl < min_dt_intvl) { + mpars.trackingTelemetryInterval = min_dt_intvl; + logWarn( + " trackingTelemetryInterval user value ({} ms) is lesser than allowed! Set it to minimal " + "allowed one: {} ms", + intvl.count(), min_dt_intvl.count()); + } + + auto st_err = setSlewingParams(mpars); if (st_err) { errorLogging(" An error occured while setting slewing parameters: ", st_err); @@ -194,10 +235,14 @@ Asibfm700Mount::error_t Asibfm700Mount::initMount() logInfo(" Max DEC-axis speed: {} degs/s", mcc::MccAngle(mpars.slewRateY).degrees()); logInfo(" HA-axis stop acceleration braking: {} degs/s^2", mcc::MccAngle(mpars.brakingAccelX).degrees()); logInfo(" DEC-axis stop acceleration braking: {} degs/s^2", mcc::MccAngle(mpars.brakingAccelY).degrees()); + + logInfo(" Slewing telemetry polling interval: {} millisecs", mpars.slewingTelemetryInterval.count()); } st_err = setTrackingParams(_mountConfig.movingModelParams()); if (st_err) { errorLogging(" An error occured while setting tracking parameters: ", st_err); + } else { + logInfo(" Tracking telemetry polling interval: {} millisecs", mpars.trackingTelemetryInterval.count()); } logInfo("Slewing and tracking parameters have been set successfully"); diff --git a/asibfm700/asibfm700_servocontroller.cpp b/asibfm700/asibfm700_servocontroller.cpp index 676d655..d72c67f 100644 --- a/asibfm700/asibfm700_servocontroller.cpp +++ b/asibfm700/asibfm700_servocontroller.cpp @@ -119,7 +119,14 @@ AsibFM700ServoController::error_t AsibFM700ServoController::hardwareSetState(har // time point from sidservo library is 'double' number represented UNIXTIME with // microseconds/nanoseconds precision - double tp = std::chrono::duration(state.time_point.time_since_epoch()).count(); + // double tp = std::chrono::duration(state.time_point.time_since_epoch()).count(); + + + // 2025-12-04: coordval_pair_t.X.t is now of type struct timespec + auto ns = std::chrono::duration_cast(state.time_point.time_since_epoch()); + auto secs = std::chrono::floor(ns); + ns -= secs; + std::timespec tp{.tv_sec = secs.count(), .tv_nsec = ns.count()}; // according to"SiTech protocol notes" X is DEC-axis and Y is HA-axis coordval_pair_t cvalpair{.X{.val = state.Y, .t = tp}, .Y{.val = state.X, .t = tp}}; @@ -151,10 +158,16 @@ AsibFM700ServoController::error_t AsibFM700ServoController::hardwareGetState(har // time point from sidservo library is 'double' number represented UNIXTIME with // microseconds/nanoseconds precision (must be equal for encXposition and encYposition) - using secs_t = std::chrono::duration; + // using secs_t = std::chrono::duration; + + // secs_t secs = secs_t{mdata.encXposition.t}; + // state->time_point = tp_t{std::chrono::duration_cast(secs)}; + + // 2025-12-04: coordval_pair_t.X.t is now of type struct timespec + auto dr = std::chrono::duration_casttime_point)::duration>( + std::chrono::seconds(mdata.encXposition.t.tv_sec) + std::chrono::nanoseconds(mdata.encXposition.t.tv_nsec)); + state->time_point = decltype(state->time_point){dr}; - secs_t secs = secs_t{mdata.encXposition.t}; - state->time_point = tp_t{std::chrono::duration_cast(secs)}; // if (mcc::utils::isEqual(secs.count(), 0.0)) { // model mode? // state->time_point = decltype(state->time_point)::clock::now();