Merge branch 'MK3' into MK3_AUTO_REPORT_TEMPERATURES

This commit is contained in:
Voinea Dragos 2020-09-15 13:38:47 +03:00
commit 073eadff7e
21 changed files with 606 additions and 302 deletions

View File

@ -293,6 +293,7 @@
#define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed) #define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed)
#define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line) #define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line)
#define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive) #define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive)
//#define LA_FLOWADJ // Adjust LA along with flow/M221 for uniform width
//#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility //#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility
//#define LA_LIVE_K // Allow adjusting K in the Tune menu //#define LA_LIVE_K // Allow adjusting K in the Tune menu
//#define LA_DEBUG // If enabled, this will generate debug information output over USB. //#define LA_DEBUG // If enabled, this will generate debug information output over USB.
@ -441,6 +442,10 @@ const unsigned int dropsegments=5; //everything with less than this number of st
#undef BED_MINTEMP #undef BED_MINTEMP
#undef BED_MAXTEMP #undef BED_MAXTEMP
#endif #endif
#if TEMP_SENSOR_AMBIENT == 0
#undef AMBIENT_MINTEMP
#undef AMBIENT_MAXTEMP
#endif
#endif //__CONFIGURATION_ADV_H #endif //__CONFIGURATION_ADV_H

View File

@ -1,5 +1,5 @@
#include "Dcodes.h" #include "Dcodes.h"
//#include "Marlin.h" #include "Marlin.h"
#include "Configuration.h" #include "Configuration.h"
#include "language.h" #include "language.h"
#include "cmdqueue.h" #include "cmdqueue.h"
@ -226,9 +226,7 @@ void dcode_0()
LOG("D0 - Reset\n"); LOG("D0 - Reset\n");
if (code_seen('B')) //bootloader if (code_seen('B')) //bootloader
{ {
cli(); softReset();
wdt_enable(WDTO_15MS);
while(1);
} }
else //reset else //reset
{ {
@ -252,8 +250,7 @@ void dcode_1()
cli(); cli();
for (int i = 0; i < 8192; i++) for (int i = 0; i < 8192; i++)
eeprom_write_byte((unsigned char*)i, (unsigned char)0xff); eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
wdt_enable(WDTO_15MS); softReset();
while(1);
} }
/*! /*!
@ -420,8 +417,7 @@ void dcode_5()
boot_dst_addr = (uint32_t)address; boot_dst_addr = (uint32_t)address;
boot_src_addr = (uint32_t)(&data); boot_src_addr = (uint32_t)(&data);
bootapp_print_vars(); bootapp_print_vars();
wdt_enable(WDTO_15MS); softReset();
while(1);
} }
while (count) while (count)
{ {
@ -467,8 +463,7 @@ void dcode_7()
boot_copy_size = (uint16_t)0xc00; boot_copy_size = (uint16_t)0xc00;
boot_src_addr = (uint32_t)0x0003e400; boot_src_addr = (uint32_t)0x0003e400;
boot_dst_addr = (uint32_t)0x0003f400; boot_dst_addr = (uint32_t)0x0003f400;
wdt_enable(WDTO_15MS); softReset();
while(1);
*/ */
} }

View File

@ -299,7 +299,7 @@ extern float feedrate;
extern int feedmultiply; extern int feedmultiply;
extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders
extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually
extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner extern float extruder_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern float current_position[NUM_AXIS] ; extern float current_position[NUM_AXIS] ;
extern float destination[NUM_AXIS] ; extern float destination[NUM_AXIS] ;
extern float min_pos[3]; extern float min_pos[3];
@ -512,4 +512,6 @@ void load_filament_final_feed();
void marlin_wait_for_click(); void marlin_wait_for_click();
void raise_z_above(float target, bool plan=true); void raise_z_above(float target, bool plan=true);
extern "C" void softReset();
#endif #endif

View File

@ -654,6 +654,12 @@ void failstats_reset_print()
#endif #endif
} }
void softReset()
{
cli();
wdt_enable(WDTO_15MS);
while(1);
}
#ifdef MESH_BED_LEVELING #ifdef MESH_BED_LEVELING
@ -768,6 +774,7 @@ static void factory_reset(char level)
} }
} }
softReset();
break; break;
@ -3394,37 +3401,24 @@ void gcode_M701()
*/ */
static void gcode_PRUSA_SN() static void gcode_PRUSA_SN()
{ {
if (farm_mode) { uint8_t selectedSerialPort_bak = selectedSerialPort;
selectedSerialPort = 0; char SN[20];
putchar(';'); selectedSerialPort = 0;
putchar('S'); SERIAL_ECHOLNRPGM(PSTR(";S"));
int numbersRead = 0; uint8_t numbersRead = 0;
ShortTimer timeout; ShortTimer timeout;
timeout.start(); timeout.start();
while (numbersRead < 19) { while (numbersRead < (sizeof(SN) - 1)) {
while (MSerial.available() > 0) { if (MSerial.available() > 0) {
uint8_t serial_char = MSerial.read(); SN[numbersRead] = MSerial.read();
selectedSerialPort = 1; numbersRead++;
putchar(serial_char);
numbersRead++;
selectedSerialPort = 0;
}
if (timeout.expired(100u)) break;
} }
selectedSerialPort = 1; if (timeout.expired(100u)) break;
putchar('\n');
#if 0
for (int b = 0; b < 3; b++) {
_tone(BEEPER, 110);
_delay(50);
_noTone(BEEPER);
_delay(50);
}
#endif
} else {
puts_P(_N("Not in farm mode."));
} }
SN[numbersRead] = 0;
selectedSerialPort = selectedSerialPort_bak;
SERIAL_ECHOLN(SN);
} }
//! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors
//! at the TACH_1 pin, which causes bad detection of print fan speed. //! at the TACH_1 pin, which causes bad detection of print fan speed.
@ -3921,9 +3915,7 @@ void process_commands()
#if (defined(WATCHDOG) && (MOTHERBOARD == BOARD_EINSY_1_0a)) #if (defined(WATCHDOG) && (MOTHERBOARD == BOARD_EINSY_1_0a))
boot_app_magic = BOOT_APP_MAGIC; boot_app_magic = BOOT_APP_MAGIC;
boot_app_flags = BOOT_APP_FLG_RUN; boot_app_flags = BOOT_APP_FLG_RUN;
wdt_enable(WDTO_15MS); softReset();
cli();
while(1);
#else //WATCHDOG #else //WATCHDOG
asm volatile("jmp 0x3E000"); asm volatile("jmp 0x3E000");
#endif //WATCHDOG #endif //WATCHDOG
@ -4391,6 +4383,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
#endif //FWRETRACT #endif //FWRETRACT
/*!
### G21 - Sets Units to Millimters <a href="https://reprap.org/wiki/G-code#G21:_Set_Units_to_Millimeters">G21: Set Units to Millimeters</a>
Units are in millimeters. Prusa doesn't support inches.
*/
case 21:
break; //Doing nothing. This is just to prevent serial UNKOWN warnings.
/*! /*!
### G28 - Home all Axes one at a time <a href="https://reprap.org/wiki/G-code#G28:_Move_to_Origin_.28Home.29">G28: Move to Origin (Home)</a> ### G28 - Home all Axes one at a time <a href="https://reprap.org/wiki/G-code#G28:_Move_to_Origin_.28Home.29">G28: Move to Origin (Home)</a>
Using `G28` without any parameters will perfom homing of all axes AND mesh bed leveling, while `G28 W` will just home all axes (no mesh bed leveling). Using `G28` without any parameters will perfom homing of all axes AND mesh bed leveling, while `G28 W` will just home all axes (no mesh bed leveling).
@ -7342,17 +7342,26 @@ Sigma_Exit:
*/ */
case 220: // M220 S<factor in percent>- set speed factor override percentage case 220: // M220 S<factor in percent>- set speed factor override percentage
{ {
if (code_seen('B')) //backup current speed factor bool codesWereSeen = false;
{ if (code_seen('B')) //backup current speed factor
saved_feedmultiply_mm = feedmultiply; {
} saved_feedmultiply_mm = feedmultiply;
if(code_seen('S')) codesWereSeen = true;
{ }
feedmultiply = code_value() ; if (code_seen('S'))
} {
if (code_seen('R')) { //restore previous feedmultiply feedmultiply = code_value();
feedmultiply = saved_feedmultiply_mm; codesWereSeen = true;
} }
if (code_seen('R')) //restore previous feedmultiply
{
feedmultiply = saved_feedmultiply_mm;
codesWereSeen = true;
}
if (!codesWereSeen)
{
printf_P(PSTR("%i%%\n"), feedmultiply);
}
} }
break; break;
@ -7368,23 +7377,26 @@ Sigma_Exit:
*/ */
case 221: // M221 S<factor in percent>- set extrude factor override percentage case 221: // M221 S<factor in percent>- set extrude factor override percentage
{ {
if(code_seen('S')) if (code_seen('S'))
{
int tmp_code = code_value();
if (code_seen('T'))
{ {
uint8_t extruder; int tmp_code = code_value();
if(setTargetedHotend(221, extruder)){ if (code_seen('T'))
break; {
} uint8_t extruder;
extruder_multiply[extruder] = tmp_code; if (setTargetedHotend(221, extruder))
break;
extruder_multiply[extruder] = tmp_code;
}
else
{
extrudemultiply = tmp_code ;
}
} }
else else
{ {
extrudemultiply = tmp_code ; printf_P(PSTR("%i%%\n"), extrudemultiply);
} }
} calculate_extruder_multipliers();
calculate_extruder_multipliers();
} }
break; break;
@ -8612,7 +8624,7 @@ Sigma_Exit:
break; 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> ### 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. @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: case 999:
@ -11758,7 +11770,6 @@ void disable_force_z()
#endif // TMC2130 #endif // TMC2130
} }
void enable_force_z() void enable_force_z()
{ {
if(bEnableForce_z) if(bEnableForce_z)

View File

@ -9,6 +9,8 @@
extern FILE _uartout; extern FILE _uartout;
#define uartout (&_uartout) #define uartout (&_uartout)
extern void softReset();
void bootapp_print_vars(void) void bootapp_print_vars(void)
{ {
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr); fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
@ -39,8 +41,7 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
boot_src_addr = (uint32_t)rptr; boot_src_addr = (uint32_t)rptr;
boot_dst_addr = (uint32_t)fptr; boot_dst_addr = (uint32_t)fptr;
bootapp_print_vars(); bootapp_print_vars();
wdt_enable(WDTO_15MS); softReset();
while(1);
} }
void bootapp_reboot_user0(uint8_t reserved) void bootapp_reboot_user0(uint8_t reserved)
@ -50,6 +51,5 @@ void bootapp_reboot_user0(uint8_t reserved)
boot_app_flags = BOOT_APP_FLG_USER0; boot_app_flags = BOOT_APP_FLG_USER0;
boot_reserved = reserved; boot_reserved = reserved;
bootapp_print_vars(); bootapp_print_vars();
wdt_enable(WDTO_15MS); softReset();
while(1);
} }

View File

@ -359,6 +359,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
| ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^ | ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^
| 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff | 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2 | 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff | 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2
| 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Power panic saved Linear Advanced K value | ??? | D3 Ax0d2c C4 | 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Power panic saved Linear Advanced K value | ??? | D3 Ax0d2c C4
| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1
| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^
| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^
| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1
| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^
| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^
| Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code
@ -561,8 +567,11 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
#define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float #define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float
#define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8
#define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8
//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
#define EEPROM_LAST_ITEM EEPROM_UVLO_LA_K #define EEPROM_LAST_ITEM EEPROM_EXPERIMENTAL_VISIBILITY
// !!!!! // !!!!!
// !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
// !!!!! // !!!!!

View File

@ -58,7 +58,7 @@
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) #define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
/// check if pin is an timer /// check if pin is an timer
#define _GET_TIMER(IO) ((DIO ## IO ## _PWM) #define _GET_TIMER(IO) (DIO ## IO ## _PWM)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html // why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html

View File

@ -478,22 +478,8 @@ bool fsensor_oq_result(void)
} }
#endif //FSENSOR_QUALITY #endif //FSENSOR_QUALITY
ISR(FSENSOR_INT_PIN_VECT) FORCE_INLINE static void fsensor_isr(int st_cnt)
{ {
if (mmu_enabled || ir_sensor_detected) return;
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
// prevent isr re-entry
static bool _lock = false;
if (_lock) return;
_lock = true;
// fetch fsensor_st_cnt atomically
int st_cnt = fsensor_st_cnt;
fsensor_st_cnt = 0;
sei();
uint8_t old_err_cnt = fsensor_err_cnt; uint8_t old_err_cnt = fsensor_err_cnt;
uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y(); uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
if (!pat9125_res) if (!pat9125_res)
@ -578,8 +564,28 @@ ISR(FSENSOR_INT_PIN_VECT)
#endif //DEBUG_FSENSOR_LOG #endif //DEBUG_FSENSOR_LOG
pat9125_y = 0; pat9125_y = 0;
_lock = false; }
return;
ISR(FSENSOR_INT_PIN_VECT)
{
if (mmu_enabled || ir_sensor_detected) return;
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
// prevent isr re-entry
static bool _lock = false;
if (!_lock)
{
// fetch fsensor_st_cnt atomically
int st_cnt = fsensor_st_cnt;
fsensor_st_cnt = 0;
_lock = true;
sei();
fsensor_isr(st_cnt);
cli();
_lock = false;
}
} }
void fsensor_setup_interrupt(void) void fsensor_setup_interrupt(void)

View File

@ -48,6 +48,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
{ {
menu_menu = menu; menu_menu = menu;
lcd_encoder = encoder; lcd_encoder = encoder;
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
asm("sei"); asm("sei");
if (reset_menu_state) if (reset_menu_state)
{ {

View File

@ -226,11 +226,23 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
// Size of Plateau of Nominal Rate. // Size of Plateau of Nominal Rate.
uint32_t plateau_steps = 0; uint32_t plateau_steps = 0;
#ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0;
uint16_t max_adv_steps = 0;
if (block->use_advance_lead) {
final_adv_steps = final_rate * block->adv_comp;
}
#endif
// Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
// have to use intersection_distance() to calculate when to abort acceleration and start braking // have to use intersection_distance() to calculate when to abort acceleration and start braking
// in order to reach the final_rate exactly at the end of this block. // in order to reach the final_rate exactly at the end of this block.
if (accel_decel_steps < block->step_event_count.wide) { if (accel_decel_steps < block->step_event_count.wide) {
plateau_steps = block->step_event_count.wide - accel_decel_steps; plateau_steps = block->step_event_count.wide - accel_decel_steps;
#ifdef LIN_ADVANCE
if (block->use_advance_lead)
max_adv_steps = block->nominal_rate * block->adv_comp;
#endif
} else { } else {
uint32_t acceleration_x4 = acceleration << 2; uint32_t acceleration_x4 = acceleration << 2;
// Avoid negative numbers // Avoid negative numbers
@ -263,14 +275,20 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
decelerate_steps = block->step_event_count.wide; decelerate_steps = block->step_event_count.wide;
accelerate_steps = block->step_event_count.wide - decelerate_steps; accelerate_steps = block->step_event_count.wide - decelerate_steps;
} }
}
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0; if (block->use_advance_lead) {
if (block->use_advance_lead) { if(!accelerate_steps || !decelerate_steps) {
final_adv_steps = exit_speed * block->adv_comp; // accelerate_steps=0: deceleration-only ramp, max_rate is effectively unused
} // decelerate_steps=0: acceleration-only ramp, max_rate _is_ final_rate
max_adv_steps = final_adv_steps;
} else {
float max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr);
max_adv_steps = max_rate * block->adv_comp;
}
}
#endif #endif
}
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
// This block locks the interrupts globally for 4.38 us, // This block locks the interrupts globally for 4.38 us,
@ -284,6 +302,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
block->final_rate = final_rate; block->final_rate = final_rate;
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
block->final_adv_steps = final_adv_steps; block->final_adv_steps = final_adv_steps;
block->max_adv_steps = max_adv_steps;
#endif #endif
} }
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
@ -1077,12 +1096,20 @@ Having the real displacement of the head, we can calculate the total movement le
&& delta_mm[E_AXIS] >= 0 && delta_mm[E_AXIS] >= 0
&& abs(delta_mm[Z_AXIS]) < 0.5; && abs(delta_mm[Z_AXIS]) < 0.5;
if (block->use_advance_lead) { if (block->use_advance_lead) {
#ifdef LA_FLOWADJ
// M221/FLOW should change uniformly the extrusion thickness
float delta_e = (e - position_float[E_AXIS]) / extruder_multiplier[extruder];
#else
// M221/FLOW only adjusts for an incorrect source diameter
float delta_e = (e - position_float[E_AXIS]);
#endif
float delta_D = sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
// all extrusion moves with LA require a compression which is proportional to the // all extrusion moves with LA require a compression which is proportional to the
// extrusion_length to distance ratio (e/D) // extrusion_length to distance ratio (e/D)
e_D_ratio = (e - position_float[E_AXIS]) / e_D_ratio = delta_e / delta_D;
sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
// Check for unusual high e_D ratio to detect if a retract move was combined with the last // Check for unusual high e_D ratio to detect if a retract move was combined with the last
// print move due to min. steps per segment. Never execute this with advance! This assumes // print move due to min. steps per segment. Never execute this with advance! This assumes
@ -1132,53 +1159,7 @@ Having the real displacement of the head, we can calculate the total movement le
block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample; block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample;
#endif #endif
block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); block->acceleration_rate = ((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
// the nominal speed doesn't change past this point: calculate the compression ratio for the
// segment and the required advance steps
block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS];
block->max_adv_steps = block->nominal_speed * block->adv_comp;
float advance_speed;
if (e_D_ratio > 0)
advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
else
advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS];
// to save more space we avoid another copy of calc_timer and go through slow division, but we
// still need to replicate the *exact* same step grouping policy (see below)
if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
float advance_rate = (F_CPU / 8.0) / advance_speed;
if (advance_speed > 20000) {
block->advance_rate = advance_rate * 4;
block->advance_step_loops = 4;
}
else if (advance_speed > 10000) {
block->advance_rate = advance_rate * 2;
block->advance_step_loops = 2;
}
else
{
// never overflow the internal accumulator with very low rates
if (advance_rate < UINT16_MAX)
block->advance_rate = advance_rate;
else
block->advance_rate = UINT16_MAX;
block->advance_step_loops = 1;
}
#ifdef LA_DEBUG
if (block->advance_step_loops > 2)
// @wavexx: we should really check for the difference between step_loops and
// advance_step_loops instead. A difference of more than 1 will lead
// to uneven speed and *should* be adjusted here by furthermore
// reducing the speed.
SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
#endif
}
#endif
// Start with a safe speed. // Start with a safe speed.
// Safe speed is the speed, from which the machine may halt to stop immediately. // Safe speed is the speed, from which the machine may halt to stop immediately.
@ -1305,6 +1286,53 @@ Having the real displacement of the head, we can calculate the total movement le
// Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated. // Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated.
block->speed_factor = block->nominal_rate / block->nominal_speed; block->speed_factor = block->nominal_rate / block->nominal_speed;
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
// calculate the compression ratio for the segment (the required advance steps are computed
// during trapezoid planning)
float adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; // (step/(mm/s))
block->adv_comp = adv_comp / block->speed_factor; // step/(step/min)
float advance_speed;
if (e_D_ratio > 0)
advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
else
advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS];
// to save more space we avoid another copy of calc_timer and go through slow division, but we
// still need to replicate the *exact* same step grouping policy (see below)
if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
float advance_rate = (F_CPU / 8.0) / advance_speed;
if (advance_speed > 20000) {
block->advance_rate = advance_rate * 4;
block->advance_step_loops = 4;
}
else if (advance_speed > 10000) {
block->advance_rate = advance_rate * 2;
block->advance_step_loops = 2;
}
else
{
// never overflow the internal accumulator with very low rates
if (advance_rate < UINT16_MAX)
block->advance_rate = advance_rate;
else
block->advance_rate = UINT16_MAX;
block->advance_step_loops = 1;
}
#ifdef LA_DEBUG
if (block->advance_step_loops > 2)
// @wavexx: we should really check for the difference between step_loops and
// advance_step_loops instead. A difference of more than 1 will lead
// to uneven speed and *should* be adjusted here by furthermore
// reducing the speed.
SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
#endif
}
#endif
calculate_trapezoid_for_block(block, block->entry_speed, safe_speed); calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
if (block->step_event_count.wide <= 32767) if (block->step_event_count.wide <= 32767)

View File

@ -73,12 +73,12 @@ typedef struct {
// steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line(). // steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line().
dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis
dda_usteps_t step_event_count; // The number of step events required to complete this block dda_usteps_t step_event_count; // The number of step events required to complete this block
long acceleration_rate; // The acceleration rate used for acceleration calculation uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
unsigned char active_extruder; // Selects the active extruder unsigned char active_extruder; // Selects the active extruder
// accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller. // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller.
long accelerate_until; // The index of the step event on which to stop acceleration uint32_t accelerate_until; // The index of the step event on which to stop acceleration
long decelerate_after; // The index of the step event on which to start decelerating uint32_t decelerate_after; // The index of the step event on which to start decelerating
// Fields used by the motion planner to manage acceleration // Fields used by the motion planner to manage acceleration
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis // float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
@ -100,13 +100,12 @@ typedef struct {
// Settings for the trapezoid generator (runs inside an interrupt handler). // Settings for the trapezoid generator (runs inside an interrupt handler).
// Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts. // Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts.
//FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway!
unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec
unsigned long initial_rate; // The jerk-adjusted step rate at start of block unsigned long initial_rate; // The jerk-adjusted step rate at start of block
unsigned long final_rate; // The minimal rate at exit unsigned long final_rate; // The minimal rate at exit
unsigned long acceleration_st; // acceleration steps/sec^2 unsigned long acceleration_st; // acceleration steps/sec^2
//FIXME does it have to be unsigned long? Probably uint8_t would be just fine. //FIXME does it have to be int? Probably uint8_t would be just fine. Need to change in other places as well
unsigned long fan_speed; int fan_speed;
volatile char busy; volatile char busy;

View File

@ -80,15 +80,21 @@ asm volatile ( \
#else //_NO_ASM #else //_NO_ASM
// NOTE: currently not implemented static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2)
void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2); {
void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2); intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16;
}
static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2)
{
intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24;
}
#endif //_NO_ASM #endif //_NO_ASM
FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) { FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) {
unsigned short timer; uint16_t timer;
if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;
if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
@ -108,7 +114,7 @@ FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops)
if(step_rate >= (8*256)){ // higher step rate if(step_rate >= (8*256)){ // higher step rate
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
unsigned char tmp_step_rate = (step_rate & 0x00ff); unsigned char tmp_step_rate = (step_rate & 0x00ff);
unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2);
MultiU16X8toH16(timer, tmp_step_rate, gain); MultiU16X8toH16(timer, tmp_step_rate, gain);
timer = (unsigned short)pgm_read_word_near(table_address) - timer; timer = (unsigned short)pgm_read_word_near(table_address) - timer;
} }

View File

@ -71,8 +71,7 @@ static dda_isteps_t
counter_z, counter_z,
counter_e; counter_e;
volatile dda_usteps_t step_events_completed; // The number of step events executed in the current block volatile dda_usteps_t step_events_completed; // The number of step events executed in the current block
static int32_t acceleration_time, deceleration_time; static uint32_t acceleration_time, deceleration_time;
//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
static uint16_t acc_step_rate; // needed for deccelaration start point static uint16_t acc_step_rate; // needed for deccelaration start point
static uint8_t step_loops; static uint8_t step_loops;
static uint16_t OCR1A_nominal; static uint16_t OCR1A_nominal;
@ -125,7 +124,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
static uint16_t main_Rate; static uint16_t main_Rate;
static uint16_t eISR_Rate; static uint16_t eISR_Rate;
static uint16_t eISR_Err; static uint32_t eISR_Err;
static uint16_t current_adv_steps; static uint16_t current_adv_steps;
static uint16_t target_adv_steps; static uint16_t target_adv_steps;
@ -234,7 +233,7 @@ void invert_z_endstop(bool endstop_invert)
// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
// first block->accelerate_until step_events_completed, then keeps going at constant speed until // first block->accelerate_until step_events_completed, then keeps going at constant speed until
// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
// The slope of acceleration is calculated with the leib ramp alghorithm. // The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far.
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
@ -348,10 +347,7 @@ FORCE_INLINE void stepper_next_block()
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
e_step_loops = current_block->advance_step_loops;
target_adv_steps = current_block->max_adv_steps; target_adv_steps = current_block->max_adv_steps;
} else {
e_step_loops = 1;
} }
e_steps = 0; e_steps = 0;
nextAdvanceISR = ADV_NEVER; nextAdvanceISR = ADV_NEVER;
@ -736,38 +732,30 @@ FORCE_INLINE uint16_t fastdiv(uint16_t q, uint8_t d)
FORCE_INLINE void advance_spread(uint16_t timer) FORCE_INLINE void advance_spread(uint16_t timer)
{ {
if(eISR_Err > timer) eISR_Err += timer;
uint8_t ticks = 0;
while(eISR_Err >= current_block->advance_rate)
{
++ticks;
eISR_Err -= current_block->advance_rate;
}
if(!ticks)
{ {
// advance-step skipped
eISR_Err -= timer;
eISR_Rate = timer; eISR_Rate = timer;
nextAdvanceISR = timer; nextAdvanceISR = timer;
return; return;
} }
// at least one step if (ticks <= 3)
uint8_t ticks = 1; eISR_Rate = fastdiv(timer, ticks + 1);
uint32_t block = current_block->advance_rate;
uint16_t max_t = timer - eISR_Err;
while (block < max_t)
{
++ticks;
block += current_block->advance_rate;
}
if (block > timer)
eISR_Err += block - timer;
else
eISR_Err -= timer - block;
if (ticks <= 4)
eISR_Rate = fastdiv(timer, ticks);
else else
{ {
// >4 ticks are still possible on slow moves // >4 ticks are still possible on slow moves
eISR_Rate = timer / ticks; eISR_Rate = timer / (ticks + 1);
} }
nextAdvanceISR = eISR_Rate / 2; nextAdvanceISR = eISR_Rate;
} }
#endif #endif
@ -799,7 +787,7 @@ FORCE_INLINE void isr() {
// 25.12us for acceleration / deceleration. // 25.12us for acceleration / deceleration.
{ {
//WRITE_NC(LOGIC_ANALYZER_CH1, true); //WRITE_NC(LOGIC_ANALYZER_CH1, true);
if (step_events_completed.wide <= (unsigned long int)current_block->accelerate_until) { if (step_events_completed.wide <= current_block->accelerate_until) {
// v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate // v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate
MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
acc_step_rate += uint16_t(current_block->initial_rate); acc_step_rate += uint16_t(current_block->initial_rate);
@ -812,19 +800,29 @@ FORCE_INLINE void isr() {
acceleration_time += timer; acceleration_time += timer;
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
if (step_events_completed.wide <= (unsigned long int)step_loops) if (step_events_completed.wide <= (unsigned long int)step_loops) {
la_state = ADV_INIT | ADV_ACC_VARY; la_state = ADV_INIT | ADV_ACC_VARY;
if (e_extruding && current_adv_steps > target_adv_steps)
target_adv_steps = current_adv_steps;
}
} }
#endif #endif
} }
else if (step_events_completed.wide > (unsigned long int)current_block->decelerate_after) { else if (step_events_completed.wide > current_block->decelerate_after) {
uint16_t step_rate; uint16_t step_rate;
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point.
if ((step_rate & 0x8000) || step_rate < uint16_t(current_block->final_rate)) { if (step_rate > acc_step_rate) { // Check step_rate stays positive
// Result is negative or too small. step_rate = uint16_t(current_block->final_rate);
step_rate = uint16_t(current_block->final_rate);
} }
else {
step_rate = acc_step_rate - step_rate; // Decelerate from acceleration end point.
// lower limit
if (step_rate < current_block->final_rate)
step_rate = uint16_t(current_block->final_rate);
}
// Step_rate to timer interval. // Step_rate to timer interval.
uint16_t timer = calc_timer(step_rate, step_loops); uint16_t timer = calc_timer(step_rate, step_loops);
_NEXT_ISR(timer); _NEXT_ISR(timer);
@ -832,9 +830,11 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (current_block->use_advance_lead) { if (current_block->use_advance_lead) {
if (step_events_completed.wide <= (unsigned long int)current_block->decelerate_after + step_loops) { if (step_events_completed.wide <= current_block->decelerate_after + step_loops) {
target_adv_steps = current_block->final_adv_steps; target_adv_steps = current_block->final_adv_steps;
la_state = ADV_INIT | ADV_ACC_VARY; la_state = ADV_INIT | ADV_ACC_VARY;
if (e_extruding && current_adv_steps < target_adv_steps)
target_adv_steps = current_adv_steps;
} }
} }
#endif #endif
@ -848,12 +848,12 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if(current_block->use_advance_lead) { if(current_block->use_advance_lead) {
if (!nextAdvanceISR) { // Due to E-jerk, there can be discontinuities in pressure state where an
// Due to E-jerk, there can be discontinuities in pressure state where an // acceleration or deceleration can be skipped or joined with the previous block.
// acceleration or deceleration can be skipped or joined with the previous block. // If LA was not previously active, re-check the pressure level
// If LA was not previously active, re-check the pressure level la_state = ADV_INIT;
la_state = ADV_INIT; if (e_extruding)
} target_adv_steps = current_adv_steps;
} }
#endif #endif
} }
@ -865,14 +865,21 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
// avoid multiple instances or function calls to advance_spread // avoid multiple instances or function calls to advance_spread
if (la_state & ADV_INIT) { if (la_state & ADV_INIT) {
LA_phase = -1;
if (current_adv_steps == target_adv_steps) { if (current_adv_steps == target_adv_steps) {
// nothing to be done in this phase // nothing to be done in this phase, cancel any pending eisr
la_state = 0; la_state = 0;
nextAdvanceISR = ADV_NEVER;
} }
else { else {
eISR_Err = current_block->advance_rate / 4; // reset error and iterations per loop for this phase
eISR_Err = current_block->advance_rate;
e_step_loops = current_block->advance_step_loops;
if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) { if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) {
// LA could reverse the direction of extrusion in this phase // LA could reverse the direction of extrusion in this phase
eISR_Err += current_block->advance_rate;
LA_phase = 0; LA_phase = 0;
} }
} }
@ -882,11 +889,13 @@ FORCE_INLINE void isr() {
advance_spread(main_Rate); advance_spread(main_Rate);
if (LA_phase >= 0) { if (LA_phase >= 0) {
if (step_loops == e_step_loops) if (step_loops == e_step_loops)
LA_phase = (eISR_Rate > main_Rate); LA_phase = (current_block->advance_rate < main_Rate);
else { else {
// avoid overflow through division. warning: we need to _guarantee_ step_loops // avoid overflow through division. warning: we need to _guarantee_ step_loops
// and e_step_loops are <= 4 due to fastdiv's limit // and e_step_loops are <= 4 due to fastdiv's limit
LA_phase = (fastdiv(eISR_Rate, step_loops) > fastdiv(main_Rate, e_step_loops)); auto adv_rate_n = fastdiv(current_block->advance_rate, step_loops);
auto main_rate_n = fastdiv(main_Rate, e_step_loops);
LA_phase = (adv_rate_n < main_rate_n);
} }
} }
} }
@ -928,26 +937,34 @@ FORCE_INLINE void isr() {
FORCE_INLINE void advance_isr() { FORCE_INLINE void advance_isr() {
if (current_adv_steps > target_adv_steps) { if (current_adv_steps > target_adv_steps) {
// decompression // decompression
if (e_step_loops != 1) {
uint16_t d_steps = current_adv_steps - target_adv_steps;
if (d_steps < e_step_loops)
e_step_loops = d_steps;
}
e_steps -= e_step_loops; e_steps -= e_step_loops;
if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR);
if(current_adv_steps > e_step_loops) current_adv_steps -= e_step_loops;
current_adv_steps -= e_step_loops;
else
current_adv_steps = 0;
nextAdvanceISR = eISR_Rate;
} }
else if (current_adv_steps < target_adv_steps) { else if (current_adv_steps < target_adv_steps) {
// compression // compression
if (e_step_loops != 1) {
uint16_t d_steps = target_adv_steps - current_adv_steps;
if (d_steps < e_step_loops)
e_step_loops = d_steps;
}
e_steps += e_step_loops; e_steps += e_step_loops;
if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR);
current_adv_steps += e_step_loops; current_adv_steps += e_step_loops;
nextAdvanceISR = eISR_Rate;
} }
else {
if (current_adv_steps == target_adv_steps) {
// advance steps completed // advance steps completed
nextAdvanceISR = ADV_NEVER; nextAdvanceISR = ADV_NEVER;
LA_phase = -1; }
e_step_loops = 1; else {
// schedule another tick
nextAdvanceISR = eISR_Rate;
} }
} }
@ -1017,7 +1034,7 @@ FORCE_INLINE void advance_isr_scheduler() {
// Schedule the next closest tick, ignoring advance if scheduled too // Schedule the next closest tick, ignoring advance if scheduled too
// soon in order to avoid skewing the regular stepper acceleration // soon in order to avoid skewing the regular stepper acceleration
if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + TCNT1 + 40) < nextMainISR) if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + 40) < nextMainISR)
OCR1A = nextAdvanceISR; OCR1A = nextAdvanceISR;
else else
OCR1A = nextMainISR; OCR1A = nextMainISR;

View File

@ -152,7 +152,11 @@ uint8_t fanSpeedBckp = 255;
bool fan_measuring = false; bool fan_measuring = false;
uint8_t fanState = 0; uint8_t fanState = 0;
#ifdef EXTRUDER_ALTFAN_DETECT #ifdef EXTRUDER_ALTFAN_DETECT
bool extruderFanIsAltfan = false; //set to Noctua struct
{
uint8_t isAltfan : 1;
uint8_t altfanOverride : 1;
} altfanStatus;
#endif //EXTRUDER_ALTFAN_DETECT #endif //EXTRUDER_ALTFAN_DETECT
#endif #endif
@ -180,6 +184,12 @@ static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP;
#ifdef BED_MAXTEMP #ifdef BED_MAXTEMP
static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP; static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
#endif #endif
#ifdef AMBIENT_MINTEMP
static int ambient_minttemp_raw = AMBIENT_RAW_LO_TEMP;
#endif
#ifdef AMBIENT_MAXTEMP
static int ambient_maxttemp_raw = AMBIENT_RAW_HI_TEMP;
#endif
static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE ); static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE );
static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN ); static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN );
@ -224,6 +234,15 @@ bool extruder_altfan_detect()
setExtruderAutoFanState(3); setExtruderAutoFanState(3);
SET_INPUT(TACH_0); 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; CRITICAL_SECTION_START;
EICRB &= ~(1 << ISC61); EICRB &= ~(1 << ISC61);
EICRB |= (1 << ISC60); EICRB |= (1 << ISC60);
@ -237,10 +256,22 @@ bool extruder_altfan_detect()
EIMSK &= ~(1 << INT6); EIMSK &= ~(1 << INT6);
countFanSpeed(); countFanSpeed();
extruderFanIsAltfan = fan_speed[0] > 100; altfanStatus.isAltfan = fan_speed[0] > 100;
setExtruderAutoFanState(1); setExtruderAutoFanState(1);
return extruderFanIsAltfan; 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 #endif //EXTRUDER_ALTFAN_DETECT
// return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on') // return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on')
@ -494,7 +525,7 @@ void setExtruderAutoFanState(uint8_t state)
if (fanState & 0x01) if (fanState & 0x01)
{ {
#ifdef EXTRUDER_ALTFAN_DETECT #ifdef EXTRUDER_ALTFAN_DETECT
if (extruderFanIsAltfan) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT;
else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
#else //EXTRUDER_ALTFAN_DETECT #else //EXTRUDER_ALTFAN_DETECT
newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
@ -639,6 +670,7 @@ void manage_heater()
return; return;
// more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms) // more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms)
// ADC values need to be converted before checking: converted values are later used in MINTEMP
updateTemperaturesFromRawValues(); updateTemperaturesFromRawValues();
check_max_temp(); check_max_temp();
@ -1165,7 +1197,6 @@ void tp_init()
#endif //MAXTEMP 2 #endif //MAXTEMP 2
#ifdef BED_MINTEMP #ifdef BED_MINTEMP
/* No bed MINTEMP error implemented?!? */
while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) { while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) {
#if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP #if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
bed_minttemp_raw += OVERSAMPLENR; bed_minttemp_raw += OVERSAMPLENR;
@ -1173,7 +1204,6 @@ void tp_init()
bed_minttemp_raw -= OVERSAMPLENR; bed_minttemp_raw -= OVERSAMPLENR;
#endif #endif
} }
#endif //BED_MINTEMP #endif //BED_MINTEMP
#ifdef BED_MAXTEMP #ifdef BED_MAXTEMP
while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) { while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) {
@ -1184,6 +1214,25 @@ void tp_init()
#endif #endif
} }
#endif //BED_MAXTEMP #endif //BED_MAXTEMP
#ifdef AMBIENT_MINTEMP
while(analog2tempAmbient(ambient_minttemp_raw) < AMBIENT_MINTEMP) {
#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP
ambient_minttemp_raw += OVERSAMPLENR;
#else
ambient_minttemp_raw -= OVERSAMPLENR;
#endif
}
#endif //AMBIENT_MINTEMP
#ifdef AMBIENT_MAXTEMP
while(analog2tempAmbient(ambient_maxttemp_raw) > AMBIENT_MAXTEMP) {
#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP
ambient_maxttemp_raw -= OVERSAMPLENR;
#else
ambient_maxttemp_raw += OVERSAMPLENR;
#endif
}
#endif //AMBIENT_MAXTEMP
} }
#if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0) #if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0)
@ -1356,7 +1405,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
SERIAL_ERROR_START; SERIAL_ERROR_START;
isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)");
#ifdef EXTRUDER_ALTFAN_DETECT #ifdef EXTRUDER_ALTFAN_DETECT
extruderFanIsAltfan = false; //full speed altfanStatus.altfanOverride = 1; //full speed
#endif //EXTRUDER_ALTFAN_DETECT #endif //EXTRUDER_ALTFAN_DETECT
setExtruderAutoFanState(3); setExtruderAutoFanState(3);
SET_OUTPUT(FAN_PIN); SET_OUTPUT(FAN_PIN);
@ -1427,26 +1476,53 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_
//! to prevent flicker and improve speed //! to prevent flicker and improve speed
uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; uint8_t last_alert_sent_to_lcd = LCDALERT_NONE;
//! update the current temperature error message
//! @param type short error abbreviation (PROGMEM)
//! @param func optional lcd update function (lcd_setalertstatus when first setting the error)
void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus)
{
char msg[LCD_WIDTH];
strcpy_P(msg, PSTR("Err: "));
strcat_P(msg, type);
(*func)(msg);
}
//! signal a temperature error on both the lcd and serial
//! @param type short error abbreviation (PROGMEM)
//! @param e optional extruder index for hotend errors
void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS)
{
temp_update_messagepgm(type, lcd_setalertstatus);
SERIAL_ERROR_START;
if(e != EXTRUDERS) {
SERIAL_ERROR((int)e);
SERIAL_ERRORPGM(": ");
}
SERIAL_ERRORPGM("Heaters switched off. ");
SERIAL_ERRORRPGM(type);
SERIAL_ERRORLNPGM(" triggered!");
}
void max_temp_error(uint8_t e) { void max_temp_error(uint8_t e) {
disable_heater(); disable_heater();
if(IsStopped() == false) { if(IsStopped() == false) {
SERIAL_ERROR_START; temp_error_messagepgm(PSTR("MAXTEMP"), e);
SERIAL_ERRORLN((int)e);
SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !");
LCD_ALERTMESSAGEPGM("Err: MAXTEMP");
} }
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop(); Stop();
#endif #endif
SET_OUTPUT(FAN_PIN); SET_OUTPUT(FAN_PIN);
SET_OUTPUT(BEEPER); SET_OUTPUT(BEEPER);
WRITE(FAN_PIN, 1); WRITE(FAN_PIN, 1);
WRITE(BEEPER, 1); WRITE(BEEPER, 1);
#ifdef EXTRUDER_ALTFAN_DETECT #ifdef EXTRUDER_ALTFAN_DETECT
extruderFanIsAltfan = false; //full speed altfanStatus.altfanOverride = 1; //full speed
#endif //EXTRUDER_ALTFAN_DETECT #endif //EXTRUDER_ALTFAN_DETECT
setExtruderAutoFanState(3); setExtruderAutoFanState(3);
// fanSpeed will consumed by the check_axes_activity() routine. // fanSpeed will consumed by the check_axes_activity() routine.
@ -1458,18 +1534,15 @@ void min_temp_error(uint8_t e) {
#ifdef DEBUG_DISABLE_MINTEMP #ifdef DEBUG_DISABLE_MINTEMP
return; return;
#endif #endif
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
disable_heater(); disable_heater();
static const char err[] PROGMEM = "Err: MINTEMP"; //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
static const char err[] PROGMEM = "MINTEMP";
if(IsStopped() == false) { if(IsStopped() == false) {
SERIAL_ERROR_START; temp_error_messagepgm(err, e);
SERIAL_ERRORLN((int)e);
SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !");
lcd_setalertstatuspgm(err);
last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP;
} else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) } else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time)
// we are already stopped due to some error, only update the status message without flickering // we are already stopped due to some error, only update the status message without flickering
lcd_updatestatuspgm(err); temp_update_messagepgm(err);
last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP;
} }
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
@ -1484,37 +1557,27 @@ void min_temp_error(uint8_t e) {
} }
void bed_max_temp_error(void) { void bed_max_temp_error(void) {
#if HEATER_BED_PIN > -1 disable_heater();
//WRITE(HEATER_BED_PIN, 0);
#endif
if(IsStopped() == false) { if(IsStopped() == false) {
SERIAL_ERROR_START; temp_error_messagepgm(PSTR("MAXTEMP BED"));
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !");
LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED");
} }
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop(); Stop();
#endif #endif
} }
void bed_min_temp_error(void) { void bed_min_temp_error(void) {
#ifdef DEBUG_DISABLE_MINTEMP #ifdef DEBUG_DISABLE_MINTEMP
return; return;
#endif #endif
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; disable_heater();
#if HEATER_BED_PIN > -1 static const char err[] PROGMEM = "MINTEMP BED";
//WRITE(HEATER_BED_PIN, 0);
#endif
static const char err[] PROGMEM = "Err: MINTEMP BED";
if(IsStopped() == false) { if(IsStopped() == false) {
SERIAL_ERROR_START; temp_error_messagepgm(err);
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !");
lcd_setalertstatuspgm(err);
last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP;
} else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) } else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time)
// we are already stopped due to some error, only update the status message without flickering // we are already stopped due to some error, only update the status message without flickering
lcd_updatestatuspgm(err); temp_update_messagepgm(err);
last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP;
} }
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
@ -1522,6 +1585,33 @@ void bed_min_temp_error(void) {
#endif #endif
} }
#ifdef AMBIENT_THERMISTOR
void ambient_max_temp_error(void) {
disable_heater();
if(IsStopped() == false) {
temp_error_messagepgm(PSTR("MAXTEMP AMB"));
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
}
void ambient_min_temp_error(void) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
disable_heater();
if(IsStopped() == false) {
temp_error_messagepgm(PSTR("MINTEMP AMB"));
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
}
#endif
#ifdef HEATER_0_USES_MAX6675 #ifdef HEATER_0_USES_MAX6675
#define MAX6675_HEAT_INTERVAL 250 #define MAX6675_HEAT_INTERVAL 250
long max6675_previous_millis = MAX6675_HEAT_INTERVAL; long max6675_previous_millis = MAX6675_HEAT_INTERVAL;
@ -1606,18 +1696,8 @@ void adc_ready(void) //callback from adc when sampling finished
} // extern "C" } // extern "C"
// Timer2 (originaly timer0) is shared with millies FORCE_INLINE static void temperature_isr()
#ifdef SYSTEM_TIMER_2
ISR(TIMER2_COMPB_vect)
#else //SYSTEM_TIMER_2
ISR(TIMER0_COMPB_vect)
#endif //SYSTEM_TIMER_2
{ {
static bool _lock = false;
if (_lock) return;
_lock = true;
asm("sei");
if (!temp_meas_ready) adc_cycle(); if (!temp_meas_ready) adc_cycle();
lcd_buttons_update(); lcd_buttons_update();
@ -1983,8 +2063,24 @@ ISR(TIMER0_COMPB_vect)
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1)) #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
check_fans(); check_fans();
#endif //(defined(TACH_0)) #endif //(defined(TACH_0))
}
_lock = false; // Timer2 (originaly timer0) is shared with millies
#ifdef SYSTEM_TIMER_2
ISR(TIMER2_COMPB_vect)
#else //SYSTEM_TIMER_2
ISR(TIMER0_COMPB_vect)
#endif //SYSTEM_TIMER_2
{
static bool _lock = false;
if (!_lock)
{
_lock = true;
sei();
temperature_isr();
cli();
_lock = false;
}
} }
void check_max_temp() void check_max_temp()
@ -2004,11 +2100,19 @@ void check_max_temp()
#else #else
if (current_temperature_bed_raw >= bed_maxttemp_raw) { if (current_temperature_bed_raw >= bed_maxttemp_raw) {
#endif #endif
target_temperature_bed = 0;
bed_max_temp_error(); bed_max_temp_error();
} }
#endif #endif
//ambient
#if defined(AMBIENT_MAXTEMP) && (TEMP_SENSOR_AMBIENT != 0)
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if (current_temperature_raw_ambient <= ambient_maxttemp_raw) {
#else
if (current_temperature_raw_ambient >= ambient_maxttemp_raw) {
#endif
ambient_max_temp_error();
}
#endif
} }
//! number of repeating the same state with consecutive step() calls //! number of repeating the same state with consecutive step() calls
//! used to slow down text switching //! used to slow down text switching
@ -2103,12 +2207,32 @@ void check_min_temp_bed()
} }
} }
#ifdef AMBIENT_MINTEMP
void check_min_temp_ambient()
{
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if (current_temperature_raw_ambient >= ambient_minttemp_raw) {
#else
if (current_temperature_raw_ambient <= ambient_minttemp_raw) {
#endif
ambient_min_temp_error();
}
}
#endif
void check_min_temp() void check_min_temp()
{ {
static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp) static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp)
static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp) static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp)
#ifdef AMBIENT_THERMISTOR #ifdef AMBIENT_THERMISTOR
if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type, so operator is ">" ;-) #ifdef AMBIENT_MINTEMP
check_min_temp_ambient();
#endif
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type
#else
if(current_temperature_raw_ambient=<(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW))
#endif
{ // ambient temperature is low { // ambient temperature is low
#endif //AMBIENT_THERMISTOR #endif //AMBIENT_THERMISTOR
// *** 'common' part of code for MK2.5 & MK3 // *** 'common' part of code for MK2.5 & MK3

View File

@ -273,6 +273,8 @@ void check_max_temp();
#ifdef EXTRUDER_ALTFAN_DETECT #ifdef EXTRUDER_ALTFAN_DETECT
extern bool extruder_altfan_detect(); extern bool extruder_altfan_detect();
extern void altfanOverride_toggle();
extern bool altfanOverride_get();
#endif //EXTRUDER_ALTFAN_DETECT #endif //EXTRUDER_ALTFAN_DETECT
extern unsigned long extruder_autofan_last_check; extern unsigned long extruder_autofan_last_check;

View File

@ -1213,6 +1213,8 @@ const short temptable_1047[][2] PROGMEM = {
#endif #endif
#if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1 #if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1
# define AMBIENT_RAW_HI_TEMP 0
# define AMBIENT_RAW_LO_TEMP 16383
const short temptable_2000[][2] PROGMEM = { const short temptable_2000[][2] PROGMEM = {
// Source: https://product.tdk.com/info/en/catalog/datasheets/503021/tpd_ntc-thermistor_ntcg_en.pdf // Source: https://product.tdk.com/info/en/catalog/datasheets/503021/tpd_ntc-thermistor_ntcg_en.pdf
// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance // Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance

View File

@ -1001,6 +1001,36 @@ void lcd_status_screen() // NOT static due to using ins
} }
} }
#ifdef ULTIPANEL_FEEDMULTIPLY
// Dead zone at 100% feedrate
if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
{
lcd_encoder = 0;
feedmultiply = 100;
}
if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply != 100)
{
feedmultiply += int(lcd_encoder);
lcd_encoder = 0;
}
#endif //ULTIPANEL_FEEDMULTIPLY
if (feedmultiply < 10)
feedmultiply = 10;
else if (feedmultiply > 999)
feedmultiply = 999;
if (lcd_status_update_delay) if (lcd_status_update_delay)
lcd_status_update_delay--; lcd_status_update_delay--;
else else
@ -1077,36 +1107,6 @@ void lcd_status_screen() // NOT static due to using ins
menu_submenu(lcd_main_menu); menu_submenu(lcd_main_menu);
lcd_refresh(); // to maybe revive the LCD if static electricity killed it. lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
} }
#ifdef ULTIPANEL_FEEDMULTIPLY
// Dead zone at 100% feedrate
if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
{
lcd_encoder = 0;
feedmultiply = 100;
}
if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply != 100)
{
feedmultiply += int(lcd_encoder);
lcd_encoder = 0;
}
#endif //ULTIPANEL_FEEDMULTIPLY
if (feedmultiply < 10)
feedmultiply = 10;
else if (feedmultiply > 999)
feedmultiply = 999;
} }
void lcd_commands() void lcd_commands()
@ -2126,6 +2126,7 @@ static void lcd_support_menu()
sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"),
_md->ip[0], _md->ip[1], _md->ip[0], _md->ip[1],
_md->ip[2], _md->ip[3]); _md->ip[2], _md->ip[3]);
} else if (_md->is_flash_air && } else if (_md->is_flash_air &&
_md->ip[0] == 0 && _md->ip[1] == 0 && _md->ip[0] == 0 && _md->ip[1] == 0 &&
_md->ip[2] == 0 && _md->ip[3] == 0 && _md->ip[2] == 0 && _md->ip[3] == 0 &&
@ -2210,6 +2211,7 @@ static void lcd_support_menu()
MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1 MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1
#endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1 MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1
#endif /* DEBUG_BUILD */ #endif /* DEBUG_BUILD */
@ -5712,6 +5714,25 @@ static void sheets_menu()
void lcd_hw_setup_menu(void) // can not be "static" void lcd_hw_setup_menu(void) // can not be "static"
{ {
typedef struct
{// 2bytes total
int8_t status;
uint8_t experimental_menu_visibility;
} _menu_data_t;
static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data");
_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
if (_md->status == 0 || lcd_draw_update)
{
_md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY);
if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE)
{
_md->experimental_menu_visibility = 0;
eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility);
}
}
MENU_BEGIN(); MENU_BEGIN();
MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch
@ -5725,6 +5746,12 @@ void lcd_hw_setup_menu(void) // can not be "static"
//! @todo Don't forget to remove this as soon Fsensor Detection works with mmu //! @todo Don't forget to remove this as soon Fsensor Detection works with mmu
if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor); if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
#endif //IR_SENSOR_ANALOG #endif //IR_SENSOR_ANALOG
if (_md->experimental_menu_visibility)
{
MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18
}
MENU_END(); MENU_END();
} }
@ -8951,13 +8978,14 @@ void lcd_finishstatus() {
lcd_draw_update = 2; lcd_draw_update = 2;
} }
void lcd_setstatus(const char* message) void lcd_setstatus(const char* message)
{ {
if (lcd_status_message_level > 0) if (lcd_status_message_level > 0)
return; return;
strncpy(lcd_status_message, message, LCD_WIDTH); lcd_updatestatus(message);
lcd_finishstatus();
} }
void lcd_updatestatuspgm(const char *message){ void lcd_updatestatuspgm(const char *message){
strncpy_P(lcd_status_message, message, LCD_WIDTH); strncpy_P(lcd_status_message, message, LCD_WIDTH);
lcd_status_message[LCD_WIDTH] = 0; lcd_status_message[LCD_WIDTH] = 0;
@ -8972,12 +9000,29 @@ void lcd_setstatuspgm(const char* message)
return; return;
lcd_updatestatuspgm(message); lcd_updatestatuspgm(message);
} }
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) void lcd_setalertstatuspgm(const char* message)
{ {
lcd_setstatuspgm(message); lcd_setstatuspgm(message);
lcd_status_message_level = 1; lcd_status_message_level = 1;
lcd_return_to_status(); lcd_return_to_status();
} }
void lcd_setalertstatus(const char* message)
{
lcd_setstatus(message);
lcd_status_message_level = 1;
lcd_return_to_status();
}
void lcd_reset_alert_level() void lcd_reset_alert_level()
{ {
lcd_status_message_level = 0; lcd_status_message_level = 0;
@ -8997,6 +9042,13 @@ void menu_lcd_longpress_func(void)
lcd_quick_feedback(); lcd_quick_feedback();
return; return;
} }
if (menu_menu == lcd_hw_setup_menu)
{
// only toggle the experimental menu visibility flag
lcd_quick_feedback();
lcd_experimental_toggle();
return;
}
// explicitely listed menus which are allowed to rise the move-z or live-adj-z functions // explicitely listed menus which are allowed to rise the move-z or live-adj-z functions
// The lists are not the same for both functions, so first decide which function is to be performed // The lists are not the same for both functions, so first decide which function is to be performed
@ -9160,3 +9212,25 @@ void lcd_crash_detect_disable()
eeprom_update_byte((uint8_t*)EEPROM_CRASH_DET, 0x00); eeprom_update_byte((uint8_t*)EEPROM_CRASH_DET, 0x00);
} }
#endif #endif
void lcd_experimental_toggle()
{
uint8_t oldVal = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY);
if (oldVal == EEPROM_EMPTY_VALUE)
oldVal = 0;
else
oldVal = !oldVal;
eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, oldVal);
}
void lcd_experimental_menu()
{
MENU_BEGIN();
MENU_ITEM_BACK_P(_T(MSG_BACK));
#ifdef EXTRUDER_ALTFAN_DETECT
MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle);////MSG_MENU_ALTFAN c=18
#endif //EXTRUDER_ALTFAN_DETECT
MENU_END();
}

View File

@ -23,9 +23,11 @@ void lcd_setstatuspgm(const char* message);
//! - always returns the display to the main status screen //! - always returns the display to the main status screen
//! - always makes lcd_reset (which is slow and causes flicker) //! - always makes lcd_reset (which is slow and causes flicker)
//! - does not update the message if there is already one (i.e. lcd_status_message_level > 0) //! - does not update the message if there is already one (i.e. lcd_status_message_level > 0)
void lcd_setalertstatus(const char* message);
void lcd_setalertstatuspgm(const char* message); void lcd_setalertstatuspgm(const char* message);
//! only update the alert message on the main status screen //! only update the alert message on the main status screen
//! has no sideeffects, may be called multiple times //! has no sideeffects, may be called multiple times
void lcd_updatestatus(const char *message);
void lcd_updatestatuspgm(const char *message); void lcd_updatestatuspgm(const char *message);
void lcd_reset_alert_level(); void lcd_reset_alert_level();
@ -257,4 +259,7 @@ enum class WizState : uint8_t
void lcd_wizard(WizState state); void lcd_wizard(WizState state);
extern void lcd_experimental_toggle();
extern void lcd_experimental_menu();
#endif //ULTRALCD_H #endif //ULTRALCD_H

View File

@ -296,6 +296,7 @@
#endif #endif
#define DETECT_SUPERPINDA #define DETECT_SUPERPINDA
#define PINDA_MINTEMP BED_MINTEMP #define PINDA_MINTEMP BED_MINTEMP
#define AMBIENT_MINTEMP -30
// Maxtemps // Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
@ -306,6 +307,7 @@
#define HEATER_1_MAXTEMP 305 #define HEATER_1_MAXTEMP 305
#define HEATER_2_MAXTEMP 305 #define HEATER_2_MAXTEMP 305
#define BED_MAXTEMP 125 #define BED_MAXTEMP 125
#define AMBIENT_MAXTEMP 100
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
// Define PID constants for extruder with PT100 // Define PID constants for extruder with PT100

View File

@ -298,6 +298,7 @@
#endif #endif
#define DETECT_SUPERPINDA #define DETECT_SUPERPINDA
#define PINDA_MINTEMP BED_MINTEMP #define PINDA_MINTEMP BED_MINTEMP
#define AMBIENT_MINTEMP -30
// Maxtemps // Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
@ -308,6 +309,7 @@
#define HEATER_1_MAXTEMP 305 #define HEATER_1_MAXTEMP 305
#define HEATER_2_MAXTEMP 305 #define HEATER_2_MAXTEMP 305
#define BED_MAXTEMP 125 #define BED_MAXTEMP 125
#define AMBIENT_MAXTEMP 100
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
// Define PID constants for extruder with PT100 // Define PID constants for extruder with PT100

View File

@ -26,14 +26,28 @@ The firmware for the Original Prusa i3 printers is proudly based on [Marlin 1.0.
1. Clone this repository and checkout the correct branch for your desired release version. 1. Clone this repository and checkout the correct branch for your desired release version.
2. Set your printer model. 1. Set your printer model.
- For MK3 --> skip to step 3. - For MK3 --> skip to step 3.
- If you have a different printer model, follow step [2.b](#2b) from Windows build - If you have a different printer model, follow step [2.b](#2b) from Windows build
1. Install GNU AWK `sudo apt-get install gawk`
If you use mawk instead of gawk you get strange errors when multi language support is generated like:
`awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
tr: write error: Broken pipe
./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
tr: write error: Broken pipe
tr: write error
cut: write error: Broken pipeNG! - some texts not found in lang_en.txt! updating binary:
primary language ids...awk: line 2: function strtonum never defined
sed: couldn't flush stdout: Broken pipe`
3. Run `./build.sh` 1. Run `./build.sh`
- Output hex file is at `"PrusaFirmware/lang/firmware.hex"` . In the same folder you can hex files for other languages as well. - Output hex file is at `"PrusaFirmware/lang/firmware.hex"` . In the same folder you can hex files for other languages as well.
4. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE. 1. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE.
- If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first. - If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first.
@ -182,7 +196,7 @@ Example:
`ninja` `ninja`
## Runing ## Running
`./tests` `./tests`
# 4. Documentation # 4. Documentation