Merge branch 'MK3' into MK3_AUTO_REPORT_TEMPERATURES
This commit is contained in:
commit
073eadff7e
@ -293,6 +293,7 @@
|
||||
#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_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_LIVE_K // Allow adjusting K in the Tune menu
|
||||
//#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_MAXTEMP
|
||||
#endif
|
||||
#if TEMP_SENSOR_AMBIENT == 0
|
||||
#undef AMBIENT_MINTEMP
|
||||
#undef AMBIENT_MAXTEMP
|
||||
#endif
|
||||
|
||||
|
||||
#endif //__CONFIGURATION_ADV_H
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "Dcodes.h"
|
||||
//#include "Marlin.h"
|
||||
#include "Marlin.h"
|
||||
#include "Configuration.h"
|
||||
#include "language.h"
|
||||
#include "cmdqueue.h"
|
||||
@ -226,9 +226,7 @@ void dcode_0()
|
||||
LOG("D0 - Reset\n");
|
||||
if (code_seen('B')) //bootloader
|
||||
{
|
||||
cli();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
else //reset
|
||||
{
|
||||
@ -252,8 +250,7 @@ void dcode_1()
|
||||
cli();
|
||||
for (int i = 0; i < 8192; i++)
|
||||
eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -420,8 +417,7 @@ void dcode_5()
|
||||
boot_dst_addr = (uint32_t)address;
|
||||
boot_src_addr = (uint32_t)(&data);
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
while (count)
|
||||
{
|
||||
@ -467,8 +463,7 @@ void dcode_7()
|
||||
boot_copy_size = (uint16_t)0xc00;
|
||||
boot_src_addr = (uint32_t)0x0003e400;
|
||||
boot_dst_addr = (uint32_t)0x0003f400;
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ extern float feedrate;
|
||||
extern int feedmultiply;
|
||||
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 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 destination[NUM_AXIS] ;
|
||||
extern float min_pos[3];
|
||||
@ -512,4 +512,6 @@ void load_filament_final_feed();
|
||||
void marlin_wait_for_click();
|
||||
void raise_z_above(float target, bool plan=true);
|
||||
|
||||
extern "C" void softReset();
|
||||
|
||||
#endif
|
||||
|
@ -654,6 +654,12 @@ void failstats_reset_print()
|
||||
#endif
|
||||
}
|
||||
|
||||
void softReset()
|
||||
{
|
||||
cli();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MESH_BED_LEVELING
|
||||
@ -768,6 +774,7 @@ static void factory_reset(char level)
|
||||
}
|
||||
|
||||
}
|
||||
softReset();
|
||||
|
||||
|
||||
break;
|
||||
@ -3394,37 +3401,24 @@ void gcode_M701()
|
||||
*/
|
||||
static void gcode_PRUSA_SN()
|
||||
{
|
||||
if (farm_mode) {
|
||||
selectedSerialPort = 0;
|
||||
putchar(';');
|
||||
putchar('S');
|
||||
int numbersRead = 0;
|
||||
ShortTimer timeout;
|
||||
timeout.start();
|
||||
uint8_t selectedSerialPort_bak = selectedSerialPort;
|
||||
char SN[20];
|
||||
selectedSerialPort = 0;
|
||||
SERIAL_ECHOLNRPGM(PSTR(";S"));
|
||||
uint8_t numbersRead = 0;
|
||||
ShortTimer timeout;
|
||||
timeout.start();
|
||||
|
||||
while (numbersRead < 19) {
|
||||
while (MSerial.available() > 0) {
|
||||
uint8_t serial_char = MSerial.read();
|
||||
selectedSerialPort = 1;
|
||||
putchar(serial_char);
|
||||
numbersRead++;
|
||||
selectedSerialPort = 0;
|
||||
}
|
||||
if (timeout.expired(100u)) break;
|
||||
while (numbersRead < (sizeof(SN) - 1)) {
|
||||
if (MSerial.available() > 0) {
|
||||
SN[numbersRead] = MSerial.read();
|
||||
numbersRead++;
|
||||
}
|
||||
selectedSerialPort = 1;
|
||||
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."));
|
||||
if (timeout.expired(100u)) break;
|
||||
}
|
||||
SN[numbersRead] = 0;
|
||||
selectedSerialPort = selectedSerialPort_bak;
|
||||
SERIAL_ECHOLN(SN);
|
||||
}
|
||||
//! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors
|
||||
//! 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))
|
||||
boot_app_magic = BOOT_APP_MAGIC;
|
||||
boot_app_flags = BOOT_APP_FLG_RUN;
|
||||
wdt_enable(WDTO_15MS);
|
||||
cli();
|
||||
while(1);
|
||||
softReset();
|
||||
#else //WATCHDOG
|
||||
asm volatile("jmp 0x3E000");
|
||||
#endif //WATCHDOG
|
||||
@ -4391,6 +4383,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
|
||||
#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>
|
||||
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
|
||||
{
|
||||
if (code_seen('B')) //backup current speed factor
|
||||
{
|
||||
saved_feedmultiply_mm = feedmultiply;
|
||||
}
|
||||
if(code_seen('S'))
|
||||
{
|
||||
feedmultiply = code_value() ;
|
||||
}
|
||||
if (code_seen('R')) { //restore previous feedmultiply
|
||||
feedmultiply = saved_feedmultiply_mm;
|
||||
}
|
||||
bool codesWereSeen = false;
|
||||
if (code_seen('B')) //backup current speed factor
|
||||
{
|
||||
saved_feedmultiply_mm = feedmultiply;
|
||||
codesWereSeen = true;
|
||||
}
|
||||
if (code_seen('S'))
|
||||
{
|
||||
feedmultiply = code_value();
|
||||
codesWereSeen = true;
|
||||
}
|
||||
if (code_seen('R')) //restore previous feedmultiply
|
||||
{
|
||||
feedmultiply = saved_feedmultiply_mm;
|
||||
codesWereSeen = true;
|
||||
}
|
||||
if (!codesWereSeen)
|
||||
{
|
||||
printf_P(PSTR("%i%%\n"), feedmultiply);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -7368,23 +7377,26 @@ Sigma_Exit:
|
||||
*/
|
||||
case 221: // M221 S<factor in percent>- set extrude factor override percentage
|
||||
{
|
||||
if(code_seen('S'))
|
||||
{
|
||||
int tmp_code = code_value();
|
||||
if (code_seen('T'))
|
||||
if (code_seen('S'))
|
||||
{
|
||||
uint8_t extruder;
|
||||
if(setTargetedHotend(221, extruder)){
|
||||
break;
|
||||
}
|
||||
extruder_multiply[extruder] = tmp_code;
|
||||
int tmp_code = code_value();
|
||||
if (code_seen('T'))
|
||||
{
|
||||
uint8_t extruder;
|
||||
if (setTargetedHotend(221, extruder))
|
||||
break;
|
||||
extruder_multiply[extruder] = tmp_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
extrudemultiply = tmp_code ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
extrudemultiply = tmp_code ;
|
||||
printf_P(PSTR("%i%%\n"), extrudemultiply);
|
||||
}
|
||||
}
|
||||
calculate_extruder_multipliers();
|
||||
calculate_extruder_multipliers();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -8612,7 +8624,7 @@ 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>
|
||||
### 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:
|
||||
@ -11758,7 +11770,6 @@ void disable_force_z()
|
||||
#endif // TMC2130
|
||||
}
|
||||
|
||||
|
||||
void enable_force_z()
|
||||
{
|
||||
if(bEnableForce_z)
|
||||
|
@ -9,6 +9,8 @@
|
||||
extern FILE _uartout;
|
||||
#define uartout (&_uartout)
|
||||
|
||||
extern void softReset();
|
||||
|
||||
void bootapp_print_vars(void)
|
||||
{
|
||||
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_dst_addr = (uint32_t)fptr;
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
|
||||
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_reserved = reserved;
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
|
@ -359,6 +359,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
||||
| ^ | ^ | ^ | 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
|
||||
| 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
|
||||
@ -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_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.
|
||||
#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 !!!!!
|
||||
// !!!!!
|
||||
|
@ -58,7 +58,7 @@
|
||||
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
|
||||
|
||||
/// 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
|
||||
|
||||
|
@ -478,22 +478,8 @@ bool fsensor_oq_result(void)
|
||||
}
|
||||
#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 pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
|
||||
if (!pat9125_res)
|
||||
@ -578,8 +564,28 @@ ISR(FSENSOR_INT_PIN_VECT)
|
||||
#endif //DEBUG_FSENSOR_LOG
|
||||
|
||||
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)
|
||||
|
@ -48,6 +48,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
|
||||
{
|
||||
menu_menu = menu;
|
||||
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");
|
||||
if (reset_menu_state)
|
||||
{
|
||||
|
@ -226,11 +226,23 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
|
||||
// Size of Plateau of Nominal Rate.
|
||||
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
|
||||
// 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.
|
||||
if (accel_decel_steps < block->step_event_count.wide) {
|
||||
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 {
|
||||
uint32_t acceleration_x4 = acceleration << 2;
|
||||
// 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;
|
||||
accelerate_steps = block->step_event_count.wide - decelerate_steps;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIN_ADVANCE
|
||||
uint16_t final_adv_steps = 0;
|
||||
if (block->use_advance_lead) {
|
||||
final_adv_steps = exit_speed * block->adv_comp;
|
||||
}
|
||||
if (block->use_advance_lead) {
|
||||
if(!accelerate_steps || !decelerate_steps) {
|
||||
// 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
|
||||
}
|
||||
|
||||
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
|
||||
// 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;
|
||||
#ifdef LIN_ADVANCE
|
||||
block->final_adv_steps = final_adv_steps;
|
||||
block->max_adv_steps = max_adv_steps;
|
||||
#endif
|
||||
}
|
||||
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
|
||||
&& abs(delta_mm[Z_AXIS]) < 0.5;
|
||||
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
|
||||
// extrusion_length to distance ratio (e/D)
|
||||
e_D_ratio = (e - position_float[E_AXIS]) /
|
||||
sqrt(sq(x - position_float[X_AXIS])
|
||||
+ sq(y - position_float[Y_AXIS])
|
||||
+ sq(z - position_float[Z_AXIS]));
|
||||
e_D_ratio = delta_e / delta_D;
|
||||
|
||||
// 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
|
||||
@ -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;
|
||||
#endif
|
||||
|
||||
block->acceleration_rate = (long)((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
|
||||
block->acceleration_rate = ((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
|
||||
|
||||
// Start with a safe speed.
|
||||
// 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.
|
||||
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);
|
||||
|
||||
if (block->step_event_count.wide <= 32767)
|
||||
|
@ -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().
|
||||
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
|
||||
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 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.
|
||||
long 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 accelerate_until; // The index of the step event on which to stop acceleration
|
||||
uint32_t decelerate_after; // The index of the step event on which to start decelerating
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
// 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).
|
||||
// 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 initial_rate; // The jerk-adjusted step rate at start of block
|
||||
unsigned long final_rate; // The minimal rate at exit
|
||||
unsigned long acceleration_st; // acceleration steps/sec^2
|
||||
//FIXME does it have to be unsigned long? Probably uint8_t would be just fine.
|
||||
unsigned long fan_speed;
|
||||
//FIXME does it have to be int? Probably uint8_t would be just fine. Need to change in other places as well
|
||||
int fan_speed;
|
||||
volatile char busy;
|
||||
|
||||
|
||||
|
@ -80,15 +80,21 @@ asm volatile ( \
|
||||
|
||||
#else //_NO_ASM
|
||||
|
||||
// NOTE: currently not implemented
|
||||
void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2);
|
||||
void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2);
|
||||
static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2)
|
||||
{
|
||||
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
|
||||
|
||||
|
||||
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 > 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
|
||||
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
|
||||
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);
|
||||
timer = (unsigned short)pgm_read_word_near(table_address) - timer;
|
||||
}
|
||||
|
@ -71,8 +71,7 @@ static dda_isteps_t
|
||||
counter_z,
|
||||
counter_e;
|
||||
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 unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
|
||||
static uint32_t acceleration_time, deceleration_time;
|
||||
static uint16_t acc_step_rate; // needed for deccelaration start point
|
||||
static uint8_t step_loops;
|
||||
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 eISR_Rate;
|
||||
static uint16_t eISR_Err;
|
||||
static uint32_t eISR_Err;
|
||||
|
||||
static uint16_t current_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
|
||||
// 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.
|
||||
// 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.
|
||||
// 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
|
||||
if (current_block->use_advance_lead) {
|
||||
e_step_loops = current_block->advance_step_loops;
|
||||
target_adv_steps = current_block->max_adv_steps;
|
||||
} else {
|
||||
e_step_loops = 1;
|
||||
}
|
||||
e_steps = 0;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
nextAdvanceISR = timer;
|
||||
return;
|
||||
}
|
||||
|
||||
// at least one step
|
||||
uint8_t 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);
|
||||
if (ticks <= 3)
|
||||
eISR_Rate = fastdiv(timer, ticks + 1);
|
||||
else
|
||||
{
|
||||
// >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
|
||||
|
||||
@ -799,7 +787,7 @@ FORCE_INLINE void isr() {
|
||||
// 25.12us for acceleration / deceleration.
|
||||
{
|
||||
//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
|
||||
MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
|
||||
acc_step_rate += uint16_t(current_block->initial_rate);
|
||||
@ -812,19 +800,29 @@ FORCE_INLINE void isr() {
|
||||
acceleration_time += timer;
|
||||
#ifdef LIN_ADVANCE
|
||||
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;
|
||||
if (e_extruding && current_adv_steps > target_adv_steps)
|
||||
target_adv_steps = current_adv_steps;
|
||||
}
|
||||
}
|
||||
#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;
|
||||
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)) {
|
||||
// Result is negative or too small.
|
||||
step_rate = uint16_t(current_block->final_rate);
|
||||
|
||||
if (step_rate > acc_step_rate) { // Check step_rate stays positive
|
||||
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.
|
||||
uint16_t timer = calc_timer(step_rate, step_loops);
|
||||
_NEXT_ISR(timer);
|
||||
@ -832,9 +830,11 @@ FORCE_INLINE void isr() {
|
||||
|
||||
#ifdef LIN_ADVANCE
|
||||
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;
|
||||
la_state = ADV_INIT | ADV_ACC_VARY;
|
||||
if (e_extruding && current_adv_steps < target_adv_steps)
|
||||
target_adv_steps = current_adv_steps;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -848,12 +848,12 @@ FORCE_INLINE void isr() {
|
||||
|
||||
#ifdef LIN_ADVANCE
|
||||
if(current_block->use_advance_lead) {
|
||||
if (!nextAdvanceISR) {
|
||||
// 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.
|
||||
// If LA was not previously active, re-check the pressure level
|
||||
la_state = ADV_INIT;
|
||||
}
|
||||
// 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.
|
||||
// If LA was not previously active, re-check the pressure level
|
||||
la_state = ADV_INIT;
|
||||
if (e_extruding)
|
||||
target_adv_steps = current_adv_steps;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -865,14 +865,21 @@ FORCE_INLINE void isr() {
|
||||
#ifdef LIN_ADVANCE
|
||||
// avoid multiple instances or function calls to advance_spread
|
||||
if (la_state & ADV_INIT) {
|
||||
LA_phase = -1;
|
||||
|
||||
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;
|
||||
nextAdvanceISR = ADV_NEVER;
|
||||
}
|
||||
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)) {
|
||||
// LA could reverse the direction of extrusion in this phase
|
||||
eISR_Err += current_block->advance_rate;
|
||||
LA_phase = 0;
|
||||
}
|
||||
}
|
||||
@ -882,11 +889,13 @@ FORCE_INLINE void isr() {
|
||||
advance_spread(main_Rate);
|
||||
if (LA_phase >= 0) {
|
||||
if (step_loops == e_step_loops)
|
||||
LA_phase = (eISR_Rate > main_Rate);
|
||||
LA_phase = (current_block->advance_rate < main_Rate);
|
||||
else {
|
||||
// avoid overflow through division. warning: we need to _guarantee_ step_loops
|
||||
// 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() {
|
||||
if (current_adv_steps > target_adv_steps) {
|
||||
// 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;
|
||||
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;
|
||||
else
|
||||
current_adv_steps = 0;
|
||||
nextAdvanceISR = eISR_Rate;
|
||||
current_adv_steps -= e_step_loops;
|
||||
}
|
||||
else if (current_adv_steps < target_adv_steps) {
|
||||
// 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;
|
||||
if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR);
|
||||
current_adv_steps += e_step_loops;
|
||||
nextAdvanceISR = eISR_Rate;
|
||||
}
|
||||
else {
|
||||
|
||||
if (current_adv_steps == target_adv_steps) {
|
||||
// advance steps completed
|
||||
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
|
||||
// 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;
|
||||
else
|
||||
OCR1A = nextMainISR;
|
||||
|
@ -152,7 +152,11 @@ uint8_t fanSpeedBckp = 255;
|
||||
bool fan_measuring = false;
|
||||
uint8_t fanState = 0;
|
||||
#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
|
||||
|
||||
@ -180,6 +184,12 @@ static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP;
|
||||
#ifdef BED_MAXTEMP
|
||||
static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
|
||||
#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 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);
|
||||
|
||||
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);
|
||||
@ -237,10 +256,22 @@ bool extruder_altfan_detect()
|
||||
EIMSK &= ~(1 << INT6);
|
||||
|
||||
countFanSpeed();
|
||||
extruderFanIsAltfan = fan_speed[0] > 100;
|
||||
altfanStatus.isAltfan = fan_speed[0] > 100;
|
||||
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
|
||||
|
||||
// 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)
|
||||
{
|
||||
#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 //EXTRUDER_ALTFAN_DETECT
|
||||
newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
|
||||
@ -639,6 +670,7 @@ void manage_heater()
|
||||
return;
|
||||
// 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();
|
||||
|
||||
check_max_temp();
|
||||
@ -1165,7 +1197,6 @@ void tp_init()
|
||||
#endif //MAXTEMP 2
|
||||
|
||||
#ifdef BED_MINTEMP
|
||||
/* No bed MINTEMP error implemented?!? */
|
||||
while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) {
|
||||
#if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
|
||||
bed_minttemp_raw += OVERSAMPLENR;
|
||||
@ -1173,7 +1204,6 @@ void tp_init()
|
||||
bed_minttemp_raw -= OVERSAMPLENR;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //BED_MINTEMP
|
||||
#ifdef BED_MAXTEMP
|
||||
while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) {
|
||||
@ -1184,6 +1214,25 @@ void tp_init()
|
||||
#endif
|
||||
}
|
||||
#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)
|
||||
@ -1356,7 +1405,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
|
||||
SERIAL_ERROR_START;
|
||||
isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)");
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
extruderFanIsAltfan = false; //full speed
|
||||
altfanStatus.altfanOverride = 1; //full speed
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
setExtruderAutoFanState(3);
|
||||
SET_OUTPUT(FAN_PIN);
|
||||
@ -1427,26 +1476,53 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_
|
||||
//! to prevent flicker and improve speed
|
||||
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) {
|
||||
disable_heater();
|
||||
if(IsStopped() == false) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLN((int)e);
|
||||
SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !");
|
||||
LCD_ALERTMESSAGEPGM("Err: MAXTEMP");
|
||||
temp_error_messagepgm(PSTR("MAXTEMP"), e);
|
||||
}
|
||||
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
|
||||
Stop();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
SET_OUTPUT(FAN_PIN);
|
||||
SET_OUTPUT(BEEPER);
|
||||
WRITE(FAN_PIN, 1);
|
||||
WRITE(BEEPER, 1);
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
extruderFanIsAltfan = false; //full speed
|
||||
altfanStatus.altfanOverride = 1; //full speed
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
setExtruderAutoFanState(3);
|
||||
// fanSpeed will consumed by the check_axes_activity() routine.
|
||||
@ -1458,18 +1534,15 @@ void min_temp_error(uint8_t e) {
|
||||
#ifdef DEBUG_DISABLE_MINTEMP
|
||||
return;
|
||||
#endif
|
||||
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
|
||||
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) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLN((int)e);
|
||||
SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !");
|
||||
lcd_setalertstatuspgm(err);
|
||||
temp_error_messagepgm(err, e);
|
||||
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)
|
||||
// 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;
|
||||
}
|
||||
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
|
||||
@ -1484,37 +1557,27 @@ void min_temp_error(uint8_t e) {
|
||||
}
|
||||
|
||||
void bed_max_temp_error(void) {
|
||||
#if HEATER_BED_PIN > -1
|
||||
//WRITE(HEATER_BED_PIN, 0);
|
||||
#endif
|
||||
disable_heater();
|
||||
if(IsStopped() == false) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !");
|
||||
LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED");
|
||||
temp_error_messagepgm(PSTR("MAXTEMP BED"));
|
||||
}
|
||||
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
|
||||
Stop();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void bed_min_temp_error(void) {
|
||||
#ifdef DEBUG_DISABLE_MINTEMP
|
||||
return;
|
||||
#endif
|
||||
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
|
||||
#if HEATER_BED_PIN > -1
|
||||
//WRITE(HEATER_BED_PIN, 0);
|
||||
#endif
|
||||
static const char err[] PROGMEM = "Err: MINTEMP BED";
|
||||
disable_heater();
|
||||
static const char err[] PROGMEM = "MINTEMP BED";
|
||||
if(IsStopped() == false) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !");
|
||||
lcd_setalertstatuspgm(err);
|
||||
temp_error_messagepgm(err);
|
||||
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)
|
||||
// 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;
|
||||
}
|
||||
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
|
||||
@ -1522,6 +1585,33 @@ void bed_min_temp_error(void) {
|
||||
#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
|
||||
#define MAX6675_HEAT_INTERVAL 250
|
||||
long max6675_previous_millis = MAX6675_HEAT_INTERVAL;
|
||||
@ -1606,18 +1696,8 @@ void adc_ready(void) //callback from adc when sampling finished
|
||||
|
||||
} // extern "C"
|
||||
|
||||
// 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
|
||||
FORCE_INLINE static void temperature_isr()
|
||||
{
|
||||
static bool _lock = false;
|
||||
if (_lock) return;
|
||||
_lock = true;
|
||||
asm("sei");
|
||||
|
||||
if (!temp_meas_ready) adc_cycle();
|
||||
lcd_buttons_update();
|
||||
|
||||
@ -1983,8 +2063,24 @@ ISR(TIMER0_COMPB_vect)
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
check_fans();
|
||||
#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()
|
||||
@ -2004,11 +2100,19 @@ void check_max_temp()
|
||||
#else
|
||||
if (current_temperature_bed_raw >= bed_maxttemp_raw) {
|
||||
#endif
|
||||
target_temperature_bed = 0;
|
||||
bed_max_temp_error();
|
||||
}
|
||||
#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
|
||||
//! 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()
|
||||
{
|
||||
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)
|
||||
#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
|
||||
#endif //AMBIENT_THERMISTOR
|
||||
// *** 'common' part of code for MK2.5 & MK3
|
||||
|
@ -273,6 +273,8 @@ 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;
|
||||
|
@ -1213,6 +1213,8 @@ const short temptable_1047[][2] PROGMEM = {
|
||||
#endif
|
||||
|
||||
#if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1
|
||||
# define AMBIENT_RAW_HI_TEMP 0
|
||||
# define AMBIENT_RAW_LO_TEMP 16383
|
||||
const short temptable_2000[][2] PROGMEM = {
|
||||
// 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
|
||||
|
@ -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)
|
||||
lcd_status_update_delay--;
|
||||
else
|
||||
@ -1077,36 +1107,6 @@ void lcd_status_screen() // NOT static due to using ins
|
||||
menu_submenu(lcd_main_menu);
|
||||
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()
|
||||
@ -2126,6 +2126,7 @@ static void lcd_support_menu()
|
||||
sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"),
|
||||
_md->ip[0], _md->ip[1],
|
||||
_md->ip[2], _md->ip[3]);
|
||||
|
||||
} else if (_md->is_flash_air &&
|
||||
_md->ip[0] == 0 && _md->ip[1] == 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
|
||||
#endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
|
||||
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1
|
||||
#endif /* DEBUG_BUILD */
|
||||
@ -5712,6 +5714,25 @@ static void sheets_menu()
|
||||
|
||||
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_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
|
||||
if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
|
||||
#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();
|
||||
}
|
||||
|
||||
@ -8951,13 +8978,14 @@ void lcd_finishstatus() {
|
||||
lcd_draw_update = 2;
|
||||
|
||||
}
|
||||
|
||||
void lcd_setstatus(const char* message)
|
||||
{
|
||||
if (lcd_status_message_level > 0)
|
||||
return;
|
||||
strncpy(lcd_status_message, message, LCD_WIDTH);
|
||||
lcd_finishstatus();
|
||||
lcd_updatestatus(message);
|
||||
}
|
||||
|
||||
void lcd_updatestatuspgm(const char *message){
|
||||
strncpy_P(lcd_status_message, message, LCD_WIDTH);
|
||||
lcd_status_message[LCD_WIDTH] = 0;
|
||||
@ -8972,12 +9000,29 @@ void lcd_setstatuspgm(const char* message)
|
||||
return;
|
||||
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)
|
||||
{
|
||||
lcd_setstatuspgm(message);
|
||||
lcd_status_message_level = 1;
|
||||
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()
|
||||
{
|
||||
lcd_status_message_level = 0;
|
||||
@ -8997,6 +9042,13 @@ void menu_lcd_longpress_func(void)
|
||||
lcd_quick_feedback();
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
#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();
|
||||
}
|
||||
|
@ -23,9 +23,11 @@ void lcd_setstatuspgm(const char* message);
|
||||
//! - always returns the display to the main status screen
|
||||
//! - 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)
|
||||
void lcd_setalertstatus(const char* message);
|
||||
void lcd_setalertstatuspgm(const char* message);
|
||||
//! 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();
|
||||
@ -257,4 +259,7 @@ enum class WizState : uint8_t
|
||||
|
||||
void lcd_wizard(WizState state);
|
||||
|
||||
extern void lcd_experimental_toggle();
|
||||
extern void lcd_experimental_menu();
|
||||
|
||||
#endif //ULTRALCD_H
|
||||
|
@ -296,6 +296,7 @@
|
||||
#endif
|
||||
#define DETECT_SUPERPINDA
|
||||
#define PINDA_MINTEMP BED_MINTEMP
|
||||
#define AMBIENT_MINTEMP -30
|
||||
|
||||
// Maxtemps
|
||||
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
|
||||
@ -306,6 +307,7 @@
|
||||
#define HEATER_1_MAXTEMP 305
|
||||
#define HEATER_2_MAXTEMP 305
|
||||
#define BED_MAXTEMP 125
|
||||
#define AMBIENT_MAXTEMP 100
|
||||
|
||||
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
|
||||
// Define PID constants for extruder with PT100
|
||||
|
@ -298,6 +298,7 @@
|
||||
#endif
|
||||
#define DETECT_SUPERPINDA
|
||||
#define PINDA_MINTEMP BED_MINTEMP
|
||||
#define AMBIENT_MINTEMP -30
|
||||
|
||||
// Maxtemps
|
||||
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
|
||||
@ -308,6 +309,7 @@
|
||||
#define HEATER_1_MAXTEMP 305
|
||||
#define HEATER_2_MAXTEMP 305
|
||||
#define BED_MAXTEMP 125
|
||||
#define AMBIENT_MAXTEMP 100
|
||||
|
||||
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
|
||||
// Define PID constants for extruder with PT100
|
||||
|
22
README.md
22
README.md
@ -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.
|
||||
|
||||
2. Set your printer model.
|
||||
1. Set your printer model.
|
||||
- For MK3 --> skip to step 3.
|
||||
- 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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@ -182,7 +196,7 @@ Example:
|
||||
|
||||
`ninja`
|
||||
|
||||
## Runing
|
||||
## Running
|
||||
`./tests`
|
||||
|
||||
# 4. Documentation
|
||||
|
Loading…
Reference in New Issue
Block a user