From 1445c2eeccb6e8efe718d6358f4826ca683a1af5 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 28 Jan 2023 18:14:34 +0100 Subject: [PATCH 01/11] Backport eeprom functions from 3.13 --- Firmware/eeprom.cpp | 191 ++++++++++++++++++++++++++++---------------- Firmware/eeprom.h | 21 ++++- 2 files changed, 140 insertions(+), 72 deletions(-) diff --git a/Firmware/eeprom.cpp b/Firmware/eeprom.cpp index baa2058fb..347ebbfa3 100644 --- a/Firmware/eeprom.cpp +++ b/Firmware/eeprom.cpp @@ -11,57 +11,22 @@ #include "language.h" -#if 0 -template -static T eeprom_read(T *address); - -template<> -char eeprom_read(char *address) -{ - return eeprom_read_byte(reinterpret_cast(address)); -} -#endif - -template -static void eeprom_write(T *address, T value); - -template<> -void eeprom_write(char *addres, char value) -{ - eeprom_write_byte(reinterpret_cast(addres), static_cast(value)); -} - - -template -static bool eeprom_is_uninitialized(T *address); - -template <> -bool eeprom_is_uninitialized(char *address) -{ - return (0xff == eeprom_read_byte(reinterpret_cast(address))); -} - -bool eeprom_is_sheet_initialized(uint8_t sheet_num) -{ - return (0xffff != eeprom_read_word(reinterpret_cast(&(EEPROM_Sheets_base-> - s[sheet_num].z_offset)))); -} - void eeprom_init() { - if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0); - if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0); - if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0); - if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_POWER_COUNT, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_FERROR_COUNT, 0); + eeprom_init_default_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0); + eeprom_init_default_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0); + eeprom_init_default_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0); + eeprom_init_default_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0); - if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0); - if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0); - if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0); + eeprom_init_default_word((uint16_t*)EEPROM_MMU_FAIL_TOT, 0); + eeprom_init_default_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_MMU_FAIL, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL, 0); + eeprom_init_default_dword((uint32_t*)EEPROM_TOTAL_TOOLCHANGE_COUNT, 0); if (eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)) == EEPROM_EMPTY_VALUE) { eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), 0); @@ -71,23 +36,13 @@ void eeprom_init() eeprom_update_word(reinterpret_cast(&(EEPROM_Sheets_base->s[0].z_offset)), last_babystep); } - for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); ++i) - { - bool is_uninitialized = true; - for (uint_least8_t j = 0; j < (sizeof(Sheet::name)/sizeof(Sheet::name[0])); ++j) - { - if (!eeprom_is_uninitialized(&(EEPROM_Sheets_base->s[i].name[j]))) is_uninitialized = false; - } - if(is_uninitialized) - { - SheetName sheetName; - eeprom_default_sheet_name(i,sheetName); - - for (uint_least8_t a = 0; a < sizeof(Sheet::name); ++a){ - eeprom_write(&(EEPROM_Sheets_base->s[i].name[a]), sheetName.c[a]); - } - } + // initialize the sheet names in eeprom + for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); i++) { + SheetName sheetName; + eeprom_default_sheet_name(i, sheetName); + eeprom_init_default_block(EEPROM_Sheets_base->s[i].name, (sizeof(Sheet::name)/sizeof(Sheet::name[0])), sheetName.c); } + if(!eeprom_is_sheet_initialized(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))) { eeprom_switch_to_next_sheet(); @@ -95,16 +50,16 @@ void eeprom_init() check_babystep(); #ifdef PINDA_TEMP_COMP -if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_PINDA_TEMP_COMPENSATION, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION, 0); #endif //PINDA_TEMP_COMP - if (eeprom_read_dword((uint32_t*)EEPROM_JOB_ID) == EEPROM_EMPTY_VALUE32) - eeprom_update_dword((uint32_t*)EEPROM_JOB_ID, 0); + eeprom_init_default_dword((uint32_t*)EEPROM_JOB_ID, 0); + eeprom_init_default_dword((uint32_t*)EEPROM_TOTALTIME, 0); + eeprom_init_default_dword((uint32_t*)EEPROM_FILAMENTUSED, 0); + eeprom_init_default_byte((uint8_t*)EEPROM_MMU_CUTTER_ENABLED, 0); + + eeprom_init_default_byte((uint8_t*)EEPROM_HEAT_BED_ON_LOAD_FILAMENT, 1); - if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255) { - eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0); - eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0); - } } //! @brief Get default sheet name for index @@ -178,3 +133,97 @@ void eeprom_switch_to_next_sheet() sheet = eeprom_next_initialized_sheet(sheet); if (sheet >= 0) eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), sheet); } + +bool __attribute__((noinline)) eeprom_is_sheet_initialized(uint8_t sheet_num) { + return (eeprom_read_word(reinterpret_cast(&(EEPROM_Sheets_base->s[sheet_num].z_offset))) != EEPROM_EMPTY_VALUE16); +} + + +bool __attribute__((noinline)) eeprom_is_initialized_block(const void *__p, size_t __n) { + const uint8_t *p = (const uint8_t*)__p; + while (__n--) { + if (eeprom_read_byte(p++) != EEPROM_EMPTY_VALUE) + return true; + } + return false; +} + +void eeprom_update_block_P(const void *__src, void *__dst, size_t __n) { + const uint8_t *src = (const uint8_t*)__src; + uint8_t *dst = (uint8_t*)__dst; + while (__n--) { + eeprom_update_byte(dst++, pgm_read_byte(src++)); + } +} + +void eeprom_toggle(uint8_t *__p) { + eeprom_write_byte(__p, !eeprom_read_byte(__p)); +} + +void __attribute__((noinline)) eeprom_increment_byte(uint8_t *__p) { + eeprom_write_byte(__p, eeprom_read_byte(__p) + 1); +} + +void __attribute__((noinline)) eeprom_increment_word(uint16_t *__p) { + eeprom_write_word(__p, eeprom_read_word(__p) + 1); +} + +void __attribute__((noinline)) eeprom_increment_dword(uint32_t *__p) { + eeprom_write_dword(__p, eeprom_read_dword(__p) + 1); +} + + +void __attribute__((noinline)) eeprom_add_byte(uint8_t *__p, uint8_t add) { + eeprom_write_byte(__p, eeprom_read_byte(__p) + add); +} + +void __attribute__((noinline)) eeprom_add_word(uint16_t *__p, uint16_t add) { + eeprom_write_word(__p, eeprom_read_word(__p) + add); +} + +void __attribute__((noinline)) eeprom_add_dword(uint32_t *__p, uint32_t add) { + eeprom_write_dword(__p, eeprom_read_dword(__p) + add); +} + + +uint8_t __attribute__((noinline)) eeprom_init_default_byte(uint8_t *__p, uint8_t def) { + uint8_t val = eeprom_read_byte(__p); + if (val == EEPROM_EMPTY_VALUE) { + eeprom_write_byte(__p, def); + return def; + } + return val; +} + +uint16_t __attribute__((noinline)) eeprom_init_default_word(uint16_t *__p, uint16_t def) { + uint16_t val = eeprom_read_word(__p); + if (val == EEPROM_EMPTY_VALUE16) { + eeprom_write_word(__p, def); + return def; + } + return val; +} + +uint32_t __attribute__((noinline)) eeprom_init_default_dword(uint32_t *__p, uint32_t def) { + uint32_t val = eeprom_read_dword(__p); + if (val == EEPROM_EMPTY_VALUE32) { + eeprom_write_dword(__p, def); + return def; + } + return val; +} + +void __attribute__((noinline)) eeprom_init_default_float(float *__p, float def) { + if (eeprom_read_dword((uint32_t*)__p) == EEPROM_EMPTY_VALUE32) + eeprom_write_float(__p, def); +} + +void __attribute__((noinline)) eeprom_init_default_block(void *__p, size_t __n, const void *def) { + if (!eeprom_is_initialized_block(__p, __n)) + eeprom_update_block(def, __p, __n); +} + +void __attribute__((noinline)) eeprom_init_default_block_P(void *__p, size_t __n, const void *def) { + if (!eeprom_is_initialized_block(__p, __n)) + eeprom_update_block_P(def, __p, __n); +} diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 0761ed3b4..5efcf6eeb 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -620,7 +620,6 @@ enum #ifdef __cplusplus void eeprom_init(); -bool eeprom_is_sheet_initialized(uint8_t sheet_num); struct SheetName { char c[sizeof(Sheet::name) + 1]; @@ -628,6 +627,26 @@ struct SheetName void eeprom_default_sheet_name(uint8_t index, SheetName &sheetName); int8_t eeprom_next_initialized_sheet(int8_t sheet); void eeprom_switch_to_next_sheet(); +bool eeprom_is_sheet_initialized(uint8_t sheet_num); + +bool eeprom_is_initialized_block(const void *__p, size_t __n); +void eeprom_update_block_P(const void *__src, void *__dst, size_t __n); +void eeprom_toggle(uint8_t *__p); + +void eeprom_increment_byte(uint8_t *__p); +void eeprom_increment_word(uint16_t *__p); +void eeprom_increment_dword(uint32_t *__p); + +void eeprom_add_byte(uint8_t *__p, uint8_t add); +void eeprom_add_word(uint16_t *__p, uint16_t add); +void eeprom_add_dword(uint32_t *__p, uint32_t add); + +uint8_t eeprom_init_default_byte(uint8_t *__p, uint8_t def); +uint16_t eeprom_init_default_word(uint16_t *__p, uint16_t def); +uint32_t eeprom_init_default_dword(uint32_t *__p, uint32_t def); +void eeprom_init_default_float(float *__p, float def); +void eeprom_init_default_block(void *__p, size_t __n, const void *def); +void eeprom_init_default_block_P(void *__p, size_t __n, const void *def); #endif #endif // EEPROM_H From 5a1ed1519cc11707f3fd03789abc50de45d55afe Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 26 Jan 2023 22:08:00 +0100 Subject: [PATCH 02/11] TM: Allocate new eeprom parameters for PTC handling --- Firmware/eeprom.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 5efcf6eeb..6380225b9 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -357,6 +357,10 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 20h 32 | ^ | Free bit | ^ | ^ | ^ | ^ | ^ | 40h 64 | ^ | Free bit | ^ | ^ | ^ | ^ | ^ | 80h 128 | ^ | Unknown | ^ | ^ +| 0x0CA5 3237 | float | EEPROM_TEMP_MODEL_U | ??? | ff ff ff ffh | Temp model linear temperature coefficient (W/K/W) | Temp model | D3 Ax0ca5 C4 +| 0x0CA1 3233 | float | EEPROM_TEMP_MODEL_V | ??? | ff ff ff ffh | Temp model linear temperature intercept (W/W) | Temp model | D3 Ax0ca1 C4 +| 0x0C9D 3229 | float | EEPROM_TEMP_MODEL_D | ??? | ff ff ff ffh | Temp model sim. 1st order IIR filter factor | Temp model | D3 Ax0c9d C4 +| 0x0C99 3225 | uint16 | EEPROM_TEMP_MODEL_L | 0-2160 | ff ffh | Temp model sim. response lag (ms) | Temp model | D3 Ax0c99 C2 |Address begin|Bit/Type | Name | Valid values | Default/FactoryReset | Description |Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: @@ -586,8 +590,13 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_HEAT_BED_ON_LOAD_FILAMENT (EEPROM_TOTAL_TOOLCHANGE_COUNT-1) //uint8 #define EEPROM_CALIBRATION_STATUS_V2 (EEPROM_HEAT_BED_ON_LOAD_FILAMENT-1) //uint8 +#define EEPROM_TEMP_MODEL_U (EEPROM_CALIBRATION_STATUS_V2-4) //float +#define EEPROM_TEMP_MODEL_V (EEPROM_TEMP_MODEL_U-4) //float +#define EEPROM_TEMP_MODEL_D (EEPROM_TEMP_MODEL_V-4) //float +#define EEPROM_TEMP_MODEL_L (EEPROM_TEMP_MODEL_D-2) //uint16_t + //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_CALIBRATION_STATUS_V2 +#define EEPROM_LAST_ITEM EEPROM_TEMP_MODEL_L // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! From 70fd9a336b4f46dcdea1ed91a14b0c0e400de1d6 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 26 Jan 2023 22:18:09 +0100 Subject: [PATCH 03/11] TM: Handle UVDL set/load/report/upgrade - Expose TEMP_MODEL_fS and TEMP_MODEL_LAG as D and L respectively, initializing the default values based on the previous hard-coded values. - Always round L to the effective sample lag to future-proof model upgrades or changes (the stored value _is_ the effective value). - Introduce UV as a new linear term for PTC heaters, defaulting to an identity for model backward-compatibility. --- Firmware/Marlin_main.cpp | 33 +++++++++----- Firmware/temp_model.h | 15 ++++--- Firmware/temperature.cpp | 43 ++++++++++++++++--- Firmware/temperature.h | 3 +- .../variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 7 ++- .../variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 7 ++- 6 files changed, 82 insertions(+), 26 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index a4634e10f..d6ac4f518 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -7586,7 +7586,8 @@ Sigma_Exit: M310 [ A ] [ F ] ; autotune M310 [ S ] ; set 0=disable 1=enable M310 [ I ] [ R ] ; set resistance at index - M310 [ P | C ] ; set power, capacitance + M310 [ P | U | V | C ] ; set power, temperature coefficient, intercept, capacitance + M310 [ D | L ] ; set simulation filter, lag M310 [ B | E | W ] ; set beeper, warning and error threshold M310 [ T ] ; set ambient temperature correction @@ -7594,7 +7595,11 @@ Sigma_Exit: - `I` - resistance index position (0-15) - `R` - resistance value at index (K/W; requires `I`) - `P` - power (W) + - `U` - linear temperature coefficient (W/K/power) + - `V` - linear temperature intercept (W/power) - `C` - capacitance (J/K) + - `D` - sim. 1st order IIR filter factor (f=100/27) + - `L` - sim. response lag (ms, 0-2160) - `S` - set 0=disable 1=enable - `B` - beep and warn when reaching warning threshold 0=disable 1=enable (default: 1) - `E` - error threshold (K/s; default in variant) @@ -7606,31 +7611,39 @@ Sigma_Exit: case 310: { // parse all parameters - float P = NAN, C = NAN, R = NAN, E = NAN, W = NAN, T = NAN; + float R = NAN, P = NAN, U = NAN, V = NAN, C = NAN, D = NAN, T = NAN, W = NAN, E = NAN; int8_t I = -1, S = -1, B = -1, F = -1; - int16_t A = -1; - if(code_seen('C')) C = code_value(); - if(code_seen('P')) P = code_value(); + int16_t A = -1, L = -1; if(code_seen('I')) I = code_value_short(); if(code_seen('R')) R = code_value(); + if(code_seen('P')) P = code_value(); + if(code_seen('U')) U = code_value(); + if(code_seen('V')) V = code_value(); + if(code_seen('C')) C = code_value(); + if(code_seen('D')) D = code_value(); + if(code_seen('L')) L = code_value_short(); if(code_seen('S')) S = code_value_short(); if(code_seen('B')) B = code_value_short(); + if(code_seen('T')) T = code_value(); if(code_seen('E')) E = code_value(); if(code_seen('W')) W = code_value(); - if(code_seen('T')) T = code_value(); if(code_seen('A')) A = code_value_short(); if(code_seen('F')) F = code_value_short(); // report values if nothing has been requested - if(isnan(C) && isnan(P) && isnan(R) && isnan(E) && isnan(W) && isnan(T) && I < 0 && S < 0 && B < 0 && A < 0) { + if(isnan(R) && isnan(P) && isnan(U) && isnan(V) && isnan(C) && isnan(D) && isnan(T) && isnan(W) && isnan(E) + && I < 0 && S < 0 && B < 0 && A < 0 && L < 0) { temp_model_report_settings(); break; } // update all parameters - if(B >= 0) temp_model_set_warn_beep(B); - if(!isnan(C) || !isnan(P) || !isnan(T) || !isnan(W) || !isnan(E)) temp_model_set_params(C, P, T, W, E); - if(I >= 0 && !isnan(R)) temp_model_set_resistance(I, R); + if(B >= 0) + temp_model_set_warn_beep(B); + if(!isnan(P) || !isnan(U) || !isnan(V) || !isnan(C) || !isnan(D) || (L >= 0) || !isnan(T) || !isnan(W) || !isnan(E)) + temp_model_set_params(P, U, V, C, D, L, T, W, E); + if(I >= 0 && !isnan(R)) + temp_model_set_resistance(I, R); // enable the model last, if requested if(S >= 0) temp_model_set_enabled(S); diff --git a/Firmware/temp_model.h b/Firmware/temp_model.h index 492781fd1..97eb5b3ba 100644 --- a/Firmware/temp_model.h +++ b/Firmware/temp_model.h @@ -7,11 +7,10 @@ constexpr uint8_t TEMP_MODEL_CAL_S = 60; // Maximum recording lenght during calibration (s) constexpr uint8_t TEMP_MODEL_CAL_R_STEP = 4; // Fan interpolation steps during calibration -constexpr float TEMP_MODEL_fS = 0.065; // simulation filter (1st-order IIR factor) constexpr float TEMP_MODEL_fE = 0.05; // error filter (1st-order IIR factor) // transport delay buffer size (samples) -constexpr uint8_t TEMP_MODEL_LAG_SIZE = (TEMP_MODEL_LAG / TEMP_MGR_INTV + 0.5); +constexpr uint8_t TEMP_MODEL_MAX_LAG_SIZE = 8; // * TEMP_MGR_INTV = 2160 // resistance values for all fan levels constexpr uint8_t TEMP_MODEL_R_SIZE = (1 << FAN_SOFT_PWM_BITS); @@ -22,14 +21,18 @@ namespace temp_model { struct model_data { // temporary buffers - float dT_lag_buf[TEMP_MODEL_LAG_SIZE]; // transport delay buffer - uint8_t dT_lag_idx = 0; // transport delay buffer index - float dT_err_prev = 0; // previous temperature delta error - float T_prev = 0; // last temperature extruder + float dT_lag_buf[TEMP_MODEL_MAX_LAG_SIZE]; // transport delay buffer + uint8_t dT_lag_idx = 0; // transport delay buffer index + float dT_err_prev = 0; // previous temperature delta error + float T_prev = 0; // last temperature extruder // configurable parameters float P; // heater power (W) + float U; // linear temperature coefficient (W/K/W) + float V; // linear temperature intercept (W/W) float C; // heatblock capacitance (J/K) + float fS; // sim. 1st order IIR filter factor (f=100/27) + uint16_t L; // sim. response lag (ms) float R[TEMP_MODEL_R_SIZE]; // heatblock resistance for all fan levels (K/W) float Ta_corr; // ambient temperature correction (K) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index cf3f9364d..f7995c1f8 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2540,15 +2540,27 @@ void temp_model_set_warn_beep(bool enabled) temp_model::warn_beep = enabled; } -void temp_model_set_params(float C, float P, float Ta_corr, float warn, float err) +// set the model lag rounding to the effective sample resolution, ensuring the reported/stored lag +// matches the current model constraints (future-proofing for model changes) +static void temp_model_set_lag(uint16_t ms) +{ + static const uint16_t intv_ms = (uint16_t)(TEMP_MGR_INTV * 1000); + temp_model::data.L = ((ms + intv_ms/2) / intv_ms) * intv_ms; +} + +void temp_model_set_params(float P, float U, float V, float C, float D, int16_t L, float Ta_corr, float warn, float err) { TempMgrGuard temp_mgr_guard; - if(!isnan(C) && C > 0) temp_model::data.C = C; if(!isnan(P) && P > 0) temp_model::data.P = P; + if(!isnan(U)) temp_model::data.U = U; + if(!isnan(V)) temp_model::data.V = V; + if(!isnan(C) && C > 0) temp_model::data.C = C; + if(!isnan(D)) temp_model::data.fS = D; + if(L >= 0) temp_model_set_lag(L); if(!isnan(Ta_corr)) temp_model::data.Ta_corr = Ta_corr; - if(!isnan(err) && err > 0) temp_model::data.err = err; if(!isnan(warn) && warn > 0) temp_model::data.warn = warn; + if(!isnan(err) && err > 0) temp_model::data.err = err; // ensure warn <= err if (temp_model::data.warn > temp_model::data.err) @@ -2573,8 +2585,9 @@ void temp_model_report_settings() SERIAL_ECHOLNPGM("Temperature Model settings:"); for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) printf_P(PSTR("%S M310 I%u R%.2f\n"), echomagic, (unsigned)i, (double)temp_model::data.R[i]); - printf_P(PSTR("%S M310 P%.2f C%.2f S%u B%u E%.2f W%.2f T%.2f\n"), - echomagic, (double)temp_model::data.P, (double)temp_model::data.C, + printf_P(PSTR("%S M310 P%.2f U%.4f V%.2f C%.2f D%.4f L%u S%u B%u E%.2f W%.2f T%.2f\n"), + echomagic, (double)temp_model::data.P, (double)temp_model::data.U, (double)temp_model::data.V, + (double)temp_model::data.C, (double)temp_model::data.fS, (unsigned)temp_model::data.L, (unsigned)temp_model::enabled, (unsigned)temp_model::warn_beep, (double)temp_model::data.err, (double)temp_model::data.warn, (double)temp_model::data.Ta_corr); @@ -2585,7 +2598,11 @@ void temp_model_reset_settings() TempMgrGuard temp_mgr_guard; temp_model::data.P = TEMP_MODEL_P; + temp_model::data.U = TEMP_MODEL_U; + temp_model::data.V = TEMP_MODEL_V; temp_model::data.C = TEMP_MODEL_C; + temp_model::data.fS = TEMP_MODEL_fS; + temp_model::data.L = (uint16_t)(TEMP_MODEL_LAG / (TEMP_MGR_INTV * 1000) + 0.5) * (uint16_t)(TEMP_MGR_INTV * 1000); for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) temp_model::data.R[i] = pgm_read_float(TEMP_MODEL_R_DEFAULT + i); temp_model::data.Ta_corr = TEMP_MODEL_Ta_corr; @@ -2601,9 +2618,21 @@ void temp_model_load_settings() static_assert(TEMP_MODEL_R_SIZE == 16); // ensure we don't desync with the eeprom table TempMgrGuard temp_mgr_guard; + // handle upgrade from a model without UVDL (FW<3.13) + // WARNING: this only works as long as UVDL are the same constants/model type as FW 3.12, + // it needs to consider the upgrading FW version otherwise! + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_U, TEMP_MODEL_U); + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_V, TEMP_MODEL_V); + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_D, TEMP_MODEL_fS); + eeprom_init_default_word((uint16_t*)EEPROM_TEMP_MODEL_L, TEMP_MODEL_LAG); + temp_model::enabled = eeprom_read_byte((uint8_t*)EEPROM_TEMP_MODEL_ENABLE); temp_model::data.P = eeprom_read_float((float*)EEPROM_TEMP_MODEL_P); + temp_model::data.U = eeprom_read_float((float*)EEPROM_TEMP_MODEL_U); + temp_model::data.V = eeprom_read_float((float*)EEPROM_TEMP_MODEL_V); temp_model::data.C = eeprom_read_float((float*)EEPROM_TEMP_MODEL_C); + temp_model::data.fS = eeprom_read_float((float*)EEPROM_TEMP_MODEL_D); + temp_model_set_lag(eeprom_read_word((uint16_t*)EEPROM_TEMP_MODEL_L)); for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) temp_model::data.R[i] = eeprom_read_float((float*)EEPROM_TEMP_MODEL_R + i); temp_model::data.Ta_corr = eeprom_read_float((float*)EEPROM_TEMP_MODEL_Ta_corr); @@ -2621,7 +2650,11 @@ void temp_model_save_settings() { eeprom_update_byte((uint8_t*)EEPROM_TEMP_MODEL_ENABLE, temp_model::enabled); eeprom_update_float((float*)EEPROM_TEMP_MODEL_P, temp_model::data.P); + eeprom_update_float((float*)EEPROM_TEMP_MODEL_U, temp_model::data.U); + eeprom_update_float((float*)EEPROM_TEMP_MODEL_V, temp_model::data.V); eeprom_update_float((float*)EEPROM_TEMP_MODEL_C, temp_model::data.C); + eeprom_update_float((float*)EEPROM_TEMP_MODEL_D, temp_model::data.fS); + eeprom_update_word((uint16_t*)EEPROM_TEMP_MODEL_L, temp_model::data.L); for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) eeprom_update_float((float*)EEPROM_TEMP_MODEL_R + i, temp_model::data.R[i]); eeprom_update_float((float*)EEPROM_TEMP_MODEL_Ta_corr, temp_model::data.Ta_corr); diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 03629db13..7e608e234 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -220,7 +220,8 @@ void PID_autotune(float temp, int extruder, int ncycles); bool temp_model_enabled(); // return temperature model state void temp_model_set_enabled(bool enabled); void temp_model_set_warn_beep(bool enabled); -void temp_model_set_params(float C = NAN, float P = NAN, float Ta_corr = NAN, float warn = NAN, float err = NAN); +void temp_model_set_params(float P=NAN, float U=NAN, float V=NAN, float C=NAN, float D=NAN, + int16_t L=-1, float Ta_corr=NAN, float warn=NAN, float err=NAN); void temp_model_set_resistance(uint8_t index, float R); void temp_model_report_settings(); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index df08de9ef..40dcb929a 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -415,6 +415,8 @@ #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) +#define TEMP_MODEL_U 1. // linear temperature coefficient (W/K/power) +#define TEMP_MODEL_V 0. // linear temperature intercept (W/power) #define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) #define TEMP_MODEL_Cl 5 // C estimation lower limit @@ -422,6 +424,9 @@ #define TEMP_MODEL_C_thr 0.01 // C estimation iteration threshold #define TEMP_MODEL_C_itr 30 // C estimation iteration limit +#define TEMP_MODEL_fS 0.065 // sim. 1st order IIR filter factor (f=100/27) +#define TEMP_MODEL_LAG 2100 // sim. response lag (ms, 0-2160) + #define TEMP_MODEL_R 20.5 // initial guess for heatblock resistance (K/W) #define TEMP_MODEL_Rl 5 // R estimation lower limit #define TEMP_MODEL_Rh 50 // R estimation upper limit @@ -429,8 +434,6 @@ #define TEMP_MODEL_R_itr 30 // R estimation iteration limit #define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_LAG 2.1 // Temperature transport delay (s) - #define TEMP_MODEL_W 1.2 // Default warning threshold (K/s) #define TEMP_MODEL_E 1.74 // Default error threshold (K/s) diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index af6ffa3b8..f5d6d2f8e 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -419,6 +419,8 @@ #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) +#define TEMP_MODEL_U 1. // linear temperature coefficient (W/K/power) +#define TEMP_MODEL_V 0. // linear temperature intercept (W/power) #define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) #define TEMP_MODEL_Cl 5 // C estimation lower limit @@ -426,6 +428,9 @@ #define TEMP_MODEL_C_thr 0.01 // C estimation iteration threshold #define TEMP_MODEL_C_itr 30 // C estimation iteration limit +#define TEMP_MODEL_fS 0.065 // sim. 1st order IIR filter factor (f=100/27) +#define TEMP_MODEL_LAG 2100 // sim. response lag (ms, 0-2160) + #define TEMP_MODEL_R 20.5 // initial guess for heatblock resistance (K/W) #define TEMP_MODEL_Rl 5 // R estimation lower limit #define TEMP_MODEL_Rh 50 // R estimation upper limit @@ -433,8 +438,6 @@ #define TEMP_MODEL_R_itr 30 // R estimation iteration limit #define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_LAG 2.1 // Temperature transport delay (s) - #define TEMP_MODEL_W 1.2 // Default warning threshold (K/s) #define TEMP_MODEL_E 1.74 // Default error threshold (K/s) From 02775fb79e8edb9ffca21d4c8680d0b9965d12a9 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 26 Jan 2023 22:25:00 +0100 Subject: [PATCH 04/11] TM: Handle D/TEMP_MODEL_fS --- Firmware/temperature.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index f7995c1f8..832ee1868 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2356,7 +2356,7 @@ void model_data::step(uint8_t heater_pwm, uint8_t fan_pwm, float heater_temp, fl uint8_t dT_next_idx = (dT_lag_idx == (TEMP_MODEL_LAG_SIZE - 1) ? 0: dT_lag_idx + 1); float dT_lag = dT_lag_buf[dT_next_idx]; float dT_lag_prev = dT_lag_buf[dT_lag_idx]; - float dT_f = iir_mul(dT_lag_prev, dT, TEMP_MODEL_fS, dT); + float dT_f = iir_mul(dT_lag_prev, dT, fS, dT); dT_lag_buf[dT_next_idx] = dT_f; dT_lag_idx = dT_next_idx; @@ -2389,6 +2389,7 @@ static bool calibrated() { if(!(data.P > 0)) return false; if(!(data.C > 0)) return false; + if(isnan(data.fS)) return false; if(!(data.Ta_corr != NAN)) return false; for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) { if(!(temp_model::data.R[i] >= 0)) From e147fc2cb000d80c5bafb511ac4924b50e7c560f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 26 Jan 2023 22:45:16 +0100 Subject: [PATCH 05/11] TM: Handle UV (PTC loss) Model UV as power-invariant, so that scaling P doesn't change the intercept location (that is, the zero point remains at the same temperature even for more powerful heaters). NOTE: It's not clear to me whether this is generally true (couldn't find a datasheet from the same heater in diffent power variants showing the efficiency loss) --- Firmware/temperature.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 832ee1868..06aa5da27 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2349,6 +2349,7 @@ void model_data::step(uint8_t heater_pwm, uint8_t fan_pwm, float heater_temp, fl const float cur_R = R[fan_pwm]; // resistance at current fan power (K/W) float dP = P * heater_scale; // current power [W] + dP *= (cur_heater_temp * U) + V; // linear temp. correction float dPl = (cur_heater_temp - cur_ambient_temp) / cur_R; // [W] leakage power float dT = (dP - dPl) * C_i; // expected temperature difference (K) @@ -2388,6 +2389,8 @@ static void setup() static bool calibrated() { if(!(data.P > 0)) return false; + if(isnan(data.U)) return false; + if(isnan(data.V)) return false; if(!(data.C > 0)) return false; if(isnan(data.fS)) return false; if(!(data.Ta_corr != NAN)) return false; From b7961ae0e9afa68df54b4083712cee0bc2adc8c8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 26 Jan 2023 23:12:06 +0100 Subject: [PATCH 06/11] TM: Handle L/TEMP_MODEL_LAG --- Firmware/temp_model.h | 1 + Firmware/temperature.cpp | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Firmware/temp_model.h b/Firmware/temp_model.h index 97eb5b3ba..15d85d512 100644 --- a/Firmware/temp_model.h +++ b/Firmware/temp_model.h @@ -22,6 +22,7 @@ struct model_data { // temporary buffers float dT_lag_buf[TEMP_MODEL_MAX_LAG_SIZE]; // transport delay buffer + uint8_t dT_lag_size = 0; // transport delay buffer size uint8_t dT_lag_idx = 0; // transport delay buffer index float dT_err_prev = 0; // previous temperature delta error float T_prev = 0; // last temperature extruder diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 06aa5da27..12f626bd5 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2320,9 +2320,10 @@ void model_data::reset(uint8_t heater_pwm _UNUSED, uint8_t fan_pwm _UNUSED, C_i = (TEMP_MGR_INTV / C); warn_s = warn * TEMP_MGR_INTV; err_s = err * TEMP_MGR_INTV; + dT_lag_size = L / (uint16_t)(TEMP_MGR_INTV * 1000); // initial values - for(uint8_t i = 0; i != TEMP_MODEL_LAG_SIZE; ++i) + for(uint8_t i = 0; i != TEMP_MODEL_MAX_LAG_SIZE; ++i) dT_lag_buf[i] = NAN; dT_lag_idx = 0; dT_err_prev = 0; @@ -2354,7 +2355,7 @@ void model_data::step(uint8_t heater_pwm, uint8_t fan_pwm, float heater_temp, fl float dT = (dP - dPl) * C_i; // expected temperature difference (K) // filter and lag dT - uint8_t dT_next_idx = (dT_lag_idx == (TEMP_MODEL_LAG_SIZE - 1) ? 0: dT_lag_idx + 1); + uint8_t dT_next_idx = (dT_lag_idx == (dT_lag_size - 1) ? 0: dT_lag_idx + 1); float dT_lag = dT_lag_buf[dT_next_idx]; float dT_lag_prev = dT_lag_buf[dT_lag_idx]; float dT_f = iir_mul(dT_lag_prev, dT, fS, dT); @@ -2393,6 +2394,7 @@ static bool calibrated() if(isnan(data.V)) return false; if(!(data.C > 0)) return false; if(isnan(data.fS)) return false; + if(!(data.L > 0)) return false; if(!(data.Ta_corr != NAN)) return false; for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) { if(!(temp_model::data.R[i] >= 0)) @@ -2550,6 +2552,14 @@ static void temp_model_set_lag(uint16_t ms) { static const uint16_t intv_ms = (uint16_t)(TEMP_MGR_INTV * 1000); temp_model::data.L = ((ms + intv_ms/2) / intv_ms) * intv_ms; + + // ensure there is at least one lag sample for filtering + if(temp_model::data.L < intv_ms) + temp_model::data.L = intv_ms; + + // do not exceed the maximum lag buffer + if(temp_model::data.L > (intv_ms * TEMP_MODEL_MAX_LAG_SIZE)) + temp_model::data.L = intv_ms * TEMP_MODEL_MAX_LAG_SIZE; } void temp_model_set_params(float P, float U, float V, float C, float D, int16_t L, float Ta_corr, float warn, float err) From 6d51752ac81bb35ac75f779c2733469060f14faf Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sat, 28 Jan 2023 14:30:09 +0100 Subject: [PATCH 07/11] TM: Optimize temp_model_set_lag Save about 20 bytes by rewriting the sample count check --- Firmware/temperature.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 12f626bd5..fafbffa33 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2551,15 +2551,16 @@ void temp_model_set_warn_beep(bool enabled) static void temp_model_set_lag(uint16_t ms) { static const uint16_t intv_ms = (uint16_t)(TEMP_MGR_INTV * 1000); - temp_model::data.L = ((ms + intv_ms/2) / intv_ms) * intv_ms; + uint16_t samples = ((ms + intv_ms/2) / intv_ms); - // ensure there is at least one lag sample for filtering - if(temp_model::data.L < intv_ms) - temp_model::data.L = intv_ms; + // ensure we do not exceed the maximum lag buffer and have at least one lag sample for filtering + if(samples < 1) + samples = 1; + else if(samples > TEMP_MODEL_MAX_LAG_SIZE) + samples = TEMP_MODEL_MAX_LAG_SIZE; - // do not exceed the maximum lag buffer - if(temp_model::data.L > (intv_ms * TEMP_MODEL_MAX_LAG_SIZE)) - temp_model::data.L = intv_ms * TEMP_MODEL_MAX_LAG_SIZE; + // round back to ms + temp_model::data.L = samples * intv_ms; } void temp_model_set_params(float P, float U, float V, float C, float D, int16_t L, float Ta_corr, float warn, float err) From 4a4be213740d9adfaa0061f9ee7ffba4819ee6ce Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 15 Feb 2023 11:24:06 +0100 Subject: [PATCH 08/11] TM: Fix UV identity --- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 4 ++-- Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 40dcb929a..3fc802499 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -415,8 +415,8 @@ #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) -#define TEMP_MODEL_U 1. // linear temperature coefficient (W/K/power) -#define TEMP_MODEL_V 0. // linear temperature intercept (W/power) +#define TEMP_MODEL_U 0. // linear temperature coefficient (W/K/power) +#define TEMP_MODEL_V 1. // linear temperature intercept (W/power) #define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) #define TEMP_MODEL_Cl 5 // C estimation lower limit diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index f5d6d2f8e..015124fab 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -419,8 +419,8 @@ #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) -#define TEMP_MODEL_U 1. // linear temperature coefficient (W/K/power) -#define TEMP_MODEL_V 0. // linear temperature intercept (W/power) +#define TEMP_MODEL_U 0. // linear temperature coefficient (W/K/power) +#define TEMP_MODEL_V 1. // linear temperature intercept (W/power) #define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) #define TEMP_MODEL_Cl 5 // C estimation lower limit From 4b499583b555991f7b01e24d28bbd0ca7e173e99 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 15 Feb 2023 11:40:53 +0100 Subject: [PATCH 09/11] TM: future-proofing for incompatible model upgrades Introduce a model version. This is initialized at "1" and doesn't require any upgrade/downgrade checks since it's currently retro-compatible. --- Firmware/eeprom.h | 3 ++- Firmware/temperature.cpp | 6 +++--- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 6380225b9..3e5c6be1f 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -594,9 +594,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_TEMP_MODEL_V (EEPROM_TEMP_MODEL_U-4) //float #define EEPROM_TEMP_MODEL_D (EEPROM_TEMP_MODEL_V-4) //float #define EEPROM_TEMP_MODEL_L (EEPROM_TEMP_MODEL_D-2) //uint16_t +#define EEPROM_TEMP_MODEL_VER (EEPROM_TEMP_MODEL_L-1) //uint8_t //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_TEMP_MODEL_L +#define EEPROM_LAST_ITEM EEPROM_TEMP_MODEL_VER // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index fafbffa33..ced7ea507 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2633,13 +2633,13 @@ void temp_model_load_settings() static_assert(TEMP_MODEL_R_SIZE == 16); // ensure we don't desync with the eeprom table TempMgrGuard temp_mgr_guard; - // handle upgrade from a model without UVDL (FW<3.13) - // WARNING: this only works as long as UVDL are the same constants/model type as FW 3.12, - // it needs to consider the upgrading FW version otherwise! + // handle upgrade from a model without UVDL (FW<3.13, TM VER<1): model is retro-compatible, + // reset UV to an identity without doing any special handling eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_U, TEMP_MODEL_U); eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_V, TEMP_MODEL_V); eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_D, TEMP_MODEL_fS); eeprom_init_default_word((uint16_t*)EEPROM_TEMP_MODEL_L, TEMP_MODEL_LAG); + eeprom_init_default_byte((uint8_t*)EEPROM_TEMP_MODEL_VER, TEMP_MODEL_VER); temp_model::enabled = eeprom_read_byte((uint8_t*)EEPROM_TEMP_MODEL_ENABLE); temp_model::data.P = eeprom_read_float((float*)EEPROM_TEMP_MODEL_P); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 3fc802499..e1ca66acf 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -412,6 +412,7 @@ // model-based temperature check #define TEMP_MODEL 1 // enable model-based temperature checks +#define TEMP_MODEL_VER 1 // model parameters version #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index 015124fab..ad599335e 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -416,6 +416,7 @@ // model-based temperature check #define TEMP_MODEL 1 // enable model-based temperature checks +#define TEMP_MODEL_VER 1 // model parameters version #define TEMP_MODEL_DEBUG 1 // extended runtime logging #define TEMP_MODEL_P 38. // heater power (W) From fd96b79ea9af569b86fee4d86b058f6f5b849f44 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 15 Feb 2023 13:42:44 +0100 Subject: [PATCH 10/11] TM: Split default model parameters into a separate header Preparation to support multiple default model parameter sets --- Firmware/temp_model.h | 9 +++- Firmware/temperature.cpp | 44 ++++++++++--------- .../variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 42 +++++++----------- .../variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 42 +++++++----------- Firmware/variants/temp_model/e3d_v6.h | 19 ++++++++ 5 files changed, 79 insertions(+), 77 deletions(-) create mode 100644 Firmware/variants/temp_model/e3d_v6.h diff --git a/Firmware/temp_model.h b/Firmware/temp_model.h index 15d85d512..0fb4206a3 100644 --- a/Firmware/temp_model.h +++ b/Firmware/temp_model.h @@ -5,7 +5,12 @@ #include "planner.h" -constexpr uint8_t TEMP_MODEL_CAL_S = 60; // Maximum recording lenght during calibration (s) +// shortcuts to get model defaults +#define __TEMP_MODEL_DEF(MODEL, VAR) TEMP_MODEL_##MODEL##_##VAR +#define _TEMP_MODEL_DEF(MODEL, VAR) __TEMP_MODEL_DEF(MODEL, VAR) +#define TEMP_MODEL_DEF(VAR) _TEMP_MODEL_DEF(TEMP_MODEL_DEFAULT, VAR) + +constexpr uint8_t TEMP_MODEL_CAL_S = 60; // Maximum recording length during calibration (s) constexpr uint8_t TEMP_MODEL_CAL_R_STEP = 4; // Fan interpolation steps during calibration constexpr float TEMP_MODEL_fE = 0.05; // error filter (1st-order IIR factor) @@ -14,7 +19,7 @@ constexpr uint8_t TEMP_MODEL_MAX_LAG_SIZE = 8; // * TEMP_MGR_INTV = 2160 // resistance values for all fan levels constexpr uint8_t TEMP_MODEL_R_SIZE = (1 << FAN_SOFT_PWM_BITS); -static const float TEMP_MODEL_R_DEFAULT[TEMP_MODEL_R_SIZE] PROGMEM = TEMP_MODEL_Rv; +static const float TEMP_MODEL_R_DEFAULT[TEMP_MODEL_R_SIZE] PROGMEM = TEMP_MODEL_DEF(Rv); namespace temp_model { diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index ced7ea507..a5aa0a5dd 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2612,17 +2612,17 @@ void temp_model_reset_settings() { TempMgrGuard temp_mgr_guard; - temp_model::data.P = TEMP_MODEL_P; - temp_model::data.U = TEMP_MODEL_U; - temp_model::data.V = TEMP_MODEL_V; - temp_model::data.C = TEMP_MODEL_C; - temp_model::data.fS = TEMP_MODEL_fS; - temp_model::data.L = (uint16_t)(TEMP_MODEL_LAG / (TEMP_MGR_INTV * 1000) + 0.5) * (uint16_t)(TEMP_MGR_INTV * 1000); + temp_model::data.P = TEMP_MODEL_DEF(P); + temp_model::data.U = TEMP_MODEL_DEF(U); + temp_model::data.V = TEMP_MODEL_DEF(V); + temp_model::data.C = TEMP_MODEL_DEF(C); + temp_model::data.fS = TEMP_MODEL_DEF(fS); + temp_model::data.L = (uint16_t)(TEMP_MODEL_DEF(LAG) / (TEMP_MGR_INTV * 1000) + 0.5) * (uint16_t)(TEMP_MGR_INTV * 1000); for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) temp_model::data.R[i] = pgm_read_float(TEMP_MODEL_R_DEFAULT + i); temp_model::data.Ta_corr = TEMP_MODEL_Ta_corr; - temp_model::data.warn = TEMP_MODEL_W; - temp_model::data.err = TEMP_MODEL_E; + temp_model::data.warn = TEMP_MODEL_DEF(W); + temp_model::data.err = TEMP_MODEL_DEF(E); temp_model::warn_beep = true; temp_model::enabled = true; temp_model::reinitialize(); @@ -2635,11 +2635,11 @@ void temp_model_load_settings() // handle upgrade from a model without UVDL (FW<3.13, TM VER<1): model is retro-compatible, // reset UV to an identity without doing any special handling - eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_U, TEMP_MODEL_U); - eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_V, TEMP_MODEL_V); - eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_D, TEMP_MODEL_fS); - eeprom_init_default_word((uint16_t*)EEPROM_TEMP_MODEL_L, TEMP_MODEL_LAG); - eeprom_init_default_byte((uint8_t*)EEPROM_TEMP_MODEL_VER, TEMP_MODEL_VER); + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_U, TEMP_MODEL_DEF(U)); + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_V, TEMP_MODEL_DEF(V)); + eeprom_init_default_float((float*)EEPROM_TEMP_MODEL_D, TEMP_MODEL_DEF(fS)); + eeprom_init_default_word((uint16_t*)EEPROM_TEMP_MODEL_L, TEMP_MODEL_DEF(LAG)); + eeprom_init_default_byte((uint8_t*)EEPROM_TEMP_MODEL_VER, TEMP_MODEL_DEF(VER)); temp_model::enabled = eeprom_read_byte((uint8_t*)EEPROM_TEMP_MODEL_ENABLE); temp_model::data.P = eeprom_read_float((float*)EEPROM_TEMP_MODEL_P); @@ -2850,10 +2850,10 @@ static bool autotune(int16_t cal_temp) for(uint8_t i = 0; i != 2; ++i) { const char* PROGMEM verb = (i == 0? PSTR("initial"): PSTR("refine")); target_temperature[0] = 0; - if(current_temperature[0] >= TEMP_MODEL_CAL_Tl) { - sprintf_P(tm_message, PSTR("TM: cool down <%dC"), TEMP_MODEL_CAL_Tl); + if(current_temperature[0] >= TEMP_MODEL_CAL_T_low) { + sprintf_P(tm_message, PSTR("TM: cool down <%dC"), TEMP_MODEL_CAL_T_low); lcd_setstatus_serial(tm_message); - cooldown(TEMP_MODEL_CAL_Tl); + cooldown(TEMP_MODEL_CAL_T_low); wait(10000); } @@ -2866,10 +2866,11 @@ static bool autotune(int16_t cal_temp) // we need a high R value for the initial C guess if(isnan(temp_model::data.R[0])) - temp_model::data.R[0] = TEMP_MODEL_Rh; + temp_model::data.R[0] = TEMP_MODEL_CAL_R_high; e = estimate(samples, &temp_model::data.C, - TEMP_MODEL_Cl, TEMP_MODEL_Ch, TEMP_MODEL_C_thr, TEMP_MODEL_C_itr, + TEMP_MODEL_CAL_C_low, TEMP_MODEL_CAL_C_high, + TEMP_MODEL_CAL_C_thr, TEMP_MODEL_CAL_C_itr, 0, current_temperature_ambient); if(isnan(e)) return true; @@ -2885,7 +2886,8 @@ static bool autotune(int16_t cal_temp) return true; e = estimate(samples, &temp_model::data.R[0], - TEMP_MODEL_Rl, TEMP_MODEL_Rh, TEMP_MODEL_R_thr, TEMP_MODEL_R_itr, + TEMP_MODEL_CAL_R_low, TEMP_MODEL_CAL_R_high, + TEMP_MODEL_CAL_R_thr, TEMP_MODEL_CAL_R_itr, 0, current_temperature_ambient); if(isnan(e)) return true; @@ -2916,7 +2918,7 @@ static bool autotune(int16_t cal_temp) // a fixed fan pwm (the norminal value) is used here, as soft_pwm_fan will be modified // during fan measurements and we'd like to include that skew during normal operation. e = estimate(samples, &temp_model::data.R[i], - TEMP_MODEL_Rl, temp_model::data.R[0], TEMP_MODEL_R_thr, TEMP_MODEL_R_itr, + TEMP_MODEL_CAL_R_low, temp_model::data.R[0], TEMP_MODEL_CAL_R_thr, TEMP_MODEL_CAL_R_itr, i, current_temperature_ambient); if(isnan(e)) return true; @@ -2973,7 +2975,7 @@ void temp_model_autotune(int16_t temp, bool selftest) // autotune SERIAL_ECHOLNPGM("TM: calibration start"); - temp_model_autotune_err = temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_Th); + temp_model_autotune_err = temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_T_high); // always reset temperature disable_heater(); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index e1ca66acf..216de0705 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -411,38 +411,26 @@ #define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45 // model-based temperature check -#define TEMP_MODEL 1 // enable model-based temperature checks -#define TEMP_MODEL_VER 1 // model parameters version -#define TEMP_MODEL_DEBUG 1 // extended runtime logging +#define TEMP_MODEL 1 // enable model-based temperature checks +#define TEMP_MODEL_DEBUG 1 // extended runtime logging -#define TEMP_MODEL_P 38. // heater power (W) -#define TEMP_MODEL_U 0. // linear temperature coefficient (W/K/power) -#define TEMP_MODEL_V 1. // linear temperature intercept (W/power) +#define TEMP_MODEL_CAL_C_low 5 // C estimation lower limit +#define TEMP_MODEL_CAL_C_high 20 // C estimation upper limit +#define TEMP_MODEL_CAL_C_thr 0.01 // C estimation iteration threshold +#define TEMP_MODEL_CAL_C_itr 30 // C estimation iteration limit -#define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) -#define TEMP_MODEL_Cl 5 // C estimation lower limit -#define TEMP_MODEL_Ch 20 // C estimation upper limit -#define TEMP_MODEL_C_thr 0.01 // C estimation iteration threshold -#define TEMP_MODEL_C_itr 30 // C estimation iteration limit +#define TEMP_MODEL_CAL_R_low 5 // R estimation lower limit +#define TEMP_MODEL_CAL_R_high 50 // R estimation upper limit +#define TEMP_MODEL_CAL_R_thr 0.01 // R estimation iteration threshold +#define TEMP_MODEL_CAL_R_itr 30 // R estimation iteration limit -#define TEMP_MODEL_fS 0.065 // sim. 1st order IIR filter factor (f=100/27) -#define TEMP_MODEL_LAG 2100 // sim. response lag (ms, 0-2160) +#define TEMP_MODEL_CAL_T_low 50 // Default calibration cooling temperature (C) +#define TEMP_MODEL_CAL_T_high 230 // Default calibration working temperature (C) -#define TEMP_MODEL_R 20.5 // initial guess for heatblock resistance (K/W) -#define TEMP_MODEL_Rl 5 // R estimation lower limit -#define TEMP_MODEL_Rh 50 // R estimation upper limit -#define TEMP_MODEL_R_thr 0.01 // R estimation iteration threshold -#define TEMP_MODEL_R_itr 30 // R estimation iteration limit +#define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_W 1.2 // Default warning threshold (K/s) -#define TEMP_MODEL_E 1.74 // Default error threshold (K/s) - -#define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C) -#define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C) - -// fall-back resistance vector (R0-15) -#define TEMP_MODEL_Rv {TEMP_MODEL_R, 18.4, 16.7, 15.2, 14.1, 13.3, 12.7, 12.1, 11.7, 11.3, 11., 10.8, 10.6, 10.4, 10.2, 10.1} +#include "temp_model/e3d_v6.h" +#define TEMP_MODEL_DEFAULT E3D_V6 // Default model parameters /*------------------------------------ diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index ad599335e..7f77e763b 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -415,38 +415,26 @@ #define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45 // model-based temperature check -#define TEMP_MODEL 1 // enable model-based temperature checks -#define TEMP_MODEL_VER 1 // model parameters version -#define TEMP_MODEL_DEBUG 1 // extended runtime logging +#define TEMP_MODEL 1 // enable model-based temperature checks +#define TEMP_MODEL_DEBUG 1 // extended runtime logging -#define TEMP_MODEL_P 38. // heater power (W) -#define TEMP_MODEL_U 0. // linear temperature coefficient (W/K/power) -#define TEMP_MODEL_V 1. // linear temperature intercept (W/power) +#define TEMP_MODEL_CAL_C_low 5 // C estimation lower limit +#define TEMP_MODEL_CAL_C_high 20 // C estimation upper limit +#define TEMP_MODEL_CAL_C_thr 0.01 // C estimation iteration threshold +#define TEMP_MODEL_CAL_C_itr 30 // C estimation iteration limit -#define TEMP_MODEL_C 12.1 // initial guess for heatblock capacitance (J/K) -#define TEMP_MODEL_Cl 5 // C estimation lower limit -#define TEMP_MODEL_Ch 20 // C estimation upper limit -#define TEMP_MODEL_C_thr 0.01 // C estimation iteration threshold -#define TEMP_MODEL_C_itr 30 // C estimation iteration limit +#define TEMP_MODEL_CAL_R_low 5 // R estimation lower limit +#define TEMP_MODEL_CAL_R_high 50 // R estimation upper limit +#define TEMP_MODEL_CAL_R_thr 0.01 // R estimation iteration threshold +#define TEMP_MODEL_CAL_R_itr 30 // R estimation iteration limit -#define TEMP_MODEL_fS 0.065 // sim. 1st order IIR filter factor (f=100/27) -#define TEMP_MODEL_LAG 2100 // sim. response lag (ms, 0-2160) +#define TEMP_MODEL_CAL_T_low 50 // Default calibration cooling temperature (C) +#define TEMP_MODEL_CAL_T_high 230 // Default calibration working temperature (C) -#define TEMP_MODEL_R 20.5 // initial guess for heatblock resistance (K/W) -#define TEMP_MODEL_Rl 5 // R estimation lower limit -#define TEMP_MODEL_Rh 50 // R estimation upper limit -#define TEMP_MODEL_R_thr 0.01 // R estimation iteration threshold -#define TEMP_MODEL_R_itr 30 // R estimation iteration limit +#define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_Ta_corr -7 // Default ambient temperature correction -#define TEMP_MODEL_W 1.2 // Default warning threshold (K/s) -#define TEMP_MODEL_E 1.74 // Default error threshold (K/s) - -#define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C) -#define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C) - -// fall-back resistance vector (R0-15) -#define TEMP_MODEL_Rv {TEMP_MODEL_R, 18.4, 16.7, 15.2, 14.1, 13.3, 12.7, 12.1, 11.7, 11.3, 11., 10.8, 10.6, 10.4, 10.2, 10.1} +#include "temp_model/e3d_v6.h" +#define TEMP_MODEL_DEFAULT E3D_V6 // Default model parameters /*------------------------------------ diff --git a/Firmware/variants/temp_model/e3d_v6.h b/Firmware/variants/temp_model/e3d_v6.h new file mode 100644 index 000000000..ac75894b7 --- /dev/null +++ b/Firmware/variants/temp_model/e3d_v6.h @@ -0,0 +1,19 @@ +#pragma once + +#define TEMP_MODEL_E3D_V6_VER 1 // model parameters version + +#define TEMP_MODEL_E3D_V6_P 38. // heater power (W) +#define TEMP_MODEL_E3D_V6_U 0. // linear temperature coefficient (W/K/power) +#define TEMP_MODEL_E3D_V6_V 1. // linear temperature intercept (W/power) + +#define TEMP_MODEL_E3D_V6_C 12.1 // initial guess for heatblock capacitance (J/K) +#define TEMP_MODEL_E3D_V6_R 20.5 // initial guess for heatblock resistance (K/W) + +#define TEMP_MODEL_E3D_V6_fS 0.065 // sim. 1st order IIR filter factor (f=100/27) +#define TEMP_MODEL_E3D_V6_LAG 2100 // sim. response lag (ms, 0-2160) + +#define TEMP_MODEL_E3D_V6_W 1.2 // Default warning threshold (K/s) +#define TEMP_MODEL_E3D_V6_E 1.74 // Default error threshold (K/s) + +// fall-back resistance vector (R0-15) +#define TEMP_MODEL_E3D_V6_Rv {TEMP_MODEL_E3D_V6_R, 18.4, 16.7, 15.2, 14.1, 13.3, 12.7, 12.1, 11.7, 11.3, 11., 10.8, 10.6, 10.4, 10.2, 10.1} From 571d25c04b2345744a5aae313d60433d5221669b Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Wed, 15 Feb 2023 14:01:19 +0100 Subject: [PATCH 11/11] TM: Move headers to support the legacy build system --- Firmware/{variants => }/temp_model/e3d_v6.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Firmware/{variants => }/temp_model/e3d_v6.h (100%) diff --git a/Firmware/variants/temp_model/e3d_v6.h b/Firmware/temp_model/e3d_v6.h similarity index 100% rename from Firmware/variants/temp_model/e3d_v6.h rename to Firmware/temp_model/e3d_v6.h