| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | // model-based temperature safety checker declarations#ifndef TEMP_MGR_INTV#error "this file is not a public interface, it should be used *only* within temperature.cpp!"#endif#include "planner.h"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 calibrationconstexpr 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);// resistance values for all fan levelsconstexpr 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;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    // configurable parameters    float P;                               // heater power (W)    float C;                               // heatblock capacitance (J/K)    float R[TEMP_MODEL_R_SIZE];            // heatblock resistance for all fan levels (K/W)    float Ta_corr;                         // ambient temperature correction (K)    // thresholds    float warn;                            // warning threshold (K/s)    float err;                             // error threshold (K/s)    // status flags    union    {        bool flags;        struct        {            bool uninitialized: 1;         // model is not initialized            bool error: 1;                 // error threshold set            bool warning: 1;               // warning threshold set        } flag_bits;    };    // pre-computed values (initialized via reset)    float C_i;                             // heatblock capacitance (precomputed dT/C)    float warn_s;                          // warning threshold (per sample)    float err_s;                           // error threshold (per sample)    // simulation functions    void reset(uint8_t heater_pwm, uint8_t fan_pwm, float heater_temp, float ambient_temp);    void step(uint8_t heater_pwm, uint8_t fan_pwm, float heater_temp, float ambient_temp);};static bool enabled;          // model check enabledstatic bool warn_beep = true; // beep on warning thresholdstatic model_data data;       // default heater datastatic bool calibrated(); // return calibration/model validity statusstatic void check();      // check and trigger errors or warnings based on current state// warning state (updated from from isr context)volatile static struct{    float dT_err;    // temperature delta error (per sample)    bool warning: 1; // warning condition    bool assert: 1;  // warning is still asserted} warning_state;static void handle_warning(); // handle warnings from user context#ifdef TEMP_MODEL_DEBUGstatic struct{    volatile struct    {        uint32_t stamp;        int8_t delta_ms;        uint8_t counter;        uint8_t cur_pwm;        float cur_temp;        float cur_amb;    } entry;    uint8_t serial;    bool enabled;} log_buf;static void log_usr(); // user log handlerstatic void log_isr(); // isr log handler#endif} // namespace temp_modelnamespace temp_model_cal {// recording scratch bufferstruct rec_entry{    float temp;  // heater temperature    uint8_t pwm; // heater PWM};constexpr uint16_t REC_BUFFER_SIZE = TEMP_MODEL_CAL_S / TEMP_MGR_INTV;static rec_entry* const rec_buffer = (rec_entry*)block_buffer; // oh-hey, free memory!static_assert(sizeof(rec_entry[REC_BUFFER_SIZE]) <= sizeof(block_buffer),    "recording length too long to fit within available buffer");} // namespace temp_model_cal
 |