Merge pull request #3552 from wavexx/temp_model_check
Thermal Model protection
This commit is contained in:
commit
0933fdb6fe
40 changed files with 2599 additions and 1455 deletions
|
@ -9,7 +9,6 @@ before_install:
|
|||
- sudo iptables -A OUTPUT -o lo -j ACCEPT
|
||||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
script:
|
||||
- bash -x test.sh
|
||||
- cp Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK3S-EINSy10a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
|
|
|
@ -75,6 +75,9 @@ void Config_StoreSettings()
|
|||
|
||||
if (EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base),reinterpret_cast<uint8_t*>(&cs),sizeof(cs),0), "cs, invalid version")
|
||||
{
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_save_settings();
|
||||
#endif
|
||||
strcpy(cs.version,EEPROM_VERSION); //!< validate data if write succeed
|
||||
EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version valid");
|
||||
}
|
||||
|
@ -173,6 +176,9 @@ void Config_PrintSettings(uint8_t level)
|
|||
printf_P(PSTR(
|
||||
"%SArc Settings: P:Max length(mm) S:Min length (mm) N:Corrections R:Min segments F:Segments/sec.\n%S M214 P%.2f S%.2f N%d R%d F%d\n"),
|
||||
echomagic, echomagic, cs.mm_per_arc_segment, cs.min_mm_per_arc_segment, cs.n_arc_correction, cs.min_arc_segments, cs.arc_segments_per_sec);
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_report_settings();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -321,6 +327,10 @@ bool Config_RetrieveSettings()
|
|||
|
||||
// Call updatePID (similar to when we have processed M301)
|
||||
updatePID();
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_load_settings();
|
||||
#endif
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
||||
}
|
||||
|
@ -353,6 +363,9 @@ void Config_ResetDefault()
|
|||
#ifdef PIDTEMP
|
||||
updatePID();
|
||||
#endif//PIDTEMP
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_reset_settings();
|
||||
#endif
|
||||
|
||||
calculate_extruder_multipliers();
|
||||
|
||||
|
|
|
@ -573,6 +573,7 @@ void dcode_9()
|
|||
for (uint8_t i = 0; i < ADC_CHAN_CNT; i++)
|
||||
printf_P(PSTR("\tADC%d=%4d\t(%S)\n"), i, dcode_9_ADC_val(i) >> 4, dcode_9_ADC_name(i));
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
uint8_t index = 0xff;
|
||||
|
@ -588,6 +589,7 @@ void dcode_9()
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -241,9 +241,10 @@ void prepare_move();
|
|||
void kill(const char *full_screen_message = NULL, unsigned char id = 0);
|
||||
void finishAndDisableSteppers();
|
||||
|
||||
void UnconditionalStop(); // Stop heaters, motion and clear current print status
|
||||
void Stop(); // Emergency stop used by overtemp functions which allows recovery
|
||||
bool IsStopped(); // Returns true if the print has been stopped
|
||||
void UnconditionalStop(); // Stop heaters, motion and clear current print status
|
||||
void ThermalStop(bool allow_pause = false); // Emergency stop used by overtemp functions which allows
|
||||
// recovery (with pause=true)
|
||||
bool IsStopped(); // Returns true if the print has been stopped
|
||||
|
||||
//put an ASCII command at the end of the current buffer, read from flash
|
||||
#define enquecommand_P(cmd) enquecommand(cmd, true)
|
||||
|
@ -255,27 +256,6 @@ void prepare_arc_move(bool isclockwise);
|
|||
void clamp_to_software_endstops(float target[3]);
|
||||
void refresh_cmd_timeout(void);
|
||||
|
||||
// Timer counter, incremented by the 1ms Arduino timer.
|
||||
// The standard Arduino timer() function returns this value atomically
|
||||
// by disabling / enabling interrupts. This is costly, if the interrupts are known
|
||||
// to be disabled.
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
|
||||
// An unsynchronized equivalent to a standard Arduino _millis() function.
|
||||
// To be used inside an interrupt routine.
|
||||
|
||||
FORCE_INLINE unsigned long millis_nc() {
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
return timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
return timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
}
|
||||
|
||||
#ifdef FAST_PWM_FAN
|
||||
void setPwmFrequency(uint8_t pin, int val);
|
||||
#endif
|
||||
|
@ -315,18 +295,12 @@ void homeaxis(uint8_t axis, uint8_t cnt = 1, uint8_t* pstep = 0);
|
|||
void homeaxis(uint8_t axis, uint8_t cnt = 1);
|
||||
#endif //TMC2130
|
||||
|
||||
|
||||
#ifdef FAN_SOFT_PWM
|
||||
extern unsigned char fanSpeedSoftPwm;
|
||||
#endif
|
||||
|
||||
#ifdef FWRETRACT
|
||||
extern bool retracted[EXTRUDERS];
|
||||
extern float retract_length_swap;
|
||||
extern float retract_recover_length_swap;
|
||||
#endif
|
||||
|
||||
|
||||
extern uint8_t host_keepalive_interval;
|
||||
|
||||
extern unsigned long starttime;
|
||||
|
@ -364,6 +338,10 @@ extern uint8_t saved_printing_type;
|
|||
#define PRINTING_TYPE_USB 1
|
||||
#define PRINTING_TYPE_NONE 2
|
||||
|
||||
extern float saved_extruder_temperature; //!< Active extruder temperature
|
||||
extern float saved_bed_temperature; //!< Bed temperature
|
||||
extern int saved_fan_speed; //!< Print fan speed
|
||||
|
||||
//save/restore printing in case that mmu is not responding
|
||||
extern bool mmu_print_saved;
|
||||
|
||||
|
@ -385,6 +363,8 @@ extern LongTimer safetyTimer;
|
|||
#define PRINT_PERCENT_DONE_INIT 0xff
|
||||
#define PRINTER_ACTIVE (IS_SD_PRINTING || usb_timer.running() || isPrintPaused || (custom_message_type == CustomMsg::TempCal) || saved_printing || (lcd_commands_type == LcdCommands::Layer1Cal) || mmu_print_saved || homing_flag || mesh_bed_leveling_flag)
|
||||
|
||||
extern bool printer_active();
|
||||
|
||||
//! Beware - mcode_in_progress is set as soon as the command gets really processed,
|
||||
//! which is not the same as posting the M600 command into the command queue
|
||||
//! There can be a considerable lag between posting M600 and its real processing which might result
|
||||
|
@ -467,6 +447,7 @@ extern uint8_t calc_percent_done();
|
|||
|
||||
#define KEEPALIVE_STATE(n) do { busy_state = n;} while (0)
|
||||
extern void host_keepalive();
|
||||
extern void host_autoreport();
|
||||
//extern MarlinBusyState busy_state;
|
||||
extern int8_t busy_state;
|
||||
|
||||
|
@ -504,7 +485,6 @@ void raise_z_above(float target, bool plan=true);
|
|||
|
||||
extern "C" void softReset();
|
||||
void stack_error();
|
||||
void pullup_error(bool fromTempISR);
|
||||
|
||||
extern uint32_t IP_address;
|
||||
|
||||
|
|
|
@ -37,11 +37,10 @@
|
|||
|
||||
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
|
||||
// requires two levels of indirection to expand macro values properly)
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
|
||||
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _REGNAME_SHORT(registerbase, suffix)
|
||||
#else
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _REGNAME(registerbase, number, suffix)
|
||||
#endif
|
||||
|
||||
// Registers used by MarlinSerial class (these are expanded
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "planner.h"
|
||||
#include "stepper.h"
|
||||
#include "temperature.h"
|
||||
#include "fancheck.h"
|
||||
#include "motion_control.h"
|
||||
#include "cardreader.h"
|
||||
#include "ConfigurationStore.h"
|
||||
|
@ -379,9 +380,10 @@ static float saved_pos[4] = { X_COORD_INVALID, 0, 0, 0 };
|
|||
static uint16_t saved_feedrate2 = 0; //!< Default feedrate (truncated from float)
|
||||
static int saved_feedmultiply2 = 0;
|
||||
static uint8_t saved_active_extruder = 0;
|
||||
static float saved_extruder_temperature = 0.0; //!< Active extruder temperature
|
||||
float saved_extruder_temperature = 0.0; //!< Active extruder temperature
|
||||
float saved_bed_temperature = 0.0; //!< Bed temperature
|
||||
static bool saved_extruder_relative_mode = false;
|
||||
static int saved_fanSpeed = 0; //!< Print fan speed
|
||||
int saved_fan_speed = 0; //!< Print fan speed
|
||||
//! @}
|
||||
|
||||
static int saved_feedmultiply_mm = 100;
|
||||
|
@ -571,6 +573,10 @@ void servo_init()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool printer_active()
|
||||
{
|
||||
return PRINTER_ACTIVE;
|
||||
}
|
||||
|
||||
bool fans_check_enabled = true;
|
||||
|
||||
|
@ -1272,9 +1278,15 @@ void setup()
|
|||
else { //printer version was changed so use default settings
|
||||
Config_ResetDefault();
|
||||
}
|
||||
SdFatUtil::set_stack_guard(); //writes magic number at the end of static variables to protect against overwriting static memory by stack
|
||||
|
||||
tp_init(); // Initialize temperature loop
|
||||
// writes a magic number at the end of static variables to monitor against incorrect overwriting
|
||||
// of static memory by stack (this needs to be done before soft_pwm_init, since the check is
|
||||
// performed inside the soft_pwm_isr)
|
||||
SdFatUtil::set_stack_guard();
|
||||
|
||||
// Initialize pwm/temperature loops
|
||||
soft_pwm_init();
|
||||
temp_mgr_init();
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
SERIAL_ECHORPGM(_n("Extruder fan type: "));
|
||||
|
@ -1359,7 +1371,9 @@ void setup()
|
|||
|
||||
setup_photpin();
|
||||
|
||||
#if 0
|
||||
servo_init();
|
||||
#endif
|
||||
|
||||
// Reset the machine correction matrix.
|
||||
// It does not make sense to load the correction matrix until the machine is homed.
|
||||
|
@ -1692,10 +1706,6 @@ void stack_error() {
|
|||
crash_and_burn(dump_crash_reason::stack_error);
|
||||
}
|
||||
|
||||
void pullup_error(bool fromTempISR) {
|
||||
crash_and_burn(fromTempISR ? dump_crash_reason::bad_pullup_temp_isr : dump_crash_reason::bad_pullup_step_isr);
|
||||
}
|
||||
|
||||
#ifdef PRUSA_M28
|
||||
void trace();
|
||||
|
||||
|
@ -1774,7 +1784,7 @@ void serial_read_stream() {
|
|||
* Output autoreport values according to features requested in M155
|
||||
*/
|
||||
#if defined(AUTO_REPORT)
|
||||
static void host_autoreport()
|
||||
void host_autoreport()
|
||||
{
|
||||
if (autoReportFeatures.TimerExpired())
|
||||
{
|
||||
|
@ -1834,7 +1844,17 @@ void host_keepalive() {
|
|||
// Before loop(), the setup() function is called by the main() routine.
|
||||
void loop()
|
||||
{
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
// Reset a previously aborted command, we can now start processing motion again
|
||||
planner_aborted = false;
|
||||
|
||||
if(Stopped) {
|
||||
// Currently Stopped (possibly due to an error) and not accepting new serial commands.
|
||||
// Signal to the host that we're currently busy waiting for supervision.
|
||||
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
||||
} else {
|
||||
// Printer is available for processing, reset state
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
}
|
||||
|
||||
if (isPrintPaused && saved_printing_type == PRINTING_TYPE_USB) { //keep believing that usb is being printed. Prevents accessing dangerous menus while pausing.
|
||||
usb_timer.start();
|
||||
|
@ -1843,13 +1863,6 @@ void loop()
|
|||
;
|
||||
}
|
||||
|
||||
#ifdef FANCHECK
|
||||
if (fan_check_error && isPrintPaused && !IS_SD_PRINTING) {
|
||||
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
||||
host_keepalive(); //prevent timeouts since usb processing is disabled until print is resumed. This is for a crude way of pausing a print on all hosts.
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PRUSA_M28
|
||||
if (prusa_sd_card_upload)
|
||||
{
|
||||
|
@ -2206,6 +2219,7 @@ void raise_z_above(float target, bool plan)
|
|||
|
||||
// Z needs raising
|
||||
current_position[Z_AXIS] = target;
|
||||
clamp_to_software_endstops(current_position);
|
||||
|
||||
#if defined(Z_MIN_PIN) && (Z_MIN_PIN > -1) && !defined(DEBUG_DISABLE_ZMINLIMIT)
|
||||
bool z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
|
||||
|
@ -2982,7 +2996,7 @@ static void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis)
|
|||
static void gcode_G80()
|
||||
{
|
||||
st_synchronize();
|
||||
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||
if (planner_aborted)
|
||||
return;
|
||||
|
||||
mesh_bed_leveling_flag = true;
|
||||
|
@ -3076,7 +3090,7 @@ static void gcode_G80()
|
|||
plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE);
|
||||
// Wait until the move is finished.
|
||||
st_synchronize();
|
||||
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||
if (planner_aborted)
|
||||
{
|
||||
custom_message_type = custom_message_type_old;
|
||||
custom_message_state = custom_message_state_old;
|
||||
|
@ -3151,7 +3165,7 @@ static void gcode_G80()
|
|||
//printf_P(PSTR("after clamping: [%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE);
|
||||
st_synchronize();
|
||||
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||
if (planner_aborted)
|
||||
{
|
||||
custom_message_type = custom_message_type_old;
|
||||
custom_message_state = custom_message_state_old;
|
||||
|
@ -4138,6 +4152,7 @@ extern uint8_t st_backlash_y;
|
|||
//!@n M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
|
||||
//!@n M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
||||
//!@n M304 - Set bed PID parameters P I and D
|
||||
//!@n M310 - Temperature model settings
|
||||
//!@n M400 - Finish all moves
|
||||
//!@n M401 - Lower z-probe if present
|
||||
//!@n M402 - Raise z-probe if present
|
||||
|
@ -4179,16 +4194,6 @@ There are reasons why some G Codes aren't in numerical order.
|
|||
|
||||
void process_commands()
|
||||
{
|
||||
#ifdef FANCHECK
|
||||
if(fan_check_error == EFCE_DETECTED) {
|
||||
fan_check_error = EFCE_REPORTED;
|
||||
if (usb_timer.running())
|
||||
lcd_pause_usb_print();
|
||||
else
|
||||
lcd_pause_print();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!buflen) return; //empty command
|
||||
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
|
@ -4642,7 +4647,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
|
|||
*/
|
||||
case 0: // G0 -> G1
|
||||
case 1: // G1
|
||||
if(Stopped == false) {
|
||||
{
|
||||
get_coordinates(); // For X Y Z E F
|
||||
|
||||
// When recovering from a previous print move, restore the originally
|
||||
|
@ -4701,7 +4706,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
|
|||
|
||||
*/
|
||||
case 2:
|
||||
if(Stopped == false) {
|
||||
{
|
||||
get_arc_coordinates();
|
||||
prepare_arc_move(true);
|
||||
}
|
||||
|
@ -4709,7 +4714,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
|
|||
|
||||
// -------------------------------
|
||||
case 3:
|
||||
if(Stopped == false) {
|
||||
{
|
||||
get_arc_coordinates();
|
||||
prepare_arc_move(false);
|
||||
}
|
||||
|
@ -7760,6 +7765,67 @@ Sigma_Exit:
|
|||
PID_autotune(temp, e, c);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef TEMP_MODEL
|
||||
/*!
|
||||
### M310 - Temperature model settings <a href="https://reprap.org/wiki/G-code#M310:_Temperature_model_settings">M310: Temperature model settings</a>
|
||||
#### Usage
|
||||
|
||||
M310 ; report values
|
||||
M310 [ A ] ; autotune
|
||||
M310 [ S ] ; set 0=disable 1=enable
|
||||
M310 [ I ] [ R ] ; set resistance at index
|
||||
M310 [ P | C ] ; set power, capacitance
|
||||
M310 [ B | E | W ] ; set beeper, warning and error threshold
|
||||
M310 [ T ] ; set ambient temperature correction
|
||||
|
||||
#### Parameters
|
||||
- `I` - resistance index position (0-15)
|
||||
- `R` - resistance value at index (K/W; requires `I`)
|
||||
- `P` - power (W)
|
||||
- `C` - capacitance (J/K)
|
||||
- `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)
|
||||
- `W` - warning threshold (K/s; default in variant)
|
||||
- `T` - ambient temperature correction (K; default in variant)
|
||||
- `A` - autotune C+R values
|
||||
*/
|
||||
case 310:
|
||||
{
|
||||
// parse all parameters
|
||||
float P = NAN, C = NAN, R = NAN, E = NAN, W = NAN, T = NAN;
|
||||
int8_t I = -1, S = -1, B = -1, A = -1;
|
||||
if(code_seen('C')) C = code_value();
|
||||
if(code_seen('P')) P = code_value();
|
||||
if(code_seen('I')) I = code_value_short();
|
||||
if(code_seen('R')) R = code_value();
|
||||
if(code_seen('S')) S = code_value_short();
|
||||
if(code_seen('B')) B = code_value_short();
|
||||
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();
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
|
||||
// enable the model last, if requested
|
||||
if(S >= 0) temp_model_set_enabled(S);
|
||||
|
||||
// run autotune
|
||||
if(A >= 0) temp_model_autotune(A);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
### M400 - Wait for all moves to finish <a href="https://reprap.org/wiki/G-code#M400:_Wait_for_current_moves_to_finish">M400: Wait for current moves to finish</a>
|
||||
|
@ -8717,16 +8783,6 @@ Sigma_Exit:
|
|||
}
|
||||
break;
|
||||
|
||||
/*!
|
||||
### M999 - Restart after being stopped <a href="https://reprap.org/wiki/G-code#M999:_Restart_after_being_stopped_by_error">M999: Restart after being stopped by error</a>
|
||||
@todo Usually doesn't work. Should be fixed or removed. Most of the time, if `Stopped` it set, the print fails and is unrecoverable.
|
||||
*/
|
||||
case 999:
|
||||
Stopped = false;
|
||||
lcd_reset_alert_level();
|
||||
gcode_LastN = Stopped_gcode_LastN;
|
||||
FlushSerialRequestResend();
|
||||
break;
|
||||
/*!
|
||||
#### End of M-Commands
|
||||
*/
|
||||
|
@ -8870,7 +8926,7 @@ Sigma_Exit:
|
|||
active_extruder = tmp_extruder;
|
||||
plan_set_position_curposXYZE();
|
||||
// Move to the old position if 'F' was in the parameters
|
||||
if (make_move && Stopped == false) {
|
||||
if (make_move) {
|
||||
prepare_move();
|
||||
}
|
||||
}
|
||||
|
@ -9144,6 +9200,23 @@ Sigma_Exit:
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef TEMP_MODEL_DEBUG
|
||||
/*!
|
||||
## D70 - Enable low-level temperature model logging for offline simulation
|
||||
#### Usage
|
||||
|
||||
D70 [ I ]
|
||||
|
||||
#### Parameters
|
||||
- `I` - Enable 0-1 (default 0)
|
||||
*/
|
||||
case 70: {
|
||||
if(code_seen('I'))
|
||||
temp_model_log_enable(code_value_short());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HEATBED_ANALYSIS
|
||||
|
||||
/*!
|
||||
|
@ -9469,7 +9542,7 @@ void mesh_plan_buffer_line(const float &x, const float &y, const float &z, const
|
|||
current_position[Z_AXIS] + t * dz,
|
||||
current_position[E_AXIS] + t * de,
|
||||
feed_rate, extruder, gcode_target);
|
||||
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||
if (planner_aborted)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -9871,6 +9944,7 @@ void UnconditionalStop()
|
|||
// Disable all heaters and unroll the temperature wait loop stack
|
||||
disable_heater();
|
||||
cancel_heatup = true;
|
||||
heating_status = HeatingStatus::NO_HEATING;
|
||||
|
||||
// Clear any saved printing state
|
||||
cancel_saved_printing();
|
||||
|
@ -9890,39 +9964,58 @@ void UnconditionalStop()
|
|||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
// Stop: Emergency stop used by overtemp functions which allows recovery
|
||||
// Emergency stop used by overtemp functions which allows recovery
|
||||
// WARNING: This function is called *continuously* during a thermal failure.
|
||||
//
|
||||
// In addition to stopping the print, this prevents subsequent G[0-3] commands to be
|
||||
// processed via USB (using "Stopped") until the print is resumed via M999 or
|
||||
// manually started from scratch with the LCD.
|
||||
//
|
||||
// Note that the current instruction is completely discarded, so resuming from Stop()
|
||||
// will introduce either over/under extrusion on the current segment, and will not
|
||||
// survive a power panic. Switching Stop() to use the pause machinery instead (with
|
||||
// the addition of disabling the headers) could allow true recovery in the future.
|
||||
void Stop()
|
||||
// This either pauses (for thermal model errors) or stops *without recovery* depending on
|
||||
// "allow_pause". If pause is allowed, this forces a printer-initiated instantanenous pause (just
|
||||
// like an LCD pause) that bypasses the host pausing functionality. In this state the printer is
|
||||
// kept in busy state and *must* be recovered from the LCD.
|
||||
void ThermalStop(bool allow_pause)
|
||||
{
|
||||
// Keep disabling heaters
|
||||
disable_heater();
|
||||
if(Stopped == false) {
|
||||
Stopped = true;
|
||||
if(allow_pause && (IS_SD_PRINTING || usb_timer.running())) {
|
||||
if (!isPrintPaused) {
|
||||
// we cannot make a distinction for the host here, the pause must be instantaneous
|
||||
// so we call the lcd_pause_print to save the print state internally. Thermal errors
|
||||
// disable heaters and save the original temperatures to saved_*, which will get
|
||||
// overwritten by stop_and_save_print_to_ram. For this corner-case, re-instate the
|
||||
// original values after the pause handler is called.
|
||||
float bed_temp = saved_bed_temperature;
|
||||
float ext_temp = saved_extruder_temperature;
|
||||
int fan_speed = saved_fan_speed;
|
||||
lcd_pause_print();
|
||||
saved_bed_temperature = bed_temp;
|
||||
saved_extruder_temperature = ext_temp;
|
||||
saved_fan_speed = fan_speed;
|
||||
}
|
||||
} else {
|
||||
// We got a hard thermal error and/or there is no print going on. Just stop.
|
||||
lcd_print_stop();
|
||||
|
||||
// Call the regular stop function if that's the first time during a new print
|
||||
if(Stopped == false) {
|
||||
Stopped = true;
|
||||
lcd_print_stop();
|
||||
Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart
|
||||
// Also prevent further menu entry
|
||||
menu_set_block(MENU_BLOCK_THERMAL_ERROR);
|
||||
}
|
||||
|
||||
// Eventually report the stopped status (though this is usually overridden by a
|
||||
// higher-priority alert status message)
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
|
||||
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
||||
}
|
||||
// Report the status on the serial, switch to a busy state
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
|
||||
|
||||
// Return to the status screen to stop any pending menu action which could have been
|
||||
// started by the user while stuck in the Stopped state. This also ensures the NEW
|
||||
// error is immediately shown.
|
||||
if (menu_menu != lcd_status_screen)
|
||||
lcd_return_to_status();
|
||||
// Eventually report the stopped status on the lcd (though this is usually overridden by a
|
||||
// higher-priority alert status message)
|
||||
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
||||
|
||||
// Make a warning sound! We cannot use Sound_MakeCustom as this would stop further moves.
|
||||
// Turn on the speaker here (if not already), and turn it off when back in the main loop.
|
||||
WRITE(BEEPER, HIGH);
|
||||
}
|
||||
|
||||
// Return to the status screen to stop any pending menu action which could have been
|
||||
// started by the user while stuck in the Stopped state. This also ensures the NEW
|
||||
// error is immediately shown.
|
||||
if (menu_menu != lcd_status_screen)
|
||||
lcd_return_to_status();
|
||||
}
|
||||
|
||||
bool IsStopped() { return Stopped; };
|
||||
|
@ -10754,20 +10847,27 @@ void long_pause() //long pause print
|
|||
start_pause_print = _millis();
|
||||
|
||||
// Stop heaters
|
||||
heating_status = HeatingStatus::NO_HEATING;
|
||||
setAllTargetHotends(0);
|
||||
|
||||
//lift z
|
||||
current_position[Z_AXIS] += Z_PAUSE_LIFT;
|
||||
clamp_to_software_endstops(current_position);
|
||||
plan_buffer_line_curposXYZE(15);
|
||||
// Lift z
|
||||
raise_z_above(current_position[Z_AXIS] + Z_PAUSE_LIFT, true);
|
||||
|
||||
//Move XY to side
|
||||
current_position[X_AXIS] = X_PAUSE_POS;
|
||||
current_position[Y_AXIS] = Y_PAUSE_POS;
|
||||
plan_buffer_line_curposXYZE(50);
|
||||
// Move XY to side
|
||||
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) {
|
||||
current_position[X_AXIS] = X_PAUSE_POS;
|
||||
current_position[Y_AXIS] = Y_PAUSE_POS;
|
||||
plan_buffer_line_curposXYZE(50);
|
||||
}
|
||||
|
||||
// Turn off the print fan
|
||||
fanSpeed = 0;
|
||||
// did we come here from a thermal error?
|
||||
if(get_temp_error()) {
|
||||
// time to stop the error beep
|
||||
WRITE(BEEPER, LOW);
|
||||
} else {
|
||||
// Turn off the print fan
|
||||
fanSpeed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void serialecho_temperatures() {
|
||||
|
@ -10871,6 +10971,7 @@ void uvlo_()
|
|||
|
||||
// Enable stepper driver interrupt to move Z axis. This should be fine as the planner and
|
||||
// command queues are empty, SD card printing is disabled, usb is inhibited.
|
||||
planner_aborted = false;
|
||||
sei();
|
||||
|
||||
// Retract
|
||||
|
@ -11003,6 +11104,7 @@ void uvlo_tiny()
|
|||
|
||||
// Enable stepper driver interrupt to move Z axis. This should be fine as the planner and
|
||||
// command queues are empty, SD card printing is disabled, usb is inhibited.
|
||||
planner_aborted = false;
|
||||
sei();
|
||||
|
||||
// The axis was moved: adjust Z as done on a regular UVLO.
|
||||
|
@ -11124,7 +11226,7 @@ void recover_print(uint8_t automatic) {
|
|||
// Set the target bed and nozzle temperatures and wait.
|
||||
sprintf_P(cmd, PSTR("M104 S%d"), target_temperature[active_extruder]);
|
||||
enquecommand(cmd);
|
||||
sprintf_P(cmd, PSTR("M190 S%d"), target_temperature_bed);
|
||||
sprintf_P(cmd, PSTR("M140 S%d"), target_temperature_bed);
|
||||
enquecommand(cmd);
|
||||
sprintf_P(cmd, PSTR("M109 S%d"), target_temperature[active_extruder]);
|
||||
enquecommand(cmd);
|
||||
|
@ -11472,8 +11574,9 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
|
|||
saved_feedmultiply2 = feedmultiply; //save feedmultiply
|
||||
saved_active_extruder = active_extruder; //save active_extruder
|
||||
saved_extruder_temperature = degTargetHotend(active_extruder);
|
||||
saved_bed_temperature = degBed();
|
||||
saved_extruder_relative_mode = axis_relative_modes & E_AXIS_MASK;
|
||||
saved_fanSpeed = fanSpeed;
|
||||
saved_fan_speed = fanSpeed;
|
||||
cmdqueue_reset(); //empty cmdqueue
|
||||
card.sdprinting = false;
|
||||
// card.closefile();
|
||||
|
@ -11482,7 +11585,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
|
|||
st_reset_timer();
|
||||
sei();
|
||||
if ((z_move != 0) || (e_move != 0)) { // extruder or z move
|
||||
#if 1
|
||||
|
||||
// Rather than calling plan_buffer_line directly, push the move into the command queue so that
|
||||
// the caller can continue processing. This is used during powerpanic to save the state as we
|
||||
// move away from the print.
|
||||
|
@ -11514,13 +11617,6 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
|
|||
// If this call is invoked from the main Arduino loop() function, let the caller know that the command
|
||||
// in the command queue is not the original command, but a new one, so it should not be removed from the queue.
|
||||
repeatcommand_front();
|
||||
#else
|
||||
plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], saved_pos[Z_AXIS] + z_move, saved_pos[E_AXIS] + e_move, homing_feedrate[Z_AXIS], active_extruder);
|
||||
st_synchronize(); //wait moving
|
||||
memcpy(current_position, saved_pos, sizeof(saved_pos));
|
||||
set_destination_to_current();
|
||||
#endif
|
||||
waiting_inside_plan_buffer_line_print_aborted = true; //unroll the stack
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11543,10 +11639,13 @@ void restore_print_from_ram_and_continue(float e_move)
|
|||
if (fan_check_error == EFCE_FIXED) fan_check_error = EFCE_OK; //reenable serial stream processing if printing from usb
|
||||
#endif
|
||||
|
||||
// for (int axis = X_AXIS; axis <= E_AXIS; axis++)
|
||||
// current_position[axis] = st_get_position_mm(axis);
|
||||
active_extruder = saved_active_extruder; //restore active_extruder
|
||||
fanSpeed = saved_fanSpeed;
|
||||
// restore bed temperature (bed can be disabled during a thermal warning)
|
||||
if (degBed() != saved_bed_temperature)
|
||||
setTargetBed(saved_bed_temperature);
|
||||
|
||||
// restore active_extruder
|
||||
active_extruder = saved_active_extruder;
|
||||
fanSpeed = saved_fan_speed;
|
||||
if (degTargetHotend(saved_active_extruder) != saved_extruder_temperature)
|
||||
{
|
||||
setTargetHotendSafe(saved_extruder_temperature, saved_active_extruder);
|
||||
|
@ -11604,7 +11703,7 @@ void restore_print_from_ram_and_continue(float e_move)
|
|||
lcd_setstatuspgm(MSG_WELCOME);
|
||||
saved_printing_type = PRINTING_TYPE_NONE;
|
||||
saved_printing = false;
|
||||
waiting_inside_plan_buffer_line_print_aborted = true; //unroll the stack
|
||||
planner_aborted = true; // unroll the stack
|
||||
}
|
||||
|
||||
// Cancel the state related to a currently saved print
|
||||
|
|
|
@ -77,5 +77,11 @@ T Timer<T>::elapsed() {
|
|||
return m_isRunning ? (_millis() - m_started) : 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Timer<T>::expired_cont(T msPeriod)
|
||||
{
|
||||
return !m_isRunning || expired(msPeriod);
|
||||
}
|
||||
|
||||
template class Timer<unsigned long>;
|
||||
template class Timer<unsigned short>;
|
||||
|
|
|
@ -21,8 +21,9 @@ public:
|
|||
void start();
|
||||
void stop(){m_isRunning = false;}
|
||||
bool running()const {return m_isRunning;}
|
||||
bool expired(T msPeriod);
|
||||
T elapsed();
|
||||
bool expired(T msPeriod); // returns true only once after expiration, then stops running
|
||||
T elapsed(); // returns the time in milliseconds since the timer was started or 0 otherwise
|
||||
bool expired_cont(T msPeriod); // return true when continuosly when expired / not running
|
||||
protected:
|
||||
T started()const {return m_started;}
|
||||
private:
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
//adc.c
|
||||
|
||||
#include "adc.h"
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "pins.h"
|
||||
|
||||
uint8_t adc_state;
|
||||
uint8_t adc_count;
|
||||
uint16_t adc_values[ADC_CHAN_CNT];
|
||||
uint16_t adc_sim_mask;
|
||||
|
||||
|
||||
#ifdef ADC_CALLBACK
|
||||
extern void ADC_CALLBACK(void);
|
||||
#endif //ADC_CALLBACK
|
||||
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
puts_P(PSTR("adc_init"));
|
||||
adc_sim_mask = 0x00;
|
||||
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
|
||||
ADMUX |= (1 << REFS0);
|
||||
ADCSRA |= (1 << ADEN);
|
||||
// ADCSRA |= (1 << ADIF) | (1 << ADSC);
|
||||
DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff);
|
||||
DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8);
|
||||
adc_reset();
|
||||
// adc_sim_mask = 0b0101;
|
||||
// adc_sim_mask = 0b100101;
|
||||
// adc_values[0] = 1023 * 16;
|
||||
// adc_values[2] = 1023 * 16;
|
||||
// adc_values[5] = 1002 * 16;
|
||||
}
|
||||
|
||||
void adc_reset(void)
|
||||
{
|
||||
adc_state = 0;
|
||||
adc_count = 0;
|
||||
uint8_t i; for (i = 0; i < ADC_CHAN_CNT; i++)
|
||||
if ((adc_sim_mask & (1 << i)) == 0)
|
||||
adc_values[i] = 0;
|
||||
}
|
||||
|
||||
void adc_setmux(uint8_t ch)
|
||||
{
|
||||
ch &= 0x0f;
|
||||
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
||||
else ADCSRB &= ~(1 << MUX5);
|
||||
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
||||
}
|
||||
|
||||
uint8_t adc_chan(uint8_t index)
|
||||
{
|
||||
uint8_t chan = 0;
|
||||
uint16_t mask = 1;
|
||||
while (mask)
|
||||
{
|
||||
if ((mask & ADC_CHAN_MSK) && (index-- == 0)) break;
|
||||
mask <<= 1;
|
||||
chan++;
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
void adc_cycle(void)
|
||||
{
|
||||
if (adc_state & 0x80)
|
||||
{
|
||||
uint8_t index = adc_state & 0x0f;
|
||||
if ((adc_sim_mask & (1 << index)) == 0)
|
||||
adc_values[index] += ADC;
|
||||
if (++index >= ADC_CHAN_CNT)
|
||||
{
|
||||
index = 0;
|
||||
adc_count++;
|
||||
if (adc_count >= ADC_OVRSAMPL)
|
||||
{
|
||||
#ifdef ADC_CALLBACK
|
||||
ADC_CALLBACK();
|
||||
#endif //ADC_CALLBACK
|
||||
adc_reset();
|
||||
}
|
||||
}
|
||||
adc_setmux(adc_chan(index));
|
||||
adc_state = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
adc_state |= 0x80;
|
||||
}
|
||||
}
|
81
Firmware/adc.cpp
Normal file
81
Firmware/adc.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include "adc.h"
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
#include "pins.h"
|
||||
|
||||
static uint8_t adc_count; //used for oversampling
|
||||
static uint8_t adc_channel_idx; //bitmask index
|
||||
volatile uint8_t adc_channel; //regular index
|
||||
volatile uint16_t adc_values[ADC_CHAN_CNT];
|
||||
|
||||
static void adc_reset();
|
||||
static void adc_setmux(uint8_t ch);
|
||||
|
||||
void adc_init()
|
||||
{
|
||||
puts_P(PSTR("adc_init"));
|
||||
DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff); //disable digital inputs PORTF
|
||||
DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8); //disable digital inputs PORTK
|
||||
ADMUX |= (1 << REFS0); //use AVCC as reference
|
||||
|
||||
//enable ADC, set prescaler/128, enable interrupt
|
||||
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIF) | (1 << ADIE);
|
||||
}
|
||||
|
||||
static void adc_reset()
|
||||
{
|
||||
static const uint8_t first_channel_idx = 0;
|
||||
static_assert((1 << first_channel_idx) & ADC_CHAN_MSK);
|
||||
|
||||
ADCSRA &= ~(1 << ADSC); //stop conversion just in case
|
||||
adc_count = 0;
|
||||
adc_channel = 0;
|
||||
adc_channel_idx = first_channel_idx;
|
||||
adc_setmux(adc_channel_idx);
|
||||
memset((void*)adc_values, 0, sizeof(adc_values));
|
||||
}
|
||||
|
||||
static void adc_setmux(uint8_t ch)
|
||||
{
|
||||
ch &= 0x0f;
|
||||
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
||||
else ADCSRB &= ~(1 << MUX5);
|
||||
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
||||
}
|
||||
|
||||
void adc_start_cycle() {
|
||||
adc_reset();
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
}
|
||||
|
||||
#ifdef ADC_CALLBACK
|
||||
extern void ADC_CALLBACK();
|
||||
#endif //ADC_CALLBACK
|
||||
|
||||
ISR(ADC_vect)
|
||||
{
|
||||
adc_values[adc_channel] += ADC;
|
||||
if (++adc_count == ADC_OVRSAMPL)
|
||||
{
|
||||
// go to the next channel
|
||||
if (++adc_channel == ADC_CHAN_CNT) {
|
||||
#ifdef ADC_CALLBACK
|
||||
ADC_CALLBACK();
|
||||
#endif
|
||||
return; // do not start the next measurement since there are no channels remaining
|
||||
}
|
||||
|
||||
// find the next channel
|
||||
while (++adc_channel_idx) {
|
||||
if (ADC_CHAN_MSK & (1 << adc_channel_idx)) {
|
||||
adc_setmux(adc_channel_idx);
|
||||
adc_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
}
|
|
@ -1,15 +1,8 @@
|
|||
//adc.h
|
||||
#ifndef _ADC_H
|
||||
#define _ADC_H
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif //defined(__cplusplus)
|
||||
|
||||
/*
|
||||
http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
||||
*/
|
||||
|
@ -22,24 +15,9 @@ http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
|||
# error "ADC_CHAN_MSK oes not match ADC_CHAN_CNT"
|
||||
#endif
|
||||
|
||||
extern uint8_t adc_state;
|
||||
extern uint8_t adc_count;
|
||||
extern uint16_t adc_values[ADC_CHAN_CNT];
|
||||
extern uint16_t adc_sim_mask;
|
||||
extern volatile uint8_t adc_channel;
|
||||
extern volatile uint16_t adc_values[ADC_CHAN_CNT];
|
||||
|
||||
|
||||
extern void adc_init(void);
|
||||
|
||||
extern void adc_reset(void);
|
||||
|
||||
extern void adc_setmux(uint8_t ch);
|
||||
|
||||
extern uint8_t adc_chan(uint8_t index);
|
||||
|
||||
extern void adc_cycle(void);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif //defined(__cplusplus)
|
||||
#endif //_ADC_H
|
||||
extern void adc_init();
|
||||
extern void adc_start_cycle(); //should be called from an atomic context only
|
||||
static inline bool adc_cycle_done() { return adc_channel >= ADC_CHAN_CNT; }
|
||||
|
|
|
@ -28,7 +28,6 @@ ShortTimer serialTimeoutTimer;
|
|||
|
||||
long gcode_N = 0;
|
||||
long gcode_LastN = 0;
|
||||
long Stopped_gcode_LastN = 0;
|
||||
|
||||
uint32_t sdpos_atomic = 0;
|
||||
|
||||
|
@ -464,8 +463,6 @@ void get_command()
|
|||
|
||||
// Don't parse N again with code_seen('N')
|
||||
cmdbuffer[bufindw + CMDHDRSIZE] = '$';
|
||||
//if no errors, continue parsing
|
||||
gcode_LastN = gcode_N;
|
||||
}
|
||||
// if we don't receive 'N' but still see '*'
|
||||
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
||||
|
@ -478,35 +475,48 @@ void get_command()
|
|||
serial_count = 0;
|
||||
return;
|
||||
}
|
||||
// Handle KILL early, even when Stopped
|
||||
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
||||
kill(MSG_M112_KILL, 2);
|
||||
// Handle the USB timer
|
||||
if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
|
||||
if (!IS_SD_PRINTING) {
|
||||
usb_timer.start();
|
||||
}
|
||||
if (Stopped == true) {
|
||||
if (code_value_uint8() <= 3) {
|
||||
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
|
||||
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
||||
}
|
||||
}
|
||||
} // end of 'G' command
|
||||
}
|
||||
if (Stopped == true) {
|
||||
// Stopped can be set either during error states (thermal error: cannot continue), or
|
||||
// when a printer-initiated action is processed. In such case the printer will send to
|
||||
// the host an action, but cannot know if the action has been processed while new
|
||||
// commands are being sent. In this situation we just drop the command while issuing
|
||||
// periodic "busy" messages in the main loop. Since we're not incrementing the received
|
||||
// line number, a request for resend will happen (if necessary), ensuring we don't skip
|
||||
// commands whenever Stopped is cleared and processing resumes.
|
||||
serial_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Command is complete: store the current line into buffer, move to the next line.
|
||||
|
||||
//If command was e-stop process now
|
||||
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
||||
kill(MSG_M112_KILL, 2);
|
||||
|
||||
// Store the current line into buffer, move to the next line.
|
||||
// Store type of entry
|
||||
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
||||
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOPGM("Storing a command line to buffer: ");
|
||||
SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
|
||||
// Store command itself
|
||||
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||
if (bufindw == sizeof(cmdbuffer))
|
||||
bufindw = 0;
|
||||
++ buflen;
|
||||
|
||||
// Update the processed gcode line
|
||||
gcode_LastN = gcode_N;
|
||||
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
SERIAL_ECHOPGM("Number of commands in the buffer: ");
|
||||
SERIAL_ECHO(buflen);
|
||||
|
|
|
@ -54,7 +54,6 @@ extern char *strchr_pointer;
|
|||
|
||||
extern long gcode_N;
|
||||
extern long gcode_LastN;
|
||||
extern long Stopped_gcode_LastN;
|
||||
|
||||
extern bool cmdqueue_pop_front();
|
||||
extern void cmdqueue_reset();
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "pins.h"
|
||||
|
||||
#if (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
|
||||
# define IR_SENSOR_ANALOG
|
||||
// TODO: IR_SENSOR_ANALOG currently disabled as being incompatible with the new thermal regulation
|
||||
// # define IR_SENSOR_ANALOG
|
||||
#endif
|
||||
|
||||
//ADC configuration
|
||||
|
@ -20,7 +21,7 @@
|
|||
#define ADC_CHAN_CNT 8 //number of used channels)
|
||||
#endif //!IR_SENSOR_ANALOG
|
||||
#define ADC_OVRSAMPL 16 //oversampling multiplier
|
||||
#define ADC_CALLBACK adc_ready //callback function ()
|
||||
#define ADC_CALLBACK adc_callback //callback function ()
|
||||
|
||||
//SWI2C configuration
|
||||
//#define SWI2C_SDA 20 //SDA on P3
|
||||
|
|
|
@ -550,8 +550,16 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
|
|||
#define EEPROM_ECOOL_ENABLE (EEPROM_JOB_ID-1) // uint8_t
|
||||
#define EEPROM_FW_CRASH_FLAG (EEPROM_ECOOL_ENABLE-1) // uint8_t
|
||||
|
||||
#define EEPROM_TEMP_MODEL_ENABLE (EEPROM_FW_CRASH_FLAG-1) // uint8_t
|
||||
#define EEPROM_TEMP_MODEL_P (EEPROM_TEMP_MODEL_ENABLE-4) // float
|
||||
#define EEPROM_TEMP_MODEL_C (EEPROM_TEMP_MODEL_P-4) // float
|
||||
#define EEPROM_TEMP_MODEL_R (EEPROM_TEMP_MODEL_C-4*16) // float[16]
|
||||
#define EEPROM_TEMP_MODEL_Ta_corr (EEPROM_TEMP_MODEL_R-4) // float
|
||||
#define EEPROM_TEMP_MODEL_W (EEPROM_TEMP_MODEL_Ta_corr-4) // float
|
||||
#define EEPROM_TEMP_MODEL_E (EEPROM_TEMP_MODEL_W-4) // float
|
||||
|
||||
//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
|
||||
#define EEPROM_LAST_ITEM EEPROM_FW_CRASH_FLAG
|
||||
#define EEPROM_LAST_ITEM EEPROM_TEMP_MODEL_E
|
||||
// !!!!!
|
||||
// !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
|
||||
// !!!!!
|
||||
|
|
300
Firmware/fancheck.cpp
Executable file
300
Firmware/fancheck.cpp
Executable file
|
@ -0,0 +1,300 @@
|
|||
// fan control and check
|
||||
#include "fancheck.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
#include "sound.h"
|
||||
#include "messages.h"
|
||||
#include "temperature.h"
|
||||
#include "stepper.h"
|
||||
|
||||
#define FAN_CHECK_PERIOD 5000 //5s
|
||||
#define FAN_CHECK_DURATION 100 //100ms
|
||||
|
||||
#ifdef FANCHECK
|
||||
volatile uint8_t fan_check_error = EFCE_OK;
|
||||
#endif
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
static struct
|
||||
{
|
||||
uint8_t isAltfan : 1;
|
||||
uint8_t altfanOverride : 1;
|
||||
} altfanStatus;
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
unsigned long extruder_autofan_last_check = _millis();
|
||||
bool fan_measuring = false;
|
||||
static uint8_t fanState = 0;
|
||||
#endif
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#if defined(FAN_PIN) && FAN_PIN > -1
|
||||
#if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN
|
||||
#error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void setExtruderAutoFanState(uint8_t state)
|
||||
{
|
||||
//If bit 1 is set (0x02), then the extruder fan speed won't be adjusted according to temperature. Useful for forcing
|
||||
//the fan to either On or Off during certain tests/errors.
|
||||
|
||||
fanState = state;
|
||||
newFanSpeed = 0;
|
||||
if (fanState & 0x01)
|
||||
{
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT;
|
||||
else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
|
||||
#else //EXTRUDER_ALTFAN_DETECT
|
||||
newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
}
|
||||
timer4_set_fan0(newFanSpeed);
|
||||
}
|
||||
|
||||
#if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1)))))
|
||||
|
||||
void countFanSpeed()
|
||||
{
|
||||
//SERIAL_ECHOPGM("edge counter 1:"); MYSERIAL.println(fan_edge_counter[1]);
|
||||
fan_speed[0] = (fan_edge_counter[0] * (float(250) / (_millis() - extruder_autofan_last_check)));
|
||||
fan_speed[1] = (fan_edge_counter[1] * (float(250) / (_millis() - extruder_autofan_last_check)));
|
||||
/*SERIAL_ECHOPGM("time interval: "); MYSERIAL.println(_millis() - extruder_autofan_last_check);
|
||||
SERIAL_ECHOPGM("extruder fan speed:"); MYSERIAL.print(fan_speed[0]); SERIAL_ECHOPGM("; edge counter:"); MYSERIAL.println(fan_edge_counter[0]);
|
||||
SERIAL_ECHOPGM("print fan speed:"); MYSERIAL.print(fan_speed[1]); SERIAL_ECHOPGM("; edge counter:"); MYSERIAL.println(fan_edge_counter[1]);
|
||||
SERIAL_ECHOLNPGM(" ");*/
|
||||
fan_edge_counter[0] = 0;
|
||||
fan_edge_counter[1] = 0;
|
||||
}
|
||||
|
||||
//! Prints serialMsg to serial port, displays lcdMsg onto the LCD and beeps.
|
||||
//! Extracted from fanSpeedError to save some space.
|
||||
//! @param serialMsg pointer into PROGMEM, this text will be printed to the serial port
|
||||
//! @param lcdMsg pointer into PROGMEM, this text will be printed onto the LCD
|
||||
static void fanSpeedErrorBeep(const char *serialMsg, const char *lcdMsg){
|
||||
SERIAL_ECHOLNRPGM(serialMsg);
|
||||
if (get_message_level() == 0) {
|
||||
Sound_MakeCustom(200,0,true);
|
||||
LCD_ALERTMESSAGERPGM(lcdMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void fanSpeedError(unsigned char _fan) {
|
||||
if (fan_check_error == EFCE_REPORTED) return;
|
||||
fan_check_error = EFCE_REPORTED;
|
||||
|
||||
if (IS_SD_PRINTING || usb_timer.running()) {
|
||||
// A print is ongoing, pause the print normally
|
||||
if(!isPrintPaused) {
|
||||
if (usb_timer.running())
|
||||
lcd_pause_usb_print();
|
||||
else
|
||||
lcd_pause_print();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Nothing is going on, but still turn off heaters and report the error
|
||||
setTargetHotend0(0);
|
||||
heating_status = HeatingStatus::NO_HEATING;
|
||||
}
|
||||
switch (_fan) {
|
||||
case 0: // extracting the same code from case 0 and case 1 into a function saves 72B
|
||||
fanSpeedErrorBeep(PSTR("Extruder fan speed is lower than expected"), MSG_FANCHECK_EXTRUDER);
|
||||
break;
|
||||
case 1:
|
||||
fanSpeedErrorBeep(PSTR("Print fan speed is lower than expected"), MSG_FANCHECK_PRINT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void checkFanSpeed()
|
||||
{
|
||||
uint8_t max_fan_errors[2];
|
||||
#ifdef FAN_SOFT_PWM
|
||||
max_fan_errors[1] = 3; // 15 seconds (Print fan)
|
||||
max_fan_errors[0] = 2; // 10 seconds (Extruder fan)
|
||||
#else //FAN_SOFT_PWM
|
||||
max_fan_errors[1] = 15; // 15 seconds (Print fan)
|
||||
max_fan_errors[0] = 5; // 5 seconds (Extruder fan)
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
if(fans_check_enabled)
|
||||
fans_check_enabled = (eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED) > 0);
|
||||
static uint8_t fan_speed_errors[2] = { 0,0 };
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 >-1))
|
||||
if ((fan_speed[0] < 20) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
|
||||
else fan_speed_errors[0] = 0;
|
||||
#endif
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
if ((fan_speed[1] < 5) && ((blocks_queued() ? block_buffer[block_buffer_tail].fan_speed : fanSpeed) > MIN_PRINT_FAN_SPEED)) fan_speed_errors[1]++;
|
||||
else fan_speed_errors[1] = 0;
|
||||
#endif
|
||||
|
||||
// drop the fan_check_error flag when both fans are ok
|
||||
if( fan_speed_errors[0] == 0 && fan_speed_errors[1] == 0 && fan_check_error == EFCE_REPORTED){
|
||||
// we may even send some info to the LCD from here
|
||||
fan_check_error = EFCE_FIXED;
|
||||
}
|
||||
if ((fan_check_error == EFCE_FIXED) && !PRINTER_ACTIVE){
|
||||
fan_check_error = EFCE_OK; //if the issue is fixed while the printer is doing nothing, reenable processing immediately.
|
||||
lcd_reset_alert_level(); //for another fan speed error
|
||||
}
|
||||
if (fans_check_enabled && (fan_check_error == EFCE_OK))
|
||||
{
|
||||
for (uint8_t fan = 0; fan < 2; fan++)
|
||||
{
|
||||
if (fan_speed_errors[fan] > max_fan_errors[fan])
|
||||
{
|
||||
fan_speed_errors[fan] = 0;
|
||||
fanSpeedError(fan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //(defined(TACH_0) && TACH_0 >-1) || (defined(TACH_1) && TACH_1 > -1)
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
ISR(INT6_vect) {
|
||||
fan_edge_counter[0]++;
|
||||
}
|
||||
|
||||
bool extruder_altfan_detect()
|
||||
{
|
||||
setExtruderAutoFanState(3);
|
||||
|
||||
SET_INPUT(TACH_0);
|
||||
|
||||
uint8_t overrideVal = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE);
|
||||
if (overrideVal == EEPROM_EMPTY_VALUE)
|
||||
{
|
||||
overrideVal = (calibration_status() == CALIBRATION_STATUS_CALIBRATED) ? 1 : 0;
|
||||
eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, overrideVal);
|
||||
}
|
||||
altfanStatus.altfanOverride = overrideVal;
|
||||
|
||||
CRITICAL_SECTION_START;
|
||||
EICRB &= ~(1 << ISC61);
|
||||
EICRB |= (1 << ISC60);
|
||||
EIMSK |= (1 << INT6);
|
||||
fan_edge_counter[0] = 0;
|
||||
CRITICAL_SECTION_END;
|
||||
extruder_autofan_last_check = _millis();
|
||||
|
||||
_delay(1000);
|
||||
|
||||
EIMSK &= ~(1 << INT6);
|
||||
|
||||
countFanSpeed();
|
||||
altfanStatus.isAltfan = fan_speed[0] > 100;
|
||||
setExtruderAutoFanState(1);
|
||||
return altfanStatus.isAltfan;
|
||||
}
|
||||
|
||||
void altfanOverride_toggle()
|
||||
{
|
||||
altfanStatus.altfanOverride = !altfanStatus.altfanOverride;
|
||||
eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanStatus.altfanOverride);
|
||||
}
|
||||
|
||||
bool altfanOverride_get()
|
||||
{
|
||||
return altfanStatus.altfanOverride;
|
||||
}
|
||||
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
void checkExtruderAutoFans()
|
||||
{
|
||||
#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
|
||||
if (!(fanState & 0x02))
|
||||
{
|
||||
fanState &= ~1;
|
||||
fanState |= current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE;
|
||||
fanState |= get_temp_error();
|
||||
}
|
||||
setExtruderAutoFanState(fanState);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // any extruder auto fan pins set
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
void readFanTach() {
|
||||
#ifdef FAN_SOFT_PWM
|
||||
if (READ(TACH_0) != fan_state[0]) {
|
||||
if(fan_measuring) fan_edge_counter[0] ++;
|
||||
fan_state[0] = !fan_state[0];
|
||||
}
|
||||
#else //FAN_SOFT_PWM
|
||||
if (READ(TACH_0) != fan_state[0]) {
|
||||
fan_edge_counter[0] ++;
|
||||
fan_state[0] = !fan_state[0];
|
||||
}
|
||||
#endif
|
||||
//if (READ(TACH_1) != fan_state[1]) {
|
||||
// fan_edge_counter[1] ++;
|
||||
// fan_state[1] = !fan_state[1];
|
||||
//}
|
||||
}
|
||||
#endif //TACH_0
|
||||
|
||||
void checkFans()
|
||||
{
|
||||
#ifndef DEBUG_DISABLE_FANCHECK
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
|
||||
#ifdef FAN_SOFT_PWM
|
||||
#ifdef FANCHECK
|
||||
if ((_millis() - extruder_autofan_last_check > FAN_CHECK_PERIOD) && (!fan_measuring)) {
|
||||
extruder_autofan_last_check = _millis();
|
||||
fanSpeedBckp = fanSpeedSoftPwm;
|
||||
|
||||
if (fanSpeedSoftPwm >= MIN_PRINT_FAN_SPEED) { //if we are in rage where we are doing fan check, set full PWM range for a short time to measure fan RPM by reading tacho signal without modulation by PWM signal
|
||||
// printf_P(PSTR("fanSpeedSoftPwm 1: %d\n"), fanSpeedSoftPwm);
|
||||
fanSpeedSoftPwm = 255;
|
||||
}
|
||||
fan_measuring = true;
|
||||
}
|
||||
if ((_millis() - extruder_autofan_last_check > FAN_CHECK_DURATION) && (fan_measuring)) {
|
||||
countFanSpeed();
|
||||
checkFanSpeed();
|
||||
//printf_P(PSTR("fanSpeedSoftPwm 1: %d\n"), fanSpeedSoftPwm);
|
||||
fanSpeedSoftPwm = fanSpeedBckp;
|
||||
//printf_P(PSTR("fan PWM: %d; extr fanSpeed measured: %d; print fan speed measured: %d \n"), fanSpeedBckp, fan_speed[0], fan_speed[1]);
|
||||
extruder_autofan_last_check = _millis();
|
||||
fan_measuring = false;
|
||||
}
|
||||
#endif //FANCHECK
|
||||
checkExtruderAutoFans();
|
||||
#else //FAN_SOFT_PWM
|
||||
if(_millis() - extruder_autofan_last_check > 1000) // only need to check fan state very infrequently
|
||||
{
|
||||
#if (defined(FANCHECK) && ((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1))))
|
||||
countFanSpeed();
|
||||
checkFanSpeed();
|
||||
#endif //(defined(TACH_0) && TACH_0 >-1) || (defined(TACH_1) && TACH_1 > -1)
|
||||
checkExtruderAutoFans();
|
||||
extruder_autofan_last_check = _millis();
|
||||
}
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
#endif
|
||||
#endif //DEBUG_DISABLE_FANCHECK
|
||||
}
|
||||
|
||||
void hotendFanSetFullSpeed()
|
||||
{
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
altfanStatus.altfanOverride = 1; //full speed
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
setExtruderAutoFanState(3);
|
||||
SET_OUTPUT(FAN_PIN);
|
||||
#ifdef FAN_SOFT_PWM
|
||||
fanSpeedSoftPwm = 255;
|
||||
#else //FAN_SOFT_PWM
|
||||
analogWrite(FAN_PIN, 255);
|
||||
#endif //FAN_SOFT_PWM
|
||||
fanSpeed = 255;
|
||||
}
|
35
Firmware/fancheck.h
Executable file
35
Firmware/fancheck.h
Executable file
|
@ -0,0 +1,35 @@
|
|||
// fan control and check
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "config.h"
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
enum {
|
||||
EFCE_OK = 0, //!< normal operation, both fans are ok
|
||||
EFCE_FIXED, //!< previous fan error was fixed
|
||||
EFCE_REPORTED //!< fan error detected and reported to LCD and serial
|
||||
};
|
||||
extern volatile uint8_t fan_check_error;
|
||||
|
||||
void readFanTach();
|
||||
#endif //(defined(TACH_0))
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
extern bool extruder_altfan_detect();
|
||||
extern void altfanOverride_toggle();
|
||||
extern bool altfanOverride_get();
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#ifdef FAN_SOFT_PWM
|
||||
extern bool fan_measuring;
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
extern unsigned long extruder_autofan_last_check;
|
||||
void setExtruderAutoFanState(uint8_t state);
|
||||
void checkExtruderAutoFans();
|
||||
#endif
|
||||
|
||||
void checkFans();
|
||||
void hotendFanSetFullSpeed();
|
|
@ -688,62 +688,8 @@ void fsensor_update(void)
|
|||
{
|
||||
if (READ(IR_SENSOR_PIN))
|
||||
{ // IR_SENSOR_PIN ~ H
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
if(!bIRsensorStateFlag)
|
||||
{
|
||||
bIRsensorStateFlag=true;
|
||||
tIRsensorCheckTimer.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tIRsensorCheckTimer.expired(IR_SENSOR_STEADY))
|
||||
{
|
||||
uint8_t nMUX1,nMUX2;
|
||||
uint16_t nADC;
|
||||
bIRsensorStateFlag=false;
|
||||
// sequence for direct data reading from AD converter
|
||||
DISABLE_TEMPERATURE_INTERRUPT();
|
||||
nMUX1=ADMUX; // ADMUX saving
|
||||
nMUX2=ADCSRB;
|
||||
adc_setmux(VOLT_IR_PIN);
|
||||
ADCSRA|=(1<<ADSC); // first conversion after ADMUX change discarded (preventively)
|
||||
while(ADCSRA&(1<<ADSC))
|
||||
;
|
||||
ADCSRA|=(1<<ADSC); // second conversion used
|
||||
while(ADCSRA&(1<<ADSC))
|
||||
;
|
||||
nADC=ADC;
|
||||
ADMUX=nMUX1; // ADMUX restoring
|
||||
ADCSRB=nMUX2;
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
// end of sequence for ...
|
||||
// Detection of correct function of fsensor v04 - it must NOT read >4.6V
|
||||
// If it does, it means a disconnected cables or faulty board
|
||||
if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) )
|
||||
{
|
||||
fsensor_disable();
|
||||
fsensor_not_responding = true;
|
||||
printf_P(PSTR("IR sensor not responding (%d)!\n"),1);
|
||||
if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause)
|
||||
|
||||
// if we are printing and FS action is set to "Pause", force pause the print
|
||||
if(oFsensorActionNA==ClFsensorActionNA::_Pause)
|
||||
lcd_pause_print();
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
fsensor_checkpoint_print();
|
||||
fsensor_enque_M600();
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // IR_SENSOR_PIN ~ L
|
||||
bIRsensorStateFlag=false;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
fsensor_checkpoint_print();
|
||||
fsensor_enque_M600();
|
||||
}
|
||||
}
|
||||
#endif //PAT9125
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#endif //CRITICAL_SECTION_START
|
||||
|
||||
#define _REGNAME(registerbase,number,suffix) registerbase##number##suffix
|
||||
#define _REGNAME_SHORT(registerbase,suffix) registerbase##suffix
|
||||
|
||||
// Macros to make a string from a macro
|
||||
#define STRINGIFY_(M) #M
|
||||
#define STRINGIFY(M) STRINGIFY_(M)
|
||||
|
|
|
@ -24,7 +24,7 @@ uint8_t menu_data[MENU_DATA_SIZE];
|
|||
#endif
|
||||
|
||||
uint8_t menu_depth = 0;
|
||||
uint8_t menu_block_entering_on_serious_errors = SERIOUS_ERR_NONE;
|
||||
uint8_t menu_block_mask = MENU_BLOCK_NONE;
|
||||
uint8_t menu_line = 0;
|
||||
uint8_t menu_item = 0;
|
||||
uint8_t menu_row = 0;
|
||||
|
|
|
@ -29,26 +29,26 @@ extern uint8_t menu_data[MENU_DATA_SIZE];
|
|||
|
||||
extern uint8_t menu_depth;
|
||||
|
||||
//! definition of serious errors possibly blocking the main menu
|
||||
//! definition of reasons blocking the main menu
|
||||
//! Use them as bit mask, so that the code may set various errors at the same time
|
||||
enum ESeriousErrors {
|
||||
SERIOUS_ERR_NONE = 0,
|
||||
SERIOUS_ERR_MINTEMP_HEATER = 0x01,
|
||||
SERIOUS_ERR_MINTEMP_BED = 0x02
|
||||
MENU_BLOCK_NONE = 0,
|
||||
MENU_BLOCK_THERMAL_ERROR = 0x01,
|
||||
#ifdef TEMP_MODEL
|
||||
MENU_BLOCK_TEMP_MODEL_AUTOTUNE = 0x02,
|
||||
#endif
|
||||
}; // and possibly others in the future.
|
||||
|
||||
//! this is a flag for disabling entering the main menu. If this is set
|
||||
//! to anything != 0, the only the main status screen will be shown on the
|
||||
//! LCD and the user will be prevented from entering the menu.
|
||||
//! Now used only to block doing anything with the printer when there is
|
||||
//! the infamous MINTEMP error (SERIOUS_ERR_MINTEMP).
|
||||
extern uint8_t menu_block_entering_on_serious_errors;
|
||||
//! this is a flag for disabling entering the main menu and longpress. If this is set to anything !=
|
||||
//! 0, the only the main status screen will be shown on the LCD and the user will be prevented from
|
||||
//! entering the menu.
|
||||
extern uint8_t menu_block_mask;
|
||||
|
||||
//! a pair of macros for manipulating the serious errors
|
||||
//! a pair of macros for manipulating menu entry
|
||||
//! a c++ class would have been better
|
||||
#define menu_set_serious_error(x) menu_block_entering_on_serious_errors |= x;
|
||||
#define menu_unset_serious_error(x) menu_block_entering_on_serious_errors &= ~x;
|
||||
#define menu_is_serious_error(x) (menu_block_entering_on_serious_errors & x) != 0
|
||||
#define menu_set_block(x) menu_block_mask |= x;
|
||||
#define menu_unset_block(x) menu_block_mask &= ~x;
|
||||
#define menu_is_blocked(x) (menu_block_mask & x) != 0
|
||||
|
||||
extern uint8_t menu_line;
|
||||
extern uint8_t menu_item;
|
||||
|
|
|
@ -159,6 +159,10 @@ const char MSG_IR_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////MSG_IR_04
|
|||
const char MSG_IR_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////MSG_IR_03_OR_OLDER c=18
|
||||
const char MSG_IR_UNKNOWN[] PROGMEM_I1 = ISTR("unknown state");////MSG_IR_UNKNOWN c=18
|
||||
#endif
|
||||
#ifdef TEMP_MODEL
|
||||
extern const char MSG_THERMAL_ANOMALY[] PROGMEM_I1 = ISTR("THERMAL ANOMALY");////c=20
|
||||
extern const char MSG_PAUSED_THERMAL_ERROR[] PROGMEM_I1 = ISTR("PAUSED THERMAL ERROR");////c=20
|
||||
#endif
|
||||
|
||||
//not internationalized messages
|
||||
const char MSG_AUTO_DEPLETE[] PROGMEM_N1 = ISTR("SpoolJoin"); ////MSG_AUTO_DEPLETE c=13
|
||||
|
@ -186,11 +190,11 @@ const char MSG_OK[] PROGMEM_N1 = "ok"; ////
|
|||
const char MSG_SD_OPEN_FILE_FAIL[] PROGMEM_N1 = "open failed, File: "; ////
|
||||
const char MSG_ENDSTOP_OPEN[] PROGMEM_N1 = "open"; ////
|
||||
const char MSG_POWERUP[] PROGMEM_N1 = "PowerUp"; ////
|
||||
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"; ////
|
||||
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Supervision required."; ////
|
||||
const char MSG_ENDSTOP_HIT[] PROGMEM_N1 = "TRIGGERED"; ////
|
||||
const char MSG_OCTOPRINT_PAUSE[] PROGMEM_N1 = "// action:pause"; ////
|
||||
const char MSG_OCTOPRINT_ASK_PAUSE[] PROGMEM_N1 = "// action:pause"; ////
|
||||
const char MSG_OCTOPRINT_PAUSED[] PROGMEM_N1 = "// action:paused"; ////
|
||||
const char MSG_OCTOPRINT_RESUME[] PROGMEM_N1 = "// action:resume"; ////
|
||||
const char MSG_OCTOPRINT_ASK_RESUME[] PROGMEM_N1 = "// action:resume"; ////
|
||||
const char MSG_OCTOPRINT_RESUMED[] PROGMEM_N1 = "// action:resumed"; ////
|
||||
const char MSG_OCTOPRINT_CANCEL[] PROGMEM_N1 = "// action:cancel"; ////
|
||||
const char MSG_FANCHECK_EXTRUDER[] PROGMEM_N1 = "Err: EXTR. FAN ERROR"; ////c=20
|
||||
|
|
|
@ -168,6 +168,10 @@ extern const char MSG_IR_04_OR_NEWER[];
|
|||
extern const char MSG_IR_03_OR_OLDER[];
|
||||
extern const char MSG_IR_UNKNOWN[];
|
||||
#endif
|
||||
#ifdef TEMP_MODEL
|
||||
extern const char MSG_THERMAL_ANOMALY[];
|
||||
extern const char MSG_PAUSED_THERMAL_ERROR[];
|
||||
#endif
|
||||
|
||||
//not internationalized messages
|
||||
extern const char MSG_BROWNOUT_RESET[];
|
||||
|
@ -193,9 +197,9 @@ extern const char MSG_ERR_STOPPED[];
|
|||
extern const char MSG_ENDSTOP_HIT[];
|
||||
extern const char MSG_EJECT_FILAMENT[];
|
||||
extern const char MSG_CUT_FILAMENT[];
|
||||
extern const char MSG_OCTOPRINT_PAUSE[];
|
||||
extern const char MSG_OCTOPRINT_ASK_PAUSE[];
|
||||
extern const char MSG_OCTOPRINT_PAUSED[];
|
||||
extern const char MSG_OCTOPRINT_RESUME[];
|
||||
extern const char MSG_OCTOPRINT_ASK_RESUME[];
|
||||
extern const char MSG_OCTOPRINT_RESUMED[];
|
||||
extern const char MSG_OCTOPRINT_CANCEL[];
|
||||
extern const char MSG_FANCHECK_EXTRUDER[];
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "fsensor.h"
|
||||
#include "cardreader.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "stepper.h"
|
||||
#include "ultralcd.h"
|
||||
#include "menu.h"
|
||||
#include "sound.h"
|
||||
|
|
|
@ -151,7 +151,7 @@ void mc_arc(float* position, float* target, float* offset, float feed_rate, floa
|
|||
// Insert the segment into the buffer
|
||||
plan_buffer_line(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS], feed_rate, extruder, position);
|
||||
// Handle the situation where the planner is aborted hard.
|
||||
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||
if (planner_aborted)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,9 @@
|
|||
#define VOLT_IR_PIN 8 //A8
|
||||
|
||||
|
||||
#define TEMP_TIM 5
|
||||
|
||||
|
||||
#define E0_TMC2130_CS 66
|
||||
#define E0_TMC2130_DIAG 65
|
||||
#define E0_STEP_PIN 34
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#define TEMP_PINDA_PIN 1 //A1
|
||||
|
||||
|
||||
#define TEMP_TIM 3
|
||||
|
||||
|
||||
#define E0_STEP_PIN 34
|
||||
#define E0_DIR_PIN 43
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
#define TEMP_PINDA_PIN 1 //A1
|
||||
|
||||
|
||||
#define TEMP_TIM 3
|
||||
|
||||
|
||||
#define E0_STEP_PIN 34
|
||||
#define E0_DIR_PIN 43
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "planner.h"
|
||||
#include "stepper.h"
|
||||
#include "temperature.h"
|
||||
#include "fancheck.h"
|
||||
#include "ultralcd.h"
|
||||
#include "language.h"
|
||||
#include "ConfigurationStore.h"
|
||||
|
@ -68,6 +69,9 @@
|
|||
#include "tmc2130.h"
|
||||
#endif //TMC2130
|
||||
|
||||
#include <util/atomic.h>
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//=============================public variables ============================
|
||||
//===========================================================================
|
||||
|
@ -592,17 +596,7 @@ void check_axes_activity()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool waiting_inside_plan_buffer_line_print_aborted = false;
|
||||
/*
|
||||
void planner_abort_soft()
|
||||
{
|
||||
// Empty the queue.
|
||||
while (blocks_queued()) plan_discard_current_block();
|
||||
// Relay to planner wait routine, that the current line shall be canceled.
|
||||
waiting_inside_plan_buffer_line_print_aborted = true;
|
||||
//current_position[i]
|
||||
}
|
||||
*/
|
||||
bool planner_aborted = false;
|
||||
|
||||
#ifdef PLANNER_DIAGNOSTICS
|
||||
static inline void planner_update_queue_min_counter()
|
||||
|
@ -615,12 +609,8 @@ static inline void planner_update_queue_min_counter()
|
|||
|
||||
extern volatile uint32_t step_events_completed; // The number of step events executed in the current block
|
||||
|
||||
void planner_abort_hard()
|
||||
void planner_reset_position()
|
||||
{
|
||||
// Abort the stepper routine and flush the planner queue.
|
||||
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
// Now the front-end (the Marlin_main.cpp with its current_position) is out of sync.
|
||||
// First update the planner's current position in the physical motor steps.
|
||||
position[X_AXIS] = st_get_position(X_AXIS);
|
||||
position[Y_AXIS] = st_get_position(Y_AXIS);
|
||||
|
@ -632,6 +622,7 @@ void planner_abort_hard()
|
|||
current_position[Y_AXIS] = st_get_position_mm(Y_AXIS);
|
||||
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
|
||||
current_position[E_AXIS] = st_get_position_mm(E_AXIS);
|
||||
|
||||
// Apply the mesh bed leveling correction to the Z axis.
|
||||
#ifdef MESH_BED_LEVELING
|
||||
if (mbl.active) {
|
||||
|
@ -664,8 +655,6 @@ void planner_abort_hard()
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
// Clear the planner queue, reset and re-enable the stepper timer.
|
||||
quickStop();
|
||||
|
||||
// Apply inverse world correction matrix.
|
||||
machine2world(current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
|
@ -673,15 +662,29 @@ void planner_abort_hard()
|
|||
#ifdef LIN_ADVANCE
|
||||
memcpy(position_float, current_position, sizeof(position_float));
|
||||
#endif
|
||||
}
|
||||
|
||||
void planner_abort_hard()
|
||||
{
|
||||
// Abort the stepper routine and flush the planner queue.
|
||||
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
// Now the front-end (the Marlin_main.cpp with its current_position) is out of sync.
|
||||
planner_reset_position();
|
||||
|
||||
// Relay to planner wait routine that the current line shall be canceled.
|
||||
planner_aborted = true;
|
||||
|
||||
// Clear the planner queue, reset and re-enable the stepper timer.
|
||||
quickStop();
|
||||
|
||||
// Resets planner junction speeds. Assumes start from rest.
|
||||
previous_nominal_speed = 0.0;
|
||||
memset(previous_speed, 0, sizeof(previous_speed));
|
||||
|
||||
// Reset position sync requests
|
||||
plan_reset_next_e_queue = false;
|
||||
plan_reset_next_e_sched = false;
|
||||
|
||||
// Relay to planner wait routine, that the current line shall be canceled.
|
||||
waiting_inside_plan_buffer_line_print_aborted = true;
|
||||
}
|
||||
|
||||
void plan_buffer_line_curposXYZE(float feed_rate) {
|
||||
|
@ -702,12 +705,11 @@ float junction_deviation = 0.1;
|
|||
// calculation the caller must also provide the physical length of the line in millimeters.
|
||||
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, uint8_t extruder, const float* gcode_target)
|
||||
{
|
||||
// Calculate the buffer head after we push this byte
|
||||
// Calculate the buffer head after we push this byte
|
||||
uint8_t next_buffer_head = next_block_index(block_buffer_head);
|
||||
|
||||
// If the buffer is full: good! That means we are well ahead of the robot.
|
||||
// If the buffer is full: good! That means we are well ahead of the robot.
|
||||
// Rest here until there is room in the buffer.
|
||||
waiting_inside_plan_buffer_line_print_aborted = false;
|
||||
if (block_buffer_tail == next_buffer_head) {
|
||||
do {
|
||||
manage_heater();
|
||||
|
@ -715,18 +717,14 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
|
|||
manage_inactivity(false);
|
||||
lcd_update(0);
|
||||
} while (block_buffer_tail == next_buffer_head);
|
||||
if (waiting_inside_plan_buffer_line_print_aborted) {
|
||||
// Inside the lcd_update(0) routine the print has been aborted.
|
||||
// Cancel the print, do not plan the current line this routine is waiting on.
|
||||
#ifdef PLANNER_DIAGNOSTICS
|
||||
planner_update_queue_min_counter();
|
||||
#endif /* PLANNER_DIAGNOSTICS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef PLANNER_DIAGNOSTICS
|
||||
planner_update_queue_min_counter();
|
||||
#endif /* PLANNER_DIAGNOSTICS */
|
||||
if(planner_aborted) {
|
||||
// avoid planning the block early if aborted
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare to set up new block
|
||||
block_t *block = &block_buffer[block_buffer_head];
|
||||
|
@ -1331,8 +1329,12 @@ Having the real displacement of the head, we can calculate the total movement le
|
|||
if (block->step_event_count.wide <= 32767)
|
||||
block->flag |= BLOCK_FLAG_DDA_LOWRES;
|
||||
|
||||
// Move the buffer head. From now the block may be picked up by the stepper interrupt controller.
|
||||
block_buffer_head = next_buffer_head;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
// Move the buffer head ensuring the current block hasn't been cancelled from an isr context
|
||||
// (this is possible both during crash detection *and* uvlo, thus needing a global cli)
|
||||
if(planner_aborted) return;
|
||||
block_buffer_head = next_buffer_head;
|
||||
}
|
||||
|
||||
// Update position
|
||||
memcpy(position, target, sizeof(target)); // position[] = target[]
|
||||
|
|
|
@ -255,11 +255,14 @@ FORCE_INLINE bool planner_queue_full() {
|
|||
return block_buffer_tail == next_block_index;
|
||||
}
|
||||
|
||||
// Reset machine position from stepper counters
|
||||
extern void planner_reset_position();
|
||||
|
||||
// Abort the stepper routine, clean up the block queue,
|
||||
// wait for the steppers to stop,
|
||||
// update planner's current position and the current_position of the front end.
|
||||
extern void planner_abort_hard();
|
||||
extern bool waiting_inside_plan_buffer_line_print_aborted;
|
||||
extern bool planner_aborted;
|
||||
|
||||
#ifdef PREVENT_DANGEROUS_EXTRUDE
|
||||
extern int extrude_min_temp;
|
||||
|
|
|
@ -287,15 +287,6 @@ ISR(TIMER1_COMPA_vect) {
|
|||
if (sp < SP_min) SP_min = sp;
|
||||
#endif //DEBUG_STACK_MONITOR
|
||||
|
||||
#ifdef DEBUG_PULLUP_CRASH
|
||||
// check for faulty pull-ups enabled on thermistor inputs
|
||||
if ((PORTF & (uint8_t)(ADC_DIDR_MSK & 0xff)) || (PORTK & (uint8_t)((ADC_DIDR_MSK >> 8) & 0xff)))
|
||||
pullup_error(false);
|
||||
#else
|
||||
PORTF &= ~(uint8_t)(ADC_DIDR_MSK & 0xff);
|
||||
PORTK &= ~(uint8_t)((ADC_DIDR_MSK >> 8) & 0xff);
|
||||
#endif // DEBUG_PULLUP_CRASH
|
||||
|
||||
#ifdef LIN_ADVANCE
|
||||
advance_isr_scheduler();
|
||||
#else
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define FIRMWARE_SYSTEM_TIMER_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "macros.h"
|
||||
#define SYSTEM_TIMER_2
|
||||
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
|
@ -26,4 +27,24 @@
|
|||
#define timer02_set_pwm0(pwm0)
|
||||
#endif //SYSTEM_TIMER_2
|
||||
|
||||
// Timer counter, incremented by the 1ms Arduino timer.
|
||||
// The standard Arduino timer() function returns this value atomically
|
||||
// by disabling / enabling interrupts. This is costly, if the interrupts are known
|
||||
// to be disabled.
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
|
||||
// An unsynchronized equivalent to a standard Arduino _millis() function.
|
||||
// To be used inside an interrupt routine.
|
||||
FORCE_INLINE unsigned long millis_nc() {
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
return timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
return timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
}
|
||||
|
||||
#endif /* FIRMWARE_SYSTEM_TIMER_H_ */
|
||||
|
|
115
Firmware/temp_model.h
Normal file
115
Firmware/temp_model.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
// 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 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);
|
||||
|
||||
// resistance values for all fan levels
|
||||
constexpr uint8_t TEMP_MODEL_R_SIZE = (1 << FAN_SOFT_PWM_BITS);
|
||||
|
||||
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 enabled
|
||||
static bool warn_beep = true; // beep on warning threshold
|
||||
static model_data data; // default heater data
|
||||
|
||||
static bool calibrated(); // return calibration/model validity status
|
||||
static 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_DEBUG
|
||||
static 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 handler
|
||||
static void log_isr(); // isr log handler
|
||||
#endif
|
||||
|
||||
} // namespace temp_model
|
||||
|
||||
namespace temp_model_cal {
|
||||
|
||||
// recording scratch buffer
|
||||
struct 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
|
File diff suppressed because it is too large
Load diff
|
@ -22,29 +22,13 @@
|
|||
#define temperature_h
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "planner.h"
|
||||
|
||||
#include "stepper.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK2 |= (1<<OCIE2B)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK2 &= ~(1<<OCIE2B)
|
||||
|
||||
#else //SYSTEM_TIMER_2
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK0 |= (1<<OCIE0B)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK0 &= ~(1<<OCIE0B)
|
||||
|
||||
#endif //SYSTEM_TIMER_2
|
||||
|
||||
|
||||
// public functions
|
||||
void tp_init(); //initialize the heating
|
||||
void soft_pwm_init(); //initialize the soft pwm isr
|
||||
void temp_mgr_init(); //initialize the temperature handler
|
||||
void manage_heater(); //it is critical that this is called periodically.
|
||||
bool get_temp_error(); //return true if any thermal error is set
|
||||
|
||||
extern bool checkAllHotends(void);
|
||||
|
||||
|
@ -82,20 +66,18 @@ extern int current_voltage_raw_bed;
|
|||
extern uint16_t current_voltage_raw_IR;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
#if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
|
||||
extern unsigned char soft_pwm_bed;
|
||||
#endif
|
||||
|
||||
extern bool bedPWMDisabled;
|
||||
|
||||
#ifdef PIDTEMP
|
||||
extern int pid_cycle, pid_number_of_cycles;
|
||||
extern float _Kp,_Ki,_Kd;
|
||||
extern bool pid_tuning_finished;
|
||||
float scalePID_i(float i);
|
||||
float scalePID_d(float d);
|
||||
float unscalePID_i(float i);
|
||||
float unscalePID_d(float d);
|
||||
|
||||
bool pidTuningRunning(); // returns true if PID tuning is still running
|
||||
void preparePidTuning(); // non-blocking call to set "pidTuningRunning" to true immediately
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -156,8 +138,7 @@ FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
|
|||
static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
|
||||
{
|
||||
if (extruder<EXTRUDERS) {
|
||||
target_temperature[extruder] = celsius;
|
||||
resetPID(extruder);
|
||||
setTargetHotend(celsius, extruder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +199,7 @@ FORCE_INLINE bool isCoolingBed() {
|
|||
#define CHECK_ALL_HEATERS (checkAllHotends()||(target_temperature_bed!=0))
|
||||
|
||||
int getHeaterPower(int heater);
|
||||
void disable_heater(); // Disable all heaters
|
||||
void disable_heater(); // Disable all heaters *instantaneously*
|
||||
void updatePID();
|
||||
|
||||
|
||||
|
@ -235,39 +216,27 @@ FORCE_INLINE void autotempShutdown(){
|
|||
|
||||
void PID_autotune(float temp, int extruder, int ncycles);
|
||||
|
||||
void setExtruderAutoFanState(uint8_t state);
|
||||
void checkExtruderAutoFans();
|
||||
#ifdef TEMP_MODEL
|
||||
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_resistance(uint8_t index, float R);
|
||||
|
||||
void temp_model_report_settings();
|
||||
void temp_model_reset_settings();
|
||||
void temp_model_load_settings();
|
||||
void temp_model_save_settings();
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
void temp_model_autotune(int16_t temp = 0);
|
||||
|
||||
enum {
|
||||
EFCE_OK = 0, //!< normal operation, both fans are ok
|
||||
EFCE_FIXED, //!< previous fan error was fixed
|
||||
EFCE_DETECTED, //!< fan error detected, but not reported yet
|
||||
EFCE_REPORTED //!< fan error detected and reported to LCD and serial
|
||||
};
|
||||
extern volatile uint8_t fan_check_error;
|
||||
#ifdef TEMP_MODEL_DEBUG
|
||||
void temp_model_log_enable(bool enable);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void countFanSpeed();
|
||||
void checkFanSpeed();
|
||||
void fanSpeedError(unsigned char _fan);
|
||||
|
||||
void check_fans();
|
||||
|
||||
#endif //(defined(TACH_0))
|
||||
|
||||
void check_min_temp();
|
||||
void check_max_temp();
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
extern bool extruder_altfan_detect();
|
||||
extern void altfanOverride_toggle();
|
||||
extern bool altfanOverride_get();
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
extern unsigned long extruder_autofan_last_check;
|
||||
#ifdef FAN_SOFT_PWM
|
||||
extern unsigned char fanSpeedSoftPwm;
|
||||
#endif
|
||||
extern uint8_t fanSpeedBckp;
|
||||
extern bool fan_measuring;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "Marlin.h"
|
||||
#include "language.h"
|
||||
#include "cardreader.h"
|
||||
#include "temperature.h"
|
||||
#include "fancheck.h"
|
||||
#include "stepper.h"
|
||||
#include "ConfigurationStore.h"
|
||||
#include "printers.h"
|
||||
|
@ -94,14 +94,15 @@ static bool lcd_autoDeplete;
|
|||
|
||||
static float manual_feedrate[] = MANUAL_FEEDRATE;
|
||||
|
||||
/* LCD message status */
|
||||
static LongTimer lcd_status_message_timeout;
|
||||
static uint8_t lcd_status_message_level;
|
||||
static char lcd_status_message[LCD_WIDTH + 1] = WELCOME_MSG;
|
||||
|
||||
/* !Configuration settings */
|
||||
|
||||
uint8_t lcd_status_message_level;
|
||||
char lcd_status_message[LCD_WIDTH + 1] = WELCOME_MSG;
|
||||
|
||||
static uint8_t lay1cal_filament = 0;
|
||||
|
||||
|
||||
static const char separator[] PROGMEM = "--------------------";
|
||||
|
||||
/** forward declarations **/
|
||||
|
@ -597,7 +598,12 @@ void lcdui_print_status_line(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
|
||||
else if ((IS_SD_PRINTING) &&
|
||||
(custom_message_type == CustomMsg::Status) &&
|
||||
(lcd_status_message_level <= LCD_STATUS_INFO) &&
|
||||
lcd_status_message_timeout.expired_cont(LCD_STATUS_INFO_TIMEOUT))
|
||||
{
|
||||
// If printing from SD, show what we are printing
|
||||
const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
|
||||
if(strlen(longFilenameOLD) > LCD_WIDTH) {
|
||||
uint8_t gh = scrollstuff;
|
||||
|
@ -860,7 +866,7 @@ void lcd_status_screen() // NOT static due to using ins
|
|||
}
|
||||
|
||||
if (current_click
|
||||
&& ( menu_block_entering_on_serious_errors == SERIOUS_ERR_NONE ) // or a serious error blocks entering the menu
|
||||
&& ( menu_block_mask == MENU_BLOCK_NONE ) // or a serious error blocks entering the menu
|
||||
)
|
||||
{
|
||||
menu_depth = 0; //redundant, as already done in lcd_return_to_status(), just to be sure
|
||||
|
@ -869,14 +875,34 @@ void lcd_status_screen() // NOT static due to using ins
|
|||
}
|
||||
}
|
||||
|
||||
void print_stop();
|
||||
|
||||
void lcd_commands()
|
||||
{
|
||||
if (planner_aborted) {
|
||||
// we are still within an aborted command. do not process any LCD command until we return
|
||||
return;
|
||||
}
|
||||
|
||||
if (lcd_commands_type == LcdCommands::StopPrint)
|
||||
{
|
||||
if (!blocks_queued() && !homing_flag)
|
||||
{
|
||||
custom_message_type = CustomMsg::Status;
|
||||
lcd_setstatuspgm(_T(MSG_PRINT_ABORTED));
|
||||
lcd_commands_type = LcdCommands::Idle;
|
||||
lcd_commands_step = 0;
|
||||
print_stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (lcd_commands_type == LcdCommands::LongPause)
|
||||
{
|
||||
if (!blocks_queued() && !homing_flag)
|
||||
{
|
||||
if (custom_message_type != CustomMsg::M117)
|
||||
{
|
||||
custom_message_type = CustomMsg::Status;
|
||||
lcd_setstatuspgm(_i("Print paused"));////MSG_PRINT_PAUSED c=20
|
||||
}
|
||||
lcd_commands_type = LcdCommands::Idle;
|
||||
|
@ -1021,14 +1047,14 @@ void lcd_commands()
|
|||
lcd_commands_step = 3;
|
||||
}
|
||||
if (lcd_commands_step == 3 && !blocks_queued()) { //PID calibration
|
||||
preparePidTuning(); // ensure we don't move to the next step early
|
||||
sprintf_P(cmd1, PSTR("M303 E0 S%3u"), pid_temp);
|
||||
// setting the correct target temperature (for visualization) is done in PID_autotune
|
||||
enquecommand(cmd1);
|
||||
lcd_setstatuspgm(_i("PID cal."));////MSG_PID_RUNNING c=20
|
||||
lcd_commands_step = 2;
|
||||
}
|
||||
if (lcd_commands_step == 2 && pid_tuning_finished) { //saving to eeprom
|
||||
pid_tuning_finished = false;
|
||||
if (lcd_commands_step == 2 && !pidTuningRunning()) { //saving to eeprom
|
||||
custom_message_state = 0;
|
||||
lcd_setstatuspgm(_i("PID cal. finished"));////MSG_PID_FINISHED c=20
|
||||
setAllTargetHotends(0); // reset all hotends temperature including the number displayed on the main screen
|
||||
|
@ -1067,18 +1093,19 @@ void lcd_return_to_status()
|
|||
void lcd_pause_print()
|
||||
{
|
||||
stop_and_save_print_to_ram(0.0, -default_retraction);
|
||||
lcd_return_to_status();
|
||||
|
||||
SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_PAUSED);
|
||||
isPrintPaused = true;
|
||||
if (LcdCommands::Idle == lcd_commands_type) {
|
||||
lcd_commands_type = LcdCommands::LongPause;
|
||||
}
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED);
|
||||
|
||||
// return to status is required to continue processing in the main loop!
|
||||
lcd_commands_type = LcdCommands::LongPause;
|
||||
lcd_return_to_status();
|
||||
}
|
||||
|
||||
//! @brief Send host action "pause"
|
||||
void lcd_pause_usb_print()
|
||||
{
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSE);
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_ASK_PAUSE);
|
||||
}
|
||||
|
||||
static void lcd_move_menu_axis();
|
||||
|
@ -5665,22 +5692,37 @@ static bool fan_error_selftest()
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool resume_print_checks() {
|
||||
// reset the lcd status so that a newer error will be shown
|
||||
lcd_return_to_status();
|
||||
lcd_reset_alert_level();
|
||||
|
||||
// ensure thermal issues (temp or fan) are resolved before we allow to resume
|
||||
if (get_temp_error()
|
||||
#ifdef FANCHECK
|
||||
|| fan_error_selftest()
|
||||
#endif
|
||||
) {
|
||||
return false; // abort if error persists
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! @brief Resume paused print, send host action "resumed"
|
||||
//! @todo It is not good to call restore_print_from_ram_and_continue() from function called by lcd_update(),
|
||||
//! as restore_print_from_ram_and_continue() calls lcd_update() internally.
|
||||
void lcd_resume_print()
|
||||
{
|
||||
lcd_return_to_status();
|
||||
lcd_reset_alert_level(); //for fan speed error
|
||||
if (fan_error_selftest()) {
|
||||
if (usb_timer.running()) SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED);
|
||||
return; //abort if error persists
|
||||
}
|
||||
// reset lcd and ensure we can resume first
|
||||
if (!resume_print_checks()) return;
|
||||
|
||||
cmdqueue_serial_disabled = false;
|
||||
lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
|
||||
st_synchronize();
|
||||
custom_message_type = CustomMsg::Resuming;
|
||||
isPrintPaused = false;
|
||||
Stopped = false; // resume processing USB commands again
|
||||
restore_print_from_ram_and_continue(default_retraction);
|
||||
pause_time += (_millis() - start_pause_print); //accumulate time when print is paused for correct statistics calculation
|
||||
refresh_cmd_timeout();
|
||||
|
@ -5691,7 +5733,11 @@ void lcd_resume_print()
|
|||
//! @brief Resume paused USB/host print, send host action "resume"
|
||||
void lcd_resume_usb_print()
|
||||
{
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_RESUME); //resume octoprint
|
||||
// reset lcd and ensure we can resume first
|
||||
if (!resume_print_checks()) return;
|
||||
|
||||
// resume the usb host
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_ASK_RESUME);
|
||||
}
|
||||
|
||||
static void change_sheet()
|
||||
|
@ -5872,14 +5918,16 @@ static void lcd_main_menu()
|
|||
}
|
||||
if(isPrintPaused)
|
||||
{
|
||||
// only allow resuming if hardware errors (temperature or fan) are cleared
|
||||
if(!get_temp_error()
|
||||
#ifdef FANCHECK
|
||||
if((fan_check_error == EFCE_FIXED) || (fan_check_error == EFCE_OK))
|
||||
&& ((fan_check_error == EFCE_FIXED) || (fan_check_error == EFCE_OK))
|
||||
#endif //FANCHECK
|
||||
{
|
||||
if (usb_timer.running()) {
|
||||
MENU_ITEM_SUBMENU_P(_T(MSG_RESUME_PRINT), lcd_resume_usb_print);
|
||||
} else {
|
||||
) {
|
||||
if (saved_printing) {
|
||||
MENU_ITEM_SUBMENU_P(_T(MSG_RESUME_PRINT), lcd_resume_print);
|
||||
} else {
|
||||
MENU_ITEM_SUBMENU_P(_T(MSG_RESUME_PRINT), lcd_resume_usb_print);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6286,56 +6334,61 @@ static void lcd_sd_updir()
|
|||
menu_data_reset(); //Forces reloading of cached variables.
|
||||
}
|
||||
|
||||
void lcd_print_stop()
|
||||
// continue stopping the print from the main loop after lcd_print_stop() is called
|
||||
void print_stop()
|
||||
{
|
||||
if (!card.sdprinting) {
|
||||
SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint
|
||||
}
|
||||
UnconditionalStop();
|
||||
// save printing time
|
||||
stoptime = _millis();
|
||||
unsigned long t = (stoptime - starttime - pause_time) / 1000; //time in s
|
||||
save_statistics(total_filament_used, t);
|
||||
|
||||
// TODO: all the following should be moved in the main marlin loop!
|
||||
#ifdef MESH_BED_LEVELING
|
||||
mbl.active = false; //also prevents undoing the mbl compensation a second time in the second planner_abort_hard()
|
||||
#endif
|
||||
// lift Z
|
||||
raise_z_above(current_position[Z_AXIS] + 10, true);
|
||||
|
||||
lcd_setstatuspgm(_T(MSG_PRINT_ABORTED));
|
||||
stoptime = _millis();
|
||||
unsigned long t = (stoptime - starttime - pause_time) / 1000; //time in s
|
||||
pause_time = 0;
|
||||
save_statistics(total_filament_used, t);
|
||||
|
||||
// reset current command
|
||||
lcd_commands_step = 0;
|
||||
lcd_commands_type = LcdCommands::Idle;
|
||||
|
||||
lcd_cooldown(); //turns off heaters and fan; goes to status screen.
|
||||
|
||||
if (axis_known_position[Z_AXIS]) {
|
||||
current_position[Z_AXIS] += Z_CANCEL_LIFT;
|
||||
clamp_to_software_endstops(current_position);
|
||||
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60);
|
||||
}
|
||||
|
||||
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) //if axis are homed, move to parked position.
|
||||
{
|
||||
// if axis are homed, move to parking position.
|
||||
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) {
|
||||
current_position[X_AXIS] = X_CANCEL_POS;
|
||||
current_position[Y_AXIS] = Y_CANCEL_POS;
|
||||
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
|
||||
}
|
||||
st_synchronize();
|
||||
|
||||
// did we come here from a thermal error?
|
||||
if(get_temp_error()) {
|
||||
// time to stop the error beep
|
||||
WRITE(BEEPER, LOW);
|
||||
} else {
|
||||
// Turn off the print fan
|
||||
fanSpeed = 0;
|
||||
}
|
||||
|
||||
if (mmu_enabled) extr_unload(); //M702 C
|
||||
|
||||
finishAndDisableSteppers(); //M84
|
||||
|
||||
lcd_setstatuspgm(MSG_WELCOME);
|
||||
custom_message_type = CustomMsg::Status;
|
||||
|
||||
planner_abort_hard(); //needs to be done since plan_buffer_line resets waiting_inside_plan_buffer_line_print_aborted to false. Also copies current to destination.
|
||||
|
||||
axis_relative_modes = E_AXIS_MASK; //XYZ absolute, E relative
|
||||
|
||||
isPrintPaused = false; //clear isPrintPaused flag to allow starting next print after pause->stop scenario.
|
||||
}
|
||||
|
||||
void lcd_print_stop()
|
||||
{
|
||||
// UnconditionalStop() will internally cause planner_abort_hard(), meaning we _cannot_ plan
|
||||
// any more move in this call! Any further move must happen inside print_stop(), which is called
|
||||
// by the main loop one iteration later.
|
||||
UnconditionalStop();
|
||||
|
||||
if (!card.sdprinting) {
|
||||
SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint
|
||||
}
|
||||
|
||||
#ifdef MESH_BED_LEVELING
|
||||
mbl.active = false;
|
||||
#endif
|
||||
|
||||
// clear any pending paused state immediately
|
||||
pause_time = 0;
|
||||
isPrintPaused = false;
|
||||
|
||||
// return to status is required to continue processing in the main loop!
|
||||
lcd_commands_type = LcdCommands::StopPrint;
|
||||
lcd_return_to_status();
|
||||
}
|
||||
|
||||
void lcd_sdcard_stop()
|
||||
|
@ -7952,57 +8005,70 @@ void lcd_finishstatus() {
|
|||
|
||||
}
|
||||
|
||||
void lcd_setstatus(const char* message)
|
||||
static bool lcd_message_check(uint8_t priority)
|
||||
{
|
||||
if (lcd_status_message_level > 0)
|
||||
return;
|
||||
lcd_updatestatus(message);
|
||||
// regular priority check
|
||||
if (priority >= lcd_status_message_level)
|
||||
return true;
|
||||
|
||||
// check if we can override an info message yet
|
||||
if (lcd_status_message_level == LCD_STATUS_INFO) {
|
||||
return lcd_status_message_timeout.expired_cont(LCD_STATUS_INFO_TIMEOUT);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lcd_updatestatuspgm(const char *message){
|
||||
strncpy_P(lcd_status_message, message, LCD_WIDTH);
|
||||
static void lcd_updatestatus(const char *message, bool progmem = false)
|
||||
{
|
||||
if (progmem)
|
||||
strncpy_P(lcd_status_message, message, LCD_WIDTH);
|
||||
else
|
||||
strncpy(lcd_status_message, message, LCD_WIDTH);
|
||||
|
||||
lcd_status_message[LCD_WIDTH] = 0;
|
||||
lcd_finishstatus();
|
||||
// hack lcd_draw_update to 1, i.e. without clear
|
||||
lcd_draw_update = 1;
|
||||
}
|
||||
|
||||
void lcd_setstatus(const char* message)
|
||||
{
|
||||
if (lcd_message_check(LCD_STATUS_NONE))
|
||||
lcd_updatestatus(message);
|
||||
}
|
||||
|
||||
void lcd_setstatuspgm(const char* message)
|
||||
{
|
||||
if (lcd_status_message_level > 0)
|
||||
return;
|
||||
lcd_updatestatuspgm(message);
|
||||
if (lcd_message_check(LCD_STATUS_NONE))
|
||||
lcd_updatestatus(message, true);
|
||||
}
|
||||
|
||||
void lcd_updatestatus(const char *message){
|
||||
strncpy(lcd_status_message, message, LCD_WIDTH);
|
||||
lcd_status_message[LCD_WIDTH] = 0;
|
||||
lcd_finishstatus();
|
||||
// hack lcd_draw_update to 1, i.e. without clear
|
||||
lcd_draw_update = 1;
|
||||
}
|
||||
|
||||
void lcd_setalertstatuspgm(const char* message, uint8_t severity)
|
||||
void lcd_setalertstatus_(const char* message, uint8_t severity, bool progmem)
|
||||
{
|
||||
if (severity > lcd_status_message_level) {
|
||||
lcd_updatestatuspgm(message);
|
||||
lcd_status_message_level = severity;
|
||||
lcd_return_to_status();
|
||||
}
|
||||
if (lcd_message_check(severity)) {
|
||||
lcd_updatestatus(message, progmem);
|
||||
lcd_status_message_timeout.start();
|
||||
lcd_status_message_level = severity;
|
||||
custom_message_type = CustomMsg::Status;
|
||||
custom_message_state = 0;
|
||||
lcd_return_to_status();
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_setalertstatus(const char* message, uint8_t severity)
|
||||
{
|
||||
if (severity > lcd_status_message_level) {
|
||||
lcd_updatestatus(message);
|
||||
lcd_status_message_level = severity;
|
||||
lcd_return_to_status();
|
||||
}
|
||||
lcd_setalertstatus_(message, severity, false);
|
||||
}
|
||||
|
||||
void lcd_setalertstatuspgm(const char* message, uint8_t severity)
|
||||
{
|
||||
lcd_setalertstatus_(message, severity, true);
|
||||
}
|
||||
|
||||
void lcd_reset_alert_level()
|
||||
{
|
||||
lcd_status_message_level = 0;
|
||||
lcd_status_message_level = 0;
|
||||
}
|
||||
|
||||
uint8_t get_message_level()
|
||||
|
@ -8013,9 +8079,9 @@ uint8_t get_message_level()
|
|||
void menu_lcd_longpress_func(void)
|
||||
{
|
||||
backlight_wake();
|
||||
if (homing_flag || mesh_bed_leveling_flag || menu_menu == lcd_babystep_z || menu_menu == lcd_move_z)
|
||||
if (homing_flag || mesh_bed_leveling_flag || menu_menu == lcd_babystep_z || menu_menu == lcd_move_z || menu_block_mask != MENU_BLOCK_NONE)
|
||||
{
|
||||
// disable longpress during re-entry, while homing or calibration
|
||||
// disable longpress during re-entry, while homing, calibration or if a serious error
|
||||
lcd_quick_feedback();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,14 +9,19 @@ extern void menu_lcd_lcdupdate_func(void);
|
|||
|
||||
// Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
|
||||
void ultralcd_init();
|
||||
void lcd_setstatus(const char* message);
|
||||
void lcd_setstatuspgm(const char* message);
|
||||
|
||||
//! LCD status severities
|
||||
#define LCD_STATUS_CRITICAL 2 //< Heater failure
|
||||
#define LCD_STATUS_ALERT 1 //< Other hardware issue
|
||||
#define LCD_STATUS_CRITICAL 3 //< Heater failure
|
||||
#define LCD_STATUS_ALERT 2 //< Other hardware issue
|
||||
#define LCD_STATUS_INFO 1 //< Message times out after a while
|
||||
#define LCD_STATUS_NONE 0 //< No alert message set
|
||||
|
||||
#define LCD_STATUS_INFO_TIMEOUT 20000
|
||||
|
||||
// Set the current status message (equivalent to LCD_STATUS_NONE)
|
||||
void lcd_setstatus(const char* message);
|
||||
void lcd_setstatuspgm(const char* message);
|
||||
|
||||
//! return to the main status screen and display the alert message
|
||||
//! Beware - it has sideeffects:
|
||||
//! - always returns the display to the main status screen
|
||||
|
@ -25,13 +30,10 @@ void lcd_setstatuspgm(const char* message);
|
|||
void lcd_setalertstatus(const char* message, uint8_t severity = LCD_STATUS_ALERT);
|
||||
void lcd_setalertstatuspgm(const char* message, uint8_t severity = LCD_STATUS_ALERT);
|
||||
|
||||
//! only update the alert message on the main status screen
|
||||
//! has no sideeffects, may be called multiple times
|
||||
void lcd_updatestatus(const char *message);
|
||||
void lcd_updatestatuspgm(const char *message);
|
||||
|
||||
void lcd_reset_alert_level();
|
||||
//! Get/reset the current alert level
|
||||
uint8_t get_message_level();
|
||||
void lcd_reset_alert_level();
|
||||
|
||||
void lcd_adjust_z();
|
||||
void lcd_pick_babystep();
|
||||
void lcd_alright();
|
||||
|
|
|
@ -413,6 +413,34 @@
|
|||
#define TEMP_RUNAWAY_EXTRUDER_HYSTERESIS 15
|
||||
#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
|
||||
|
||||
// model-based temperature check
|
||||
#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_C 11. // 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_R 25 // 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_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)
|
||||
|
||||
#define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C)
|
||||
#define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C)
|
||||
|
||||
|
||||
/*------------------------------------
|
||||
MOTOR CURRENT SETTINGS
|
||||
*------------------------------------*/
|
||||
|
|
|
@ -417,6 +417,34 @@
|
|||
#define TEMP_RUNAWAY_EXTRUDER_HYSTERESIS 15
|
||||
#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
|
||||
|
||||
// model-based temperature check
|
||||
#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_C 11. // 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_R 25 // 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_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)
|
||||
|
||||
#define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C)
|
||||
#define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C)
|
||||
|
||||
|
||||
/*------------------------------------
|
||||
MOTOR CURRENT SETTINGS
|
||||
*------------------------------------*/
|
||||
|
|
|
@ -138,15 +138,18 @@ pos_mm_t pos_2_mm(float pos){
|
|||
void xyzcal_meassure_enter(void)
|
||||
{
|
||||
DBG(_n("xyzcal_meassure_enter\n"));
|
||||
|
||||
// disable heaters and stop motion before we initialize sm4
|
||||
disable_heater();
|
||||
DISABLE_TEMPERATURE_INTERRUPT();
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
DISABLE_FANCHECK_INTERRUPT();
|
||||
#endif //(defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
st_synchronize();
|
||||
|
||||
// disable incompatible interrupts
|
||||
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
#ifdef WATCHDOG
|
||||
wdt_disable();
|
||||
#endif //WATCHDOG
|
||||
|
||||
// setup internal callbacks
|
||||
sm4_stop_cb = 0;
|
||||
sm4_update_pos_cb = xyzcal_update_pos;
|
||||
sm4_calc_delay_cb = xyzcal_calc_delay;
|
||||
|
@ -155,21 +158,18 @@ void xyzcal_meassure_enter(void)
|
|||
void xyzcal_meassure_leave(void)
|
||||
{
|
||||
DBG(_n("xyzcal_meassure_leave\n"));
|
||||
planner_abort_hard();
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
ENABLE_FANCHECK_INTERRUPT();
|
||||
#endif //(defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
// resync planner position from counters (changed by xyzcal_update_pos)
|
||||
planner_reset_position();
|
||||
|
||||
// re-enable interrupts
|
||||
#ifdef WATCHDOG
|
||||
wdt_enable(WDTO_4S);
|
||||
#ifdef EMERGENCY_HANDLERS
|
||||
WDTCSR |= (1 << WDIE);
|
||||
#endif //EMERGENCY_HANDLERS
|
||||
#endif //WATCHDOG
|
||||
sm4_stop_cb = 0;
|
||||
sm4_update_pos_cb = 0;
|
||||
sm4_calc_delay_cb = 0;
|
||||
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
}
|
||||
|
||||
|
||||
|
@ -999,13 +999,9 @@ BedSkewOffsetDetectionResultType xyzcal_scan_and_process(){
|
|||
return ret;
|
||||
}
|
||||
|
||||
BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy(void){
|
||||
BedSkewOffsetDetectionResultType ret = BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
|
||||
|
||||
//@size=258
|
||||
BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy(void) {
|
||||
// DBG(_n("xyzcal_find_bed_induction_sensor_point_xy x=%ld y=%ld z=%ld\n"), count_position[X_AXIS], count_position[Y_AXIS], count_position[Z_AXIS]);
|
||||
st_synchronize();
|
||||
|
||||
BedSkewOffsetDetectionResultType ret = BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
|
||||
xyzcal_meassure_enter();
|
||||
if (xyzcal_searchZ())
|
||||
ret = xyzcal_scan_and_process();
|
||||
|
|
Loading…
Add table
Reference in a new issue