merging with upstream

This commit is contained in:
PavelSindler 2017-08-15 15:24:32 +02:00
parent 6b2470fa4b
commit cdb4cb7864
13 changed files with 12962 additions and 12442 deletions

View File

@ -173,6 +173,10 @@
//if PREVENT_DANGEROUS_EXTRUDE is on, you can still disable (uncomment) very long bits of extrusion separately. //if PREVENT_DANGEROUS_EXTRUDE is on, you can still disable (uncomment) very long bits of extrusion separately.
#define PREVENT_LENGTHY_EXTRUDE #define PREVENT_LENGTHY_EXTRUDE
#ifdef DEBUG_DISABLE_PREVENT_EXTRUDER
#undef PREVENT_DANGEROUS_EXTRUDE
#undef PREVENT_LENGTHY_EXTRUDE
#endif //DEBUG_DISABLE_PREVENT_EXTRUDER
#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. #define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances.
@ -282,9 +286,13 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#define Y_HOME_DIR -1 #define Y_HOME_DIR -1
#define Z_HOME_DIR -1 #define Z_HOME_DIR -1
#ifdef DEBUG_DISABLE_SWLIMITS
#define min_software_endstops false
#define max_software_endstops false
#else
#define min_software_endstops true // If true, axis won't move to coordinates less than HOME_POS. #define min_software_endstops true // If true, axis won't move to coordinates less than HOME_POS.
#define max_software_endstops true // If true, axis won't move to coordinates greater than the defined lengths below. #define max_software_endstops true // If true, axis won't move to coordinates greater than the defined lengths below.
#endif //DEBUG_DISABLE_SWLIMITS
#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS) #define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)

View File

@ -68,7 +68,11 @@
// When first starting the main fan, run it at full speed for the // When first starting the main fan, run it at full speed for the
// given number of milliseconds. This gets the fan spinning reliably // given number of milliseconds. This gets the fan spinning reliably
// before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu) // before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu)
#define FAN_KICKSTART_TIME 1000 // RP: new implementation - long pulse at 100% when starting, short pulse
#define FAN_KICK_START_TIME 800 //when starting from zero (long kick time)
#define FAN_KICK_RUN_MINPWM 25 //PWM treshold for short kicks
#define FAN_KICK_IDLE_TIME 4000 //delay between short kicks
#define FAN_KICK_RUN_TIME 50 //short kick time
@ -312,24 +316,45 @@
#endif #endif
#endif #endif
// extruder advance constant (s2/mm3) /**
// * Implementation of linear pressure control
// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K * cubic mm per second ^ 2 *
// * Assumption: advance = k * (delta velocity)
// Hooke's law says: force = k * distance * K=0 means advance disabled.
// Bernoulli's principle says: v ^ 2 / 2 + g . h + pressure / density = constant * See Marlin documentation for calibration instructions.
// so: v ^ 2 is proportional to number of steps we advance the extruder */
//#define ADVANCE //#define LIN_ADVANCE
#ifdef ADVANCE #ifdef LIN_ADVANCE
#define EXTRUDER_ADVANCE_K .006 #define LIN_ADVANCE_K 0 //Try around 45 for PLA, around 25 for ABS.
#define D_FILAMENT 1.75 /**
#define STEPS_MM_E 174.6 * Some Slicers produce Gcode with randomly jumping extrusion widths occasionally.
#define EXTRUSION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) * For example within a 0.4mm perimeter it may produce a single segment of 0.05mm width.
#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUSION_AREA) * 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.
#endif // ADVANCE *
* 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 // 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
// Arc interpretation settings: // Arc interpretation settings:
#define MM_PER_ARC_SEGMENT 1 #define MM_PER_ARC_SEGMENT 1

View File

@ -96,6 +96,7 @@ void serial_echopair_P(const char *s_P, float v);
void serial_echopair_P(const char *s_P, double v); void serial_echopair_P(const char *s_P, double v);
void serial_echopair_P(const char *s_P, unsigned long v); void serial_echopair_P(const char *s_P, unsigned long v);
extern int selectedSerialPort;
//Things to write to serial from Program memory. Saves 400 to 2k of RAM. //Things to write to serial from Program memory. Saves 400 to 2k of RAM.
FORCE_INLINE void serialprintPGM(const char *str) FORCE_INLINE void serialprintPGM(const char *str)

View File

@ -64,6 +64,23 @@ FORCE_INLINE void store_char(unsigned char c)
store_char(c); store_char(c);
} }
} }
SIGNAL(USART2_RX_vect)
{
if (selectedSerialPort == 1) {
// Test for a framing error.
if (UCSR2A & (1<<FE2)) {
// Characters received with the framing errors will be ignored.
// The temporary variable "c" was made volatile, so the compiler does not optimize this out.
volatile unsigned char c = UDR2;
} else {
// Read the input register.
unsigned char c = UDR2;
store_char(c);
}
}
}
#endif #endif
// Constructors //////////////////////////////////////////////////////////////// // Constructors ////////////////////////////////////////////////////////////////
@ -88,7 +105,7 @@ void MarlinSerial::begin(long baud)
useU2X = false; useU2X = false;
} }
#endif #endif
// set up the first (original serial port)
if (useU2X) { if (useU2X) {
M_UCSRxA = 1 << M_U2Xx; M_UCSRxA = 1 << M_U2Xx;
baud_setting = (F_CPU / 4 / baud - 1) / 2; baud_setting = (F_CPU / 4 / baud - 1) / 2;
@ -104,6 +121,24 @@ void MarlinSerial::begin(long baud)
sbi(M_UCSRxB, M_RXENx); sbi(M_UCSRxB, M_RXENx);
sbi(M_UCSRxB, M_TXENx); sbi(M_UCSRxB, M_TXENx);
sbi(M_UCSRxB, M_RXCIEx); sbi(M_UCSRxB, M_RXCIEx);
// set up the second serial port
if (useU2X) {
UCSR2A = 1 << U2X2;
baud_setting = (F_CPU / 4 / baud - 1) / 2;
} else {
UCSR2A = 0;
baud_setting = (F_CPU / 8 / baud - 1) / 2;
}
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
UBRR2H = baud_setting >> 8;
UBRR2L = baud_setting;
sbi(UCSR2B, RXEN2);
sbi(UCSR2B, TXEN2);
sbi(UCSR2B, RXCIE2);
} }
void MarlinSerial::end() void MarlinSerial::end()
@ -111,6 +146,10 @@ void MarlinSerial::end()
cbi(M_UCSRxB, M_RXENx); cbi(M_UCSRxB, M_RXENx);
cbi(M_UCSRxB, M_TXENx); cbi(M_UCSRxB, M_TXENx);
cbi(M_UCSRxB, M_RXCIEx); cbi(M_UCSRxB, M_RXCIEx);
cbi(UCSR2B, RXEN2);
cbi(UCSR2B, TXEN2);
cbi(UCSR2B, RXCIE2);
} }

View File

@ -73,6 +73,7 @@
// is the index of the location from which to read. // is the index of the location from which to read.
#define RX_BUFFER_SIZE 128 #define RX_BUFFER_SIZE 128
extern int selectedSerialPort;
struct ring_buffer struct ring_buffer
{ {
@ -110,24 +111,48 @@ class MarlinSerial //: public Stream
} }
FORCE_INLINE void checkRx(void) void checkRx(void)
{ {
if((M_UCSRxA & (1<<M_RXCx)) != 0) { if (selectedSerialPort == 0) {
// Test for a framing error. if((M_UCSRxA & (1<<M_RXCx)) != 0) {
if (M_UCSRxA & (1<<M_FEx)) { // Test for a framing error.
// Characters received with the framing errors will be ignored. if (M_UCSRxA & (1<<M_FEx)) {
// The temporary variable "c" was made volatile, so the compiler does not optimize this out. // Characters received with the framing errors will be ignored.
volatile unsigned char c = M_UDRx; // The temporary variable "c" was made volatile, so the compiler does not optimize this out.
} else { volatile unsigned char c = M_UDRx;
unsigned char c = M_UDRx; } else {
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; unsigned char c = M_UDRx;
// if we should be storing the received character into the location int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
// just before the tail (meaning that the head would advance to the // if we should be storing the received character into the location
// current location of the tail), we're about to overflow the buffer // just before the tail (meaning that the head would advance to the
// and so we don't write the character or advance the head. // current location of the tail), we're about to overflow the buffer
if (i != rx_buffer.tail) { // and so we don't write the character or advance the head.
rx_buffer.buffer[rx_buffer.head] = c; if (i != rx_buffer.tail) {
rx_buffer.head = i; rx_buffer.buffer[rx_buffer.head] = c;
rx_buffer.head = i;
}
selectedSerialPort = 0;
}
}
} else if(selectedSerialPort == 1) {
if((UCSR2A & (1<<RXC2)) != 0) {
// Test for a framing error.
if (UCSR2A & (1<<FE2)) {
// Characters received with the framing errors will be ignored.
// The temporary variable "c" was made volatile, so the compiler does not optimize this out.
volatile unsigned char c = UDR2;
} else {
unsigned char c = UDR2;
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != rx_buffer.tail) {
rx_buffer.buffer[rx_buffer.head] = c;
rx_buffer.head = i;
}
selectedSerialPort = 1;
} }
} }
} }

View File

@ -55,6 +55,7 @@
#include "math.h" #include "math.h"
#include "util.h" #include "util.h"
#include <avr/wdt.h>
#ifdef BLINKM #ifdef BLINKM
#include "BlinkM.h" #include "BlinkM.h"
@ -198,6 +199,7 @@
// M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) // M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
// M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal] // M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
// M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ] // M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
// M900 - Set LIN_ADVANCE options, if enabled. See Configuration_adv.h for details.
// M907 - Set digital trimpot motor current using axis codes. // M907 - Set digital trimpot motor current using axis codes.
// M908 - Control digital trimpot directly. // M908 - Control digital trimpot directly.
// M350 - Set microstepping mode. // M350 - Set microstepping mode.
@ -286,6 +288,8 @@ unsigned int custom_message_type;
unsigned int custom_message_state; unsigned int custom_message_state;
char snmm_filaments_used = 0; char snmm_filaments_used = 0;
int selectedSerialPort;
float distance_from_min[3]; float distance_from_min[3];
bool sortAlpha = false; bool sortAlpha = false;
@ -994,8 +998,22 @@ void factory_reset(char level, bool quiet)
// are initialized by the main() routine provided by the Arduino framework. // are initialized by the main() routine provided by the Arduino framework.
void setup() void setup()
{ {
lcd_init();
lcd_print_at_PGM(0, 1, PSTR(" Original Prusa "));
lcd_print_at_PGM(0, 2, PSTR(" 3D Printers "));
setup_killpin(); setup_killpin();
setup_powerhold(); setup_powerhold();
farm_mode = eeprom_read_byte((uint8_t*)EEPROM_FARM_MODE);
EEPROM_read_B(EEPROM_FARM_NUMBER, &farm_no);
//if ((farm_mode == 0xFF && farm_no == 0) || (farm_no == 0xFFFF)) farm_mode = false; //if farm_mode has not been stored to eeprom yet and farm number is set to zero or EEPROM is fresh, deactivate farm mode
if (farm_no == 0xFFFF) farm_no = 0;
if (farm_mode)
{
prusa_statistics(8);
selectedSerialPort = 1;
} else {
selectedSerialPort = 0;
}
MYSERIAL.begin(BAUDRATE); MYSERIAL.begin(BAUDRATE);
SERIAL_PROTOCOLLNPGM("start"); SERIAL_PROTOCOLLNPGM("start");
SERIAL_ECHO_START; SERIAL_ECHO_START;
@ -1050,6 +1068,8 @@ void setup()
tp_init(); // Initialize temperature loop tp_init(); // Initialize temperature loop
plan_init(); // Initialize planner; plan_init(); // Initialize planner;
watchdog_init(); watchdog_init();
lcd_print_at_PGM(0, 1, PSTR(" Original Prusa ")); // we need to do this again for some reason, no time to research
lcd_print_at_PGM(0, 2, PSTR(" 3D Printers "));
st_init(); // Initialize stepper, this enables interrupts! st_init(); // Initialize stepper, this enables interrupts!
setup_photpin(); setup_photpin();
servo_init(); servo_init();
@ -1123,7 +1143,7 @@ void setup()
} }
else else
{ {
_delay_ms(1000); // wait 1sec to display the splash screen //_delay_ms(1000); // wait 1sec to display the splash screen // what's this and why do we need it?? - andre
} }
@ -1192,6 +1212,7 @@ void setup()
eeprom_write_byte((uint8_t*)EEPROM_SD_SORT, 0); eeprom_write_byte((uint8_t*)EEPROM_SD_SORT, 0);
} }
#ifndef DEBUG_DISABLE_STARTMSGS
check_babystep(); //checking if Z babystep is in allowed range check_babystep(); //checking if Z babystep is in allowed range
if (calibration_status() == CALIBRATION_STATUS_ASSEMBLED || if (calibration_status() == CALIBRATION_STATUS_ASSEMBLED ||
@ -1218,6 +1239,7 @@ void setup()
lcd_show_fullscreen_message_and_wait_P(MSG_DEFAULT_SETTINGS_LOADED); lcd_show_fullscreen_message_and_wait_P(MSG_DEFAULT_SETTINGS_LOADED);
} }
#endif //DEBUG_DISABLE_STARTMSGS
lcd_update_enable(true); lcd_update_enable(true);
// Store the currently running firmware into an eeprom, // Store the currently running firmware into an eeprom,
@ -1377,6 +1399,11 @@ void get_command()
rx_buffer_full = true; //sets flag that buffer was full rx_buffer_full = true; //sets flag that buffer was full
} }
char serial_char = MYSERIAL.read(); char serial_char = MYSERIAL.read();
if (selectedSerialPort == 1) {
selectedSerialPort = 0;
MYSERIAL.write(serial_char);
selectedSerialPort = 1;
}
TimeSent = millis(); TimeSent = millis();
TimeNow = millis(); TimeNow = millis();
@ -1618,6 +1645,15 @@ static inline long code_value_long() { return strtol(strchr_pointer+1, NUL
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 float code_value_float() {
char* e = strchr(strchr_pointer, 'E');
if (!e) return strtod(strchr_pointer + 1, NULL);
*e = 0;
float ret = strtod(strchr_pointer + 1, NULL);
*e = 'E';
return ret;
}
#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) \
{ return pgm_read_##reader##_near(p); } { return pgm_read_##reader##_near(p); }
@ -1803,6 +1839,39 @@ static float probe_pt(float x, float y, float z_before) {
#endif // #ifdef ENABLE_AUTO_BED_LEVELING #endif // #ifdef ENABLE_AUTO_BED_LEVELING
#ifdef LIN_ADVANCE
/**
* M900: Set and/or Get advance K factor and WH/D ratio
*
* K<factor> Set advance K factor
* R<ratio> Set ratio directly (overrides WH/D)
* W<width> H<height> D<diam> Set ratio from WH/D
*/
inline void gcode_M900() {
st_synchronize();
const float newK = code_seen('K') ? code_value_float() : -1;
if (newK >= 0) extruder_advance_k = newK;
float newR = code_seen('R') ? code_value_float() : -1;
if (newR < 0) {
const float newD = code_seen('D') ? code_value_float() : -1,
newW = code_seen('W') ? code_value_float() : -1,
newH = code_seen('H') ? code_value_float() : -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_ECHOPGM("Advance K=");
SERIAL_ECHOLN(extruder_advance_k);
SERIAL_ECHOPGM(" E/D=");
const float ratio = advance_ed_ratio;
if (ratio) SERIAL_ECHOLN(ratio); else SERIAL_ECHOLNPGM("Auto");
}
#endif // LIN_ADVANCE
void homeaxis(int axis) { void homeaxis(int axis) {
#define HOMEAXIS_DO(LETTER) \ #define HOMEAXIS_DO(LETTER) \
((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1)) ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
@ -2058,6 +2127,33 @@ void process_commands()
trace(); trace();
prusa_sd_card_upload = true; prusa_sd_card_upload = true;
card.openFile(strchr_pointer+4,false); card.openFile(strchr_pointer+4,false);
} else if (code_seen("SN")) {
if (farm_mode) {
selectedSerialPort = 0;
MSerial.write(";S");
// S/N is:CZPX0917X003XC13518
int numbersRead = 0;
while (numbersRead < 19) {
while (MSerial.available() > 0) {
uint8_t serial_char = MSerial.read();
selectedSerialPort = 1;
MSerial.write(serial_char);
numbersRead++;
selectedSerialPort = 0;
}
}
selectedSerialPort = 1;
MSerial.write('\n');
/*for (int b = 0; b < 3; b++) {
tone(BEEPER, 110);
delay(50);
noTone(BEEPER);
delay(50);
}*/
} else {
MYSERIAL.println("Not in farm mode.");
}
} else if(code_seen("Fir")){ } else if(code_seen("Fir")){
SERIAL_PROTOCOLLN(FW_version); SERIAL_PROTOCOLLN(FW_version);
@ -5360,6 +5456,12 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
} }
break; break;
#ifdef LIN_ADVANCE
case 900: // M900: Set LIN_ADVANCE options.
gcode_M900();
break;
#endif
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
@ -5511,7 +5613,12 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
} }
snmm_filaments_used |= (1 << tmp_extruder); //for stop print snmm_filaments_used |= (1 << tmp_extruder); //for stop print
#ifdef SNMM #ifdef SNMM
snmm_extruder = tmp_extruder; #ifdef LIN_ADVANCE
if (snmm_extruder != tmp_extruder)
clear_current_adv_vars(); //Check if the selected extruder is not the active one and reset LIN_ADVANCE variables if so.
#endif
snmm_extruder = tmp_extruder;
st_synchronize(); st_synchronize();
delay(100); delay(100);
@ -5601,6 +5708,60 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
} }
} // end if(code_seen('T')) (end of T codes) } // end if(code_seen('T')) (end of T codes)
#ifdef DEBUG_DCODES
else if (code_seen('D')) // D codes (debug)
{
switch((int)code_value_uint8())
{
case 0: // D0 - Reset
if (*(strchr_pointer + 1) == 0) break;
MYSERIAL.println("D0 - Reset");
asm volatile("jmp 0x00000");
break;
case 1: // D1 - Clear EEPROM
{
MYSERIAL.println("D1 - Clear EEPROM");
cli();
for (int i = 0; i < 4096; i++)
eeprom_write_byte((unsigned char*)i, (unsigned char)0);
sei();
}
break;
case 2: // D2 - Read/Write PIN
{
if (code_seen('P')) // Pin (0-255)
{
int pin = (int)code_value();
if ((pin >= 0) && (pin <= 255))
{
if (code_seen('F')) // Function in/out (0/1)
{
int fnc = (int)code_value();
if (fnc == 0) pinMode(pin, INPUT);
else if (fnc == 1) pinMode(pin, OUTPUT);
}
if (code_seen('V')) // Value (0/1)
{
int val = (int)code_value();
if (val == 0) digitalWrite(pin, LOW);
else if (val == 1) digitalWrite(pin, HIGH);
}
else
{
int val = (digitalRead(pin) != LOW)?1:0;
MYSERIAL.print("PIN");
MYSERIAL.print(pin);
MYSERIAL.print("=");
MYSERIAL.println(val);
}
}
}
}
break;
}
}
#endif //DEBUG_DCODES
else else
{ {
SERIAL_ECHO_START; SERIAL_ECHO_START;
@ -5674,6 +5835,9 @@ void get_arc_coordinates()
void clamp_to_software_endstops(float target[3]) void clamp_to_software_endstops(float target[3])
{ {
#ifdef DEBUG_DISABLE_SWLIMITS
return;
#endif //DEBUG_DISABLE_SWLIMITS
world2machine_clamp(target[0], target[1]); world2machine_clamp(target[0], target[1]);
// Clamp the Z coordinate. // Clamp the Z coordinate.

View File

@ -126,6 +126,12 @@ float extrude_min_temp=EXTRUDE_MINTEMP;
static char meas_sample; //temporary variable to hold filament measurement sample static char meas_sample; //temporary variable to hold filament measurement sample
#endif #endif
#ifdef LIN_ADVANCE
float extruder_advance_k = LIN_ADVANCE_K,
advance_ed_ratio = LIN_ADVANCE_E_D_RATIO,
position_float[NUM_AXIS] = { 0 };
#endif
// Returns the index of the next block in the ring buffer // Returns the index of the next block in the ring buffer
// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.
static inline int8_t next_block_index(int8_t block_index) { static inline int8_t next_block_index(int8_t block_index) {
@ -411,6 +417,9 @@ 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
#ifdef LIN_ADVANCE
memset(position_float, 0, sizeof(position)); // clear position
#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;
@ -497,25 +506,53 @@ void check_axes_activity()
disable_e2(); disable_e2();
} }
#if defined(FAN_PIN) && FAN_PIN > -1 #if defined(FAN_PIN) && FAN_PIN > -1
#ifdef FAN_KICKSTART_TIME #ifdef FAN_KICK_START_TIME
static unsigned long fan_kick_end; static bool fan_kick = false;
if (tail_fan_speed) { static unsigned long fan_kick_timer = 0;
if (fan_kick_end == 0) { static unsigned char prev_fan_speed = 0;
// Just starting up fan - run at full power. if (tail_fan_speed)
fan_kick_end = millis() + FAN_KICKSTART_TIME; {
tail_fan_speed = 255; if (prev_fan_speed != tail_fan_speed)
} else if (fan_kick_end > millis()) { //speed changed
// Fan still spinning up. if (prev_fan_speed == 0) //prev speed == 0 (starting - long kick)
tail_fan_speed = 255; fan_kick_timer = millis() + FAN_KICK_START_TIME;
} else { else if (tail_fan_speed <= FAN_KICK_RUN_MINPWM) //speed <= max kick speed (short kick)
fan_kick_end = 0; fan_kick_timer = millis() + FAN_KICK_RUN_TIME;
} else //speed > max kick speed (no kick)
#endif//FAN_KICKSTART_TIME fan_kick_timer = 0;
#ifdef FAN_SOFT_PWM prev_fan_speed = tail_fan_speed; //store previous value
fanSpeedSoftPwm = tail_fan_speed; if (fan_kick_timer)
#else fan_kick = true;
analogWrite(FAN_PIN,tail_fan_speed); }
#endif//!FAN_SOFT_PWM else
{
if (fan_kick)
{
if (fan_kick_timer < millis())
{
fan_kick = false;
if (tail_fan_speed <= FAN_KICK_RUN_MINPWM)
fan_kick_timer = millis() + FAN_KICK_IDLE_TIME;
}
}
else if (tail_fan_speed <= FAN_KICK_RUN_MINPWM)
{
if (fan_kick_timer < millis())
{
fan_kick_timer = millis() + FAN_KICK_RUN_TIME;
fan_kick = true;
}
}
}
if (fan_kick)
tail_fan_speed = 255;
}
#endif//FAN_KICKSTART_TIME
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = tail_fan_speed;
#else
analogWrite(FAN_PIN,tail_fan_speed);
#endif//!FAN_SOFT_PWM
#endif//FAN_PIN > -1 #endif//FAN_PIN > -1
#ifdef AUTOTEMP #ifdef AUTOTEMP
getHighESpeed(); getHighESpeed();
@ -676,12 +713,22 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
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
target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);
#ifdef LIN_ADVANCE
const float mm_D_float = sqrt(sq(x - position_float[X_AXIS]) + sq(y - position_float[Y_AXIS]));
float de_float = e - 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
#ifdef 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 +737,10 @@ 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
#ifdef 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 +1163,37 @@ 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;
#ifdef 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)
//
block->use_advance_lead = block->steps_e
&& (block->steps_x || block->steps_y)
&& extruder_advance_k
&& (uint32_t)block->steps_e != block->step_event_count
&& de_float > 0.0;
if (block->use_advance_lead)
block->abs_adv_steps_multiplier8 = lround(
extruder_advance_k
* ((advance_ed_ratio < 0.000001) ? de_float / mm_D_float : advance_ed_ratio) // Use the fixed ratio, if set
* (block->nominal_speed / (float)block->nominal_rate)
* axis_steps_per_unit[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);
@ -1121,6 +1203,12 @@ 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[]
#ifdef LIN_ADVANCE
position_float[X_AXIS] = x;
position_float[Y_AXIS] = y;
position_float[Z_AXIS] = z;
position_float[E_AXIS] = e;
#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).
@ -1179,6 +1267,12 @@ 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]);
#ifdef LIN_ADVANCE
position_float[X_AXIS] = x;
position_float[Y_AXIS] = y;
position_float[Z_AXIS] = z;
position_float[E_AXIS] = e;
#endif
st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[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;

View File

@ -88,8 +88,17 @@ typedef struct {
// Pre-calculated division for the calculate_trapezoid_for_block() routine to run faster. // Pre-calculated division for the calculate_trapezoid_for_block() routine to run faster.
float speed_factor; float speed_factor;
#ifdef LIN_ADVANCE
bool use_advance_lead;
unsigned long abs_adv_steps_multiplier8; // Factorised by 2^8 to avoid float
#endif
} block_t; } block_t;
#ifdef LIN_ADVANCE
extern float extruder_advance_k, advance_ed_ratio;
#endif
#ifdef ENABLE_AUTO_BED_LEVELING #ifdef ENABLE_AUTO_BED_LEVELING
// this holds the required transform to compensate for bed level // this holds the required transform to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix; extern matrix_3x3 plan_bed_level_matrix;

View File

@ -88,6 +88,26 @@ 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};
#ifdef LIN_ADVANCE
uint16_t ADV_NEVER = 65535;
static uint16_t nextMainISR = 0;
static uint16_t nextAdvanceISR = ADV_NEVER;
static uint16_t eISR_Rate = ADV_NEVER;
static volatile int e_steps; //Extrusion steps to be executed by the stepper
static int final_estep_rate; //Speed of extruder at cruising speed
static int current_estep_rate; //The current speed of the extruder
static int current_adv_steps; //The current pretension of filament expressed in steps
#define ADV_RATE(T, L) (e_steps ? (T) * (L) / abs(e_steps) : ADV_NEVER)
#define _NEXT_ISR(T) nextMainISR = T
#else
#define _NEXT_ISR(T) OCR1A = T
#endif
//=========================================================================== //===========================================================================
//=============================functions ============================ //=============================functions ============================
//=========================================================================== //===========================================================================
@ -308,24 +328,27 @@ FORCE_INLINE void trapezoid_generator_reset() {
step_loops_nominal = step_loops; step_loops_nominal = step_loops;
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; _NEXT_ISR(acceleration_time);
// SERIAL_ECHO_START;
// SERIAL_ECHOPGM("advance :");
// SERIAL_ECHO(current_block->advance/256.0);
// SERIAL_ECHOPGM("advance rate :");
// SERIAL_ECHO(current_block->advance_rate/256.0);
// SERIAL_ECHOPGM("initial advance :");
// SERIAL_ECHO(current_block->initial_advance/256.0);
// SERIAL_ECHOPGM("final advance :");
// SERIAL_ECHOLN(current_block->final_advance/256.0);
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
current_estep_rate = ((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
} }
// "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) ISR(TIMER1_COMPA_vect) {
{ #ifdef LIN_ADVANCE
advance_isr_scheduler();
#else
isr();
#endif
}
void isr() {
// 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?
@ -343,13 +366,13 @@ ISR(TIMER1_COMPA_vect)
#ifdef Z_LATE_ENABLE #ifdef Z_LATE_ENABLE
if(current_block->steps_z > 0) { if(current_block->steps_z > 0) {
enable_z(); enable_z();
OCR1A = 2000; //1ms wait _NEXT_ISR(2000); //1ms wait
return; return;
} }
#endif #endif
} }
else { else {
OCR1A=2000; // 1kHz. _NEXT_ISR(2000); // 1kHz.
} }
} }
@ -395,7 +418,7 @@ ISR(TIMER1_COMPA_vect)
CHECK_ENDSTOPS CHECK_ENDSTOPS
{ {
{ {
#if defined(X_MIN_PIN) && X_MIN_PIN > -1 #if defined(X_MIN_PIN) && (X_MIN_PIN > -1) && !defined(DEBUG_DISABLE_XMINLIMIT)
bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING); bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
@ -411,7 +434,7 @@ ISR(TIMER1_COMPA_vect)
CHECK_ENDSTOPS CHECK_ENDSTOPS
{ {
{ {
#if defined(X_MAX_PIN) && X_MAX_PIN > -1 #if defined(X_MAX_PIN) && (X_MAX_PIN > -1) && !defined(DEBUG_DISABLE_XMAXLIMIT)
bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING); bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
@ -431,7 +454,7 @@ ISR(TIMER1_COMPA_vect)
#endif #endif
CHECK_ENDSTOPS CHECK_ENDSTOPS
{ {
#if defined(Y_MIN_PIN) && Y_MIN_PIN > -1 #if defined(Y_MIN_PIN) && (Y_MIN_PIN > -1) && !defined(DEBUG_DISABLE_YMINLIMIT)
bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING); bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
@ -445,7 +468,7 @@ ISR(TIMER1_COMPA_vect)
else { // +direction else { // +direction
CHECK_ENDSTOPS CHECK_ENDSTOPS
{ {
#if defined(Y_MAX_PIN) && Y_MAX_PIN > -1 #if defined(Y_MAX_PIN) && (Y_MAX_PIN > -1) && !defined(DEBUG_DISABLE_YMAXLIMIT)
bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING); bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
@ -467,7 +490,7 @@ ISR(TIMER1_COMPA_vect)
count_direction[Z_AXIS]=-1; count_direction[Z_AXIS]=-1;
if(check_endstops && ! check_z_endstop) if(check_endstops && ! check_z_endstop)
{ {
#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1 #if defined(Z_MIN_PIN) && (Z_MIN_PIN > -1) && !defined(DEBUG_DISABLE_ZMINLIMIT)
bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING); bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
@ -488,7 +511,7 @@ ISR(TIMER1_COMPA_vect)
count_direction[Z_AXIS]=1; count_direction[Z_AXIS]=1;
CHECK_ENDSTOPS CHECK_ENDSTOPS
{ {
#if defined(Z_MAX_PIN) && Z_MAX_PIN > -1 #if defined(Z_MAX_PIN) && (Z_MAX_PIN > -1) && !defined(DEBUG_DISABLE_ZMAXLIMIT)
bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING); bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
@ -501,7 +524,7 @@ ISR(TIMER1_COMPA_vect)
} }
// Supporting stopping on a trigger of the Z-stop induction sensor, not only for the Z-minus movements. // Supporting stopping on a trigger of the Z-stop induction sensor, not only for the Z-minus movements.
#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1 #if defined(Z_MIN_PIN) && (Z_MIN_PIN > -1) && !defined(DEBUG_DISABLE_ZMINLIMIT)
if(check_z_endstop) { if(check_z_endstop) {
// Check the Z min end-stop no matter what. // Check the Z min end-stop no matter what.
// Good for searching for the center of an induction target. // Good for searching for the center of an induction target.
@ -554,6 +577,15 @@ ISR(TIMER1_COMPA_vect)
MSerial.checkRx(); // Check for serial chars. MSerial.checkRx(); // Check for serial chars.
#endif #endif
#ifdef LIN_ADVANCE
counter_e += current_block->steps_e;
if (counter_e > 0) {
counter_e -= current_block->step_event_count;
count_position[E_AXIS] += count_direction[E_AXIS];
((out_bits&(1<<E_AXIS))!=0) ? --e_steps : ++e_steps;
}
#endif
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 +628,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,9 +636,21 @@ 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;
} }
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
const int delta_adv_steps = current_estep_rate - current_adv_steps;
current_adv_steps += delta_adv_steps;
e_steps += delta_adv_steps;
}
// If we have esteps to execute, fire the next advance_isr "now"
if (e_steps) nextAdvanceISR = 0;
#endif
// Calculare new timer value // Calculare new timer value
unsigned short timer; unsigned short timer;
unsigned short step_rate; unsigned short step_rate;
@ -620,8 +665,15 @@ ISR(TIMER1_COMPA_vect)
// step_rate to timer interval // step_rate to timer interval
timer = calc_timer(acc_step_rate); timer = calc_timer(acc_step_rate);
OCR1A = timer; _NEXT_ISR(timer);
acceleration_time += timer; acceleration_time += timer;
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
current_estep_rate = ((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);
@ -639,11 +691,25 @@ ISR(TIMER1_COMPA_vect)
// step_rate to timer interval // step_rate to timer interval
timer = calc_timer(step_rate); timer = calc_timer(step_rate);
OCR1A = timer; _NEXT_ISR(timer);
deceleration_time += timer; deceleration_time += timer;
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
current_estep_rate = ((uint32_t)step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
}
eISR_Rate = ADV_RATE(timer, step_loops);
#endif
} }
else { else {
OCR1A = OCR1A_nominal; #ifdef LIN_ADVANCE
if (current_block->use_advance_lead)
current_estep_rate = final_estep_rate;
eISR_Rate = ADV_RATE(OCR1A_nominal, step_loops_nominal);
#endif
_NEXT_ISR(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;
} }
@ -656,6 +722,69 @@ ISR(TIMER1_COMPA_vect)
} }
} }
#ifdef LIN_ADVANCE
// Timer interrupt for E. e_steps is set in the main routine.
void advance_isr() {
nextAdvanceISR = eISR_Rate;
if (e_steps) {
bool dir =
#ifdef SNMM
((e_steps < 0) == (snmm_extruder & 1))
#else
(e_steps < 0)
#endif
? INVERT_E0_DIR : !INVERT_E0_DIR; //If we have SNMM, reverse every second extruder.
WRITE(E0_DIR_PIN, dir);
for (uint8_t i = step_loops; e_steps && i--;) {
WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
e_steps < 0 ? ++e_steps : --e_steps;
WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN);
}
}
}
void advance_isr_scheduler() {
// 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
if (OCR1A < TCNT1 + 16) OCR1A = TCNT1 + 16;
}
void clear_current_adv_vars() {
e_steps = 0; //Should be already 0 at an filament change event, but just to be sure..
current_adv_steps = 0;
}
#endif // LIN_ADVANCE
void st_init() void st_init()
{ {
digipot_init(); //Initialize Digipot Motor Current digipot_init(); //Initialize Digipot Motor Current
@ -844,6 +973,11 @@ void st_init()
TCNT1 = 0; TCNT1 = 0;
ENABLE_STEPPER_DRIVER_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT();
#ifdef LIN_ADVANCE
e_steps = 0;
current_adv_steps = 0;
#endif
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();
} }

View File

@ -44,6 +44,16 @@ extern bool abort_on_endstop_hit;
// Initialize and start the stepper motor subsystem // Initialize and start the stepper motor subsystem
void st_init(); void st_init();
// Interrupt Service Routines
void isr();
#ifdef LIN_ADVANCE
void advance_isr();
void advance_isr_scheduler();
void clear_current_adv_vars(); //Used to reset the built up pretension and remaining esteps on filament change.
#endif
// Block until all buffered steps are executed // Block until all buffered steps are executed
void st_synchronize(); void st_synchronize();

View File

@ -1303,6 +1303,9 @@ void max_temp_error(uint8_t e) {
} }
void min_temp_error(uint8_t e) { void min_temp_error(uint8_t e) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
disable_heater(); disable_heater();
if(IsStopped() == false) { if(IsStopped() == false) {
SERIAL_ERROR_START; SERIAL_ERROR_START;
@ -1333,6 +1336,9 @@ void bed_max_temp_error(void) {
} }
void bed_min_temp_error(void) { void bed_min_temp_error(void) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
#if HEATER_BED_PIN > -1 #if HEATER_BED_PIN > -1
WRITE(HEATER_BED_PIN, 0); WRITE(HEATER_BED_PIN, 0);
#endif #endif

View File

@ -2046,8 +2046,9 @@ void lcd_diag_show_end_stops()
void prusa_statistics(int _message, uint8_t _fil_nr) { void prusa_statistics(int _message, uint8_t _fil_nr) {
#ifdef DEBUG_DISABLE_PRUSA_STATISTICS
return;
#endif //DEBUG_DISABLE_PRUSA_STATISTICS
switch (_message) switch (_message)
{ {

View File

@ -820,7 +820,11 @@ static void lcd_implementation_status_screen()
lcd_printPGM(PSTR(" ")); lcd_printPGM(PSTR(" "));
//Print status line #ifdef DEBUG_DISABLE_LCD_STATUS_LINE
return;
#endif //DEBUG_DISABLE_LCD_STATUS_LINE
//Print status line
lcd.setCursor(0, 3); lcd.setCursor(0, 3);
// If heating in progress, set flag // If heating in progress, set flag