Prusa_farm.cpp 13 KB

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