diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp
index 0a5142629..70ffe2c49 100644
--- a/Firmware/Dcodes.cpp
+++ b/Firmware/Dcodes.cpp
@@ -252,10 +252,10 @@ void dcode_1()
/*!
*
- ### D2 - Read/Write RAM D3: Read/Write RAM
+ ### D2 - Read/Write RAM D2: Read/Write RAM
This command can be used without any additional parameters. It will read the entire RAM.
- D3 [ A | C | X ]
+ D2 [ A | C | X ]
- `A` - Address (0x0000-0x1fff)
- `C` - Count (0x0001-0x2000)
@@ -355,7 +355,7 @@ void dcode_4()
### D5 - Read/Write FLASH D5: Read/Write Flash
This command can be used without any additional parameters. It will read the 1kb FLASH.
- D3 [ A | C | X | E ]
+ D5 [ A | C | X | E ]
- `A` - Address (0x00000-0x3ffff)
- `C` - Count (0x0001-0x2000)
diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h
index 58b3351de..a0b3c19b8 100755
--- a/Firmware/Marlin.h
+++ b/Firmware/Marlin.h
@@ -146,40 +146,39 @@ void manage_inactivity(bool ignore_stepper_queue=false);
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
#if defined(Z_AXIS_ALWAYS_ON)
#ifdef Z_DUAL_STEPPER_DRIVERS
- #define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
- #define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
+ #define poweron_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
+ #define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#else
- #define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
- #define disable_z() {}
+ #define poweron_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
+ #define poweroff_z() {}
#endif
#else
#ifdef Z_DUAL_STEPPER_DRIVERS
- #define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
- #define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
+ #define poweron_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
+ #define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#else
- #define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
- #define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
+ #define poweron_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
+ #define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#endif
#endif
#else
- #define enable_z() {}
- #define disable_z() {}
+ #define poweron_z() {}
+ #define poweroff_z() {}
#endif
-#ifdef PSU_Delta
+#ifndef PSU_Delta
+ #define enable_z() poweron_z()
+ #define disable_z() poweroff_z()
+#else
void init_force_z();
void check_force_z();
- #undef disable_z
- #define disable_z() disable_force_z()
- void disable_force_z();
- #undef enable_z
- #define enable_z() enable_force_z()
void enable_force_z();
+ void disable_force_z();
+ #define enable_z() enable_force_z()
+ #define disable_z() disable_force_z()
#endif // PSU_Delta
-
-
//#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
//#ifdef Z_DUAL_STEPPER_DRIVERS
//#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp
index a204f9f0b..cd4ee63f4 100755
--- a/Firmware/Marlin_main.cpp
+++ b/Firmware/Marlin_main.cpp
@@ -1298,10 +1298,6 @@ void setup()
st_init(); // Initialize stepper, this enables interrupts!
-#ifdef UVLO_SUPPORT
- setup_uvlo_interrupt();
-#endif //UVLO_SUPPORT
-
#ifdef TMC2130
tmc2130_mode = silentMode?TMC2130_MODE_SILENT:TMC2130_MODE_NORMAL;
update_mode_profile();
@@ -1596,12 +1592,14 @@ void setup()
lcd_update(2);
lcd_setstatuspgm(_T(WELCOME_MSG));
}
-
}
-
-
}
+
+ // Only arm the uvlo interrupt _after_ a recovering print has been initialized and
+ // the entire state machine initialized.
+ setup_uvlo_interrupt();
#endif //UVLO_SUPPORT
+
fCheckModeInit();
fSetMmuMode(mmu_enabled);
KEEPALIVE_STATE(NOT_BUSY);
@@ -9490,7 +9488,8 @@ if(0)
#ifdef PAT9125
fsensor_autoload_check_stop();
#endif //PAT9125
- fsensor_update();
+ if (fsensor_enabled && !saved_printing)
+ fsensor_update();
}
}
}
@@ -9595,7 +9594,7 @@ void kill(const char *full_screen_message, unsigned char id)
disable_x();
// SERIAL_ECHOLNPGM("kill - disable Y");
disable_y();
- disable_z();
+ poweroff_z();
disable_e0();
disable_e1();
disable_e2();
@@ -10482,6 +10481,16 @@ void serialecho_temperatures() {
}
#ifdef UVLO_SUPPORT
+void uvlo_drain_reset()
+{
+ // burn all that residual power
+ wdt_enable(WDTO_1S);
+ WRITE(BEEPER,HIGH);
+ lcd_clear();
+ lcd_puts_at_P(0, 1, MSG_POWERPANIC_DETECTED);
+ while(1);
+}
+
void uvlo_()
{
@@ -10521,7 +10530,7 @@ void uvlo_()
// save the global state at planning time
uint16_t feedrate_bckp;
- if (blocks_queued())
+ if (current_block)
{
memcpy(saved_target, current_block->gcode_target, sizeof(saved_target));
feedrate_bckp = current_block->gcode_feedrate;
@@ -10579,7 +10588,7 @@ void uvlo_()
+ UVLO_Z_AXIS_SHIFT;
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60, active_extruder);
st_synchronize();
- disable_z();
+ poweroff_z();
// Write the file position.
eeprom_update_dword((uint32_t*)(EEPROM_FILE_POSITION), sd_position);
@@ -10638,7 +10647,7 @@ void uvlo_()
WRITE(BEEPER,HIGH);
// All is set: with all the juice left, try to move extruder away to detach the nozzle completely from the print
- enable_z();
+ poweron_z();
current_position[X_AXIS] = (current_position[X_AXIS] < 0.5f * (X_MIN_POS + X_MAX_POS)) ? X_MIN_POS : X_MAX_POS;
plan_buffer_line_curposXYZE(500, active_extruder);
st_synchronize();
@@ -10693,7 +10702,7 @@ void uvlo_tiny()
+ UVLO_TINY_Z_AXIS_SHIFT;
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60, active_extruder);
st_synchronize();
- disable_z();
+ poweroff_z();
// Update Z position
eeprom_update_float((float*)(EEPROM_UVLO_TINY_CURRENT_POSITION_Z), current_position[Z_AXIS]);
@@ -10711,11 +10720,7 @@ void uvlo_tiny()
eeprom_update_word((uint16_t*)EEPROM_POWER_COUNT_TOT, eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) + 1);
printf_P(_N("UVLO_TINY - end %d\n"), _millis() - time_start);
-
- // burn all that residual power
- wdt_enable(WDTO_1S);
- WRITE(BEEPER,HIGH);
- while(1);
+ uvlo_drain_reset();
}
#endif //UVLO_SUPPORT
@@ -10762,12 +10767,19 @@ void setup_uvlo_interrupt() {
DDRE &= ~(1 << 4); //input pin
PORTE &= ~(1 << 4); //no internal pull-up
- //sensing falling edge
+ // sensing falling edge
EICRB |= (1 << 0);
EICRB &= ~(1 << 1);
- //enable INT4 interrupt
+ // enable INT4 interrupt
EIMSK |= (1 << 4);
+
+ // check if power was lost before we armed the interrupt
+ if(!(PINE & (1 << 4)) && eeprom_read_byte((uint8_t*)EEPROM_UVLO))
+ {
+ SERIAL_ECHOLNPGM("INT4");
+ uvlo_drain_reset();
+ }
}
ISR(INT4_vect) {
@@ -10787,10 +10799,13 @@ void recover_print(uint8_t automatic) {
// Recover position, temperatures and extrude_multipliers
bool mbl_was_active = recover_machine_state_after_power_panic();
- // Attempt to lift the print head on the first recovery, so one may remove the excess priming material.
- bool raise_z = (eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 1);
- if(raise_z && (current_position[Z_AXIS]<25))
- enquecommand_P(PSTR("G1 Z25 F800"));
+ // Lift the print head 25mm, first to avoid collisions with oozed material with the print,
+ // and second also so one may remove the excess priming material.
+ if(eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 1)
+ {
+ sprintf_P(cmd, PSTR("G1 Z%.3f F800"), current_position[Z_AXIS] + 25);
+ enquecommand(cmd);
+ }
// Home X and Y axes. Homing just X and Y shall not touch the babystep and the world2machine
// transformation status. G28 will not touch Z when MBL is off.
@@ -11118,7 +11133,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
#endif
// save the global state at planning time
- if (blocks_queued())
+ if (current_block)
{
memcpy(saved_target, current_block->gcode_target, sizeof(saved_target));
saved_feedrate2 = current_block->gcode_feedrate;
@@ -11578,8 +11593,6 @@ if(!(bEnableForce_z||eeprom_read_byte((uint8_t*)EEPROM_SILENT)))
void disable_force_z()
{
- uint16_t z_microsteps=0;
-
if(!bEnableForce_z) return; // motor already disabled (may be ;-p )
bEnableForce_z=false;
@@ -11590,8 +11603,6 @@ void disable_force_z()
update_mode_profile();
tmc2130_init(true);
#endif // TMC2130
-
- axis_known_position[Z_AXIS]=false;
}
diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp
index 64b46b30c..fce8f6fed 100755
--- a/Firmware/fsensor.cpp
+++ b/Firmware/fsensor.cpp
@@ -121,14 +121,16 @@ unsigned long nIRsensorLastTime;
void fsensor_stop_and_save_print(void)
{
printf_P(PSTR("fsensor_stop_and_save_print\n"));
- stop_and_save_print_to_ram(0, 0); //XYZE - no change
+ stop_and_save_print_to_ram(0, 0);
+ fsensor_watch_runout = false;
}
void fsensor_restore_print_and_continue(void)
{
printf_P(PSTR("fsensor_restore_print_and_continue\n"));
+ fsensor_watch_runout = true;
fsensor_err_cnt = 0;
- restore_print_from_ram_and_continue(0); //XYZ = orig, E - no change
+ restore_print_from_ram_and_continue(0);
}
// fsensor_checkpoint_print cuts the current print job at the current position,
@@ -376,7 +378,6 @@ void fsensor_oq_meassure_start(uint8_t skip)
fsensor_oq_sh_sum = 0;
pat9125_update();
pat9125_y = 0;
- fsensor_watch_runout = false;
fsensor_oq_meassure = true;
}
@@ -388,7 +389,6 @@ void fsensor_oq_meassure_stop(void)
printf_P(_N(" st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max);
printf_P(_N(" yd_min=%u yd_max=%u yd_avg=%u sh_avg=%u\n"), fsensor_oq_yd_min, fsensor_oq_yd_max, (uint16_t)((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum), (uint16_t)(fsensor_oq_sh_sum / fsensor_oq_samples));
fsensor_oq_meassure = false;
- fsensor_watch_runout = true;
fsensor_err_cnt = 0;
}
@@ -561,29 +561,31 @@ void fsensor_enque_M600(){
void fsensor_update(void)
{
#ifdef PAT9125
- if (fsensor_enabled && fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
+ if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
{
+ fsensor_stop_and_save_print();
+ KEEPALIVE_STATE(IN_HANDLER);
+
bool autoload_enabled_tmp = fsensor_autoload_enabled;
fsensor_autoload_enabled = false;
bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
fsensor_oq_meassure_enabled = true;
- fsensor_stop_and_save_print();
+ // move the nozzle away while checking the filament
+ current_position[Z_AXIS] += 0.8;
+ if(current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
+ plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder);
+ st_synchronize();
+ // check the filament in isolation
fsensor_err_cnt = 0;
fsensor_oq_meassure_start(0);
-
- enquecommand_front_P((PSTR("G1 E-3 F200")));
- process_commands();
- KEEPALIVE_STATE(IN_HANDLER);
- cmdqueue_pop_front();
- st_synchronize();
-
- enquecommand_front_P((PSTR("G1 E3 F200")));
- process_commands();
- KEEPALIVE_STATE(IN_HANDLER);
- cmdqueue_pop_front();
- st_synchronize();
+ float e_tmp = current_position[E_AXIS];
+ current_position[E_AXIS] -= 3;
+ plan_buffer_line_curposXYZE(200/60, active_extruder);
+ current_position[E_AXIS] = e_tmp;
+ plan_buffer_line_curposXYZE(200/60, active_extruder);
+ st_synchronize();
uint8_t err_cnt = fsensor_err_cnt;
fsensor_oq_meassure_stop();
@@ -604,7 +606,7 @@ void fsensor_update(void)
fsensor_enque_M600();
}
#else //PAT9125
- if (CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected)
+ if (CHECK_FSENSOR && ir_sensor_detected)
{
if(digitalRead(IR_SENSOR_PIN))
{ // IR_SENSOR_PIN ~ H
diff --git a/Firmware/heatbed_pwm.cpp b/Firmware/heatbed_pwm.cpp
index a3e5444c3..e85515016 100755
--- a/Firmware/heatbed_pwm.cpp
+++ b/Firmware/heatbed_pwm.cpp
@@ -45,6 +45,12 @@
// If there are any change requirements in the future, the signal must be checked with an osciloscope again,
// ad-hoc changes may completely screw things up!
+// 2020-01-29 update: we are introducing a new option to the automaton that will allow us to force the output state
+// to either full ON or OFF. This is so that interference during the MBL probing is minimal.
+// To accomplish this goal we use bedPWMDisabled. It is only supposed to be used for brief periods of time as to
+// not make the bed temperature too unstable. Also, careful consideration should be used when using this
+// option as leaving this enabled will also keep the bed output in the state it stopped in.
+
///! Definition off finite automaton states
enum class States : uint8_t {
ZERO_START = 0,///< entry point of the automaton - reads the soft_pwm_bed value for the next whole PWM cycle
@@ -61,6 +67,8 @@ enum class States : uint8_t {
///! Inner states of the finite automaton
static States state = States::ZERO_START;
+bool bedPWMDisabled = 0;
+
///! Fast PWM counter is used in the RISE and FALL states (62.5kHz)
static uint8_t slowCounter = 0;
///! Slow PWM counter is used in the ZERO and ONE states (62.5kHz/8 or 64)
@@ -93,6 +101,7 @@ ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
{
switch(state){
case States::ZERO_START:
+ if (bedPWMDisabled) return; // stay in the OFF state and do not change the output pin
pwm = soft_pwm_bed << 1;// expecting soft_pwm_bed to be 7bit!
if( pwm != 0 ){
state = States::ZERO; // do nothing, let it tick once again after the 30Hz period
@@ -136,6 +145,7 @@ ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
break;
case States::ONE: // state ONE - we'll either stay in ONE or change to FALL
OCR0B = 255;
+ if (bedPWMDisabled) return; // stay in the ON state and do not change the output pin
slowCounter += slowInc; // this does software timer_clk/256 or less
if( slowCounter < pwm ){
return;
diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp
index 6466edc45..88cbc671a 100644
--- a/Firmware/mesh_bed_calibration.cpp
+++ b/Firmware/mesh_bed_calibration.cpp
@@ -6,6 +6,7 @@
#include "mesh_bed_leveling.h"
#include "stepper.h"
#include "ultralcd.h"
+#include "temperature.h"
#ifdef TMC2130
#include "tmc2130.h"
@@ -946,6 +947,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
)
{
bool high_deviation_occured = false;
+ bedPWMDisabled = 1;
#ifdef TMC2130
FORCE_HIGH_POWER_START;
#endif
@@ -1044,6 +1046,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
#ifdef TMC2130
FORCE_HIGH_POWER_END;
#endif
+ bedPWMDisabled = 0;
return true;
error:
@@ -1053,6 +1056,7 @@ error:
#ifdef TMC2130
FORCE_HIGH_POWER_END;
#endif
+ bedPWMDisabled = 0;
return false;
}
diff --git a/Firmware/messages.c b/Firmware/messages.c
index 68bad5ffb..2b113673e 100644
--- a/Firmware/messages.c
+++ b/Firmware/messages.c
@@ -171,3 +171,4 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
#ifdef LA_LIVE_K
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
#endif
+const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
diff --git a/Firmware/messages.h b/Firmware/messages.h
index 678524abb..7cc240d3b 100644
--- a/Firmware/messages.h
+++ b/Firmware/messages.h
@@ -170,6 +170,7 @@ extern const char MSG_FANCHECK_EXTRUDER[];
extern const char MSG_FANCHECK_PRINT[];
extern const char MSG_M112_KILL[];
extern const char MSG_ADVANCE_K[];
+extern const char MSG_POWERPANIC_DETECTED[];
#if defined(__cplusplus)
}
diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp
index 88674cf98..7517978be 100755
--- a/Firmware/temperature.cpp
+++ b/Firmware/temperature.cpp
@@ -1403,6 +1403,7 @@ void disable_heater()
target_temperature_bed=0;
soft_pwm_bed=0;
timer02_set_pwm0(soft_pwm_bed << 1);
+ bedPWMDisabled = 0;
#if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
//WRITE(HEATER_BED_PIN,LOW);
#endif
@@ -2002,6 +2003,8 @@ void check_max_temp()
//! number of repeating the same state with consecutive step() calls
//! used to slow down text switching
struct alert_automaton_mintemp {
+ const char *m2;
+ alert_automaton_mintemp(const char *m2):m2(m2){}
private:
enum { ALERT_AUTOMATON_SPEED_DIV = 5 };
enum class States : uint8_t { Init = 0, TempAboveMintemp, ShowPleaseRestart, ShowMintemp };
@@ -2021,7 +2024,6 @@ public:
//! @param current_temp current hotend/bed temperature (for computing simple hysteresis)
//! @param mintemp minimal temperature including hysteresis to check current_temp against
void step(float current_temp, float mintemp){
- static const char m2[] PROGMEM = "MINTEMP fixed";
static const char m1[] PROGMEM = "Please restart";
switch(state){
case States::Init: // initial state - check hysteresis
@@ -2049,8 +2051,9 @@ public:
}
}
};
-
-static alert_automaton_mintemp alert_automaton_hotend, alert_automaton_bed;
+static const char m2hotend[] PROGMEM = "MINTEMP HEATER fixed";
+static const char m2bed[] PROGMEM = "MINTEMP BED fixed";
+static alert_automaton_mintemp alert_automaton_hotend(m2hotend), alert_automaton_bed(m2bed);
void check_min_temp_heater0()
{
diff --git a/Firmware/temperature.h b/Firmware/temperature.h
index acbb27937..57e2521bc 100755
--- a/Firmware/temperature.h
+++ b/Firmware/temperature.h
@@ -84,6 +84,8 @@ extern int current_voltage_raw_IR;
extern unsigned char soft_pwm_bed;
#endif
+extern bool bedPWMDisabled;
+
#ifdef PIDTEMP
extern int pid_cycle, pid_number_of_cycles;
extern float Kc,_Kp,_Ki,_Kd;
diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp
index df9000c4f..dc93fe53a 100755
--- a/Firmware/ultralcd.cpp
+++ b/Firmware/ultralcd.cpp
@@ -7541,6 +7541,12 @@ bool lcd_selftest()
int _progress = 0;
bool _result = true;
bool _swapped_fan = false;
+#if IR_SENSOR_ANALOG
+ bool bAction;
+ bAction=lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is the filament unloaded?"),false,true);
+ if(!bAction)
+ return(false);
+#endif //IR_SENSOR_ANALOG
lcd_wait_for_cool_down();
lcd_clear();
lcd_set_cursor(0, 0); lcd_puts_P(_i("Self test start "));////MSG_SELFTEST_START c=20
@@ -7552,12 +7558,6 @@ bool lcd_selftest()
_delay(2000);
#endif //!IR_SENSOR_ANALOG
KEEPALIVE_STATE(IN_HANDLER);
-#if IR_SENSOR_ANALOG
- bool bAction;
- bAction=lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament unloaded?"),false,true);
- if(!bAction)
- return(false);
-#endif //IR_SENSOR_ANALOG
_progress = lcd_selftest_screen(TestScreen::ExtruderFan, _progress, 3, true, 2000);
#if (defined(FANCHECK) && defined(TACH_0))