Split LIN_ADVANCE from TMC2103 support
Check: https://github.com/prusa3d/Prusa-Firmware/pull/93 and https://github.com/madhunm/Prusa-Firmware/tree/MK2/Firmware
This commit is contained in:
parent
202f2351f9
commit
9c201c4dd6
|
|
@ -5,7 +5,7 @@
|
||||||
#include "Configuration_prusa.h"
|
#include "Configuration_prusa.h"
|
||||||
|
|
||||||
// Firmware version
|
// Firmware version
|
||||||
#define FW_version "3.0.11"
|
#define FW_version "3.0.11-L01"
|
||||||
|
|
||||||
#define FW_PRUSA3D_MAGIC "PRUSA3DFW"
|
#define FW_PRUSA3D_MAGIC "PRUSA3DFW"
|
||||||
#define FW_PRUSA3D_MAGIC_LEN 10
|
#define FW_PRUSA3D_MAGIC_LEN 10
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,19 @@ void Config_StoreSettings()
|
||||||
EEPROM_WRITE_VAR(i, filament_size[2]);
|
EEPROM_WRITE_VAR(i, filament_size[2]);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
//
|
||||||
|
// Linear Advance
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
EEPROM_WRITE_VAR(i, extruder_advance_k);
|
||||||
|
EEPROM_WRITE_VAR(i, advance_ed_ratio);
|
||||||
|
#else
|
||||||
|
dummy = 0.0f;
|
||||||
|
EEPROM_WRITE_VAR(i, dummy);
|
||||||
|
EEPROM_WRITE_VAR(i, dummy);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*MYSERIAL.print("Top address used:\n");
|
/*MYSERIAL.print("Top address used:\n");
|
||||||
MYSERIAL.print(i);
|
MYSERIAL.print(i);
|
||||||
MYSERIAL.print("\n");
|
MYSERIAL.print("\n");
|
||||||
|
|
@ -259,6 +272,14 @@ void Config_PrintSettings()
|
||||||
SERIAL_ECHOLNPGM("Filament settings: Disabled");
|
SERIAL_ECHOLNPGM("Filament settings: Disabled");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
SERIAL_ECHO_START;
|
||||||
|
SERIAL_ECHOLNPGM("Linear Advance:");
|
||||||
|
SERIAL_ECHOPAIR(" M900 K", extruder_advance_k);
|
||||||
|
SERIAL_ECHOPAIR(" R", advance_ed_ratio);
|
||||||
|
SERIAL_ECHO('\n');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -349,6 +370,18 @@ void Config_RetrieveSettings()
|
||||||
#endif
|
#endif
|
||||||
calculate_volumetric_multipliers();
|
calculate_volumetric_multipliers();
|
||||||
// Call updatePID (similar to when we have processed M301)
|
// Call updatePID (similar to when we have processed M301)
|
||||||
|
//
|
||||||
|
// Linear Advance
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
EEPROM_READ_VAR(i, extruder_advance_k);
|
||||||
|
EEPROM_READ_VAR(i, advance_ed_ratio);
|
||||||
|
#else
|
||||||
|
EEPROM_READ_VAR(i, dummy);
|
||||||
|
EEPROM_READ_VAR(i, dummy);
|
||||||
|
#endif
|
||||||
|
|
||||||
updatePID();
|
updatePID();
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
||||||
|
|
@ -433,6 +466,11 @@ void Config_ResetDefault()
|
||||||
#endif
|
#endif
|
||||||
calculate_volumetric_multipliers();
|
calculate_volumetric_multipliers();
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
extruder_advance_k = LIN_ADVANCE_K;
|
||||||
|
advance_ed_ratio = LIN_ADVANCE_E_D_RATIO;
|
||||||
|
#endif
|
||||||
|
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,10 @@
|
||||||
|
|
||||||
#define VERSION_STRING "1.0.2"
|
#define VERSION_STRING "1.0.2"
|
||||||
|
|
||||||
|
#ifdef AUTOMATIC_CURRENT_CONTROL
|
||||||
|
bool auto_current_control = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "ultralcd.h"
|
#include "ultralcd.h"
|
||||||
|
|
||||||
|
|
@ -208,6 +212,7 @@
|
||||||
// M928 - Start SD logging (M928 filename.g) - ended by M29
|
// M928 - Start SD logging (M928 filename.g) - ended by M29
|
||||||
// M999 - Restart after being stopped by error
|
// M999 - Restart after being stopped by error
|
||||||
|
|
||||||
|
// M900 - Set and/or Get advance K factor and WH/D ratio (Requires LIN_ADVANCE)
|
||||||
//Stepper Movement Variables
|
//Stepper Movement Variables
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
@ -1598,6 +1603,22 @@ void get_command()
|
||||||
#endif //SDSUPPORT
|
#endif //SDSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WITHIN(V,L,H) ((V) >= (L) && (V) <= (H))
|
||||||
|
#define NUMERIC(a) WITHIN(a, '0', '9')
|
||||||
|
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-')
|
||||||
|
|
||||||
|
static char *current_command, // The command currently being executed
|
||||||
|
*current_command_args, // The address where arguments begin
|
||||||
|
*seen_pointer; // Set by code_seen(), used by the code_value functions
|
||||||
|
|
||||||
|
inline bool code_has_value() {
|
||||||
|
int i = 1;
|
||||||
|
char c = seen_pointer[i];
|
||||||
|
while (c == ' ') c = seen_pointer[++i];
|
||||||
|
if (c == '-' || c == '+') c = seen_pointer[++i];
|
||||||
|
if (c == '.') c = seen_pointer[++i];
|
||||||
|
return NUMERIC(c);
|
||||||
|
}
|
||||||
|
|
||||||
// Return True if a character was found
|
// Return True if a character was found
|
||||||
static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
||||||
|
|
@ -1606,6 +1627,7 @@ static inline float code_value() { return strtod(strchr_pointer+1, NULL);
|
||||||
static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
|
static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
|
||||||
static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
|
static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
|
||||||
static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); };
|
static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); };
|
||||||
|
static inline bool code_value_bool() { return !code_has_value() || code_value_uint8() > 0; }
|
||||||
|
|
||||||
#define DEFINE_PGM_READ_ANY(type, reader) \
|
#define DEFINE_PGM_READ_ANY(type, reader) \
|
||||||
static inline type pgm_read_any(const type *p) \
|
static inline type pgm_read_any(const type *p) \
|
||||||
|
|
@ -5336,6 +5358,33 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 900: {
|
||||||
|
|
||||||
|
st_synchronize();
|
||||||
|
|
||||||
|
const float newK = code_seen('K') ? code_value() : -1;
|
||||||
|
if (newK >= 0) extruder_advance_k = newK;
|
||||||
|
|
||||||
|
float newR = code_seen('R') ? code_value() : -1;
|
||||||
|
if (newR < 0) {
|
||||||
|
const float newD = code_seen('D') ? code_value() : -1,
|
||||||
|
newW = code_seen('W') ? code_value() : -1,
|
||||||
|
newH = code_seen('H') ? code_value() : -1;
|
||||||
|
if (newD >= 0 && newW >= 0 && newH >= 0)
|
||||||
|
newR = newD ? (newW * newH) / (sq(newD * 0.5) * M_PI) : 0;
|
||||||
|
}
|
||||||
|
if (newR >= 0) advance_ed_ratio = newR;
|
||||||
|
|
||||||
|
SERIAL_ECHO_START;
|
||||||
|
SERIAL_ECHOPAIR("Advance K=", extruder_advance_k);
|
||||||
|
SERIAL_ECHOPGM(" E/D=");
|
||||||
|
const float ratio = advance_ed_ratio;
|
||||||
|
if (ratio) SERIAL_ECHO(ratio); else SERIAL_ECHOPGM("Auto");
|
||||||
|
SERIAL_ECHO('\n');
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 907: // M907 Set digital trimpot motor current using axis codes.
|
case 907: // M907 Set digital trimpot motor current using axis codes.
|
||||||
{
|
{
|
||||||
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
|
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,11 @@ const char * const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM] PROGMEM = {
|
||||||
MSG_ADJUSTZ_NL
|
MSG_ADJUSTZ_NL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char MSG_ADVANCE_K_EN[] PROGMEM = "Advance K";
|
||||||
|
const char * const MSG_ADVANCE_K_LANG_TABLE[1] PROGMEM = {
|
||||||
|
MSG_ADVANCE_K_EN
|
||||||
|
};
|
||||||
|
|
||||||
const char MSG_AMAX_EN[] PROGMEM = "Amax ";
|
const char MSG_AMAX_EN[] PROGMEM = "Amax ";
|
||||||
const char * const MSG_AMAX_LANG_TABLE[1] PROGMEM = {
|
const char * const MSG_AMAX_LANG_TABLE[1] PROGMEM = {
|
||||||
MSG_AMAX_EN
|
MSG_AMAX_EN
|
||||||
|
|
@ -918,6 +923,11 @@ const char * const MSG_E_CAL_KNOB_LANG_TABLE[LANG_NUM] PROGMEM = {
|
||||||
MSG_E_CAL_KNOB_NL
|
MSG_E_CAL_KNOB_NL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char MSG_E_D_RATIO_EN[] PROGMEM = "E-D Ratio";
|
||||||
|
const char * const MSG_E_D_RATIO_LANG_TABLE[1] PROGMEM = {
|
||||||
|
MSG_E_D_RATIO_EN
|
||||||
|
};
|
||||||
|
|
||||||
const char MSG_Enqueing_EN[] PROGMEM = "enqueing \"";
|
const char MSG_Enqueing_EN[] PROGMEM = "enqueing \"";
|
||||||
const char * const MSG_Enqueing_LANG_TABLE[1] PROGMEM = {
|
const char * const MSG_Enqueing_LANG_TABLE[1] PROGMEM = {
|
||||||
MSG_Enqueing_EN
|
MSG_Enqueing_EN
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ extern const char* const MSG_ACTIVE_EXTRUDER_LANG_TABLE[1];
|
||||||
#define MSG_ACTIVE_EXTRUDER LANG_TABLE_SELECT_EXPLICIT(MSG_ACTIVE_EXTRUDER_LANG_TABLE, 0)
|
#define MSG_ACTIVE_EXTRUDER LANG_TABLE_SELECT_EXPLICIT(MSG_ACTIVE_EXTRUDER_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM];
|
extern const char* const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM];
|
||||||
#define MSG_ADJUSTZ LANG_TABLE_SELECT(MSG_ADJUSTZ_LANG_TABLE)
|
#define MSG_ADJUSTZ LANG_TABLE_SELECT(MSG_ADJUSTZ_LANG_TABLE)
|
||||||
|
extern const char* const MSG_ADVANCE_K_LANG_TABLE[1];
|
||||||
|
#define MSG_ADVANCE_K LANG_TABLE_SELECT_EXPLICIT(MSG_ADVANCE_K_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_AMAX_LANG_TABLE[1];
|
extern const char* const MSG_AMAX_LANG_TABLE[1];
|
||||||
#define MSG_AMAX LANG_TABLE_SELECT_EXPLICIT(MSG_AMAX_LANG_TABLE, 0)
|
#define MSG_AMAX LANG_TABLE_SELECT_EXPLICIT(MSG_AMAX_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_AUTHOR_LANG_TABLE[1];
|
extern const char* const MSG_AUTHOR_LANG_TABLE[1];
|
||||||
|
|
@ -176,6 +178,8 @@ extern const char* const MSG_EXTERNAL_RESET_LANG_TABLE[1];
|
||||||
#define MSG_EXTERNAL_RESET LANG_TABLE_SELECT_EXPLICIT(MSG_EXTERNAL_RESET_LANG_TABLE, 0)
|
#define MSG_EXTERNAL_RESET LANG_TABLE_SELECT_EXPLICIT(MSG_EXTERNAL_RESET_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_E_CAL_KNOB_LANG_TABLE[LANG_NUM];
|
extern const char* const MSG_E_CAL_KNOB_LANG_TABLE[LANG_NUM];
|
||||||
#define MSG_E_CAL_KNOB LANG_TABLE_SELECT(MSG_E_CAL_KNOB_LANG_TABLE)
|
#define MSG_E_CAL_KNOB LANG_TABLE_SELECT(MSG_E_CAL_KNOB_LANG_TABLE)
|
||||||
|
extern const char* const MSG_E_D_RATIO_LANG_TABLE[1];
|
||||||
|
#define MSG_E_D_RATIO LANG_TABLE_SELECT_EXPLICIT(MSG_E_D_RATIO_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_Enqueing_LANG_TABLE[1];
|
extern const char* const MSG_Enqueing_LANG_TABLE[1];
|
||||||
#define MSG_Enqueing LANG_TABLE_SELECT_EXPLICIT(MSG_Enqueing_LANG_TABLE, 0)
|
#define MSG_Enqueing LANG_TABLE_SELECT_EXPLICIT(MSG_Enqueing_LANG_TABLE, 0)
|
||||||
extern const char* const MSG_FACTOR_LANG_TABLE[1];
|
extern const char* const MSG_FACTOR_LANG_TABLE[1];
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,11 @@
|
||||||
#define MSG_REFRESH "\xF8" "Refresh"
|
#define MSG_REFRESH "\xF8" "Refresh"
|
||||||
#define MSG_WATCH "Info screen"
|
#define MSG_WATCH "Info screen"
|
||||||
#define MSG_TUNE "Tune"
|
#define MSG_TUNE "Tune"
|
||||||
|
|
||||||
|
//Linear Advance option
|
||||||
|
#define MSG_ADVANCE_K "Advance K"
|
||||||
|
#define MSG_E_D_RATIO "E-D Ratio"
|
||||||
|
|
||||||
#define MSG_PAUSE_PRINT "Pause print"
|
#define MSG_PAUSE_PRINT "Pause print"
|
||||||
#define MSG_RESUME_PRINT "Resume print"
|
#define MSG_RESUME_PRINT "Resume print"
|
||||||
#define MSG_STOP_PRINT "Stop print"
|
#define MSG_STOP_PRINT "Stop print"
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,22 @@
|
||||||
#include "temperature.h"
|
#include "temperature.h"
|
||||||
#include "ultralcd.h"
|
#include "ultralcd.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
|
#include "Configuration_prusa.h"
|
||||||
|
|
||||||
#ifdef MESH_BED_LEVELING
|
#ifdef MESH_BED_LEVELING
|
||||||
#include "mesh_bed_leveling.h"
|
#include "mesh_bed_leveling.h"
|
||||||
#include "mesh_bed_calibration.h"
|
#include "mesh_bed_calibration.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define UNEAR_ZERO(x) ((x) < 0.000001)
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
float extruder_advance_k = LIN_ADVANCE_K,
|
||||||
|
advance_ed_ratio = LIN_ADVANCE_E_D_RATIO,
|
||||||
|
position_float[NUM_AXIS] = { 0 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//=============================public variables ============================
|
//=============================public variables ============================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
@ -411,6 +421,11 @@ void plan_init() {
|
||||||
block_buffer_head = 0;
|
block_buffer_head = 0;
|
||||||
block_buffer_tail = 0;
|
block_buffer_tail = 0;
|
||||||
memset(position, 0, sizeof(position)); // clear position
|
memset(position, 0, sizeof(position)); // clear position
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
memset(position_float, 0, sizeof(position_float));
|
||||||
|
#endif
|
||||||
|
|
||||||
previous_speed[0] = 0.0;
|
previous_speed[0] = 0.0;
|
||||||
previous_speed[1] = 0.0;
|
previous_speed[1] = 0.0;
|
||||||
previous_speed[2] = 0.0;
|
previous_speed[2] = 0.0;
|
||||||
|
|
@ -675,13 +690,32 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
|
||||||
#else
|
#else
|
||||||
target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
|
target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
|
||||||
#endif // ENABLE_MESH_BED_LEVELING
|
#endif // ENABLE_MESH_BED_LEVELING
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
const float mm_D_float = sqrt(sq(target[X_AXIS] - position_float[X_AXIS]) + sq(target[Y_AXIS] - position_float[Y_AXIS]));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long de = target[E_AXIS] - position[E_AXIS];
|
||||||
|
|
||||||
target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
float de_float = target[E_AXIS] - position_float[E_AXIS];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PREVENT_DANGEROUS_EXTRUDE
|
#ifdef PREVENT_DANGEROUS_EXTRUDE
|
||||||
if(target[E_AXIS]!=position[E_AXIS])
|
if(target[E_AXIS]!=position[E_AXIS])
|
||||||
{
|
{
|
||||||
if(degHotend(active_extruder)<extrude_min_temp)
|
if(degHotend(active_extruder)<extrude_min_temp)
|
||||||
{
|
{
|
||||||
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
|
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
|
||||||
|
|
||||||
|
de = 0; // no difference
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
position_float[E_AXIS] = e;
|
||||||
|
de_float = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNRPGM(MSG_ERR_COLD_EXTRUDE_STOP);
|
SERIAL_ECHOLNRPGM(MSG_ERR_COLD_EXTRUDE_STOP);
|
||||||
}
|
}
|
||||||
|
|
@ -690,6 +724,12 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
|
||||||
if(labs(target[E_AXIS]-position[E_AXIS])>axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH)
|
if(labs(target[E_AXIS]-position[E_AXIS])>axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH)
|
||||||
{
|
{
|
||||||
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
|
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
position_float[E_AXIS] = e;
|
||||||
|
de_float = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNRPGM(MSG_ERR_LONG_EXTRUDE_STOP);
|
SERIAL_ECHOLNRPGM(MSG_ERR_LONG_EXTRUDE_STOP);
|
||||||
}
|
}
|
||||||
|
|
@ -1112,6 +1152,41 @@ Having the real displacement of the head, we can calculate the total movement le
|
||||||
previous_nominal_speed = block->nominal_speed;
|
previous_nominal_speed = block->nominal_speed;
|
||||||
previous_safe_speed = safe_speed;
|
previous_safe_speed = safe_speed;
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use LIN_ADVANCE for blocks if all these are true:
|
||||||
|
//
|
||||||
|
// esteps : We have E steps todo (a printing move)
|
||||||
|
//
|
||||||
|
// block->steps[X_AXIS] || block->steps[Y_AXIS] : We have a movement in XY direction (i.e., not retract / prime).
|
||||||
|
//
|
||||||
|
// extruder_advance_k : There is an advance factor set.
|
||||||
|
//
|
||||||
|
// block->steps[E_AXIS] != block->step_event_count : A problem occurs if the move before a retract is too small.
|
||||||
|
// In that case, the retract and move will be executed together.
|
||||||
|
// This leads to too many advance steps due to a huge e_acceleration.
|
||||||
|
// The math is good, but we must avoid retract moves with advance!
|
||||||
|
// de_float > 0.0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
|
||||||
|
//
|
||||||
|
|
||||||
|
float tmp1[] = DEFAULT_AXIS_STEPS_PER_UNIT;
|
||||||
|
|
||||||
|
|
||||||
|
block->use_advance_lead = delta_mm[E_AXIS]
|
||||||
|
&& (block->steps_x || block->steps_y)
|
||||||
|
&& extruder_advance_k
|
||||||
|
&& (uint32_t)delta_mm[E_AXIS] != block->step_event_count
|
||||||
|
&& de_float > 0.0;
|
||||||
|
if (block->use_advance_lead)
|
||||||
|
block->abs_adv_steps_multiplier8 = lround(
|
||||||
|
extruder_advance_k
|
||||||
|
* (UNEAR_ZERO(advance_ed_ratio) ? de_float / mm_D_float : advance_ed_ratio) // Use the fixed ratio, if set
|
||||||
|
* (block->nominal_speed / (float)block->nominal_rate)
|
||||||
|
* tmp1[E_AXIS] * 256.0
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
// 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;
|
||||||
calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
|
calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
|
||||||
|
|
@ -1122,6 +1197,13 @@ Having the real displacement of the head, we can calculate the total movement le
|
||||||
// Update position
|
// Update position
|
||||||
memcpy(position, target, sizeof(target)); // position[] = target[]
|
memcpy(position, target, sizeof(target)); // position[] = target[]
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
position_float[X_AXIS] = target[X_AXIS];
|
||||||
|
position_float[Y_AXIS] = target[Y_AXIS];
|
||||||
|
position_float[Z_AXIS] = target[Z_AXIS];
|
||||||
|
position_float[E_AXIS] = target[E_AXIS];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Recalculate the trapezoids to maximize speed at the segment transitions while respecting
|
// Recalculate the trapezoids to maximize speed at the segment transitions while respecting
|
||||||
// the machine limits (maximum acceleration and maximum jerk).
|
// the machine limits (maximum acceleration and maximum jerk).
|
||||||
// This runs asynchronously with the stepper interrupt controller, which may
|
// This runs asynchronously with the stepper interrupt controller, which may
|
||||||
|
|
@ -1179,7 +1261,15 @@ void plan_set_position(float x, float y, float z, const float &e)
|
||||||
position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
|
position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
|
||||||
#endif // ENABLE_MESH_BED_LEVELING
|
#endif // ENABLE_MESH_BED_LEVELING
|
||||||
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
||||||
st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]);
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
position_float[X_AXIS] = position[X_AXIS];
|
||||||
|
position_float[Y_AXIS] = position[Y_AXIS];
|
||||||
|
position_float[Z_AXIS] = position[Z_AXIS];
|
||||||
|
position_float[E_AXIS] = position[E_AXIS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
st_set_position(position_float[X_AXIS], position_float[Y_AXIS], position_float[Z_AXIS], position_float[E_AXIS]);
|
||||||
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
|
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
|
||||||
previous_speed[0] = 0.0;
|
previous_speed[0] = 0.0;
|
||||||
previous_speed[1] = 0.0;
|
previous_speed[1] = 0.0;
|
||||||
|
|
@ -1197,7 +1287,12 @@ void plan_set_z_position(const float &z)
|
||||||
void plan_set_e_position(const float &e)
|
void plan_set_e_position(const float &e)
|
||||||
{
|
{
|
||||||
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
position_float[E_AXIS] = e;
|
||||||
|
#endif
|
||||||
st_set_e_position(position[E_AXIS]);
|
st_set_e_position(position[E_AXIS]);
|
||||||
|
previous_speed[E_AXIS] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PREVENT_DANGEROUS_EXTRUDE
|
#ifdef PREVENT_DANGEROUS_EXTRUDE
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,12 @@ enum BlockFlag {
|
||||||
BLOCK_FLAG_START_FROM_FULL_HALT = 4,
|
BLOCK_FLAG_START_FROM_FULL_HALT = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
extern float extruder_advance_k;
|
||||||
|
extern float advance_ed_ratio;
|
||||||
|
extern float position_float[NUM_AXIS];
|
||||||
|
#endif
|
||||||
|
|
||||||
// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
|
// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
|
||||||
// the source g-code and may never actually be reached if acceleration management is active.
|
// the source g-code and may never actually be reached if acceleration management is active.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -56,6 +62,12 @@ typedef struct {
|
||||||
long accelerate_until; // The index of the step event on which to stop acceleration
|
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
|
long decelerate_after; // The index of the step event on which to start decelerating
|
||||||
|
|
||||||
|
// Advance extrusion
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
bool use_advance_lead;
|
||||||
|
uint32_t abs_adv_steps_multiplier8; // Factorised by 2^8 to avoid float
|
||||||
|
#endif
|
||||||
|
|
||||||
// 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
|
||||||
// The nominal speed for this block in mm/sec.
|
// The nominal speed for this block in mm/sec.
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,48 @@ int8_t SilentMode;
|
||||||
volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0};
|
volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0};
|
||||||
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
|
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
|
||||||
|
constexpr uint16_t ADV_NEVER = 65535;
|
||||||
|
|
||||||
|
uint16_t nextMainISR = 0,
|
||||||
|
nextAdvanceISR = ADV_NEVER,
|
||||||
|
eISR_Rate = ADV_NEVER;
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
volatile int e_steps[EXTRUDERS];
|
||||||
|
int final_estep_rate,
|
||||||
|
current_estep_rate[EXTRUDERS],
|
||||||
|
current_adv_steps[EXTRUDERS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADV_RATE(T, L) (e_steps[TOOL_E_INDEX] ? (T) * (L) / abs(e_steps[TOOL_E_INDEX]) : ADV_NEVER)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros for bit masks
|
||||||
|
#define TEST(n,b) (((n)&_BV(b))!=0)
|
||||||
|
#define SBI(n,b) (n |= _BV(b))
|
||||||
|
#define CBI(n,b) (n &= ~_BV(b))
|
||||||
|
#define SET_BIT(n,b,value) (n) ^= ((-value)^(n)) & (_BV(b))
|
||||||
|
|
||||||
|
unsigned char last_direction_bits = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The direction of a single motor
|
||||||
|
//
|
||||||
|
static FORCE_INLINE bool motor_direction(AxisEnum axis) { return TEST(last_direction_bits, axis); }
|
||||||
|
|
||||||
|
#define TOOL_E_INDEX current_block->active_extruder
|
||||||
|
|
||||||
|
// Macros to contrain values
|
||||||
|
#define NOLESS(v,n) do{ if (v < n) v = n; }while(0)
|
||||||
|
#define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#define _ENABLE_ISRs() do { cli(); SBI(TIMSK0, OCIE0B); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//=============================functions ============================
|
//=============================functions ============================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
@ -320,12 +362,50 @@ FORCE_INLINE void trapezoid_generator_reset() {
|
||||||
// SERIAL_ECHOPGM("final advance :");
|
// SERIAL_ECHOPGM("final advance :");
|
||||||
// SERIAL_ECHOLN(current_block->final_advance/256.0);
|
// SERIAL_ECHOLN(current_block->final_advance/256.0);
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
if (current_block->use_advance_lead) {
|
||||||
|
current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
||||||
|
final_estep_rate = (current_block->nominal_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stepper Driver Interrupt
|
||||||
|
*
|
||||||
|
* Directly pulses the stepper motors at high frequency.
|
||||||
|
* Timer 1 runs at a base frequency of 2MHz, with this ISR using OCR1A compare mode.
|
||||||
|
*
|
||||||
|
* OCR1A Frequency
|
||||||
|
* 1 2 MHz
|
||||||
|
* 50 40 KHz
|
||||||
|
* 100 20 KHz - capped max rate
|
||||||
|
* 200 10 KHz - nominal max rate
|
||||||
|
* 2000 1 KHz - sleep rate
|
||||||
|
* 4000 500 Hz - init rate
|
||||||
|
*/
|
||||||
|
ISR(TIMER1_COMPA_vect) {
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
advance_isr_scheduler();
|
||||||
|
#else
|
||||||
|
isr();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// "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.
|
||||||
ISR(TIMER1_COMPA_vect)
|
void isr()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifndef LIN_ADVANCE
|
||||||
|
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
|
||||||
|
CBI(TIMSK0, OCIE0B); // Temperature ISR
|
||||||
|
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||||
|
sei();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If there is no current block, attempt to pop one from the buffer
|
// If there is no current block, attempt to pop one from the buffer
|
||||||
if (current_block == NULL) {
|
if (current_block == NULL) {
|
||||||
// Anything in the buffer?
|
// Anything in the buffer?
|
||||||
|
|
@ -344,12 +424,15 @@ ISR(TIMER1_COMPA_vect)
|
||||||
if(current_block->steps_z > 0) {
|
if(current_block->steps_z > 0) {
|
||||||
enable_z();
|
enable_z();
|
||||||
OCR1A = 2000; //1ms wait
|
OCR1A = 2000; //1ms wait
|
||||||
|
_ENABLE_ISRs();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OCR1A=2000; // 1kHz.
|
OCR1A=2000; // 1kHz.
|
||||||
|
_ENABLE_ISRs();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,10 +598,11 @@ ISR(TIMER1_COMPA_vect)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LIN_ADVANCE
|
||||||
if ((out_bits & (1 << E_AXIS)) != 0)
|
if ((out_bits & (1 << E_AXIS)) != 0)
|
||||||
{ // -direction
|
{ // -direction
|
||||||
//AKU
|
//AKU
|
||||||
#ifdef SNMM
|
#ifdef SNMM
|
||||||
if (snmm_extruder == 0 || snmm_extruder == 2)
|
if (snmm_extruder == 0 || snmm_extruder == 2)
|
||||||
{
|
{
|
||||||
NORM_E_DIR();
|
NORM_E_DIR();
|
||||||
|
|
@ -527,14 +611,14 @@ ISR(TIMER1_COMPA_vect)
|
||||||
{
|
{
|
||||||
REV_E_DIR();
|
REV_E_DIR();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
REV_E_DIR();
|
REV_E_DIR();
|
||||||
#endif // SNMM
|
#endif // SNMM
|
||||||
count_direction[E_AXIS] = -1;
|
count_direction[E_AXIS] = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // +direction
|
{ // +direction
|
||||||
#ifdef SNMM
|
#ifdef SNMM
|
||||||
if (snmm_extruder == 0 || snmm_extruder == 2)
|
if (snmm_extruder == 0 || snmm_extruder == 2)
|
||||||
{
|
{
|
||||||
REV_E_DIR();
|
REV_E_DIR();
|
||||||
|
|
@ -543,17 +627,30 @@ ISR(TIMER1_COMPA_vect)
|
||||||
{
|
{
|
||||||
NORM_E_DIR();
|
NORM_E_DIR();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
NORM_E_DIR();
|
NORM_E_DIR();
|
||||||
#endif // SNMM
|
#endif // SNMM
|
||||||
count_direction[E_AXIS] = 1;
|
count_direction[E_AXIS] = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for(uint8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
|
for(uint8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
|
||||||
#ifndef AT90USB
|
#ifndef AT90USB
|
||||||
MSerial.checkRx(); // Check for serial chars.
|
MSerial.checkRx(); // Check for serial chars.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
counter_e += current_block->steps_e;
|
||||||
|
if (counter_e > 0) {
|
||||||
|
counter_e -= current_block->step_event_count;
|
||||||
|
#ifndef MIXING_EXTRUDER
|
||||||
|
// Don't step E here for mixing extruder
|
||||||
|
count_position[E_AXIS] += count_direction[E_AXIS];
|
||||||
|
motor_direction(E_AXIS) ? --e_steps[TOOL_E_INDEX] : ++e_steps[TOOL_E_INDEX];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif //LIN_ADVANCE
|
||||||
|
|
||||||
counter_x += current_block->steps_x;
|
counter_x += current_block->steps_x;
|
||||||
if (counter_x > 0) {
|
if (counter_x > 0) {
|
||||||
WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
|
WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
|
||||||
|
|
@ -596,6 +693,7 @@ ISR(TIMER1_COMPA_vect)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIN_ADVANCE
|
||||||
counter_e += current_block->steps_e;
|
counter_e += current_block->steps_e;
|
||||||
if (counter_e > 0) {
|
if (counter_e > 0) {
|
||||||
WRITE_E_STEP(!INVERT_E_STEP_PIN);
|
WRITE_E_STEP(!INVERT_E_STEP_PIN);
|
||||||
|
|
@ -603,6 +701,7 @@ ISR(TIMER1_COMPA_vect)
|
||||||
count_position[E_AXIS]+=count_direction[E_AXIS];
|
count_position[E_AXIS]+=count_direction[E_AXIS];
|
||||||
WRITE_E_STEP(INVERT_E_STEP_PIN);
|
WRITE_E_STEP(INVERT_E_STEP_PIN);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
step_events_completed += 1;
|
step_events_completed += 1;
|
||||||
if(step_events_completed >= current_block->step_event_count) break;
|
if(step_events_completed >= current_block->step_event_count) break;
|
||||||
}
|
}
|
||||||
|
|
@ -622,6 +721,15 @@ ISR(TIMER1_COMPA_vect)
|
||||||
timer = calc_timer(acc_step_rate);
|
timer = calc_timer(acc_step_rate);
|
||||||
OCR1A = timer;
|
OCR1A = timer;
|
||||||
acceleration_time += timer;
|
acceleration_time += timer;
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
|
||||||
|
if (current_block->use_advance_lead)
|
||||||
|
{
|
||||||
|
current_estep_rate[TOOL_E_INDEX] = ((uint32_t)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
||||||
|
}
|
||||||
|
eISR_Rate = ADV_RATE(timer, step_loops);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
|
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
|
||||||
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
|
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
|
||||||
|
|
@ -641,6 +749,15 @@ ISR(TIMER1_COMPA_vect)
|
||||||
timer = calc_timer(step_rate);
|
timer = calc_timer(step_rate);
|
||||||
OCR1A = timer;
|
OCR1A = timer;
|
||||||
deceleration_time += timer;
|
deceleration_time += timer;
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
|
||||||
|
if (current_block->use_advance_lead)
|
||||||
|
{
|
||||||
|
current_estep_rate[TOOL_E_INDEX] = ((uint32_t)step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
||||||
|
}
|
||||||
|
eISR_Rate = ADV_RATE(timer, step_loops);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OCR1A = OCR1A_nominal;
|
OCR1A = OCR1A_nominal;
|
||||||
|
|
@ -648,14 +765,145 @@ ISR(TIMER1_COMPA_vect)
|
||||||
step_loops = step_loops_nominal;
|
step_loops = step_loops_nominal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIN_ADVANCE
|
||||||
|
NOLESS(OCR1A, TCNT1 + 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
// If current block is finished, reset pointer
|
// If current block is finished, reset pointer
|
||||||
if (step_events_completed >= current_block->step_event_count) {
|
if (step_events_completed >= current_block->step_event_count) {
|
||||||
current_block = NULL;
|
current_block = NULL;
|
||||||
plan_discard_current_block();
|
plan_discard_current_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIN_ADVANCE
|
||||||
|
_ENABLE_ISRs(); // re-enable ISRs
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined LIN_ADVANCE
|
||||||
|
|
||||||
|
#define CYCLES_EATEN_E (E_STEPPERS * 5)
|
||||||
|
#define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E))
|
||||||
|
|
||||||
|
// Timer interrupt for E. e_steps is set in the main routine;
|
||||||
|
|
||||||
|
void advance_isr()
|
||||||
|
{
|
||||||
|
|
||||||
|
nextAdvanceISR = eISR_Rate;
|
||||||
|
|
||||||
|
#define SET_E_STEP_DIR(INDEX) \
|
||||||
|
if (e_steps[INDEX]) E## INDEX ##_DIR_WRITE(e_steps[INDEX] < 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)
|
||||||
|
|
||||||
|
#define START_E_PULSE(INDEX) \
|
||||||
|
if (e_steps[INDEX]) E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN)
|
||||||
|
|
||||||
|
#define STOP_E_PULSE(INDEX) \
|
||||||
|
if (e_steps[INDEX]) { \
|
||||||
|
e_steps[INDEX] < 0 ? ++e_steps[INDEX] : --e_steps[INDEX]; \
|
||||||
|
E## INDEX ##_STEP_WRITE(INVERT_E_STEP_PIN); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_E_STEP_DIR(0);
|
||||||
|
#if E_STEPPERS > 1
|
||||||
|
SET_E_STEP_DIR(1);
|
||||||
|
#if E_STEPPERS > 2
|
||||||
|
SET_E_STEP_DIR(2);
|
||||||
|
#if E_STEPPERS > 3
|
||||||
|
SET_E_STEP_DIR(3);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Step all E steppers that have steps
|
||||||
|
for (uint8_t i = step_loops; i--;) {
|
||||||
|
|
||||||
|
#if EXTRA_CYCLES_E > 20
|
||||||
|
uint32_t pulse_start = TCNT0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
START_E_PULSE(0);
|
||||||
|
#if E_STEPPERS > 1
|
||||||
|
START_E_PULSE(1);
|
||||||
|
#if E_STEPPERS > 2
|
||||||
|
START_E_PULSE(2);
|
||||||
|
#if E_STEPPERS > 3
|
||||||
|
START_E_PULSE(3);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For minimum pulse time wait before stopping pulses
|
||||||
|
#if EXTRA_CYCLES_E > 20
|
||||||
|
while (EXTRA_CYCLES_E > (uint32_t)(TCNT0 - pulse_start) * (INT0_PRESCALER)) { /* nada */ }
|
||||||
|
pulse_start = TCNT0;
|
||||||
|
#elif EXTRA_CYCLES_E > 0
|
||||||
|
DELAY_NOPS(EXTRA_CYCLES_E);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STOP_E_PULSE(0);
|
||||||
|
#if E_STEPPERS > 1
|
||||||
|
STOP_E_PULSE(1);
|
||||||
|
#if E_STEPPERS > 2
|
||||||
|
STOP_E_PULSE(2);
|
||||||
|
#if E_STEPPERS > 3
|
||||||
|
STOP_E_PULSE(3);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For minimum pulse time wait before looping
|
||||||
|
#if EXTRA_CYCLES_E > 20
|
||||||
|
if (i) while (EXTRA_CYCLES_E > (uint32_t)(TCNT0 - pulse_start) * (INT0_PRESCALER)) { /* nada */ }
|
||||||
|
#elif EXTRA_CYCLES_E > 0
|
||||||
|
if (i) DELAY_NOPS(EXTRA_CYCLES_E);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // steps_loop
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_isr_scheduler() {
|
||||||
|
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
|
||||||
|
CBI(TIMSK0, OCIE0B); // Temperature ISR
|
||||||
|
DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||||
|
sei();
|
||||||
|
|
||||||
|
// Run main stepping ISR if flagged
|
||||||
|
if (!nextMainISR) isr();
|
||||||
|
|
||||||
|
// Run Advance stepping ISR if flagged
|
||||||
|
if (!nextAdvanceISR) advance_isr();
|
||||||
|
|
||||||
|
// Is the next advance ISR scheduled before the next main ISR?
|
||||||
|
if (nextAdvanceISR <= nextMainISR) {
|
||||||
|
// Set up the next interrupt
|
||||||
|
OCR1A = nextAdvanceISR;
|
||||||
|
// New interval for the next main ISR
|
||||||
|
if (nextMainISR) nextMainISR -= nextAdvanceISR;
|
||||||
|
// Will call Stepper::advance_isr on the next interrupt
|
||||||
|
nextAdvanceISR = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The next main ISR comes first
|
||||||
|
OCR1A = nextMainISR;
|
||||||
|
// New interval for the next advance ISR, if any
|
||||||
|
if (nextAdvanceISR && nextAdvanceISR != ADV_NEVER)
|
||||||
|
nextAdvanceISR -= nextMainISR;
|
||||||
|
// Will call Stepper::isr on the next interrupt
|
||||||
|
nextMainISR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't run the ISR faster than possible
|
||||||
|
NOLESS(OCR1A, TCNT1 + 16);
|
||||||
|
|
||||||
|
// Restore original ISR settings
|
||||||
|
_ENABLE_ISRs();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ADVANCE or LIN_ADVANCE
|
||||||
|
|
||||||
void st_init()
|
void st_init()
|
||||||
{
|
{
|
||||||
digipot_init(); //Initialize Digipot Motor Current
|
digipot_init(); //Initialize Digipot Motor Current
|
||||||
|
|
@ -844,6 +1092,17 @@ void st_init()
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||||
|
|
||||||
|
#ifdef LIN_ADVANCE
|
||||||
|
#if defined(TCCR0A) && defined(WGM01)
|
||||||
|
TCCR0A &= ~(1<<WGM01);
|
||||||
|
TCCR0A &= ~(1<<WGM00);
|
||||||
|
#endif
|
||||||
|
e_steps[0] = 0;
|
||||||
|
e_steps[1] = 0;
|
||||||
|
e_steps[2] = 0;
|
||||||
|
TIMSK0 |= (1<<OCIE0A);
|
||||||
|
#endif //ADVANCE
|
||||||
|
|
||||||
enable_endstops(true); // Start with endstops active. After homing they can be disabled
|
enable_endstops(true); // Start with endstops active. After homing they can be disabled
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#define stepper_h
|
#define stepper_h
|
||||||
|
|
||||||
#include "planner.h"
|
#include "planner.h"
|
||||||
|
#include "stepper_indirection.h"
|
||||||
|
|
||||||
#if EXTRUDERS > 2
|
#if EXTRUDERS > 2
|
||||||
#define WRITE_E_STEP(v) { if(current_block->active_extruder == 2) { WRITE(E2_STEP_PIN, v); } else { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}}
|
#define WRITE_E_STEP(v) { if(current_block->active_extruder == 2) { WRITE(E2_STEP_PIN, v); } else { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}}
|
||||||
|
|
@ -41,6 +42,28 @@
|
||||||
extern bool abort_on_endstop_hit;
|
extern bool abort_on_endstop_hit;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
extern uint16_t nextMainISR, nextAdvanceISR, eISR_Rate;
|
||||||
|
#define _NEXT_ISR(T) nextMainISR = T
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
extern volatile int e_steps[EXTRUDERS];
|
||||||
|
extern int final_estep_rate;
|
||||||
|
extern int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s]
|
||||||
|
extern int current_adv_steps[EXTRUDERS]; // The amount of current added esteps due to advance.
|
||||||
|
// i.e., the current amount of pressure applied
|
||||||
|
// to the spring (=filament).
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define _NEXT_ISR(T) OCR1A = T
|
||||||
|
#endif // ADVANCE or LIN_ADVANCE
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
extern void advance_isr();
|
||||||
|
extern void advance_isr_scheduler();
|
||||||
|
#endif
|
||||||
|
extern unsigned char last_direction_bits; // The next stepping-bits to be output
|
||||||
|
|
||||||
|
|
||||||
// Initialize and start the stepper motor subsystem
|
// Initialize and start the stepper motor subsystem
|
||||||
void st_init();
|
void st_init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* Marlin 3D Printer Firmware
|
||||||
|
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||||
|
*
|
||||||
|
* Based on Sprinter and grbl.
|
||||||
|
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
stepper_indirection.h - stepper motor driver indirection macros
|
||||||
|
to allow some stepper functions to be done via SPI/I2c instead of direct pin manipulation
|
||||||
|
Part of Marlin
|
||||||
|
|
||||||
|
Copyright (c) 2015 Dominik Wenger
|
||||||
|
|
||||||
|
Marlin is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Marlin is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Marlin. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STEPPER_INDIRECTION_H
|
||||||
|
#define STEPPER_INDIRECTION_H
|
||||||
|
|
||||||
|
#if defined(HAVE_TMC2130)
|
||||||
|
#include "TMC2130Stepper.h"
|
||||||
|
void tmc2130_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// X Stepper
|
||||||
|
#if defined(HAVE_TMC2130) && defined(X_IS_TMC2130)
|
||||||
|
extern TMC2130Stepper stepperX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define X_ENABLE_INIT SET_OUTPUT(X_ENABLE_PIN)
|
||||||
|
#define X_ENABLE_WRITE(STATE) WRITE(X_ENABLE_PIN,STATE)
|
||||||
|
#define X_ENABLE_READ READ(X_ENABLE_PIN)
|
||||||
|
|
||||||
|
#define X_DIR_INIT SET_OUTPUT(X_DIR_PIN)
|
||||||
|
#define X_DIR_WRITE(STATE) WRITE(X_DIR_PIN,STATE)
|
||||||
|
#define X_DIR_READ READ(X_DIR_PIN)
|
||||||
|
|
||||||
|
#define X_STEP_INIT SET_OUTPUT(X_STEP_PIN)
|
||||||
|
#define X_STEP_WRITE(STATE) WRITE(X_STEP_PIN,STATE)
|
||||||
|
#define X_STEP_READ READ(X_STEP_PIN)
|
||||||
|
|
||||||
|
// Y Stepper
|
||||||
|
#if defined(HAVE_TMC2130) && defined(Y_IS_TMC2130)
|
||||||
|
extern TMC2130Stepper stepperY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Y_ENABLE_INIT SET_OUTPUT(Y_ENABLE_PIN)
|
||||||
|
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
|
||||||
|
#define Y_ENABLE_READ READ(Y_ENABLE_PIN)
|
||||||
|
|
||||||
|
#define Y_DIR_INIT SET_OUTPUT(Y_DIR_PIN)
|
||||||
|
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
|
||||||
|
#define Y_DIR_READ READ(Y_DIR_PIN)
|
||||||
|
|
||||||
|
#define Y_STEP_INIT SET_OUTPUT(Y_STEP_PIN)
|
||||||
|
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
|
||||||
|
#define Y_STEP_READ READ(Y_STEP_PIN)
|
||||||
|
|
||||||
|
// Z Stepper
|
||||||
|
#if defined(HAVE_TMC2130) && defined(Z_IS_TMC2130)
|
||||||
|
extern TMC2130Stepper stepperZ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z_ENABLE_INIT SET_OUTPUT(Z_ENABLE_PIN)
|
||||||
|
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
|
||||||
|
#define Z_ENABLE_READ READ(Z_ENABLE_PIN)
|
||||||
|
|
||||||
|
#define Z_DIR_INIT SET_OUTPUT(Z_DIR_PIN)
|
||||||
|
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
|
||||||
|
#define Z_DIR_READ READ(Z_DIR_PIN)
|
||||||
|
|
||||||
|
#define Z_STEP_INIT SET_OUTPUT(Z_STEP_PIN)
|
||||||
|
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
|
||||||
|
#define Z_STEP_READ READ(Z_STEP_PIN)
|
||||||
|
|
||||||
|
// E0 Stepper
|
||||||
|
#if defined(HAVE_TMC2130) && defined(E0_IS_TMC2130)
|
||||||
|
extern TMC2130Stepper stepperE0;
|
||||||
|
#endif
|
||||||
|
#define E0_ENABLE_INIT SET_OUTPUT(E0_ENABLE_PIN)
|
||||||
|
#define E0_ENABLE_WRITE(STATE) WRITE(E0_ENABLE_PIN,STATE)
|
||||||
|
#define E0_ENABLE_READ READ(E0_ENABLE_PIN)
|
||||||
|
|
||||||
|
#define E0_DIR_INIT SET_OUTPUT(E0_DIR_PIN)
|
||||||
|
#define E0_DIR_WRITE(STATE) WRITE(E0_DIR_PIN,STATE)
|
||||||
|
#define E0_DIR_READ READ(E0_DIR_PIN)
|
||||||
|
|
||||||
|
#define E0_STEP_INIT SET_OUTPUT(E0_STEP_PIN)
|
||||||
|
#define E0_STEP_WRITE(STATE) WRITE(E0_STEP_PIN,STATE)
|
||||||
|
#define E0_STEP_READ READ(E0_STEP_PIN)
|
||||||
|
|
||||||
|
#endif // STEPPER_INDIRECTION_H
|
||||||
|
|
@ -3720,6 +3720,11 @@ static void lcd_tune_menu()
|
||||||
} else {
|
} else {
|
||||||
MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set_tune);
|
MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set_tune);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
MENU_ITEM_EDIT(float3, MSG_ADVANCE_K, &extruder_advance_k, 0, 999);
|
||||||
|
MENU_ITEM_EDIT(float3, MSG_E_D_RATIO, &advance_ed_ratio, 0, 999);
|
||||||
|
#endif
|
||||||
END_MENU();
|
END_MENU();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,49 @@ GENERAL SETTINGS
|
||||||
//#define E3D_PT100_BED_NO_AMP
|
//#define E3D_PT100_BED_NO_AMP
|
||||||
|
|
||||||
|
|
||||||
|
// Linear Advance feature - EXPERIMENTAL!
|
||||||
|
/**
|
||||||
|
* Implementation of linear pressure control
|
||||||
|
*
|
||||||
|
* Assumption: advance = k * (delta velocity)
|
||||||
|
* K=0 means advance disabled.
|
||||||
|
* See Marlin documentation for calibration instructions.
|
||||||
|
*/
|
||||||
|
#define LIN_ADVANCE
|
||||||
|
|
||||||
|
#if defined(LIN_ADVANCE)
|
||||||
|
#define LIN_ADVANCE_K 75
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Slicers produce Gcode with randomly jumping extrusion widths occasionally.
|
||||||
|
* For example within a 0.4mm perimeter it may produce a single segment of 0.05mm width.
|
||||||
|
* While this is harmless for normal printing (the fluid nature of the filament will
|
||||||
|
* close this very, very tiny gap), it throws off the LIN_ADVANCE pressure adaption.
|
||||||
|
*
|
||||||
|
* For this case LIN_ADVANCE_E_D_RATIO can be used to set the extrusion:distance ratio
|
||||||
|
* to a fixed value. Note that using a fixed ratio will lead to wrong nozzle pressures
|
||||||
|
* if the slicer is using variable widths or layer heights within one print!
|
||||||
|
*
|
||||||
|
* This option sets the default E:D ratio at startup. Use `M900` to override this value.
|
||||||
|
*
|
||||||
|
* Example: `M900 W0.4 H0.2 D1.75`, where:
|
||||||
|
* - W is the extrusion width in mm
|
||||||
|
* - H is the layer height in mm
|
||||||
|
* - D is the filament diameter in mm
|
||||||
|
*
|
||||||
|
* Example: `M900 R0.0458` to set the ratio directly.
|
||||||
|
*
|
||||||
|
* Set to 0 to auto-detect the ratio based on given Gcode G1 print moves.
|
||||||
|
*
|
||||||
|
* Slic3r (including Prusa Slic3r) produces Gcode compatible with the automatic mode.
|
||||||
|
* Cura (as of this writing) may produce Gcode incompatible with the automatic mode.
|
||||||
|
*/
|
||||||
|
#define LIN_ADVANCE_E_D_RATIO 0.033260135 // The calculated ratio (or 0) according to the formula W * H / ((D / 2) ^ 2 * PI)
|
||||||
|
// Example: 0.4 * 0.2 / ((1.75 / 2) ^ 2 * PI) = 0.033260135
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------
|
/*------------------------------------
|
||||||
AXIS SETTINGS
|
AXIS SETTINGS
|
||||||
*------------------------------------*/
|
*------------------------------------*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue