Prusa_farm.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. #include "Prusa_farm.h"
  2. #include "macros.h"
  3. #include "Marlin.h"
  4. #include "cmdqueue.h"
  5. #include "temperature.h"
  6. #include "cardreader.h"
  7. #include "conv2str.h"
  8. #include "util.h"
  9. #include "ultralcd.h"
  10. #include "Filament_sensor.h"
  11. #ifdef PRUSA_FARM
  12. uint8_t farm_mode = 0;
  13. static ShortTimer NcTime;
  14. static uint8_t farm_timer = 8;
  15. static uint8_t status_number = 0;
  16. static bool no_response = false;
  17. #ifdef PRUSA_M28
  18. #define CHUNK_SIZE 64 // bytes
  19. #define SAFETY_MARGIN 1
  20. bool prusa_sd_card_upload = false;
  21. char chunk[CHUNK_SIZE+SAFETY_MARGIN];
  22. #endif
  23. static void prusa_statistics_err(char c);
  24. static void prusa_stat_printerstatus(uint8_t _status);
  25. static void prusa_stat_farm_number();
  26. static void prusa_stat_diameter();
  27. static void prusa_stat_temperatures();
  28. static void prusa_stat_printinfo();
  29. static void lcd_send_status();
  30. #ifdef FARM_CONNECT_MESSAGE
  31. static void proc_commands();
  32. static void lcd_connect_printer();
  33. #endif //FARM_CONNECT_MESSAGE
  34. #ifdef PRUSA_M28
  35. static void trace();
  36. #endif
  37. static void prusa_statistics_err(char c) {
  38. SERIAL_ECHOPGM("{[ERR:");
  39. SERIAL_ECHO(c);
  40. SERIAL_ECHO(']');
  41. prusa_stat_farm_number();
  42. }
  43. static void prusa_statistics_case0(uint8_t statnr) {
  44. SERIAL_ECHO('{');
  45. prusa_stat_printerstatus(statnr);
  46. prusa_stat_farm_number();
  47. prusa_stat_printinfo();
  48. }
  49. static void prusa_stat_printerstatus(uint8_t _status) {
  50. SERIAL_ECHOPGM("[PRN:");
  51. SERIAL_ECHO(_status);
  52. SERIAL_ECHO(']');
  53. }
  54. static void prusa_stat_farm_number() {
  55. SERIAL_ECHOPGM("[PFN:0]");
  56. }
  57. static void prusa_stat_diameter() {
  58. SERIAL_ECHOPGM("[DIA:");
  59. SERIAL_ECHO(eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM));
  60. SERIAL_ECHO(']');
  61. }
  62. static void prusa_stat_temperatures() {
  63. SERIAL_ECHOPGM("[ST0:");
  64. SERIAL_ECHO(target_temperature[0]);
  65. SERIAL_ECHOPGM("][STB:");
  66. SERIAL_ECHO(target_temperature_bed);
  67. SERIAL_ECHOPGM("][AT0:");
  68. SERIAL_ECHO(current_temperature[0]);
  69. SERIAL_ECHOPGM("][ATB:");
  70. SERIAL_ECHO(current_temperature_bed);
  71. SERIAL_ECHO(']');
  72. }
  73. static void prusa_stat_printinfo() {
  74. SERIAL_ECHOPGM("[TFU:");
  75. SERIAL_ECHO(total_filament_used);
  76. SERIAL_ECHOPGM("][PCD:");
  77. SERIAL_ECHO(itostr3(card.percentDone()));
  78. SERIAL_ECHOPGM("][FEM:");
  79. SERIAL_ECHO(itostr3(feedmultiply));
  80. SERIAL_ECHOPGM("][FNM:");
  81. SERIAL_ECHO(card.longFilename[0] ? card.longFilename : card.filename);
  82. SERIAL_ECHOPGM("][TIM:");
  83. if (starttime != 0) {
  84. SERIAL_ECHO(_millis() / 1000 - starttime / 1000);
  85. }
  86. else {
  87. SERIAL_ECHO(0);
  88. }
  89. SERIAL_ECHOPGM("][FWR:");
  90. SERIAL_ECHORPGM(FW_VERSION_STR_P());
  91. SERIAL_ECHO(']');
  92. prusa_stat_diameter();
  93. }
  94. static void lcd_send_status() {
  95. if (farm_mode && no_response && (NcTime.expired(NC_TIME * 1000))) {
  96. //send important status messages periodicaly
  97. prusa_statistics(8);
  98. NcTime.start();
  99. #ifdef FARM_CONNECT_MESSAGE
  100. lcd_connect_printer();
  101. #endif //FARM_CONNECT_MESSAGE
  102. }
  103. }
  104. #ifdef FARM_CONNECT_MESSAGE
  105. static void proc_commands() {
  106. if (buflen) {
  107. process_commands();
  108. if (!cmdbuffer_front_already_processed)
  109. cmdqueue_pop_front();
  110. cmdbuffer_front_already_processed = false;
  111. }
  112. }
  113. static void lcd_connect_printer() {
  114. lcd_update_enable(false);
  115. lcd_clear();
  116. int i = 0;
  117. int t = 0;
  118. lcd_puts_at_P(0, 0, PSTR("Connect printer to"));
  119. lcd_puts_at_P(0, 1, PSTR("monitoring or hold"));
  120. lcd_puts_at_P(0, 2, PSTR("the knob to continue"));
  121. while (no_response) {
  122. i++;
  123. t++;
  124. delay_keep_alive(100);
  125. proc_commands();
  126. if (t == 10) {
  127. prusa_statistics(8);
  128. t = 0;
  129. }
  130. if (READ(BTN_ENC)) { //if button is not pressed
  131. i = 0;
  132. lcd_puts_at_P(0, 3, PSTR(" "));
  133. }
  134. if (i != 0)
  135. lcd_putc_at((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, LCD_STR_SOLID_BLOCK[0]);
  136. if (i == NC_BUTTON_LONG_PRESS * 10)
  137. no_response = false;
  138. }
  139. lcd_update_enable(true);
  140. lcd_update(2);
  141. }
  142. #endif //FARM_CONNECT_MESSAGE
  143. #ifdef PRUSA_M28
  144. static void trace() {
  145. Sound_MakeCustom(25,440,true);
  146. }
  147. void serial_read_stream() {
  148. setAllTargetHotends(0);
  149. setTargetBed(0);
  150. lcd_clear();
  151. lcd_puts_P(PSTR(" Upload in progress"));
  152. // first wait for how many bytes we will receive
  153. uint32_t bytesToReceive;
  154. // receive the four bytes
  155. char bytesToReceiveBuffer[4];
  156. for (int i=0; i<4; i++) {
  157. int data;
  158. while ((data = MYSERIAL.read()) == -1) {};
  159. bytesToReceiveBuffer[i] = data;
  160. }
  161. // make it a uint32
  162. memcpy(&bytesToReceive, &bytesToReceiveBuffer, 4);
  163. // we're ready, notify the sender
  164. MYSERIAL.write('+');
  165. // lock in the routine
  166. uint32_t receivedBytes = 0;
  167. while (prusa_sd_card_upload) {
  168. int i;
  169. for (i=0; i<CHUNK_SIZE; i++) {
  170. int data;
  171. // check if we're not done
  172. if (receivedBytes == bytesToReceive) {
  173. break;
  174. }
  175. // read the next byte
  176. while ((data = MYSERIAL.read()) == -1) {};
  177. receivedBytes++;
  178. // save it to the chunk
  179. chunk[i] = data;
  180. }
  181. // write the chunk to SD
  182. card.write_command_no_newline(&chunk[0]);
  183. // notify the sender we're ready for more data
  184. MYSERIAL.write('+');
  185. // for safety
  186. manage_heater();
  187. // check if we're done
  188. if(receivedBytes == bytesToReceive) {
  189. trace(); // beep
  190. card.closefile();
  191. prusa_sd_card_upload = false;
  192. SERIAL_PROTOCOLLNRPGM(MSG_FILE_SAVED);
  193. }
  194. }
  195. }
  196. #endif //PRUSA_M28
  197. void prusa_statistics(uint8_t _message) {
  198. const uint8_t _fil_nr = 0;
  199. if (!farm_mode)
  200. return;
  201. switch (_message) {
  202. case 0: // default message
  203. if (busy_state == PAUSED_FOR_USER) {
  204. prusa_statistics_case0(15);
  205. }
  206. else if (isPrintPaused) {
  207. prusa_statistics_case0(14);
  208. }
  209. else if (IS_SD_PRINTING || loading_flag) {
  210. prusa_statistics_case0(4);
  211. }
  212. else {
  213. SERIAL_ECHO('{');
  214. prusa_stat_printerstatus(1);
  215. prusa_stat_farm_number();
  216. prusa_stat_diameter();
  217. status_number = 1;
  218. }
  219. break;
  220. case 1: // 1 heating
  221. SERIAL_ECHO('{');
  222. prusa_stat_printerstatus(2);
  223. prusa_stat_farm_number();
  224. status_number = 2;
  225. farm_timer = 1;
  226. break;
  227. case 2: // heating done
  228. SERIAL_ECHO('{');
  229. prusa_stat_printerstatus(3);
  230. prusa_stat_farm_number();
  231. SERIAL_ECHOLN('}');
  232. status_number = 3;
  233. farm_timer = 1;
  234. if (IS_SD_PRINTING || loading_flag) {
  235. SERIAL_ECHO('{');
  236. prusa_stat_printerstatus(4);
  237. prusa_stat_farm_number();
  238. status_number = 4;
  239. }
  240. else {
  241. SERIAL_ECHO('{');
  242. prusa_stat_printerstatus(3);
  243. prusa_stat_farm_number();
  244. status_number = 3;
  245. }
  246. farm_timer = 1;
  247. break;
  248. case 3: // filament change
  249. // must do a return here to prevent doing SERIAL_ECHOLN("}") at the very end of this function
  250. // saved a considerable amount of FLASH
  251. return;
  252. break;
  253. case 4: // print succesfull
  254. SERIAL_ECHOPGM("{[RES:1][FIL:");
  255. MYSERIAL.print(int(_fil_nr));
  256. SERIAL_ECHO(']');
  257. prusa_stat_printerstatus(status_number);
  258. prusa_stat_farm_number();
  259. farm_timer = 2;
  260. break;
  261. case 5: // print not succesfull
  262. SERIAL_ECHOPGM("{[RES:0][FIL:");
  263. MYSERIAL.print(int(_fil_nr));
  264. SERIAL_ECHO(']');
  265. prusa_stat_printerstatus(status_number);
  266. prusa_stat_farm_number();
  267. farm_timer = 2;
  268. break;
  269. case 6: // print done
  270. SERIAL_ECHOPGM("{[PRN:8]");
  271. prusa_stat_farm_number();
  272. status_number = 8;
  273. farm_timer = 2;
  274. break;
  275. case 7: // print done - stopped
  276. SERIAL_ECHOPGM("{[PRN:9]");
  277. prusa_stat_farm_number();
  278. status_number = 9;
  279. farm_timer = 2;
  280. break;
  281. case 8: // printer started
  282. SERIAL_ECHOPGM("{[PRN:0]");
  283. prusa_stat_farm_number();
  284. status_number = 0;
  285. farm_timer = 2;
  286. break;
  287. case 20: // echo farm no
  288. SERIAL_ECHO('{');
  289. prusa_stat_printerstatus(status_number);
  290. prusa_stat_farm_number();
  291. farm_timer = 4;
  292. break;
  293. case 21: // temperatures
  294. SERIAL_ECHO('{');
  295. prusa_stat_temperatures();
  296. prusa_stat_farm_number();
  297. prusa_stat_printerstatus(status_number);
  298. break;
  299. case 22: // waiting for filament change
  300. SERIAL_ECHOPGM("{[PRN:5]");
  301. prusa_stat_farm_number();
  302. status_number = 5;
  303. break;
  304. case 90: // Error - Thermal Runaway
  305. prusa_statistics_err('1');
  306. break;
  307. case 91: // Error - Thermal Runaway Preheat
  308. prusa_statistics_err('2');
  309. break;
  310. case 92: // Error - Min temp
  311. prusa_statistics_err('3');
  312. break;
  313. case 93: // Error - Max temp
  314. prusa_statistics_err('4');
  315. break;
  316. case 99: // heartbeat
  317. SERIAL_ECHOPGM("{[PRN:99]");
  318. prusa_stat_temperatures();
  319. prusa_stat_farm_number();
  320. break;
  321. }
  322. SERIAL_ECHOLN('}');
  323. }
  324. void prusa_statistics_update_from_status_screen() {
  325. if (farm_mode) {
  326. farm_timer--;
  327. if (farm_timer < 1) {
  328. farm_timer = 10;
  329. prusa_statistics(0);
  330. }
  331. switch (farm_timer) {
  332. case 8:
  333. prusa_statistics(21);
  334. if(loading_flag)
  335. prusa_statistics(22);
  336. break;
  337. case 5:
  338. if (IS_SD_PRINTING)
  339. prusa_statistics(20);
  340. break;
  341. }
  342. }
  343. }
  344. void prusa_statistics_update_from_lcd_update() {
  345. lcd_send_status();
  346. }
  347. void farm_mode_init() {
  348. farm_mode = eeprom_init_default_byte((uint8_t*)EEPROM_FARM_MODE, 0);
  349. if (farm_mode) {
  350. no_response = true; //we need confirmation by recieving PRUSA thx
  351. prusa_statistics(8);
  352. #ifdef HAS_SECOND_SERIAL_PORT
  353. selectedSerialPort = 1;
  354. #endif //HAS_SECOND_SERIAL_PORT
  355. MYSERIAL.begin(BAUDRATE);
  356. #ifdef FILAMENT_SENSOR
  357. //to be converted to Filament_sensor.h...
  358. //disabled filament autoload (PFW360)
  359. fsensor.setAutoLoadEnabled(false);
  360. #endif //FILAMENT_SENSOR
  361. // ~ FanCheck -> on
  362. eeprom_update_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED, true);
  363. }
  364. }
  365. bool farm_prusa_code_seen() {
  366. if (!farm_mode)
  367. return false;
  368. if (code_seen_P(PSTR("PRN"))) { // PRUSA PRN
  369. printf_P(_N("%u"), status_number);
  370. }
  371. else if (code_seen_P(PSTR("thx"))) { // PRUSA thx
  372. no_response = false;
  373. }
  374. #ifdef PRUSA_M28
  375. else if (code_seen_P(PSTR("M28"))) { // PRUSA M28
  376. trace();
  377. prusa_sd_card_upload = true;
  378. card.openFileWrite(strchr_pointer+4);
  379. }
  380. #endif //PRUSA_M28
  381. else if (code_seen_P(PSTR("fv"))) { // PRUSA fv
  382. // get file version
  383. #ifdef SDSUPPORT
  384. card.openFileReadFilteredGcode(strchr_pointer + 3, true);
  385. while (true) {
  386. uint16_t readByte = card.getFilteredGcodeChar();
  387. MYSERIAL.write(readByte);
  388. if (readByte == '\n') {
  389. break;
  390. }
  391. }
  392. card.closefile();
  393. #endif // SDSUPPORT
  394. }
  395. else {
  396. return false;
  397. }
  398. return true;
  399. }
  400. void farm_gcode_g98() {
  401. farm_mode = 1;
  402. eeprom_update_byte((unsigned char *)EEPROM_FARM_MODE, farm_mode);
  403. SilentModeMenu = SILENT_MODE_OFF;
  404. eeprom_update_byte((unsigned char *)EEPROM_SILENT, SilentModeMenu);
  405. fCheckModeInit(); // alternatively invoke printer reset
  406. }
  407. void farm_gcode_g99() {
  408. farm_disable();
  409. lcd_update(2);
  410. fCheckModeInit(); // alternatively invoke printer reset
  411. }
  412. void farm_disable() {
  413. farm_mode = false;
  414. eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
  415. }
  416. #else //PRUSA_FARM
  417. void prusa_statistics(_UNUSED uint8_t message) {
  418. }
  419. void prusa_statistics_update_from_status_screen() {
  420. }
  421. void prusa_statistics_update_from_lcd_update() {
  422. }
  423. void farm_mode_init() {
  424. }
  425. bool farm_prusa_code_seen() {
  426. return false;
  427. }
  428. void farm_gcode_g98() {
  429. }
  430. void farm_gcode_g99() {
  431. }
  432. void farm_disable() {
  433. }
  434. #endif //PRUSA_FARM