Browse Source

Nextion TFT touch screen (#21324)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
Skorpi08 3 years ago
parent
commit
b51aed8aa5
No account linked to committer's email address

+ 8
- 0
Marlin/Configuration.h View File

@@ -2397,6 +2397,14 @@
2397 2397
 #endif
2398 2398
 
2399 2399
 //
2400
+// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
2401
+//
2402
+//#define NEXTION_TFT
2403
+#if ENABLED(NEXTION_TFT)
2404
+  #define LCD_SERIAL_PORT 1  // Default is 1 for Nextion
2405
+#endif
2406
+
2407
+//
2400 2408
 // Third-party or vendor-customized controller interfaces.
2401 2409
 // Sources should be installed in 'src/lcd/extui'.
2402 2410
 //

+ 1
- 1
Marlin/src/inc/Conditionals_LCD.h View File

@@ -460,7 +460,7 @@
460 460
 #endif
461 461
 
462 462
 // Extensible UI serial touch screens. (See src/lcd/extui)
463
-#if ANY(HAS_DGUS_LCD, MALYAN_LCD, TOUCH_UI_FTDI_EVE, ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
463
+#if ANY(HAS_DGUS_LCD, MALYAN_LCD, TOUCH_UI_FTDI_EVE, ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, NEXTION_TFT)
464 464
   #define IS_EXTUI 1
465 465
   #define EXTENSIBLE_UI
466 466
 #endif

+ 1
- 0
Marlin/src/inc/SanityCheck.h View File

@@ -2353,6 +2353,7 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
2353 2353
   + ENABLED(MAKEBOARD_MINI_2_LINE_DISPLAY_1602) \
2354 2354
   + ENABLED(MAKRPANEL) \
2355 2355
   + ENABLED(MALYAN_LCD) \
2356
+  + ENABLED(NEXTION_TFT) \
2356 2357
   + ENABLED(MKS_LCD12864) \
2357 2358
   + ENABLED(OLED_PANEL_TINYBOY2) \
2358 2359
   + ENABLED(OVERLORD_OLED) \

+ 174
- 0
Marlin/src/lcd/extui/lib/nextion/FileNavigator.cpp View File

@@ -0,0 +1,174 @@
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
+/* ****************************************
24
+ * lcd/extui/lib/nextion/FileNavigator.cpp
25
+ * ****************************************
26
+ * Extensible_UI implementation for Nextion
27
+ * https://github.com/Skorpi08
28
+ * ***************************************/
29
+
30
+#include "../../../../inc/MarlinConfigPre.h"
31
+
32
+#if ENABLED(NEXTION_TFT)
33
+
34
+#include "FileNavigator.h"
35
+#include "nextion_tft.h"
36
+
37
+using namespace ExtUI;
38
+
39
+#define DEBUG_OUT NEXDEBUGLEVEL
40
+#include "../../../../core/debug_out.h"
41
+
42
+FileList  FileNavigator::filelist;                          // Instance of the Marlin file API
43
+char      FileNavigator::currentfoldername[MAX_PATH_LEN];   // Current folder path
44
+uint16_t  FileNavigator::lastindex;
45
+uint8_t   FileNavigator::folderdepth;
46
+uint16_t  FileNavigator::currentindex;                      // override the panel request
47
+
48
+FileNavigator filenavigator;
49
+
50
+FileNavigator::FileNavigator() { reset(); }
51
+
52
+void FileNavigator::reset() {
53
+  currentfoldername[0] = '\0';
54
+  folderdepth  = 0;
55
+  currentindex = 0;
56
+  lastindex    = 0;
57
+  // Start at root folder
58
+  while (!filelist.isAtRootDir()) filelist.upDir();
59
+  refresh();
60
+}
61
+
62
+void FileNavigator::refresh() { filelist.refresh(); }
63
+
64
+void FileNavigator::getFiles(uint16_t index) {
65
+  uint16_t files = 7, fseek = 0, fcnt  = 0;
66
+  if (index == 0)
67
+    currentindex = 0;
68
+  else {
69
+    // Each time we change folder we reset the file index to 0 and keep track
70
+    // of the current position as the TFT panel isn't aware of folder trees.
71
+    --currentindex; // go back a file to take account of the .. added to the root.
72
+    if (index > lastindex)
73
+      currentindex += files + 1;
74
+    else if (currentindex >= files)
75
+      currentindex -= files - 1;
76
+    else
77
+      currentindex = 0;
78
+  }
79
+  lastindex = index;
80
+
81
+  #if NEXDEBUG(AC_FILE)
82
+    DEBUG_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
83
+  #endif
84
+
85
+  if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
86
+    nextion.SendtoTFT(PSTR("vis p0,1"));
87
+    nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
88
+    SEND_VAL("tmpUP", "0");
89
+    files--;
90
+  }
91
+  else {
92
+    nextion.SendtoTFT(PSTR("vis p0,0"));
93
+    nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
94
+  }
95
+
96
+  for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
97
+    if (filelist.seek(seek)) {
98
+      nextion.SendtoTFT(PSTR("s"));
99
+      LCD_SERIAL.print(fcnt);
100
+      nextion.SendtoTFT(PSTR(".txt=\""));
101
+      if (filelist.isDir()) {
102
+        LCD_SERIAL.print(filelist.shortFilename());
103
+        nextion.SendtoTFT(PSTR("/\""));
104
+        nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
105
+
106
+        nextion.SendtoTFT(PSTR("l"));
107
+        LCD_SERIAL.print(fcnt);
108
+        nextion.SendtoTFT(PSTR(".txt=\""));
109
+        LCD_SERIAL.print(filelist.filename());
110
+        nextion.SendtoTFT(PSTR("\""));
111
+        nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
112
+        SEND_PCO2("l", fcnt, "1055");
113
+      }
114
+      else {
115
+        LCD_SERIAL.print(currentfoldername);
116
+        LCD_SERIAL.print(filelist.shortFilename());
117
+        nextion.SendtoTFT(PSTR("\""));
118
+        nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
119
+
120
+        nextion.SendtoTFT(PSTR("l"));
121
+        LCD_SERIAL.print(fcnt);
122
+        nextion.SendtoTFT(PSTR(".txt=\""));
123
+        LCD_SERIAL.print(filelist.longFilename());
124
+        nextion.SendtoTFT(PSTR("\""));
125
+        nextion.SendtoTFT(PSTR("\xFF\xFF\xFF"));
126
+      }
127
+      fcnt++;
128
+      fseek = seek;
129
+      #if NEXDEBUG(AC_FILE)
130
+        DEBUG_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
131
+      #endif
132
+    }
133
+  }
134
+  SEND_VAL("n0", filelist.count());
135
+  SEND_VAL("n1", fseek + 1);
136
+}
137
+
138
+void FileNavigator::changeDIR(char *folder) {
139
+  #if NEXDEBUG(AC_FILE)
140
+    DEBUG_ECHOLNPAIR("currentfolder: ", currentfoldername, "  New: ", folder);
141
+  #endif
142
+  if (folderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
143
+  strcat(currentfoldername, folder);
144
+  strcat(currentfoldername, "/");
145
+  filelist.changeDir(folder);
146
+  refresh();
147
+  folderdepth++;
148
+  currentindex = 0;
149
+}
150
+
151
+void FileNavigator::upDIR() {
152
+  filelist.upDir();
153
+  refresh();
154
+  folderdepth--;
155
+  currentindex = 0;
156
+  // Remove the last child folder from the stored path
157
+  if (folderdepth == 0) {
158
+    currentfoldername[0] = '\0';
159
+    reset();
160
+  }
161
+  else {
162
+    char *pos = nullptr;
163
+    for (uint8_t f = 0; f < folderdepth; f++)
164
+      pos = strchr(currentfoldername, '/');
165
+    pos[1] = '\0';
166
+  }
167
+  #if NEXDEBUG(AC_FILE)
168
+    DEBUG_ECHOLNPAIR("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
169
+  #endif
170
+}
171
+
172
+char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
173
+
174
+#endif // NEXTION_TFT

+ 53
- 0
Marlin/src/lcd/extui/lib/nextion/FileNavigator.h View File

@@ -0,0 +1,53 @@
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
+#pragma once
23
+
24
+/* ****************************************
25
+ * lcd/extui/lib/nextion/FileNavigator.cpp
26
+ * ****************************************
27
+ * Extensible_UI implementation for Nextion
28
+ * https://github.com/Skorpi08
29
+ * ***************************************/
30
+
31
+#include "nextion_tft_defs.h" // for MAX_PATH_LEN
32
+#include "../../ui_api.h"
33
+
34
+using namespace ExtUI;
35
+
36
+class FileNavigator {
37
+  public:
38
+    FileNavigator();
39
+    static void  reset();
40
+    static void  getFiles(uint16_t);
41
+    static void  upDIR();
42
+    static void  changeDIR(char *);
43
+    static void  refresh();
44
+    static char* getCurrentFolderName();
45
+  private:
46
+    static FileList filelist;
47
+    static char     currentfoldername[MAX_PATH_LEN];
48
+    static uint16_t lastindex;
49
+    static uint8_t  folderdepth;
50
+    static uint16_t currentindex;
51
+};
52
+
53
+extern FileNavigator filenavigator;

+ 729
- 0
Marlin/src/lcd/extui/lib/nextion/nextion_tft.cpp View File

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

+ 62
- 0
Marlin/src/lcd/extui/lib/nextion/nextion_tft.h View File

@@ -0,0 +1,62 @@
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
+#pragma once
23
+
24
+/* ****************************************
25
+ * lcd/extui/lib/nextion/nextion_tft.h
26
+ * ****************************************
27
+ * Extensible_UI implementation for Nextion
28
+ * https://github.com/Skorpi08
29
+ * ***************************************/
30
+
31
+#include "nextion_tft_defs.h"
32
+#include "../../../../inc/MarlinConfigPre.h"
33
+#include "../../ui_api.h"
34
+
35
+class NextionTFT {
36
+  private:
37
+    static uint8_t command_len;
38
+    static char    nextion_command[MAX_CMND_LEN];
39
+    static char    selectedfile[MAX_PATH_LEN];
40
+
41
+  public:
42
+    NextionTFT();
43
+    static void Startup();
44
+    static void IdleLoop();
45
+    static void PrinterKilled(PGM_P, PGM_P);
46
+    static void ConfirmationRequest(const char * const );
47
+    static void StatusChange(const char * const );
48
+    static void SendtoTFT(PGM_P);
49
+    static void UpdateOnChange();
50
+    static void PrintFinished();
51
+    static void PanelInfo(uint8_t);
52
+
53
+  private:
54
+    static bool ReadTFTCommand();
55
+    static void SendFileList(int8_t);
56
+    static void SelectFile();
57
+    static void ProcessPanelRequest();
58
+    static void PanelAction(uint8_t);
59
+    static void _format_time(char *, uint32_t);
60
+};
61
+
62
+extern NextionTFT nextion;

+ 63
- 0
Marlin/src/lcd/extui/lib/nextion/nextion_tft_defs.h View File

@@ -0,0 +1,63 @@
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
+#pragma once
23
+
24
+/* ****************************************
25
+ * lcd/extui/lib/nextion/nextion_tft_defs.h
26
+ * ****************************************
27
+ * Extensible_UI implementation for Nextion
28
+ * https://github.com/Skorpi08
29
+ * ***************************************/
30
+
31
+#include "../../../../inc/MarlinConfigPre.h"
32
+
33
+//#define NEXDEBUGLEVEL 255
34
+#if NEXDEBUGLEVEL
35
+  // Bit-masks for selective debug:
36
+  enum NexDebugMask : uint8_t {
37
+    N_INFO   = _BV(0),
38
+    N_ACTION = _BV(1),
39
+    N_FILE   = _BV(2),
40
+    N_PANEL  = _BV(3),
41
+    N_MARLIN = _BV(4),
42
+    N_SOME   = _BV(5),
43
+    N_ALL    = _BV(6)
44
+  };
45
+  #define NEXDEBUG(M) (((M) & NEXDEBUGLEVEL) == M)  // Debug flag macro
46
+#else
47
+  #define NEXDEBUG(M) false
48
+#endif
49
+
50
+#define MAX_FOLDER_DEPTH                4    // Limit folder depth TFT has a limit for the file path
51
+#define MAX_CMND_LEN                   16 * MAX_FOLDER_DEPTH // Maximum Length for a Panel command
52
+#define MAX_PATH_LEN                   16 * MAX_FOLDER_DEPTH // Maximum number of characters in a SD file path
53
+
54
+ // TFT panel commands
55
+#define  msg_welcome                MACHINE_NAME " Ready."
56
+
57
+#define SEND_TEMP(x,y,t,z)  (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR(".txt=\"")), LCD_SERIAL.print(y), nextion.SendtoTFT(PSTR(t)), LCD_SERIAL.print(z), nextion.SendtoTFT(PSTR("\"\xFF\xFF\xFF")))
58
+#define SEND_VAL(x,y)       (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR(".val=")),   LCD_SERIAL.print(y), nextion.SendtoTFT(PSTR("\xFF\xFF\xFF")))
59
+#define SEND_TXT(x,y)       (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR(".txt=\"")), nextion.SendtoTFT(PSTR(y)),  nextion.SendtoTFT(PSTR("\"\xFF\xFF\xFF")))
60
+#define SEND_TXT_P(x,y)     (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR(".txt=\"")), nextion.SendtoTFT(y), nextion.SendtoTFT(PSTR("\"\xFF\xFF\xFF")))
61
+#define SEND_VALasTXT(x,y)  (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR(".txt=\"")), LCD_SERIAL.print(y), nextion.SendtoTFT(PSTR("\"\xFF\xFF\xFF")))
62
+#define SEND_TXT_END(x)     (nextion.SendtoTFT(PSTR(x)), nextion.SendtoTFT(PSTR("\xFF\xFF\xFF")))
63
+#define SEND_PCO2(x,y,z)    (nextion.SendtoTFT(PSTR(x)), LCD_SERIAL.print(y), nextion.SendtoTFT(PSTR(".pco=")), nextion.SendtoTFT(PSTR(z)), nextion.SendtoTFT(PSTR("\xFF\xFF\xFF")))

+ 117
- 0
Marlin/src/lcd/extui/nextion_lcd.cpp View File

@@ -0,0 +1,117 @@
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
+/**
24
+ * lcd/extui/nextion_lcd.cpp
25
+ *
26
+ * Nextion TFT support for Marlin
27
+ */
28
+
29
+#include "../../inc/MarlinConfigPre.h"
30
+
31
+#if ENABLED(NEXTION_TFT)
32
+
33
+#include "ui_api.h"
34
+#include "lib/nextion/nextion_tft.h"
35
+
36
+namespace ExtUI {
37
+
38
+  void onStartup()                                   { nextion.Startup();  }
39
+  void onIdle()                                      { nextion.IdleLoop(); }
40
+  void onPrinterKilled(PGM_P const error, PGM_P const component) { nextion.PrinterKilled(error,component); }
41
+  void onMediaInserted() {}
42
+  void onMediaError()    {}
43
+  void onMediaRemoved()  {}
44
+  void onPlayTone(const uint16_t frequency, const uint16_t duration) {}
45
+  void onPrintTimerStarted() {}
46
+  void onPrintTimerPaused()  {}
47
+  void onPrintTimerStopped() {}
48
+  void onFilamentRunout(const extruder_t)            {}
49
+  void onUserConfirmRequired(const char * const msg) { nextion.ConfirmationRequest(msg); }
50
+  void onStatusChanged(const char * const msg)       { nextion.StatusChange(msg);        }
51
+
52
+  void onHomingStart()    {}
53
+  void onHomingComplete() {}
54
+  void onPrintFinished()                             { nextion.PrintFinished(); }
55
+
56
+  void onFactoryReset()   {}
57
+
58
+  void onStoreSettings(char *buff) {
59
+    // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
60
+    // permanent data to be stored, it can write up to eeprom_data_size bytes
61
+    // into buff.
62
+
63
+    // Example:
64
+    //  static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
65
+    //  memcpy(buff, &myDataStruct, sizeof(myDataStruct));
66
+  }
67
+
68
+  void onLoadSettings(const char *buff) {
69
+    // Called while loading settings from EEPROM. If the ExtUI
70
+    // needs to retrieve data, it should copy up to eeprom_data_size bytes
71
+    // from buff
72
+
73
+    // Example:
74
+    //  static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
75
+    //  memcpy(&myDataStruct, buff, sizeof(myDataStruct));
76
+  }
77
+
78
+  void onConfigurationStoreWritten(bool success) {
79
+    // Called after the entire EEPROM has been written,
80
+    // whether successful or not.
81
+  }
82
+
83
+  void onConfigurationStoreRead(bool success) {
84
+    // Called after the entire EEPROM has been read,
85
+    // whether successful or not.
86
+  }
87
+
88
+  #if HAS_MESH
89
+    void onMeshLevelingStart() {}
90
+
91
+    void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
92
+      // Called when any mesh points are updated
93
+    }
94
+
95
+    void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
96
+      // Called to indicate a special condition
97
+    }
98
+  #endif
99
+
100
+  #if ENABLED(POWER_LOSS_RECOVERY)
101
+    void onPowerLossResume() {
102
+      // Called on resume from power-loss
103
+    }
104
+  #endif
105
+
106
+  #if HAS_PID_HEATING
107
+    void onPidTuning(const result_t rst) {
108
+      // Called for temperature PID tuning result
109
+      nextion.PanelInfo(37);
110
+    }
111
+  #endif
112
+
113
+  void onSteppersDisabled() {}
114
+  void onSteppersEnabled()  {}
115
+}
116
+
117
+#endif // NEXTION_TFT

+ 13
- 2
Marlin/src/lcd/extui/ui_api.cpp View File

@@ -651,6 +651,17 @@ namespace ExtUI {
651 651
     void setAxisMaxJerk_mm_s(const float &value, const extruder_t) { planner.set_max_jerk(E_AXIS, value); }
652 652
   #endif
653 653
 
654
+  #if ENABLED(DUAL_X_CARRIAGE)
655
+    uint8_t getIDEX_Mode() { return dual_x_carriage_mode; }
656
+  #endif
657
+
658
+  #if PREHEAT_COUNT
659
+      uint16_t getMaterial_preset_E(const uint16_t index) { return ui.material_preset[index].hotend_temp; }
660
+    #if HAS_HEATED_BED
661
+      uint16_t getMaterial_preset_B(const uint16_t index) { return ui.material_preset[index].bed_temp; }
662
+    #endif
663
+  #endif
664
+
654 665
   feedRate_t getFeedrate_mm_s()                       { return feedrate_mm_s; }
655 666
   int16_t getFlowPercentage(const extruder_t extr)    { return planner.flow_percentage[extr]; }
656 667
   feedRate_t getMinFeedrate_mm_s()                    { return planner.settings.min_feedrate_mm_s; }
@@ -663,8 +674,8 @@ namespace ExtUI {
663 674
   void setMinFeedrate_mm_s(const feedRate_t fr)       { planner.settings.min_feedrate_mm_s = fr; }
664 675
   void setMinTravelFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
665 676
   void setPrintingAcceleration_mm_s2(const float &acc) { planner.settings.acceleration = acc; }
666
-  void setRetractAcceleration_mm_s2(const float &acc)  { planner.settings.retract_acceleration = acc; }
667
-  void setTravelAcceleration_mm_s2(const float &acc)   { planner.settings.travel_acceleration = acc; }
677
+  void setRetractAcceleration_mm_s2(const float &acc) { planner.settings.retract_acceleration = acc; }
678
+  void setTravelAcceleration_mm_s2(const float &acc)  { planner.settings.travel_acceleration = acc; }
668 679
 
669 680
   #if ENABLED(BABYSTEPPING)
670 681
 

+ 12
- 0
Marlin/src/lcd/extui/ui_api.h View File

@@ -139,6 +139,17 @@ namespace ExtUI {
139 139
 
140 140
   uint32_t getProgress_seconds_elapsed();
141 141
 
142
+  #if PREHEAT_COUNT
143
+    uint16_t getMaterial_preset_E(const uint16_t);
144
+    #if HAS_HEATED_BED
145
+      uint16_t getMaterial_preset_B(const uint16_t);
146
+    #endif
147
+  #endif
148
+
149
+  #if ENABLED(DUAL_X_CARRIAGE)
150
+    uint8_t getIDEX_Mode();
151
+  #endif
152
+
142 153
   #if ENABLED(SHOW_REMAINING_TIME)
143 154
     inline uint32_t getProgress_seconds_remaining() { return ui.get_remaining_time(); }
144 155
   #endif
@@ -171,6 +182,7 @@ namespace ExtUI {
171 182
   #endif
172 183
 
173 184
   #if ENABLED(PRINTCOUNTER)
185
+    char* getFailedPrints_str(char buffer[21]);
174 186
     char* getTotalPrints_str(char buffer[21]);
175 187
     char* getFinishedPrints_str(char buffer[21]);
176 188
     char* getTotalPrintTime_str(char buffer[21]);

+ 2
- 0
platformio.ini View File

@@ -59,6 +59,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
59 59
   -<src/lcd/extui/lib/ftdi_eve_touch_ui>
60 60
   -<src/lcd/extui/anycubic_chiron_lcd.cpp> -<src/lcd/extui/lib/anycubic_chiron>
61 61
   -<src/lcd/extui/anycubic_i3mega_lcd.cpp> -<src/lcd/extui/lib/anycubic_i3mega>
62
+  -<src/lcd/extui/nextion_lcd.cpp> -<src/lcd/extui/lib/nextion>
62 63
   -<src/lcd/lcdprint.cpp>
63 64
   -<src/lcd/touch/touch_buttons.cpp>
64 65
   -<src/sd/usb_flashdrive/lib-uhs2> -<src/sd/usb_flashdrive/lib-uhs3>
@@ -289,6 +290,7 @@ HAS_MENU_TRAMMING       = src_filter=+<src/lcd/menu/menu_tramming.cpp>
289 290
 HAS_MENU_UBL            = src_filter=+<src/lcd/menu/menu_ubl.cpp>
290 291
 ANYCUBIC_LCD_CHIRON     = src_filter=+<src/lcd/extui/anycubic_chiron_lcd.cpp> +<src/lcd/extui/lib/anycubic_chiron>
291 292
 ANYCUBIC_LCD_I3MEGA     = src_filter=+<src/lcd/extui/anycubic_i3mega_lcd.cpp> +<src/lcd/extui/lib/anycubic_i3mega>
293
+NEXTION_TFT             = src_filter=+<src/lcd/extui/nextion_lcd.cpp> +<src/lcd/extui/lib/nextion>
292 294
 HAS_DGUS_LCD            = src_filter=+<src/lcd/extui/lib/dgus> +<src/lcd/extui/dgus_lcd.cpp>
293 295
 DGUS_LCD_UI_FYSETC      = src_filter=+<src/lcd/extui/lib/dgus/fysetc>
294 296
 DGUS_LCD_UI_HIPRECY     = src_filter=+<src/lcd/extui/lib/dgus/hiprecy>

Loading…
Cancel
Save