Commit 1e7265b6 authored by MagoKimbra's avatar MagoKimbra

fix ADVANCED LPC

parent fd9eeea6
...@@ -268,17 +268,37 @@ ...@@ -268,17 +268,37 @@
#define THERMAL_PROTECTION_PERIOD 40 // Seconds #define THERMAL_PROTECTION_PERIOD 40 // Seconds
#define THERMAL_PROTECTION_HYSTERESIS 4 // Degrees Celsius #define THERMAL_PROTECTION_HYSTERESIS 4 // Degrees Celsius
// Whenever an M104 or M109 increases the target temperature the firmware will wait for the /**
// WATCH TEMP PERIOD to expire, and if the temperature hasn't increased by WATCH TEMP INCREASE * Whenever an M104 or M109 increases the target temperature the firmware will wait for the
// degrees, the machine is halted, requiring a hard reset. This test restarts with any M104/M109, * WATCH TEMP PERIOD to expire, and if the temperature hasn't increased by WATCH TEMP INCREASE
//but only if the current temperature is far enough below the target for a reliable test. * degrees, the machine is halted, requiring a hard reset. This test restarts with any M104/M109,
#define WATCH_TEMP_PERIOD 16 // Seconds * but only if the current temperature is far enough below the target for a reliable test.
#define WATCH_TEMP_INCREASE 4 // Degrees Celsius *
* If you get false positives for "Heating failed" increase WATCH TEMP PERIOD and/or decrease WATCH TEMP INCREASE
* WATCH TEMP INCREASE should not be below 2.
*/
#define WATCH_TEMP_PERIOD 20 // Seconds
#define WATCH_TEMP_INCREASE 2 // Degrees Celsius
/**
* Thermal Protection parameters for the bed are just as above for hotends.
*/
//#define THERMAL_PROTECTION_BED //#define THERMAL_PROTECTION_BED
#define THERMAL_PROTECTION_BED_PERIOD 20 // Seconds #define THERMAL_PROTECTION_BED_PERIOD 20 // Seconds
#define THERMAL_PROTECTION_BED_HYSTERESIS 2 // Degrees Celsius #define THERMAL_PROTECTION_BED_HYSTERESIS 2 // Degrees Celsius
/**
* Whenever an M140 or M190 increases the target temperature the firmware will wait for the
* WATCH BED TEMP PERIOD to expire, and if the temperature hasn't increased by WATCH BED TEMP INCREASE
* degrees, the machine is halted, requiring a hard reset. This test restarts with any M140/M190,
* but only if the current temperature is far enough below the target for a reliable test.
*
* If you get too many "Heating failed" errors, increase WATCH BED TEMP PERIOD and/or decrease
* WATCH BED TEMP INCREASE. (WATCH BED TEMP INCREASE should not be below 2.)
*/
#define WATCH_BED_TEMP_PERIOD 60 // Seconds
#define WATCH_BED_TEMP_INCREASE 2 // Degrees Celsius
/********************************************************************************/ /********************************************************************************/
...@@ -563,9 +583,21 @@ ...@@ -563,9 +583,21 @@
*****************************************************************************************/ *****************************************************************************************/
//#define ADVANCE //#define ADVANCE
#define EXTRUDER_ADVANCE_K .0 #define EXTRUDER_ADVANCE_K 0.0
#define D_FILAMENT 1.75 #define D_FILAMENT 1.75
#define STEPS_PER_CUBIC_MM_E 0.85 /*****************************************************************************************/
/*****************************************************************************************
****************** Extruder Advance Linear Pressure Control *****************************
*****************************************************************************************
* *
* Assumption: advance = k * (delta velocity) *
* K=0 means advance disabled. A good value for a gregs wade extruder will be around K=75*
* *
*****************************************************************************************/
//#define ADVANCE_LPC
#define ADVANCE_LPC_K 75
/*****************************************************************************************/ /*****************************************************************************************/
......
...@@ -5356,7 +5356,7 @@ inline void gcode_M92() { ...@@ -5356,7 +5356,7 @@ inline void gcode_M92() {
#endif #endif
/** /**
* M104: Set hot end temperature * M104: Set hotend temperature
*/ */
inline void gcode_M104() { inline void gcode_M104() {
if (setTargetedExtruder(104)) return; if (setTargetedExtruder(104)) return;
...@@ -6368,7 +6368,7 @@ inline void gcode_M226() { ...@@ -6368,7 +6368,7 @@ inline void gcode_M226() {
* M363: SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree) * M363: SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
*/ */
inline bool gcode_M363() { inline bool gcode_M363() {
ECHO_LM(DB,"Cal: Psi 90 "); ECHO_LM(DB, "Cal: Psi 90 ");
return SCARA_move_to_cal(50, 90); return SCARA_move_to_cal(50, 90);
} }
...@@ -7230,6 +7230,17 @@ inline void gcode_M503() { ...@@ -7230,6 +7230,17 @@ inline void gcode_M503() {
} }
#endif #endif
#if ENABLED(ADVANCE_LPC)
/**
* M905: Set advance factor
*/
inline void gcode_M905() {
st_synchronize();
if (code_seen('K')) extruder_advance_k = code_value();
ECHO_LMV(DB, "Advance factor = ", extruder_advance_k);
}
#endif
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
/** /**
* M906: Set motor currents * M906: Set motor currents
...@@ -7866,14 +7877,14 @@ void process_next_command() { ...@@ -7866,14 +7877,14 @@ void process_next_command() {
case 112: // M112 Emergency Stop case 112: // M112 Emergency Stop
gcode_M112(); break; gcode_M112(); break;
case 114: // M114 Report current position
gcode_M114(); break;
#if ENABLED(HOST_KEEPALIVE_FEATURE) #if ENABLED(HOST_KEEPALIVE_FEATURE)
case 113: // M113: Set Host Keepalive interval case 113: // M113: Set Host Keepalive interval
gcode_M113(); break; gcode_M113(); break;
#endif #endif
case 114: // M114 Report current position
gcode_M114(); break;
case 115: // M115 Report capabilities case 115: // M115 Report capabilities
gcode_M115(); break; gcode_M115(); break;
...@@ -8090,7 +8101,7 @@ void process_next_command() { ...@@ -8090,7 +8101,7 @@ void process_next_command() {
#endif #endif
#if ENABLED(FILAMENTCHANGEENABLE) #if ENABLED(FILAMENTCHANGEENABLE)
case 600: //Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal] case 600: // Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
gcode_M600(); break; gcode_M600(); break;
#endif #endif
...@@ -8104,6 +8115,11 @@ void process_next_command() { ...@@ -8104,6 +8115,11 @@ void process_next_command() {
gcode_M666(); break; gcode_M666(); break;
#endif #endif
#if ENABLED(ADVANCE_LPC)
case 905: // M905 Set advance factor.
gcode_M905(); break;
#endif
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
case 906: // M906 Set motor currents XYZ T0-4 E case 906: // M906 Set motor currents XYZ T0-4 E
gcode_M906(); break; gcode_M906(); break;
......
...@@ -36,6 +36,10 @@ void idle( ...@@ -36,6 +36,10 @@ void idle(
void manage_inactivity(bool ignore_stepper_queue = false); void manage_inactivity(bool ignore_stepper_queue = false);
#if ENABLED(DUAL_X_CARRIAGE)
extern bool extruder_duplication_enabled;
#endif
void FlushSerialRequestResend(); void FlushSerialRequestResend();
void ok_to_send(); void ok_to_send();
...@@ -134,6 +138,10 @@ extern bool axis_known_position[3]; ...@@ -134,6 +138,10 @@ extern bool axis_known_position[3];
extern bool axis_homed[3]; extern bool axis_homed[3];
extern float zprobe_zoffset; extern float zprobe_zoffset;
#if ENABLED(ADVANCE_LPC)
extern int extruder_advance_k;
#endif
#if HEATER_USES_AD595 #if HEATER_USES_AD595
extern float ad595_offset[HOTENDS]; extern float ad595_offset[HOTENDS];
extern float ad595_gain[HOTENDS]; extern float ad595_gain[HOTENDS];
......
...@@ -505,7 +505,7 @@ ...@@ -505,7 +505,7 @@
*/ */
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE)
#define EXTRUSION_AREA (0.25 * (D_FILAMENT) * (D_FILAMENT) * M_PI) #define EXTRUSION_AREA (0.25 * (D_FILAMENT) * (D_FILAMENT) * M_PI)
#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS + active_extruder] / EXTRUSION_AREA) #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS + active_extruder] / (EXTRUSION_AREA))
#endif #endif
/** /**
......
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
#define SERIAL_HEATER_BED "bed" #define SERIAL_HEATER_BED "bed"
#define SERIAL_STOPPED_HEATER ", system stopped! Heater_ID: " #define SERIAL_STOPPED_HEATER ", system stopped! Heater_ID: "
//#define SERIAL_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !" #define SERIAL_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
#define SERIAL_T_HEATING_FAILED "Heating failed" #define SERIAL_T_HEATING_FAILED "Heating failed"
#define SERIAL_T_THERMAL_RUNAWAY "Thermal Runaway" #define SERIAL_T_THERMAL_RUNAWAY "Thermal Runaway"
#define SERIAL_T_MAXTEMP "MAXTEMP triggered" #define SERIAL_T_MAXTEMP "MAXTEMP triggered"
......
...@@ -151,13 +151,13 @@ ...@@ -151,13 +151,13 @@
#define MSG_BABYSTEP_Z MSG_BABYSTEP " " MSG_Z #define MSG_BABYSTEP_Z MSG_BABYSTEP " " MSG_Z
#define MSG_ENDSTOP_ABORT "Finecorsa abort." #define MSG_ENDSTOP_ABORT "Finecorsa abort."
#define MSG_HEATING_FAILED_LCD "Riscaldamento fallito" #define MSG_HEATING_FAILED_LCD "Riscaldamento fallito"
#define MSG_ERR_REDUNDANT_TEMP "REDUNDANT TEMP ERROR" #define MSG_ERR_REDUNDANT_TEMP "Err: TEMP RIDONDANTI"
#define MSG_THERMAL_RUNAWAY "THERMAL RUNAWAY" #define MSG_THERMAL_RUNAWAY "TEMP FUORI CONTROLLO"
#define MSG_AD595 "AD595 Offset & Gain" #define MSG_AD595 "AD595 Offset & Gain"
#define MSG_ERR_MAXTEMP "MAXTEMP ERROR" #define MSG_ERR_MAXTEMP "Err: TEMP MASSIMA"
#define MSG_ERR_MINTEMP "MINTEMP ERROR" #define MSG_ERR_MINTEMP "Err: TEMP MINIMA"
#define MSG_ERR_MAXTEMP_BED "MAXTEMP BED ERROR" #define MSG_ERR_MAXTEMP_BED "Err: TEMP MASSIMA PIATTO"
#define MSG_ERR_MINTEMP_BED "MINTEMP BED ERROR" #define MSG_ERR_MINTEMP_BED "Err: TEMP MINIMA PIATTO"
#define MSG_END_DAY "giorni" #define MSG_END_DAY "giorni"
#define MSG_END_HOUR "ore" #define MSG_END_HOUR "ore"
#define MSG_END_MINUTE "minuti" #define MSG_END_MINUTE "minuti"
......
...@@ -1126,7 +1126,20 @@ float junction_deviation = 0.1; ...@@ -1126,7 +1126,20 @@ float junction_deviation = 0.1;
ECHO_SMV(OK, "advance :", block->advance/256); ECHO_SMV(OK, "advance :", block->advance/256);
ECHO_EMV("advance rate :", block->advance_rate/256); ECHO_EMV("advance rate :", block->advance_rate/256);
*/ */
#endif // ADVANCE #elif ENABLED(ADVANCE_LPC) // ADVANCE_LPC
// bse == allsteps: A problem occurs when there's a very tiny move before a retract.
// In this case, the retract and the move will be executed together.
// This leads to an enormous number of advance steps due to a huge e_acceleration.
// The math is correct, but you don't want a retract move done with advance!
// So this situation is filtered out here.
if (!bse || (!bsx && !bsy && !bsz) || extruder_advance_k == 0 || bse == allsteps) {
block->use_advance_lead = false;
}
else {
block->use_advance_lead = true;
block->e_speed_multiplier8 = (block->steps[E_AXIS] << 8) / block->step_event_count;
}
#endif
calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed); calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed);
......
...@@ -49,25 +49,32 @@ ...@@ -49,25 +49,32 @@
// 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 {
unsigned char active_driver; // Selects the active driver
// Fields used by the bresenham algorithm for tracing the line // Fields used by the bresenham algorithm for tracing the line
unsigned long steps[NUM_AXIS]; // Step count along each axis unsigned long steps[NUM_AXIS]; // Step count along each axis
unsigned long step_event_count; // The number of step events required to complete this block
#if ENABLED(COLOR_MIXING_EXTRUDER) #if ENABLED(COLOR_MIXING_EXTRUDER)
unsigned long mix_event_count[DRIVER_EXTRUDERS]; // Step count for each stepper in a mixing extruder unsigned long mix_event_count[DRIVER_EXTRUDERS]; // Step count for each stepper in a mixing extruder
#endif #endif
unsigned long step_event_count; // The number of step events required to complete this block
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
long acceleration_rate; // The acceleration rate used for acceleration calculation long acceleration_rate; // The acceleration rate used for acceleration calculation
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
unsigned char active_driver; // Selects the active driver
// Advance extrusion
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE)
long advance_rate; long advance_rate;
volatile long initial_advance; volatile long initial_advance;
volatile long final_advance; volatile long final_advance;
float advance; float advance;
#elif ENABLED(ADVANCE_LPC)
bool use_advance_lead;
int e_speed_multiplier8;
#endif #endif
// Fields used by the motion planner to manage acceleration // Fields used by the motion planner to manage acceleration
......
...@@ -21,7 +21,26 @@ ...@@ -21,7 +21,26 @@
*/ */
/** /**
* stepper.cpp - stepper motor driver: executes motion plans using stepper motors * stepper.cpp - A singleton object to execute motion plans using stepper motors
*
* Derived from Grbl
* Copyright (c) 2009-2011 Simen Svale Skogsrud
*
* Grbl 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.
*
* Grbl 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 Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith * The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
* and Philipp Tiefenbacher. * and Philipp Tiefenbacher.
*/ */
...@@ -46,8 +65,13 @@ block_t* current_block; // A pointer to the block currently being traced ...@@ -46,8 +65,13 @@ block_t* current_block; // A pointer to the block currently being traced
//static makes it impossible to be called from outside of this file by extern.! //static makes it impossible to be called from outside of this file by extern.!
// Variables used by The Stepper Driver Interrupt // Variables used by The Stepper Driver Interrupt
static unsigned char out_bits = 0; // The next stepping-bits to be output static unsigned char last_direction_bits = 0; // The next stepping-bits to be output
static unsigned int cleaning_buffer_counter; static unsigned int cleaning_buffer_counter = 0;
//
// The direction of a single motor
//
FORCE_INLINE bool motor_direction(AxisEnum axis) { return TEST(last_direction_bits, axis); }
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
static bool performing_homing = false, static bool performing_homing = false,
...@@ -59,10 +83,19 @@ static unsigned int cleaning_buffer_counter; ...@@ -59,10 +83,19 @@ static unsigned int cleaning_buffer_counter;
static long counter_X, counter_Y, counter_Z, counter_E; static long counter_X, counter_Y, counter_Z, counter_E;
volatile static unsigned long step_events_completed; // The number of step events executed in the current block volatile static unsigned long step_events_completed; // The number of step events executed in the current block
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE) || ENABLED(ADVANCE_LPC)
unsigned char old_OCR0A;
#if ENABLED(ADVANCE)
static long advance_rate, advance, final_advance = 0; static long advance_rate, advance, final_advance = 0;
static long old_advance = 0; static long old_advance = 0;
static long e_steps[6]; static long e_steps[6];
#elif ENABLED(ADVANCE_LPC)
int extruder_advance_k = ADVANCE_LPC_K;
volatile int e_steps[EXTRUDERS];
static int final_estep_rate;
static int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s]
static int current_adv_steps[EXTRUDERS];
#endif
#endif #endif
static long acceleration_time, deceleration_time; static long acceleration_time, deceleration_time;
...@@ -376,9 +409,9 @@ inline void update_endstops() { ...@@ -376,9 +409,9 @@ inline void update_endstops() {
// Head direction in -X axis for CoreXY and CoreXZ bots. // Head direction in -X axis for CoreXY and CoreXZ bots.
// If Delta1 == -Delta2, the movement is only in Y or Z axis // If Delta1 == -Delta2, the movement is only in Y or Z axis
if ((current_block->steps[A_AXIS] != current_block->steps[CORE_AXIS_2]) || (TEST(out_bits, A_AXIS) == TEST(out_bits, CORE_AXIS_2))) { if ((current_block->steps[A_AXIS] != current_block->steps[CORE_AXIS_2]) || (TEST(out_bits, A_AXIS) == TEST(out_bits, CORE_AXIS_2))) {
if (TEST(out_bits, X_HEAD)) if (motor_direction(X_HEAD))
#else #else
if (TEST(out_bits, X_AXIS)) // stepping along -X axis (regular Cartesian bot) if (motor_direction(X_AXIS)) // stepping along -X axis (regular Cartesian bot)
#endif #endif
{ // -direction { // -direction
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
...@@ -410,9 +443,9 @@ inline void update_endstops() { ...@@ -410,9 +443,9 @@ inline void update_endstops() {
// Head direction in -Y axis for CoreXY bots. // Head direction in -Y axis for CoreXY bots.
// If DeltaX == DeltaY, the movement is only in X axis // If DeltaX == DeltaY, the movement is only in X axis
if ((current_block->steps[A_AXIS] != current_block->steps[B_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, B_AXIS))) { if ((current_block->steps[A_AXIS] != current_block->steps[B_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, B_AXIS))) {
if (TEST(out_bits, Y_HEAD)) if (motor_direction(Y_HEAD))
#else #else
if (TEST(out_bits, Y_AXIS)) // -direction if (motor_direction(Y_AXIS)) // -direction
#endif #endif
{ // -direction { // -direction
#if HAS(Y_MIN) #if HAS(Y_MIN)
...@@ -432,9 +465,9 @@ inline void update_endstops() { ...@@ -432,9 +465,9 @@ inline void update_endstops() {
// Head direction in -Z axis for CoreXZ bots. // Head direction in -Z axis for CoreXZ bots.
// If DeltaX == DeltaZ, the movement is only in X axis // If DeltaX == DeltaZ, the movement is only in X axis
if ((current_block->steps[A_AXIS] != current_block->steps[C_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, C_AXIS))) { if ((current_block->steps[A_AXIS] != current_block->steps[C_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, C_AXIS))) {
if (TEST(out_bits, Z_HEAD)) if (motor_direction(Z_HEAD))
#else #else
if (TEST(out_bits, Z_AXIS)) if (motor_direction(Z_AXIS))
#endif #endif
{ // z -direction { // z -direction
#if HAS(Z_MIN) #if HAS(Z_MIN)
...@@ -579,7 +612,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { ...@@ -579,7 +612,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
void set_stepper_direction(bool onlye) { void set_stepper_direction(bool onlye) {
#define SET_STEP_DIR(AXIS) \ #define SET_STEP_DIR(AXIS) \
if (TEST(out_bits, AXIS ##_AXIS)) { \ if (motor_direction(AXIS ##_AXIS)) { \
AXIS ##_APPLY_DIR(INVERT_## AXIS ##_DIR, false); \ AXIS ##_APPLY_DIR(INVERT_## AXIS ##_DIR, false); \
count_direction[AXIS ##_AXIS] = -1; \ count_direction[AXIS ##_AXIS] = -1; \
} \ } \
...@@ -595,7 +628,7 @@ void set_stepper_direction(bool onlye) { ...@@ -595,7 +628,7 @@ void set_stepper_direction(bool onlye) {
} }
#if DISABLED(ADVANCE) #if DISABLED(ADVANCE)
if (TEST(out_bits, E_AXIS)) { if (motor_direction(E_AXIS)) {
REV_E_DIR(); REV_E_DIR();
count_direction[E_AXIS] = -1; count_direction[E_AXIS] = -1;
} }
...@@ -610,8 +643,11 @@ void set_stepper_direction(bool onlye) { ...@@ -610,8 +643,11 @@ void set_stepper_direction(bool onlye) {
// block begins. // block begins.
FORCE_INLINE void trapezoid_generator_reset() { FORCE_INLINE void trapezoid_generator_reset() {
if (current_block->direction_bits != out_bits) { static int8_t last_driver = -1;
out_bits = current_block->direction_bits;
if (current_block->direction_bits != last_direction_bits || current_block->active_driver != last_driver) {
last_direction_bits = current_block->direction_bits;
last_driver = current_block->active_driver;
set_stepper_direction(); set_stepper_direction();
} }
...@@ -630,6 +666,13 @@ FORCE_INLINE void trapezoid_generator_reset() { ...@@ -630,6 +666,13 @@ FORCE_INLINE void trapezoid_generator_reset() {
acc_step_rate = current_block->initial_rate; acc_step_rate = current_block->initial_rate;
acceleration_time = calc_timer(acc_step_rate); acceleration_time = calc_timer(acc_step_rate);
OCR1A = acceleration_time; OCR1A = acceleration_time;
#if ENABLED(ADVANCE_LPC)
if (current_block->use_advance_lead) {
current_estep_rate[current_block->active_driver] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
final_estep_rate = (current_block->nominal_rate * current_block->e_speed_multiplier8) >> 8;
}
#endif
} }
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
...@@ -698,12 +741,12 @@ ISR(TIMER1_COMPA_vect) { ...@@ -698,12 +741,12 @@ ISR(TIMER1_COMPA_vect) {
counter_E -= current_block->step_event_count; counter_E -= current_block->step_event_count;
#if DISABLED(COLOR_MIXING_EXTRUDER) #if DISABLED(COLOR_MIXING_EXTRUDER)
// Don't step E for mixing extruder // Don't step E for mixing extruder
e_steps[current_block->active_driver] += TEST(out_bits, E_AXIS) ? -1 : 1; e_steps[current_block->active_driver] += motor_direction(E_AXIS) ? -1 : 1;
#endif #endif
} }
#if ENABLED(COLOR_MIXING_EXTRUDER) #if ENABLED(COLOR_MIXING_EXTRUDER)
long dir = TEST(out_bits, E_AXIS) ? -1 : 1; long dir = motor_direction(E_AXIS) ? -1 : 1;
for (uint8_t j = 0; j < DRIVER_EXTRUDERS; j++) { for (uint8_t j = 0; j < DRIVER_EXTRUDERS; j++) {
counter_m[j] += current_block->steps[E_AXIS]; counter_m[j] += current_block->steps[E_AXIS];
if (counter_m[j] > 0) { if (counter_m[j] > 0) {
...@@ -712,7 +755,21 @@ ISR(TIMER1_COMPA_vect) { ...@@ -712,7 +755,21 @@ ISR(TIMER1_COMPA_vect) {
} }
} }
#endif // !COLOR_MIXING_EXTRUDER #endif // !COLOR_MIXING_EXTRUDER
#endif // ADVANCE #elif ENABLED(ADVANCE_LPC) // ADVANCE_LPC
counter_E += current_block->steps[E_AXIS];
if (counter_E > 0) {
counter_E -= current_block->step_event_count;
count_position[E_AXIS] += count_direction[E_AXIS];
e_steps[current_block->active_driver] += motor_direction(E_AXIS) ? -1 : 1;
}
if (current_block->use_advance_lead) {
int delta_adv_steps; // Maybe a char would be enough?
delta_adv_steps = (((long)extruder_advance_k * current_estep_rate[current_block->active_driver]) >> 9) - current_adv_steps[current_block->active_driver];
e_steps[current_block->active_driver] += delta_adv_steps;
current_adv_steps[current_block->active_driver] += delta_adv_steps;
}
#endif
#define _COUNTER(AXIS) counter_## AXIS #define _COUNTER(AXIS) counter_## AXIS
#define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP
...@@ -746,7 +803,7 @@ ISR(TIMER1_COMPA_vect) { ...@@ -746,7 +803,7 @@ ISR(TIMER1_COMPA_vect) {
STEP_START(X); STEP_START(X);
STEP_START(Y); STEP_START(Y);
STEP_START(Z); STEP_START(Z);
#if DISABLED(ADVANCE) #if DISABLED(ADVANCE) && DISABLED(ADVANCE_LPC)
STEP_START(E); STEP_START(E);
#if ENABLED(COLOR_MIXING_EXTRUDER) #if ENABLED(COLOR_MIXING_EXTRUDER)
STEP_START_MIXING; STEP_START_MIXING;
...@@ -760,7 +817,7 @@ ISR(TIMER1_COMPA_vect) { ...@@ -760,7 +817,7 @@ ISR(TIMER1_COMPA_vect) {
STEP_END(X); STEP_END(X);
STEP_END(Y); STEP_END(Y);
STEP_END(Z); STEP_END(Z);
#if DISABLED(ADVANCE) #if DISABLED(ADVANCE) && DISABLED(ADVANCE_LPC)
STEP_END(E); STEP_END(E);
#if ENABLED(COLOR_MIXING_EXTRUDER) #if ENABLED(COLOR_MIXING_EXTRUDER)
STEP_END_MIXING; STEP_END_MIXING;
...@@ -801,8 +858,11 @@ ISR(TIMER1_COMPA_vect) { ...@@ -801,8 +858,11 @@ ISR(TIMER1_COMPA_vect) {
#endif #endif
old_advance = advance >> 8; old_advance = advance >> 8;
#elif ENABLED(ADVANCE_LPC) // ADVANCE_LPC
if (current_block->use_advance_lead)
current_estep_rate[current_block->active_driver] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
#endif
#endif // ADVANCE
} }
else if (step_events_completed > (unsigned long)current_block->decelerate_after) { else if (step_events_completed > (unsigned long)current_block->decelerate_after) {
MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate); MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate);
...@@ -836,9 +896,16 @@ ISR(TIMER1_COMPA_vect) { ...@@ -836,9 +896,16 @@ ISR(TIMER1_COMPA_vect) {
#endif #endif
old_advance = advance_whole; old_advance = advance_whole;
#endif //ADVANCE #elif ENABLED(ADVANCE_LPC) // ADVANCE_LPC
if (current_block->use_advance_lead)
current_estep_rate[current_block->active_driver] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8;
#endif
} }
else { else {
#if ENABLED(ADVANCE_LPC)
if (current_block->use_advance_lead)
current_estep_rate[current_block->active_driver] = final_estep_rate;
#endif
OCR1A = OCR1A_nominal; OCR1A = OCR1A_nominal;
// ensure we're running at the correct step rate, even if we just came off an acceleration // ensure we're running at the correct step rate, even if we just came off an acceleration
step_loops = step_loops_nominal; step_loops = step_loops_nominal;
...@@ -854,12 +921,25 @@ ISR(TIMER1_COMPA_vect) { ...@@ -854,12 +921,25 @@ ISR(TIMER1_COMPA_vect) {
} }
} }
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE) || ENABLED(ADVANCE_LPC)
unsigned char old_OCR0A;
// Timer interrupt for E. e_steps is set in the main routine; // Timer interrupt for E. e_steps is set in the main routine;
// Timer 0 is shared with millies // Timer 0 is shared with millies
ISR(TIMER0_COMPA_vect) { ISR(TIMER0_COMPA_vect) {
old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz)
byte maxesteps = 0;
for (unsigned char i = 0; i < EXTRUDERS; i++)
if (abs(e_steps[i]) > maxesteps) maxesteps = abs(e_steps[i]);
if (maxesteps > 3)
old_OCR0A += 13; // ~19kHz (250000/13 = 19230 Hz)
else if (maxesteps > 2)
old_OCR0A += 17; // ~15kHz (250000/17 = 14705 Hz)
else if (maxesteps > 1)
old_OCR0A += 26; // ~10kHz (250000/26 = 9615 Hz)
else
old_OCR0A += 52; // ~5kHz (250000/52 = 4807 Hz)
OCR0A = old_OCR0A; OCR0A = old_OCR0A;
#define STEP_E_ONCE(INDEX) \ #define STEP_E_ONCE(INDEX) \
...@@ -876,27 +956,25 @@ ISR(TIMER1_COMPA_vect) { ...@@ -876,27 +956,25 @@ ISR(TIMER1_COMPA_vect) {
E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); \ E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); \
} }
// Step all E steppers that have steps, up to 4 steps per interrupt // Step all E steppers that have steps
for (uint8_t i = 0; i < 4; i++) {
STEP_E_ONCE(0); STEP_E_ONCE(0);
#if DRIVER_EXTRUDERS > 1 #if EXTRUDERS > 1
STEP_E_ONCE(1); STEP_E_ONCE(1);
#if DRIVER_EXTRUDERS > 2 #if EXTRUDERS > 2
STEP_E_ONCE(2); STEP_E_ONCE(2);
#if DRIVER_EXTRUDERS > 3 #if EXTRUDERS > 3
STEP_E_ONCE(3); STEP_E_ONCE(3);
#if DRIVER_EXTRUDERS > 4 #if EXTRUDERS > 4
STEP_E_ONCE(4); STEP_E_ONCE(4);
#if DRIVER_EXTRUDERS > 5 #if EXTRUDERS > 5
STEP_E_ONCE(5); STEP_E_ONCE(5);
#endif // DRIVER_EXTRUDERS > 5 #endif
#endif // DRIVER_EXTRUDERS > 4 #endif
#endif // DRIVER_EXTRUDERS > 3 #endif
#endif // DRIVER_EXTRUDERS > 2 #endif
#endif // DRIVER_EXTRUDERS > 1 #endif
}
} }
#endif // ADVANCE #endif
void st_init() { void st_init() {
digipot_init(); //Initialize Digipot Motor Current digipot_init(); //Initialize Digipot Motor Current
...@@ -1165,14 +1243,23 @@ void st_init() { ...@@ -1165,14 +1243,23 @@ void st_init() {
TCNT1 = 0; TCNT1 = 0;
ENABLE_STEPPER_DRIVER_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT();
#if ENABLED(ADVANCE) || ENABLED(ADVANCE_LPC)
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE)
e_steps[0] = e_steps[1] = e_steps[2] = e_steps[3] = e_steps[4] = e_steps[5] = 0;
#elif ENABLED(ADVANCE_LPC)
for (uint8_t i = 0; i < EXTRUDERS; i++) {
e_steps[i] = 0;
current_adv_steps[i] = 0;
}
#endif
#if defined(TCCR0A) && defined(WGM01) #if defined(TCCR0A) && defined(WGM01)
CBI(TCCR0A, WGM01); CBI(TCCR0A, WGM01);
CBI(TCCR0A, WGM00); CBI(TCCR0A, WGM00);
#endif #endif
e_steps[0] = e_steps[1] = e_steps[2] = e_steps[3] = e_steps[4] = e_steps[5] = 0;
SBI(TIMSK0, OCIE0A); SBI(TIMSK0, OCIE0A);
#endif //ADVANCE
#endif // ADVANCE or ADVANCE_LPC
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();
......
...@@ -232,7 +232,6 @@ ...@@ -232,7 +232,6 @@
#define NORM_E_DIR() { switch(current_block->active_driver) { case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; }} #define NORM_E_DIR() { switch(current_block->active_driver) { case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; }}
#define REV_E_DIR() { switch(current_block->active_driver) { case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; }} #define REV_E_DIR() { switch(current_block->active_driver) { case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; }}
#else #else
extern bool extruder_duplication_enabled;
#define E_STEP_WRITE(v) { if(extruder_duplication_enabled) { E0_STEP_WRITE(v); E1_STEP_WRITE(v); } else if(current_block->active_driver == 1) { E1_STEP_WRITE(v); } else { E0_STEP_WRITE(v); }} #define E_STEP_WRITE(v) { if(extruder_duplication_enabled) { E0_STEP_WRITE(v); E1_STEP_WRITE(v); } else if(current_block->active_driver == 1) { E1_STEP_WRITE(v); } else { E0_STEP_WRITE(v); }}
#define NORM_E_DIR() { if(extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if(current_block->active_driver == 1) { E1_DIR_WRITE(!INVERT_E1_DIR); } else { E0_DIR_WRITE(!INVERT_E0_DIR); }} #define NORM_E_DIR() { if(extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if(current_block->active_driver == 1) { E1_DIR_WRITE(!INVERT_E1_DIR); } else { E0_DIR_WRITE(!INVERT_E0_DIR); }}
#define REV_E_DIR() { if(extruder_duplication_enabled) { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); } else if(current_block->active_driver == 1) { E1_DIR_WRITE( INVERT_E1_DIR); } else { E0_DIR_WRITE( INVERT_E0_DIR); }} #define REV_E_DIR() { if(extruder_duplication_enabled) { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); } else if(current_block->active_driver == 1) { E1_DIR_WRITE( INVERT_E1_DIR); } else { E0_DIR_WRITE( INVERT_E0_DIR); }}
......
...@@ -391,6 +391,12 @@ ...@@ -391,6 +391,12 @@
#endif #endif
#endif #endif
/**
* Advance Extrusion
*/
#if ENABLED(ADVANCE) && ENABLED(ADVANCE_LPC)
#error You can enable ADVANCE or ADVANCE_LPC, but not both.
#endif
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE)
#if DISABLED(EXTRUDER_ADVANCE_K) #if DISABLED(EXTRUDER_ADVANCE_K)
#error DEPENDENCY ERROR: Missing setting EXTRUDER_ADVANCE_K #error DEPENDENCY ERROR: Missing setting EXTRUDER_ADVANCE_K
......
...@@ -200,6 +200,11 @@ static void updateTemperaturesFromRawValues(); ...@@ -200,6 +200,11 @@ static void updateTemperaturesFromRawValues();
millis_t watch_heater_next_ms[HOTENDS] = { 0 }; millis_t watch_heater_next_ms[HOTENDS] = { 0 };
#endif #endif
#if ENABLED(THERMAL_PROTECTION_BED)
int watch_target_bed_temp = 0;
millis_t watch_bed_next_ms = 0;
#endif
#if DISABLED(SOFT_PWM_SCALE) #if DISABLED(SOFT_PWM_SCALE)
#define SOFT_PWM_SCALE 0 #define SOFT_PWM_SCALE 0
#endif #endif
...@@ -286,12 +291,12 @@ void autotempShutdown() { ...@@ -286,12 +291,12 @@ void autotempShutdown() {
#if HAS(AUTO_FAN) #if HAS(AUTO_FAN)
if (ms > next_auto_fan_check_ms) { if (ms > next_auto_fan_check_ms) {
checkExtruderAutoFans(); checkExtruderAutoFans();
next_auto_fan_check_ms = ms + 2500; next_auto_fan_check_ms = ms + 2500UL;
} }
#endif #endif
if (heating && input > temp) { if (heating && input > temp) {
if (ms > t2 + 5000) { if (ms > t2 + 5000UL) {
heating = false; heating = false;
if (hotend < 0) if (hotend < 0)
soft_pwm_bed = (bias - d) >> 1; soft_pwm_bed = (bias - d) >> 1;
...@@ -304,7 +309,7 @@ void autotempShutdown() { ...@@ -304,7 +309,7 @@ void autotempShutdown() {
} }
if (!heating && input < temp) { if (!heating && input < temp) {
if (ms > t1 + 5000) { if (ms > t1 + 5000UL) {
heating = true; heating = true;
t2 = ms; t2 = ms;
t_low = t2 - t1; t_low = t2 - t1;
...@@ -699,7 +704,7 @@ void manage_heater() { ...@@ -699,7 +704,7 @@ void manage_heater() {
if (ct < max(HEATER_0_MINTEMP, 0.01)) min_temp_error(0); if (ct < max(HEATER_0_MINTEMP, 0.01)) min_temp_error(0);
#endif #endif
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || DISABLED(PIDTEMPBED) || HAS(AUTO_FAN) #if ENABLED(THERMAL_PROTECTION_HOTENDS) || ENABLED(THERMAL_PROTECTION_BED) || DISABLED(PIDTEMPBED) || HAS(AUTO_FAN)
millis_t ms = millis(); millis_t ms = millis();
#endif #endif
...@@ -733,9 +738,27 @@ void manage_heater() { ...@@ -733,9 +738,27 @@ void manage_heater() {
#endif // THERMAL_PROTECTION_HOTENDS #endif // THERMAL_PROTECTION_HOTENDS
// Check if the temperature is failing to increase
#if ENABLED(THERMAL_PROTECTION_BED)
// Is it time to check the bed?
if (watch_bed_next_ms && ELAPSED(ms, watch_bed_next_ms)) {
// Has it failed to increase enough?
if (degBed() < watch_target_bed_temp) {
// Stop!
_temp_error(-1, PSTR(SERIAL_T_HEATING_FAILED), PSTR(MSG_HEATING_FAILED_LCD));
}
else {
// Start again if the target is still far off
start_watching_bed();
}
}
#endif // THERMAL_PROTECTION_HOTENDS
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
if (fabs(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) { if (fabs(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) {
_temp_error(0, PSTR(MSG_EXTRUDER_SWITCHED_OFF), PSTR(MSG_ERR_REDUNDANT_TEMP)); _temp_error(0, PSTR(SERIAL_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP));
} }
#endif #endif
...@@ -791,7 +814,7 @@ void manage_heater() { ...@@ -791,7 +814,7 @@ void manage_heater() {
soft_pwm_bed = 0; soft_pwm_bed = 0;
WRITE_HEATER_BED(LOW); WRITE_HEATER_BED(LOW);
} }
#else // BED_LIMIT_SWITCHING #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING
// Check if temperature is within the correct range // Check if temperature is within the correct range
if (current_temperature_bed > BED_MINTEMP && current_temperature_bed < BED_MAXTEMP) { if (current_temperature_bed > BED_MINTEMP && current_temperature_bed < BED_MAXTEMP) {
soft_pwm_bed = current_temperature_bed < target_temperature_bed ? MAX_BED_POWER >> 1 : 0; soft_pwm_bed = current_temperature_bed < target_temperature_bed ? MAX_BED_POWER >> 1 : 0;
...@@ -1226,6 +1249,22 @@ void tp_init() { ...@@ -1226,6 +1249,22 @@ void tp_init() {
} }
#endif #endif
#if ENABLED(THERMAL_PROTECTION_BED)
/**
* Start Heating Sanity Check for bed that are below
* their target temperature by a configurable margin.
* This is called when the temperature is set. (M140, M190)
*/
void start_watching_bed() {
if (degBed() < degTargetBed() - (WATCH_BED_TEMP_INCREASE + TEMP_BED_HYSTERESIS + 1)) {
watch_target_bed_temp = degBed() + WATCH_BED_TEMP_INCREASE;
watch_bed_next_ms = millis() + (WATCH_BED_TEMP_PERIOD) * 1000UL;
}
else
watch_bed_next_ms = 0;
}
#endif
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || ENABLED(THERMAL_PROTECTION_BED) #if ENABLED(THERMAL_PROTECTION_HOTENDS) || ENABLED(THERMAL_PROTECTION_BED)
void thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc) { void thermal_runaway_protection(TRState* state, millis_t* timer, float temperature, float target_temperature, int heater_id, int period_seconds, int hysteresis_degc) {
...@@ -1268,7 +1307,7 @@ void tp_init() { ...@@ -1268,7 +1307,7 @@ void tp_init() {
if (temperature >= tr_target_temperature[heater_index] - hysteresis_degc) if (temperature >= tr_target_temperature[heater_index] - hysteresis_degc)
*timer = millis(); *timer = millis();
// If the timer goes too long without a reset, trigger shutdown // If the timer goes too long without a reset, trigger shutdown
else if (millis() > *timer + period_seconds * 1000UL) else if (ELAPSED(millis(), *timer + period_seconds * 1000UL))
*state = TRRunaway; *state = TRRunaway;
break; break;
case TRRunaway: case TRRunaway:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment