Merge pull request #122 from PavelSindler/MK2

Multimaterial stop print extended, selftest fixed, XYZ cal. improved, unload filament reverted
This commit is contained in:
XPila 2017-06-22 11:49:05 +02:00 committed by GitHub
commit 01d21c3e14
26 changed files with 8873 additions and 7994 deletions

View File

@ -5,11 +5,10 @@
#include "Configuration_prusa.h" #include "Configuration_prusa.h"
// Firmware version // Firmware version
#define FW_version "3.0.12-RC1" #define FW_version "3.0.12-RC2"
#define FW_PRUSA3D_MAGIC "PRUSA3DFW" #define FW_PRUSA3D_MAGIC "PRUSA3DFW"
#define FW_PRUSA3D_MAGIC_LEN 10 #define FW_PRUSA3D_MAGIC_LEN 10
// The total size of the EEPROM is // The total size of the EEPROM is
// 4096 for the Atmega2560 // 4096 for the Atmega2560
#define EEPROM_TOP 4096 #define EEPROM_TOP 4096

View File

@ -299,6 +299,7 @@ extern unsigned int heating_status_counter;
extern bool custom_message; extern bool custom_message;
extern unsigned int custom_message_type; extern unsigned int custom_message_type;
extern unsigned int custom_message_state; extern unsigned int custom_message_state;
extern char snmm_filaments_used;
extern unsigned long PingTime; extern unsigned long PingTime;
@ -323,6 +324,9 @@ extern unsigned long start_pause_print;
extern bool mesh_bed_leveling_flag; extern bool mesh_bed_leveling_flag;
extern bool mesh_bed_run_from_menu; extern bool mesh_bed_run_from_menu;
extern float distance_from_min[3];
extern float angleDiff;
extern void calculate_volumetric_multipliers(); extern void calculate_volumetric_multipliers();
// Similar to the default Arduino delay function, // Similar to the default Arduino delay function,

View File

@ -285,6 +285,10 @@ bool custom_message;
bool loading_flag = false; bool loading_flag = false;
unsigned int custom_message_type; unsigned int custom_message_type;
unsigned int custom_message_state; unsigned int custom_message_state;
char snmm_filaments_used = 0;
float distance_from_min[3];
float angleDiff;
bool volumetric_enabled = false; bool volumetric_enabled = false;
float filament_size[EXTRUDERS] = { DEFAULT_NOMINAL_FILAMENT_DIA float filament_size[EXTRUDERS] = { DEFAULT_NOMINAL_FILAMENT_DIA
@ -2300,11 +2304,10 @@ void process_commands()
} }
break; break;
case 4: // G4 dwell case 4: // G4 dwell
LCD_MESSAGERPGM(MSG_DWELL);
codenum = 0; codenum = 0;
if(code_seen('P')) codenum = code_value(); // milliseconds to wait if(code_seen('P')) codenum = code_value(); // milliseconds to wait
if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
if(codenum != 0) LCD_MESSAGERPGM(MSG_DWELL);
st_synchronize(); st_synchronize();
codenum += millis(); // keep track of when we started waiting codenum += millis(); // keep track of when we started waiting
previous_millis_cmd = millis(); previous_millis_cmd = millis();
@ -3655,14 +3658,15 @@ void process_commands()
calibration_status_store(CALIBRATION_STATUS_ASSEMBLED); calibration_status_store(CALIBRATION_STATUS_ASSEMBLED);
eeprom_update_word((uint16_t*)EEPROM_BABYSTEP_Z, 0); eeprom_update_word((uint16_t*)EEPROM_BABYSTEP_Z, 0);
// Complete XYZ calibration. // Complete XYZ calibration.
BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level); uint8_t point_too_far_mask = 0;
uint8_t point_too_far_mask = 0; BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level, point_too_far_mask);
clean_up_after_endstop_move(); clean_up_after_endstop_move();
// Print head up. // Print head up.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder); plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
st_synchronize(); st_synchronize();
if (result >= 0) { if (result >= 0) {
point_too_far_mask = 0;
// Second half: The fine adjustment. // Second half: The fine adjustment.
// Let the planner use the uncorrected coordinates. // Let the planner use the uncorrected coordinates.
mbl.reset(); mbl.reset();
@ -4301,6 +4305,7 @@ Sigma_Exit:
#endif #endif
} }
} }
snmm_filaments_used = 0;
break; break;
case 85: // M85 case 85: // M85
if(code_seen('S')) { if(code_seen('S')) {
@ -4451,7 +4456,7 @@ Sigma_Exit:
tmp_extruder = active_extruder; tmp_extruder = active_extruder;
if(code_seen('T')) { if(code_seen('T')) {
tmp_extruder = code_value(); tmp_extruder = code_value();
if(tmp_extruder >= EXTRUDERS) { if(tmp_extruder >= EXTRUDERS) {
SERIAL_ECHO_START; SERIAL_ECHO_START;
SERIAL_ECHO(MSG_M200_INVALID_EXTRUDER); SERIAL_ECHO(MSG_M200_INVALID_EXTRUDER);
break; break;
@ -5441,13 +5446,19 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
case 702: case 702:
{ {
#ifdef SNMM #ifdef SNMM
extr_unload_all(); if (code_seen('U')) {
extr_unload_used(); //unload all filaments which were used in current print
}
else if (code_seen('C')) {
extr_unload(); //unload just current filament
}
else {
extr_unload_all(); //unload all filaments
}
#else #else
custom_message = true; custom_message = true;
custom_message_type = 2; custom_message_type = 2;
lcd_setstatuspgm(MSG_UNLOADING_FILAMENT); lcd_setstatuspgm(MSG_UNLOADING_FILAMENT);
current_position[E_AXIS] += 3;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400 / 60, active_extruder);
current_position[E_AXIS] -= 80; current_position[E_AXIS] -= 80;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 7000 / 60, active_extruder); plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 7000 / 60, active_extruder);
st_synchronize(); st_synchronize();
@ -5474,11 +5485,17 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
int index; int index;
for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++); for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++);
if (*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '9') { if ((*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '9') && *(strchr_pointer + index) != '?') {
SERIAL_ECHOLNPGM("Invalid T code."); SERIAL_ECHOLNPGM("Invalid T code.");
} }
else { else {
tmp_extruder = code_value(); if (*(strchr_pointer + index) == '?') {
tmp_extruder = choose_extruder_menu();
}
else {
tmp_extruder = code_value();
}
snmm_filaments_used |= (1 << tmp_extruder); //for stop print
#ifdef SNMM #ifdef SNMM
snmm_extruder = tmp_extruder; snmm_extruder = tmp_extruder;

View File

@ -25,6 +25,21 @@ const char * const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_ADJUSTZ_DE MSG_ADJUSTZ_DE
}; };
const char MSG_ALL_EN[] PROGMEM = "All";
const char MSG_ALL_CZ[] PROGMEM = "Vse";
const char MSG_ALL_IT[] PROGMEM = "Tutti";
const char MSG_ALL_ES[] PROGMEM = "Todos";
const char MSG_ALL_PL[] PROGMEM = "Wszystko";
const char MSG_ALL_DE[] PROGMEM = "Alle";
const char * const MSG_ALL_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_ALL_EN,
MSG_ALL_CZ,
MSG_ALL_IT,
MSG_ALL_ES,
MSG_ALL_PL,
MSG_ALL_DE
};
const char MSG_AMAX_EN[] PROGMEM = "Amax "; const char MSG_AMAX_EN[] PROGMEM = "Amax ";
const char * const MSG_AMAX_LANG_TABLE[1] PROGMEM = { const char * const MSG_AMAX_LANG_TABLE[1] PROGMEM = {
MSG_AMAX_EN MSG_AMAX_EN
@ -590,6 +605,21 @@ const char * const MSG_CHANGING_FILAMENT_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_CHANGING_FILAMENT_DE MSG_CHANGING_FILAMENT_DE
}; };
const char MSG_CHOOSE_EXTRUDER_EN[] PROGMEM = "Choose extruder:";
const char MSG_CHOOSE_EXTRUDER_CZ[] PROGMEM = "Vyberte extruder:";
const char MSG_CHOOSE_EXTRUDER_IT[] PROGMEM = "Seleziona estrusore:";
const char MSG_CHOOSE_EXTRUDER_ES[] PROGMEM = "Elegir extrusor:";
const char MSG_CHOOSE_EXTRUDER_PL[] PROGMEM = "Wybierz ekstruder";
const char MSG_CHOOSE_EXTRUDER_DE[] PROGMEM = "Waehlen Sie Extruder";
const char * const MSG_CHOOSE_EXTRUDER_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_CHOOSE_EXTRUDER_EN,
MSG_CHOOSE_EXTRUDER_CZ,
MSG_CHOOSE_EXTRUDER_IT,
MSG_CHOOSE_EXTRUDER_ES,
MSG_CHOOSE_EXTRUDER_PL,
MSG_CHOOSE_EXTRUDER_DE
};
const char MSG_CLEAN_NOZZLE_E_EN[] PROGMEM = "E calibration finished. Please clean the nozzle. Click when done."; const char MSG_CLEAN_NOZZLE_E_EN[] PROGMEM = "E calibration finished. Please clean the nozzle. Click when done.";
const char MSG_CLEAN_NOZZLE_E_CZ[] PROGMEM = "E kalibrace ukoncena. Prosim ocistete trysku. Po te potvrdte tlacitkem."; const char MSG_CLEAN_NOZZLE_E_CZ[] PROGMEM = "E kalibrace ukoncena. Prosim ocistete trysku. Po te potvrdte tlacitkem.";
const char MSG_CLEAN_NOZZLE_E_IT[] PROGMEM = "Calibrazione E terminata. Si prega di pulire l'ugello. Click per continuare."; const char MSG_CLEAN_NOZZLE_E_IT[] PROGMEM = "Calibrazione E terminata. Si prega di pulire l'ugello. Click per continuare.";
@ -700,6 +730,21 @@ const char * const MSG_COUNT_X_LANG_TABLE[1] PROGMEM = {
MSG_COUNT_X_EN MSG_COUNT_X_EN
}; };
const char MSG_CURRENT_EN[] PROGMEM = "Current";
const char MSG_CURRENT_CZ[] PROGMEM = "Pouze aktualni";
const char MSG_CURRENT_IT[] PROGMEM = "Attuale";
const char MSG_CURRENT_ES[] PROGMEM = "Actual";
const char MSG_CURRENT_PL[] PROGMEM = "Tylko aktualne";
const char MSG_CURRENT_DE[] PROGMEM = "Aktuelles";
const char * const MSG_CURRENT_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_CURRENT_EN,
MSG_CURRENT_CZ,
MSG_CURRENT_IT,
MSG_CURRENT_ES,
MSG_CURRENT_PL,
MSG_CURRENT_DE
};
const char MSG_DISABLE_STEPPERS_EN[] PROGMEM = "Disable steppers"; const char MSG_DISABLE_STEPPERS_EN[] PROGMEM = "Disable steppers";
const char MSG_DISABLE_STEPPERS_CZ[] PROGMEM = "Vypnout motory"; const char MSG_DISABLE_STEPPERS_CZ[] PROGMEM = "Vypnout motory";
const char MSG_DISABLE_STEPPERS_IT[] PROGMEM = "Disabilit motori"; const char MSG_DISABLE_STEPPERS_IT[] PROGMEM = "Disabilit motori";
@ -812,6 +857,71 @@ const char * const MSG_EXTERNAL_RESET_LANG_TABLE[1] PROGMEM = {
MSG_EXTERNAL_RESET_EN MSG_EXTERNAL_RESET_EN
}; };
const char MSG_EXTRUDER_EN[] PROGMEM = "Extruder";
const char MSG_EXTRUDER_IT[] PROGMEM = "Estrusore";
const char MSG_EXTRUDER_ES[] PROGMEM = "Extrusor";
const char MSG_EXTRUDER_PL[] PROGMEM = "Ekstruder";
const char * const MSG_EXTRUDER_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_EXTRUDER_EN,
MSG_EXTRUDER_EN,
MSG_EXTRUDER_IT,
MSG_EXTRUDER_ES,
MSG_EXTRUDER_PL,
MSG_EXTRUDER_EN
};
const char MSG_EXTRUDER_1_EN[] PROGMEM = "Extruder 1";
const char MSG_EXTRUDER_1_IT[] PROGMEM = "Estrusore 1";
const char MSG_EXTRUDER_1_ES[] PROGMEM = "Extrusor 1";
const char MSG_EXTRUDER_1_PL[] PROGMEM = "Ekstruder 1";
const char * const MSG_EXTRUDER_1_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_EXTRUDER_1_EN,
MSG_EXTRUDER_1_EN,
MSG_EXTRUDER_1_IT,
MSG_EXTRUDER_1_ES,
MSG_EXTRUDER_1_PL,
MSG_EXTRUDER_1_EN
};
const char MSG_EXTRUDER_2_EN[] PROGMEM = "Extruder 2";
const char MSG_EXTRUDER_2_IT[] PROGMEM = "Estrusore 2";
const char MSG_EXTRUDER_2_ES[] PROGMEM = "Extrusor 2";
const char MSG_EXTRUDER_2_PL[] PROGMEM = "Ekstruder 2";
const char * const MSG_EXTRUDER_2_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_EXTRUDER_2_EN,
MSG_EXTRUDER_2_EN,
MSG_EXTRUDER_2_IT,
MSG_EXTRUDER_2_ES,
MSG_EXTRUDER_2_PL,
MSG_EXTRUDER_2_EN
};
const char MSG_EXTRUDER_3_EN[] PROGMEM = "Extruder 3";
const char MSG_EXTRUDER_3_IT[] PROGMEM = "Estrusore 3";
const char MSG_EXTRUDER_3_ES[] PROGMEM = "Extrusor 3";
const char MSG_EXTRUDER_3_PL[] PROGMEM = "Ekstruder 3";
const char * const MSG_EXTRUDER_3_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_EXTRUDER_3_EN,
MSG_EXTRUDER_3_EN,
MSG_EXTRUDER_3_IT,
MSG_EXTRUDER_3_ES,
MSG_EXTRUDER_3_PL,
MSG_EXTRUDER_3_EN
};
const char MSG_EXTRUDER_4_EN[] PROGMEM = "Extruder 4";
const char MSG_EXTRUDER_4_IT[] PROGMEM = "Estrusore 4";
const char MSG_EXTRUDER_4_ES[] PROGMEM = "Extrusor 4";
const char MSG_EXTRUDER_4_PL[] PROGMEM = "Ekstruder 4";
const char * const MSG_EXTRUDER_4_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_EXTRUDER_4_EN,
MSG_EXTRUDER_4_EN,
MSG_EXTRUDER_4_IT,
MSG_EXTRUDER_4_ES,
MSG_EXTRUDER_4_PL,
MSG_EXTRUDER_4_EN
};
const char MSG_E_CAL_KNOB_EN[] PROGMEM = "Rotate knob until mark reaches extruder body. Click when done."; const char MSG_E_CAL_KNOB_EN[] PROGMEM = "Rotate knob until mark reaches extruder body. Click when done.";
const char MSG_E_CAL_KNOB_CZ[] PROGMEM = "Otacejte tlacitkem dokud znacka nedosahne tela extruderu. Potvrdte tlacitkem."; const char MSG_E_CAL_KNOB_CZ[] PROGMEM = "Otacejte tlacitkem dokud znacka nedosahne tela extruderu. Potvrdte tlacitkem.";
const char MSG_E_CAL_KNOB_IT[] PROGMEM = "Girare la manopola affinche' il segno raggiunga il corpo dell'estrusore. Click per continuare."; const char MSG_E_CAL_KNOB_IT[] PROGMEM = "Girare la manopola affinche' il segno raggiunga il corpo dell'estrusore. Click per continuare.";
@ -3154,6 +3264,21 @@ const char * const MSG_USB_PRINTING_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_USB_PRINTING_DE MSG_USB_PRINTING_DE
}; };
const char MSG_USED_EN[] PROGMEM = "Used during print";
const char MSG_USED_CZ[] PROGMEM = "Pouzite behem tisku";
const char MSG_USED_IT[] PROGMEM = "Usati nella stampa";
const char MSG_USED_ES[] PROGMEM = "Usado en impresion";
const char MSG_USED_PL[] PROGMEM = "Uzyte przy druku";
const char MSG_USED_DE[] PROGMEM = "Beim Druck benutzte";
const char * const MSG_USED_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_USED_EN,
MSG_USED_CZ,
MSG_USED_IT,
MSG_USED_ES,
MSG_USED_PL,
MSG_USED_DE
};
const char MSG_USERWAIT_EN[] PROGMEM = "Wait for user..."; const char MSG_USERWAIT_EN[] PROGMEM = "Wait for user...";
const char MSG_USERWAIT_IT[] PROGMEM = "Attendendo utente"; const char MSG_USERWAIT_IT[] PROGMEM = "Attendendo utente";
const char MSG_USERWAIT_ES[] PROGMEM = "Esperando ordenes"; const char MSG_USERWAIT_ES[] PROGMEM = "Esperando ordenes";

View File

@ -30,6 +30,8 @@ extern const char* const MSG_ACTIVE_EXTRUDER_LANG_TABLE[1];
#define MSG_ACTIVE_EXTRUDER LANG_TABLE_SELECT_EXPLICIT(MSG_ACTIVE_EXTRUDER_LANG_TABLE, 0) #define MSG_ACTIVE_EXTRUDER LANG_TABLE_SELECT_EXPLICIT(MSG_ACTIVE_EXTRUDER_LANG_TABLE, 0)
extern const char* const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM]; extern const char* const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM];
#define MSG_ADJUSTZ LANG_TABLE_SELECT(MSG_ADJUSTZ_LANG_TABLE) #define MSG_ADJUSTZ LANG_TABLE_SELECT(MSG_ADJUSTZ_LANG_TABLE)
extern const char* const MSG_ALL_LANG_TABLE[LANG_NUM];
#define MSG_ALL LANG_TABLE_SELECT(MSG_ALL_LANG_TABLE)
extern const char* const MSG_AMAX_LANG_TABLE[1]; extern const char* const MSG_AMAX_LANG_TABLE[1];
#define MSG_AMAX LANG_TABLE_SELECT_EXPLICIT(MSG_AMAX_LANG_TABLE, 0) #define MSG_AMAX LANG_TABLE_SELECT_EXPLICIT(MSG_AMAX_LANG_TABLE, 0)
extern const char* const MSG_AUTHOR_LANG_TABLE[1]; extern const char* const MSG_AUTHOR_LANG_TABLE[1];
@ -120,6 +122,8 @@ extern const char* const MSG_CHANGE_SUCCESS_LANG_TABLE[LANG_NUM];
#define MSG_CHANGE_SUCCESS LANG_TABLE_SELECT(MSG_CHANGE_SUCCESS_LANG_TABLE) #define MSG_CHANGE_SUCCESS LANG_TABLE_SELECT(MSG_CHANGE_SUCCESS_LANG_TABLE)
extern const char* const MSG_CHANGING_FILAMENT_LANG_TABLE[LANG_NUM]; extern const char* const MSG_CHANGING_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_CHANGING_FILAMENT LANG_TABLE_SELECT(MSG_CHANGING_FILAMENT_LANG_TABLE) #define MSG_CHANGING_FILAMENT LANG_TABLE_SELECT(MSG_CHANGING_FILAMENT_LANG_TABLE)
extern const char* const MSG_CHOOSE_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_CHOOSE_EXTRUDER LANG_TABLE_SELECT(MSG_CHOOSE_EXTRUDER_LANG_TABLE)
extern const char* const MSG_CLEAN_NOZZLE_E_LANG_TABLE[LANG_NUM]; extern const char* const MSG_CLEAN_NOZZLE_E_LANG_TABLE[LANG_NUM];
#define MSG_CLEAN_NOZZLE_E LANG_TABLE_SELECT(MSG_CLEAN_NOZZLE_E_LANG_TABLE) #define MSG_CLEAN_NOZZLE_E LANG_TABLE_SELECT(MSG_CLEAN_NOZZLE_E_LANG_TABLE)
extern const char* const MSG_CNG_SDCARD_LANG_TABLE[1]; extern const char* const MSG_CNG_SDCARD_LANG_TABLE[1];
@ -140,6 +144,8 @@ extern const char* const MSG_CORRECTLY_LANG_TABLE[LANG_NUM];
#define MSG_CORRECTLY LANG_TABLE_SELECT(MSG_CORRECTLY_LANG_TABLE) #define MSG_CORRECTLY LANG_TABLE_SELECT(MSG_CORRECTLY_LANG_TABLE)
extern const char* const MSG_COUNT_X_LANG_TABLE[1]; extern const char* const MSG_COUNT_X_LANG_TABLE[1];
#define MSG_COUNT_X LANG_TABLE_SELECT_EXPLICIT(MSG_COUNT_X_LANG_TABLE, 0) #define MSG_COUNT_X LANG_TABLE_SELECT_EXPLICIT(MSG_COUNT_X_LANG_TABLE, 0)
extern const char* const MSG_CURRENT_LANG_TABLE[LANG_NUM];
#define MSG_CURRENT LANG_TABLE_SELECT(MSG_CURRENT_LANG_TABLE)
extern const char* const MSG_DISABLE_STEPPERS_LANG_TABLE[LANG_NUM]; extern const char* const MSG_DISABLE_STEPPERS_LANG_TABLE[LANG_NUM];
#define MSG_DISABLE_STEPPERS LANG_TABLE_SELECT(MSG_DISABLE_STEPPERS_LANG_TABLE) #define MSG_DISABLE_STEPPERS LANG_TABLE_SELECT(MSG_DISABLE_STEPPERS_LANG_TABLE)
extern const char* const MSG_DWELL_LANG_TABLE[LANG_NUM]; extern const char* const MSG_DWELL_LANG_TABLE[LANG_NUM];
@ -174,6 +180,16 @@ extern const char* const MSG_ERR_STOPPED_LANG_TABLE[1];
#define MSG_ERR_STOPPED LANG_TABLE_SELECT_EXPLICIT(MSG_ERR_STOPPED_LANG_TABLE, 0) #define MSG_ERR_STOPPED LANG_TABLE_SELECT_EXPLICIT(MSG_ERR_STOPPED_LANG_TABLE, 0)
extern const char* const MSG_EXTERNAL_RESET_LANG_TABLE[1]; extern const char* const MSG_EXTERNAL_RESET_LANG_TABLE[1];
#define MSG_EXTERNAL_RESET LANG_TABLE_SELECT_EXPLICIT(MSG_EXTERNAL_RESET_LANG_TABLE, 0) #define MSG_EXTERNAL_RESET LANG_TABLE_SELECT_EXPLICIT(MSG_EXTERNAL_RESET_LANG_TABLE, 0)
extern const char* const MSG_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDER LANG_TABLE_SELECT(MSG_EXTRUDER_LANG_TABLE)
extern const char* const MSG_EXTRUDER_1_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDER_1 LANG_TABLE_SELECT(MSG_EXTRUDER_1_LANG_TABLE)
extern const char* const MSG_EXTRUDER_2_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDER_2 LANG_TABLE_SELECT(MSG_EXTRUDER_2_LANG_TABLE)
extern const char* const MSG_EXTRUDER_3_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDER_3 LANG_TABLE_SELECT(MSG_EXTRUDER_3_LANG_TABLE)
extern const char* const MSG_EXTRUDER_4_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDER_4 LANG_TABLE_SELECT(MSG_EXTRUDER_4_LANG_TABLE)
extern const char* const MSG_E_CAL_KNOB_LANG_TABLE[LANG_NUM]; extern const char* const MSG_E_CAL_KNOB_LANG_TABLE[LANG_NUM];
#define MSG_E_CAL_KNOB LANG_TABLE_SELECT(MSG_E_CAL_KNOB_LANG_TABLE) #define MSG_E_CAL_KNOB LANG_TABLE_SELECT(MSG_E_CAL_KNOB_LANG_TABLE)
extern const char* const MSG_Enqueing_LANG_TABLE[1]; extern const char* const MSG_Enqueing_LANG_TABLE[1];
@ -582,6 +598,8 @@ extern const char* const MSG_UNLOAD_FILAMENT_4_LANG_TABLE[LANG_NUM];
#define MSG_UNLOAD_FILAMENT_4 LANG_TABLE_SELECT(MSG_UNLOAD_FILAMENT_4_LANG_TABLE) #define MSG_UNLOAD_FILAMENT_4 LANG_TABLE_SELECT(MSG_UNLOAD_FILAMENT_4_LANG_TABLE)
extern const char* const MSG_USB_PRINTING_LANG_TABLE[LANG_NUM]; extern const char* const MSG_USB_PRINTING_LANG_TABLE[LANG_NUM];
#define MSG_USB_PRINTING LANG_TABLE_SELECT(MSG_USB_PRINTING_LANG_TABLE) #define MSG_USB_PRINTING LANG_TABLE_SELECT(MSG_USB_PRINTING_LANG_TABLE)
extern const char* const MSG_USED_LANG_TABLE[LANG_NUM];
#define MSG_USED LANG_TABLE_SELECT(MSG_USED_LANG_TABLE)
extern const char* const MSG_USERWAIT_LANG_TABLE[LANG_NUM]; extern const char* const MSG_USERWAIT_LANG_TABLE[LANG_NUM];
#define MSG_USERWAIT LANG_TABLE_SELECT(MSG_USERWAIT_LANG_TABLE) #define MSG_USERWAIT LANG_TABLE_SELECT(MSG_USERWAIT_LANG_TABLE)
extern const char* const MSG_VMIN_LANG_TABLE[1]; extern const char* const MSG_VMIN_LANG_TABLE[1];

View File

@ -293,3 +293,12 @@
#define MSG_TEMP_CALIBRATION_ON "Tepl. kal. [ON]" #define MSG_TEMP_CALIBRATION_ON "Tepl. kal. [ON]"
#define MSG_TEMP_CALIBRATION_OFF "Tepl. kal. [OFF]" #define MSG_TEMP_CALIBRATION_OFF "Tepl. kal. [OFF]"
#define MSG_PREPARE_FILAMENT "Pripravte filament" #define MSG_PREPARE_FILAMENT "Pripravte filament"
#define MSG_ALL "Vse"
#define MSG_USED "Pouzite behem tisku"
#define MSG_CURRENT "Pouze aktualni"
#define MSG_CHOOSE_EXTRUDER "Vyberte extruder:"
#define MSG_EXTRUDER "Extruder"
#define MSG_EXTRUDER_1 "Extruder 1"
#define MSG_EXTRUDER_2 "Extruder 2"
#define MSG_EXTRUDER_3 "Extruder 3"
#define MSG_EXTRUDER_4 "Extruder 4"

317
Firmware/language_de.h Normal file
View File

@ -0,0 +1,317 @@
+/**
+ * German
+ *
+ * LCD Menu Messages
+ * Please note these are limited to 17 characters!
+ *
+ */
+
+#define(length = 20) WELCOME_MSG CUSTOM_MENDEL_NAME " bereit."
+ #define MSG_SD_INSERTED "SD eingesetzt"
+ #define MSG_SD_REMOVED "SD entfernt "
+ #define MSG_MAIN "Hauptmenue"
+ #define MSG_DISABLE_STEPPERS "Motoren aus"
+ #define MSG_AUTO_HOME "Startposition"
+ #define MSG_SET_HOME_OFFSETS "Abstand vom Ursprung einstellen"
+ #define MSG_SET_ORIGIN "Ursprung einstellen"
+ #define MSG_COOLDOWN "Abkuehlen"
+ #define MSG_SWITCH_PS_ON "Netzteil EIN"
+ #define MSG_SWITCH_PS_OFF "Netzteil AUS"
+ #define MSG_MOVE_AXIS "Achsbewegung"
+ #define MSG_MOVE_X "Bewege X"
+ #define MSG_MOVE_Y "Bewege Y"
+ #define MSG_MOVE_Z "Bewege Z"
+ #define MSG_MOVE_E "Extruder"
+ #define MSG_SPEED "Geschwindigkeit"
+ #define MSG_NOZZLE "Duese"
+ #define MSG_NOZZLE1 "Duese2"
+ #define MSG_NOZZLE2 "Duese3"
+ #define MSG_BED "Bed"
+ #define MSG_FAN_SPEED "Luefter-Tempo"
+ #define MSG_FLOW "Durchfluss"
+ #define MSG_FLOW0 "Durchfluss 0"
+ #define MSG_FLOW1 "Durchfluss 1"
+ #define MSG_FLOW2 "Durchfluss 2"
+ #define MSG_CONTROL "Kontrolle"
+ #define MSG_MIN " \002 Min"
+ #define MSG_MAX " \002 Max"
+ #define MSG_FACTOR " \002 Fakt"
+ #define MSG_TEMPERATURE "Temperatur"
+ #define MSG_MOTION "Bewegung"
+ #define MSG_VOLUMETRIC "Filament"
+ #define MSG_VOLUMETRIC_ENABLED "E in mm3"
+ #define MSG_STORE_EPROM "Abspeichern"
+ #define MSG_LOAD_EPROM "Lade Speicher"
+ #define MSG_RESTORE_FAILSAFE "Standardwerte setzen"
+ #define MSG_REFRESH "\xF8" "Erneuern"
+ #define MSG_WATCH "Information"
+ #define MSG_TUNE "Feineinstellung"
+ #define MSG_PAUSE_PRINT "Druck unterbrech."
+ #define MSG_RESUME_PRINT "Fortsetzen"
+ #define MSG_STOP_PRINT "Druck abbrechen"
+ #define MSG_CARD_MENU "Drucken von SD"
+ #define MSG_NO_CARD "Keine SD Karte"
+ #define MSG_DWELL "Einen Moment bitte."
+ #define MSG_USERWAIT "Warte auf user..."
+ #define MSG_RESUMING "Druck fortgesetzt"
+ #define(length = 20) MSG_PRINT_ABORTED "Druck abgebrochen"
+ #define MSG_NO_MOVE "Keine Bewegung."
+ #define MSG_KILLED "ABGEBROCHEN. "
+ #define MSG_STOPPED "GESTOPPT. "
+ #define MSG_FILAMENTCHANGE "Filament-Wechsel"
+ #define MSG_INIT_SDCARD "Init SD Karte"
+ #define MSG_CNG_SDCARD "Wechsel SD Karte"
+ #define MSG_BABYSTEP_X "Babystep X"
+ #define MSG_BABYSTEP_Y "Babystep Y"
+ #define MSG_BABYSTEP_Z "Z einstellen"
+ #define MSG_ADJUSTZ "Auto Z einstellen?"
+ #define MSG_PICK_Z "Waehle Abdruck"
+
+#define MSG_SETTINGS "Einstellungen"
+ #define MSG_PREHEAT "Vorwaermen"
+ #define MSG_UNLOAD_FILAMENT "Filament entladen"
+ #define MSG_LOAD_FILAMENT "Filament laden"
+
+#define MSG_RECTRACT "Retract"
+ #define MSG_ERROR "FEHLER:"
+ #define(length = 20) MSG_PREHEAT_NOZZLE "Duese Vorwaermen"
+ #define MSG_SUPPORT "Support"
+ #define(length = 20) MSG_CORRECTLY "Wechsel ok?"
+ #define MSG_YES "Ja"
+ #define MSG_NO "Nein"
+ #define(length = 19) MSG_NOT_LOADED "Fil. nicht geladen"
+ #define MSG_NOT_COLOR "Farbe unklar"
+ #define(length = 20) MSG_LOADING_FILAMENT "Filament leadt"
+ #define(length = 20) MSG_PLEASE_WAIT "Bitte warten"
+ #define MSG_LOADING_COLOR "Lade Farbe"
+ #define MSG_CHANGE_SUCCESS "Wechsel erfolgr.!"
+ #define(length = 20) MSG_PRESS "und Knopf druecken"
+ #define(length = 20) MSG_INSERT_FILAMENT "Filament einlegen"
+ #define(length = 20) MSG_CHANGING_FILAMENT "Filament-Wechsel!"
+
+
+#define MSG_SILENT_MODE_ON "Mode [leise]"
+ #define MSG_SILENT_MODE_OFF "Mode [Hohe Leist]"
+ #define(length = 20) MSG_REBOOT "Zum Uebernehmen "
+ #define(length = 22) MSG_TAKE_EFFECT "Drucker neu starten"
+
+#define MSG_Enqueing "enqueuing \"
+ #define MSG_POWERUP "Einschalten"
+ #define MSG_CONFIGURATION_VER " Letztes Update:"
+ #define MSG_FREE_MEMORY " Freier Speicher: "
+ #define MSG_PLANNER_BUFFER_BYTES " PlannerBufferBytes: "
+ #define MSG_OK "ok"
+ #define MSG_ERR_CHECKSUM_MISMATCH "Pruefsummenfehler, Letzte Zeile: " //Checksum Fehler, Letzte Zeile: "
+ #define MSG_ERR_NO_CHECKSUM "Keine Pruefsumme mit Zeilennummer, Letzte Zeile: " //Keine Checksum mit Zeilennummer, Letzte Zeile: "
+ #define MSG_BEGIN_FILE_LIST "Beginn Dateiliste"
+ #define MSG_END_FILE_LIST "Ende Dateiliste"
+ #define MSG_M104_INVALID_EXTRUDER "M104 Falscher Extruder"
+ #define MSG_M105_INVALID_EXTRUDER "M105 Falscher Extruder"
+ #define MSG_M200_INVALID_EXTRUDER "M200 Falscher Extruder"
+ #define MSG_M218_INVALID_EXTRUDER "M218 Falscher Extruder"
+ #define MSG_M221_INVALID_EXTRUDER "M221 Falscher Extruder"
+ #define MSG_ERR_NO_THERMISTORS "Keine Thermistoren - keine Temperatur"
+ #define MSG_M109_INVALID_EXTRUDER "M109 Falscher Extruder"
+ #define MSG_HEATING "Aufwaermen"
+ #define(length = 20) MSG_HEATING_COMPLETE "Aufwaermen OK"
+ #define MSG_BED_HEATING "Bed aufwaermen"
+ #define MSG_BED_DONE "Bed OK"
+ #define MSG_M115_REPORT "FIRMWARE_NAME:Marlin V1.0.2; Sprinter/grbl mashup for gen6 FIRMWARE_URL:" FIRMWARE_URL " PROTOCOL_VERSION:" PROTOCOL_VERSION " MACHINE_TYPE:" CUSTOM_MENDEL_NAME " EXTRUDER_COUNT:" STRINGIFY(EXTRUDERS) " UUID:" MACHINE_UUID "\n"
+ #define MSG_ERR_KILLED "Printer gestoppt. kill() aufgerufen!"
+ #define MSG_ERR_STOPPED "Drucker aufgrund von Fehlern gestoppt. Fehler beheben und mit M999 neu starten. (Temperatur wird zurueckgesetzt. Nach dem Neustart neu einstellen!)"
+ #define MSG_RESEND "Wiederholen: "
+ #define MSG_M119_REPORT "Statusbericht Endanschlag"
+ #define MSG_ENDSTOP_HIT "AUSGELOEST"
+ #define MSG_ENDSTOP_OPEN "offen"
+
+#define MSG_SD_CANT_OPEN_SUBDIR "Kann Unterverz. nicht oeffnen"
+ #define MSG_SD_INIT_FAIL "SD Init fehlerhaft"
+ #define MSG_SD_VOL_INIT_FAIL "Dateisystem Init fehlerhaft"
+ #define MSG_SD_OPENROOT_FAIL "Zugriff auf Basisverzeichnis misslungen"
+ #define MSG_SD_CARD_OK "SD Karte ok"
+ #define MSG_SD_WORKDIR_FAIL "Oeffnen Arbeitsverzeichnis misslungen"
+ #define MSG_SD_OPEN_FILE_FAIL "Fehler beim Oeffnen der Datei: "
+ #define MSG_SD_FILE_OPENED "Datei geoeffnet: "
+ #define MSG_SD_FILE_SELECTED "Datei ausgewaehlt"
+ #define MSG_SD_WRITE_TO_FILE "Schreiben der Datei: "
+ #define MSG_SD_PRINTING_BYTE "SD printing byte "
+ #define MSG_SD_NOT_PRINTING "Kein SD Print"
+ #define MSG_SD_ERR_WRITE_TO_FILE "Fehler beim Schreiben in Datei"
+ #define MSG_SD_CANT_ENTER_SUBDIR "Zugangsproblem Unterverzeichnis: "
+ #define MSG_STEPPER_TOO_HIGH "Schrittrate zu hoch"
+ #define MSG_ENDSTOPS_HIT "Endanschlag erreicht"
+ #define MSG_ERR_COLD_EXTRUDE_STOP "Stopp, Extruder kalt!"
+ #define MSG_BABYSTEPPING_X "Babystepping X"
+ #define MSG_BABYSTEPPING_Y "Babystepping Y"
+ #define MSG_BABYSTEPPING_Z "Z wurde eingestellt"
+ #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Menuestruktur fehlerhaft"
+
+#define MSG_LANGUAGE_NAME "Deutsch"
+ #define MSG_LANGUAGE_SELECT "Waehle Sprache"
+ #define MSG_PRUSA3D "prusa3d.com"
+ #define MSG_PRUSA3D_FORUM "forum.prusa3d.com"
+ #define MSG_PRUSA3D_HOWTO "howto.prusa3d.com"
+
+#define MSG_SELFTEST_ERROR "Selbtest Fehler!"
+ #define MSG_SELFTEST_PLEASECHECK "Bitte pruefe:"
+ #define MSG_SELFTEST_NOTCONNECTED "Nicht angeschlossen"
+ #define MSG_SELFTEST_HEATERTHERMISTOR "Heater/Thermistor"
+ #define MSG_SELFTEST_BEDHEATER "Bed / Heater"
+ #define MSG_SELFTEST_WIRINGERROR "Verdrahtungfehler"
+ #define MSG_SELFTEST_ENDSTOPS "Endschalter"
+ #define MSG_SELFTEST_MOTOR "Motor"
+ #define MSG_SELFTEST_ENDSTOP "Endstop"
+ #define MSG_SELFTEST_ENDSTOP_NOTHIT "Ende nicht getrof."
+ #define MSG_SELFTEST_OK "Selbsttest OK"
+ #define MSG_LOOSE_PULLEY "Lose Riemenscheibe"
+
+#define MSG_SELFTEST_FAN "Lueftertest"
+#define(length = 20) MSG_SELFTEST_COOLING_FAN "Vorderer Luefter?"
+#define(length = 20) MSG_SELFTEST_EXTRUDER_FAN "Linker Luefter?"
+#define MSG_SELFTEST_FAN_YES "Dreht"
+#define MSG_SELFTEST_FAN_NO "Dreht nicht"
+
+#define(length = 20) MSG_STATS_TOTALFILAMENT "Gesamtfilament:"
+ #define(length = 20) MSG_STATS_TOTALPRINTTIME "Totale Druckzeit:"
+ #define(length = 20) MSG_STATS_FILAMENTUSED "Filamentverbrauch:"
+ #define(length = 20) MSG_STATS_PRINTTIME "Druckzeit: "
+ #define(length = 20) MSG_SELFTEST_START "Selbsttest start "
+ #define(length = 20) MSG_SELFTEST_CHECK_ENDSTOPS "Pruefe Endschalter "
+ #define(length = 20) MSG_SELFTEST_CHECK_HOTEND "Pruefe Hotend"
+ #define(length = 20) MSG_SELFTEST_CHECK_X "Pruefe X Achse "
+ #define(length = 20) MSG_SELFTEST_CHECK_Y "Pruefe Y Achse "
+ #define(length = 20) MSG_SELFTEST_CHECK_Z "Pruefe Z Achse "
+ #define(length = 20) MSG_SELFTEST_CHECK_BED "Pr\x81fe Bed "
+ #define(length = 20) MSG_SELFTEST_CHECK_ALLCORRECT "Alles richtig "
+ #define MSG_SELFTEST "Selbsttest "
+ #define(length = 20) MSG_SELFTEST_FAILED "Selbsttest misslung."
+ #define MSG_STATISTICS "Statistiken "
+ #define MSG_USB_PRINTING "Drucken ueber USB"
+ #define MSG_HOMEYZ "Kalibrieren Z"
+ #define MSG_HOMEYZ_PROGRESS "Kalibriere Z"
+ #define MSG_HOMEYZ_DONE "Kalibrierung OK"
+
+#define MSG_SHOW_END_STOPS "Endschalter Stat."
+ #define MSG_CALIBRATE_BED "Kalibrierung XYZ"
+ #define MSG_CALIBRATE_BED_RESET "Reset XYZ Kalibr."
+
+#define(length = 20, lines = 8) MSG_MOVE_CARRIAGE_TO_THE_TOP "Kalibrieren von XYZ. Drehen Sie den Knopf bis der obere Anschlag erreicht wird. Klicken wenn ganz oben."
+ #define(length = 20, lines = 8) MSG_MOVE_CARRIAGE_TO_THE_TOP_Z "Kalibrieren von Z. Drehen Sie den Knopf bis der obere Anschlag erreicht wird. Klicken wenn ganz oben."
+
+#define(length = 20, lines = 8) MSG_CONFIRM_NOZZLE_CLEAN "Bitte entfernen Sie ueberstehendes Filament von der Duese. Klicken wenn sauber."
+ #define(length = 20, lines = 2) MSG_CONFIRM_CARRIAGE_AT_THE_TOP "Ist der Schlitten ganz oben?"
+
+#define(length = 60) MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 "Suchen Bed Kalibrierpunkt"
+ #define(length = 14) MSG_FIND_BED_OFFSET_AND_SKEW_LINE2 " von 4"
+ #define(length = 60) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 "Verbesserung Bed Kalibrierpunkt"
+ #define(length = 14) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 " von 9"
+ #define(length = 60) MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1 "Messen der Referenzhoehe des Kalibrierpunktes"
+ #define(length = 14) MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 " von 9"
#define MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION "Iteration "
+
+#define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND "XYZ-Kalibrierung fehlgeschlagen. Bed-Kalibrierpunkt nicht gefunden."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED "XYZ-Kalibrierung fehlgeschlagen. Bitte schauen Sie in das Handbuch."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_PERFECT "XYZ-Kalibrierung ok. X/Y-Achsen sind senkrecht zueinander. Glueckwunsch!"
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD "XYZ Kalibrierung in Ordnung. X/Y Achsen sind etwas schief."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME "XYZ Kalibrierung in Ordnung. Schiefheit wird automatisch korrigiert."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR "XYZ-Kalibrierung fehlgeschlagen. Linker vorderer Kalibrierpunkt ist zu weit vorne."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR "XYZ-Kalibrierung fehlgeschlagen. Rechter vorderer Kalibrierpunkt ist zu weit vorne."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR "XYZ-Kalibrierung fehlgeschlagen. Vordere Kalibrierpunkte sind zu weit vorne."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR "XYZ-Kalibrierung ungenau. Linker vorderer Kalibrierpunkt ist zu weit vorne."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR "XYZ-Kalibrierung ungenau. Rechter vorderer Kalibrierpunkt ist zu weit vorne."
+ #define(length = 20, lines = 8) MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR "XYZ-Kalibrierung ungenau. Vordere Kalibrierpunkte sind zu weit vorne."
+
+#define(length = 20, lines = 4) MSG_BED_LEVELING_FAILED_POINT_LOW "Z-Kal. fehlgeschlg. Sensor nicht ausgeloest. Schmutzige Duese? Warte auf Reset"
+ #define(length = 20, lines = 4) MSG_BED_LEVELING_FAILED_POINT_HIGH "Z-Kalibrierung fehlgeschlg. Sensor zu hoch ausgeloest. Warte auf Reset."
+ #define(length = 20, lines = 4) MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED "Z-Kalibrierung fehlgeschlg. Sensor nicht angeschlossen. Warte auf Reset."
+
+#define(length = 20, lines = 2) MSG_NEW_FIRMWARE_AVAILABLE "Neue Firmware Version verfuegbar:"
+ #define(length = 20) MSG_NEW_FIRMWARE_PLEASE_UPGRADE "Bitte aktualisieren."
+
+ #define(length = 20, lines = 8) MSG_FOLLOW_CALIBRATION_FLOW "Der Drucker wurde noch nicht kalibriert. Bitte folgen Sie dem Handbuch, Kapitel First steps, Abschnitt Calibration flow."
+ #define(length = 20, lines = 12) MSG_BABYSTEP_Z_NOT_SET "Der Abstand zwischen der Spitze der Duese und der Bed ist noch nicht eingestellt. Bitte folgen Sie dem Handbuch, First steps, section First layer calibration."
+
+
+ #define(length = 20, lines = 4) MSG_FILAMENT_LOADING_T0 "Filament in extruder 1 einlegen. Klicken wenn fertig."
+ #define(length = 20, lines = 4) MSG_FILAMENT_LOADING_T1 "Filament in extruder 2 einlegen. Klicken wenn fertig."
+ #define(length = 20, lines = 4) MSG_FILAMENT_LOADING_T2 "Filament in extruder 3 einlegen. Klicken wenn fertig."
+ #define(length = 20, lines = 4) MSG_FILAMENT_LOADING_T3 "Filament in extruder 4 einlegen. Klicken wenn fertig."
+ #define(length = 20, lines = 1) MSG_CHANGE_EXTR "Wechsel extruder"
+
+ #define(length = 20, lines = 4) MSG_FIL_ADJUSTING "Filament positionieren. Bitte warten."
+ #define(length = 20, lines = 8) MSG_CONFIRM_NOZZLE_CLEAN_FIL_ADJ "Filamente sind jetzt eingestellt. Bitte reinigen Sie die Duese zur Kalibrierung. Klicken wenn fertig."
+
+ #define(length = 20, lines = 1) MSG_CALIBRATE_E "Kalibriere E"
+//#define(length=20, lines=1) "Reset E Cal."
+#define(length = 20, lines = 8) MSG_E_CAL_KNOB "Knopf drehen bis die Filamentmarkierung erreicht ist. Klicken wenn fertig."
+
+//#define(length=20, lines=1) MSG_FARM_CARD_MENU "Farm mode print"
+#define(length = 20, lines = 8) MSG_MARK_FIL "Filament 100mm vom Extrudergehaeuse markieren. Klicken wenn Fertig."
+ #define(length = 20, lines = 8) MSG_CLEAN_NOZZLE_E "E-Kalibrierung beendet. Bitte reinigen Sie die Duese. Klicken wenn fertig."
+ #define(length = 20, lines = 3) MSG_WAITING_TEMP "Warten auf Abkuehlung von Heater und Bed."
+ #define(length = 20, lines = 2) MSG_FILAMENT_CLEAN "Ist Farbe rein?"
+ #define(lenght = 20, lines = 1) MSG_UNLOADING_FILAMENT "Filament auswerfen"
+ #define(length = 20, lines = 8) MSG_PAPER "Legen ein Blatt Papier unter die Duese waehrend der Kalibrierung der ersten 4 Punkte. Wenn die Duese das Papier einklemmt, Drucker sofort ausschalten"
+
+#define MSG_BED_CORRECTION_MENU "Bed level Korrekt"
+ #define MSG_BED_CORRECTION_LEFT "Links [um]"
+ #define MSG_BED_CORRECTION_RIGHT "Rechts [um]"
+ #define MSG_BED_CORRECTION_FRONT "Vorne [um]"
+ #define MSG_BED_CORRECTION_REAR "Hinten [um]"
+ #define MSG_BED_CORRECTION_RESET "Ruecksetzen"
+
+#define MSG_MESH_BED_LEVELING "Mesh Bed Leveling"
+ #define MSG_MENU_CALIBRATION "Kalibrierung"
+ #define MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF "SD Karte [normal]"
+ #define MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON "SD Karte [FlashAir]"
#define MSG_FINISHING_MOVEMENTS "Bewegung beenden"
#define MSG_PRINT_PAUSED "Druck pausiert"
#define MSG_RESUMING_PRINT "Druck weitergehen"
#define MSG_PID_EXTRUDER "PID Kalibrierung"
#define MSG_SET_TEMPERATURE "Temp. einsetzen"
#define MSG_PID_FINISHED "PID Kalib. fertig"
#define MSG_PID_RUNNING "PID Kalib."
#define MSG_CALIBRATE_PINDA "Kalibrieren"
#define MSG_CALIBRATION_PINDA_MENU "Temp. kalibrieren"
#define MSG_PINDA_NOT_CALIBRATED "Temperatur wurde nicht kalibriert"
#define MSG_PINDA_PREHEAT "PINDA erwaermen"
#define MSG_TEMP_CALIBRATION "Temp Kalib. "
#define MSG_TEMP_CALIBRATION_DONE "Temp. Kalibrierung fertig. Klicken um weiter zu gehen."
#define MSG_TEMP_CALIBRATION_ON "Temp. Kal. [ON]"
#define MSG_TEMP_CALIBRATION_OFF "Temp. Kal. [OFF]"
#define MSG_LOAD_ALL "Alle laden"
#define MSG_LOAD_FILAMENT_1 "Filament 1 laden"
#define MSG_LOAD_FILAMENT_2 "Filament 2 laden"
#define MSG_LOAD_FILAMENT_3 "Filament 3 laden"
#define MSG_LOAD_FILAMENT_4 "Filament 4 laden"
#define MSG_UNLOAD_FILAMENT_1 "Filam. 1 entladen"
#define MSG_UNLOAD_FILAMENT_2 "Filam. 2 entladen"
#define MSG_UNLOAD_FILAMENT_3 "Filam. 3 entladen"
#define MSG_UNLOAD_FILAMENT_4 "Filam. 4 entladen"
#define MSG_UNLOAD_ALL "Alles entladen"
#define MSG_PREPARE_FILAMENT "Filam. bereithalten"
#define MSG_ALL "Alle"
#define MSG_USED "Beim Druck benutzte"
#define MSG_CURRENT "Aktuelles"
#define MSG_CHOOSE_EXTRUDER "Waehlen Sie Extruder"
#define MSG_EXTRUDER "Extruder"
#define MSG_EXTRUDER_1 "Extruder 1"
#define MSG_EXTRUDER_2 "Extruder 2"
#define MSG_EXTRUDER_3 "Extruder 3"
#define MSG_EXTRUDER_4 "Extruder 4"

View File

@ -273,9 +273,9 @@
#define MSG_MESH_BED_LEVELING "Mesh Bed Leveling" #define MSG_MESH_BED_LEVELING "Mesh Bed Leveling"
#define MSG_MENU_CALIBRATION "Calibration" #define MSG_MENU_CALIBRATION "Calibration"
#define MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF "SD card [normal]" #define(length=19, lines=1) MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF "SD card [normal]"
#define MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON "SD card [FlshAir]" #define(length=19, lines=1) MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON "SD card [FlshAir]"
#define MSG_PRINTER_DISCONNECTED "Printer disconnected" #define(length=20, lines=1) MSG_PRINTER_DISCONNECTED "Printer disconnected"
#define(length=20, lines=1) MSG_FINISHING_MOVEMENTS "Finishing movements" #define(length=20, lines=1) MSG_FINISHING_MOVEMENTS "Finishing movements"
#define(length=20, lines=1) MSG_PRINT_PAUSED "Print paused" #define(length=20, lines=1) MSG_PRINT_PAUSED "Print paused"
#define(length=20, lines=1) MSG_RESUMING_PRINT "Resuming print" #define(length=20, lines=1) MSG_RESUMING_PRINT "Resuming print"
@ -293,5 +293,13 @@
#define(length=20, lines=1) MSG_TEMP_CALIBRATION_ON "Temp. cal. [ON]" #define(length=20, lines=1) MSG_TEMP_CALIBRATION_ON "Temp. cal. [ON]"
#define(length=20, lines=1) MSG_TEMP_CALIBRATION_OFF "Temp. cal. [OFF]" #define(length=20, lines=1) MSG_TEMP_CALIBRATION_OFF "Temp. cal. [OFF]"
#define(length=20, lines=1) MSG_PREPARE_FILAMENT "Prepare new filament" #define(length=20, lines=1) MSG_PREPARE_FILAMENT "Prepare new filament"
#define(length=19, lines=1) MSG_ALL "All"
#define(length=19, lines=1) MSG_USED "Used during print"
#define(length=19, lines=1) MSG_CURRENT "Current"
#define(length=20, lines=1) MSG_CHOOSE_EXTRUDER "Choose extruder:"
#define(length=17, lines=1) MSG_EXTRUDER "Extruder"
#define(length=17, lines=1) MSG_EXTRUDER_1 "Extruder 1"
#define(length=17, lines=1) MSG_EXTRUDER_2 "Extruder 2"
#define(length=17, lines=1) MSG_EXTRUDER_3 "Extruder 3"
#define(length=17, lines=1) MSG_EXTRUDER_4 "Extruder 4"

View File

@ -287,3 +287,12 @@
#define MSG_UNLOAD_FILAMENT_4 "Soltar fil. 4" #define MSG_UNLOAD_FILAMENT_4 "Soltar fil. 4"
#define MSG_UNLOAD_ALL "Soltar todos fil." #define MSG_UNLOAD_ALL "Soltar todos fil."
#define MSG_PREPARE_FILAMENT "Preparar filamento" #define MSG_PREPARE_FILAMENT "Preparar filamento"
#define MSG_ALL "Todos"
#define MSG_USED "Usado en impresion"
#define MSG_CURRENT "Actual"
#define MSG_CHOOSE_EXTRUDER "Elegir extrusor:"
#define MSG_EXTRUDER "Extrusor"
#define MSG_EXTRUDER_1 "Extrusor 1"
#define MSG_EXTRUDER_2 "Extrusor 2"
#define MSG_EXTRUDER_3 "Extrusor 3"
#define MSG_EXTRUDER_4 "Extrusor 4"

View File

@ -278,3 +278,12 @@
#define MSG_UNLOAD_FILAMENT_4 "Rilasciare fil. 1" #define MSG_UNLOAD_FILAMENT_4 "Rilasciare fil. 1"
#define MSG_UNLOAD_ALL "Rilasciare tutti" #define MSG_UNLOAD_ALL "Rilasciare tutti"
#define MSG_PREPARE_FILAMENT "Preparare filamento" #define MSG_PREPARE_FILAMENT "Preparare filamento"
#define MSG_ALL "Tutti"
#define MSG_USED "Usati nella stampa"
#define MSG_CURRENT "Attuale"
#define MSG_CHOOSE_EXTRUDER "Seleziona estrusore:"
#define MSG_EXTRUDER "Estrusore"
#define MSG_EXTRUDER_1 "Estrusore 1"
#define MSG_EXTRUDER_2 "Estrusore 2"
#define MSG_EXTRUDER_3 "Estrusore 3"
#define MSG_EXTRUDER_4 "Estrusore 4"

View File

@ -290,3 +290,12 @@
#define MSG_UNLOAD_FILAMENT_4 "Wyjac filament 4" #define MSG_UNLOAD_FILAMENT_4 "Wyjac filament 4"
#define MSG_UNLOAD_ALL "Wyjac wszystkie" #define MSG_UNLOAD_ALL "Wyjac wszystkie"
#define MSG_PREPARE_FILAMENT "Przygotuj filament" #define MSG_PREPARE_FILAMENT "Przygotuj filament"
#define MSG_ALL "Wszystko"
#define MSG_USED "Uzyte przy druku"
#define MSG_CURRENT "Tylko aktualne"
#define MSG_CHOOSE_EXTRUDER "Wybierz ekstruder"
#define MSG_EXTRUDER "Ekstruder"
#define MSG_EXTRUDER_1 "Ekstruder 1"
#define MSG_EXTRUDER_2 "Ekstruder 2"
#define MSG_EXTRUDER_3 "Ekstruder 3"
#define MSG_EXTRUDER_4 "Ekstruder 4"

View File

@ -29,11 +29,6 @@ float world2machine_shift[2];
#define MACHINE_AXIS_SCALE_X 1.f #define MACHINE_AXIS_SCALE_X 1.f
#define MACHINE_AXIS_SCALE_Y 1.f #define MACHINE_AXIS_SCALE_Y 1.f
// 0.12 degrees equals to an offset of 0.5mm on 250mm length.
#define BED_SKEW_ANGLE_MILD (0.12f * M_PI / 180.f)
// 0.25 degrees equals to an offset of 1.1mm on 250mm length.
#define BED_SKEW_ANGLE_EXTREME (0.25f * M_PI / 180.f)
#define BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN (0.8f) #define BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN (0.8f)
#define BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X (0.8f) #define BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X (0.8f)
#define BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y (1.5f) #define BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y (1.5f)
@ -48,6 +43,11 @@ float world2machine_shift[2];
// by the Least Squares fitting and the X coordinate will be weighted low. // by the Least Squares fitting and the X coordinate will be weighted low.
#define Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH (Y_MIN_POS - 0.5f) #define Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH (Y_MIN_POS - 0.5f)
// 0.12 degrees equals to an offset of 0.5mm on 250mm length.
const float bed_skew_angle_mild = (0.12f * M_PI / 180.f);
// 0.25 degrees equals to an offset of 1.1mm on 250mm length.
const float bed_skew_angle_extreme = (0.25f * M_PI / 180.f);
// Positions of the bed reference points in the machine coordinates, referenced to the P.I.N.D.A sensor. // Positions of the bed reference points in the machine coordinates, referenced to the P.I.N.D.A sensor.
// The points are ordered in a zig-zag fashion to speed up the calibration. // The points are ordered in a zig-zag fashion to speed up the calibration.
const float bed_ref_points[] PROGMEM = { const float bed_ref_points[] PROGMEM = {
@ -75,15 +75,21 @@ const float bed_ref_points_4[] PROGMEM = {
static inline float sqr(float x) { return x * x; } static inline float sqr(float x) { return x * x; }
static inline bool point_on_1st_row(const uint8_t i, const uint8_t npts)
{
if (npts == 4) return (i == 0);
else return (i < 3);
}
// Weight of a point coordinate in a least squares optimization. // Weight of a point coordinate in a least squares optimization.
// The first row of points may not be fully reachable // The first row of points may not be fully reachable
// and the y values may be shortened a bit by the bed carriage // and the y values may be shortened a bit by the bed carriage
// pulling the belt up. // pulling the belt up.
static inline float point_weight_x(const uint8_t i, const float &y) static inline float point_weight_x(const uint8_t i, const uint8_t npts, const float &y)
{ {
float w = 1.f; float w = 1.f;
if (i < 3) { if (point_on_1st_row(i, npts)) {
if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) { if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) {
w = WEIGHT_FIRST_ROW_X_HIGH; w = WEIGHT_FIRST_ROW_X_HIGH;
} else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) { } else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) {
// If the point is fully outside, give it some weight. // If the point is fully outside, give it some weight.
@ -101,10 +107,10 @@ static inline float point_weight_x(const uint8_t i, const float &y)
// The first row of points may not be fully reachable // The first row of points may not be fully reachable
// and the y values may be shortened a bit by the bed carriage // and the y values may be shortened a bit by the bed carriage
// pulling the belt up. // pulling the belt up.
static inline float point_weight_y(const uint8_t i, const float &y) static inline float point_weight_y(const uint8_t i, const uint8_t npts, const float &y)
{ {
float w = 1.f; float w = 1.f;
if (i < 3) { if (point_on_1st_row(i, npts)) {
if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) { if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) {
w = WEIGHT_FIRST_ROW_Y_HIGH; w = WEIGHT_FIRST_ROW_Y_HIGH;
} else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) { } else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) {
@ -138,6 +144,8 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
) )
{ {
if (verbosity_level >= 10) { if (verbosity_level >= 10) {
SERIAL_ECHOLNPGM("calculate machine skew and offset LS");
// Show the initial state, before the fitting. // Show the initial state, before the fitting.
SERIAL_ECHOPGM("X vector, initial: "); SERIAL_ECHOPGM("X vector, initial: ");
MYSERIAL.print(vec_x[0], 5); MYSERIAL.print(vec_x[0], 5);
@ -210,7 +218,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
(c == 0) ? 1.f : (c == 0) ? 1.f :
((c == 2) ? (-s1 * measured_pts[2 * i]) : ((c == 2) ? (-s1 * measured_pts[2 * i]) :
(-c2 * measured_pts[2 * i + 1])); (-c2 * measured_pts[2 * i + 1]));
float w = point_weight_x(i, measured_pts[2 * i + 1]); float w = point_weight_x(i, npts, measured_pts[2 * i + 1]);
acc += a * b * w; acc += a * b * w;
} }
// Second for the residuum in the y axis. // Second for the residuum in the y axis.
@ -225,7 +233,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
(c == 1) ? 1.f : (c == 1) ? 1.f :
((c == 2) ? ( c1 * measured_pts[2 * i]) : ((c == 2) ? ( c1 * measured_pts[2 * i]) :
(-s2 * measured_pts[2 * i + 1])); (-s2 * measured_pts[2 * i + 1]));
float w = point_weight_y(i, measured_pts[2 * i + 1]); float w = point_weight_y(i, npts, measured_pts[2 * i + 1]);
acc += a * b * w; acc += a * b * w;
} }
} }
@ -241,7 +249,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
((r == 2) ? (-s1 * measured_pts[2 * i]) : ((r == 2) ? (-s1 * measured_pts[2 * i]) :
(-c2 * measured_pts[2 * i + 1]))); (-c2 * measured_pts[2 * i + 1])));
float fx = c1 * measured_pts[2 * i] - s2 * measured_pts[2 * i + 1] + cntr[0] - pgm_read_float(true_pts + i * 2); float fx = c1 * measured_pts[2 * i] - s2 * measured_pts[2 * i + 1] + cntr[0] - pgm_read_float(true_pts + i * 2);
float w = point_weight_x(i, measured_pts[2 * i + 1]); float w = point_weight_x(i, npts, measured_pts[2 * i + 1]);
acc += j * fx * w; acc += j * fx * w;
} }
{ {
@ -251,7 +259,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
((r == 2) ? ( c1 * measured_pts[2 * i]) : ((r == 2) ? ( c1 * measured_pts[2 * i]) :
(-s2 * measured_pts[2 * i + 1]))); (-s2 * measured_pts[2 * i + 1])));
float fy = s1 * measured_pts[2 * i] + c2 * measured_pts[2 * i + 1] + cntr[1] - pgm_read_float(true_pts + i * 2 + 1); float fy = s1 * measured_pts[2 * i] + c2 * measured_pts[2 * i + 1] + cntr[1] - pgm_read_float(true_pts + i * 2 + 1);
float w = point_weight_y(i, measured_pts[2 * i + 1]); float w = point_weight_y(i, npts, measured_pts[2 * i + 1]);
acc += j * fy * w; acc += j * fy * w;
} }
} }
@ -278,8 +286,8 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
if (verbosity_level >= 20) { if (verbosity_level >= 20) {
SERIAL_ECHOPGM("iteration: "); SERIAL_ECHOPGM("iteration: ");
MYSERIAL.print(iter, 0); MYSERIAL.print(int(iter));
SERIAL_ECHOPGM("correction vector: "); SERIAL_ECHOPGM("; correction vector: ");
MYSERIAL.print(h[0], 5); MYSERIAL.print(h[0], 5);
SERIAL_ECHOPGM(", "); SERIAL_ECHOPGM(", ");
MYSERIAL.print(h[1], 5); MYSERIAL.print(h[1], 5);
@ -308,13 +316,13 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
BedSkewOffsetDetectionResultType result = BED_SKEW_OFFSET_DETECTION_PERFECT; BedSkewOffsetDetectionResultType result = BED_SKEW_OFFSET_DETECTION_PERFECT;
{ {
float angleDiff = fabs(a2 - a1); angleDiff = fabs(a2 - a1);
if (angleDiff > BED_SKEW_ANGLE_MILD) if (angleDiff > bed_skew_angle_mild)
result = (angleDiff > BED_SKEW_ANGLE_EXTREME) ? result = (angleDiff > bed_skew_angle_extreme) ?
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME : BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME :
BED_SKEW_OFFSET_DETECTION_SKEW_MILD; BED_SKEW_OFFSET_DETECTION_SKEW_MILD;
if (fabs(a1) > BED_SKEW_ANGLE_EXTREME || if (fabs(a1) > bed_skew_angle_extreme ||
fabs(a2) > BED_SKEW_ANGLE_EXTREME) fabs(a2) > bed_skew_angle_extreme)
result = BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME; result = BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME;
} }
@ -357,19 +365,36 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
float errX = sqr(pgm_read_float(true_pts + i * 2) - x); float errX = sqr(pgm_read_float(true_pts + i * 2) - x);
float errY = sqr(pgm_read_float(true_pts + i * 2 + 1) - y); float errY = sqr(pgm_read_float(true_pts + i * 2 + 1) - y);
float err = sqrt(errX + errY); float err = sqrt(errX + errY);
if (i < 3) { if (verbosity_level >= 10) {
float w = point_weight_y(i, measured_pts[2 * i + 1]); SERIAL_ECHOPGM("point #");
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X || MYSERIAL.print(int(i));
(w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y)) SERIAL_ECHOLNPGM(":");
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED; }
} else {
if (err > BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN) if (point_on_1st_row(i, npts)) {
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED; if(verbosity_level >= 20) SERIAL_ECHOPGM("Point on first row");
float w = point_weight_y(i, npts, measured_pts[2 * i + 1]);
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
(w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y)) {
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
if (verbosity_level >= 20) {
SERIAL_ECHOPGM(", weigth Y: ");
MYSERIAL.print(w);
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X) SERIAL_ECHOPGM(", error X > max. error X");
if (w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y) SERIAL_ECHOPGM(", error Y > max. error Y");
}
}
}
else {
if(verbosity_level >=20 ) SERIAL_ECHOPGM("Point not on first row");
if (err > BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN) {
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
if(verbosity_level >= 20) SERIAL_ECHOPGM(", error > max. error euclidian");
}
} }
if (verbosity_level >= 10) { if (verbosity_level >= 10) {
SERIAL_ECHOPGM("point #"); SERIAL_ECHOLNPGM("");
MYSERIAL.print(int(i)); SERIAL_ECHOPGM("measured: (");
SERIAL_ECHOPGM(" measured: (");
MYSERIAL.print(measured_pts[i * 2], 5); MYSERIAL.print(measured_pts[i * 2], 5);
SERIAL_ECHOPGM(", "); SERIAL_ECHOPGM(", ");
MYSERIAL.print(measured_pts[i * 2 + 1], 5); MYSERIAL.print(measured_pts[i * 2 + 1], 5);
@ -381,18 +406,30 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
MYSERIAL.print(pgm_read_float(true_pts + i * 2), 5); MYSERIAL.print(pgm_read_float(true_pts + i * 2), 5);
SERIAL_ECHOPGM(", "); SERIAL_ECHOPGM(", ");
MYSERIAL.print(pgm_read_float(true_pts + i * 2 + 1), 5); MYSERIAL.print(pgm_read_float(true_pts + i * 2 + 1), 5);
SERIAL_ECHOPGM("), error: "); SERIAL_ECHOLNPGM(")");
SERIAL_ECHOPGM("error: ");
MYSERIAL.print(err); MYSERIAL.print(err);
SERIAL_ECHOPGM(", error X: "); SERIAL_ECHOPGM(", error X: ");
MYSERIAL.print(errX); MYSERIAL.print(sqrt(errX));
SERIAL_ECHOPGM(", error Y: "); SERIAL_ECHOPGM(", error Y: ");
MYSERIAL.print(errY); MYSERIAL.print(sqrt(errY));
SERIAL_ECHOLNPGM(""); SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM("");
} }
} }
if (verbosity_level >= 20) {
SERIAL_ECHOLNPGM("Max. errors:");
SERIAL_ECHOPGM("Max. error X:");
MYSERIAL.println(BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X);
SERIAL_ECHOPGM("Max. error Y:");
MYSERIAL.println(BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y);
SERIAL_ECHOPGM("Max. error euclidian:");
MYSERIAL.println(BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN);
SERIAL_ECHOLNPGM("");
}
#if 0 #if 0
if (result == BED_SKEW_OFFSET_DETECTION_PERFECT && fabs(a1) < BED_SKEW_ANGLE_MILD && fabs(a2) < BED_SKEW_ANGLE_MILD) { if (result == BED_SKEW_OFFSET_DETECTION_PERFECT && fabs(a1) < bed_skew_angle_mild && fabs(a2) < bed_skew_angle_mild) {
if (verbosity_level > 0) if (verbosity_level > 0)
SERIAL_ECHOLNPGM("Very little skew detected. Disabling skew correction."); SERIAL_ECHOLNPGM("Very little skew detected. Disabling skew correction.");
// Just disable the skew correction. // Just disable the skew correction.
@ -419,7 +456,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
for (int8_t i = 0; i < npts; ++ i) { for (int8_t i = 0; i < npts; ++ i) {
float x = vec_x[0] * measured_pts[i * 2] + vec_y[0] * measured_pts[i * 2 + 1]; float x = vec_x[0] * measured_pts[i * 2] + vec_y[0] * measured_pts[i * 2 + 1];
float y = vec_x[1] * measured_pts[i * 2] + vec_y[1] * measured_pts[i * 2 + 1]; float y = vec_x[1] * measured_pts[i * 2] + vec_y[1] * measured_pts[i * 2 + 1];
float w = point_weight_x(i, y); float w = point_weight_x(i, npts, y);
cntr[0] += w * (pgm_read_float(true_pts + i * 2) - x); cntr[0] += w * (pgm_read_float(true_pts + i * 2) - x);
wx += w; wx += w;
if (verbosity_level >= 20) { if (verbosity_level >= 20) {
@ -434,7 +471,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
SERIAL_ECHOLNPGM("wx:"); SERIAL_ECHOLNPGM("wx:");
MYSERIAL.print(wx); MYSERIAL.print(wx);
} }
w = point_weight_y(i, y); w = point_weight_y(i, npts, y);
cntr[1] += w * (pgm_read_float(true_pts + i * 2 + 1) - y); cntr[1] += w * (pgm_read_float(true_pts + i * 2 + 1) - y);
wy += w; wy += w;
@ -532,6 +569,13 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
MYSERIAL.print(sqrt(sqr(measured_pts[i * 2] - x) + sqr(measured_pts[i * 2 + 1] - y))); MYSERIAL.print(sqrt(sqr(measured_pts[i * 2] - x) + sqr(measured_pts[i * 2 + 1] - y)));
SERIAL_ECHOLNPGM(""); SERIAL_ECHOLNPGM("");
} }
if (verbosity_level >= 20) {
SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM("Calculate offset and skew returning result:");
MYSERIAL.print(int(result));
SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM("");
}
delay_keep_alive(100); delay_keep_alive(100);
} }
@ -623,7 +667,7 @@ static inline bool vec_undef(const float v[2])
void world2machine_initialize() void world2machine_initialize()
{ {
// SERIAL_ECHOLNPGM("world2machine_initialize()"); //SERIAL_ECHOLNPGM("world2machine_initialize");
float cntr[2] = { float cntr[2] = {
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0)), eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0)),
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4)) eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4))
@ -639,7 +683,7 @@ void world2machine_initialize()
bool reset = false; bool reset = false;
if (vec_undef(cntr) || vec_undef(vec_x) || vec_undef(vec_y)) { if (vec_undef(cntr) || vec_undef(vec_x) || vec_undef(vec_y)) {
// SERIAL_ECHOLNPGM("Undefined bed correction matrix."); SERIAL_ECHOLNPGM("Undefined bed correction matrix.");
reset = true; reset = true;
} }
else { else {
@ -744,9 +788,9 @@ static inline void update_current_position_z()
} }
// At the current position, find the Z stop. // At the current position, find the Z stop.
inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter) inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int verbosity_level)
{ {
// SERIAL_ECHOLNPGM("find_bed_induction_sensor_point_z 1"); if(verbosity_level >= 10) SERIAL_ECHOLNPGM("find bed induction sensor point z");
bool endstops_enabled = enable_endstops(true); bool endstops_enabled = enable_endstops(true);
bool endstop_z_enabled = enable_z_endstop(false); bool endstop_z_enabled = enable_z_endstop(false);
float z = 0.f; float z = 0.f;
@ -799,8 +843,9 @@ error:
#define FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS (6.f) #define FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS (6.f)
#define FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP (1.f) #define FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP (1.f)
#define FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP (0.2f) #define FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP (0.2f)
inline bool find_bed_induction_sensor_point_xy() inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
{ {
if(verbosity_level >= 10) MYSERIAL.println("find bed induction sensor point xy");
float feedrate = homing_feedrate[X_AXIS] / 60.f; float feedrate = homing_feedrate[X_AXIS] / 60.f;
bool found = false; bool found = false;
@ -811,14 +856,22 @@ inline bool find_bed_induction_sensor_point_xy()
float y1 = current_position[Y_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS; float y1 = current_position[Y_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
uint8_t nsteps_y; uint8_t nsteps_y;
uint8_t i; uint8_t i;
if (x0 < X_MIN_POS) if (x0 < X_MIN_POS) {
x0 = X_MIN_POS; x0 = X_MIN_POS;
if (x1 > X_MAX_POS) if (verbosity_level >= 20) SERIAL_ECHOLNPGM("X searching radius lower than X_MIN. Clamping was done.");
x1 = X_MAX_POS; }
if (y0 < Y_MIN_POS_FOR_BED_CALIBRATION) if (x1 > X_MAX_POS) {
y0 = Y_MIN_POS_FOR_BED_CALIBRATION; x1 = X_MAX_POS;
if (y1 > Y_MAX_POS) if (verbosity_level >= 20) SERIAL_ECHOLNPGM("X searching radius higher than X_MAX. Clamping was done.");
y1 = Y_MAX_POS; }
if (y0 < Y_MIN_POS_FOR_BED_CALIBRATION) {
y0 = Y_MIN_POS_FOR_BED_CALIBRATION;
if (verbosity_level >= 20) SERIAL_ECHOLNPGM("Y searching radius lower than Y_MIN. Clamping was done.");
}
if (y1 > Y_MAX_POS) {
y1 = Y_MAX_POS;
if (verbosity_level >= 20) SERIAL_ECHOLNPGM("Y searching radius higher than X_MAX. Clamping was done.");
}
nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP)); nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP));
enable_endstops(false); enable_endstops(false);
@ -1244,6 +1297,7 @@ inline bool improve_bed_induction_sensor_point3(int verbosity_level)
float a, b; float a, b;
bool result = true; bool result = true;
if (verbosity_level >= 20) MYSERIAL.println("Improve bed induction sensor point3");
// Was the sensor point detected too far in the minus Y axis? // Was the sensor point detected too far in the minus Y axis?
// If yes, the center of the induction point cannot be reached by the machine. // If yes, the center of the induction point cannot be reached by the machine.
{ {
@ -1578,7 +1632,7 @@ inline void scan_bed_induction_sensor_point()
#define MESH_BED_CALIBRATION_SHOW_LCD #define MESH_BED_CALIBRATION_SHOW_LCD
BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level) BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask)
{ {
// Don't let the manage_inactivity() function remove power from the motors. // Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout(); refresh_cmd_timeout();
@ -1601,40 +1655,28 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
SERIAL_ECHOPGM("Iteration: "); SERIAL_ECHOPGM("Iteration: ");
MYSERIAL.println(int(iteration + 1)); MYSERIAL.println(int(iteration + 1));
if (verbosity_level >= 20) {
SERIAL_ECHOLNPGM("Vectors: ");
if (iteration > 0) { SERIAL_ECHOPGM("vec_x[0]:");
// Cache the current correction matrix. MYSERIAL.print(vec_x[0], 5);
world2machine_initialize(); SERIAL_ECHOLNPGM("");
vec_x[0] = world2machine_rotation_and_skew[0][0]; SERIAL_ECHOPGM("vec_x[1]:");
vec_x[1] = world2machine_rotation_and_skew[1][0]; MYSERIAL.print(vec_x[1], 5);
vec_y[0] = world2machine_rotation_and_skew[0][1]; SERIAL_ECHOLNPGM("");
vec_y[1] = world2machine_rotation_and_skew[1][1]; SERIAL_ECHOPGM("vec_y[0]:");
cntr[0] = world2machine_shift[0]; MYSERIAL.print(vec_y[0], 5);
cntr[1] = world2machine_shift[1]; SERIAL_ECHOLNPGM("");
if (verbosity_level >= 20) { SERIAL_ECHOPGM("vec_y[1]:");
SERIAL_ECHOPGM("vec_x[0]:"); MYSERIAL.print(vec_y[1], 5);
MYSERIAL.print(vec_x[0], 5); SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM(""); SERIAL_ECHOPGM("cntr[0]:");
SERIAL_ECHOPGM("vec_x[1]:"); MYSERIAL.print(cntr[0], 5);
MYSERIAL.print(vec_x[1], 5); SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM(""); SERIAL_ECHOPGM("cntr[1]:");
SERIAL_ECHOPGM("vec_y[0]:"); MYSERIAL.print(cntr[1], 5);
MYSERIAL.print(vec_y[0], 5); SERIAL_ECHOLNPGM("");
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("vec_y[1]:");
MYSERIAL.print(vec_y[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("cntr[0]:");
MYSERIAL.print(cntr[0], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("cntr[1]:");
MYSERIAL.print(cntr[1], 5);
SERIAL_ECHOLNPGM("");
}
// and reset the correction matrix, so the planner will not do anything.
world2machine_reset();
} }
#ifdef MESH_BED_CALIBRATION_SHOW_LCD #ifdef MESH_BED_CALIBRATION_SHOW_LCD
uint8_t next_line; uint8_t next_line;
lcd_display_message_fullscreen_P(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1, next_line); lcd_display_message_fullscreen_P(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1, next_line);
@ -1643,7 +1685,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */ #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Collect the rear 2x3 points. // Collect the rear 2x3 points.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; current_position[Z_AXIS] = MESH_HOME_Z_SEARCH + FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP * iteration * 0.3;
for (int k = 0; k < 4; ++k) { for (int k = 0; k < 4; ++k) {
// Don't let the manage_inactivity() function remove power from the motors. // Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout(); refresh_cmd_timeout();
@ -1672,10 +1714,10 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
delay_keep_alive(5000); delay_keep_alive(5000);
} }
// Go to the measurement point position. // Go to the measurement point position.
if (iteration == 0) { //if (iteration == 0) {
current_position[X_AXIS] = pgm_read_float(bed_ref_points_4 + k * 2); current_position[X_AXIS] = pgm_read_float(bed_ref_points_4 + k * 2);
current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + k * 2 + 1); current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + k * 2 + 1);
} /*}
else { else {
// if first iteration failed, count corrected point coordinates as initial // if first iteration failed, count corrected point coordinates as initial
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew(). // Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
@ -1687,21 +1729,24 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
if (current_position[Y_AXIS] < Y_MIN_POS_FOR_BED_CALIBRATION) if (current_position[Y_AXIS] < Y_MIN_POS_FOR_BED_CALIBRATION)
current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION; current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION;
} }*/
if (verbosity_level >= 20) { if (verbosity_level >= 20) {
SERIAL_ECHOPGM("corrected current_position[X_AXIS]:"); SERIAL_ECHOPGM("current_position[X_AXIS]:");
MYSERIAL.print(current_position[X_AXIS], 5); MYSERIAL.print(current_position[X_AXIS], 5);
SERIAL_ECHOLNPGM(""); SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("corrected current_position[Y_AXIS]:"); SERIAL_ECHOPGM("current_position[Y_AXIS]:");
MYSERIAL.print(current_position[Y_AXIS], 5); MYSERIAL.print(current_position[Y_AXIS], 5);
SERIAL_ECHOLNPGM(""); SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("current_position[Z_AXIS]:");
MYSERIAL.print(current_position[Z_AXIS], 5);
SERIAL_ECHOLNPGM("");
} }
go_to_current(homing_feedrate[X_AXIS] / 60.f); go_to_current(homing_feedrate[X_AXIS] / 60.f);
if (verbosity_level >= 10) if (verbosity_level >= 10)
delay_keep_alive(3000); delay_keep_alive(3000);
if (!find_bed_induction_sensor_point_xy()) if (!find_bed_induction_sensor_point_xy(verbosity_level))
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
#if 1 #if 1
@ -1734,22 +1779,30 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
MYSERIAL.println(current_position[X_AXIS]); MYSERIAL.println(current_position[X_AXIS]);
MYSERIAL.println(current_position[Y_AXIS]); MYSERIAL.println(current_position[Y_AXIS]);
} }
//pt[0] = (pt[0] * iteration) / (iteration + 1); pt[0] = (pt[0] * iteration) / (iteration + 1);
//pt[0] += (current_position[X_AXIS]/(iteration + 1)); //count average pt[0] += (current_position[X_AXIS]/(iteration + 1)); //count average
//pt[1] = (pt[1] * iteration) / (iteration + 1); pt[1] = (pt[1] * iteration) / (iteration + 1);
//pt[1] += (current_position[Y_AXIS] / (iteration + 1)); pt[1] += (current_position[Y_AXIS] / (iteration + 1));
pt[0] += current_position[X_AXIS]; //pt[0] += current_position[X_AXIS];
if(iteration > 0) pt[0] = pt[0] / 2; //if(iteration > 0) pt[0] = pt[0] / 2;
pt[1] += current_position[Y_AXIS]; //pt[1] += current_position[Y_AXIS];
if (iteration > 0) pt[1] = pt[1] / 2; //if (iteration > 0) pt[1] = pt[1] / 2;
if (verbosity_level >= 20) {
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("pt[0]:");
MYSERIAL.println(pt[0]);
SERIAL_ECHOPGM("pt[1]:");
MYSERIAL.println(pt[1]);
}
if (current_position[Y_AXIS] < Y_MIN_POS) if (current_position[Y_AXIS] < Y_MIN_POS)
current_position[Y_AXIS] = Y_MIN_POS; current_position[Y_AXIS] = Y_MIN_POS;
// Start searching for the other points at 3mm above the last point. // Start searching for the other points at 3mm above the last point.
current_position[Z_AXIS] += 3.f; current_position[Z_AXIS] += 3.f + FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP * iteration * 0.3;
//cntr[0] += pt[0]; //cntr[0] += pt[0];
//cntr[1] += pt[1]; //cntr[1] += pt[1];
if (verbosity_level >= 10 && k == 0) { if (verbosity_level >= 10 && k == 0) {
@ -1775,6 +1828,15 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
} }
} }
if (pts[1] < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) {
too_far_mask |= 1 << 1; //front center point is out of reach
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("WARNING: Front point not reachable. Y coordinate:");
MYSERIAL.print(pts[1]);
SERIAL_ECHOPGM(" < ");
MYSERIAL.println(Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
}
result = calculate_machine_skew_and_offset_LS(pts, 4, bed_ref_points_4, vec_x, vec_y, cntr, verbosity_level); result = calculate_machine_skew_and_offset_LS(pts, 4, bed_ref_points_4, vec_x, vec_y, cntr, verbosity_level);
if (result >= 0) { if (result >= 0) {
world2machine_update(vec_x, vec_y, cntr); world2machine_update(vec_x, vec_y, cntr);
@ -1811,6 +1873,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
// Correct the current_position to match the transformed coordinate system after world2machine_rotation_and_skew and world2machine_shift were set. // Correct the current_position to match the transformed coordinate system after world2machine_rotation_and_skew and world2machine_shift were set.
world2machine_update_current(); world2machine_update_current();
if (verbosity_level >= 20) { if (verbosity_level >= 20) {
// Test the positions. Are the positions reproducible? Now the calibration is active in the planner. // Test the positions. Are the positions reproducible? Now the calibration is active in the planner.
delay_keep_alive(3000); delay_keep_alive(3000);
@ -1827,6 +1890,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
} }
return result; return result;
} }
if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED && too_far_mask == 2) return result; //if fitting failed and front center point is out of reach, terminate calibration and inform user
iteration++; iteration++;
} }
return result; return result;
@ -1848,6 +1912,8 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
float *cntr = vec_y + 2; float *cntr = vec_y + 2;
memset(pts, 0, sizeof(float) * 7 * 7); memset(pts, 0, sizeof(float) * 7 * 7);
if (verbosity_level >= 10) SERIAL_ECHOLNPGM("Improving bed offset and skew");
// Cache the current correction matrix. // Cache the current correction matrix.
world2machine_initialize(); world2machine_initialize();
vec_x[0] = world2machine_rotation_and_skew[0][0]; vec_x[0] = world2machine_rotation_and_skew[0][0];
@ -1893,7 +1959,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
delay_keep_alive(5000); delay_keep_alive(5000);
current_position[Y_AXIS] = Y_MIN_POS; current_position[Y_AXIS] = Y_MIN_POS;
go_to_current(homing_feedrate[X_AXIS] / 60.f); go_to_current(homing_feedrate[X_AXIS] / 60.f);
SERIAL_ECHOLNPGM("At Y-4"); SERIAL_ECHOLNPGM("At Y_MIN_POS");
delay_keep_alive(5000); delay_keep_alive(5000);
} }
// Go to the measurement point. // Go to the measurement point.
@ -1901,8 +1967,15 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
current_position[X_AXIS] = vec_x[0] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[0] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[0]; current_position[X_AXIS] = vec_x[0] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[0] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[0];
current_position[Y_AXIS] = vec_x[1] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[1] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[1]; current_position[Y_AXIS] = vec_x[1] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[1] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[1];
// The calibration points are very close to the min Y. // The calibration points are very close to the min Y.
if (current_position[Y_AXIS] < Y_MIN_POS_FOR_BED_CALIBRATION) if (current_position[Y_AXIS] < Y_MIN_POS_FOR_BED_CALIBRATION){
current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION; current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION;
if (verbosity_level >= 20) {
SERIAL_ECHOPGM("Calibration point ");
SERIAL_ECHO(mesh_point);
SERIAL_ECHOPGM("lower than Ymin. Y coordinate clamping was used.");
SERIAL_ECHOLNPGM("");
}
}
go_to_current(homing_feedrate[X_AXIS]/60); go_to_current(homing_feedrate[X_AXIS]/60);
// Find its Z position by running the normal vertical search. // Find its Z position by running the normal vertical search.
if (verbosity_level >= 10) if (verbosity_level >= 10)
@ -1983,6 +2056,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
if (verbosity_level >= 5) { if (verbosity_level >= 5) {
// Test the positions. Are the positions reproducible? // Test the positions. Are the positions reproducible?
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) { for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors. // Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout(); refresh_cmd_timeout();
@ -2017,7 +2091,17 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
// In case of success, update the too_far_mask from the calculated points. // In case of success, update the too_far_mask from the calculated points.
for (uint8_t mesh_point = 0; mesh_point < 3; ++ mesh_point) { for (uint8_t mesh_point = 0; mesh_point < 3; ++ mesh_point) {
float y = vec_x[1] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[1] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[1]; float y = vec_x[1] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[1] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[1];
if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) distance_from_min[mesh_point] = (y - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
if (verbosity_level >= 20) {
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("Distance from min:");
MYSERIAL.print(distance_from_min[mesh_point]);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("y:");
MYSERIAL.print(y);
SERIAL_ECHOLNPGM("");
}
if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH)
too_far_mask |= 1 << mesh_point; too_far_mask |= 1 << mesh_point;
} }
} }
@ -2042,6 +2126,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
if (verbosity_level >= 5) { if (verbosity_level >= 5) {
// Test the positions. Are the positions reproducible? Now the calibration is active in the planner. // Test the positions. Are the positions reproducible? Now the calibration is active in the planner.
delay_keep_alive(3000); delay_keep_alive(3000);
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) { for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors. // Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout(); refresh_cmd_timeout();
@ -2347,3 +2432,33 @@ void babystep_reset()
{ {
babystepLoadZ = 0; babystepLoadZ = 0;
} }
void count_xyz_details() {
float a1, a2;
float cntr[2] = {
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 0)),
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 4))
};
float vec_x[2] = {
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 0)),
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 4))
};
float vec_y[2] = {
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 0)),
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 4))
};
a2 = -1 * asin(vec_y[0] / MACHINE_AXIS_SCALE_Y);
a1 = asin(vec_x[1] / MACHINE_AXIS_SCALE_X);
angleDiff = fabs(a2 - a1);
for (uint8_t mesh_point = 0; mesh_point < 3; ++mesh_point) {
float y = vec_x[1] * pgm_read_float(bed_ref_points + mesh_point * 2) + vec_y[1] * pgm_read_float(bed_ref_points + mesh_point * 2 + 1) + cntr[1];
distance_from_min[mesh_point] = (y - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
}
}
/*countDistanceFromMin() {
}*/

View File

@ -6,6 +6,9 @@
// is built properly, the end stops are at the correct positions and the axes are perpendicular. // is built properly, the end stops are at the correct positions and the axes are perpendicular.
extern const float bed_ref_points[] PROGMEM; extern const float bed_ref_points[] PROGMEM;
extern const float bed_skew_angle_mild;
extern const float bed_skew_angle_extreme;
// Is the world2machine correction activated? // Is the world2machine correction activated?
enum World2MachineCorrectionMode enum World2MachineCorrectionMode
{ {
@ -140,8 +143,8 @@ inline bool world2machine_clamp(float &x, float &y)
return clamped; return clamped;
} }
extern bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3); extern bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
extern bool find_bed_induction_sensor_point_xy(); extern bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
extern void go_home_with_z_lift(); extern void go_home_with_z_lift();
// Positive or zero: ok // Positive or zero: ok
@ -157,7 +160,7 @@ enum BedSkewOffsetDetectionResultType {
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2 BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2
}; };
extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level); extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask);
extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask); extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask);
extern bool sample_mesh_and_store_reference(); extern bool sample_mesh_and_store_reference();
@ -178,5 +181,6 @@ extern void babystep_undo();
// Reset the current babystep counter without moving the axes. // Reset the current babystep counter without moving the axes.
extern void babystep_reset(); extern void babystep_reset();
extern void count_xyz_details();
#endif /* MESH_BED_CALIBRATION_H */ #endif /* MESH_BED_CALIBRATION_H */

View File

@ -640,7 +640,7 @@ void lcd_commands()
#endif #endif
lcd_ignore_click(false); lcd_ignore_click(false);
#ifdef SNMM #ifdef SNMM
lcd_commands_step = 7; lcd_commands_step = 8;
#else #else
lcd_commands_step = 3; lcd_commands_step = 3;
#endif #endif
@ -671,9 +671,17 @@ void lcd_commands()
lcd_commands_step = 5; lcd_commands_step = 5;
} }
if (lcd_commands_step == 7 && !blocks_queued()) { if (lcd_commands_step == 7 && !blocks_queued()) {
enquecommand_P(PSTR("M702")); switch(snmm_stop_print_menu()) {
case 0: enquecommand_P(PSTR("M702")); break;//all
case 1: enquecommand_P(PSTR("M702 U")); break; //used
case 2: enquecommand_P(PSTR("M702 C")); break; //current
default: enquecommand_P(PSTR("M702")); break;
}
lcd_commands_step = 3; lcd_commands_step = 3;
} }
if (lcd_commands_step == 8 && !blocks_queued()) { //step 8 is here for delay (going to next step after execution of all gcodes from step 4)
lcd_commands_step = 7;
}
} }
if (lcd_commands_type == 3) if (lcd_commands_type == 3)
@ -931,6 +939,8 @@ static void lcd_support_menu()
MENU_ITEM(back, PSTR("FlashAir IP Addr:"), lcd_main_menu); MENU_ITEM(back, PSTR("FlashAir IP Addr:"), lcd_main_menu);
MENU_ITEM(back_RAM, menuData.supportMenu.ip_str, lcd_main_menu); MENU_ITEM(back_RAM, menuData.supportMenu.ip_str, lcd_main_menu);
} }
MENU_ITEM(back, PSTR("------------"), lcd_main_menu);
MENU_ITEM(function, PSTR("XYZ cal. details"), lcd_service_mode_show_result);
END_MENU(); END_MENU();
} }
@ -1336,6 +1346,57 @@ static void lcd_move_e()
} }
} }
void lcd_service_mode_show_result() {
lcd_set_custom_characters_degree();
count_xyz_details();
lcd_update_enable(false);
lcd_implementation_clear();
lcd_printPGM(PSTR("Y distance from min:"));
lcd_print_at_PGM(0, 1, PSTR("Left:"));
lcd_print_at_PGM(0, 2, PSTR("Center:"));
lcd_print_at_PGM(0, 3, PSTR("Right:"));
for (int i = 0; i < 3; i++) {
if(distance_from_min[i] < 200) {
lcd_print_at_PGM(8, i + 1, PSTR(""));
lcd.print(distance_from_min[i]);
lcd_print_at_PGM((distance_from_min[i] < 0) ? 14 : 13, i + 1, PSTR("mm"));
} else lcd_print_at_PGM(8, i + 1, PSTR("N/A"));
}
delay_keep_alive(500);
while (!lcd_clicked()) {
delay_keep_alive(100);
}
delay_keep_alive(500);
lcd_implementation_clear();
lcd_printPGM(PSTR("Angle diff: "));
if (angleDiff < 100) {
lcd.print(angleDiff * 180 / M_PI);
lcd.print(LCD_STR_DEGREE);
}else lcd_print_at_PGM(12, 0, PSTR("N/A"));
lcd_print_at_PGM(0, 1, PSTR("--------------------"));
lcd_print_at_PGM(0, 2, PSTR("Mild:"));
lcd_print_at_PGM(12, 2, PSTR(""));
lcd.print(bed_skew_angle_mild * 180 / M_PI);
lcd.print(LCD_STR_DEGREE);
lcd_print_at_PGM(0, 3, PSTR("Extreme:"));
lcd_print_at_PGM(12, 3, PSTR(""));
lcd.print(bed_skew_angle_extreme * 180 / M_PI);
lcd.print(LCD_STR_DEGREE);
delay_keep_alive(500);
while (!lcd_clicked()) {
delay_keep_alive(100);
}
delay_keep_alive(500);
lcd_set_custom_characters_arrows();
lcd_return_to_status();
lcd_update_enable(true);
lcd_update(2);
}
// Save a single axis babystep value. // Save a single axis babystep value.
void EEPROM_save_B(int pos, int* value) void EEPROM_save_B(int pos, int* value)
@ -2890,6 +2951,138 @@ void bowden_menu() {
} }
} }
static char snmm_stop_print_menu() { //menu for choosing which filaments will be unloaded in stop print
lcd_implementation_clear();
lcd_print_at_PGM(0,0,MSG_UNLOAD_FILAMENT); lcd.print(":");
lcd.setCursor(0, 1); lcd.print(">");
lcd_print_at_PGM(1,1,MSG_ALL);
lcd_print_at_PGM(1,2,MSG_USED);
lcd_print_at_PGM(1,3,MSG_CURRENT);
char cursor_pos = 1;
int enc_dif = 0;
while (1) {
manage_heater();
manage_inactivity(true);
if (abs((enc_dif - encoderDiff)) > 4) {
if ((abs(enc_dif - encoderDiff)) > 1) {
if (enc_dif > encoderDiff) cursor_pos--;
if (enc_dif < encoderDiff) cursor_pos++;
if (cursor_pos > 3) cursor_pos = 3;
if (cursor_pos < 1) cursor_pos = 1;
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(0, cursor_pos);
lcd.print(">");
enc_dif = encoderDiff;
delay(100);
}
}
if (lcd_clicked()) {
while (lcd_clicked());
delay(10);
while (lcd_clicked());
return(cursor_pos - 1);
}
}
}
char choose_extruder_menu() {
int items_no = 4;
int first = 0;
int enc_dif = 0;
char cursor_pos = 1;
enc_dif = encoderDiff;
lcd_implementation_clear();
lcd_printPGM(MSG_CHOOSE_EXTRUDER);
lcd.setCursor(0, 1);
lcd.print(">");
for (int i = 0; i < 3; i++) {
lcd_print_at_PGM(1, i + 1, MSG_EXTRUDER);
}
while (1) {
for (int i = 0; i < 3; i++) {
lcd.setCursor(2 + strlen_P(MSG_EXTRUDER), i+1);
lcd.print(first + i + 1);
}
manage_heater();
manage_inactivity(true);
if (abs((enc_dif - encoderDiff)) > 4) {
if ((abs(enc_dif - encoderDiff)) > 1) {
if (enc_dif > encoderDiff) {
cursor_pos--;
}
if (enc_dif < encoderDiff) {
cursor_pos++;
}
if (cursor_pos > 3) {
cursor_pos = 3;
if (first < items_no - 3) {
first++;
lcd_implementation_clear();
lcd_printPGM(MSG_CHOOSE_EXTRUDER);
for (int i = 0; i < 3; i++) {
lcd_print_at_PGM(1, i + 1, MSG_EXTRUDER);
}
}
}
if (cursor_pos < 1) {
cursor_pos = 1;
if (first > 0) {
first--;
lcd_implementation_clear();
lcd_printPGM(MSG_CHOOSE_EXTRUDER);
for (int i = 0; i < 3; i++) {
lcd_print_at_PGM(1, i + 1, MSG_EXTRUDER);
}
}
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(0, cursor_pos);
lcd.print(">");
enc_dif = encoderDiff;
delay(100);
}
}
if (lcd_clicked()) {
lcd_update(2);
while (lcd_clicked());
delay(10);
while (lcd_clicked());
return(cursor_pos + first - 1);
}
}
}
char reset_menu() { char reset_menu() {
#ifdef SNMM #ifdef SNMM
int items_no = 5; int items_no = 5;
@ -3116,7 +3309,7 @@ static void extr_adj(int extruder) //loading filament for SNMM
} }
static void extr_unload() { //unloads filament void extr_unload() { //unloads filament
float tmp_motor[3] = DEFAULT_PWM_MOTOR_CURRENT; float tmp_motor[3] = DEFAULT_PWM_MOTOR_CURRENT;
float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD; float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
int8_t SilentMode; int8_t SilentMode;
@ -3254,6 +3447,30 @@ void extr_unload_all() {
} }
} }
//unloading just used filament (for snmm)
void extr_unload_used() {
if (degHotend0() > EXTRUDE_MINTEMP) {
for (int i = 0; i < 4; i++) {
if (snmm_filaments_used & (1 << i)) {
change_extr(i);
extr_unload();
}
}
snmm_filaments_used = 0;
}
else {
lcd_implementation_clear();
lcd.setCursor(0, 0);
lcd_printPGM(MSG_ERROR);
lcd.setCursor(0, 2);
lcd_printPGM(MSG_PREHEAT_NOZZLE);
delay(2000);
lcd_implementation_clear();
lcd_return_to_status();
}
}
static void extr_unload_0() { static void extr_unload_0() {
@ -3287,7 +3504,6 @@ static void fil_load_menu()
END_MENU(); END_MENU();
} }
static void fil_unload_menu() static void fil_unload_menu()
{ {
START_MENU(); START_MENU();
@ -3304,10 +3520,10 @@ static void fil_unload_menu()
static void change_extr_menu(){ static void change_extr_menu(){
START_MENU(); START_MENU();
MENU_ITEM(back, MSG_MAIN, lcd_main_menu); MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
MENU_ITEM(function, PSTR("Extruder 1"), extr_change_0); MENU_ITEM(function, MSG_EXTRUDER_1, extr_change_0);
MENU_ITEM(function, PSTR("Extruder 2"), extr_change_1); MENU_ITEM(function, MSG_EXTRUDER_2, extr_change_1);
MENU_ITEM(function, PSTR("Extruder 3"), extr_change_2); MENU_ITEM(function, MSG_EXTRUDER_3, extr_change_2);
MENU_ITEM(function, PSTR("Extruder 4"), extr_change_3); MENU_ITEM(function, MSG_EXTRUDER_4, extr_change_3);
END_MENU(); END_MENU();
} }
@ -4244,10 +4460,11 @@ static bool lcd_selfcheck_endstops()
if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1 || READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1 || READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1 || READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1 || READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1)
{ {
_result = false; _result = false;
String _error = String((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? "X" : "") + char _error[4] = "";
String((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? "Y" : "") + if (READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) strcat(_error, "X");
String((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? "Z" : ""); if (READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) strcat(_error, "Y");
lcd_selftest_error(3, _error.c_str(), ""); if (READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) strcat(_error, "Z");
lcd_selftest_error(3, _error, "");
} }
manage_heater(); manage_heater();
manage_inactivity(true); manage_inactivity(true);
@ -4263,9 +4480,9 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
int _checked_snapshot = (_isbed) ? degBed() : degHotend(0); int _checked_snapshot = (_isbed) ? degBed() : degHotend(0);
int _opposite_snapshot = (_isbed) ? degHotend(0) : degBed(); int _opposite_snapshot = (_isbed) ? degHotend(0) : degBed();
int _cycles = (_isbed) ? 120 : 30; int _cycles = (_isbed) ? 180 : 60; //~ 90s / 30s
target_temperature[0] = (_isbed) ? 0 : 100; target_temperature[0] = (_isbed) ? 0 : 200;
target_temperature_bed = (_isbed) ? 100 : 0; target_temperature_bed = (_isbed) ? 100 : 0;
manage_heater(); manage_heater();
manage_inactivity(true); manage_inactivity(true);
@ -4277,6 +4494,14 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
manage_heater(); manage_heater();
manage_inactivity(true); manage_inactivity(true);
_progress = (_isbed) ? lcd_selftest_screen(5, _progress, 2, false, 400) : lcd_selftest_screen(1, _progress, 2, false, 400); _progress = (_isbed) ? lcd_selftest_screen(5, _progress, 2, false, 400) : lcd_selftest_screen(1, _progress, 2, false, 400);
/*if (_isbed) {
MYSERIAL.print("Bed temp:");
MYSERIAL.println(degBed());
}
else {
MYSERIAL.print("Hotend temp:");
MYSERIAL.println(degHotend(0));
}*/
} while (_docycle); } while (_docycle);
@ -4286,7 +4511,13 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
int _checked_result = (_isbed) ? degBed() - _checked_snapshot : degHotend(0) - _checked_snapshot; int _checked_result = (_isbed) ? degBed() - _checked_snapshot : degHotend(0) - _checked_snapshot;
int _opposite_result = (_isbed) ? degHotend(0) - _opposite_snapshot : degBed() - _opposite_snapshot; int _opposite_result = (_isbed) ? degHotend(0) - _opposite_snapshot : degBed() - _opposite_snapshot;
/*
MYSERIAL.println("");
MYSERIAL.print("Checked result:");
MYSERIAL.println(_checked_result);
MYSERIAL.print("Opposite result:");
MYSERIAL.println(_opposite_result);
*/
if (_opposite_result < ((_isbed) ? 10 : 3)) if (_opposite_result < ((_isbed) ? 10 : 3))
{ {
if (_checked_result >= ((_isbed) ? 3 : 10)) if (_checked_result >= ((_isbed) ? 3 : 10))

View File

@ -223,7 +223,9 @@ static void extr_unload_2();
static void extr_unload_3(); static void extr_unload_3();
static void lcd_disable_farm_mode(); static void lcd_disable_farm_mode();
void extr_unload_all(); void extr_unload_all();
static void extr_unload(); void extr_unload_used();
void extr_unload();
static char snmm_stop_print_menu();
void stack_error(); void stack_error();
static void lcd_ping_allert(); static void lcd_ping_allert();
@ -246,6 +248,7 @@ union MenuData;
void bowden_menu(); void bowden_menu();
char reset_menu(); char reset_menu();
char choose_extruder_menu();
void lcd_pinda_calibration_menu(); void lcd_pinda_calibration_menu();
void lcd_calibrate_pinda(); void lcd_calibrate_pinda();
@ -253,4 +256,6 @@ void lcd_temp_calibration_set();
void display_loading(); void display_loading();
void lcd_service_mode_show_result();
#endif //ULTRALCD_H #endif //ULTRALCD_H