Compare commits
2 Commits
c2a2459f81
...
7ef2abcd4a
| Author | SHA1 | Date |
|---|---|---|
|
|
7ef2abcd4a | |
|
|
57a166c9a4 |
|
|
@ -178,6 +178,11 @@ period_ms = 2000
|
|||
;
|
||||
; Yaw starting point: firmware steps_per_rev=177000 over ~180 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
|
||||
; True bearing (0 = north) the gimbal points at when parked at the centre.
|
||||
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) |
|
||||
| `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_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` | `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 |
|
||||
|
|
|
|||
|
|
@ -271,6 +271,23 @@ again; too weak and the motor stalls on ordinary friction mid-sweep, trips the
|
|||
same latch, and records a phantom endstop. The firmware's `steps_per_rev` guard
|
||||
is what catches the second case, so it has to be set from the real travel.
|
||||
|
||||
> **The centre lives in `config.ini`, not here.** `install.sh` cannot write it —
|
||||
> `hardware.ini` is merged *over* `config.ini` and wins, so a shared key would
|
||||
> silently discard whatever `gimbal heading setup` had saved. What it does instead
|
||||
> is work the requirement out from `steps_per_rev` and print it as a `NOTE` in the
|
||||
> block, because the default is wrong for any geared-up rig:
|
||||
>
|
||||
> ```
|
||||
> ; NOTE: half this travel is 605389 counts, so config.ini needs
|
||||
> ; [Motor] yaw_center_count = 1000000 (or anything above 605389)
|
||||
> ; The 500000 default would put the negative end at -105389.
|
||||
> ```
|
||||
>
|
||||
> The range is centre ± half the travel, so a centre below half-travel puts the
|
||||
> negative end under zero. On tower 121 the inherited `500000` homed to
|
||||
> `-104749..1104749`; at `1000000` it homes to `395194..1604807`. A warning names
|
||||
> it after every home if it is still too small.
|
||||
|
||||
**`travel_deg` is a nameplate fact**, and the host divides the measured homing
|
||||
travel by it to derive `[Motor] <axis>_counts_per_deg` into `config.ini`. A rough
|
||||
angle gives a proportionally rough degree scale - 1 % out here is 1 % out on every
|
||||
|
|
|
|||
|
|
@ -299,6 +299,24 @@ do_vimba() {
|
|||
# and a non-numeric value makes the program refuse to start with a message about
|
||||
# a config key. Absent, it starts and reports the axis as undeclared - naming the
|
||||
# missing keys and which axis will not move, which is the useful failure.
|
||||
# The centre lives in config.ini, not here - it is calibration, and hardware.ini
|
||||
# is merged OVER config.ini, so a shared key would silently discard whatever
|
||||
# `gimbal heading setup` had saved. All this file can do is say what the value
|
||||
# has to be, which it can work out from the travel.
|
||||
#
|
||||
# The range is centre +/- half the travel, so a centre below half-travel puts the
|
||||
# negative end under zero. The long-standing 500000 default suits the Delta's
|
||||
# ~89k half-travel and does not survive a gear ratio several times higher.
|
||||
center_note() {
|
||||
local steps="$1" ax="$2"
|
||||
[[ -z $steps ]] && return 0
|
||||
local half=$(( steps / 2 ))
|
||||
local want=$(( (half / 1000000 + 1) * 1000000 ))
|
||||
echo "; NOTE: half this travel is $half counts, so config.ini needs"
|
||||
echo "; [Motor] ${ax}_center_count = $want (or anything above $half)"
|
||||
echo "; The 500000 default would put the negative end at $(( 500000 - half ))."
|
||||
}
|
||||
|
||||
kv_or_todo() {
|
||||
local key="$1" value="$2" why="$3"
|
||||
if [[ -n $value ]]; then
|
||||
|
|
@ -400,6 +418,7 @@ EOF
|
|||
"mechanical angle between the hard stops. Rough is fine to start; every bearing inherits its error proportionally until 'gimbal heading setup' supersedes it"
|
||||
kv_or_todo "steps_per_rev" "$STEPS_PER_REV" \
|
||||
"measured full travel IN COUNTS - read it off a homing run. The only guard against a PHANTOM endstop"
|
||||
center_note "$STEPS_PER_REV" "$ax"
|
||||
kv_or_todo "sw_mode" "$SW_MODE" \
|
||||
"TMC SW_MODE. 0 = no physical switches (StallGuard homing); set the bits if this axis has REFL/REFR wired"
|
||||
else
|
||||
|
|
|
|||
|
|
@ -88,4 +88,20 @@ struct DrivetrainEcho {
|
|||
CheckResult checkDrivetrainAdopted(const std::string& axis, const DrivetrainExpectation& want,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "fgc/CameraProfile.h"
|
||||
#include "fgc/AxisSpeed.h"
|
||||
#include "fgc/FirmwareConfig.h"
|
||||
#include "fgc/HardwareChecks.h"
|
||||
#include "fgc/HardwarePresence.h"
|
||||
#include "fgc/TmcCurrent.h"
|
||||
#include "fgc/ICameraSource.h"
|
||||
|
|
@ -1498,6 +1499,15 @@ struct Application::Impl {
|
|||
const long want_margin =
|
||||
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
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -184,4 +184,28 @@ CheckResult checkDeclaredValues(const std::string& axis, const DeclaredValue* va
|
|||
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
|
||||
|
|
|
|||
|
|
@ -174,3 +174,50 @@ TEST_CASE("a real mismatch alongside an absent field still names the mismatch")
|
|||
CHECK_FALSE(r.pass);
|
||||
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