Stop addressing an axis this tower does not have, and carry the live calibration
This commit is contained in:
parent
5b3662c529
commit
31da8012d7
|
|
@ -289,11 +289,22 @@ struct CalibAxisView {
|
||||||
double r2 = 0;
|
double r2 = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
};
|
};
|
||||||
|
// The degrees<->counts map an axis is actually using right now: from config.ini
|
||||||
|
// at startup, replaced in memory by a fit or a homing derivation. Distinct from
|
||||||
|
// CalibAxisView, which describes the last FIT and only exists once one has run.
|
||||||
|
struct AxisMapView {
|
||||||
|
double counts_per_deg = 0;
|
||||||
|
double deg_at_center = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct CalibResultView {
|
struct CalibResultView {
|
||||||
bool has = false;
|
bool has = false; // has a fit run THIS SESSION?
|
||||||
long long ts_ms = 0;
|
long long ts_ms = 0;
|
||||||
bool pitch_present = false;
|
bool pitch_present = false;
|
||||||
CalibAxisView yaw, pitch;
|
CalibAxisView yaw, pitch;
|
||||||
|
// Always populated. "No fit this session" is not the same as "uncalibrated":
|
||||||
|
// the working calibration usually comes from config.ini and predates the run.
|
||||||
|
AxisMapView live_yaw, live_pitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Worst-case encoder tracking error from the last DIAG run, per axis, for the
|
// Worst-case encoder tracking error from the last DIAG run, per axis, for the
|
||||||
|
|
|
||||||
|
|
@ -907,6 +907,9 @@ struct Application::Impl {
|
||||||
// --- Activity strip + last calibration ---
|
// --- Activity strip + last calibration ---
|
||||||
s.calib = last_calib_view;
|
s.calib = last_calib_view;
|
||||||
s.calib.pitch_present = s.gimbal.pitch_present || s.calib.pitch_present;
|
s.calib.pitch_present = s.gimbal.pitch_present || s.calib.pitch_present;
|
||||||
|
// The map in force right now, whether or not anything was fitted today.
|
||||||
|
s.calib.live_yaw = {cfg.geometry.yaw.counts_per_deg, cfg.geometry.yaw.deg_at_center};
|
||||||
|
s.calib.live_pitch = {cfg.geometry.pitch.counts_per_deg, cfg.geometry.pitch.deg_at_center};
|
||||||
s.diag = last_diag_view;
|
s.diag = last_diag_view;
|
||||||
s.test = last_test_view;
|
s.test = last_test_view;
|
||||||
fillActivity(s);
|
fillActivity(s);
|
||||||
|
|
@ -1040,7 +1043,11 @@ struct Application::Impl {
|
||||||
} clear_homing{homing_active_};
|
} clear_homing{homing_active_};
|
||||||
|
|
||||||
motor->sendCommand("ENABLE Y");
|
motor->sendCommand("ENABLE Y");
|
||||||
motor->sendCommand("ENABLE P");
|
// Only address axes this tower actually has. A yaw-only rig answers
|
||||||
|
// "ERR axis not present" to every pitch command, which arrives in the log
|
||||||
|
// as a row of warnings at every startup - noise that trains an operator to
|
||||||
|
// ignore exactly the channel that reports real faults.
|
||||||
|
if (cfg.hardware.hasAxis("pitch")) motor->sendCommand("ENABLE P");
|
||||||
// Tell the firmware where to anchor the homed midpoint and how much
|
// Tell the firmware where to anchor the homed midpoint and how much
|
||||||
// clearance to keep from each endstop, BEFORE homing: finishHoming() uses
|
// clearance to keep from each endstop, BEFORE homing: finishHoming() uses
|
||||||
// the centre count to re-origin, so a late send would apply to the next
|
// the centre count to re-origin, so a late send would apply to the next
|
||||||
|
|
@ -1050,7 +1057,10 @@ struct Application::Impl {
|
||||||
// Confirm the current landed BEFORE driving into anything. This is the
|
// Confirm the current landed BEFORE driving into anything. This is the
|
||||||
// only check standing between a stale firmware and an endstop that cannot
|
// only check standing between a stale firmware and an endstop that cannot
|
||||||
// survive full torque.
|
// survive full torque.
|
||||||
if (yaw_current_.ok || pitch_current_.ok) {
|
// Only when a reduction is actually depended on. An axis running at one
|
||||||
|
// current for everything has nothing to lose if the command went astray,
|
||||||
|
// and the check costs a DUMP round trip whose output floods the log.
|
||||||
|
if (cfg.drivetrain.yaw.reducesForHoming() || cfg.drivetrain.pitch.reducesForHoming()) {
|
||||||
if (auto dd = freshDump(std::chrono::seconds(3))) {
|
if (auto dd = freshDump(std::chrono::seconds(3))) {
|
||||||
if (!verifyCurrentAdoption(*dd)) return;
|
if (!verifyCurrentAdoption(*dd)) return;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1122,7 +1132,7 @@ struct Application::Impl {
|
||||||
}
|
}
|
||||||
// Production move speeds for subsequent MOVE commands.
|
// Production move speeds for subsequent MOVE commands.
|
||||||
motor->sendCommand("SPEED Y 50000");
|
motor->sendCommand("SPEED Y 50000");
|
||||||
motor->sendCommand("SPEED P 150000");
|
if (cfg.hardware.hasAxis("pitch")) motor->sendCommand("SPEED P 150000");
|
||||||
LOG_INFO << "Gimbal init finished";
|
LOG_INFO << "Gimbal init finished";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1208,9 +1218,11 @@ struct Application::Impl {
|
||||||
// clampTarget() keeps clear of each hard limit.
|
// clampTarget() keeps clear of each hard limit.
|
||||||
void sendAnchorConfig() {
|
void sendAnchorConfig() {
|
||||||
motor->sendCommand("CENTER Y " + std::to_string(cfg.geometry.yaw.center_count));
|
motor->sendCommand("CENTER Y " + std::to_string(cfg.geometry.yaw.center_count));
|
||||||
motor->sendCommand("CENTER P " + std::to_string(cfg.geometry.pitch.center_count));
|
|
||||||
motor->sendCommand("MARGIN Y " + std::to_string(cfg.yaw_soft_margin_counts));
|
motor->sendCommand("MARGIN Y " + std::to_string(cfg.yaw_soft_margin_counts));
|
||||||
|
if (cfg.hardware.hasAxis("pitch")) {
|
||||||
|
motor->sendCommand("CENTER P " + std::to_string(cfg.geometry.pitch.center_count));
|
||||||
motor->sendCommand("MARGIN P " + std::to_string(cfg.pitch_soft_margin_counts));
|
motor->sendCommand("MARGIN P " + std::to_string(cfg.pitch_soft_margin_counts));
|
||||||
|
}
|
||||||
// Motor current belongs here too: it governs homing torque, so it has to
|
// Motor current belongs here too: it governs homing torque, so it has to
|
||||||
// land before the search, not after it.
|
// land before the search, not after it.
|
||||||
auto sendCurrent = [&](char axis, const TmcCurrentPlan& p) {
|
auto sendCurrent = [&](char axis, const TmcCurrentPlan& p) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue