Marlin 2.0 for Flying Bear 4S/5
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.
 
 
 
 
 
 

736 lines
24 KiB

/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* ****************************************
* lcd/extui/nextion/nextion_tft.h
* ****************************************
* Extensible_UI implementation for Nextion
* https://github.com/Skorpi08
* ***************************************/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(NEXTION_TFT)
#include "../../../MarlinCore.h"
#include "../../../feature/pause.h"
#include "../../../module/stepper.h"
#include "../../../gcode/queue.h"
#include "../../../libs/numtostr.h"
#include "../../../sd/cardreader.h"
#include "FileNavigator.h"
#include "nextion_tft.h"
#define DEBUG_OUT NEXDEBUGLEVEL
#include "../../../core/debug_out.h"
char NextionTFT::selectedfile[MAX_PATH_LEN];
char NextionTFT::nextion_command[MAX_CMND_LEN];
uint8_t NextionTFT::command_len;
uint32_t layer = 0;
NextionTFT nextion;
NextionTFT::NextionTFT() {}
void NextionTFT::Startup() {
selectedfile[0] = '\0';
nextion_command[0] = '\0';
command_len = 0;
LCD_SERIAL.begin(115200);
SEND_VAL("tmppage.connected", 0);
delay_ms(100);
SEND_VAL("tmppage.connected", 1);
SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
DEBUG_ECHOLNPGM("Nextion Debug Level ", NEXDEBUGLEVEL);
}
void NextionTFT::IdleLoop() {
if (ReadTFTCommand()) {
ProcessPanelRequest();
command_len = 0;
}
UpdateOnChange();
}
void NextionTFT::PrinterKilled(FSTR_P const error, FSTR_P const component) {
SEND_TXT_END("page error");
SEND_TXT_F("t3", F("Error"));
SEND_TXT_F("t4", component);
SEND_TXT_F("t5", error);
SEND_TXT_F("t6", F("Need reset"));
}
void NextionTFT::PrintFinished() {
SEND_TXT_END("page printfinished");
}
void NextionTFT::ConfirmationRequest(const char * const msg) {
SEND_VALasTXT("tmppage.M117", msg);
#if NEXDEBUG(N_MARLIN)
DEBUG_ECHOLNPGM("ConfirmationRequest() ", msg, " printer_state:", printer_state);
#endif
}
void NextionTFT::StatusChange(const char * const msg) {
#if NEXDEBUG(N_MARLIN)
DEBUG_ECHOLNPGM("StatusChange() ", msg, "\nprinter_state:", printer_state);
#endif
SEND_VALasTXT("tmppage.M117", msg);
}
void NextionTFT::SendtoTFT(FSTR_P const fstr/*=nullptr*/) { // A helper to print PROGMEM string to the panel
#if NEXDEBUG(N_SOME)
DEBUG_ECHOF(fstr);
#endif
PGM_P str = FTOP(fstr);
while (const char c = pgm_read_byte(str++)) LCD_SERIAL.write(c);
}
bool NextionTFT::ReadTFTCommand() {
bool command_ready = false;
while ((LCD_SERIAL.available() > 0) && (command_len < MAX_CMND_LEN)) {
nextion_command[command_len] = LCD_SERIAL.read();
if (nextion_command[command_len] == 10) {
command_ready = true;
break;
}
command_len++;
}
if (command_ready) {
nextion_command[command_len] = 0x00;
if (nextion_command[0] == 'G' || nextion_command[0] == 'M' || nextion_command[0] == 'T')
injectCommands(nextion_command);
#if NEXDEBUG(N_ALL)
DEBUG_ECHOLNPGM("< ", nextion_command);
#endif
#if NEXDEBUG(N_SOME)
uint8_t req = atoi(&nextion_command[1]);
if (req > 7 && req != 20)
DEBUG_ECHOLNPGM( "> ", AS_CHAR(nextion_command[0]),
"\n> ", AS_CHAR(nextion_command[1]),
"\n> ", AS_CHAR(nextion_command[2]),
"\n> ", AS_CHAR(nextion_command[3]),
"\nprinter_state:", printer_state);
#endif
}
return command_ready;
}
void NextionTFT::SendFileList(int8_t startindex) {
// respond to panel request for 7 files starting at index
#if NEXDEBUG(N_INFO)
DEBUG_ECHOLNPGM("## SendFileList ## ", startindex);
#endif
filenavigator.getFiles(startindex);
}
void NextionTFT::SelectFile() {
strncpy(selectedfile, nextion_command + 4, command_len - 4);
selectedfile[command_len - 5] = '\0';
#if NEXDEBUG(N_FILE)
DEBUG_ECHOLNPAIR_F(" Selected File: ", selectedfile);
#endif
switch (selectedfile[0]) {
case '/': // Valid file selected
//SEND_TXT("tmppage.M117", msg_sd_file_open_success);
break;
case '<': // .. (go up folder level)
filenavigator.upDIR();
SendFileList(0);
break;
default: // enter sub folder
filenavigator.changeDIR(selectedfile);
SendFileList(0);
break;
}
}
void NextionTFT::_format_time(char *outstr, uint32_t time) {
const uint8_t hrs = time / 3600,
min = (time / 60) % 60,
sec = time % 60;
if (hrs)
sprintf_P(outstr, PSTR("%02d:%02dm"), hrs, min);
else
sprintf_P(outstr, PSTR("%02d:%02ds"), min, sec);
}
void NextionTFT::ProcessPanelRequest() {
// Break these up into logical blocks as its easier to navigate than one huge switch case!
if (nextion_command[0] == 'X') {
int8_t req = atoi(&nextion_command[1]);
// Information requests
if (req <= 49)
PanelInfo(req);
// Simple Actions
else if (req >= 50)
PanelAction(req);
}
}
#define SEND_NA(A) SEND_TXT(A, "n/a")
void NextionTFT::PanelInfo(uint8_t req) {
switch (req) {
case 0: break;
case 1: // Get SD Card list
if (!isPrinting()) {
if (!isMediaInserted()) safe_delay(500);
if (!isMediaInserted()) { // Make sure the card is removed
//SEND_TXT("tmppage.M117", msg_no_sd_card);
}
else if (nextion_command[3] == 'S')
SendFileList(atoi(&nextion_command[4]));
}
break;
case 2: // Printer Info
if (!isPrinting()) {
SEND_VAL("tmppage.connected", 1);
SEND_VALasTXT("tmppage.marlin", SHORT_BUILD_VERSION);
SEND_VALasTXT("tmppage.compiled", __DATE__ " / " __TIME__);
SEND_VALasTXT("tmppage.extruder", EXTRUDERS);
SEND_VALasTXT("tmppage.printer", MACHINE_NAME);
SEND_VALasTXT("tmppage.author", STRING_CONFIG_H_AUTHOR);
SEND_VALasTXT("tmppage.released", STRING_DISTRIBUTION_DATE);
SEND_VALasTXT("tmppage.bedx", X_BED_SIZE);
SEND_VALasTXT("tmppage.bedy", Y_BED_SIZE);
SEND_VALasTXT("tmppage.bedz", Z_MAX_POS);
SEND_TEMP("tmppage.t0", ui8tostr3rj(getActualTemp_celsius(E0)), " / ", ui8tostr3rj(getTargetTemp_celsius(E0)));
SEND_TEMP("tmppage.t1", ui8tostr3rj(getActualTemp_celsius(E1)), " / ", ui8tostr3rj(getTargetTemp_celsius(E1)));
SEND_TEMP("tmppage.t2", ui8tostr3rj(getActualTemp_celsius(BED)), " / ", ui8tostr3rj(getTargetTemp_celsius(BED)));
SEND_VALasTXT("tmppage.tool", getActiveTool());
SEND_VALasTXT("tmppage.fan", ui8tostr3rj(getActualFan_percent(FAN0)));
SEND_VALasTXT("tmppage.speed", getFeedrate_percent());
SEND_VALasTXT("tmppage.flow", getFlow_percent(getActiveTool()));
SEND_VALasTXT("tmppage.progress", ui8tostr3rj(getProgress_percent()));
SEND_VALasTXT("tmppage.layer", layer);
SEND_VALasTXT("tmppage.x", getAxisPosition_mm(X));
SEND_VALasTXT("tmppage.y", getAxisPosition_mm(Y));
SEND_VALasTXT("tmppage.z", getAxisPosition_mm(Z));
SEND_VAL("tmppage.homed", isPositionKnown());
SEND_VAL("tmppage.homedx", isAxisPositionKnown(X));
SEND_VAL("tmppage.homedy", isAxisPositionKnown(Y));
SEND_VAL("tmppage.homedz", isAxisPositionKnown(Z));
#if ENABLED(DUAL_X_CARRIAGE)
SEND_VAL("tmppage.idexmode", getIDEX_Mode());
#endif
SEND_TXT("tmppage.M117", msg_welcome);
}
break;
case 23: // Linear Advance
#if ENABLED(LIN_ADVANCE)
SEND_VALasTXT("linadvance", getLinearAdvance_mm_mm_s(getActiveTool()));
#else
SEND_NA("linadvance");
#endif
break;
case 24: // TMC Motor Current
#if HAS_TRINAMIC_CONFIG
#define SEND_TRINAMIC_CURR(A, B) SEND_VALasTXT(A, getAxisCurrent_mA(B))
#else
#define SEND_TRINAMIC_CURR(A, B) SEND_NA(A)
#endif
SEND_TRINAMIC_CURR("x", X);
SEND_TRINAMIC_CURR("x2", X2);
SEND_TRINAMIC_CURR("y", Y);
SEND_TRINAMIC_CURR("y2", Y2);
SEND_TRINAMIC_CURR("z", Z);
SEND_TRINAMIC_CURR("z2", Z2);
SEND_TRINAMIC_CURR("e", E0);
SEND_TRINAMIC_CURR("e1", E1);
break;
case 25: // TMC Bump Sensitivity
#if HAS_TRINAMIC_CONFIG
#define SEND_TRINAMIC_BUMP(A, B) SEND_VALasTXT(A, getTMCBumpSensitivity(B))
#else
#define SEND_TRINAMIC_BUMP(A, B) SEND_NA(A)
#endif
SEND_TRINAMIC_BUMP("x", X);
SEND_TRINAMIC_BUMP("x2", X2);
SEND_TRINAMIC_BUMP("y", Y);
SEND_TRINAMIC_BUMP("y2", Y2);
SEND_TRINAMIC_BUMP("z", Z);
SEND_TRINAMIC_BUMP("z2", Z2);
break;
case 26: // TMC Hybrid Threshold Speed
#if 0 && BOTH(HAS_TRINAMIC_CONFIG, HYBRID_THRESHOLD)
#define SEND_TRINAMIC_THRS(A, B) SEND_VALasTXT(A, getAxisPWMthrs(B))
#else
#define SEND_TRINAMIC_THRS(A, B) SEND_NA(A)
#endif
SEND_TRINAMIC_THRS("x", X);
SEND_TRINAMIC_THRS("x2", X2);
SEND_TRINAMIC_THRS("y", Y);
SEND_TRINAMIC_THRS("y2", Y2);
SEND_TRINAMIC_THRS("z", Z);
SEND_TRINAMIC_THRS("z2", Z2);
SEND_TRINAMIC_THRS("e", E0);
SEND_TRINAMIC_THRS("e1", E1);
break;
case 27: // Printcounter
#if ENABLED(PRINTCOUNTER)
char buffer[21];
#define SEND_PRINT_INFO(A, B) SEND_VALasTXT(A, B(buffer))
#else
#define SEND_PRINT_INFO(A, B) SEND_NA(A)
#endif
SEND_PRINT_INFO("t5", getTotalPrints_str);
SEND_PRINT_INFO("t3", getFinishedPrints_str);
SEND_PRINT_INFO("t4", getFailedPrints_str);
SEND_PRINT_INFO("t6", getTotalPrintTime_str);
SEND_PRINT_INFO("t7", getLongestPrint_str);
SEND_PRINT_INFO("t8", getFilamentUsed_str);
break;
case 28: // Filament laod/unload
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#define SEND_PAUSE_INFO(A, B) SEND_VALasTXT(A, fc_settings[getActiveTool()].B)
#else
#define SEND_PAUSE_INFO(A, B) SEND_NA(A)
#endif
SEND_PAUSE_INFO("filamentin", load_length);
SEND_PAUSE_INFO("filamentout", unload_length);
break;
case 29: // Preheat
#if HAS_PREHEAT
if (!isPrinting()) {
// Preheat PLA
if (nextion_command[4] == 'P') {
SEND_VALasTXT("pe", getMaterial_preset_E(0));
#if HAS_HEATED_BED
SEND_VALasTXT("pb", getMaterial_preset_B(0));
#endif
}
// Preheat ABS
if (nextion_command[4] == 'A') {
SEND_VALasTXT("ae", getMaterial_preset_E(1));
#if HAS_HEATED_BED
SEND_VALasTXT("ab", getMaterial_preset_B(1));
#endif
}
// Preheat PETG
if (nextion_command[4] == 'G') {
#ifdef PREHEAT_3_TEMP_HOTEND
SEND_VALasTXT("ge", getMaterial_preset_E(2));
#if HAS_HEATED_BED
SEND_VALasTXT("gb", getMaterial_preset_B(2));
#endif
#endif
}
}
#endif
break;
case 30: // Velocity
SEND_VALasTXT("x", getAxisMaxFeedrate_mm_s(X));
SEND_VALasTXT("y", getAxisMaxFeedrate_mm_s(Y));
SEND_VALasTXT("z", getAxisMaxFeedrate_mm_s(Z));
SEND_VALasTXT("e", getAxisMaxFeedrate_mm_s(getActiveTool()));
SEND_VALasTXT("min", getMinFeedrate_mm_s());
SEND_VALasTXT("tmin", getMinTravelFeedrate_mm_s());
break;
case 31: // Jerk
#if ENABLED(CLASSIC_JERK)
#define SEND_JERK_INFO(A, B) SEND_VALasTXT(A, getAxisMaxJerk_mm_s(B))
#else
#define SEND_JERK_INFO(A, B) SEND_NA(A)
//SEND_VALasTXT("x", getJunctionDeviation_mm());
SEND_TXT("tmppage.M117", "classic Jerk not enabled");
#endif
SEND_JERK_INFO("x", X);
SEND_JERK_INFO("y", Y);
SEND_JERK_INFO("z", Z);
SEND_JERK_INFO("e", getActiveTool());
break;
case 32: // Steps-per-mm
SEND_VALasTXT("x", getAxisSteps_per_mm(X));
SEND_VALasTXT("y", getAxisSteps_per_mm(Y));
SEND_VALasTXT("z", getAxisSteps_per_mm(Z));
SEND_VALasTXT("e0", getAxisSteps_per_mm(E0));
SEND_VALasTXT("e1", getAxisSteps_per_mm(E1));
break;
case 33: // Acceleration
SEND_VALasTXT("x", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(X)));
SEND_VALasTXT("y", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(Y)));
SEND_VALasTXT("z", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(Z)));
SEND_VALasTXT("e", ui16tostr5rj(getAxisMaxAcceleration_mm_s2(getActiveTool())));
SEND_VALasTXT("print", ui16tostr5rj(getPrintingAcceleration_mm_s2()));
SEND_VALasTXT("retract", ui16tostr5rj(getRetractAcceleration_mm_s2()));
SEND_VALasTXT("travel", ui16tostr5rj(getTravelAcceleration_mm_s2()));
break;
case 34: // Dual X carriage offset
#if ENABLED(DUAL_X_CARRIAGE)
#define SEND_IDEX_INFO(A, B) SEND_VALasTXT(A, getNozzleOffset_mm(B, getActiveTool()))
#else
#define SEND_IDEX_INFO(A, B) SEND_NA(A)
#endif
SEND_IDEX_INFO("x", X);
SEND_IDEX_INFO("y", Y);
SEND_IDEX_INFO("z", Z);
break;
case 35: // Probe offset
#if HAS_PROBE_XY_OFFSET
#define SEND_PROBE_INFO(A, B) SEND_VALasTXT(A, getProbeOffset_mm(B))
#else
#define SEND_PROBE_INFO(A, B) SEND_NA(A)
#endif
SEND_PROBE_INFO("x", X);
SEND_PROBE_INFO("y", Y);
SEND_VALasTXT("z", getZOffset_mm());
break;
case 36: // Endstop Info
#if X_HOME_TO_MIN
SEND_VALasTXT("x1", READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
#elif X_HOME_TO_MAX
SEND_VALasTXT("x2", READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
#endif
#if Y_HOME_TO_MIN
SEND_VALasTXT("y1", READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
#elif Y_HOME_TO_MAX
SEND_VALasTXT("y2", READ(X_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
#endif
#if Z_HOME_TO_MIN
SEND_VALasTXT("z1", READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
#elif Z_HOME_TO_MAX
SEND_VALasTXT("z2", READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
#endif
#if HAS_Z2_MIN
SEND_VALasTXT("z2", READ(Z2_MIN_PIN) != Z2_MIN_ENDSTOP_INVERTING ? "triggered" : "open");
#elif HAS_Z2_MAX
SEND_VALasTXT("z2", READ(Z2_MAX_PIN) != Z2_MAX_ENDSTOP_INVERTING ? "triggered" : "open");
#endif
#if HAS_BED_PROBE
//SEND_VALasTXT("bltouch", READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING ? "triggered" : "open");
#else
SEND_NA("bltouch");
#endif
break;
case 37: // PID
#if ENABLED(PIDTEMP)
#define SEND_PID_INFO_0(A, B) SEND_VALasTXT(A, getPID_K##B(E0))
#else
#define SEND_PID_INFO_0(A, B) SEND_NA(A)
#endif
#if BOTH(PIDTEMP, HAS_MULTI_EXTRUDER)
#define SEND_PID_INFO_1(A, B) SEND_VALasTXT(A, getPID_K##B(E1))
#else
#define SEND_PID_INFO_1(A, B) SEND_NA(A)
#endif
#if ENABLED(PIDTEMPBED)
#define SEND_PID_INFO_BED(A, B) SEND_VALasTXT(A, getBedPID_K##B())
#else
#define SEND_PID_INFO_BED(A, B) SEND_NA(A)
#endif
SEND_PID_INFO_0("p0", p);
SEND_PID_INFO_0("i0", i);
SEND_PID_INFO_0("d0", d);
SEND_PID_INFO_1("p1", p);
SEND_PID_INFO_1("i1", i);
SEND_PID_INFO_1("d1", d);
SEND_PID_INFO_BED("hbp", p);
SEND_PID_INFO_BED("hbi", i);
SEND_PID_INFO_BED("hbd", d);
break;
}
}
void NextionTFT::PanelAction(uint8_t req) {
switch (req) {
case 50: // Pause SD print
//if (isPrintingFromMedia()) {
//SEND_TXT("tmppage.M117", "Paused");
pausePrint();
SEND_TXT_END("qpause.picc=29");
//}
break;
case 51: // Resume SD Print
resumePrint();
SEND_TXT_END("qpause.picc=28");
break;
case 52: // Stop SD print
//if (isPrintingFromMedia()) {
stopPrint();
SEND_TXT_END("page prepare");
//}
break;
case 54: // A13 Select file
SelectFile();
break;
case 65: // Cool Down
if (!isPrinting()) coolDown();
break;
case 66: // Refresh SD
if (!isPrinting()) {
injectCommands(F("M21"));
filenavigator.reset();
}
break;
case 56: // Set Fan, Flow, Print Speed
switch (nextion_command[4]) {
case 'S': setTargetFan_percent(atof(&nextion_command[5]), FAN0); break;
case 'P': setFeedrate_percent(atoi(&nextion_command[5])); break;
case 'F': setFlow_percent(atoi(&nextion_command[5]), getActiveTool()); break;
}
break;
case 57: // Disable Motors
if (!isPrinting()) {
stepper.disable_all_steppers();
SEND_TXT("tmppage.M117", "Motors disabled");
}
break;
case 58: // Load/Unload Filament
#if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
if (canMove(getActiveTool())) {
switch (nextion_command[4]) {
case 'L': injectCommands(F("M701")); break;
case 'U': injectCommands(F("M702")); break;
}
}
else {
SEND_TXT("tmppage.M117", "Preheat first");
SEND_TXT_END("page preheat");
}
#else
SEND_TXT("tmppage.M117", "Filament loading disabled");
#endif
break;
case 63: // Preheat // Temps defined in configuration.h
#if HAS_PREHEAT
if (!isPrinting()) switch (nextion_command[4]) {
// Preheat PLA
case 'P':
#if HAS_HEATED_BED
setTargetTemp_celsius(getMaterial_preset_B(0), BED);
#endif
setTargetTemp_celsius(getMaterial_preset_E(0), getActiveTool());
break;
// Preheat ABS
case 'A':
#if HAS_HEATED_BED
setTargetTemp_celsius(getMaterial_preset_B(1), BED);
#endif
setTargetTemp_celsius(getMaterial_preset_E(1), getActiveTool());
break;
// Preheat PETG
case 'G':
#if HAS_HEATED_BED
setTargetTemp_celsius(getMaterial_preset_B(2), BED);
#endif
setTargetTemp_celsius(getMaterial_preset_E(2), getActiveTool());
break;
}
#else
SEND_TXT("tmppage.M117", "Preheat disabled");
#endif
break;
}
}
void NextionTFT::UpdateOnChange() {
const millis_t ms = millis();
static millis_t next_event_ms = 0;
static celsius_float_t last_degBed = 999, last_degHotend0 = 999, last_degHotend1 = 999,
last_degTargetBed = 999, last_degTargetHotend0 = 999, last_degTargetHotend1 = 999;
// tmppage Temperature
if (!WITHIN(last_degHotend0 - getActualTemp_celsius(E0), -0.2, 0.2) || !WITHIN(last_degTargetHotend0 - getTargetTemp_celsius(E0), -0.5, 0.5)) {
SEND_TEMP("tmppage.t0", ui8tostr3rj(getActualTemp_celsius(E0)), " / ", ui8tostr3rj(getTargetTemp_celsius(E0)));
last_degHotend0 = getActualTemp_celsius(E0);
last_degTargetHotend0 = getTargetTemp_celsius(E0);
}
if (!WITHIN(last_degHotend1 - getActualTemp_celsius(E1), -0.2, 0.2) || !WITHIN(last_degTargetHotend1 - getTargetTemp_celsius(E1), -0.5, 0.5)) {
SEND_TEMP("tmppage.t1", ui8tostr3rj(getActualTemp_celsius(E1)), " / ", ui8tostr3rj(getTargetTemp_celsius(E1)));
last_degHotend1 = getActualTemp_celsius(E1);
last_degTargetHotend1 = getTargetTemp_celsius(E1);
}
if (!WITHIN(last_degBed - getActualTemp_celsius(BED), -0.2, 0.2) || !WITHIN(last_degTargetBed - getTargetTemp_celsius(BED), -0.5, 0.5)) {
SEND_TEMP("tmppage.t2", ui8tostr3rj(getActualTemp_celsius(BED)), " / ", ui8tostr3rj(getTargetTemp_celsius(BED)));
last_degBed = getActualTemp_celsius(BED);
last_degTargetBed = getTargetTemp_celsius(BED);
}
// tmppage Tool
static uint8_t last_active_extruder = 99;
if (last_active_extruder != getActiveTool()) {
SEND_VALasTXT("tmppage.tool", getActiveTool());
last_active_extruder = getActiveTool();
}
// tmppage Fan Speed
static uint8_t last_fan_speed = 99;
if (last_fan_speed != getActualFan_percent(FAN0)) {
SEND_VALasTXT("tmppage.fan", ui8tostr3rj(getActualFan_percent(FAN0)));
last_fan_speed = getActualFan_percent(FAN0);
}
// tmppage Print Speed
static uint8_t last_print_speed = 99;
if (last_print_speed != getFeedrate_percent()) {
SEND_VALasTXT("tmppage.speed", ui8tostr3rj(getFeedrate_percent()));
last_print_speed = getFeedrate_percent();
}
// tmppage Flow
static uint8_t last_flow_speed = 99;
if (last_flow_speed != getFlow_percent(getActiveTool())) {
SEND_VALasTXT("tmppage.flow", getFlow_percent(getActiveTool()));
last_flow_speed = getFlow_percent(getActiveTool());
}
// tmppage Axis
static float last_get_axis_position_mmX = 999, last_get_axis_position_mmY = 999, last_get_axis_position_mmZ = 999;
// tmppage Progress + Layer + Time
if (isPrinting()) {
if (ELAPSED(ms, next_event_ms)) {
next_event_ms = ms + 1000;
#if ENABLED(SHOW_REMAINING_TIME)
const uint32_t remaining = getProgress_seconds_remaining();
char remaining_str[10];
_format_time(remaining_str, remaining);
SEND_VALasTXT("tmppage.remaining", remaining_str);
#endif
const uint32_t elapsed = getProgress_seconds_elapsed();
char elapsed_str[10];
_format_time(elapsed_str, elapsed);
SEND_VALasTXT("tmppage.elapsed", elapsed_str);
}
static uint8_t last_progress = 99;
if (last_progress != getProgress_percent()) {
SEND_VALasTXT("tmppage.progress", ui8tostr3rj(getProgress_percent()));
last_progress = getProgress_percent();
}
if (last_get_axis_position_mmZ < getAxisPosition_mm(Z)) {
layer++;
SEND_VALasTXT("tmppage.layer", layer);
}
if (last_get_axis_position_mmZ > getAxisPosition_mm(Z)) {
layer--;
SEND_VALasTXT("tmppage.layer", layer);
}
}
if (!WITHIN(last_get_axis_position_mmX - getAxisPosition_mm(X), -0.1, 0.1)) {
if (ELAPSED(ms, next_event_ms)) {
next_event_ms = ms + 30;
SEND_VALasTXT("tmppage.x", getAxisPosition_mm(X));
last_get_axis_position_mmX = getAxisPosition_mm(X);
}
}
if (!WITHIN(last_get_axis_position_mmY - getAxisPosition_mm(Y), -0.1, 0.1)) {
if (ELAPSED(ms, next_event_ms)) {
next_event_ms = ms + 30;
SEND_VALasTXT("tmppage.y", getAxisPosition_mm(Y));
last_get_axis_position_mmY = getAxisPosition_mm(Y);
}
}
if (!WITHIN(last_get_axis_position_mmZ - getAxisPosition_mm(Z), -0.1, 0.1)) {
SEND_VALasTXT("tmppage.z", getAxisPosition_mm(Z));
last_get_axis_position_mmZ = getAxisPosition_mm(Z);
}
// tmppage homed
static bool last_homed = false, last_homedX = false, last_homedY = false, last_homedZ = false;
if (last_homed != isPositionKnown()) {
SEND_VAL("tmppage.homed", isPositionKnown());
last_homed = isPositionKnown();
}
if (last_homedX != isAxisPositionKnown(X)) {
SEND_VAL("tmppage.homedx", isAxisPositionKnown(X));
last_homedX = isAxisPositionKnown(X);
}
if (last_homedY != isAxisPositionKnown(Y)) {
SEND_VAL("tmppage.homedy", isAxisPositionKnown(Y));
last_homedY = isAxisPositionKnown(Y);
}
if (last_homedZ != isAxisPositionKnown(Z)) {
SEND_VAL("tmppage.homedz", isAxisPositionKnown(Z));
last_homedZ = isAxisPositionKnown(Z);
}
#if ENABLED(DUAL_X_CARRIAGE)
// tmppage IDEX Mode
static uint8_t last_IDEX_Mode = 99;
if (last_IDEX_Mode != getIDEX_Mode()) {
SEND_VAL("tmppage.idexmode", getIDEX_Mode());
last_IDEX_Mode = getIDEX_Mode();
}
#endif
}
#endif // NEXTION_TFT