My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

nextion_tft.cpp 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /* ****************************************
  23. * lcd/extui/nextion/nextion_tft.h
  24. * ****************************************
  25. * Extensible_UI implementation for Nextion
  26. * https://github.com/Skorpi08
  27. * ***************************************/
  28. #include "../../../inc/MarlinConfigPre.h"
  29. #if ENABLED(NEXTION_TFT)
  30. #include "../../../MarlinCore.h"
  31. #include "../../../feature/pause.h"
  32. #include "../../../module/stepper.h"
  33. #include "../../../gcode/queue.h"
  34. #include "../../../libs/numtostr.h"
  35. #include "../../../sd/cardreader.h"
  36. #include "FileNavigator.h"
  37. #include "nextion_tft.h"
  38. #define DEBUG_OUT NEXDEBUGLEVEL
  39. #include "../../../core/debug_out.h"
  40. char NextionTFT::selectedfile[MAX_PATH_LEN];
  41. char NextionTFT::nextion_command[MAX_CMND_LEN];
  42. uint8_t NextionTFT::command_len;
  43. uint32_t layer = 0;
  44. NextionTFT nextion;
  45. NextionTFT::NextionTFT() {}
  46. void NextionTFT::Startup() {
  47. selectedfile[0] = '\0';
  48. nextion_command[0] = '\0';
  49. command_len = 0;
  50. LCD_SERIAL.begin(115200);
  51. SEND_VAL("tmppage.connected", 0);
  52. delay_ms(100);
  53. SEND_VAL("tmppage.connected", 1);
  54. SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
  55. SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
  56. SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
  57. SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
  58. SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
  59. SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
  60. SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
  61. SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
  62. SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
  63. DEBUG_ECHOLNPGM("Nextion Debug Level ", NEXDEBUGLEVEL);
  64. }
  65. void NextionTFT::IdleLoop() {
  66. if (ReadTFTCommand()) {
  67. ProcessPanelRequest();
  68. command_len = 0;
  69. }
  70. UpdateOnChange();
  71. }
  72. void NextionTFT::PrinterKilled(PGM_P error, PGM_P component) {
  73. SEND_TXT_END("page error");
  74. SEND_TXT("t3", "Error");
  75. SEND_TXT_P("t4", component);
  76. SEND_TXT_P("t5", error);
  77. SEND_TXT("t6", "Need reset");
  78. }
  79. void NextionTFT::PrintFinished() {
  80. SEND_TXT_END("page printfinished");
  81. }
  82. void NextionTFT::ConfirmationRequest(const char * const msg) {
  83. SEND_VALasTXT("tmppage.M117", msg);
  84. #if NEXDEBUG(N_MARLIN)
  85. DEBUG_ECHOLNPGM("ConfirmationRequest() ", msg, " printer_state:", printer_state);
  86. #endif
  87. }
  88. void NextionTFT::StatusChange(const char * const msg) {
  89. #if NEXDEBUG(N_MARLIN)
  90. DEBUG_ECHOLNPGM("StatusChange() ", msg, "\nprinter_state:", printer_state);
  91. #endif
  92. SEND_VALasTXT("tmppage.M117", msg);
  93. }
  94. void NextionTFT::SendtoTFT(PGM_P str) { // A helper to print PROGMEM string to the panel
  95. #if NEXDEBUG(N_SOME)
  96. DEBUG_ECHOPGM_P(str);
  97. #endif
  98. while (const char c = pgm_read_byte(str++))
  99. LCD_SERIAL.write(c);
  100. }
  101. bool NextionTFT::ReadTFTCommand() {
  102. bool command_ready = false;
  103. while ((LCD_SERIAL.available() > 0) && (command_len < MAX_CMND_LEN)) {
  104. nextion_command[command_len] = LCD_SERIAL.read();
  105. if (nextion_command[command_len] == 10) {
  106. command_ready = true;
  107. break;
  108. }
  109. command_len++;
  110. }
  111. if (command_ready) {
  112. nextion_command[command_len] = 0x00;
  113. if (nextion_command[0] == 'G' || nextion_command[0] == 'M' || nextion_command[0] == 'T')
  114. injectCommands(nextion_command);
  115. #if NEXDEBUG(N_ALL)
  116. DEBUG_ECHOLNPGM("< ", nextion_command);
  117. #endif
  118. #if NEXDEBUG(N_SOME)
  119. uint8_t req = atoi(&nextion_command[1]);
  120. if (req > 7 && req != 20)
  121. DEBUG_ECHOLNPGM( "> ", AS_CHAR(nextion_command[0]),
  122. "\n> ", AS_CHAR(nextion_command[1]),
  123. "\n> ", AS_CHAR(nextion_command[2]),
  124. "\n> ", AS_CHAR(nextion_command[3]),
  125. "\nprinter_state:", printer_state);
  126. #endif
  127. }
  128. return command_ready;
  129. }
  130. void NextionTFT::SendFileList(int8_t startindex) {
  131. // respond to panel request for 7 files starting at index
  132. #if NEXDEBUG(N_INFO)
  133. DEBUG_ECHOLNPGM("## SendFileList ## ", startindex);
  134. #endif
  135. filenavigator.getFiles(startindex);
  136. }
  137. void NextionTFT::SelectFile() {
  138. strncpy(selectedfile, nextion_command + 4, command_len - 4);
  139. selectedfile[command_len - 5] = '\0';
  140. #if NEXDEBUG(N_FILE)
  141. DEBUG_ECHOLNPAIR_F(" Selected File: ", selectedfile);
  142. #endif
  143. switch (selectedfile[0]) {
  144. case '/': // Valid file selected
  145. //SEND_TXT("tmppage.M117", msg_sd_file_open_success);
  146. break;
  147. case '<': // .. (go up folder level)
  148. filenavigator.upDIR();
  149. SendFileList(0);
  150. break;
  151. default: // enter sub folder
  152. filenavigator.changeDIR(selectedfile);
  153. SendFileList(0);
  154. break;
  155. }
  156. }
  157. void NextionTFT::_format_time(char *outstr, uint32_t time) {
  158. const uint8_t hrs = time / 3600,
  159. min = (time / 60) % 60,
  160. sec = time % 60;
  161. if (hrs)
  162. sprintf_P(outstr, PSTR("%02d:%02dm"), hrs, min);
  163. else
  164. sprintf_P(outstr, PSTR("%02d:%02ds"), min, sec);
  165. }
  166. void NextionTFT::ProcessPanelRequest() {
  167. // Break these up into logical blocks as its easier to navigate than one huge switch case!
  168. if (nextion_command[0] == 'X') {
  169. int8_t req = atoi(&nextion_command[1]);
  170. // Information requests
  171. if (req <= 49)
  172. PanelInfo(req);
  173. // Simple Actions
  174. else if (req >= 50)
  175. PanelAction(req);
  176. }
  177. }
  178. #define SEND_NA(A) SEND_TXT(A, "n/a")
  179. void NextionTFT::PanelInfo(uint8_t req) {
  180. switch (req) {
  181. case 0: break;
  182. case 1: // Get SD Card list
  183. if (!isPrinting()) {
  184. if (!isMediaInserted()) safe_delay(500);
  185. if (!isMediaInserted()) { // Make sure the card is removed
  186. //SEND_TXT("tmppage.M117", msg_no_sd_card);
  187. }
  188. else if (nextion_command[3] == 'S')
  189. SendFileList(atoi(&nextion_command[4]));
  190. }
  191. break;
  192. case 2: // Printer Info
  193. if (!isPrinting()) {
  194. SEND_VAL("tmppage.connected", 1);
  195. SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
  196. SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
  197. SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
  198. SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
  199. SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
  200. SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
  201. SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
  202. SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
  203. SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
  204. SEND_TEMP("tmppage.t0", ui8tostr3rj(getActualTemp_celsius(E0)), " / ", ui8tostr3rj(getTargetTemp_celsius(E0)));
  205. SEND_TEMP("tmppage.t1", ui8tostr3rj(getActualTemp_celsius(E1)), " / ", ui8tostr3rj(getTargetTemp_celsius(E1)));
  206. SEND_TEMP("tmppage.t2", ui8tostr3rj(getActualTemp_celsius(BED)), " / ", ui8tostr3rj(getTargetTemp_celsius(BED)));
  207. SEND_VALasTXT("tmppage.tool", getActiveTool());
  208. SEND_VALasTXT("tmppage.fan", ui8tostr3rj(getActualFan_percent(FAN0)));
  209. SEND_VALasTXT("tmppage.speed", getFeedrate_percent());
  210. SEND_VALasTXT("tmppage.flow", getFlow_percent(getActiveTool()));
  211. SEND_VALasTXT("tmppage.progress", ui8tostr3rj(getProgress_percent()));
  212. SEND_VALasTXT("tmppage.layer", layer);
  213. SEND_VALasTXT("tmppage.x", getAxisPosition_mm(X));
  214. SEND_VALasTXT("tmppage.y", getAxisPosition_mm(Y));
  215. SEND_VALasTXT("tmppage.z", getAxisPosition_mm(Z));
  216. SEND_VAL("tmppage.homed", isPositionKnown());
  217. SEND_VAL("tmppage.homedx", isAxisPositionKnown(X));
  218. SEND_VAL("tmppage.homedy", isAxisPositionKnown(Y));
  219. SEND_VAL("tmppage.homedz", isAxisPositionKnown(Z));
  220. #if ENABLED(DUAL_X_CARRIAGE)
  221. SEND_VAL("tmppage.idexmode", getIDEX_Mode());
  222. #endif
  223. SEND_TXT("tmppage.M117", msg_welcome);
  224. }
  225. break;
  226. case 23: // Linear Advance
  227. #if ENABLED(LIN_ADVANCE)
  228. SEND_VALasTXT("linadvance", getLinearAdvance_mm_mm_s(getActiveTool()));
  229. #else
  230. SEND_NA("linadvance");
  231. #endif
  232. break;
  233. case 24: // TMC Motor Current
  234. #if HAS_TRINAMIC_CONFIG
  235. #define SEND_TRINAMIC_CURR(A, B) SEND_VALasTXT(A, getAxisCurrent_mA(B))
  236. #else
  237. #define SEND_TRINAMIC_CURR(A, B) SEND_NA(A)
  238. #endif
  239. SEND_TRINAMIC_CURR("x", X);
  240. SEND_TRINAMIC_CURR("x2", X2);
  241. SEND_TRINAMIC_CURR("y", Y);
  242. SEND_TRINAMIC_CURR("y2", Y2);
  243. SEND_TRINAMIC_CURR("z", Z);
  244. SEND_TRINAMIC_CURR("z2", Z2);
  245. SEND_TRINAMIC_CURR("e", E0);
  246. SEND_TRINAMIC_CURR("e1", E1);
  247. break;
  248. case 25: // TMC Bump Sensitivity
  249. #if HAS_TRINAMIC_CONFIG
  250. #define SEND_TRINAMIC_BUMP(A, B) SEND_VALasTXT(A, getTMCBumpSensitivity(B))
  251. #else
  252. #define SEND_TRINAMIC_BUMP(A, B) SEND_NA(A)
  253. #endif
  254. SEND_TRINAMIC_BUMP("x", X);
  255. SEND_TRINAMIC_BUMP("x2", X2);
  256. SEND_TRINAMIC_BUMP("y", Y);
  257. SEND_TRINAMIC_BUMP("y2", Y2);
  258. SEND_TRINAMIC_BUMP("z", Z);
  259. SEND_TRINAMIC_BUMP("z2", Z2);
  260. break;
  261. case 26: // TMC Hybrid Threshold Speed
  262. #if 0 && BOTH(HAS_TRINAMIC_CONFIG, HYBRID_THRESHOLD)
  263. #define SEND_TRINAMIC_THRS(A, B) SEND_VALasTXT(A, getAxisPWMthrs(B))
  264. #else
  265. #define SEND_TRINAMIC_THRS(A, B) SEND_NA(A)
  266. #endif
  267. SEND_TRINAMIC_THRS("x", X);
  268. SEND_TRINAMIC_THRS("x2", X2);
  269. SEND_TRINAMIC_THRS("y", Y);
  270. SEND_TRINAMIC_THRS("y2", Y2);
  271. SEND_TRINAMIC_THRS("z", Z);
  272. SEND_TRINAMIC_THRS("z2", Z2);
  273. SEND_TRINAMIC_THRS("e", E0);
  274. SEND_TRINAMIC_THRS("e1", E1);
  275. break;
  276. case 27: // Printcounter
  277. #if ENABLED(PRINTCOUNTER)
  278. char buffer[21];
  279. #define SEND_PRINT_INFO(A, B) SEND_VALasTXT(A, B(buffer))
  280. #else
  281. #define SEND_PRINT_INFO(A, B) SEND_NA(A)
  282. #endif
  283. SEND_PRINT_INFO("t5", getTotalPrints_str);
  284. SEND_PRINT_INFO("t3", getFinishedPrints_str);
  285. SEND_PRINT_INFO("t4", getFailedPrints_str);
  286. SEND_PRINT_INFO("t6", getTotalPrintTime_str);
  287. SEND_PRINT_INFO("t7", getLongestPrint_str);
  288. SEND_PRINT_INFO("t8", getFilamentUsed_str);
  289. break;
  290. case 28: // Filament laod/unload
  291. #if ENABLED(ADVANCED_PAUSE_FEATURE)
  292. #define SEND_PAUSE_INFO(A, B) SEND_VALasTXT(A, fc_settings[getActiveTool()].B)
  293. #else
  294. #define SEND_PAUSE_INFO(A, B) SEND_NA(A)
  295. #endif
  296. SEND_PAUSE_INFO("filamentin", load_length);
  297. SEND_PAUSE_INFO("filamentout", unload_length);
  298. break;
  299. case 29: // Preheat
  300. #if PREHEAT_COUNT
  301. if (!isPrinting()) {
  302. // Preheat PLA
  303. if (nextion_command[4] == 'P') {
  304. SEND_VALasTXT("pe", getMaterial_preset_E(0));
  305. #if HAS_HEATED_BED
  306. SEND_VALasTXT("pb", getMaterial_preset_B(0));
  307. #endif
  308. }
  309. // Preheat ABS
  310. if (nextion_command[4] == 'A') {
  311. SEND_VALasTXT("ae", getMaterial_preset_E(1));
  312. #if HAS_HEATED_BED
  313. SEND_VALasTXT("ab", getMaterial_preset_B(1));
  314. #endif
  315. }
  316. // Preheat PETG
  317. if (nextion_command[4] == 'G') {
  318. #ifdef PREHEAT_3_TEMP_HOTEND
  319. SEND_VALasTXT("ge", getMaterial_preset_E(2));
  320. #if HAS_HEATED_BED
  321. SEND_VALasTXT("gb", getMaterial_preset_B(2));
  322. #endif
  323. #endif
  324. }
  325. }
  326. #endif
  327. break;
  328. case 30: // Velocity
  329. SEND_VALasTXT("x", getAxisMaxFeedrate_mm_s(X));
  330. SEND_VALasTXT("y", getAxisMaxFeedrate_mm_s(Y));
  331. SEND_VALasTXT("z", getAxisMaxFeedrate_mm_s(Z));
  332. SEND_VALasTXT("e", getAxisMaxFeedrate_mm_s(getActiveTool()));
  333. SEND_VALasTXT("min", getMinFeedrate_mm_s());
  334. SEND_VALasTXT("tmin", getMinTravelFeedrate_mm_s());
  335. break;
  336. case 31: // Jerk
  337. #if ENABLED(CLASSIC_JERK)
  338. #define SEND_JERK_INFO(A, B) SEND_VALasTXT(A, getAxisMaxJerk_mm_s(B))
  339. #else
  340. #define SEND_JERK_INFO(A, B) SEND_NA(A)
  341. //SEND_VALasTXT("x", getJunctionDeviation_mm());
  342. SEND_TXT("tmppage.M117", "classic Jerk not enabled");
  343. #endif
  344. SEND_JERK_INFO("x", X);
  345. SEND_JERK_INFO("y", Y);
  346. SEND_JERK_INFO("z", Z);
  347. SEND_JERK_INFO("e", getActiveTool());
  348. break;
  349. case 32: // Steps-per-mm
  350. SEND_VALasTXT("x", getAxisSteps_per_mm(X));
  351. SEND_VALasTXT("y", getAxisSteps_per_mm(Y));
  352. SEND_VALasTXT("z", getAxisSteps_per_mm(Z));
  353. SEND_VALasTXT("e0", getAxisSteps_per_mm(E0));
  354. SEND_VALasTXT("e1", getAxisSteps_per_mm(E1));
  355. break;
  356. case 33: // Acceleration
  357. SEND_VALasTXT("x", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(X)));
  358. SEND_VALasTXT("y", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(Y)));
  359. SEND_VALasTXT("z", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(Z)));
  360. SEND_VALasTXT("e", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(getActiveTool())));
  361. SEND_VALasTXT("print", ui16tostr5rj(getPrintingAcceleration_mm_s2()));
  362. SEND_VALasTXT("retract", ui16tostr5rj(getRetractAcceleration_mm_s2()));
  363. SEND_VALasTXT("travel", ui16tostr5rj(getTravelAcceleration_mm_s2()));
  364. break;
  365. case 34: // Dual X carriage offset
  366. #if ENABLED(DUAL_X_CARRIAGE)
  367. #define SEND_IDEX_INFO(A, B) SEND_VALasTXT(A, getNozzleOffset_mm(B, getActiveTool()))
  368. #else
  369. #define SEND_IDEX_INFO(A, B) SEND_NA(A)
  370. #endif
  371. SEND_IDEX_INFO("x", X);
  372. SEND_IDEX_INFO("y", Y);
  373. SEND_IDEX_INFO("z", Z);
  374. break;
  375. case 35: // Probe offset
  376. #if HAS_PROBE_XY_OFFSET
  377. #define SEND_PROBE_INFO(A, B) SEND_VALasTXT(A, getProbeOffset_mm(B))
  378. #else
  379. #define SEND_PROBE_INFO(A, B) SEND_NA(A)
  380. #endif
  381. SEND_PROBE_INFO("x", X);
  382. SEND_PROBE_INFO("y", Y);
  383. SEND_VALasTXT("z", getZOffset_mm());
  384. break;
  385. case 36: // Endstop Info
  386. #if HAS_X_MIN
  387. SEND_VALasTXT("x1", READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
  388. #endif
  389. #if HAS_X_MAX
  390. SEND_VALasTXT("x2", READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
  391. #endif
  392. #if HAS_Y_MIN
  393. SEND_VALasTXT("y1", READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
  394. #endif
  395. #if HAS_Z_MIN
  396. SEND_VALasTXT("z1", READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
  397. #endif
  398. #if HAS_Z_MAX
  399. SEND_VALasTXT("z2", READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
  400. #endif
  401. #if HAS_Z2_MIN
  402. SEND_VALasTXT("z2", READ(Z2_MIN_PIN) != Z2_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
  403. #endif
  404. #if HAS_Z2_MAX
  405. SEND_VALasTXT("z2", READ(Z2_MAX_PIN) != Z2_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
  406. #endif
  407. #if HAS_BED_PROBE
  408. //SEND_VALasTXT("bltouch", READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING ? "triggered" : "open");
  409. #else
  410. SEND_NA("bltouch");
  411. #endif
  412. break;
  413. case 37: // PID
  414. #if ENABLED(PIDTEMP)
  415. #define SEND_PID_INFO_0(A, B) SEND_VALasTXT(A, getPIDValues_K##B(E0))
  416. #else
  417. #define SEND_PID_INFO_0(A, B) SEND_NA(A)
  418. #endif
  419. #if BOTH(PIDTEMP, HAS_MULTI_EXTRUDER)
  420. #define SEND_PID_INFO_1(A, B) SEND_VALasTXT(A, getPIDValues_K##B(E1))
  421. #else
  422. #define SEND_PID_INFO_1(A, B) SEND_NA(A)
  423. #endif
  424. #if ENABLED(PIDTEMPBED)
  425. #define SEND_PID_INFO_BED(A, B) SEND_VALasTXT(A, getBedPIDValues_K##B())
  426. #else
  427. #define SEND_PID_INFO_BED(A, B) SEND_NA(A)
  428. #endif
  429. SEND_PID_INFO_0("p0", p);
  430. SEND_PID_INFO_0("i0", i);
  431. SEND_PID_INFO_0("d0", d);
  432. SEND_PID_INFO_1("p1", p);
  433. SEND_PID_INFO_1("i1", i);
  434. SEND_PID_INFO_1("d1", d);
  435. SEND_PID_INFO_BED("hbp", p);
  436. SEND_PID_INFO_BED("hbi", i);
  437. SEND_PID_INFO_BED("hbd", d);
  438. break;
  439. }
  440. }
  441. void NextionTFT::PanelAction(uint8_t req) {
  442. switch (req) {
  443. case 50: // Pause SD print
  444. //if (isPrintingFromMedia()) {
  445. //SEND_TXT("tmppage.M117", "Paused");
  446. pausePrint();
  447. SEND_TXT_END("qpause.picc=29");
  448. //}
  449. break;
  450. case 51: // Resume SD Print
  451. resumePrint();
  452. SEND_TXT_END("qpause.picc=28");
  453. break;
  454. case 52: // Stop SD print
  455. //if (isPrintingFromMedia()) {
  456. stopPrint();
  457. SEND_TXT_END("page prepare");
  458. //}
  459. break;
  460. case 54: // A13 Select file
  461. SelectFile();
  462. break;
  463. case 65: // Cool Down
  464. if (!isPrinting()) coolDown();
  465. break;
  466. case 66: // Refresh SD
  467. if (!isPrinting()) {
  468. injectCommands_P(PSTR("M21"));
  469. filenavigator.reset();
  470. }
  471. break;
  472. case 56: // Set Fan, Flow, Print Speed
  473. switch (nextion_command[4]) {
  474. case 'S': setTargetFan_percent(atof(&nextion_command[5]), FAN0); break;
  475. case 'P': setFeedrate_percent(atoi(&nextion_command[5])); break;
  476. case 'F': setFlow_percent(atoi(&nextion_command[5]), getActiveTool()); break;
  477. }
  478. break;
  479. case 57: // Disable Motors
  480. if (!isPrinting()) {
  481. stepper.disable_all_steppers();
  482. SEND_TXT("tmppage.M117", "Motors disabled");
  483. }
  484. break;
  485. case 58: // Load/Unload Filament
  486. #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
  487. if (canMove(getActiveTool())) {
  488. switch (nextion_command[4]) {
  489. case 'L': injectCommands_P(PSTR("M701")); break;
  490. case 'U': injectCommands_P(PSTR("M702")); break;
  491. }
  492. }
  493. else {
  494. SEND_TXT("tmppage.M117", "Preheat first");
  495. SEND_TXT_END("page preheat");
  496. }
  497. #else
  498. SEND_TXT("tmppage.M117", "Filament loading disabled");
  499. #endif
  500. break;
  501. case 63: // Preheat // Temps defined in configuration.h
  502. #if PREHEAT_COUNT
  503. if (!isPrinting()) switch (nextion_command[4]) {
  504. // Preheat PLA
  505. case 'P':
  506. #if HAS_HEATED_BED
  507. setTargetTemp_celsius(getMaterial_preset_B(0), BED);
  508. #endif
  509. setTargetTemp_celsius(getMaterial_preset_E(0), getActiveTool());
  510. break;
  511. // Preheat ABS
  512. case 'A':
  513. #if HAS_HEATED_BED
  514. setTargetTemp_celsius(getMaterial_preset_B(1), BED);
  515. #endif
  516. setTargetTemp_celsius(getMaterial_preset_E(1), getActiveTool());
  517. break;
  518. // Preheat PETG
  519. case 'G':
  520. #if HAS_HEATED_BED
  521. setTargetTemp_celsius(getMaterial_preset_B(2), BED);
  522. #endif
  523. setTargetTemp_celsius(getMaterial_preset_E(2), getActiveTool());
  524. break;
  525. }
  526. #else
  527. SEND_TXT("tmppage.M117", "Preheat disabled");
  528. #endif
  529. break;
  530. }
  531. }
  532. void NextionTFT::UpdateOnChange() {
  533. const millis_t ms = millis();
  534. static millis_t next_event_ms = 0;
  535. static celsius_float_t last_degBed = 999, last_degHotend0 = 999, last_degHotend1 = 999,
  536. last_degTargetBed = 999, last_degTargetHotend0 = 999, last_degTargetHotend1 = 999;
  537. // tmppage Temperature
  538. if (!WITHIN(last_degHotend0 - getActualTemp_celsius(E0), -0.2, 0.2) || !WITHIN(last_degTargetHotend0 - getTargetTemp_celsius(E0), -0.5, 0.5)) {
  539. SEND_TEMP("tmppage.t0", ui8tostr3rj(getActualTemp_celsius(E0)), " / ", ui8tostr3rj(getTargetTemp_celsius(E0)));
  540. last_degHotend0 = getActualTemp_celsius(E0);
  541. last_degTargetHotend0 = getTargetTemp_celsius(E0);
  542. }
  543. if (!WITHIN(last_degHotend1 - getActualTemp_celsius(E1), -0.2, 0.2) || !WITHIN(last_degTargetHotend1 - getTargetTemp_celsius(E1), -0.5, 0.5)) {
  544. SEND_TEMP("tmppage.t1", ui8tostr3rj(getActualTemp_celsius(E1)), " / ", ui8tostr3rj(getTargetTemp_celsius(E1)));
  545. last_degHotend1 = getActualTemp_celsius(E1);
  546. last_degTargetHotend1 = getTargetTemp_celsius(E1);
  547. }
  548. if (!WITHIN(last_degBed - getActualTemp_celsius(BED), -0.2, 0.2) || !WITHIN(last_degTargetBed - getTargetTemp_celsius(BED), -0.5, 0.5)) {
  549. SEND_TEMP("tmppage.t2", ui8tostr3rj(getActualTemp_celsius(BED)), " / ", ui8tostr3rj(getTargetTemp_celsius(BED)));
  550. last_degBed = getActualTemp_celsius(BED);
  551. last_degTargetBed = getTargetTemp_celsius(BED);
  552. }
  553. // tmppage Tool
  554. static uint8_t last_active_extruder = 99;
  555. if (last_active_extruder != getActiveTool()) {
  556. SEND_VALasTXT("tmppage.tool", getActiveTool());
  557. last_active_extruder = getActiveTool();
  558. }
  559. // tmppage Fan Speed
  560. static uint8_t last_fan_speed = 99;
  561. if (last_fan_speed != getActualFan_percent(FAN0)) {
  562. SEND_VALasTXT("tmppage.fan", ui8tostr3rj(getActualFan_percent(FAN0)));
  563. last_fan_speed = getActualFan_percent(FAN0);
  564. }
  565. // tmppage Print Speed
  566. static uint8_t last_print_speed = 99;
  567. if (last_print_speed != getFeedrate_percent()) {
  568. SEND_VALasTXT("tmppage.speed", ui8tostr3rj(getFeedrate_percent()));
  569. last_print_speed = getFeedrate_percent();
  570. }
  571. // tmppage Flow
  572. static uint8_t last_flow_speed = 99;
  573. if (last_flow_speed != getFlow_percent(getActiveTool())) {
  574. SEND_VALasTXT("tmppage.flow", getFlow_percent(getActiveTool()));
  575. last_flow_speed = getFlow_percent(getActiveTool());
  576. }
  577. // tmppage Axis
  578. static float last_get_axis_position_mmX = 999, last_get_axis_position_mmY = 999, last_get_axis_position_mmZ = 999;
  579. // tmppage Progress + Layer + Time
  580. if (isPrinting()) {
  581. if (ELAPSED(ms, next_event_ms)) {
  582. next_event_ms = ms + 1000;
  583. #if ENABLED(SHOW_REMAINING_TIME)
  584. const uint32_t remaining = getProgress_seconds_remaining();
  585. char remaining_str[10];
  586. _format_time(remaining_str, remaining);
  587. SEND_VALasTXT("tmppage.remaining", remaining_str);
  588. #endif
  589. const uint32_t elapsed = getProgress_seconds_elapsed();
  590. char elapsed_str[10];
  591. _format_time(elapsed_str, elapsed);
  592. SEND_VALasTXT("tmppage.elapsed", elapsed_str);
  593. }
  594. static uint8_t last_progress = 99;
  595. if (last_progress != getProgress_percent()) {
  596. SEND_VALasTXT("tmppage.progress", ui8tostr3rj(getProgress_percent()));
  597. last_progress = getProgress_percent();
  598. }
  599. if (last_get_axis_position_mmZ < getAxisPosition_mm(Z)) {
  600. layer++;
  601. SEND_VALasTXT("tmppage.layer", layer);
  602. }
  603. if (last_get_axis_position_mmZ > getAxisPosition_mm(Z)) {
  604. layer--;
  605. SEND_VALasTXT("tmppage.layer", layer);
  606. }
  607. }
  608. if (!WITHIN(last_get_axis_position_mmX - getAxisPosition_mm(X), -0.1, 0.1)) {
  609. if (ELAPSED(ms, next_event_ms)) {
  610. next_event_ms = ms + 30;
  611. SEND_VALasTXT("tmppage.x", getAxisPosition_mm(X));
  612. last_get_axis_position_mmX = getAxisPosition_mm(X);
  613. }
  614. }
  615. if (!WITHIN(last_get_axis_position_mmY - getAxisPosition_mm(Y), -0.1, 0.1)) {
  616. if (ELAPSED(ms, next_event_ms)) {
  617. next_event_ms = ms + 30;
  618. SEND_VALasTXT("tmppage.y", getAxisPosition_mm(Y));
  619. last_get_axis_position_mmY = getAxisPosition_mm(Y);
  620. }
  621. }
  622. if (!WITHIN(last_get_axis_position_mmZ - getAxisPosition_mm(Z), -0.1, 0.1)) {
  623. SEND_VALasTXT("tmppage.z", getAxisPosition_mm(Z));
  624. last_get_axis_position_mmZ = getAxisPosition_mm(Z);
  625. }
  626. // tmppage homed
  627. static bool last_homed = false, last_homedX = false, last_homedY = false, last_homedZ = false;
  628. if (last_homed != isPositionKnown()) {
  629. SEND_VAL("tmppage.homed", isPositionKnown());
  630. last_homed = isPositionKnown();
  631. }
  632. if (last_homedX != isAxisPositionKnown(X)) {
  633. SEND_VAL("tmppage.homedx", isAxisPositionKnown(X));
  634. last_homedX = isAxisPositionKnown(X);
  635. }
  636. if (last_homedY != isAxisPositionKnown(Y)) {
  637. SEND_VAL("tmppage.homedy", isAxisPositionKnown(Y));
  638. last_homedY = isAxisPositionKnown(Y);
  639. }
  640. if (last_homedZ != isAxisPositionKnown(Z)) {
  641. SEND_VAL("tmppage.homedz", isAxisPositionKnown(Z));
  642. last_homedZ = isAxisPositionKnown(Z);
  643. }
  644. #if ENABLED(DUAL_X_CARRIAGE)
  645. // tmppage IDEX Mode
  646. static uint8_t last_IDEX_Mode = 99;
  647. if (last_IDEX_Mode != getIDEX_Mode()) {
  648. SEND_VAL("tmppage.idexmode", getIDEX_Mode());
  649. last_IDEX_Mode = getIDEX_Mode();
  650. }
  651. #endif
  652. }
  653. #endif // NEXTION_TFT