From 9a61167aa63d7099b2c65cbab66fd16c8767e36a Mon Sep 17 00:00:00 2001 From: pgdalmeida Date: Thu, 17 Sep 2026 17:58:46 +0200 Subject: [PATCH] Parse the motor current the firmware echoes back in DUMP --- include/fgc/DumpParser.h | 10 ++++++++++ src/core/DumpParser.cpp | 3 +++ tests/test_dumpparser.cpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/fgc/DumpParser.h b/include/fgc/DumpParser.h index 3503529..7cf0f84 100644 --- a/include/fgc/DumpParser.h +++ b/include/fgc/DumpParser.h @@ -21,6 +21,16 @@ struct DumpAxis { long center_count = 0; // count the firmware anchored the homed midpoint to long hold_target = 0; long speed = 0; + // Motor current, as the firmware believes it applied it. GLOBALSCALER and + // IHOLD_IRUN are write-only on the TMC5160, so this echo is the only way the + // host can confirm a CURRENT command landed. + // + // -1 means the field was absent, i.e. the firmware predates the command - + // which is a different thing from "applied a current of zero" and has to stay + // distinguishable, because one is a version skew and the other is a fault. + long global_scaler = -1; + long run_irun = -1; + long homing_irun = -1; // Encoder-tracking health accumulated by the firmware hold corrector. long hold_corrections = 0; // # of hold resyncs since firmware boot/RESET long hold_peak_dev = 0; // largest deviation seen while holding (counts) diff --git a/src/core/DumpParser.cpp b/src/core/DumpParser.cpp index 4b86962..235495b 100644 --- a/src/core/DumpParser.cpp +++ b/src/core/DumpParser.cpp @@ -162,6 +162,9 @@ DumpData parseDump(const std::string& block) { ax.center_count = asInt(get(m, "center", "0")); ax.hold_target = asInt(get(m, "hold_target", "0")); ax.speed = asInt(get(m, "speed", "0")); + ax.global_scaler = asInt(get(m, "gs", "-1")); + ax.run_irun = asInt(get(m, "irun", "-1")); + ax.homing_irun = asInt(get(m, "irun_home", "-1")); ax.hold_corrections = asInt(get(m, "hold_corr", "0")); ax.hold_peak_dev = asInt(get(m, "hold_peak", "0")); ax.hold_cumulative_dev = asInt(get(m, "hold_cumul", "0")); diff --git a/tests/test_dumpparser.cpp b/tests/test_dumpparser.cpp index 47837bf..4aca8c5 100644 --- a/tests/test_dumpparser.cpp +++ b/tests/test_dumpparser.cpp @@ -136,3 +136,32 @@ TEST_CASE("formatDump renders valid and invalid dumps") { CHECK(joined.find("[P]") != std::string::npos); CHECK(joined.find("RAMP_STAT") != std::string::npos); } + +TEST_CASE("a DUMP axis line carries the motor current the firmware applied") { + auto d = parseDump( + "DUMP BEGIN build=abc uptime=1 mcusr=0x3 free_ram=100\n" + "DUMP Y state=3 hsub=0 enabled=1 lim_neg=-105389 lim_pos=1105389 hold_target=0 " + "speed=3000 center=500000 soft_margin=5000 gs=80 irun=31 irun_home=7 " + "hold_corr=0 hold_peak=0 hold_cumul=0 has_encoder=1\n" + "DUMP END\n"); + REQUIRE(d.valid); + REQUIRE(d.axes.size() == 1); + CHECK(d.axes[0].global_scaler == 80); + CHECK(d.axes[0].run_irun == 31); + CHECK(d.axes[0].homing_irun == 7); +} + +TEST_CASE("a DUMP from firmware without the current fields reports -1, not zero") { + // Zero is a legitimate IRUN; absent is a version skew. Conflating them would + // let an old firmware look like one configured to zero current. + auto d = parseDump( + "DUMP BEGIN build=abc uptime=1 mcusr=0x3 free_ram=100\n" + "DUMP Y state=3 hsub=0 enabled=1 lim_neg=0 lim_pos=0 hold_target=0 speed=3000 " + "center=500000 soft_margin=5000 hold_corr=0 hold_peak=0 hold_cumul=0 has_encoder=1\n" + "DUMP END\n"); + REQUIRE(d.valid); + REQUIRE(d.axes.size() == 1); + CHECK(d.axes[0].global_scaler == -1); + CHECK(d.axes[0].run_irun == -1); + CHECK(d.axes[0].homing_irun == -1); +}