diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index b76a4adf94..5d9bcc7158 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1662,6 +1662,37 @@ // Enable additional compensation using hotend temperature // Note: this values cannot be calibrated automatically but have to be set manually //#define USE_TEMP_EXT_COMPENSATION + + // Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START + // (e.g. 30), in steps of PTC_SAMPLE_RES (e.g. 5) with PTC_SAMPLE_COUNT (e.g. 10) samples. + + // #define PTC_SAMPLE_START 30.0f + // #define PTC_SAMPLE_RES 5.0f + // #define PTC_SAMPLE_COUNT 10U + + // Bed temperature calibration builds a similar table. + + // #define BTC_SAMPLE_START 60.0f + // #define BTC_SAMPLE_RES 5.0f + // #define BTC_SAMPLE_COUNT 10U + + // The temperature the probe should be at while taking measurements during bed temperature + // calibration. + // #define BTC_PROBE_TEMP 30.0f + + // Height above Z=0.0f to raise the nozzle. Lowering this can help the probe to heat faster. + // Note: the Z=0.0f offset is determined by the probe offset which can be set using M851. + // #define PTC_PROBE_HEATING_OFFSET 0.5f + + // Height to raise the Z-probe between heating and taking the next measurement. Some probes + // may fail to untrigger if they have been triggered for a long time, which can be solved by + // increasing the height the probe is raised to. + // #define PTC_PROBE_RAISE 15U + + // If the probe is outside of the defined range, use linear extrapolation using the closest + // point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0] + // and data[4] to perform linear extrapolation for values below PTC_SAMPLE_START. + // #define PTC_LINEAR_EXTRAPOLATION 4 #endif #endif diff --git a/Marlin/src/feature/probe_temp_comp.cpp b/Marlin/src/feature/probe_temp_comp.cpp index 92ff2e9771..c3459d2345 100644 --- a/Marlin/src/feature/probe_temp_comp.cpp +++ b/Marlin/src/feature/probe_temp_comp.cpp @@ -165,28 +165,41 @@ void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const float & } float ProbeTempComp::get_offset_for_temperature(const TempSensorID tsi, const float &temp) { - const uint8_t measurements = cali_info[tsi].measurements; const float start_temp = cali_info[tsi].start_temp, - end_temp = cali_info[tsi].end_temp, res_temp = cali_info[tsi].temp_res; const int16_t * const data = sensor_z_offsets[tsi]; - if (temp <= start_temp) return 0.0f; - if (temp >= end_temp) return static_cast(data[measurements - 1]) / 1000.0f; + auto point = [&](uint8_t i) { + return xy_float_t({start_temp + i*res_temp, static_cast(data[i])}); + }; + + auto linear_interp = [](float x, xy_float_t p1, xy_float_t p2) { + return (p2.y - p1.y) / (p2.x - p2.y) * (x - p1.x) + p1.y; + }; // Linear interpolation - int16_t val1 = 0, val2 = data[0]; - uint8_t idx = 0; - float meas_temp = start_temp + res_temp; - while (meas_temp < temp) { - if (++idx >= measurements) return static_cast(val2) / 1000.0f; - meas_temp += res_temp; - val1 = val2; - val2 = data[idx]; - } - const float factor = (meas_temp - temp) / static_cast(res_temp); - return (static_cast(val2) - static_cast(val2 - val1) * factor) / 1000.0f; + uint8_t idx = static_cast(temp - start_temp / res_temp); + + // offset in um + float offset = 0.0f; + + #if !defined(PTC_LINEAR_EXTRAPOLATION) || PTC_LINEAR_EXTRAPOLATION <= 0 + if (idx < 0) + offset = 0.0f; + else if (idx > measurements - 2) + offset = static_cast(data[measurements - 1]); + #else + if (idx < 0) + offset = linear_interp(temp, point(0), point(PTC_LINEAR_EXTRAPOLATION)); + else if (idx > measurements - 2) + offset = linear_interp(temp, point(measurements - PTC_LINEAR_EXTRAPOLATION - 1), point(measurements - 1)); + #endif + else + offset = linear_interp(temp, point(idx), point(idx + 1)); + + // return offset in mm + return offset / 1000.0f; } bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d) { diff --git a/Marlin/src/feature/probe_temp_comp.h b/Marlin/src/feature/probe_temp_comp.h index 5ae4175104..2562722d12 100644 --- a/Marlin/src/feature/probe_temp_comp.h +++ b/Marlin/src/feature/probe_temp_comp.h @@ -45,9 +45,44 @@ typedef struct { * measurement errors/shifts due to changed temperature. */ +// Probe temperature calibration constants +#ifndef PTC_SAMPLE_COUNT + #define PTC_SAMPLE_COUNT 10U +#endif +#ifndef PTC_SAMPLE_RES + #define PTC_SAMPLE_RES 5.0f +#endif +#ifndef PTC_SAMPLE_START + #define PTC_SAMPLE_START 30.0f +#endif +#define PTC_SAMPLE_END ((PTC_SAMPLE_START) + (PTC_SAMPLE_COUNT) * (PTC_SAMPLE_RES)) + +// Bed temperature calibration constants +#ifndef BTC_PROBE_TEMP + #define BTC_PROBE_TEMP 30.0f +#endif +#ifndef BTC_SAMPLE_COUNT + #define BTC_SAMPLE_COUNT 10U +#endif +#ifndef BTC_SAMPLE_STEP + #define BTC_SAMPLE_RES 5.0f +#endif +#ifndef BTC_SAMPLE_START + #define BTC_SAMPLE_START 60.0f +#endif +#define BTC_SAMPLE_END ((BTC_SAMPLE_START) + (BTC_SAMPLE_COUNT) * (BTC_SAMPLE_RES)) + +#ifndef PTC_PROBE_HEATING_OFFSET + #define PTC_PROBE_HEATING_OFFSET 0.5f +#endif + +#ifndef PTC_PROBE_RAISE + #define PTC_PROBE_RAISE 10.0f +#endif + static constexpr temp_calib_t cali_info_init[TSI_COUNT] = { - { 10, 5, 30, 30 + 10 * 5 }, // Probe - { 10, 5, 60, 60 + 10 * 5 }, // Bed + { PTC_SAMPLE_COUNT, PTC_SAMPLE_RES, PTC_SAMPLE_START, PTC_SAMPLE_END }, // Probe + { BTC_SAMPLE_COUNT, BTC_SAMPLE_RES, BTC_SAMPLE_START, BTC_SAMPLE_END }, // Bed #if ENABLED(USE_TEMP_EXT_COMPENSATION) { 20, 5, 180, 180 + 5 * 20 } // Extruder #endif @@ -66,7 +101,7 @@ class ProbeTempComp { //measure_point = { 12.0f, 7.3f }; // Coordinates for the MK52 magnetic heatbed static constexpr int probe_calib_bed_temp = BED_MAX_TARGET, // Bed temperature while calibrating probe - bed_calib_probe_temp = 30; // Probe temperature while calibrating bed + bed_calib_probe_temp = BTC_PROBE_TEMP; // Probe temperature while calibrating bed static int16_t *sensor_z_offsets[TSI_COUNT], z_offsets_probe[cali_info_init[TSI_PROBE].measurements], // (µm) diff --git a/Marlin/src/gcode/calibrate/G76_M871.cpp b/Marlin/src/gcode/calibrate/G76_M871.cpp index adabf22344..bc7aee8f4d 100644 --- a/Marlin/src/gcode/calibrate/G76_M871.cpp +++ b/Marlin/src/gcode/calibrate/G76_M871.cpp @@ -105,7 +105,7 @@ void GcodeSuite::G76() { auto g76_probe = [](const TempSensorID sid, uint16_t &targ, const xy_pos_t &nozpos) { do_blocking_move_to_z(5.0); // Raise nozzle before probing - const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_NONE, 0, false); // verbose=0, probe_relative=false + const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false); // verbose=0, probe_relative=false if (isnan(measured_z)) SERIAL_ECHOLNPGM("!Received NAN. Aborting."); else { @@ -132,8 +132,8 @@ void GcodeSuite::G76() { planner.synchronize(); const xyz_pos_t parkpos = temp_comp.park_point, - probe_pos_xyz = temp_comp.measure_point + xyz_pos_t({ 0.0f, 0.0f, 0.5f }), - noz_pos_xyz = probe_pos_xyz - probe.offset_xy; // Nozzle position based on probe position + probe_pos_xyz = xyz_pos_t(temp_comp.measure_point) + xyz_pos_t({ 0.0f, 0.0f, PTC_PROBE_HEATING_OFFSET }), + noz_pos_xyz = probe_pos_xyz - xy_pos_t(probe.offset_xy); // Nozzle position based on probe position if (do_bed_cal || do_probe_cal) { // Ensure park position is reachable