diff options
Diffstat (limited to 'Sprinter/Sprinter.pde')
-rw-r--r-- | Sprinter/Sprinter.pde | 815 |
1 files changed, 597 insertions, 218 deletions
diff --git a/Sprinter/Sprinter.pde b/Sprinter/Sprinter.pde index 0254a68..6383f22 100644 --- a/Sprinter/Sprinter.pde +++ b/Sprinter/Sprinter.pde @@ -1,6 +1,6 @@ /* Reprap firmware based on Sprinter - Optimize for Sanguinololu 1.2 and above, RAMPS + Optimized for Sanguinololu 1.2 and above / RAMPS 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 @@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* - This firmware is a mashup between Sprinter,grbl and parts from marlin. + This firmware is a mashup between Sprinter, grbl and parts from marlin. (https://github.com/kliment/Sprinter) Changes by Doppler Michael (midopple) @@ -30,9 +30,9 @@ Sprinter Changelog - Look forward function --> calculate 16 Steps forward, get from Firmaware Marlin and Grbl - Stepper control with Timer 1 (Interrupt) - - Extruder heating with PID use a Softpwm (Timer 2) with 500 hz to free Timer1 für Steppercontrol + - Extruder heating with PID use a Softpwm (Timer 2) with 500 hz to free Timer1 for Steppercontrol - command M220 Sxxx --> tune Printing speed online (+/- 50 %) - - G2 / G3 command --> circle funktion + - G2 / G3 command --> circle function - Baudrate set to 250 kbaud - Testet on Sanguinololu Board - M30 Command can delete files on SD Card @@ -42,15 +42,15 @@ Version 1.3.04T - Implement Plannercode from Marlin V1 big thanks to Erik - Stepper interrupt with Step loops - - Stepperfrequenz 30 Khz + - Stepperfrequency 30 Khz - New Command * M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec * M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 - * M205 - advanced settings: minimum travel speed S=while printing T=travel only, X= maximum xy jerk, Z=maximum Z jerk + * M205 - advanced settings: minimum travel speed S=while printing T=travel only, X= maximum xy jerk, Z=maximum Z jerk, E = max E jerk - Remove unused Variables - Check Uart Puffer while circle processing (CMD: G2 / G3) - Fast Xfer Function --> move Text to Flash - - Option to deaktivate ARC (G2/G3) function (save flash) + - Option to deactivate ARC (G2/G3) function (save flash) - Removed modulo (%) operator, which uses an expensive divide Version 1.3.05T @@ -77,7 +77,7 @@ A ';' inside a line ignores just the portion following the ';' character. The beginning of the line is still interpreted. - - Same fix for SD Card, testet and work + - Same fix for SD Card, tested and work Version 1.3.09T - Move SLOWDOWN Function up @@ -94,9 +94,54 @@ - Make fastio & Arduino pin numbering consistent for AT90USB128x. --> Thanks to lincomatic - Select Speedtable with F_CPU - Use same Values for Speedtables as Marlin -- + Version 1.3.12T +- Fixed arc offset. + + Version 1.3.13T +- Extrudemultiply with code M221 Sxxx (S100 original Extrude value) +- use Feedratefactor only when Extrude > 0 +- M106 / M107 can drive the FAN with PWM + Port check for not using Timer 1 +- Added M93 command. Sends current steps for all axis. +- New Option --> FAN_SOFT_PWM, with this option the FAN PWM can use every digital I/O + + Version 1.3.14T +- When endstop is hit count the virtual steps, so the print lose no position when endstop is hit + + Version 1.3.15T +- M206 - set additional homing offset +- Option for minimum FAN start speed --> #define MINIMUM_FAN_START_SPEED 50 (set it to zero to deactivate) + Version 1.3.16T +- Extra Max Feedrate for Retract (MAX_RETRACT_FEEDRATE) + + Version 1.3.17T +- M303 - PID relay autotune possible +- G4 Wait until last move is done + + Version 1.3.18T +- Problem with Thermistor 3 table when sensor is broken and temp is -20 °C + + Version 1.3.19T +- Set maximum acceleration. If "steps per unit" is Change the acc were not recalculated +- Extra Parameter for Max Extruder Jerk +- New Parameter (max_e_jerk) in EEPROM --> Default settings after update ! + + Version 1.3.20T +- fix a few typos and correct english usage +- reimplement homing routine as an inline function +- refactor eeprom routines to make it possible to modify the value of a single parameter +- calculate eeprom parameter addresses based on previous param address plus sizeof(type) +- add 0 C point in Thermistortable 7 + + Version 1.3.21T +- M301 set PID Parameter, and Store to EEPROM +- If no PID is used, deaktivate Variables for PID settings + + Version 1.3.22T +- Error in JERK calculation after G92 command is send, make problems + with Z-Lift function in Slic3r +- Add homing values can shown with M206 D */ @@ -173,6 +218,7 @@ void __cxa_pure_virtual(){}; // or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. // M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default) // M92 - Set axis_steps_per_unit - same syntax as G92 +// M93 - Send axis_steps_per_unit // M115 - Capabilities string // M119 - Show Endstopper State // M140 - Set bed target temp @@ -180,23 +226,30 @@ void __cxa_pure_virtual(){}; // M201 - Set maximum acceleration in units/s^2 for print moves (M201 X1000 Y1000) // M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec // M203 - Set temperture monitor to Sx -// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 -// M205 - advanced settings: minimum travel speed S=while printing T=travel only, X= maximum xy jerk, Z=maximum Z jerk +// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) in mm/sec^2 +// M205 - advanced settings: minimum travel speed S=while printing T=travel only, X=maximum xy jerk, Z=maximum Z jerk +// M206 - set additional homing offset + +// M220 - set speed factor override percentage S=factor in percent +// M221 - set extruder multiply factor S100 --> original Extrude Speed + +// M301 - Set PID parameters P I and D +// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C) -// M220 - set speed factor override percentage S:factor in percent +// M400 - Finish all moves // M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). +// M501 - reads parameters from EEPROM (if you need to reset them after you changed them temporarily). // M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. // M503 - Print settings // Debug feature / Testing the PID for Hotend -// M601 - Show Temp jitter from Extruder (min / max value from Hotend Temperatur while printing) -// M602 - Reset Temp jitter from Extruder (min / max val) --> Dont use it while Printing +// M601 - Show Temp jitter from Extruder (min / max value from Hotend Temperature while printing) +// M602 - Reset Temp jitter from Extruder (min / max val) --> Don't use it while Printing // M603 - Show Free Ram -#define _VERSION_TEXT "1.3.11T / 19.03.2012" +#define _VERSION_TEXT "1.3.22T / 20.08.2012" //Stepper Movement Variables char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; @@ -210,6 +263,11 @@ float move_acceleration = _ACCELERATION; // Normal acceleration mm/s^2 float retract_acceleration = _RETRACT_ACCELERATION; // Normal acceleration mm/s^2 float max_xy_jerk = _MAX_XY_JERK; float max_z_jerk = _MAX_Z_JERK; +float max_e_jerk = _MAX_E_JERK; +unsigned long min_seg_time = _MIN_SEG_TIME; +#ifdef PIDTEMP + unsigned int PID_Kp = PID_PGAIN, PID_Ki = PID_IGAIN, PID_Kd = PID_DGAIN; +#endif long max_acceleration_units_per_sq_second[4] = _MAX_ACCELERATION_UNITS_PER_SQ_SECOND; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts @@ -228,16 +286,21 @@ unsigned long plateau_steps; //unsigned long steps_per_sqr_second; -//adjustable feed faktor for online tuning printerspeed -volatile int feedmultiply=100; //100->original / 200-> Faktor 2 / 50 -> Faktor 0.5 +//adjustable feed factor for online tuning printer speed +volatile int feedmultiply=100; //100->original / 200 -> Factor 2 / 50 -> Factor 0.5 int saved_feedmultiply; volatile bool feedmultiplychanged=false; +volatile int extrudemultiply=100; //100->1 200->2 //boolean acceleration_enabled = false, accelerating = false; //unsigned long interval; float destination[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0}; float current_position[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0}; +float add_homing[3]={0,0,0}; +static unsigned short virtual_steps_x = 0; +static unsigned short virtual_steps_y = 0; +static unsigned short virtual_steps_z = 0; bool home_all_axis = true; //unsigned ?? ToDo: Check @@ -260,7 +323,7 @@ bool is_homing = false; #ifdef USE_ARC_FUNCTION -//For arc centerpont, send bei Command G2/G3 +//For arc center point coordinates, sent by commands G2/G3 float offset[3] = {0.0, 0.0, 0.0}; #endif @@ -275,6 +338,12 @@ float offset[3] = {0.0, 0.0, 0.0}; float osc_wait_remainder = 0.0; #endif +#if (MINIMUM_FAN_START_SPEED > 0) + unsigned char fan_last_speed = 0; + unsigned char fan_org_start_speed = 0; + unsigned long previous_millis_fan_start = 0; +#endif + // comm variables and Commandbuffer // BUFSIZE is reduced from 8 to 6 to free more RAM for the PLANNER #define MAX_CMD_SIZE 96 @@ -305,7 +374,7 @@ unsigned long previous_millis_cmd = 0; unsigned long max_inactive_time = 0; unsigned long stepper_inactive_time = 0; -//Temp Montor for repetier +//Temp Monitor for repetier unsigned char manage_monitor = 255; @@ -562,8 +631,8 @@ int FreeRam1(void) void analogWrite_check(uint8_t check_pin, int val) { #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - //Atmega168 / 328 can not useed OCR1A and OCR1B - //This are PINS PB1 / PB2 or on Ardurino D9 / D10 + //Atmega168/328 can't use OCR1A and OCR1B + //These are pins PB1/PB2 or on Arduino D9/D10 if((check_pin != 9) && (check_pin != 10)) { analogWrite(check_pin, val); @@ -571,8 +640,8 @@ void analogWrite_check(uint8_t check_pin, int val) #endif #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - //Atmega664P / 1284P can not useed OCR1A and OCR1B - //This are PINS PD4 / PD5 or on Ardurino D12 / D13 + //Atmega664P/1284P can't use OCR1A and OCR1B + //These are pins PD4/PD5 or on Arduino D12/D13 if((check_pin != 12) && (check_pin != 13)) { analogWrite(check_pin, val); @@ -580,8 +649,8 @@ void analogWrite_check(uint8_t check_pin, int val) #endif #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - //Atmega1280 / 2560 can not useed OCR1A, OCR1B and OCR1C - //This are PINS PB5,PB6,PB7 or on Ardurino D11,D12,and D13 + //Atmega1280/2560 can't use OCR1A, OCR1B and OCR1C + //These are pins PB5,PB6,PB7 or on Arduino D11,D12 and D13 if((check_pin != 11) && (check_pin != 12) && (check_pin != 13)) { analogWrite(check_pin, val); @@ -657,6 +726,10 @@ void setup() SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan #endif + #ifdef EXTRUDERFAN_PIN + SET_OUTPUT(EXTRUDERFAN_PIN); //Set pin used for extruder cooling fan + #endif + //endstops and pullups #ifdef ENDSTOPPULLUPS #if X_MIN_PIN > -1 @@ -744,10 +817,7 @@ void setup() SET_OUTPUT(E_STEP_PIN); #endif - for(int8_t i=0; i < NUM_AXIS; i++) - { - axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; - } + // for(int i=0; i < NUM_AXIS; i++){ // axis_max_interval[i] = 100000000.0 / (max_start_speed_units_per_second[i] * axis_steps_per_unit[i]); @@ -782,7 +852,7 @@ void setup() #endif - #ifdef PID_SOFT_PWM + #if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1)) showString(PSTR("Soft PWM Init\r\n")); init_Timer2_softpwm(); #endif @@ -798,6 +868,10 @@ void setup() //second value --> Print settings to UART EEPROM_RetrieveSettings(false,false); #endif + + #ifdef PIDTEMP + updatePID(); + #endif //Free Ram showString(PSTR("Free Ram: ")); @@ -808,6 +882,12 @@ void setup() Serial.print((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); showString(PSTR(" / ")); Serial.println(BLOCK_BUFFER_SIZE); + + for(int8_t i=0; i < NUM_AXIS; i++) + { + axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; + } + } @@ -856,6 +936,10 @@ void loop() //check heater every n milliseconds manage_heater(); manage_inactivity(1); + #if (MINIMUM_FAN_START_SPEED > 0) + manage_fan_start_speed(); + #endif + } //------------------------------------------------ @@ -875,10 +959,10 @@ void check_buffer_while_arc() //------------------------------------------------ void get_command() { - while( Serial.available() > 0 && buflen < BUFSIZE) + while( Serial.available() > 0 && buflen < BUFSIZE) { serial_char = Serial.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + if(serial_char == '\n' || serial_char == '\r' || (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) ) { if(!serial_count) { //if empty line comment_mode = false; // for new command @@ -984,12 +1068,12 @@ void get_command() { return; } - while( filesize > sdpos && buflen < BUFSIZE) + while( filesize > sdpos && buflen < BUFSIZE) { serial_char = file.read(); read_char_int = (int)serial_char; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || read_char_int == -1) + if(serial_char == '\n' || serial_char == '\r' || (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) || read_char_int == -1) { sdpos = file.curPosition(); if(sdpos >= filesize) @@ -1042,6 +1126,67 @@ FORCE_INLINE bool code_seen(char code) return (strchr_pointer != NULL); //Return True if a character was found } +FORCE_INLINE void homing_routine(char axis) +{ + int min_pin, max_pin, home_dir, max_length, home_bounce; + + switch(axis){ + case X_AXIS: + min_pin = X_MIN_PIN; + max_pin = X_MAX_PIN; + home_dir = X_HOME_DIR; + max_length = X_MAX_LENGTH; + home_bounce = 10; + break; + case Y_AXIS: + min_pin = Y_MIN_PIN; + max_pin = Y_MAX_PIN; + home_dir = Y_HOME_DIR; + max_length = Y_MAX_LENGTH; + home_bounce = 10; + break; + case Z_AXIS: + min_pin = Z_MIN_PIN; + max_pin = Z_MAX_PIN; + home_dir = Z_HOME_DIR; + max_length = Z_MAX_LENGTH; + home_bounce = 4; + break; + default: + //never reached + break; + } + + if ((min_pin > -1 && home_dir==-1) || (max_pin > -1 && home_dir==1)) + { + current_position[axis] = -1.5 * max_length * home_dir; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = 0; + feedrate = homing_feedrate[axis]; + prepare_move(); + st_synchronize(); + + current_position[axis] = home_bounce/2 * home_dir; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = 0; + prepare_move(); + st_synchronize(); + + current_position[axis] = -home_bounce * home_dir; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = 0; + feedrate = homing_feedrate[axis]/2; + prepare_move(); + st_synchronize(); + + current_position[axis] = (home_dir == -1) ? 0 : max_length; + current_position[axis] += add_homing[axis]; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = current_position[axis]; + feedrate = 0; + } +} + //------------------------------------------------ // CHECK COMMAND AND CONVERT VALUES //------------------------------------------------ @@ -1084,6 +1229,7 @@ FORCE_INLINE void process_commands() if(code_seen('P')) codenum = code_value(); // milliseconds to wait if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait codenum += millis(); // keep track of when we started waiting + st_synchronize(); // wait for all movements to finish while(millis() < codenum ){ manage_heater(); } @@ -1107,102 +1253,13 @@ FORCE_INLINE void process_commands() home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) - { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)) - { - st_synchronize(); - current_position[X_AXIS] = -1.5 * X_MAX_LENGTH * X_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = 0; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - - st_synchronize(); - current_position[X_AXIS] = 5 * X_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = 0; - prepare_move(); - - st_synchronize(); - current_position[X_AXIS] = -10 * X_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = 0; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - st_synchronize(); - - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0; - } - } - //showString(PSTR("HOME X AXIS\r\n")); + homing_routine(X_AXIS); if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) - { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)) - { - current_position[Y_AXIS] = -1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = 0; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); - st_synchronize(); - - current_position[Y_AXIS] = 5 * Y_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = 0; - prepare_move(); - st_synchronize(); - - current_position[Y_AXIS] = -10 * Y_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = 0; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); - st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0; - } - } - //showString(PSTR("HOME Y AXIS\r\n")); + homing_routine(Y_AXIS); if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) - { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)) - { - current_position[Z_AXIS] = -1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 0; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); - st_synchronize(); - - current_position[Z_AXIS] = 2 * Z_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 0; - prepare_move(); - st_synchronize(); - - current_position[Z_AXIS] = -3 * Z_HOME_DIR; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 0; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); - st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0; - } - } - - //showString(PSTR("HOME Z AXIS\r\n")); + homing_routine(Z_AXIS); #ifdef ENDSTOPS_ONLY_FOR_HOMING enable_endstops(false); @@ -1385,6 +1442,9 @@ FORCE_INLINE void process_commands() case 42: //M42 -Change pin status via gcode if (code_seen('S')) { +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif int pin_status = code_value(); if (code_seen('P') && pin_status >= 0 && pin_status <= 255) { @@ -1408,6 +1468,9 @@ FORCE_INLINE void process_commands() } break; case 104: // M104 +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif if (code_seen('S')) target_raw = temp2analogh(target_temp = code_value()); #ifdef WATCHPERIOD if(target_raw > current_raw) @@ -1422,6 +1485,9 @@ FORCE_INLINE void process_commands() #endif break; case 140: // M140 set bed temp +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif #if TEMP_1_PIN > -1 || defined BED_USES_AD595 if (code_seen('S')) target_bed_raw = temp2analogBed(code_value()); #endif @@ -1464,6 +1530,9 @@ FORCE_INLINE void process_commands() return; //break; case 109: { // M109 - Wait for extruder heater to reach target. +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif if (code_seen('S')) target_raw = temp2analogh(target_temp = code_value()); #ifdef WATCHPERIOD if(target_raw>current_raw) @@ -1498,6 +1567,9 @@ FORCE_INLINE void process_commands() codenum = millis(); } manage_heater(); + #if (MINIMUM_FAN_START_SPEED > 0) + manage_fan_start_speed(); + #endif #ifdef TEMP_RESIDENCY_TIME /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time or when current temp falls outside the hysteresis after target temp was reached */ @@ -1510,7 +1582,10 @@ FORCE_INLINE void process_commands() } } break; - case 190: // M190 - Wait bed for heater to reach target. + case 190: // M190 - Wait for bed heater to reach target temperature. +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif #if TEMP_1_PIN > -1 if (code_seen('S')) target_bed_raw = temp2analogBed(code_value()); codenum = millis(); @@ -1526,25 +1601,64 @@ FORCE_INLINE void process_commands() codenum = millis(); } manage_heater(); + #if (MINIMUM_FAN_START_SPEED > 0) + manage_fan_start_speed(); + #endif } #endif break; #if FAN_PIN > -1 case 106: //M106 Fan On +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif if (code_seen('S')) { - WRITE(FAN_PIN, HIGH); - analogWrite_check(FAN_PIN, constrain(code_value(),0,255) ); + unsigned char l_fan_code_val = constrain(code_value(),0,255); + + #if (MINIMUM_FAN_START_SPEED > 0) + if(l_fan_code_val > 0 && fan_last_speed == 0) + { + if(l_fan_code_val < MINIMUM_FAN_START_SPEED) + { + fan_org_start_speed = l_fan_code_val; + l_fan_code_val = MINIMUM_FAN_START_SPEED; + previous_millis_fan_start = millis(); + } + fan_last_speed = l_fan_code_val; + } + else + { + fan_last_speed = l_fan_code_val; + fan_org_start_speed = 0; + } + #endif + + #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1) + g_fan_pwm_val = l_fan_code_val; + #else + WRITE(FAN_PIN, HIGH); + analogWrite_check(FAN_PIN, l_fan_code_val; + #endif + } else { - WRITE(FAN_PIN, HIGH); - analogWrite_check(FAN_PIN, 255 ); + #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1) + g_fan_pwm_val = 255; + #else + WRITE(FAN_PIN, HIGH); + analogWrite_check(FAN_PIN, 255 ); + #endif } break; case 107: //M107 Fan Off - analogWrite_check(FAN_PIN, 0); - WRITE(FAN_PIN, LOW); + #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1) + g_fan_pwm_val = 0; + #else + analogWrite_check(FAN_PIN, 0); + WRITE(FAN_PIN, LOW); + #endif break; #endif #if (PS_ON_PIN > -1) @@ -1552,6 +1666,9 @@ FORCE_INLINE void process_commands() SET_OUTPUT(PS_ON_PIN); //GND break; case 81: // M81 - ATX Power Off +#ifdef CHAIN_OF_COMMAND + st_synchronize(); // wait for all movements to finish +#endif SET_INPUT(PS_ON_PIN); //Floating break; #endif @@ -1567,6 +1684,13 @@ FORCE_INLINE void process_commands() { stepper_inactive_time = code_value() * 1000; } + else if(code_seen('T')) + { + enable_x(); + enable_y(); + enable_z(); + enable_e(); + } else { disable_x(); @@ -1582,7 +1706,11 @@ FORCE_INLINE void process_commands() case 92: // M92 for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + if(code_seen(axis_codes[i])) + { + axis_steps_per_unit[i] = code_value(); + axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; + } } // Update start speed intervals and axis order. TODO: refactor axis_max_interval[] calculation into a function, as it @@ -1594,6 +1722,17 @@ FORCE_INLINE void process_commands() // all steps_per_unit related variables // } break; + case 93: // M93 show current axis steps. + showString(PSTR("ok ")); + showString(PSTR("X:")); + Serial.print(axis_steps_per_unit[0]); + showString(PSTR("Y:")); + Serial.print(axis_steps_per_unit[1]); + showString(PSTR("Z:")); + Serial.print(axis_steps_per_unit[2]); + showString(PSTR("E:")); + Serial.println(axis_steps_per_unit[3]); + break; case 115: // M115 showString(PSTR("FIRMWARE_NAME: Sprinter Experimental PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\r\n")); //Serial.println(uuid); @@ -1639,7 +1778,7 @@ FORCE_INLINE void process_commands() showString(PSTR("\r\n")); break; - case 201: // M201 + case 201: // M201 Set maximum acceleration in units/s^2 for print moves (M201 X1000 Y1000) for(int8_t i=0; i < NUM_AXIS; i++) { @@ -1669,28 +1808,74 @@ FORCE_INLINE void process_commands() if(code_seen('S')) manage_monitor = code_value(); if(manage_monitor==100) manage_monitor=1; // Set 100 to heated bed break; - case 204: // M204 acclereration S normal moves T filmanent only moves + case 204: // M204 acceleration S normal moves T filmanent only moves if(code_seen('S')) move_acceleration = code_value() ; if(code_seen('T')) retract_acceleration = code_value() ; break; - case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk + case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E= max E jerk if(code_seen('S')) minimumfeedrate = code_value(); if(code_seen('T')) mintravelfeedrate = code_value(); //if(code_seen('B')) minsegmenttime = code_value() ; if(code_seen('X')) max_xy_jerk = code_value() ; if(code_seen('Z')) max_z_jerk = code_value() ; + if(code_seen('E')) max_e_jerk = code_value() ; + break; + case 206: // M206 additional homing offset + if(code_seen('D')) + { + showString(PSTR("Addhome X:")); Serial.print(add_homing[0]); + showString(PSTR(" Y:")); Serial.print(add_homing[1]); + showString(PSTR(" Z:")); Serial.println(add_homing[2]); + } + + for(int8_t cnt_i=0; cnt_i < 3; cnt_i++) + { + if(code_seen(axis_codes[cnt_i])) add_homing[cnt_i] = code_value(); + } break; case 220: // M220 S<factor in percent>- set speed factor override percentage { if(code_seen('S')) { feedmultiply = code_value() ; - if(feedmultiply < 20) feedmultiply = 20; - if(feedmultiply > 200) feedmultiply = 200; + feedmultiply = constrain(feedmultiply, 20, 200); feedmultiplychanged=true; } } break; + case 221: // M221 S<factor in percent>- set extrude factor override percentage + { + if(code_seen('S')) + { + extrudemultiply = code_value() ; + extrudemultiply = constrain(extrudemultiply, 40, 200); + } + } + break; +#ifdef PIDTEMP + case 301: // M301 + { + if(code_seen('P')) PID_Kp = code_value(); + if(code_seen('I')) PID_Ki = code_value(); + if(code_seen('D')) PID_Kd = code_value(); + updatePID(); + } + break; +#endif //PIDTEMP +#ifdef PID_AUTOTUNE + case 303: // M303 PID autotune + { + float help_temp = 150.0; + if (code_seen('S')) help_temp=code_value(); + PID_autotune(help_temp); + } + break; +#endif + case 400: // M400 finish all moves + { + st_synchronize(); + } + break; #ifdef USE_EEPROM_SETTINGS case 500: // Store settings in EEPROM { @@ -1700,11 +1885,19 @@ FORCE_INLINE void process_commands() case 501: // Read settings from EEPROM { EEPROM_RetrieveSettings(false,true); + for(int8_t i=0; i < NUM_AXIS; i++) + { + axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; + } } break; case 502: // Revert to default settings { EEPROM_RetrieveSettings(true,true); + for(int8_t i=0; i < NUM_AXIS; i++) + { + axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; + } } break; case 503: // print settings currently in memory @@ -1796,15 +1989,26 @@ FORCE_INLINE void get_coordinates() } #ifdef USE_ARC_FUNCTION -FORCE_INLINE void get_arc_coordinates() +void get_arc_coordinates() { get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); + if(code_seen('I')) { + offset[0] = code_value(); + } + else { + offset[0] = 0.0; + } + if(code_seen('J')) { + offset[1] = code_value(); + } + else { + offset[1] = 0.0; + } } #endif + void prepare_move() { long help_feedrate = 0; @@ -1824,8 +2028,16 @@ void prepare_move() if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; } } + + if(destination[E_AXIS] > current_position[E_AXIS]) + { + help_feedrate = ((long)feedrate*(long)feedmultiply); + } + else + { + help_feedrate = ((long)feedrate*(long)100); + } - help_feedrate = ((long)feedrate*(long)feedmultiply); plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], help_feedrate/6000.0); for(int i=0; i < NUM_AXIS; i++) @@ -1842,8 +2054,15 @@ void prepare_arc_move(char isclockwise) float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc long help_feedrate = 0; - - help_feedrate = ((long)feedrate*(long)feedmultiply); + if(destination[E_AXIS] > current_position[E_AXIS]) + { + help_feedrate = ((long)feedrate*(long)feedmultiply); + } + else + { + help_feedrate = ((long)feedrate*(long)100); + } + // Trace the arc mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, help_feedrate/6000.0, r, isclockwise); @@ -1892,8 +2111,27 @@ FORCE_INLINE void manage_inactivity(byte debug) check_axes_activity(); } - - +#if (MINIMUM_FAN_START_SPEED > 0) +void manage_fan_start_speed(void) +{ + if(fan_org_start_speed > 0) + { + if((millis() - previous_millis_fan_start) > MINIMUM_FAN_START_TIME ) + { + #if FAN_PIN > -1 + #if defined(FAN_SOFT_PWM) + g_fan_pwm_val = fan_org_start_speed; + #else + WRITE(FAN_PIN, HIGH); + analogWrite_check(FAN_PIN, fan_org_start_speed; + #endif + #endif + + fan_org_start_speed = 0; + } + } +} +#endif // Planner with Interrupt for Stepper @@ -1957,6 +2195,7 @@ static int8_t prev_block_index(int8_t block_index) { static long position[4]; static float previous_speed[4]; // Speed of previous path line segment static float previous_nominal_speed; // Nominal speed of previous path line segment +static unsigned char G92_reset_previous_speed = 0; // Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the @@ -2008,7 +2247,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // have to use intersection_distance() to calculate when to abort acceleration and start braking + // have to use intersection_distance() to calculate when to abort acceleration and start breaking // in order to reach the final_rate exactly at the end of this block. if (plateau_steps < 0) { accelerate_steps = ceil( @@ -2083,10 +2322,17 @@ void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *n // implements the reverse pass. void planner_reverse_pass() { uint8_t block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + + //Make a local copy of block_buffer_tail, because the interrupt can alter it + CRITICAL_SECTION_START; + unsigned char tail = block_buffer_tail; + CRITICAL_SECTION_END; + + if(((block_buffer_head-tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) + { block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); block_t *block[3] = { NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { + while(block_index != tail) { block_index = prev_block_index(block_index); block[2]= block[1]; block[1]= block[0]; @@ -2252,6 +2498,9 @@ void check_axes_activity() { float junction_deviation = 0.1; +float max_E_feedrate_calc = MAX_RETRACT_FEEDRATE; +bool retract_feedrate_aktiv = false; + // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. @@ -2265,6 +2514,9 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) while(block_buffer_tail == next_buffer_head) { manage_heater(); manage_inactivity(1); + #if (MINIMUM_FAN_START_SPEED > 0) + manage_fan_start_speed(); + #endif } // The target position of the tool in absolute steps @@ -2287,6 +2539,8 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->steps_e *= extrudemultiply; + block->steps_e /= 100; block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); // Bail if this is a zero-length block @@ -2297,7 +2551,25 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<<X_AXIS); } if (target[Y_AXIS] < position[Y_AXIS]) { block->direction_bits |= (1<<Y_AXIS); } if (target[Z_AXIS] < position[Z_AXIS]) { block->direction_bits |= (1<<Z_AXIS); } - if (target[E_AXIS] < position[E_AXIS]) { block->direction_bits |= (1<<E_AXIS); } + if (target[E_AXIS] < position[E_AXIS]) + { + block->direction_bits |= (1<<E_AXIS); + //High Feedrate for retract + max_E_feedrate_calc = MAX_RETRACT_FEEDRATE; + retract_feedrate_aktiv = true; + } + else + { + if(retract_feedrate_aktiv) + { + if(block->steps_e > 0) + retract_feedrate_aktiv = false; + } + else + { + max_E_feedrate_calc = max_feedrate[E_AXIS]; + } + } #ifdef DELAY_ENABLE @@ -2311,12 +2583,12 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) enable_y(); delayMicroseconds(DELAY_ENABLE); } - if(if(block->steps_z != 0)) + if(block->steps_z != 0) { enable_z(); delayMicroseconds(DELAY_ENABLE); } - if(if(block->steps_e != 0)) + if(block->steps_e != 0) { enable_e(); delayMicroseconds(DELAY_ENABLE); @@ -2336,7 +2608,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) if(feed_rate<minimumfeedrate) feed_rate=minimumfeedrate; } - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + // slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); #ifdef SLOWDOWN if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); @@ -2346,7 +2618,8 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + //delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*extrudemultiply/100.0; if ( block->steps_x <= dropsegments && block->steps_y <= dropsegments && block->steps_z <= dropsegments ) { block->millimeters = fabs(delta_mm[E_AXIS]); @@ -2381,32 +2654,24 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) */ - // Calculate speed in mm/sec for each axis + // Calculate and limit speed in mm/sec for each axis float current_speed[4]; - for(int i=0; i < 4; i++) { - current_speed[i] = delta_mm[i] * inverse_second; - } - - // Limit speed per axis float speed_factor = 1.0; //factor <=1 do decrease speed - for(int i=0; i < 4; i++) { + for(int i=0; i < 3; i++) + { + current_speed[i] = delta_mm[i] * inverse_second; if(fabs(current_speed[i]) > max_feedrate[i]) speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i])); } + + current_speed[E_AXIS] = delta_mm[E_AXIS] * inverse_second; + if(fabs(current_speed[E_AXIS]) > max_E_feedrate_calc) + speed_factor = min(speed_factor, max_E_feedrate_calc / fabs(current_speed[E_AXIS])); + // Correct the speed - if( speed_factor < 1.0) { -// Serial.print("speed factor : "); Serial.println(speed_factor); - for(int i=0; i < 4; i++) { - if(fabs(current_speed[i]) > max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i])); - /* - if(speed_factor < 0.1) { - Serial.print("speed factor : "); Serial.println(speed_factor); - Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); - } - */ - } + if( speed_factor < 1.0) + { for(unsigned char i=0; i < 4; i++) { current_speed[i] *= speed_factor; } @@ -2475,25 +2740,42 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) } #endif // Start with a safe speed - float vmax_junction = max_xy_jerk/2; + float vmax_junction = max_xy_jerk/2; + float vmax_junction_factor = 1.0; + if(fabs(current_speed[Z_AXIS]) > max_z_jerk/2) - vmax_junction = max_z_jerk/2; + vmax_junction = min(vmax_junction, max_z_jerk/2); + + if(fabs(current_speed[E_AXIS]) > max_e_jerk/2) + vmax_junction = min(vmax_junction, max_e_jerk/2); + + if(G92_reset_previous_speed == 1) + { + vmax_junction = 0.1; + G92_reset_previous_speed = 0; + } + vmax_junction = min(vmax_junction, block->nominal_speed); + float safe_speed = vmax_junction; - if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { + if ((moves_queued > 1) && (previous_nominal_speed > 0.0001)) { float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); - if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { - vmax_junction = block->nominal_speed; - } + // if((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) { + vmax_junction = block->nominal_speed; + // } if (jerk > max_xy_jerk) { - vmax_junction *= (max_xy_jerk/jerk); + vmax_junction_factor = (max_xy_jerk/jerk); } if(fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { - vmax_junction *= (max_z_jerk/fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); + vmax_junction_factor= min(vmax_junction_factor, (max_z_jerk/fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]))); } + if(fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) { + vmax_junction_factor = min(vmax_junction_factor, (max_e_jerk/fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]))); + } + vmax_junction = min(previous_nominal_speed, vmax_junction * vmax_junction_factor); // Limit speed to max previous speed } block->max_entry_speed = vmax_junction; - + // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); block->entry_speed = min(vmax_junction, v_allowable); @@ -2506,10 +2788,14 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) // block nominal speed limits both the current and next maximum junction speeds. Hence, in both // the reverse and forward planners, the corresponding block junction speed will always be at the // the maximum junction speed and may always be ignored for any speed reduction checks. - if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } - else { block->nominal_length_flag = false; } + if (block->nominal_speed <= v_allowable) { + block->nominal_length_flag = true; + } + else { + block->nominal_length_flag = false; + } block->recalculate_flag = true; // Always calculate trapezoid for new block - + // Update previous path unit_vector and nominal speed memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] previous_nominal_speed = block->nominal_speed; @@ -2536,10 +2822,8 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) #endif // ADVANCE - - calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, - MINIMUM_PLANNER_SPEED/block->nominal_speed); + safe_speed/block->nominal_speed); // Move buffer head block_buffer_head = next_buffer_head; @@ -2554,6 +2838,12 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) st_wake_up(); } +int calc_plannerpuffer_fill(void) +{ + int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + return(moves_queued); +} + void plan_set_position(float x, float y, float z, float e) { position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); @@ -2561,11 +2851,17 @@ void plan_set_position(float x, float y, float z, float e) position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + virtual_steps_x = 0; + virtual_steps_y = 0; + virtual_steps_z = 0; + previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. previous_speed[0] = 0.0; previous_speed[1] = 0.0; previous_speed[2] = 0.0; previous_speed[3] = 0.0; + + G92_reset_previous_speed = 1; } #ifdef AUTOTEMP @@ -2577,16 +2873,19 @@ void getHighESpeed() if((target_temp+2) < autotemp_min) //probably temperature set to zero. return; //do nothing - float high=0; + float high=0.0; uint8_t block_index = block_buffer_tail; - while(block_index != block_buffer_head) - { - float se=block_buffer[block_index].steps_e/float(block_buffer[block_index].step_event_count)*block_buffer[block_index].nominal_rate; - //se; units steps/sec; - if(se>high) - { - high=se; + while(block_index != block_buffer_head) { + if((block_buffer[block_index].steps_x != 0) || + (block_buffer[block_index].steps_y != 0) || + (block_buffer[block_index].steps_z != 0)) { + float se=(float(block_buffer[block_index].steps_e)/float(block_buffer[block_index].step_event_count))*block_buffer[block_index].nominal_speed; + //se; units steps/sec; + if(se>high) + { + high=se; + } } block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); } @@ -2611,7 +2910,6 @@ void getHighESpeed() - // Stepper // intRes = intIn1 * intIn2 >> 16 @@ -2711,7 +3009,7 @@ static unsigned long step_events_completed; // The number of step events execute static short e_steps; static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; -static unsigned short acc_step_rate; // needed for deccelaration start point +static unsigned short acc_step_rate; // needed for deceleration start point static char step_loops; static unsigned short OCR1A_nominal; @@ -2739,7 +3037,7 @@ static bool old_z_max_endstop=false; // // time -----> // -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// The trapezoid is the shape of the speed curve over time. It starts at block->initial_rate, accelerates // first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. // The slope of acceleration is calculated with the leib ramp alghorithm. @@ -2840,7 +3138,7 @@ ISR(TIMER1_COMPA_vect) // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt out_bits = current_block->direction_bits; - // Set direction en check limit switches + // Set direction and check limit switches if ((out_bits & (1<<X_AXIS)) != 0) { // -direction WRITE(X_DIR_PIN, INVERT_X_DIR); CHECK_ENDSTOPS @@ -2848,10 +3146,18 @@ ISR(TIMER1_COMPA_vect) #if X_MIN_PIN > -1 bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOP_INVERT); if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_x_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_x_hit=false; } old_x_min_endstop = x_min_endstop; + #else + endstop_x_hit=false; #endif } } @@ -2862,10 +3168,18 @@ ISR(TIMER1_COMPA_vect) #if X_MAX_PIN > -1 bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOP_INVERT); if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_x_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_x_hit=false; } old_x_max_endstop = x_max_endstop; + #else + endstop_x_hit=false; #endif } } @@ -2877,10 +3191,18 @@ ISR(TIMER1_COMPA_vect) #if Y_MIN_PIN > -1 bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOP_INVERT); if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { - endstop_y_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_y_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_y_hit=false; } old_y_min_endstop = y_min_endstop; + #else + endstop_y_hit=false; #endif } } @@ -2891,10 +3213,18 @@ ISR(TIMER1_COMPA_vect) #if Y_MAX_PIN > -1 bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOP_INVERT); if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ - endstop_y_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_y_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_y_hit=false; } old_y_max_endstop = y_max_endstop; + #else + endstop_y_hit=false; #endif } } @@ -2906,10 +3236,18 @@ ISR(TIMER1_COMPA_vect) #if Z_MIN_PIN > -1 bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOP_INVERT); if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { - endstop_z_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_z_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_z_hit=false; } old_z_min_endstop = z_min_endstop; + #else + endstop_z_hit=false; #endif } } @@ -2920,10 +3258,18 @@ ISR(TIMER1_COMPA_vect) #if Z_MAX_PIN > -1 bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOP_INVERT); if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { - endstop_z_hit=true; - step_events_completed = current_block->step_event_count; + if(!is_homing) + endstop_z_hit=true; + else + step_events_completed = current_block->step_event_count; + } + else + { + endstop_z_hit=false; } old_z_max_endstop = z_max_endstop; + #else + endstop_z_hit=false; #endif } } @@ -2953,24 +3299,52 @@ ISR(TIMER1_COMPA_vect) } } #endif //ADVANCE - + + counter_x += current_block->steps_x; if (counter_x > 0) { - WRITE(X_STEP_PIN, HIGH); + if(!endstop_x_hit) + { + if(virtual_steps_x) + virtual_steps_x--; + else + WRITE(X_STEP_PIN, HIGH); + } + else + virtual_steps_x++; + counter_x -= current_block->step_event_count; WRITE(X_STEP_PIN, LOW); } counter_y += current_block->steps_y; if (counter_y > 0) { - WRITE(Y_STEP_PIN, HIGH); + if(!endstop_y_hit) + { + if(virtual_steps_y) + virtual_steps_y--; + else + WRITE(Y_STEP_PIN, HIGH); + } + else + virtual_steps_y++; + counter_y -= current_block->step_event_count; WRITE(Y_STEP_PIN, LOW); } counter_z += current_block->steps_z; if (counter_z > 0) { - WRITE(Z_STEP_PIN, HIGH); + if(!endstop_z_hit) + { + if(virtual_steps_z) + virtual_steps_z--; + else + WRITE(Z_STEP_PIN, HIGH); + } + else + virtual_steps_z++; + counter_z -= current_block->step_event_count; WRITE(Z_STEP_PIN, LOW); } @@ -2983,8 +3357,10 @@ ISR(TIMER1_COMPA_vect) WRITE(E_STEP_PIN, LOW); } #endif //!ADVANCE + step_events_completed += 1; if(step_events_completed >= current_block->step_event_count) break; + } // Calculare new timer value unsigned short timer; @@ -3130,6 +3506,9 @@ void st_synchronize() while(blocks_queued()) { manage_heater(); manage_inactivity(1); + #if (MINIMUM_FAN_START_SPEED > 0) + manage_fan_start_speed(); + #endif } } |