|
1 /* |
|
2 Reprap firmware based on Sprinter and grbl. |
|
3 Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm |
|
4 |
|
5 This program is free software: you can redistribute it and/or modify |
|
6 it under the terms of the GNU General Public License as published by |
|
7 the Free Software Foundation, either version 3 of the License, or |
|
8 (at your option) any later version. |
|
9 |
|
10 This program is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 GNU General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU General Public License |
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
17 */ |
|
18 |
|
19 /* |
|
20 This firmware is a mashup between Sprinter and grbl. |
|
21 (https://github.com/kliment/Sprinter) |
|
22 (https://github.com/simen/grbl/tree) |
|
23 |
|
24 It has preliminary support for Matthew Roberts advance algorithm |
|
25 http://reprap.org/pipermail/reprap-dev/2011-May/003323.html |
|
26 */ |
|
27 |
|
28 /* |
|
29 RepRapPro ammendations, deletions and additions |
|
30 |
|
31 G10, M0, M1, M112 and T commands added/modified by AB 18/7/12 |
|
32 Much conditional-compiled code for old/unused hardware removed - AB 29/7/12 |
|
33 |
|
34 */ |
|
35 |
|
36 /* |
|
37 NeoSoft modifications: |
|
38 |
|
39 Implement: |
|
40 - M571 to enable PWM on extruder Movement (laser modulation support), second E parameter to disable real E drive |
|
41 - MXXX to enable Emergency Stop button (if disabled the button can be used to programmatically pause the lasercut for user interaction. For example: |
|
42 move to bottom left of print rectangle, ask user to align workpiece (wait for button press), then move to bottom right and ask user to align the other workpiece end, wait for button press to start engraving... |
|
43 |
|
44 EXT PINS: |
|
45 30, 29,28 = EXT1-3, 27=EXT4=LED |
|
46 |
|
47 M571 pin default to EXT3 (PIN 28) in pins.h |
|
48 |
|
49 Emergency Stop (PAUSE) button on EXT2 (PIN 29): |
|
50 If not stopped: call stop() |
|
51 If stopped: execute code from M999 Command (do not inject M999, execute the code!) |
|
52 // bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); |
|
53 //pinMode(inPin, INPUT); |
|
54 |
|
55 alternative approach (better?): |
|
56 make copy of "void enquecommand(const char *cmd)" with following behaviour: |
|
57 - pause serial receiver enqueueing (the irq should respond like "buffer full") |
|
58 - call alternative of stop() which memorizes the last PROCESSED line? |
|
59 */ |
|
60 |
|
61 #include "Marlin.h" |
|
62 |
|
63 #include "ultralcd.h" |
|
64 #include "led.h" |
|
65 #include "z_probe.h" |
|
66 #include "FPUTransform.h" |
|
67 #include "planner.h" |
|
68 #include "stepper.h" |
|
69 #include "temperature.h" |
|
70 #include "motion_control.h" |
|
71 #include "cardreader.h" |
|
72 #include "EEPROMwrite.h" |
|
73 #include "language.h" |
|
74 #include "pins_arduino.h" |
|
75 #include "slave_comms.h" |
|
76 |
|
77 #define VERSION_STRING "1.0.2 RRP/NeoSoft" |
|
78 |
|
79 // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html |
|
80 // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes |
|
81 |
|
82 //Implemented Codes |
|
83 //------------------- |
|
84 // G0 -> G1 |
|
85 // G1 - Coordinated Movement X Y Z E |
|
86 // G2 - CW ARC |
|
87 // G3 - CCW ARC |
|
88 // G4 - Dwell S<seconds> or P<milliseconds> |
|
89 // G10 - set head offset and temps |
|
90 // G28 - Home all Axis |
|
91 // G29 - Detailed Z-Probe (3 location test) |
|
92 // G30 - Single Z Probe (probe current location) |
|
93 // G31 - Report Curent Probe status |
|
94 // G32 - Probe Z and calibrate with FPU |
|
95 // G90 - Use Absolute Coordinates |
|
96 // G91 - Use Relative Coordinates |
|
97 // G92 - Set current position to cordinates given |
|
98 |
|
99 //RepRap M Codes |
|
100 // M104 - Set extruder target temp (deprecated) |
|
101 // M105 - Read current temp |
|
102 // M106 - Fan on |
|
103 // M107 - Fan off |
|
104 // M109 - Wait for extruder current temp to reach target temp. (deprecated) |
|
105 // M114 - Display current position |
|
106 |
|
107 //Custom M Codes |
|
108 // M17 - Enable/Power all stepper motors |
|
109 // M18 - Disable all stepper motors; same as M84 |
|
110 // M20 - List SD card |
|
111 // M21 - Init SD card |
|
112 // M22 - Release SD card |
|
113 // M23 - Select SD file (M23 filename.g) |
|
114 // M24 - Start/resume SD print |
|
115 // M25 - Pause SD print |
|
116 // M26 - Set SD position in bytes (M26 S12345) |
|
117 // M27 - Report SD print status |
|
118 // M28 - Start SD write (M28 filename.g) |
|
119 // M29 - Stop SD write |
|
120 // M30 - Fast SD transfer |
|
121 // M31 - high speed xfer capabilities |
|
122 // M35 - Output time since last M109 or SD card start to serial |
|
123 |
|
124 // M42 - Change pin status via gcode |
|
125 // M82 - Set E codes absolute (default) |
|
126 // M83 - Set E codes relative while in Absolute Coordinates (G90) mode |
|
127 // M84 - Disable steppers until next move, |
|
128 // or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. |
|
129 // M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default) |
|
130 // M92 - Set axis_steps_per_unit - same syntax as G92 |
|
131 // M114 - Output current position to serial port |
|
132 // M115 - Capabilities string |
|
133 // M117 - display message |
|
134 // M119 - Output Endstop status to serial port |
|
135 // M140 - Set bed target temp |
|
136 // M190 - Wait for bed current temp to reach target temp. |
|
137 // M200 - Set filament diameter |
|
138 // M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) |
|
139 // M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!! |
|
140 // M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec |
|
141 // M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate |
|
142 // 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=maximum E jerk |
|
143 // M206 - set additional homeing offset |
|
144 // M208 - set axis max length |
|
145 // M220 S<factor in percent>- set speed factor override percentage |
|
146 // M221 S<factor in percent>- set extrude factor override percentage |
|
147 // M240 - Trigger a camera to take a photograph |
|
148 // M301 - Set PID parameters P I D and W |
|
149 // M302 - S1 Allow cold extrudes, S0 cold extrues not allowed (default) |
|
150 // M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C) |
|
151 // M304 - Set thermistor parameters |
|
152 // M400 - Finish all moves |
|
153 // M500 - stores paramters in EEPROM |
|
154 // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). |
|
155 // M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. |
|
156 // M503 - print the current settings (from memory not from eeprom) |
|
157 // M510 - FPU Enable |
|
158 // M511 - FPU Reset |
|
159 // M512 - FPU Disable |
|
160 // M999 - Restart after being stopped by error |
|
161 |
|
162 // M555 - Temporary: master/slave comms test |
|
163 |
|
164 // TN - Select extruder N |
|
165 |
|
166 //Stepper Movement Variables |
|
167 |
|
168 //=========================================================================== |
|
169 //=============================imported variables============================ |
|
170 //=========================================================================== |
|
171 |
|
172 |
|
173 //=========================================================================== |
|
174 //=============================public variables============================= |
|
175 //=========================================================================== |
|
176 #ifdef SDSUPPORT |
|
177 CardReader card; |
|
178 #endif |
|
179 float homing_feedrate[] = HOMING_FEEDRATE; |
|
180 float fast_home_feedrate[] = FAST_HOME_FEEDRATE; |
|
181 bool axis_relative_modes[] = AXIS_RELATIVE_MODES; |
|
182 volatile int feedmultiply=100; //100->1 200->2 |
|
183 int saved_feedmultiply; |
|
184 volatile bool feedmultiplychanged=false; |
|
185 volatile int extrudemultiply=100; //100->1 200->2 |
|
186 float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; |
|
187 float add_homeing[3]={0,0,0}; |
|
188 float max_length[] = AXES_MAX_LENGTHS; |
|
189 #ifdef ADVANCE |
|
190 float advance_k = EXTRUDER_ADVANCE_K; |
|
191 #endif |
|
192 uint8_t active_extruder = 0; |
|
193 float extruder_x_off[EXTRUDERS]; |
|
194 float extruder_y_off[EXTRUDERS]; |
|
195 float extruder_z_off[EXTRUDERS]; |
|
196 float extruder_standby[EXTRUDERS]; |
|
197 float extruder_temperature[EXTRUDERS]; |
|
198 float x_off_d; |
|
199 float y_off_d; |
|
200 float z_off_d; |
|
201 float temp_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; |
|
202 bool extruder_selected=false; |
|
203 |
|
204 |
|
205 unsigned char FanSpeed=0; |
|
206 bool m571_enabled = 0; |
|
207 bool n571_enabled = 0; |
|
208 |
|
209 float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; |
|
210 float offset[3] = {0.0, 0.0, 0.0}; |
|
211 float feedrate = 1500.0, next_feedrate, saved_feedrate; |
|
212 |
|
213 // used by FPU transform code |
|
214 float modified_destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; |
|
215 |
|
216 //=========================================================================== |
|
217 //=============================private variables============================= |
|
218 //=========================================================================== |
|
219 const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; |
|
220 static bool home_all_axis = true; |
|
221 static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; |
|
222 |
|
223 static bool relative_mode = false; //Determines Absolute or Relative Coordinates |
|
224 static bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. |
|
225 |
|
226 static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; |
|
227 static bool fromsd[BUFSIZE]; |
|
228 static int bufindr = 0; |
|
229 static int bufindw = 0; |
|
230 static int buflen = 0; |
|
231 //static int i = 0; |
|
232 static char serial_char; |
|
233 static int serial_count = 0; |
|
234 static boolean comment_mode = false; |
|
235 static char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc |
|
236 |
|
237 const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 |
|
238 |
|
239 //static float tt = 0; |
|
240 //static float bt = 0; |
|
241 |
|
242 //Inactivity shutdown variables |
|
243 static unsigned long previous_millis_cmd = 0; |
|
244 static unsigned long max_inactive_time = 0; |
|
245 static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l; |
|
246 |
|
247 static unsigned long starttime=0; |
|
248 static unsigned long stoptime=0; |
|
249 |
|
250 static uint8_t tmp_extruder; |
|
251 |
|
252 |
|
253 bool Stopped=false; |
|
254 |
|
255 //=========================================================================== |
|
256 //=============================ROUTINES============================= |
|
257 //=========================================================================== |
|
258 |
|
259 void get_arc_coordinates(); |
|
260 |
|
261 extern "C"{ |
|
262 extern unsigned int __bss_end; |
|
263 extern unsigned int __heap_start; |
|
264 extern void *__brkval; |
|
265 |
|
266 int freeMemory() { |
|
267 int free_memory; |
|
268 |
|
269 if((int)__brkval == 0) |
|
270 free_memory = ((int)&free_memory) - ((int)&__bss_end); |
|
271 else |
|
272 free_memory = ((int)&free_memory) - ((int)__brkval); |
|
273 |
|
274 return free_memory; |
|
275 } |
|
276 } |
|
277 |
|
278 //adds an command to the main command buffer |
|
279 //thats really done in a non-safe way. |
|
280 //needs overworking someday |
|
281 void enquecommand(const char *cmd) |
|
282 { |
|
283 if(buflen < BUFSIZE) |
|
284 { |
|
285 //this is dangerous if a mixing of serial and this happsens |
|
286 strcpy(&(cmdbuffer[bufindw][0]),cmd); |
|
287 SERIAL_ECHO_START; |
|
288 SERIAL_ECHOPGM("enqueing \""); |
|
289 SERIAL_ECHO(cmdbuffer[bufindw]); |
|
290 SERIAL_ECHOLNPGM("\""); |
|
291 bufindw= (bufindw + 1)%BUFSIZE; |
|
292 buflen += 1; |
|
293 } |
|
294 } |
|
295 |
|
296 void setup_photpin() |
|
297 { |
|
298 #ifdef PHOTOGRAPH_PIN |
|
299 #if (PHOTOGRAPH_PIN > -1) |
|
300 SET_OUTPUT(PHOTOGRAPH_PIN); |
|
301 WRITE(PHOTOGRAPH_PIN, LOW); |
|
302 #endif |
|
303 #endif |
|
304 } |
|
305 |
|
306 void setup_powerhold() |
|
307 { |
|
308 #ifdef SUICIDE_PIN |
|
309 #if (SUICIDE_PIN> -1) |
|
310 SET_OUTPUT(SUICIDE_PIN); |
|
311 WRITE(SUICIDE_PIN, HIGH); |
|
312 #endif |
|
313 #endif |
|
314 } |
|
315 |
|
316 void suicide() |
|
317 { |
|
318 #ifdef SUICIDE_PIN |
|
319 #if (SUICIDE_PIN> -1) |
|
320 SET_OUTPUT(SUICIDE_PIN); |
|
321 WRITE(SUICIDE_PIN, LOW); |
|
322 #endif |
|
323 #endif |
|
324 } |
|
325 |
|
326 void setup() |
|
327 { |
|
328 setup_powerhold(); |
|
329 MYSERIAL.begin(BAUDRATE); |
|
330 SERIAL_PROTOCOLLNPGM("start"); |
|
331 SERIAL_ECHO_START; |
|
332 |
|
333 for(int8_t i = 0; i < EXTRUDERS; i++) |
|
334 { |
|
335 extruder_x_off[i] = X_EXTRUDER_OFFSET; |
|
336 extruder_y_off[i] = Y_EXTRUDER_OFFSET; |
|
337 extruder_z_off[i] = Z_EXTRUDER_OFFSET; |
|
338 extruder_standby[i] = STANDBY_TEMP; |
|
339 extruder_temperature[i] = DEFAULT_TEMP; |
|
340 } |
|
341 |
|
342 |
|
343 // Check startup - does nothing if bootloader sets MCUSR to 0 |
|
344 byte mcu = MCUSR; |
|
345 if(mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP); |
|
346 if(mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET); |
|
347 if(mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET); |
|
348 if(mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET); |
|
349 if(mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET); |
|
350 MCUSR=0; |
|
351 |
|
352 SERIAL_ECHOPGM(MSG_MARLIN); |
|
353 SERIAL_ECHOLNPGM(VERSION_STRING); |
|
354 #ifdef STRING_VERSION_CONFIG_H |
|
355 #ifdef STRING_CONFIG_H_AUTHOR |
|
356 SERIAL_ECHO_START; |
|
357 SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); |
|
358 SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); |
|
359 SERIAL_ECHOPGM(MSG_AUTHOR); |
|
360 SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); |
|
361 #endif |
|
362 #endif |
|
363 SERIAL_ECHO_START; |
|
364 SERIAL_ECHOPGM(MSG_FREE_MEMORY); |
|
365 SERIAL_ECHO(freeMemory()); |
|
366 SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES); |
|
367 SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); |
|
368 for(int8_t i = 0; i < BUFSIZE; i++) |
|
369 { |
|
370 fromsd[i] = false; |
|
371 } |
|
372 |
|
373 EEPROM_RetrieveSettings(); // loads data from EEPROM if available |
|
374 |
|
375 for(int8_t i=0; i < NUM_AXIS; i++) |
|
376 { |
|
377 axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; |
|
378 } |
|
379 |
|
380 |
|
381 tp_init(); // Initialize temperature loop |
|
382 plan_init(); // Initialize planner; |
|
383 st_init(); // Initialize stepper; |
|
384 #if (LED_PIN > -1) |
|
385 led_init(); |
|
386 #endif |
|
387 probe_init(); //Initializes probe if PROBE_PIN is defined |
|
388 FPUTransform_init(); //Initializes FPU when UMFPUSUPPORT defined |
|
389 setup_photpin(); |
|
390 |
|
391 #ifdef REPRAPPRO_MULTIMATERIALS |
|
392 setup_slave(); |
|
393 #endif |
|
394 |
|
395 } |
|
396 |
|
397 |
|
398 void loop() |
|
399 { |
|
400 if(buflen < (BUFSIZE-1)) |
|
401 get_command(); |
|
402 #ifdef SDSUPPORT |
|
403 card.checkautostart(false); |
|
404 #endif |
|
405 if(buflen) |
|
406 { |
|
407 #ifdef SDSUPPORT |
|
408 if(card.saving) |
|
409 { |
|
410 if(strstr(cmdbuffer[bufindr],"M29") == NULL) |
|
411 { |
|
412 card.write_command(cmdbuffer[bufindr]); |
|
413 SERIAL_PROTOCOLLNPGM(MSG_OK); |
|
414 } |
|
415 else |
|
416 { |
|
417 card.closefile(); |
|
418 SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); |
|
419 } |
|
420 } |
|
421 else |
|
422 { |
|
423 process_commands(); |
|
424 } |
|
425 #else |
|
426 process_commands(); |
|
427 #endif //SDSUPPORT |
|
428 buflen = (buflen-1); |
|
429 bufindr = (bufindr + 1)%BUFSIZE; |
|
430 } |
|
431 //check heater every n milliseconds |
|
432 manage_heater(); |
|
433 manage_inactivity(1); |
|
434 checkHitEndstops(); |
|
435 LCD_STATUS; |
|
436 LED_STATUS; |
|
437 } |
|
438 |
|
439 void get_command() |
|
440 { |
|
441 while( MYSERIAL.available() > 0 && buflen < BUFSIZE) { |
|
442 serial_char = MYSERIAL.read(); |
|
443 if(serial_char == '\n' || |
|
444 serial_char == '\r' || |
|
445 (serial_char == ':' && comment_mode == false) || |
|
446 serial_count >= (MAX_CMD_SIZE - 1) ) |
|
447 { |
|
448 if(!serial_count) { //if empty line |
|
449 comment_mode = false; //for new command |
|
450 return; |
|
451 } |
|
452 cmdbuffer[bufindw][serial_count] = 0; //terminate string |
|
453 if(!comment_mode){ |
|
454 comment_mode = false; //for new command |
|
455 fromsd[bufindw] = false; |
|
456 if(strstr(cmdbuffer[bufindw], "N") != NULL) |
|
457 { |
|
458 strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); |
|
459 gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); |
|
460 if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { |
|
461 SERIAL_ERROR_START; |
|
462 SERIAL_ERRORPGM(MSG_ERR_LINE_NO); |
|
463 SERIAL_ERRORLN(gcode_LastN); |
|
464 //Serial.println(gcode_N); |
|
465 FlushSerialRequestResend(); |
|
466 serial_count = 0; |
|
467 return; |
|
468 } |
|
469 |
|
470 if(strstr(cmdbuffer[bufindw], "*") != NULL) |
|
471 { |
|
472 byte checksum = 0; |
|
473 byte count = 0; |
|
474 while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; |
|
475 strchr_pointer = strchr(cmdbuffer[bufindw], '*'); |
|
476 |
|
477 if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { |
|
478 SERIAL_ERROR_START; |
|
479 SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); |
|
480 SERIAL_ERRORLN(gcode_LastN); |
|
481 FlushSerialRequestResend(); |
|
482 serial_count = 0; |
|
483 return; |
|
484 } |
|
485 //if no errors, continue parsing |
|
486 } |
|
487 else |
|
488 { |
|
489 SERIAL_ERROR_START; |
|
490 SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); |
|
491 SERIAL_ERRORLN(gcode_LastN); |
|
492 FlushSerialRequestResend(); |
|
493 serial_count = 0; |
|
494 return; |
|
495 } |
|
496 |
|
497 gcode_LastN = gcode_N; |
|
498 //if no errors, continue parsing |
|
499 } |
|
500 else // if we don't receive 'N' but still see '*' |
|
501 { |
|
502 if((strstr(cmdbuffer[bufindw], "*") != NULL)) |
|
503 { |
|
504 SERIAL_ERROR_START; |
|
505 SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); |
|
506 SERIAL_ERRORLN(gcode_LastN); |
|
507 serial_count = 0; |
|
508 return; |
|
509 } |
|
510 } |
|
511 if((strstr(cmdbuffer[bufindw], "G") != NULL)){ |
|
512 strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); |
|
513 switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ |
|
514 case 0: |
|
515 case 1: |
|
516 case 2: |
|
517 case 3: |
|
518 if(Stopped == false) { // If printer is stopped by an error the G[0-3] codes are ignored. |
|
519 #ifdef SDSUPPORT |
|
520 if(card.saving) |
|
521 break; |
|
522 #endif //SDSUPPORT |
|
523 SERIAL_PROTOCOLLNPGM(MSG_OK); |
|
524 } |
|
525 else { |
|
526 SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); |
|
527 LCD_MESSAGEPGM(MSG_STOPPED); |
|
528 } |
|
529 break; |
|
530 default: |
|
531 break; |
|
532 } |
|
533 |
|
534 } |
|
535 bufindw = (bufindw + 1)%BUFSIZE; |
|
536 buflen += 1; |
|
537 } |
|
538 serial_count = 0; //clear buffer |
|
539 } |
|
540 else |
|
541 { |
|
542 if(serial_char == ';') comment_mode = true; |
|
543 if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; |
|
544 } |
|
545 } |
|
546 #ifdef SDSUPPORT |
|
547 if(!card.sdprinting || serial_count!=0){ |
|
548 return; |
|
549 } |
|
550 while( !card.eof() && buflen < BUFSIZE) { |
|
551 int16_t n=card.get(); |
|
552 serial_char = (char)n; |
|
553 if(serial_char == '\n' || |
|
554 serial_char == '\r' || |
|
555 (serial_char == ':' && comment_mode == false) || |
|
556 serial_count >= (MAX_CMD_SIZE - 1)||n==-1) |
|
557 { |
|
558 if(card.eof()){ |
|
559 SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED); |
|
560 stoptime=millis(); |
|
561 char time[30]; |
|
562 unsigned long t=(stoptime-starttime)/1000; |
|
563 int sec,min; |
|
564 min=t/60; |
|
565 sec=t%60; |
|
566 sprintf(time,"%i min, %i sec",min,sec); |
|
567 SERIAL_ECHO_START; |
|
568 SERIAL_ECHOLN(time); |
|
569 LCD_MESSAGE(time); |
|
570 card.printingHasFinished(); |
|
571 card.checkautostart(true); |
|
572 |
|
573 } |
|
574 if(!serial_count) |
|
575 { |
|
576 comment_mode = false; //for new command |
|
577 return; //if empty line |
|
578 } |
|
579 cmdbuffer[bufindw][serial_count] = 0; //terminate string |
|
580 // if(!comment_mode){ |
|
581 fromsd[bufindw] = true; |
|
582 buflen += 1; |
|
583 bufindw = (bufindw + 1)%BUFSIZE; |
|
584 // } |
|
585 comment_mode = false; //for new command |
|
586 serial_count = 0; //clear buffer |
|
587 } |
|
588 else |
|
589 { |
|
590 if(serial_char == ';') comment_mode = true; |
|
591 if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; |
|
592 } |
|
593 } |
|
594 |
|
595 #endif //SDSUPPORT |
|
596 |
|
597 } |
|
598 |
|
599 |
|
600 float code_value() |
|
601 { |
|
602 return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); |
|
603 } |
|
604 |
|
605 long code_value_long() |
|
606 { |
|
607 return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); |
|
608 } |
|
609 |
|
610 bool code_seen(char code_string[]) //Return True if the string was found |
|
611 { |
|
612 return (strstr(cmdbuffer[bufindr], code_string) != NULL); |
|
613 } |
|
614 |
|
615 bool code_seen(char code) |
|
616 { |
|
617 strchr_pointer = strchr(cmdbuffer[bufindr], code); |
|
618 return (strchr_pointer != NULL); //Return True if a character was found |
|
619 } |
|
620 |
|
621 #define HOMEAXIS(LETTER) \ |
|
622 if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ |
|
623 { \ |
|
624 current_position[LETTER##_AXIS] = 0; \ |
|
625 plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ |
|
626 destination[LETTER##_AXIS] = 1.1 * max_length[LETTER##_AXIS] * LETTER##_HOME_DIR; \ |
|
627 feedrate = fast_home_feedrate[LETTER##_AXIS]; \ |
|
628 plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ |
|
629 st_synchronize();\ |
|
630 \ |
|
631 current_position[LETTER##_AXIS] = 0;\ |
|
632 plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ |
|
633 destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ |
|
634 plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ |
|
635 st_synchronize();\ |
|
636 \ |
|
637 destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ |
|
638 feedrate = homing_feedrate[LETTER##_AXIS] ; \ |
|
639 plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ |
|
640 st_synchronize();\ |
|
641 \ |
|
642 current_position[LETTER##_AXIS] = LETTER##_HOME_POS;\ |
|
643 destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ |
|
644 feedrate = 0.0;\ |
|
645 endstops_hit_on_purpose();\ |
|
646 } |
|
647 |
|
648 void wait_for_temp(uint8_t& t_ext, unsigned long& codenum) |
|
649 { |
|
650 /* See if we are heating up or cooling down */ |
|
651 bool target_direction = isHeatingHotend(t_ext); // true if heating, false if cooling |
|
652 |
|
653 #ifdef TEMP_RESIDENCY_TIME |
|
654 long residencyStart; |
|
655 residencyStart = -1; |
|
656 /* continue to loop until we have reached the target temp |
|
657 _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ |
|
658 while((residencyStart == -1) || |
|
659 (residencyStart >= 0 && (((unsigned int) (millis() - residencyStart)) < (TEMP_RESIDENCY_TIME * 1000UL))) ) |
|
660 { |
|
661 #else |
|
662 while ( target_direction ? (isHeatingHotend(t_ext)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) |
|
663 { |
|
664 #endif //TEMP_RESIDENCY_TIME |
|
665 if( (millis() - codenum) > 1000UL ) |
|
666 { //Print Temp Reading and remaining time every 1 second while heating up/cooling down |
|
667 SERIAL_PROTOCOLPGM("T:"); |
|
668 SERIAL_PROTOCOL_F(degHotend(t_ext),1); |
|
669 SERIAL_PROTOCOLPGM(" E:"); |
|
670 SERIAL_PROTOCOL( (int)t_ext ); |
|
671 #ifdef TEMP_RESIDENCY_TIME |
|
672 SERIAL_PROTOCOLPGM(" W:"); |
|
673 if(residencyStart > -1) |
|
674 { |
|
675 codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - (millis() - residencyStart)) / 1000UL; |
|
676 SERIAL_PROTOCOLLN( codenum ); |
|
677 } else |
|
678 { |
|
679 SERIAL_PROTOCOLLN( "?" ); |
|
680 } |
|
681 #else |
|
682 SERIAL_PROTOCOLLN(""); |
|
683 #endif |
|
684 codenum = millis(); |
|
685 } |
|
686 manage_heater(); |
|
687 manage_inactivity(1); |
|
688 lcd_status(); |
|
689 led_status(); |
|
690 #ifdef TEMP_RESIDENCY_TIME |
|
691 /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time |
|
692 or when current temp falls outside the hysteresis after target temp was reached */ |
|
693 if ((residencyStart == -1 && target_direction && (degHotend(t_ext) >= (degTargetHotend(t_ext)-TEMP_WINDOW))) || |
|
694 (residencyStart == -1 && !target_direction && (degHotend(t_ext) <= (degTargetHotend(t_ext)+TEMP_WINDOW))) || |
|
695 (residencyStart > -1 && labs(degHotend(t_ext) - degTargetHotend(t_ext)) > TEMP_HYSTERESIS) ) |
|
696 { |
|
697 residencyStart = millis(); |
|
698 } |
|
699 #endif //TEMP_RESIDENCY_TIME |
|
700 } |
|
701 LCD_MESSAGEPGM(MSG_HEATING_COMPLETE); |
|
702 starttime=millis(); |
|
703 previous_millis_cmd = millis(); |
|
704 } |
|
705 |
|
706 |
|
707 void process_commands() |
|
708 { |
|
709 unsigned long codenum; //throw away variable |
|
710 char *starpos = NULL; |
|
711 |
|
712 if(code_seen('G')) |
|
713 { |
|
714 switch((int)code_value()) |
|
715 { |
|
716 case 0: // G0 -> G1 |
|
717 case 1: // G1 |
|
718 if(Stopped == false) { |
|
719 get_coordinates(); // For X Y Z E F |
|
720 prepare_move(); |
|
721 //ClearToSend(); |
|
722 return; |
|
723 } |
|
724 //break; |
|
725 case 2: // G2 - CW ARC |
|
726 if(Stopped == false) { |
|
727 get_arc_coordinates(); |
|
728 prepare_arc_move(true); |
|
729 return; |
|
730 } |
|
731 case 3: // G3 - CCW ARC |
|
732 if(Stopped == false) { |
|
733 get_arc_coordinates(); |
|
734 prepare_arc_move(false); |
|
735 return; |
|
736 } |
|
737 case 4: // G4 dwell |
|
738 LCD_MESSAGEPGM(MSG_DWELL); |
|
739 codenum = 0; |
|
740 if(code_seen('P')) codenum = code_value(); // milliseconds to wait |
|
741 if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait |
|
742 |
|
743 st_synchronize(); |
|
744 codenum += millis(); // keep track of when we started waiting |
|
745 previous_millis_cmd = millis(); |
|
746 while(millis() < codenum ){ |
|
747 manage_heater(); |
|
748 manage_inactivity(1); |
|
749 } |
|
750 break; |
|
751 |
|
752 case 10: // Set offsets |
|
753 if(code_seen('P')) |
|
754 { |
|
755 tmp_extruder = code_value(); |
|
756 get_coordinates(); |
|
757 extruder_x_off[tmp_extruder] = destination[0]; // X |
|
758 extruder_y_off[tmp_extruder] = destination[1]; // Y |
|
759 extruder_z_off[tmp_extruder] = destination[2]; // Z |
|
760 if(code_seen('R')) |
|
761 extruder_standby[tmp_extruder] = code_value(); |
|
762 if(code_seen('S')) |
|
763 extruder_temperature[tmp_extruder] = code_value(); |
|
764 } |
|
765 break; |
|
766 |
|
767 case 28: //G28 Home all Axis one at a time |
|
768 saved_feedrate = feedrate; |
|
769 saved_feedmultiply = feedmultiply; |
|
770 feedmultiply = 100; |
|
771 previous_millis_cmd = millis(); |
|
772 |
|
773 enable_endstops(true); |
|
774 |
|
775 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
776 destination[i] = current_position[i]; |
|
777 } |
|
778 feedrate = 0.0; |
|
779 home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); |
|
780 |
|
781 if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) |
|
782 { |
|
783 HOMEAXIS(X); |
|
784 } |
|
785 |
|
786 if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { |
|
787 HOMEAXIS(Y); |
|
788 } |
|
789 |
|
790 if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { |
|
791 HOMEAXIS(Z); |
|
792 } |
|
793 |
|
794 if((home_all_axis) || code_seen(axis_codes[X_AXIS])) |
|
795 { |
|
796 if(code_value_long() != 0) { |
|
797 current_position[X_AXIS]=code_value(); |
|
798 } |
|
799 current_position[X_AXIS]+=add_homeing[0]; |
|
800 } |
|
801 |
|
802 if((home_all_axis) || code_seen(axis_codes[Y_AXIS])) { |
|
803 if(code_value_long() != 0) { |
|
804 current_position[Y_AXIS]=code_value(); |
|
805 } |
|
806 current_position[Y_AXIS]+=add_homeing[1]; |
|
807 } |
|
808 |
|
809 if((home_all_axis) || code_seen(axis_codes[Z_AXIS])) { |
|
810 if(code_value_long() != 0) { |
|
811 current_position[Z_AXIS]=code_value(); |
|
812 } |
|
813 current_position[Z_AXIS]+=add_homeing[2]; |
|
814 } |
|
815 plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); |
|
816 |
|
817 #ifdef ENDSTOPS_ONLY_FOR_HOMING |
|
818 enable_endstops(false); |
|
819 #endif |
|
820 |
|
821 feedrate = saved_feedrate; |
|
822 feedmultiply = saved_feedmultiply; |
|
823 previous_millis_cmd = millis(); |
|
824 endstops_hit_on_purpose(); |
|
825 break; |
|
826 case 29: |
|
827 probe_3points(); |
|
828 break; |
|
829 case 30: |
|
830 probe_1point(); |
|
831 break; |
|
832 case 31: |
|
833 probe_status(); |
|
834 break; |
|
835 case 32: |
|
836 FPUTransform_determineBedOrientation(); |
|
837 break; |
|
838 case 90: // G90 |
|
839 relative_mode = false; |
|
840 break; |
|
841 case 91: // G91 |
|
842 relative_mode = true; |
|
843 break; |
|
844 case 92: // G92 |
|
845 if(!code_seen(axis_codes[E_AXIS])) |
|
846 st_synchronize(); |
|
847 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
848 if(code_seen(axis_codes[i])) { |
|
849 current_position[i] = code_value()+add_homeing[i]; |
|
850 if(i == E_AXIS) { |
|
851 current_position[i] = code_value(); |
|
852 plan_set_e_position(current_position[E_AXIS]); |
|
853 } |
|
854 else { |
|
855 current_position[i] = code_value()+add_homeing[i]; |
|
856 plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); |
|
857 } |
|
858 } |
|
859 } |
|
860 break; |
|
861 } |
|
862 } |
|
863 |
|
864 else if(code_seen('M')) |
|
865 { |
|
866 switch( (int)code_value() ) |
|
867 { |
|
868 case 0: // Stops - add me... |
|
869 case 1: |
|
870 case 112: |
|
871 break; |
|
872 |
|
873 case 17: |
|
874 LCD_MESSAGEPGM(MSG_NO_MOVE); |
|
875 enable_x(); |
|
876 enable_y(); |
|
877 enable_z(); |
|
878 // N571 disables real E drive! (ie. on laser operations) |
|
879 if (!n571_enabled) { |
|
880 enable_e0(); |
|
881 enable_e1(); |
|
882 enable_e2(); |
|
883 } |
|
884 break; |
|
885 |
|
886 #ifdef SDSUPPORT |
|
887 case 20: // M20 - list SD card |
|
888 SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST); |
|
889 card.ls(); |
|
890 SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST); |
|
891 break; |
|
892 case 21: // M21 - init SD card |
|
893 |
|
894 card.initsd(); |
|
895 |
|
896 break; |
|
897 case 22: //M22 - release SD card |
|
898 card.release(); |
|
899 |
|
900 break; |
|
901 case 23: //M23 - Select file |
|
902 starpos = (strchr(strchr_pointer + 4,'*')); |
|
903 if(starpos!=NULL) |
|
904 *(starpos-1)='\0'; |
|
905 card.openFile(strchr_pointer + 4,true); |
|
906 break; |
|
907 case 24: //M24 - Start SD print |
|
908 card.startFileprint(); |
|
909 starttime=millis(); |
|
910 break; |
|
911 case 25: //M25 - Pause SD print |
|
912 card.pauseSDPrint(); |
|
913 break; |
|
914 case 26: //M26 - Set SD index |
|
915 if(card.cardOK && code_seen('S')) { |
|
916 card.setIndex(code_value_long()); |
|
917 } |
|
918 break; |
|
919 case 27: //M27 - Get SD status |
|
920 card.getStatus(); |
|
921 break; |
|
922 case 28: //M28 - Start SD write |
|
923 starpos = (strchr(strchr_pointer + 4,'*')); |
|
924 if(starpos != NULL){ |
|
925 char* npos = strchr(cmdbuffer[bufindr], 'N'); |
|
926 strchr_pointer = strchr(npos,' ') + 1; |
|
927 *(starpos-1) = '\0'; |
|
928 } |
|
929 card.openFile(strchr_pointer+4,false); |
|
930 break; |
|
931 case 29: //M29 - Stop SD write |
|
932 //processed in write to file routine above |
|
933 //card,saving = false; |
|
934 break; |
|
935 case 30: //M30 <filename> Delete File |
|
936 if (card.cardOK){ |
|
937 card.closefile(); |
|
938 starpos = (strchr(strchr_pointer + 4,'*')); |
|
939 if(starpos != NULL){ |
|
940 char* npos = strchr(cmdbuffer[bufindr], 'N'); |
|
941 strchr_pointer = strchr(npos,' ') + 1; |
|
942 *(starpos-1) = '\0'; |
|
943 } |
|
944 card.removeFile(strchr_pointer + 4); |
|
945 } |
|
946 break; |
|
947 |
|
948 case 32: //M32 - fast SD transfer |
|
949 card.fast_xfer(strchr_pointer+4); |
|
950 break; |
|
951 case 33: //M31 - high speed xfer capabilities |
|
952 SERIAL_ECHOPGM("RAW:"); |
|
953 SERIAL_ECHOLN(SD_FAST_XFER_CHUNK_SIZE); |
|
954 break; |
|
955 #endif //SDSUPPORT |
|
956 |
|
957 case 35: //M35 take time since the start of the SD print or an M109 command |
|
958 { |
|
959 stoptime=millis(); |
|
960 char time[30]; |
|
961 unsigned long t=(stoptime-starttime)/1000; |
|
962 int sec,min; |
|
963 min=t/60; |
|
964 sec=t%60; |
|
965 sprintf(time,"%i min, %i sec",min,sec); |
|
966 SERIAL_ECHO_START; |
|
967 SERIAL_ECHOLN(time); |
|
968 LCD_MESSAGE(time); |
|
969 } |
|
970 break; |
|
971 case 42: //M42 -Change pin status via gcode |
|
972 if (code_seen('S')) |
|
973 { |
|
974 int pin_status = code_value(); |
|
975 if (code_seen('P') && pin_status >= 0 && pin_status <= 255) |
|
976 { |
|
977 int pin_number = code_value(); |
|
978 for(int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++) |
|
979 { |
|
980 if (sensitive_pins[i] == pin_number) |
|
981 { |
|
982 pin_number = -1; |
|
983 break; |
|
984 } |
|
985 } |
|
986 |
|
987 if (pin_number > -1) |
|
988 { |
|
989 pinMode(pin_number, OUTPUT); |
|
990 digitalWrite(pin_number, pin_status); |
|
991 analogWrite(pin_number, pin_status); |
|
992 } |
|
993 } |
|
994 } |
|
995 break; |
|
996 case 104: // M104 |
|
997 tmp_extruder = active_extruder; |
|
998 if(code_seen('T')) { // Why is this T and not S? - AB |
|
999 tmp_extruder = code_value(); |
|
1000 if(tmp_extruder >= EXTRUDERS) { |
|
1001 SERIAL_ECHO_START; |
|
1002 SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER); |
|
1003 SERIAL_ECHOLN(tmp_extruder); |
|
1004 break; |
|
1005 } |
|
1006 } |
|
1007 if (code_seen('S')) |
|
1008 { |
|
1009 extruder_temperature[tmp_extruder] = code_value(); |
|
1010 setTargetHotend(code_value(), tmp_extruder); |
|
1011 } |
|
1012 |
|
1013 break; |
|
1014 case 140: // M140 set bed temp |
|
1015 if (code_seen('S')) setTargetBed(code_value()); |
|
1016 break; |
|
1017 case 1105: |
|
1018 #if (TEMP_0_PIN > -1) |
|
1019 SERIAL_PROTOCOLPGM("ok T0 raw:"); |
|
1020 SERIAL_PROTOCOL(rawHotend(tmp_extruder)); |
|
1021 SERIAL_PROTOCOLPGM(", min:"); |
|
1022 SERIAL_PROTOCOL(minHotend(tmp_extruder)); |
|
1023 SERIAL_PROTOCOLPGM(", max:"); |
|
1024 SERIAL_PROTOCOL(maxHotend(tmp_extruder)); |
|
1025 #endif |
|
1026 break; |
|
1027 case 105 : // M105 |
|
1028 tmp_extruder = active_extruder; |
|
1029 if(code_seen('T')) { |
|
1030 tmp_extruder = code_value(); |
|
1031 if(tmp_extruder >= EXTRUDERS) { |
|
1032 SERIAL_ECHO_START; |
|
1033 SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER); |
|
1034 SERIAL_ECHOLN(tmp_extruder); |
|
1035 break; |
|
1036 } |
|
1037 } |
|
1038 #if (TEMP_0_PIN > -1) |
|
1039 SERIAL_PROTOCOLPGM("ok T:"); |
|
1040 SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); |
|
1041 SERIAL_PROTOCOLPGM(" /"); |
|
1042 SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1); |
|
1043 #if TEMP_BED_PIN > -1 |
|
1044 SERIAL_PROTOCOLPGM(" B:"); |
|
1045 SERIAL_PROTOCOL_F(degBed(),1); |
|
1046 SERIAL_PROTOCOLPGM(" /"); |
|
1047 SERIAL_PROTOCOL_F(degTargetBed(),1); |
|
1048 #endif //TEMP_BED_PIN |
|
1049 #else |
|
1050 SERIAL_ERROR_START; |
|
1051 SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS); |
|
1052 #endif |
|
1053 #ifdef PIDTEMP |
|
1054 SERIAL_PROTOCOLPGM(" @:"); |
|
1055 SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); |
|
1056 #endif |
|
1057 SERIAL_PROTOCOLLN(""); |
|
1058 return; |
|
1059 break; |
|
1060 case 109: |
|
1061 // M109 - Wait for extruder heater to reach target. |
|
1062 tmp_extruder = active_extruder; |
|
1063 if(code_seen('T')) { // Why is this T and not S? - AB |
|
1064 tmp_extruder = code_value(); |
|
1065 if(tmp_extruder >= EXTRUDERS) { |
|
1066 SERIAL_ECHO_START; |
|
1067 SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER); |
|
1068 SERIAL_ECHOLN(tmp_extruder); |
|
1069 break; |
|
1070 } |
|
1071 } |
|
1072 LCD_MESSAGEPGM(MSG_HEATING); |
|
1073 |
|
1074 if (code_seen('S')) |
|
1075 { |
|
1076 extruder_temperature[tmp_extruder] = code_value(); |
|
1077 setTargetHotend(code_value(), tmp_extruder); |
|
1078 } |
|
1079 |
|
1080 |
|
1081 codenum = millis(); |
|
1082 wait_for_temp(tmp_extruder, codenum); |
|
1083 break; |
|
1084 case 190: // M190 - Wait for bed heater to reach target. |
|
1085 #if TEMP_BED_PIN > -1 |
|
1086 LCD_MESSAGEPGM(MSG_BED_HEATING); |
|
1087 if (code_seen('S')) setTargetBed(code_value()); |
|
1088 codenum = millis(); |
|
1089 while(isHeatingBed()) |
|
1090 { |
|
1091 if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. |
|
1092 { |
|
1093 float tt=degHotend(active_extruder); |
|
1094 SERIAL_PROTOCOLPGM("T:"); |
|
1095 SERIAL_PROTOCOL(tt); |
|
1096 SERIAL_PROTOCOLPGM(" E:"); |
|
1097 SERIAL_PROTOCOL((int)active_extruder); |
|
1098 SERIAL_PROTOCOLPGM(" B:"); |
|
1099 SERIAL_PROTOCOL_F(degBed(),1); |
|
1100 SERIAL_PROTOCOLLN(""); |
|
1101 codenum = millis(); |
|
1102 } |
|
1103 manage_heater(); |
|
1104 manage_inactivity(1); |
|
1105 LCD_STATUS; |
|
1106 } |
|
1107 LCD_MESSAGEPGM(MSG_BED_DONE); |
|
1108 previous_millis_cmd = millis(); |
|
1109 #endif |
|
1110 break; |
|
1111 |
|
1112 #if FAN_PIN > -1 |
|
1113 case 106: //M106 Fan On |
|
1114 if (code_seen('S')){ |
|
1115 FanSpeed=constrain(code_value(),0,255); |
|
1116 } |
|
1117 else { |
|
1118 FanSpeed=255; |
|
1119 } |
|
1120 break; |
|
1121 case 107: //M107 Fan Off |
|
1122 FanSpeed = 0; |
|
1123 break; |
|
1124 #endif //FAN_PIN |
|
1125 |
|
1126 |
|
1127 case 82: |
|
1128 axis_relative_modes[3] = false; |
|
1129 break; |
|
1130 case 83: |
|
1131 axis_relative_modes[3] = true; |
|
1132 break; |
|
1133 case 18: //compatibility |
|
1134 case 84: // M84 |
|
1135 if(code_seen('S')){ |
|
1136 stepper_inactive_time = code_value() * 1000; |
|
1137 } |
|
1138 else |
|
1139 { |
|
1140 bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3]))); |
|
1141 if(all_axis) |
|
1142 { |
|
1143 st_synchronize(); |
|
1144 disable_e0(); |
|
1145 disable_e1(); |
|
1146 disable_e2(); |
|
1147 finishAndDisableSteppers(); |
|
1148 |
|
1149 if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable |
|
1150 } |
|
1151 else |
|
1152 { |
|
1153 st_synchronize(); |
|
1154 if(code_seen('X')) disable_x(); |
|
1155 if(code_seen('Y')) disable_y(); |
|
1156 if(code_seen('Z')) disable_z(); |
|
1157 #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS |
|
1158 if(code_seen('E')) { |
|
1159 disable_e0(); |
|
1160 disable_e1(); |
|
1161 disable_e2(); |
|
1162 if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable |
|
1163 } |
|
1164 #endif |
|
1165 LCD_MESSAGEPGM(MSG_PART_RELEASE); |
|
1166 } |
|
1167 } |
|
1168 break; |
|
1169 case 85: // M85 |
|
1170 code_seen('S'); |
|
1171 max_inactive_time = code_value() * 1000; |
|
1172 break; |
|
1173 case 92: // M92 |
|
1174 for(int8_t i=0; i < NUM_AXIS; i++) |
|
1175 { |
|
1176 if(code_seen(axis_codes[i])) |
|
1177 axis_steps_per_unit[i] = code_value(); |
|
1178 } |
|
1179 break; |
|
1180 case 115: // M115 |
|
1181 SerialprintPGM(MSG_M115_REPORT); |
|
1182 break; |
|
1183 case 117: // M117 display message |
|
1184 LCD_MESSAGE(cmdbuffer[bufindr]+5); |
|
1185 break; |
|
1186 case 114: // M114 |
|
1187 SERIAL_PROTOCOLPGM("X:"); |
|
1188 SERIAL_PROTOCOL(current_position[X_AXIS]); |
|
1189 SERIAL_PROTOCOLPGM("Y:"); |
|
1190 SERIAL_PROTOCOL(current_position[Y_AXIS]); |
|
1191 SERIAL_PROTOCOLPGM("Z:"); |
|
1192 SERIAL_PROTOCOL(current_position[Z_AXIS]); |
|
1193 SERIAL_PROTOCOLPGM("E:"); |
|
1194 SERIAL_PROTOCOL(current_position[E_AXIS]); |
|
1195 |
|
1196 SERIAL_PROTOCOLPGM(MSG_COUNT_X); |
|
1197 SERIAL_PROTOCOL(float(st_get_position(X_AXIS))/axis_steps_per_unit[X_AXIS]); |
|
1198 SERIAL_PROTOCOLPGM("Y:"); |
|
1199 SERIAL_PROTOCOL(float(st_get_position(Y_AXIS))/axis_steps_per_unit[Y_AXIS]); |
|
1200 SERIAL_PROTOCOLPGM("Z:"); |
|
1201 SERIAL_PROTOCOL(float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]); |
|
1202 |
|
1203 SERIAL_PROTOCOLLN(""); |
|
1204 break; |
|
1205 case 120: // M120 |
|
1206 enable_endstops(false) ; |
|
1207 break; |
|
1208 case 121: // M121 |
|
1209 enable_endstops(true) ; |
|
1210 break; |
|
1211 case 119: // M119 |
|
1212 #if (X_MIN_PIN > -1) |
|
1213 SERIAL_PROTOCOLPGM(MSG_X_MIN); |
|
1214 SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1215 #endif |
|
1216 #if (X_MAX_PIN > -1) |
|
1217 SERIAL_PROTOCOLPGM(MSG_X_MAX); |
|
1218 SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1219 #endif |
|
1220 #if (Y_MIN_PIN > -1) |
|
1221 SERIAL_PROTOCOLPGM(MSG_Y_MIN); |
|
1222 SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1223 #endif |
|
1224 #if (Y_MAX_PIN > -1) |
|
1225 SERIAL_PROTOCOLPGM(MSG_Y_MAX); |
|
1226 SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1227 #endif |
|
1228 #if (Z_MIN_PIN > -1) |
|
1229 SERIAL_PROTOCOLPGM(MSG_Z_MIN); |
|
1230 SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1231 #endif |
|
1232 #if (Z_MAX_PIN > -1) |
|
1233 SERIAL_PROTOCOLPGM(MSG_Z_MAX); |
|
1234 SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); |
|
1235 #endif |
|
1236 SERIAL_PROTOCOLLN(""); |
|
1237 break; |
|
1238 case 201: // M201 |
|
1239 for(int8_t i=0; i < NUM_AXIS; i++) |
|
1240 { |
|
1241 if(code_seen(axis_codes[i])) |
|
1242 { |
|
1243 max_acceleration_units_per_sq_second[i] = code_value(); |
|
1244 axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; |
|
1245 } |
|
1246 } |
|
1247 break; |
|
1248 #if 0 // Not used for Sprinter/grbl gen6 |
|
1249 case 202: // M202 |
|
1250 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
1251 if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; |
|
1252 } |
|
1253 break; |
|
1254 #endif |
|
1255 case 203: // M203 max feedrate mm/sec |
|
1256 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
1257 if(code_seen(axis_codes[i])) max_feedrate[i] = code_value(); |
|
1258 } |
|
1259 break; |
|
1260 case 204: // M204 acclereration S normal moves T filmanent only moves |
|
1261 { |
|
1262 if(code_seen('S')) acceleration = code_value() ; |
|
1263 if(code_seen('T')) retract_acceleration = code_value() ; |
|
1264 } |
|
1265 break; |
|
1266 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 |
|
1267 { |
|
1268 if(code_seen('S')) minimumfeedrate = code_value(); |
|
1269 if(code_seen('T')) mintravelfeedrate = code_value(); |
|
1270 if(code_seen('B')) minsegmenttime = code_value() ; |
|
1271 if(code_seen('X')) max_xy_jerk = code_value() ; |
|
1272 if(code_seen('Z')) max_z_jerk = code_value() ; |
|
1273 if(code_seen('E')) max_e_jerk = code_value() ; |
|
1274 #ifdef ADVANCE |
|
1275 if(code_seen('K')) advance_k = code_value() ; |
|
1276 #endif |
|
1277 } |
|
1278 break; |
|
1279 case 206: // M206 additional homeing offset |
|
1280 for(int8_t i=0; i < 3; i++) |
|
1281 { |
|
1282 if(code_seen(axis_codes[i])) add_homeing[i] = code_value(); |
|
1283 } |
|
1284 break; |
|
1285 case 208: // M208 set axis max length |
|
1286 for(int8_t i=0; i < 3; i++) |
|
1287 { |
|
1288 if(code_seen(axis_codes[i])) { |
|
1289 max_length[i] = code_value(); |
|
1290 SERIAL_PROTOCOL(axis_codes[i]); |
|
1291 SERIAL_PROTOCOL(" Axis max length: "); |
|
1292 SERIAL_PROTOCOL(max_length[i]); |
|
1293 } |
|
1294 } |
|
1295 break; |
|
1296 case 220: // M220 S<factor in percent>- set speed factor override percentage |
|
1297 { |
|
1298 if(code_seen('S')) |
|
1299 { |
|
1300 feedmultiply = code_value() ; |
|
1301 feedmultiplychanged=true; |
|
1302 } |
|
1303 } |
|
1304 break; |
|
1305 case 221: // M221 S<factor in percent>- set extrude factor override percentage |
|
1306 { |
|
1307 if(code_seen('S')) |
|
1308 { |
|
1309 extrudemultiply = code_value() ; |
|
1310 } |
|
1311 } |
|
1312 break; |
|
1313 |
|
1314 #ifdef PIDTEMP |
|
1315 case 301: // M301 |
|
1316 { |
|
1317 if(code_seen('P')) Kp = code_value(); |
|
1318 if(code_seen('I')) Ki = code_value()*PID_dT; |
|
1319 if(code_seen('D')) Kd = code_value()/PID_dT; |
|
1320 if(code_seen('W')) Ki_Max = constrain(code_value(),0,255); |
|
1321 |
|
1322 updatePID(); |
|
1323 SERIAL_PROTOCOL(MSG_OK); |
|
1324 SERIAL_PROTOCOL(" p:"); |
|
1325 SERIAL_PROTOCOL(Kp); |
|
1326 SERIAL_PROTOCOL(" i:"); |
|
1327 SERIAL_PROTOCOL(Ki/PID_dT); |
|
1328 SERIAL_PROTOCOL(" d:"); |
|
1329 SERIAL_PROTOCOL(Kd*PID_dT); |
|
1330 SERIAL_PROTOCOL(" w:"); |
|
1331 SERIAL_PROTOCOL(Ki_Max); |
|
1332 |
|
1333 SERIAL_PROTOCOLLN(""); |
|
1334 } |
|
1335 break; |
|
1336 #endif //PIDTEMP |
|
1337 case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/ |
|
1338 { |
|
1339 #ifdef PHOTOGRAPH_PIN |
|
1340 #if (PHOTOGRAPH_PIN > -1) |
|
1341 const uint8_t NUM_PULSES=16; |
|
1342 const float PULSE_LENGTH=0.01524; |
|
1343 for(int i=0; i < NUM_PULSES; i++) { |
|
1344 WRITE(PHOTOGRAPH_PIN, HIGH); |
|
1345 _delay_ms(PULSE_LENGTH); |
|
1346 WRITE(PHOTOGRAPH_PIN, LOW); |
|
1347 _delay_ms(PULSE_LENGTH); |
|
1348 } |
|
1349 delay(7.33); |
|
1350 for(int i=0; i < NUM_PULSES; i++) { |
|
1351 WRITE(PHOTOGRAPH_PIN, HIGH); |
|
1352 _delay_ms(PULSE_LENGTH); |
|
1353 WRITE(PHOTOGRAPH_PIN, LOW); |
|
1354 _delay_ms(PULSE_LENGTH); |
|
1355 } |
|
1356 #endif |
|
1357 #endif |
|
1358 } |
|
1359 break; |
|
1360 |
|
1361 case 302: // allow cold extrudes |
|
1362 { |
|
1363 if (code_seen('S')) |
|
1364 { |
|
1365 allow_cold_extrudes(code_value()); |
|
1366 }else{ |
|
1367 allow_cold_extrudes(true); |
|
1368 } |
|
1369 } |
|
1370 break; |
|
1371 case 303: // M303 PID autotune |
|
1372 { |
|
1373 float temp = 150.0; |
|
1374 if (code_seen('S')) temp=code_value(); |
|
1375 PID_autotune(temp); |
|
1376 } |
|
1377 break; |
|
1378 case 304: // Set thermistor parameters |
|
1379 { |
|
1380 // M304 H0 B3960 R4700 |
|
1381 // M304 H1 Bb Rr |
|
1382 if (code_seen('H')) |
|
1383 { |
|
1384 if(!code_value()){ |
|
1385 //set BED thermistor |
|
1386 if(code_seen('B')) b_beta = code_value(); |
|
1387 if(code_seen('R')) b_resistor = code_value(); |
|
1388 if(code_seen('T')) b_thermistor = code_value(); |
|
1389 b_inf = ( b_thermistor*exp(-b_beta/298.15) ); |
|
1390 SERIAL_PROTOCOL(MSG_OK); |
|
1391 SERIAL_PROTOCOL(" M304 H0 B"); |
|
1392 SERIAL_PROTOCOL(b_beta); |
|
1393 SERIAL_PROTOCOL(" R"); |
|
1394 SERIAL_PROTOCOL(b_resistor); |
|
1395 SERIAL_PROTOCOL(" T"); |
|
1396 SERIAL_PROTOCOL(b_thermistor); |
|
1397 SERIAL_PROTOCOLLN(""); |
|
1398 }else{ |
|
1399 //set active Nozzle thermistor |
|
1400 if(code_seen('B')) n_beta = code_value(); |
|
1401 if(code_seen('R')) n_resistor = code_value(); |
|
1402 if(code_seen('T')) n_thermistor = code_value(); |
|
1403 n_inf = ( n_thermistor*exp(-n_beta/298.15) ); |
|
1404 SERIAL_PROTOCOL(MSG_OK); |
|
1405 SERIAL_PROTOCOL(" M304 H1 B"); |
|
1406 SERIAL_PROTOCOL(n_beta); |
|
1407 SERIAL_PROTOCOL(" R"); |
|
1408 SERIAL_PROTOCOL(n_resistor); |
|
1409 SERIAL_PROTOCOL(" T"); |
|
1410 SERIAL_PROTOCOL(n_thermistor); |
|
1411 SERIAL_PROTOCOLLN(""); |
|
1412 } |
|
1413 } |
|
1414 } |
|
1415 break; |
|
1416 case 400: // M400 finish all moves |
|
1417 { |
|
1418 st_synchronize(); |
|
1419 } |
|
1420 break; |
|
1421 case 500: // Store settings in EEPROM |
|
1422 { |
|
1423 EEPROM_StoreSettings(); |
|
1424 } |
|
1425 break; |
|
1426 case 501: // Read settings from EEPROM |
|
1427 { |
|
1428 EEPROM_RetrieveSettings(); |
|
1429 } |
|
1430 break; |
|
1431 case 502: // Revert to default settings |
|
1432 { |
|
1433 EEPROM_RetrieveSettings(true); |
|
1434 } |
|
1435 break; |
|
1436 case 503: // print settings currently in memory |
|
1437 { |
|
1438 EEPROM_printSettings(); |
|
1439 } |
|
1440 break; |
|
1441 case 504: // print free memory |
|
1442 { |
|
1443 SERIAL_ECHO_START; |
|
1444 SERIAL_ECHOPGM("Free Memory:"); |
|
1445 SERIAL_ECHO(freeMemory()); |
|
1446 } |
|
1447 break; |
|
1448 case 999: // Restart after being stopped |
|
1449 Stopped = false; |
|
1450 gcode_LastN = Stopped_gcode_LastN; |
|
1451 FlushSerialRequestResend(); |
|
1452 break; |
|
1453 case 510: // FPU Enable |
|
1454 { |
|
1455 FPUEnable(); |
|
1456 } |
|
1457 break; |
|
1458 case 511: // FPU Reset |
|
1459 { |
|
1460 FPUReset(); |
|
1461 } |
|
1462 break; |
|
1463 case 512: // FPU Disable |
|
1464 { |
|
1465 FPUDisable(); |
|
1466 } |
|
1467 break; |
|
1468 #ifdef REPRAPPRO_MULTIMATERIALS |
|
1469 case 555: // Slave comms test |
|
1470 talkToSlave("t 0"); |
|
1471 SERIAL_ECHO_START; |
|
1472 SERIAL_ECHOPGM("Slave response:"); |
|
1473 SERIAL_ECHO(listenToSlave()); |
|
1474 break; |
|
1475 case 556: // Set temp |
|
1476 talkToSlave("T 0 100"); |
|
1477 break; |
|
1478 case 557: // Call stepper test |
|
1479 talkToSlave("A"); |
|
1480 break; |
|
1481 case 558: // Send interrupt |
|
1482 for(int ii=0; ii < 1000; ii++) |
|
1483 { |
|
1484 toggleSlaveClock(); |
|
1485 delay(1); |
|
1486 } |
|
1487 break; |
|
1488 #endif |
|
1489 |
|
1490 case 571: // enable extruder active pin |
|
1491 if (code_seen('S')) |
|
1492 { |
|
1493 m571_enabled = (int)code_value(); |
|
1494 } |
|
1495 |
|
1496 if (code_seen('E')) |
|
1497 { |
|
1498 n571_enabled = (int)code_value(); |
|
1499 } |
|
1500 |
|
1501 WRITE(M571_PIN, LOW);// M571 disable in any case! |
|
1502 |
|
1503 SERIAL_ECHO_START; |
|
1504 SERIAL_ECHO("Parameters: S<0|1> enable extruder active pin, E<0|1> if enabled prevent real drive movement"); |
|
1505 |
|
1506 SERIAL_ECHO_START; |
|
1507 SERIAL_ECHO("Extruder active pin: "); |
|
1508 if (m571_enabled) { |
|
1509 SERIAL_ECHOLN("enabled"); |
|
1510 } else { |
|
1511 SERIAL_ECHOLN("disabled"); |
|
1512 } |
|
1513 |
|
1514 SERIAL_ECHO_START; |
|
1515 SERIAL_ECHO("Extruder motor move: "); |
|
1516 if (!n571_enabled) { |
|
1517 SERIAL_ECHOLN("enabled"); |
|
1518 } else { |
|
1519 SERIAL_ECHOLN("disabled"); |
|
1520 } |
|
1521 |
|
1522 break; |
|
1523 |
|
1524 |
|
1525 |
|
1526 } |
|
1527 } |
|
1528 |
|
1529 else if(code_seen('T')) |
|
1530 { |
|
1531 tmp_extruder = code_value(); |
|
1532 if(tmp_extruder >= EXTRUDERS) |
|
1533 { |
|
1534 SERIAL_ECHO_START; |
|
1535 SERIAL_ECHO(MSG_STANDBY_TEMP); |
|
1536 SERIAL_ECHO(active_extruder); |
|
1537 setTargetHotend(extruder_standby[active_extruder], active_extruder); |
|
1538 } |
|
1539 else |
|
1540 { |
|
1541 if((tmp_extruder != active_extruder) || !extruder_selected) |
|
1542 { |
|
1543 setTargetHotend(extruder_standby[active_extruder], active_extruder); |
|
1544 extruder_selected = true; |
|
1545 |
|
1546 // Deal with offsets here: record current pos as temp_position; |
|
1547 // move to temp_position + tmp_extruder - active_extruder; |
|
1548 // Set current pos to be temp_position |
|
1549 // TOTHINKABOUT: What about cumulative errors with a LOT of extruder changes? |
|
1550 |
|
1551 for(int8_t i=0; i < NUM_AXIS; i++) |
|
1552 { |
|
1553 temp_position[i] = current_position[i]; |
|
1554 destination[i] = current_position[i]; |
|
1555 } |
|
1556 next_feedrate = feedrate; |
|
1557 x_off_d = extruder_x_off[tmp_extruder] - extruder_x_off[active_extruder]; |
|
1558 y_off_d = extruder_y_off[tmp_extruder] - extruder_y_off[active_extruder]; |
|
1559 z_off_d = extruder_z_off[tmp_extruder] - extruder_z_off[active_extruder]; |
|
1560 |
|
1561 if(z_off_d > 0) |
|
1562 { |
|
1563 destination[Z_AXIS] += z_off_d; |
|
1564 feedrate = fast_home_feedrate[Z_AXIS]; |
|
1565 prepare_move(); |
|
1566 destination[X_AXIS] = temp_position[X_AXIS] + x_off_d; |
|
1567 destination[Y_AXIS] = temp_position[Y_AXIS] + y_off_d; |
|
1568 feedrate = fast_home_feedrate[X_AXIS]; |
|
1569 prepare_move(); |
|
1570 } else |
|
1571 { |
|
1572 destination[X_AXIS] += x_off_d; |
|
1573 destination[Y_AXIS] += y_off_d; |
|
1574 feedrate = fast_home_feedrate[X_AXIS]; |
|
1575 prepare_move(); |
|
1576 destination[Z_AXIS] = temp_position[Z_AXIS] + z_off_d; |
|
1577 feedrate = fast_home_feedrate[Z_AXIS]; |
|
1578 prepare_move(); |
|
1579 } |
|
1580 |
|
1581 for(int8_t i=0; i < NUM_AXIS; i++) |
|
1582 current_position[i] = temp_position[i]; |
|
1583 feedrate = next_feedrate; |
|
1584 active_extruder = tmp_extruder; |
|
1585 |
|
1586 SERIAL_ECHO_START; |
|
1587 SERIAL_ECHO(MSG_ACTIVE_EXTRUDER); |
|
1588 SERIAL_PROTOCOLLN((int)active_extruder); |
|
1589 |
|
1590 setTargetHotend(extruder_temperature[active_extruder], active_extruder); |
|
1591 |
|
1592 |
|
1593 codenum = millis(); |
|
1594 wait_for_temp(active_extruder, codenum); |
|
1595 } |
|
1596 } |
|
1597 } |
|
1598 |
|
1599 |
|
1600 else |
|
1601 { |
|
1602 SERIAL_ECHO_START; |
|
1603 SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); |
|
1604 SERIAL_ECHO(cmdbuffer[bufindr]); |
|
1605 SERIAL_ECHOLNPGM("\""); |
|
1606 } |
|
1607 |
|
1608 ClearToSend(); |
|
1609 } |
|
1610 |
|
1611 void FlushSerialRequestResend() |
|
1612 { |
|
1613 //char cmdbuffer[bufindr][100]="Resend:"; |
|
1614 MYSERIAL.flush(); |
|
1615 SERIAL_PROTOCOLPGM(MSG_RESEND); |
|
1616 SERIAL_PROTOCOLLN(gcode_LastN + 1); |
|
1617 ClearToSend(); |
|
1618 } |
|
1619 |
|
1620 void ClearToSend() |
|
1621 { |
|
1622 previous_millis_cmd = millis(); |
|
1623 #ifdef SDSUPPORT |
|
1624 if(fromsd[bufindr]) |
|
1625 return; |
|
1626 #endif //SDSUPPORT |
|
1627 SERIAL_PROTOCOLLNPGM(MSG_OK); |
|
1628 } |
|
1629 |
|
1630 void get_coordinates() |
|
1631 { |
|
1632 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
1633 if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i]; |
|
1634 else destination[i] = current_position[i]; //Are these else lines really needed? |
|
1635 } |
|
1636 if(code_seen('F')) { |
|
1637 next_feedrate = code_value(); |
|
1638 if(next_feedrate > 0.0) feedrate = next_feedrate; |
|
1639 } |
|
1640 } |
|
1641 |
|
1642 void get_arc_coordinates() |
|
1643 { |
|
1644 get_coordinates(); |
|
1645 if(code_seen('I')) { |
|
1646 offset[0] = code_value(); |
|
1647 } |
|
1648 else { |
|
1649 offset[0] = 0.0; |
|
1650 } |
|
1651 if(code_seen('J')) { |
|
1652 offset[1] = code_value(); |
|
1653 } |
|
1654 else { |
|
1655 offset[1] = 0.0; |
|
1656 } |
|
1657 } |
|
1658 |
|
1659 void prepare_move() |
|
1660 { |
|
1661 |
|
1662 // transform destination ********************************************* |
|
1663 |
|
1664 FPUTransform_transformDestination(); |
|
1665 |
|
1666 if (min_software_endstops) { |
|
1667 if (modified_destination[X_AXIS] < X_HOME_POS) modified_destination[X_AXIS] = X_HOME_POS; |
|
1668 if (modified_destination[Y_AXIS] < Y_HOME_POS) modified_destination[Y_AXIS] = Y_HOME_POS; |
|
1669 if (modified_destination[Z_AXIS] < Z_HOME_POS) modified_destination[Z_AXIS] = Z_HOME_POS; |
|
1670 } |
|
1671 |
|
1672 if (max_software_endstops) { |
|
1673 if (modified_destination[X_AXIS] > max_length[X_AXIS]) modified_destination[X_AXIS] = max_length[X_AXIS]; |
|
1674 if (modified_destination[Y_AXIS] > max_length[Y_AXIS]) modified_destination[Y_AXIS] = max_length[Y_AXIS]; |
|
1675 if (modified_destination[Z_AXIS] > max_length[Z_AXIS]) modified_destination[Z_AXIS] = max_length[Z_AXIS]; |
|
1676 } |
|
1677 previous_millis_cmd = millis(); |
|
1678 plan_buffer_line(modified_destination[X_AXIS], modified_destination[Y_AXIS], modified_destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder); |
|
1679 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
1680 current_position[i] = destination[i]; |
|
1681 } |
|
1682 } |
|
1683 |
|
1684 void prepare_arc_move(char isclockwise) { |
|
1685 float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc |
|
1686 |
|
1687 // transform destination ********************************************* |
|
1688 FPUTransform_transformDestination(); |
|
1689 |
|
1690 // Trace the arc |
|
1691 mc_arc(current_position, modified_destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder); |
|
1692 |
|
1693 // As far as the parser is concerned, the position is now == target. In reality the |
|
1694 // motion control system might still be processing the action and the real tool position |
|
1695 // in any intermediate location. |
|
1696 for(int8_t i=0; i < NUM_AXIS; i++) { |
|
1697 current_position[i] = destination[i]; |
|
1698 } |
|
1699 previous_millis_cmd = millis(); |
|
1700 } |
|
1701 |
|
1702 #ifdef CONTROLLERFAN_PIN |
|
1703 unsigned long lastMotor = 0; //Save the time for when a motor was turned on last |
|
1704 unsigned long lastMotorCheck = 0; |
|
1705 |
|
1706 void controllerFan() |
|
1707 { |
|
1708 if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms |
|
1709 { |
|
1710 lastMotorCheck = millis(); |
|
1711 |
|
1712 if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) |
|
1713 #if EXTRUDERS > 2 |
|
1714 || !READ(E2_ENABLE_PIN) |
|
1715 #endif |
|
1716 #if EXTRUDER > 1 |
|
1717 || !READ(E2_ENABLE_PIN) |
|
1718 #endif |
|
1719 || !READ(E0_ENABLE_PIN)) //If any of the drivers are enabled... |
|
1720 { |
|
1721 lastMotor = millis(); //... set time to NOW so the fan will turn on |
|
1722 } |
|
1723 |
|
1724 if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC... |
|
1725 { |
|
1726 WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off |
|
1727 } |
|
1728 else |
|
1729 { |
|
1730 WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on |
|
1731 } |
|
1732 } |
|
1733 } |
|
1734 #endif |
|
1735 |
|
1736 void manage_inactivity(byte debug) |
|
1737 { |
|
1738 if( (millis() - previous_millis_cmd) > max_inactive_time ) |
|
1739 if(max_inactive_time) |
|
1740 kill(); |
|
1741 if(stepper_inactive_time) { |
|
1742 if( (millis() - previous_millis_cmd) > stepper_inactive_time ) |
|
1743 { |
|
1744 if(blocks_queued() == false) { |
|
1745 disable_x(); |
|
1746 disable_y(); |
|
1747 disable_z(); |
|
1748 disable_e0(); |
|
1749 disable_e1(); |
|
1750 disable_e2(); |
|
1751 if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable |
|
1752 } |
|
1753 } |
|
1754 } |
|
1755 #ifdef CONTROLLERFAN_PIN |
|
1756 controllerFan(); //Check if fan should be turned on to cool stepper drivers down |
|
1757 #endif |
|
1758 check_axes_activity(); |
|
1759 } |
|
1760 |
|
1761 void kill() |
|
1762 { |
|
1763 cli(); // Stop interrupts |
|
1764 disable_heater(); |
|
1765 |
|
1766 disable_x(); |
|
1767 disable_y(); |
|
1768 disable_z(); |
|
1769 disable_e0(); |
|
1770 disable_e1(); |
|
1771 disable_e2(); |
|
1772 if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable |
|
1773 |
|
1774 SERIAL_ERROR_START; |
|
1775 SERIAL_ERRORLNPGM(MSG_ERR_KILLED); |
|
1776 LCD_MESSAGEPGM(MSG_KILLED); |
|
1777 suicide(); |
|
1778 while(1); // Wait for reset |
|
1779 } |
|
1780 |
|
1781 void Stop() |
|
1782 { |
|
1783 disable_heater(); |
|
1784 if(Stopped == false) { |
|
1785 Stopped = true; |
|
1786 Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart |
|
1787 if (m571_enabled) WRITE(M571_PIN, LOW);// M571 disable |
|
1788 SERIAL_ERROR_START; |
|
1789 SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); |
|
1790 LCD_MESSAGEPGM(MSG_STOPPED); |
|
1791 } |
|
1792 } |
|
1793 |
|
1794 bool IsStopped() { return Stopped; }; |
|
1795 |
|
1796 |