My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. /*
  2. Reprap firmware based on Sprinter and grbl.
  3. Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /*
  16. This firmware is a mashup between Sprinter and grbl.
  17. (https://github.com/kliment/Sprinter)
  18. (https://github.com/simen/grbl/tree)
  19. It has preliminary support for Matthew Roberts advance algorithm
  20. http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
  21. */
  22. #include <EEPROM.h>
  23. #include "EEPROMwrite.h"
  24. #include "fastio.h"
  25. #include "Configuration.h"
  26. #include "pins.h"
  27. #include "Marlin.h"
  28. #include "ultralcd.h"
  29. #include "streaming.h"
  30. #include "planner.h"
  31. #include "stepper.h"
  32. #include "temperature.h"
  33. #include "motion_control.h"
  34. #include "cardreader.h"
  35. char version_string[] = "1.0.0 Alpha 1";
  36. // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html
  37. // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
  38. //Implemented Codes
  39. //-------------------
  40. // G0 -> G1
  41. // G1 - Coordinated Movement X Y Z E
  42. // G2 - CW ARC
  43. // G3 - CCW ARC
  44. // G4 - Dwell S<seconds> or P<milliseconds>
  45. // G28 - Home all Axis
  46. // G90 - Use Absolute Coordinates
  47. // G91 - Use Relative Coordinates
  48. // G92 - Set current position to cordinates given
  49. //RepRap M Codes
  50. // M104 - Set extruder target temp
  51. // M105 - Read current temp
  52. // M106 - Fan on
  53. // M107 - Fan off
  54. // M109 - Wait for extruder current temp to reach target temp.
  55. // M114 - Display current position
  56. //Custom M Codes
  57. // M20 - List SD card
  58. // M21 - Init SD card
  59. // M22 - Release SD card
  60. // M23 - Select SD file (M23 filename.g)
  61. // M24 - Start/resume SD print
  62. // M25 - Pause SD print
  63. // M26 - Set SD position in bytes (M26 S12345)
  64. // M27 - Report SD print status
  65. // M28 - Start SD write (M28 filename.g)
  66. // M29 - Stop SD write
  67. // M30 - Output time since last M109 or SD card start to serial
  68. // M42 - Change pin status via gcode
  69. // M80 - Turn on Power Supply
  70. // M81 - Turn off Power Supply
  71. // M82 - Set E codes absolute (default)
  72. // M83 - Set E codes relative while in Absolute Coordinates (G90) mode
  73. // M84 - Disable steppers until next move,
  74. // or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout.
  75. // M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
  76. // M92 - Set axis_steps_per_unit - same syntax as G92
  77. // M115 - Capabilities string
  78. // M140 - Set bed target temp
  79. // M190 - Wait for bed current temp to reach target temp.
  80. // M200 - Set filament diameter
  81. // M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
  82. // M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
  83. // M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
  84. // 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
  85. // M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
  86. // M220 - set speed factor override percentage S:factor in percent
  87. // M301 - Set PID parameters P I and D
  88. // M500 - stores paramters in EEPROM
  89. // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D
  90. // M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
  91. //Stepper Movement Variables
  92. //===========================================================================
  93. //=============================imported variables============================
  94. //===========================================================================
  95. extern float HeaterPower;
  96. //===========================================================================
  97. //=============================public variables=============================
  98. //===========================================================================
  99. CardReader card;
  100. float homing_feedrate[] = HOMING_FEEDRATE;
  101. bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
  102. volatile int feedmultiply=100; //100->1 200->2
  103. int saved_feedmultiply;
  104. volatile bool feedmultiplychanged=false;
  105. //===========================================================================
  106. //=============================private variables=============================
  107. //===========================================================================
  108. const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
  109. static float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0};
  110. static float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0};
  111. static float offset[3] = {0.0, 0.0, 0.0};
  112. static bool home_all_axis = true;
  113. static float feedrate = 1500.0, next_feedrate, saved_feedrate;
  114. static long gcode_N, gcode_LastN;
  115. static bool relative_mode = false; //Determines Absolute or Relative Coordinates
  116. 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.
  117. static uint8_t fanpwm=0;
  118. static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
  119. static bool fromsd[BUFSIZE];
  120. static int bufindr = 0;
  121. static int bufindw = 0;
  122. static int buflen = 0;
  123. static int i = 0;
  124. static char serial_char;
  125. static int serial_count = 0;
  126. static boolean comment_mode = false;
  127. static char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc
  128. const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
  129. static float tt = 0, bt = 0;
  130. //Inactivity shutdown variables
  131. static unsigned long previous_millis_cmd = 0;
  132. static unsigned long max_inactive_time = 0;
  133. static unsigned long stepper_inactive_time = 0;
  134. static unsigned long starttime=0;
  135. static unsigned long stoptime=0;
  136. //===========================================================================
  137. //=============================ROUTINES=============================
  138. //===========================================================================
  139. //adds an command to the main command buffer
  140. //thats really done in a non-safe way.
  141. //needs overworking someday
  142. void enquecommand(const char *cmd)
  143. {
  144. if(buflen < BUFSIZE)
  145. {
  146. //this is dangerous if a mixing of serial and this happsens
  147. strcpy(&(cmdbuffer[bufindw][0]),cmd);
  148. SERIAL_ECHOLN("enqueing \""<<cmdbuffer[bufindw]<<"\"");
  149. bufindw= (bufindw + 1)%BUFSIZE;
  150. buflen += 1;
  151. }
  152. }
  153. void setup()
  154. {
  155. Serial.begin(BAUDRATE);
  156. SERIAL_ECHOLN("Marlin "<<version_string);
  157. Serial.println("start");
  158. for(int i = 0; i < BUFSIZE; i++)
  159. {
  160. fromsd[i] = false;
  161. }
  162. RetrieveSettings(); // loads data from EEPROM if available
  163. for(int i=0; i < NUM_AXIS; i++)
  164. {
  165. axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
  166. }
  167. plan_init(); // Initialize planner;
  168. st_init(); // Initialize stepper;
  169. tp_init(); // Initialize temperature loop
  170. }
  171. void loop()
  172. {
  173. if(buflen<3)
  174. get_command();
  175. card.checkautostart(false);
  176. if(buflen)
  177. {
  178. #ifdef SDSUPPORT
  179. if(card.savetosd)
  180. {
  181. if(strstr(cmdbuffer[bufindr],"M29") == NULL)
  182. {
  183. card.write_command(cmdbuffer[bufindr]);
  184. Serial.println("ok");
  185. }
  186. else
  187. {
  188. card.closefile();
  189. Serial.println("Done saving file.");
  190. }
  191. }
  192. else
  193. {
  194. process_commands();
  195. }
  196. #else
  197. process_commands();
  198. #endif //SDSUPPORT
  199. buflen = (buflen-1);
  200. bufindr = (bufindr + 1)%BUFSIZE;
  201. }
  202. //check heater every n milliseconds
  203. manage_heater();
  204. manage_inactivity(1);
  205. LCD_STATUS;
  206. }
  207. inline void get_command()
  208. {
  209. while( Serial.available() > 0 && buflen < BUFSIZE) {
  210. serial_char = Serial.read();
  211. if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) )
  212. {
  213. if(!serial_count) return; //if empty line
  214. cmdbuffer[bufindw][serial_count] = 0; //terminate string
  215. if(!comment_mode){
  216. fromsd[bufindw] = false;
  217. if(strstr(cmdbuffer[bufindw], "N") != NULL)
  218. {
  219. strchr_pointer = strchr(cmdbuffer[bufindw], 'N');
  220. gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));
  221. if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) {
  222. Serial.print("Serial Error: Line Number is not Last Line Number+1, Last Line:");
  223. Serial.println(gcode_LastN);
  224. //Serial.println(gcode_N);
  225. FlushSerialRequestResend();
  226. serial_count = 0;
  227. return;
  228. }
  229. if(strstr(cmdbuffer[bufindw], "*") != NULL)
  230. {
  231. byte checksum = 0;
  232. byte count = 0;
  233. while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];
  234. strchr_pointer = strchr(cmdbuffer[bufindw], '*');
  235. if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) {
  236. Serial.print("Error: checksum mismatch, Last Line:");
  237. Serial.println(gcode_LastN);
  238. FlushSerialRequestResend();
  239. serial_count = 0;
  240. return;
  241. }
  242. //if no errors, continue parsing
  243. }
  244. else
  245. {
  246. Serial.print("Error: No Checksum with line number, Last Line:");
  247. Serial.println(gcode_LastN);
  248. FlushSerialRequestResend();
  249. serial_count = 0;
  250. return;
  251. }
  252. gcode_LastN = gcode_N;
  253. //if no errors, continue parsing
  254. }
  255. else // if we don't receive 'N' but still see '*'
  256. {
  257. if((strstr(cmdbuffer[bufindw], "*") != NULL))
  258. {
  259. Serial.print("Error: No Line Number with checksum, Last Line:");
  260. Serial.println(gcode_LastN);
  261. serial_count = 0;
  262. return;
  263. }
  264. }
  265. if((strstr(cmdbuffer[bufindw], "G") != NULL)){
  266. strchr_pointer = strchr(cmdbuffer[bufindw], 'G');
  267. switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){
  268. case 0:
  269. case 1:
  270. case 2:
  271. case 3:
  272. #ifdef SDSUPPORT
  273. if(card.savetosd)
  274. break;
  275. #endif //SDSUPPORT
  276. Serial.println("ok");
  277. break;
  278. default:
  279. break;
  280. }
  281. }
  282. bufindw = (bufindw + 1)%BUFSIZE;
  283. buflen += 1;
  284. }
  285. comment_mode = false; //for new command
  286. serial_count = 0; //clear buffer
  287. }
  288. else
  289. {
  290. if(serial_char == ';') comment_mode = true;
  291. if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
  292. }
  293. }
  294. #ifdef SDSUPPORT
  295. if(!card.sdmode || serial_count!=0){
  296. return;
  297. }
  298. while( card.filesize > card.sdpos && buflen < BUFSIZE) {
  299. short n = card.file.read();
  300. serial_char = (char)n;
  301. if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1)
  302. {
  303. card.sdpos = card.file.curPosition();
  304. if(card.sdpos >= card.filesize){
  305. card.sdmode = false;
  306. Serial.println("echo: Done printing file");
  307. stoptime=millis();
  308. char time[30];
  309. unsigned long t=(stoptime-starttime)/1000;
  310. int sec,min;
  311. min=t/60;
  312. sec=t%60;
  313. sprintf(time,"echo: %i min, %i sec",min,sec);
  314. Serial.println(time);
  315. LCD_MESSAGE(time);
  316. card.checkautostart(true);
  317. }
  318. if(!serial_count)
  319. return; //if empty line
  320. cmdbuffer[bufindw][serial_count] = 0; //terminate string
  321. if(!comment_mode){
  322. fromsd[bufindw] = true;
  323. buflen += 1;
  324. bufindw = (bufindw + 1)%BUFSIZE;
  325. }
  326. comment_mode = false; //for new command
  327. serial_count = 0; //clear buffer
  328. }
  329. else
  330. {
  331. if(serial_char == ';') comment_mode = true;
  332. if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
  333. }
  334. }
  335. #endif //SDSUPPORT
  336. }
  337. inline float code_value()
  338. {
  339. return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL));
  340. }
  341. inline long code_value_long()
  342. {
  343. return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10));
  344. }
  345. inline bool code_seen(char code_string[]) //Return True if the string was found
  346. {
  347. return (strstr(cmdbuffer[bufindr], code_string) != NULL);
  348. }
  349. inline bool code_seen(char code)
  350. {
  351. strchr_pointer = strchr(cmdbuffer[bufindr], code);
  352. return (strchr_pointer != NULL); //Return True if a character was found
  353. }
  354. inline void process_commands()
  355. {
  356. unsigned long codenum; //throw away variable
  357. char *starpos = NULL;
  358. if(code_seen('G'))
  359. {
  360. switch((int)code_value())
  361. {
  362. case 0: // G0 -> G1
  363. case 1: // G1
  364. get_coordinates(); // For X Y Z E F
  365. prepare_move();
  366. previous_millis_cmd = millis();
  367. //ClearToSend();
  368. return;
  369. //break;
  370. case 2: // G2 - CW ARC
  371. get_arc_coordinates();
  372. prepare_arc_move(true);
  373. previous_millis_cmd = millis();
  374. return;
  375. case 3: // G3 - CCW ARC
  376. get_arc_coordinates();
  377. prepare_arc_move(false);
  378. previous_millis_cmd = millis();
  379. return;
  380. case 4: // G4 dwell
  381. codenum = 0;
  382. if(code_seen('P')) codenum = code_value(); // milliseconds to wait
  383. if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
  384. codenum += millis(); // keep track of when we started waiting
  385. while(millis() < codenum ){
  386. manage_heater();
  387. }
  388. break;
  389. case 28: //G28 Home all Axis one at a time
  390. saved_feedrate = feedrate;
  391. saved_feedmultiply = feedmultiply;
  392. feedmultiply = 100;
  393. for(int i=0; i < NUM_AXIS; i++) {
  394. destination[i] = current_position[i];
  395. }
  396. feedrate = 0.0;
  397. home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));
  398. if((home_all_axis) || (code_seen(axis_codes[X_AXIS])))
  399. {
  400. if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){
  401. // st_synchronize();
  402. current_position[X_AXIS] = 0;
  403. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  404. destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;
  405. feedrate = homing_feedrate[X_AXIS];
  406. prepare_move();
  407. // st_synchronize();
  408. current_position[X_AXIS] = 0;
  409. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  410. destination[X_AXIS] = -5 * X_HOME_DIR;
  411. prepare_move();
  412. // st_synchronize();
  413. destination[X_AXIS] = 10 * X_HOME_DIR;
  414. feedrate = homing_feedrate[X_AXIS]/2 ;
  415. prepare_move();
  416. // st_synchronize();
  417. current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH;
  418. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  419. destination[X_AXIS] = current_position[X_AXIS];
  420. feedrate = 0.0;
  421. }
  422. }
  423. if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) {
  424. if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){
  425. current_position[Y_AXIS] = 0;
  426. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  427. destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR;
  428. feedrate = homing_feedrate[Y_AXIS];
  429. prepare_move();
  430. // st_synchronize();
  431. current_position[Y_AXIS] = 0;
  432. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  433. destination[Y_AXIS] = -5 * Y_HOME_DIR;
  434. prepare_move();
  435. // st_synchronize();
  436. destination[Y_AXIS] = 10 * Y_HOME_DIR;
  437. feedrate = homing_feedrate[Y_AXIS]/2;
  438. prepare_move();
  439. // st_synchronize();
  440. current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH;
  441. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  442. destination[Y_AXIS] = current_position[Y_AXIS];
  443. feedrate = 0.0;
  444. }
  445. }
  446. if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) {
  447. if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){
  448. current_position[Z_AXIS] = 0;
  449. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  450. destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR;
  451. feedrate = homing_feedrate[Z_AXIS];
  452. prepare_move();
  453. // st_synchronize();
  454. current_position[Z_AXIS] = 0;
  455. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  456. destination[Z_AXIS] = -2 * Z_HOME_DIR;
  457. prepare_move();
  458. // st_synchronize();
  459. destination[Z_AXIS] = 3 * Z_HOME_DIR;
  460. feedrate = homing_feedrate[Z_AXIS]/2;
  461. prepare_move();
  462. // st_synchronize();
  463. current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH;
  464. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  465. destination[Z_AXIS] = current_position[Z_AXIS];
  466. feedrate = 0.0;
  467. }
  468. }
  469. feedrate = saved_feedrate;
  470. feedmultiply = saved_feedmultiply;
  471. previous_millis_cmd = millis();
  472. break;
  473. case 90: // G90
  474. relative_mode = false;
  475. break;
  476. case 91: // G91
  477. relative_mode = true;
  478. break;
  479. case 92: // G92
  480. if(!code_seen(axis_codes[E_AXIS]))
  481. st_synchronize();
  482. for(int i=0; i < NUM_AXIS; i++) {
  483. if(code_seen(axis_codes[i])) current_position[i] = code_value();
  484. }
  485. plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  486. break;
  487. }
  488. }
  489. else if(code_seen('M'))
  490. {
  491. switch( (int)code_value() )
  492. {
  493. #ifdef SDSUPPORT
  494. case 20: // M20 - list SD card
  495. Serial.println("Begin file list");
  496. card.root.ls();
  497. Serial.println("End file list");
  498. break;
  499. case 21: // M21 - init SD card
  500. card.sdmode = false;
  501. card.initsd();
  502. break;
  503. case 22: //M22 - release SD card
  504. card.sdmode = false;
  505. card.sdactive = false;
  506. break;
  507. case 23: //M23 - Select file
  508. if(card.sdactive){
  509. card.sdmode = false;
  510. card.file.close();
  511. starpos = (strchr(strchr_pointer + 4,'*'));
  512. if(starpos!=NULL)
  513. *(starpos-1)='\0';
  514. if (card.file.open(&card.root, strchr_pointer + 4, O_READ)) {
  515. Serial.print("File opened:");
  516. Serial.print(strchr_pointer + 4);
  517. Serial.print(" Size:");
  518. Serial.println(card.file.fileSize());
  519. card.sdpos = 0;
  520. card.filesize = card.file.fileSize();
  521. Serial.println("File selected");
  522. }
  523. else{
  524. Serial.println("file.open failed");
  525. }
  526. }
  527. break;
  528. case 24: //M24 - Start SD print
  529. if(card.sdactive){
  530. card.sdmode = true;
  531. starttime=millis();
  532. }
  533. break;
  534. case 25: //M25 - Pause SD print
  535. if(card.sdmode){
  536. card.sdmode = false;
  537. }
  538. break;
  539. case 26: //M26 - Set SD index
  540. if(card.sdactive && code_seen('S')){
  541. card.sdpos = code_value_long();
  542. card.file.seekSet(card.sdpos);
  543. }
  544. break;
  545. case 27: //M27 - Get SD status
  546. if(card.sdactive){
  547. Serial.print("SD printing byte ");
  548. Serial.print(card.sdpos);
  549. Serial.print("/");
  550. Serial.println(card.filesize);
  551. }
  552. else{
  553. Serial.println("Not SD printing");
  554. }
  555. break;
  556. case 28: //M28 - Start SD write
  557. if(card.sdactive){
  558. char* npos = 0;
  559. card.file.close();
  560. card.sdmode = false;
  561. starpos = (strchr(strchr_pointer + 4,'*'));
  562. if(starpos != NULL){
  563. npos = strchr(cmdbuffer[bufindr], 'N');
  564. strchr_pointer = strchr(npos,' ') + 1;
  565. *(starpos-1) = '\0';
  566. }
  567. if (!card.file.open(&card.root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
  568. {
  569. Serial.print("open failed, File: ");
  570. Serial.print(strchr_pointer + 4);
  571. Serial.print(".");
  572. }
  573. else{
  574. card.savetosd = true;
  575. Serial.print("Writing to file: ");
  576. Serial.println(strchr_pointer + 4);
  577. }
  578. }
  579. break;
  580. case 29: //M29 - Stop SD write
  581. //processed in write to file routine above
  582. //savetosd = false;
  583. break;
  584. #endif //SDSUPPORT
  585. case 30: //M30 take time since the start of the SD print or an M109 command
  586. {
  587. stoptime=millis();
  588. char time[30];
  589. unsigned long t=(stoptime-starttime)/1000;
  590. int sec,min;
  591. min=t/60;
  592. sec=t%60;
  593. sprintf(time,"echo: time needed %i min, %i sec",min,sec);
  594. Serial.println(time);
  595. LCD_MESSAGE(time);
  596. }
  597. break;
  598. case 42: //M42 -Change pin status via gcode
  599. if (code_seen('S'))
  600. {
  601. int pin_status = code_value();
  602. if (code_seen('P') && pin_status >= 0 && pin_status <= 255)
  603. {
  604. int pin_number = code_value();
  605. for(int i = 0; i < (int)sizeof(sensitive_pins); i++)
  606. {
  607. if (sensitive_pins[i] == pin_number)
  608. {
  609. pin_number = -1;
  610. break;
  611. }
  612. }
  613. if (pin_number > -1)
  614. {
  615. pinMode(pin_number, OUTPUT);
  616. digitalWrite(pin_number, pin_status);
  617. analogWrite(pin_number, pin_status);
  618. }
  619. }
  620. }
  621. break;
  622. case 104: // M104
  623. if (code_seen('S')) setTargetHotend0(code_value());
  624. setWatch();
  625. break;
  626. case 140: // M140 set bed temp
  627. if (code_seen('S')) setTargetBed(code_value());
  628. break;
  629. case 105: // M105
  630. #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595)
  631. tt = degHotend0();
  632. #endif
  633. #if TEMP_1_PIN > -1
  634. bt = degBed();
  635. #endif
  636. #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595)
  637. Serial.print("ok T:");
  638. Serial.print(tt);
  639. #if TEMP_1_PIN > -1
  640. #ifdef PIDTEMP
  641. Serial.print(" B:");
  642. #if TEMP_1_PIN > -1
  643. Serial.println(bt);
  644. #else
  645. Serial.println(HeaterPower);
  646. #endif
  647. #else //not PIDTEMP
  648. Serial.println();
  649. #endif //PIDTEMP
  650. #else
  651. Serial.println();
  652. #endif //TEMP_1_PIN
  653. #else
  654. Serial.println("echo: No thermistors - no temp");
  655. #endif
  656. return;
  657. break;
  658. case 109:
  659. {// M109 - Wait for extruder heater to reach target.
  660. LCD_MESSAGE("Heating...");
  661. if (code_seen('S')) setTargetHotend0(code_value());
  662. setWatch();
  663. codenum = millis();
  664. /* See if we are heating up or cooling down */
  665. bool target_direction = isHeatingHotend0(); // true if heating, false if cooling
  666. #ifdef TEMP_RESIDENCY_TIME
  667. long residencyStart;
  668. residencyStart = -1;
  669. /* continue to loop until we have reached the target temp
  670. _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */
  671. while((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ||
  672. (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) {
  673. #else
  674. while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) {
  675. #endif //TEMP_RESIDENCY_TIME
  676. if( (millis() - codenum) > 1000 )
  677. { //Print Temp Reading every 1 second while heating up/cooling down
  678. Serial.print("T:");
  679. Serial.println( degHotend0() );
  680. codenum = millis();
  681. }
  682. manage_heater();
  683. LCD_STATUS;
  684. #ifdef TEMP_RESIDENCY_TIME
  685. /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time
  686. or when current temp falls outside the hysteresis after target temp was reached */
  687. if ((residencyStart == -1 && target_direction && !isHeatingHotend0()) ||
  688. (residencyStart == -1 && !target_direction && !isCoolingHotend0()) ||
  689. (residencyStart > -1 && labs(degHotend0() - degTargetHotend0()) > TEMP_HYSTERESIS) )
  690. {
  691. residencyStart = millis();
  692. }
  693. #endif //TEMP_RESIDENCY_TIME
  694. }
  695. LCD_MESSAGE("Heating done.");
  696. starttime=millis();
  697. }
  698. break;
  699. case 190: // M190 - Wait bed for heater to reach target.
  700. #if TEMP_1_PIN > -1
  701. if (code_seen('S')) setTargetBed(code_value());
  702. codenum = millis();
  703. while(isHeatingBed())
  704. {
  705. if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
  706. {
  707. float tt=degHotend0();
  708. Serial.print("T:");
  709. Serial.println( tt );
  710. Serial.print("ok T:");
  711. Serial.print( tt );
  712. Serial.print(" B:");
  713. Serial.println( degBed() );
  714. codenum = millis();
  715. }
  716. manage_heater();
  717. }
  718. #endif
  719. break;
  720. #if FAN_PIN > -1
  721. case 106: //M106 Fan On
  722. if (code_seen('S')){
  723. WRITE(FAN_PIN,HIGH);
  724. fanpwm=constrain(code_value(),0,255);
  725. analogWrite(FAN_PIN, fanpwm);
  726. }
  727. else {
  728. WRITE(FAN_PIN,HIGH);
  729. fanpwm=255;
  730. analogWrite(FAN_PIN, fanpwm);
  731. }
  732. break;
  733. case 107: //M107 Fan Off
  734. WRITE(FAN_PIN,LOW);
  735. analogWrite(FAN_PIN, 0);
  736. break;
  737. #endif //FAN_PIN
  738. #if (PS_ON_PIN > -1)
  739. case 80: // M80 - ATX Power On
  740. SET_OUTPUT(PS_ON_PIN); //GND
  741. break;
  742. case 81: // M81 - ATX Power Off
  743. SET_INPUT(PS_ON_PIN); //Floating
  744. break;
  745. #endif
  746. case 82:
  747. axis_relative_modes[3] = false;
  748. break;
  749. case 83:
  750. axis_relative_modes[3] = true;
  751. break;
  752. case 18: //compatibility
  753. case 84:
  754. if(code_seen('S')){
  755. stepper_inactive_time = code_value() * 1000;
  756. }
  757. else
  758. {
  759. st_synchronize();
  760. disable_x();
  761. disable_y();
  762. disable_z();
  763. disable_e();
  764. }
  765. break;
  766. case 85: // M85
  767. code_seen('S');
  768. max_inactive_time = code_value() * 1000;
  769. break;
  770. case 92: // M92
  771. for(int i=0; i < NUM_AXIS; i++)
  772. {
  773. if(code_seen(axis_codes[i]))
  774. axis_steps_per_unit[i] = code_value();
  775. }
  776. break;
  777. case 115: // M115
  778. Serial.println("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1");
  779. break;
  780. case 114: // M114
  781. Serial.print("X:");
  782. Serial.print(current_position[X_AXIS]);
  783. Serial.print("Y:");
  784. Serial.print(current_position[Y_AXIS]);
  785. Serial.print("Z:");
  786. Serial.print(current_position[Z_AXIS]);
  787. Serial.print("E:");
  788. Serial.print(current_position[E_AXIS]);
  789. #ifdef DEBUG_STEPS
  790. Serial.print(" Count X:");
  791. Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]);
  792. Serial.print("Y:");
  793. Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]);
  794. Serial.print("Z:");
  795. Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]);
  796. #endif
  797. Serial.println("");
  798. break;
  799. case 119: // M119
  800. #if (X_MIN_PIN > -1)
  801. Serial.print("x_min:");
  802. Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  803. #endif
  804. #if (X_MAX_PIN > -1)
  805. Serial.print("x_max:");
  806. Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  807. #endif
  808. #if (Y_MIN_PIN > -1)
  809. Serial.print("y_min:");
  810. Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  811. #endif
  812. #if (Y_MAX_PIN > -1)
  813. Serial.print("y_max:");
  814. Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  815. #endif
  816. #if (Z_MIN_PIN > -1)
  817. Serial.print("z_min:");
  818. Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  819. #endif
  820. #if (Z_MAX_PIN > -1)
  821. Serial.print("z_max:");
  822. Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
  823. #endif
  824. Serial.println("");
  825. break;
  826. //TODO: update for all axis, use for loop
  827. case 201: // M201
  828. for(int i=0; i < NUM_AXIS; i++)
  829. {
  830. if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
  831. }
  832. break;
  833. #if 0 // Not used for Sprinter/grbl gen6
  834. case 202: // M202
  835. for(int i=0; i < NUM_AXIS; i++) {
  836. if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
  837. }
  838. break;
  839. #endif
  840. case 203: // M203 max feedrate mm/sec
  841. for(int i=0; i < NUM_AXIS; i++) {
  842. if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ;
  843. }
  844. break;
  845. case 204: // M204 acclereration S normal moves T filmanent only moves
  846. {
  847. if(code_seen('S')) acceleration = code_value() ;
  848. if(code_seen('T')) retract_acceleration = code_value() ;
  849. }
  850. break;
  851. 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
  852. {
  853. if(code_seen('S')) minimumfeedrate = code_value()*60 ;
  854. if(code_seen('T')) mintravelfeedrate = code_value()*60 ;
  855. if(code_seen('B')) minsegmenttime = code_value() ;
  856. if(code_seen('X')) max_xy_jerk = code_value()*60 ;
  857. if(code_seen('Z')) max_z_jerk = code_value()*60 ;
  858. }
  859. break;
  860. case 220: // M220 S<factor in percent>- set speed factor override percentage
  861. {
  862. if(code_seen('S'))
  863. {
  864. feedmultiply = code_value() ;
  865. feedmultiplychanged=true;
  866. }
  867. }
  868. break;
  869. #ifdef PIDTEMP
  870. case 301: // M301
  871. if(code_seen('P')) Kp = code_value();
  872. if(code_seen('I')) Ki = code_value()*PID_dT;
  873. if(code_seen('D')) Kd = code_value()/PID_dT;
  874. break;
  875. #endif //PIDTEMP
  876. case 500: // Store settings in EEPROM
  877. {
  878. StoreSettings();
  879. }
  880. break;
  881. case 501: // Read settings from EEPROM
  882. {
  883. RetrieveSettings();
  884. }
  885. break;
  886. case 502: // Revert to default settings
  887. {
  888. RetrieveSettings(true);
  889. }
  890. break;
  891. }
  892. }
  893. else
  894. {
  895. Serial.print("echo: Unknown command:\"");
  896. Serial.print(cmdbuffer[bufindr]);
  897. Serial.println("\"");
  898. }
  899. ClearToSend();
  900. }
  901. void FlushSerialRequestResend()
  902. {
  903. //char cmdbuffer[bufindr][100]="Resend:";
  904. Serial.flush();
  905. Serial.print("Resend:");
  906. Serial.println(gcode_LastN + 1);
  907. ClearToSend();
  908. }
  909. void ClearToSend()
  910. {
  911. previous_millis_cmd = millis();
  912. #ifdef SDSUPPORT
  913. if(fromsd[bufindr])
  914. return;
  915. #endif //SDSUPPORT
  916. Serial.println("ok");
  917. }
  918. inline void get_coordinates()
  919. {
  920. for(int i=0; i < NUM_AXIS; i++) {
  921. if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i];
  922. else destination[i] = current_position[i]; //Are these else lines really needed?
  923. }
  924. if(code_seen('F')) {
  925. next_feedrate = code_value();
  926. if(next_feedrate > 0.0) feedrate = next_feedrate;
  927. }
  928. }
  929. inline void get_arc_coordinates()
  930. {
  931. get_coordinates();
  932. if(code_seen('I')) offset[0] = code_value();
  933. if(code_seen('J')) offset[1] = code_value();
  934. }
  935. void prepare_move()
  936. {
  937. plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0);
  938. for(int i=0; i < NUM_AXIS; i++) {
  939. current_position[i] = destination[i];
  940. }
  941. }
  942. void prepare_arc_move(char isclockwise) {
  943. float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc
  944. // Trace the arc
  945. mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60.0/100.0, r, isclockwise);
  946. // As far as the parser is concerned, the position is now == target. In reality the
  947. // motion control system might still be processing the action and the real tool position
  948. // in any intermediate location.
  949. for(int i=0; i < NUM_AXIS; i++) {
  950. current_position[i] = destination[i];
  951. }
  952. }
  953. void manage_inactivity(byte debug)
  954. {
  955. if( (millis()-previous_millis_cmd) > max_inactive_time )
  956. if(max_inactive_time)
  957. kill();
  958. if( (millis()-previous_millis_cmd) > stepper_inactive_time )
  959. if(stepper_inactive_time)
  960. {
  961. disable_x();
  962. disable_y();
  963. disable_z();
  964. disable_e();
  965. }
  966. check_axes_activity();
  967. }
  968. void kill()
  969. {
  970. disable_heater();
  971. disable_x();
  972. disable_y();
  973. disable_z();
  974. disable_e();
  975. if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT);
  976. SERIAL_ERRORLN("Printer halted. kill() called !!");
  977. while(1); // Wait for reset
  978. }