Warn when the homed travel falls below zero, and say why the centre matters
This commit is contained in:
parent
c2a2459f81
commit
57a166c9a4
|
|
@ -178,6 +178,11 @@ period_ms = 2000
|
||||||
;
|
;
|
||||||
; Yaw starting point: firmware steps_per_rev=177000 over ~180 deg => ~983.33.
|
; Yaw starting point: firmware steps_per_rev=177000 over ~180 deg => ~983.33.
|
||||||
yaw_counts_per_deg = 983.33
|
yaw_counts_per_deg = 983.33
|
||||||
|
; MUST exceed half the homed travel: the range is centre +/- half-travel, so a
|
||||||
|
; smaller centre puts the negative end below zero. 500000 suits the Delta
|
||||||
|
; (~89k half-travel); the IOTA's higher gear ratio needs 1000000. The centre
|
||||||
|
; itself is arbitrary - only the span is physical - and a warning names it
|
||||||
|
; after each home if it is too small.
|
||||||
yaw_center_count = 500000
|
yaw_center_count = 500000
|
||||||
; True bearing (0 = north) the gimbal points at when parked at the centre.
|
; True bearing (0 = north) the gimbal points at when parked at the centre.
|
||||||
yaw_heading_at_center = 0.0
|
yaw_heading_at_center = 0.0
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ Parsed and validated by `ConfigLoader` ([src/core/Config.cpp](../src/core/Config
|
||||||
| `Logging` | `trace` | csv | — | Wire-trace categories, off by default (`--trace` overrides) |
|
| `Logging` | `trace` | csv | — | Wire-trace categories, off by default (`--trace` overrides) |
|
||||||
| `UI` | `enable_tui` | bool | `false` | Full-screen terminal dashboard (`--tui`/`--no-tui` override; needs `WITH_TUI=ON`) |
|
| `UI` | `enable_tui` | bool | `false` | Full-screen terminal dashboard (`--tui`/`--no-tui` override; needs `WITH_TUI=ON`) |
|
||||||
| `Motor` | `yaw_counts_per_deg` / `pitch_counts_per_deg` | float | `983.33` / — | Encoder counts per degree (**calibrate**; may be negative to flip) |
|
| `Motor` | `yaw_counts_per_deg` / `pitch_counts_per_deg` | float | `983.33` / — | Encoder counts per degree (**calibrate**; may be negative to flip) |
|
||||||
| `Motor` | `yaw_center_count` / `pitch_center_count` | int | `500000` | Count homing **defines** as the middle of the found travel |
|
| `Motor` | `yaw_center_count` / `pitch_center_count` | int | `500000` | Count homing **defines** as the middle of the found travel. **Must exceed half the travel**, or the negative end falls below zero — the `500000` default suits the Delta's ~89k half-travel, not a geared-up rig (the IOTA needs 1000000). A warning names it after each home |
|
||||||
| `Motor` | `yaw_heading_at_center` | float | `0` | True bearing (0 = north) at that centre (**calibrate**) |
|
| `Motor` | `yaw_heading_at_center` | float | `0` | True bearing (0 = north) at that centre (**calibrate**) |
|
||||||
| `Motor` | `pitch_angle_at_center` | float | `0` | Elevation above level at that centre (**calibrate**; not 0 on a real rig) |
|
| `Motor` | `pitch_angle_at_center` | float | `0` | Elevation above level at that centre (**calibrate**; not 0 on a real rig) |
|
||||||
| `Motor` | `yaw_soft_margin_counts` / `pitch_soft_margin_counts` | int | `5000` | Clearance kept from each hard endstop; sent to the firmware, which enforces it |
|
| `Motor` | `yaw_soft_margin_counts` / `pitch_soft_margin_counts` | int | `5000` | Clearance kept from each hard endstop; sent to the firmware, which enforces it |
|
||||||
|
|
|
||||||
|
|
@ -88,4 +88,20 @@ struct DrivetrainEcho {
|
||||||
CheckResult checkDrivetrainAdopted(const std::string& axis, const DrivetrainExpectation& want,
|
CheckResult checkDrivetrainAdopted(const std::string& axis, const DrivetrainExpectation& want,
|
||||||
const DrivetrainEcho& got);
|
const DrivetrainEcho& got);
|
||||||
|
|
||||||
|
// Does the homed travel fit entirely in positive counts?
|
||||||
|
//
|
||||||
|
// `center_count` defines where the middle of the found travel sits, so the range
|
||||||
|
// is center +/- half the travel. A center smaller than half the travel puts the
|
||||||
|
// negative end below zero. The 500000 default was sized for the Delta, whose
|
||||||
|
// half-travel is ~89k; a drivetrain geared up by 7x has ~605k and crosses zero.
|
||||||
|
//
|
||||||
|
// Whether the TMC5160 actually misbehaves there is NOT established - XACTUAL is
|
||||||
|
// a signed 32-bit register and the firmware round-trips the sign correctly - but
|
||||||
|
// homing is the only thing that has ever driven that far, so the region is
|
||||||
|
// untested in normal operation. The cheap fix is to not be there.
|
||||||
|
//
|
||||||
|
// `center` and `half_travel` are in counts. A non-positive half_travel means the
|
||||||
|
// axis has not homed, and nothing is checked.
|
||||||
|
CheckResult checkTravelFitsPositive(const std::string& axis, long center, long half_travel);
|
||||||
|
|
||||||
} // namespace fgc
|
} // namespace fgc
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "fgc/CameraProfile.h"
|
#include "fgc/CameraProfile.h"
|
||||||
#include "fgc/AxisSpeed.h"
|
#include "fgc/AxisSpeed.h"
|
||||||
#include "fgc/FirmwareConfig.h"
|
#include "fgc/FirmwareConfig.h"
|
||||||
|
#include "fgc/HardwareChecks.h"
|
||||||
#include "fgc/HardwarePresence.h"
|
#include "fgc/HardwarePresence.h"
|
||||||
#include "fgc/TmcCurrent.h"
|
#include "fgc/TmcCurrent.h"
|
||||||
#include "fgc/ICameraSource.h"
|
#include "fgc/ICameraSource.h"
|
||||||
|
|
@ -1498,6 +1499,15 @@ struct Application::Impl {
|
||||||
const long want_margin =
|
const long want_margin =
|
||||||
is_yaw ? cfg.yaw_soft_margin_counts : cfg.pitch_soft_margin_counts;
|
is_yaw ? cfg.yaw_soft_margin_counts : cfg.pitch_soft_margin_counts;
|
||||||
|
|
||||||
|
// The centre is arbitrary, but it has to be big enough that the whole
|
||||||
|
// travel stays positive: the range is centre +/- half the travel, so
|
||||||
|
// a centre below half-travel puts the negative end under zero. The
|
||||||
|
// 500000 default was sized for the Delta's ~89k half-travel and does
|
||||||
|
// not survive a gear ratio 7x higher.
|
||||||
|
const auto fits = checkTravelFitsPositive(name, map.center_count,
|
||||||
|
(a.lim_pos - a.lim_neg) / 2);
|
||||||
|
if (fits.ran && !fits.pass) LOG_WARN << fits.detail;
|
||||||
|
|
||||||
// One encoder quantum of slack: ENC_CONST makes X_ENC advance in 12.8
|
// One encoder quantum of slack: ENC_CONST makes X_ENC advance in 12.8
|
||||||
// microstep steps, so the midpoint can land a count or so off.
|
// microstep steps, so the midpoint can land a count or so off.
|
||||||
const long mid = a.lim_neg + (a.lim_pos - a.lim_neg) / 2;
|
const long mid = a.lim_neg + (a.lim_pos - a.lim_neg) / 2;
|
||||||
|
|
|
||||||
|
|
@ -184,4 +184,28 @@ CheckResult checkDeclaredValues(const std::string& axis, const DeclaredValue* va
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckResult checkTravelFitsPositive(const std::string& axis, long center, long half_travel) {
|
||||||
|
CheckResult r;
|
||||||
|
if (half_travel <= 0) {
|
||||||
|
r.ran = false;
|
||||||
|
r.detail = axis + ": not homed, so the travel range is not known yet";
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
const long lo = center - half_travel;
|
||||||
|
if (lo >= 0) {
|
||||||
|
r.detail = axis + ": travel is entirely positive (" + std::to_string(lo) + " .. " +
|
||||||
|
std::to_string(center + half_travel) + ")";
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
r.pass = false;
|
||||||
|
r.detail = axis + ": homed travel reaches " + std::to_string(lo) +
|
||||||
|
" -- below zero. [Motor] " + axis + "_center_count is " +
|
||||||
|
std::to_string(center) + " but half the travel is " +
|
||||||
|
std::to_string(half_travel) + ", so raise the centre above that (a round "
|
||||||
|
"number with headroom, e.g. " +
|
||||||
|
std::to_string(((half_travel / 1000000) + 1) * 1000000) +
|
||||||
|
"). The centre is arbitrary; only the span is physical";
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fgc
|
} // namespace fgc
|
||||||
|
|
|
||||||
|
|
@ -174,3 +174,50 @@ TEST_CASE("a real mismatch alongside an absent field still names the mismatch")
|
||||||
CHECK_FALSE(r.pass);
|
CHECK_FALSE(r.pass);
|
||||||
CHECK(r.detail.find("GLOBALSCALER wanted 80, firmware has 255") != std::string::npos);
|
CHECK(r.detail.find("GLOBALSCALER wanted 80, firmware has 255") != std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- the travel must fit in positive counts -------------------------------
|
||||||
|
|
||||||
|
TEST_CASE("the Delta's centre comfortably holds its travel") {
|
||||||
|
// ~89k half-travel against a 500000 centre: 411k .. 589k, all positive.
|
||||||
|
auto r = checkTravelFitsPositive("yaw", 500000, 89000);
|
||||||
|
CHECK(r.ran);
|
||||||
|
CHECK(r.pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("the IOTA's gear ratio pushes the same centre below zero") {
|
||||||
|
// The real case: half-travel 604749 against the inherited 500000 default
|
||||||
|
// gives lim_neg -104749, which is what tower 121 actually homed to.
|
||||||
|
auto r = checkTravelFitsPositive("yaw", 500000, 604749);
|
||||||
|
CHECK(r.ran);
|
||||||
|
CHECK_FALSE(r.pass);
|
||||||
|
CHECK(r.detail.find("-104749") != std::string::npos);
|
||||||
|
CHECK(r.detail.find("yaw_center_count") != std::string::npos);
|
||||||
|
// The suggestion is the next round million above half the travel - 1000000
|
||||||
|
// here, which is the value actually adopted. Not 2000000: over-suggesting
|
||||||
|
// wastes range for no reason.
|
||||||
|
CHECK(r.detail.find("1000000") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("raising the centre fixes it") {
|
||||||
|
auto r = checkTravelFitsPositive("yaw", 1000000, 604749);
|
||||||
|
CHECK(r.pass);
|
||||||
|
CHECK(r.detail.find("395251") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("the suggestion scales with the drivetrain, not a fixed constant") {
|
||||||
|
// A ratio big enough that 1000000 would not be enough either.
|
||||||
|
auto r = checkTravelFitsPositive("yaw", 500000, 1400000);
|
||||||
|
CHECK_FALSE(r.pass);
|
||||||
|
CHECK(r.detail.find("2000000") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("exactly touching zero is accepted, one count below is not") {
|
||||||
|
CHECK(checkTravelFitsPositive("yaw", 604749, 604749).pass);
|
||||||
|
CHECK_FALSE(checkTravelFitsPositive("yaw", 604748, 604749).pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("an un-homed axis is not checked") {
|
||||||
|
auto r = checkTravelFitsPositive("pitch", 500000, 0);
|
||||||
|
CHECK_FALSE(r.ran);
|
||||||
|
CHECK(r.pass);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue