Automatic bed calibration by searching the 3x3 point matrix.

Fixed a problem with low RAM by re-vamping the langtool.
This commit is contained in:
bubnikv 2016-06-16 14:29:04 +02:00
parent e115c5145f
commit 6cff4b92ff
18 changed files with 8642 additions and 5993 deletions

View file

@ -5,10 +5,12 @@
#include "Configuration_prusa.h"
// Firmware version
#define FW_version "3.0.1"
#define FW_version "3.0.2"
// The total size of the EEPROM is
// 4096 for the Atmega2560
#define EEPROM_SILENT 4095
#define EEPROM_LANG 4094
#define EEPROM_BABYSTEP_X 4092
@ -17,8 +19,12 @@
#define EEPROM_BABYSTEP_Z_SET 4087
#define EEPROM_BABYSTEP_Z0 4085
#define EEPROM_FILAMENTUSED 4081
// uint32_t
#define EEPROM_TOTALTIME 4077
#define EEPROM_BED_CALIBRATION_CENTER (EEPROM_TOTALTIME-2*4)
#define EEPROM_BED_CALIBRATION_VEC_X (EEPROM_BED_CALIBRATION_CENTER-2*4)
#define EEPROM_BED_CALIBRATION_VEC_Y (EEPROM_BED_CALIBRATION_VEC_X-2*4)
// This configuration file contains the basic settings.

View file

@ -0,0 +1,59 @@
{
"build_systems":
[
{
"name": "compile",
"working_dir": "$project_path",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
// Arduino build process:
// https://www.arduino.cc/en/Hacking/BuildProcess
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\arduino_debug.exe\" --pref build.path=..\\output --verify --board marlinAddon:avr:rambo -v --preserve-temp-files Firmware.ino"
},
{
"name": "compile & upload",
"working_dir": "$project_path",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
//FIXME
// Better to use avrdude directly?
// http://www.nongnu.org/avrdude/user-manual/avrdude_4.html
// avrdude -F -v -pm168 -cstk500v1 -P\\.\COM4 -b19200 -D -Uflash:w:"file.hex":i
// may need add path to avrdude config file: -C"c:\utils\arduino-0016\hardware\tools\avr\etc\avrdude.conf" if Arduino IDE installed in "c:\utils\arduino-0016\"
// https://typeunsafe.wordpress.com/2011/07/22/programming-arduino-with-avrdude/
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\arduino_debug.exe\" --pref build.path=..\\output --upload --port COM6 --board marlinAddon:avr:rambo -v --preserve-temp-files Firmware.ino"
},
{
"name": "map-data",
"working_dir": "$project_path",
// https://sourceware.org/binutils/docs-2.21/binutils/objdump.html
// Maybe it is better to generate map files by the linker?
// avr-gcc -g -mmcu=atmega8 -Wl,-Map,demo.map -o demo.elf demo.o
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr\\bin\\avr-objdump.exe\" -x -S -C -j .data ..\\output\\Firmware.ino.elf > ..\\output\\Firmware-data.map"
},
{
"name": "map-bss",
"working_dir": "$project_path",
// https://sourceware.org/binutils/docs-2.21/binutils/objdump.html
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr\\bin\\avr-objdump.exe\" -x -S -C -j .bss ..\\output\\Firmware.ino.elf > ..\\output\\Firmware-bss.map"
},
{
"name": "map-all",
"working_dir": "$project_path",
// https://sourceware.org/binutils/docs-2.21/binutils/objdump.html
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr\\bin\\avr-objdump.exe\" -x -S -C ..\\output\\Firmware.ino.elf > ..\\output\\Firmware-all.map"
},
{
"name": "disassemble",
"working_dir": "$project_path",
// https://sourceware.org/binutils/docs-2.21/binutils/objdump.html
"shell_cmd": "\"c:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr\\bin\\avr-objdump.exe\" -h -w -S ..\\output\\Firmware.ino.elf > ..\\output\\Firmware.asm"
}
],
"folders":
[
{
"path": "."
// "folder_exclude_patterns": [".svn", "._d", ".metadata", ".settings"],
// "file_exclude_patterns": ["XS.c"]
}
]
}

View file

@ -250,6 +250,7 @@ extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in per
extern float filament_size[EXTRUDERS]; // cross-sectional area of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder.
extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern float current_position[NUM_AXIS] ;
extern float destination[NUM_AXIS] ;
extern float add_homing[3];
#ifdef DELTA
extern float endstop_adj[3];
@ -322,3 +323,6 @@ extern void digipot_i2c_init();
extern void calculate_volumetric_multipliers();
// Similar to the default Arduino delay function,
// but it keeps the background tasks running.
extern void delay_keep_alive(int ms);

View file

@ -46,6 +46,7 @@
#ifdef MESH_BED_LEVELING
#include "mesh_bed_leveling.h"
#include "mesh_bed_calibration.h"
#endif
#include "ultralcd.h"
@ -247,6 +248,8 @@ int value;
int babystepLoad[3];
float homing_feedrate[] = HOMING_FEEDRATE;
// Currently only the extruder axis may be switched to a relative mode.
// Other axes are always absolute or relative based on the common relative_mode flag.
bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
int feedmultiply=100; //100->1 200->2
int saved_feedmultiply;
@ -260,8 +263,8 @@ int extruder_multiply[EXTRUDERS] = {100
#endif
};
bool is_usb_printing;
bool _doMeshL;
bool is_usb_printing = false;
bool _doMeshL = false;
unsigned int usb_printing_counter;
int lcd_change_fil_state = 0;
@ -406,20 +409,24 @@ const char echomagic[] PROGMEM = "echo:";
//=============================Private Variables=============================
//===========================================================================
const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
static float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0};
float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0};
#ifndef DELTA
static float delta[3] = {0.0, 0.0, 0.0};
#endif
// For tracing an arc
static float offset[3] = {0.0, 0.0, 0.0};
static bool home_all_axis = true;
static float feedrate = 1500.0, next_feedrate, saved_feedrate;
static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
static bool relative_mode = false; //Determines Absolute or Relative Coordinates
// Determines Absolute or Relative Coordinates.
// Also there is bool axis_relative_modes[] per axis flag.
static bool relative_mode = false;
static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
// Marking a line in the cmdbuffer. If false, the command is confirmed by sending an "OK" on the serial line.
static bool fromsd[BUFSIZE];
static int bufindr = 0;
static int bufindw = 0;
@ -498,11 +505,6 @@ void serial_echopair_P(const char *s_P, unsigned long v)
}
#endif //!SDSUPPORT
#ifdef MESH_BED_LEVELING
static void find_bed();
#endif
//adds an command to the main command buffer
//thats really done in a non-safe way.
//needs overworking someday
@ -636,6 +638,20 @@ void setup()
SERIAL_PROTOCOLLNPGM("start");
SERIAL_ECHO_START;
#if 0
SERIAL_ECHOLN("Reading eeprom from 0 to 100: start");
for (int i = 0; i < 4096; ++ i) {
int b = eeprom_read_byte((unsigned char*)i);
if (b != 255) {
SERIAL_ECHO(i);
SERIAL_ECHO(":");
SERIAL_ECHO(b);
SERIAL_ECHOLN("");
}
}
SERIAL_ECHOLN("Reading eeprom from 0 to 100: done");
#endif
// Check startup - does nothing if bootloader sets MCUSR to 0
byte mcu = MCUSR;
if(mcu & 1) SERIAL_ECHOLNRPGM(MSG_POWERUP);
@ -669,9 +685,6 @@ void setup()
{
fromsd[i] = false;
}
// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
Config_RetrieveSettings();
@ -995,7 +1008,9 @@ DEFINE_PGM_READ_ANY(signed char, byte);
#define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \
static const PROGMEM type array##_P[3] = \
{ X_##CONFIG, Y_##CONFIG, Z_##CONFIG }; \
static inline type array(int axis) \
static inline type array(int axis) \
{ return pgm_read_any(&array##_P[axis]); } \
type array##_ext(int axis) \
{ return pgm_read_any(&array##_P[axis]); }
XYZ_CONSTS_FROM_CONFIG(float, base_min_pos, MIN_POS);
@ -1506,6 +1521,7 @@ void process_commands()
// PRUSA GCODES
/*
if(code_seen('PRUSA')){
if(code_seen('Fir')){
@ -1519,12 +1535,15 @@ void process_commands()
lcd_force_language_selection();
} else if(code_seen('Lz')) {
EEPROM_save_B(EEPROM_BABYSTEP_Z,0);
} else if (code_seen('Cal')) {
lcd_calibration();
}
}
//else if (code_seen('Cal')) {
// lcd_calibration();
// }
}
else if(code_seen('G'))
else
*/
if(code_seen('G'))
{
switch((int)code_value())
{
@ -1786,7 +1805,6 @@ void process_commands()
mbl.active = 0;
#endif
saved_feedrate = feedrate;
saved_feedmultiply = feedmultiply;
feedmultiply = 100;
@ -1939,15 +1957,17 @@ void process_commands()
feedrate = max_feedrate[Z_AXIS];
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate, active_extruder);
st_synchronize();
#endif
#endif // defined (Z_RAISE_BEFORE_HOMING) && (Z_RAISE_BEFORE_HOMING > 0)
#ifdef MESH_BED_LEVELING // If Mesh bed leveling, moxve X&Y to safe position for home
if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] ))
{
HOMEAXIS(X);
HOMEAXIS(Y);
}
destination[X_AXIS] = MESH_MIN_X - X_PROBE_OFFSET_FROM_EXTRUDER;
destination[Y_AXIS] = MESH_MIN_Y - Y_PROBE_OFFSET_FROM_EXTRUDER;
if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] ))
{
HOMEAXIS(X);
HOMEAXIS(Y);
}
// 1st mesh bed leveling measurement point, corrected.
mbl.get_meas_xy(0, 0, destination[X_AXIS], destination[Y_AXIS], false);
// destination[X_AXIS] = MESH_MIN_X - X_PROBE_OFFSET_FROM_EXTRUDER;
// destination[Y_AXIS] = MESH_MIN_Y - Y_PROBE_OFFSET_FROM_EXTRUDER;
destination[Z_AXIS] = MESH_HOME_Z_SEARCH; // Set destination away from bed
feedrate = homing_feedrate[Z_AXIS]/10;
current_position[Z_AXIS] = 0;
@ -1959,11 +1979,11 @@ void process_commands()
current_position[Y_AXIS] = destination[Y_AXIS];
HOMEAXIS(Z);
_doMeshL = true;
#else
HOMEAXIS(Z);
#endif
#else // MESH_BED_LEVELING
HOMEAXIS(Z);
#endif // MESH_BED_LEVELING
}
#else // Z Safe mode activated.
#else // defined(Z_SAFE_HOMING): Z Safe mode activated.
if(home_all_axis) {
destination[X_AXIS] = round(Z_SAFE_HOMING_X_POINT - X_PROBE_OFFSET_FROM_EXTRUDER);
destination[Y_AXIS] = round(Z_SAFE_HOMING_Y_POINT - Y_PROBE_OFFSET_FROM_EXTRUDER);
@ -2005,10 +2025,8 @@ void process_commands()
SERIAL_ECHOLNRPGM(MSG_ZPROBE_OUT);
}
}
#endif
#endif
#endif // Z_SAFE_HOMING
#endif // Z_HOME_DIR < 0
if(code_seen(axis_codes[Z_AXIS])) {
if(code_value_long() != 0) {
@ -2046,15 +2064,17 @@ void process_commands()
}
}
#endif
#ifdef MESH_BED_LEVELING
if (code_seen('W'))
{
_doMeshL = false;
SERIAL_ECHOLN("G80 disabled");
SERIAL_ECHOLN("G80 disabled");
}
if ( _doMeshL)
{
st_synchronize();
enquecommand_P((PSTR("G80")));
}
#endif
@ -2270,7 +2290,7 @@ void process_commands()
// Firstly check if we know where we are
if ( !( axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS] ) ){
// We don't know where we are! HOME!
enquecommand_P((PSTR("G28")));
enquecommand_P((PSTR("G28 W0")));
enquecommand_P((PSTR("G80")));
break;
}
@ -2278,13 +2298,13 @@ void process_commands()
mbl.reset();
// Cycle through all points and probe them
current_position[X_AXIS] = MESH_MIN_X - X_PROBE_OFFSET_FROM_EXTRUDER;
current_position[Y_AXIS] = MESH_MIN_Y - Y_PROBE_OFFSET_FROM_EXTRUDER;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[X_AXIS]/30, active_extruder);
// First move up.
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]/60, active_extruder);
// The move to the first calibration point.
mbl.get_meas_xy(0, 0, current_position[X_AXIS], current_position[Y_AXIS], false);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[X_AXIS]/30, active_extruder);
// Wait until the move is finished.
st_synchronize();
int mesh_point = 0;
@ -2301,7 +2321,6 @@ void process_commands()
// Move Z to proper distance
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], Z_LIFT_FEEDRATE, active_extruder);
st_synchronize();
// Get cords of measuring point
@ -2309,26 +2328,19 @@ void process_commands()
iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag
current_position[X_AXIS] = mbl.get_meas_x(ix);
current_position[Y_AXIS] = mbl.get_meas_y(iy);
current_position[X_AXIS] -= X_PROBE_OFFSET_FROM_EXTRUDER;
current_position[Y_AXIS] -= Y_PROBE_OFFSET_FROM_EXTRUDER;
mbl.get_meas_xy(ix, iy, current_position[X_AXIS], current_position[Y_AXIS], false);
enable_endstops(false);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], XY_AXIS_FEEDRATE, active_extruder);
st_synchronize();
// Go down until endstop is hit
find_bed();
find_bed_induction_sensor_point_z();
mbl.set_z(ix, iy, current_position[Z_AXIS]);
if (!IS_SD_PRINTING)
{
custom_message_state--;
}
if (!IS_SD_PRINTING)
{
custom_message_state--;
}
mesh_point++;
}
@ -2343,16 +2355,14 @@ void process_commands()
plan_buffer_line(current_position[X_AXIS], current_position[X_AXIS], current_position[Z_AXIS], current_position[E_AXIS], XY_AXIS_FEEDRATE, active_extruder);
st_synchronize();
if(card.sdprinting || is_usb_printing )
{
if(card.sdprinting || is_usb_printing )
{
if(eeprom_read_byte((unsigned char*)EEPROM_BABYSTEP_Z_SET) == 0x01)
{
{
EEPROM_read_B(EEPROM_BABYSTEP_Z,&babystepLoad[2]);
babystepsTodo[Z_AXIS] = babystepLoad[2];
}
}
}
break;
@ -2388,7 +2398,7 @@ void process_commands()
case 82:
SERIAL_PROTOCOLLNPGM("Finding bed ");
setup_for_endstop_move();
find_bed();
find_bed_induction_sensor_point_z();
clean_up_after_endstop_move();
SERIAL_PROTOCOLPGM("Bed found at: ");
SERIAL_PROTOCOL_F(current_position[Z_AXIS], 5);
@ -2705,6 +2715,102 @@ void process_commands()
}
break;
case 44:
reset_bed_offset_and_skew();
break;
case 45: // M45: mesh_bed_calibration
{
// Firstly check if we know where we are
if ( !( axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) ){
// We don't know where we are! HOME!
enquecommand_P((PSTR("G28 X0 Y0")));
enquecommand_P((PSTR("M45")));
break;
}
setup_for_endstop_move();
find_bed_offset_and_skew();
// improve_bed_offset_and_skew();
clean_up_after_endstop_move();
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);
/*
current_position[X_AXIS] = X_MIN_POS+0.2;
current_position[Y_AXIS] = Y_MIN_POS+0.2;
current_position[Z_AXIS] = Z_MIN_POS;
plan_buffer_line(current_position[X_AXIS], current_position[X_AXIS], current_position[Z_AXIS], current_position[E_AXIS], XY_AXIS_FEEDRATE, active_extruder);
*/
st_synchronize();
}
break;
case 46: // M46: mesh_bed_calibration with manual Z up
{
// Firstly check if we know where we are
if ( !( axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) ){
// We don't know where we are! HOME!
enquecommand_P((PSTR("G28 X0 Y0 W0"))); // W0 tells G28 to not perform mesh bed leveling.
enquecommand_P((PSTR("M46")));
break;
}
lcd_update_enable(false);
if (lcd_calibrate_z_end_stop_manual()) {
mbl.reset();
setup_for_endstop_move();
find_bed_offset_and_skew();
// improve_bed_offset_and_skew(1);
clean_up_after_endstop_move();
// Print head up.
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);
st_synchronize();
}
// lcd_update_enable(true);
//lcd_implementation_clear();
//lcd_return_to_status();
// lcd_update();
// Mesh bed leveling.
// enquecommand_P((PSTR("G80")));
// The iprovement.
//enquecommand_P((PSTR("G80")));
enquecommand_P((PSTR("G28 X0 Y0 W0")));
enquecommand_P((PSTR("M47")));
}
break;
case 47:
{
// Firstly check if we know where we are
if ( !( axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) ) {
// We don't know where we are! HOME!
enquecommand_P((PSTR("G28 X0 Y0 W0"))); // W0 tells G28 to not perform mesh bed leveling.
enquecommand_P((PSTR("M47")));
break;
}
lcd_update_enable(false);
mbl.reset();
setup_for_endstop_move();
bool success = improve_bed_offset_and_skew(1);
clean_up_after_endstop_move();
// Print head up.
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);
st_synchronize();
lcd_update_enable(true);
lcd_update();
if (success)
// Mesh bed leveling.
enquecommand_P((PSTR("G80")));
break;
}
// case 47:
// lcd_diag_show_end_stops();
// break;
// M48 Z-Probe repeatability measurement function.
//
// Usage: M48 <n #_samples> <X X_position_for_samples> <Y Y_position_for_samples> <V Verbose_Level> <Engage_probe_for_each_reading> <L legs_of_movement_prior_to_doing_probe>
@ -4789,36 +4895,6 @@ void calculate_delta(float cartesian[3])
#ifdef MESH_BED_LEVELING
static void find_bed() {
feedrate = homing_feedrate[Z_AXIS];
// move down until you find the bed
float zPosition = -10;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
// we have to let the planner know where we are right now as it is not where we said to go.
zPosition = st_get_position_mm(Z_AXIS);
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]);
// move up the retract distance
zPosition += home_retract_mm(Z_AXIS);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
// move back down slowly to find bed
feedrate = homing_feedrate[Z_AXIS]/4;
zPosition -= home_retract_mm(Z_AXIS) * 2;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
// make sure the planner knows where we are as it may be a bit different than we last said to move to
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
void mesh_plan_buffer_line(const float &x, const float &y, const float &z, const float &e, const float &feed_rate, const uint8_t extruder) {
float dx = x - current_position[X_AXIS];
float dy = y - current_position[Y_AXIS];
@ -5467,4 +5543,21 @@ void calculate_volumetric_multipliers() {
#endif
#endif
}
void delay_keep_alive(int ms)
{
for (;;) {
manage_heater();
manage_inactivity();
lcd_update();
if (ms == 0)
break;
else if (ms >= 50) {
delay(50);
ms -= 50;
} else {
delay(ms);
ms = 0;
}
}
}

153
Firmware/langtool.pl Normal file
View file

@ -0,0 +1,153 @@
#!/usr/bin/perl
# Processes language_xx.h files into language.cpp and language.h
use strict;
use warnings;
my @langs = ("en","cz","it","es","pl");
sub parselang
{
my ($filename) = @_;
open(my $fh, '<:encoding(UTF-8)', $filename)
or die "Could not open file '$filename' $!";
# Create a new hash reference.
my $out = {};
while (my $line = <$fh>) {
chomp $line;
next if (index($line, 'MSG') == -1);
$line =~ /(?is)\#define\s*(\S*)\s*(.*)/;
my $symbol = $1;
my $v = $2;
next if (! defined $symbol or length($symbol) == 0);
# Trim whitespaces from both sides
$v =~ s/^\s+|\s+$//g;
#$string =~ s/" MACHINE_NAME "/Prusa i3/;
$v =~ s/" FIRMWARE_URL "/https:\/\/github.com\/prusa3d\/Prusa-i3-Plus\//;
$v =~ s/" PROTOCOL_VERSION "/1.0/;
$v =~ s/" STRINGIFY\(EXTRUDERS\) "/1/;
$v =~ s/" MACHINE_UUID "/00000000-0000-0000-0000-000000000000/;
${$out}{$symbol} = $v;
}
return $out;
}
my %texts;
my $num_languages = 0;
foreach my $lang (@langs) {
my $symbols = parselang("language_$lang.h");
foreach my $key (keys %{$symbols}) {
if (! (exists $texts{$key})) {
$texts{$key} = [];
}
my $strings = $texts{$key};
die "Symbol $key defined first in $lang, undefined in the preceding language files."
if (scalar(@$strings) != $num_languages);
push @$strings, ${$symbols}{$key};
}
$num_languages += 1;
foreach my $key (keys %texts) {
my $strings = $texts{$key};
if (scalar(@$strings) != $num_languages) {
# die "Symbol $key undefined in $lang."
print "Symbol $key undefined in $lang. Using the english variant.\n";
push @$strings, ${$strings}[0];
}
}
}
my $filename = 'language_all.h';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
# For the programmatic access to the program memory, read
# http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
print $fh <<END
#ifndef LANGUAGE_ALL_H
#define LANGUAGE_ALL_H
#define LANG_NUM (${num_languages})
extern unsigned char lang_selected;
#define LANG_TABLE_SELECT_EXPLICIT(TABLE, LANG) ((const char*)(pgm_read_ptr(TABLE + (LANG))))
#define LANG_TABLE_SELECT(TABLE) LANG_TABLE_SELECT_EXPLICIT(TABLE, lang_selected)
END
;
foreach my $key (sort(keys %texts)) {
print $fh "extern const char* const ${key}_LANG_TABLE[LANG_NUM];\n";
print $fh "#define $key LANG_TABLE_SELECT(${key}_LANG_TABLE)\n";
print $fh "#define ${key}_EXPLICIT(LANG) LANG_TABLE_SELECT_EXPLICIT(${key}_LANG_TABLE, LANG)\n"
if ($key eq "MSG_LANGUAGE_NAME" || $key eq "MSG_LANGUAGE_SELECT");
}
print $fh <<END
extern char* CAT2(const char *s1,const char *s2);
extern char* CAT4(const char *s1,const char *s2,const char *s3,const char *s4);
#endif //LANGUAGE_ALL.H
END
;
close $fh;
print ".h created\n";
$filename = 'language_all.cpp';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh <<'END'
#include <avr/pgmspace.h>
#include "configuration_prusa.h"
#include "language_all.h"
#define LCD_WIDTH 20
extern unsigned char lang_selected;
END
;
foreach my $key (sort(keys %texts)) {
my $strings = $texts{$key};
for (my $i = 0; $i <= $#{$strings}; $i ++) {
my $suffix = uc($langs[$i]);
print $fh "const char ${key}_${suffix}[] PROGMEM = ${$strings}[$i];\n";
}
print $fh "const char * const ${key}_LANG_TABLE[LANG_NUM] PROGMEM = {\n";
for (my $i = 0; $i <= $#{$strings}; $i ++) {
my $suffix = uc($langs[$i]);
print $fh "\t${key}_${suffix}";
print $fh ',' if $i < $#{$strings};
print $fh "\n";
}
print $fh "};\n\n";
}
print $fh <<'END'
char langbuffer[LCD_WIDTH+1];
char* CAT2(const char *s1,const char *s2) {
unsigned char len=0;
strncpy_P(langbuffer+len,s1,LCD_WIDTH-len);
len+=strlen_P(s1);
strncpy_P(langbuffer+len,s2,LCD_WIDTH-len);
return langbuffer;
}
char* CAT4(const char *s1,const char *s2,const char *s3,const char *s4) {
unsigned char len=0;
strncpy_P(langbuffer+len,s1,LCD_WIDTH-len);
len+=strlen_P(s1);
strncpy_P(langbuffer+len,s2,LCD_WIDTH-len);
len+=strlen_P(s2);
strncpy_P(langbuffer+len,s3,LCD_WIDTH-len);
len+=strlen_P(s3);
strncpy_P(langbuffer+len,s4,LCD_WIDTH-len);
return langbuffer;
}
END
;
print ".cpp created.\nDone!\n";

File diff suppressed because it is too large Load diff

View file

@ -1,267 +1,551 @@
#ifndef LANGUAGE_ALL_H
#define LANGUAGE_ALL_H
extern unsigned char lang_selected;
extern const char** MSG_ALL[];
#define WELCOME_MSG MSG_ALL[lang_selected][0]
#define MSG_SD_INSERTED MSG_ALL[lang_selected][1]
#define MSG_SD_REMOVED MSG_ALL[lang_selected][2]
#define MSG_MAIN MSG_ALL[lang_selected][3]
#define MSG_AUTOSTART MSG_ALL[lang_selected][4]
#define MSG_DISABLE_STEPPERS MSG_ALL[lang_selected][5]
#define MSG_AUTO_HOME MSG_ALL[lang_selected][6]
#define MSG_SET_HOME_OFFSETS MSG_ALL[lang_selected][7]
#define MSG_SET_ORIGIN MSG_ALL[lang_selected][8]
#define MSG_PREHEAT_PLA MSG_ALL[lang_selected][9]
#define MSG_PREHEAT_PLA0 MSG_ALL[lang_selected][10]
#define MSG_PREHEAT_PLA1 MSG_ALL[lang_selected][11]
#define MSG_PREHEAT_PLA2 MSG_ALL[lang_selected][12]
#define MSG_PREHEAT_PLA012 MSG_ALL[lang_selected][13]
#define MSG_PREHEAT_PLA_BEDONLY MSG_ALL[lang_selected][14]
#define MSG_PREHEAT_PLA_SETTINGS MSG_ALL[lang_selected][15]
#define MSG_PREHEAT_ABS MSG_ALL[lang_selected][16]
#define MSG_PREHEAT_ABS0 MSG_ALL[lang_selected][17]
#define MSG_PREHEAT_ABS1 MSG_ALL[lang_selected][18]
#define MSG_PREHEAT_ABS2 MSG_ALL[lang_selected][19]
#define MSG_PREHEAT_ABS012 MSG_ALL[lang_selected][20]
#define MSG_PREHEAT_ABS_BEDONLY MSG_ALL[lang_selected][21]
#define MSG_PREHEAT_ABS_SETTINGS MSG_ALL[lang_selected][22]
#define MSG_COOLDOWN MSG_ALL[lang_selected][23]
#define MSG_SWITCH_PS_ON MSG_ALL[lang_selected][24]
#define MSG_SWITCH_PS_OFF MSG_ALL[lang_selected][25]
#define MSG_EXTRUDE MSG_ALL[lang_selected][26]
#define MSG_RETRACT MSG_ALL[lang_selected][27]
#define MSG_MOVE_AXIS MSG_ALL[lang_selected][28]
#define MSG_MOVE_X MSG_ALL[lang_selected][29]
#define MSG_MOVE_Y MSG_ALL[lang_selected][30]
#define MSG_MOVE_Z MSG_ALL[lang_selected][31]
#define MSG_MOVE_E MSG_ALL[lang_selected][32]
#define MSG_MOVE_E1 MSG_ALL[lang_selected][33]
#define MSG_MOVE_E2 MSG_ALL[lang_selected][34]
#define MSG_MOVE_01MM MSG_ALL[lang_selected][35]
#define MSG_MOVE_1MM MSG_ALL[lang_selected][36]
#define MSG_MOVE_10MM MSG_ALL[lang_selected][37]
#define MSG_SPEED MSG_ALL[lang_selected][38]
#define MSG_NOZZLE MSG_ALL[lang_selected][39]
#define MSG_NOZZLE1 MSG_ALL[lang_selected][40]
#define MSG_NOZZLE2 MSG_ALL[lang_selected][41]
#define MSG_BED MSG_ALL[lang_selected][42]
#define MSG_FAN_SPEED MSG_ALL[lang_selected][43]
#define MSG_FLOW MSG_ALL[lang_selected][44]
#define MSG_FLOW0 MSG_ALL[lang_selected][45]
#define MSG_FLOW1 MSG_ALL[lang_selected][46]
#define MSG_FLOW2 MSG_ALL[lang_selected][47]
#define MSG_CONTROL MSG_ALL[lang_selected][48]
#define MSG_MIN MSG_ALL[lang_selected][49]
#define MSG_MAX MSG_ALL[lang_selected][50]
#define MSG_FACTOR MSG_ALL[lang_selected][51]
#define MSG_AUTOTEMP MSG_ALL[lang_selected][52]
#define MSG_ON MSG_ALL[lang_selected][53]
#define MSG_OFF MSG_ALL[lang_selected][54]
#define MSG_PID_P MSG_ALL[lang_selected][55]
#define MSG_PID_I MSG_ALL[lang_selected][56]
#define MSG_PID_D MSG_ALL[lang_selected][57]
#define MSG_PID_C MSG_ALL[lang_selected][58]
#define MSG_ACC MSG_ALL[lang_selected][59]
#define MSG_VXY_JERK MSG_ALL[lang_selected][60]
#define MSG_VZ_JERK MSG_ALL[lang_selected][61]
#define MSG_VE_JERK MSG_ALL[lang_selected][62]
#define MSG_VMAX MSG_ALL[lang_selected][63]
#define MSG_X MSG_ALL[lang_selected][64]
#define MSG_Y MSG_ALL[lang_selected][65]
#define MSG_Z MSG_ALL[lang_selected][66]
#define MSG_E MSG_ALL[lang_selected][67]
#define MSG_VMIN MSG_ALL[lang_selected][68]
#define MSG_VTRAV_MIN MSG_ALL[lang_selected][69]
#define MSG_AMAX MSG_ALL[lang_selected][70]
#define MSG_A_RETRACT MSG_ALL[lang_selected][71]
#define MSG_XSTEPS MSG_ALL[lang_selected][72]
#define MSG_YSTEPS MSG_ALL[lang_selected][73]
#define MSG_ZSTEPS MSG_ALL[lang_selected][74]
#define MSG_ESTEPS MSG_ALL[lang_selected][75]
#define MSG_TEMPERATURE MSG_ALL[lang_selected][76]
#define MSG_MOTION MSG_ALL[lang_selected][77]
#define MSG_VOLUMETRIC MSG_ALL[lang_selected][78]
#define MSG_VOLUMETRIC_ENABLED MSG_ALL[lang_selected][79]
#define MSG_FILAMENT_SIZE_EXTRUDER_0 MSG_ALL[lang_selected][80]
#define MSG_FILAMENT_SIZE_EXTRUDER_1 MSG_ALL[lang_selected][81]
#define MSG_FILAMENT_SIZE_EXTRUDER_2 MSG_ALL[lang_selected][82]
#define MSG_CONTRAST MSG_ALL[lang_selected][83]
#define MSG_STORE_EPROM MSG_ALL[lang_selected][84]
#define MSG_LOAD_EPROM MSG_ALL[lang_selected][85]
#define MSG_RESTORE_FAILSAFE MSG_ALL[lang_selected][86]
#define MSG_REFRESH MSG_ALL[lang_selected][87]
#define MSG_WATCH MSG_ALL[lang_selected][88]
#define MSG_PREPARE MSG_ALL[lang_selected][89]
#define MSG_TUNE MSG_ALL[lang_selected][90]
#define MSG_PAUSE_PRINT MSG_ALL[lang_selected][91]
#define MSG_RESUME_PRINT MSG_ALL[lang_selected][92]
#define MSG_STOP_PRINT MSG_ALL[lang_selected][93]
#define MSG_CARD_MENU MSG_ALL[lang_selected][94]
#define MSG_NO_CARD MSG_ALL[lang_selected][95]
#define MSG_DWELL MSG_ALL[lang_selected][96]
#define MSG_USERWAIT MSG_ALL[lang_selected][97]
#define MSG_RESUMING MSG_ALL[lang_selected][98]
#define MSG_PRINT_ABORTED MSG_ALL[lang_selected][99]
#define MSG_NO_MOVE MSG_ALL[lang_selected][100]
#define MSG_KILLED MSG_ALL[lang_selected][101]
#define MSG_STOPPED MSG_ALL[lang_selected][102]
#define MSG_CONTROL_RETRACT MSG_ALL[lang_selected][103]
#define MSG_CONTROL_RETRACT_SWAP MSG_ALL[lang_selected][104]
#define MSG_CONTROL_RETRACTF MSG_ALL[lang_selected][105]
#define MSG_CONTROL_RETRACT_ZLIFT MSG_ALL[lang_selected][106]
#define MSG_CONTROL_RETRACT_RECOVER MSG_ALL[lang_selected][107]
#define MSG_CONTROL_RETRACT_RECOVER_SWAP MSG_ALL[lang_selected][108]
#define MSG_CONTROL_RETRACT_RECOVERF MSG_ALL[lang_selected][109]
#define MSG_AUTORETRACT MSG_ALL[lang_selected][110]
#define MSG_FILAMENTCHANGE MSG_ALL[lang_selected][111]
#define MSG_INIT_SDCARD MSG_ALL[lang_selected][112]
#define MSG_CNG_SDCARD MSG_ALL[lang_selected][113]
#define MSG_ZPROBE_OUT MSG_ALL[lang_selected][114]
#define MSG_POSITION_UNKNOWN MSG_ALL[lang_selected][115]
#define MSG_ZPROBE_ZOFFSET MSG_ALL[lang_selected][116]
#define MSG_BABYSTEP_X MSG_ALL[lang_selected][117]
#define MSG_BABYSTEP_Y MSG_ALL[lang_selected][118]
#define MSG_BABYSTEP_Z MSG_ALL[lang_selected][119]
#define MSG_ENDSTOP_ABORT MSG_ALL[lang_selected][120]
#define MSG_ADJUSTZ MSG_ALL[lang_selected][121]
#define MSG_PICK_Z MSG_ALL[lang_selected][122]
#define MSG_HOMEYZ MSG_ALL[lang_selected][123]
#define MSG_HOMEYZ_PROGRESS MSG_ALL[lang_selected][124]
#define MSG_HOMEYZ_DONE MSG_ALL[lang_selected][125]
#define MSG_SETTINGS MSG_ALL[lang_selected][126]
#define MSG_PREHEAT MSG_ALL[lang_selected][127]
#define MSG_UNLOAD_FILAMENT MSG_ALL[lang_selected][128]
#define MSG_LOAD_FILAMENT MSG_ALL[lang_selected][129]
#define MSG_RECTRACT MSG_ALL[lang_selected][130]
#define MSG_ERROR MSG_ALL[lang_selected][131]
#define MSG_PREHEAT_NOZZLE MSG_ALL[lang_selected][132]
#define MSG_SUPPORT MSG_ALL[lang_selected][133]
#define MSG_CORRECTLY MSG_ALL[lang_selected][134]
#define MSG_YES MSG_ALL[lang_selected][135]
#define MSG_NO MSG_ALL[lang_selected][136]
#define MSG_NOT_LOADED MSG_ALL[lang_selected][137]
#define MSG_NOT_COLOR MSG_ALL[lang_selected][138]
#define MSG_LOADING_FILAMENT MSG_ALL[lang_selected][139]
#define MSG_PLEASE_WAIT MSG_ALL[lang_selected][140]
#define MSG_LOADING_COLOR MSG_ALL[lang_selected][141]
#define MSG_CHANGE_SUCCESS MSG_ALL[lang_selected][142]
#define MSG_PRESS MSG_ALL[lang_selected][143]
#define MSG_INSERT_FILAMENT MSG_ALL[lang_selected][144]
#define MSG_CHANGING_FILAMENT MSG_ALL[lang_selected][145]
#define MSG_SILENT_MODE_ON MSG_ALL[lang_selected][146]
#define MSG_SILENT_MODE_OFF MSG_ALL[lang_selected][147]
#define MSG_REBOOT MSG_ALL[lang_selected][148]
#define MSG_TAKE_EFFECT MSG_ALL[lang_selected][149]
#define MSG_Enqueing MSG_ALL[lang_selected][150]
#define MSG_POWERUP MSG_ALL[lang_selected][151]
#define MSG_EXTERNAL_RESET MSG_ALL[lang_selected][152]
#define MSG_BROWNOUT_RESET MSG_ALL[lang_selected][153]
#define MSG_WATCHDOG_RESET MSG_ALL[lang_selected][154]
#define MSG_SOFTWARE_RESET MSG_ALL[lang_selected][155]
#define MSG_AUTHOR MSG_ALL[lang_selected][156]
#define MSG_CONFIGURATION_VER MSG_ALL[lang_selected][157]
#define MSG_FREE_MEMORY MSG_ALL[lang_selected][158]
#define MSG_PLANNER_BUFFER_BYTES MSG_ALL[lang_selected][159]
#define MSG_OK MSG_ALL[lang_selected][160]
#define MSG_FILE_SAVED MSG_ALL[lang_selected][161]
#define MSG_ERR_LINE_NO MSG_ALL[lang_selected][162]
#define MSG_ERR_CHECKSUM_MISMATCH MSG_ALL[lang_selected][163]
#define MSG_ERR_NO_CHECKSUM MSG_ALL[lang_selected][164]
#define MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM MSG_ALL[lang_selected][165]
#define MSG_FILE_PRINTED MSG_ALL[lang_selected][166]
#define MSG_BEGIN_FILE_LIST MSG_ALL[lang_selected][167]
#define MSG_END_FILE_LIST MSG_ALL[lang_selected][168]
#define MSG_M104_INVALID_EXTRUDER MSG_ALL[lang_selected][169]
#define MSG_M105_INVALID_EXTRUDER MSG_ALL[lang_selected][170]
#define MSG_M200_INVALID_EXTRUDER MSG_ALL[lang_selected][171]
#define MSG_M218_INVALID_EXTRUDER MSG_ALL[lang_selected][172]
#define MSG_M221_INVALID_EXTRUDER MSG_ALL[lang_selected][173]
#define MSG_ERR_NO_THERMISTORS MSG_ALL[lang_selected][174]
#define MSG_M109_INVALID_EXTRUDER MSG_ALL[lang_selected][175]
#define MSG_HEATING MSG_ALL[lang_selected][176]
#define MSG_HEATING_COMPLETE MSG_ALL[lang_selected][177]
#define MSG_BED_HEATING MSG_ALL[lang_selected][178]
#define MSG_BED_DONE MSG_ALL[lang_selected][179]
#define MSG_M115_REPORT MSG_ALL[lang_selected][180]
#define MSG_COUNT_X MSG_ALL[lang_selected][181]
#define MSG_ERR_KILLED MSG_ALL[lang_selected][182]
#define MSG_ERR_STOPPED MSG_ALL[lang_selected][183]
#define MSG_RESEND MSG_ALL[lang_selected][184]
#define MSG_UNKNOWN_COMMAND MSG_ALL[lang_selected][185]
#define MSG_ACTIVE_EXTRUDER MSG_ALL[lang_selected][186]
#define MSG_INVALID_EXTRUDER MSG_ALL[lang_selected][187]
#define MSG_X_MIN MSG_ALL[lang_selected][188]
#define MSG_X_MAX MSG_ALL[lang_selected][189]
#define MSG_Y_MIN MSG_ALL[lang_selected][190]
#define MSG_Y_MAX MSG_ALL[lang_selected][191]
#define MSG_Z_MIN MSG_ALL[lang_selected][192]
#define MSG_Z_MAX MSG_ALL[lang_selected][193]
#define MSG_M119_REPORT MSG_ALL[lang_selected][194]
#define MSG_ENDSTOP_HIT MSG_ALL[lang_selected][195]
#define MSG_ENDSTOP_OPEN MSG_ALL[lang_selected][196]
#define MSG_HOTEND_OFFSET MSG_ALL[lang_selected][197]
#define MSG_SD_CANT_OPEN_SUBDIR MSG_ALL[lang_selected][198]
#define MSG_SD_INIT_FAIL MSG_ALL[lang_selected][199]
#define MSG_SD_VOL_INIT_FAIL MSG_ALL[lang_selected][200]
#define MSG_SD_OPENROOT_FAIL MSG_ALL[lang_selected][201]
#define MSG_SD_CARD_OK MSG_ALL[lang_selected][202]
#define MSG_SD_WORKDIR_FAIL MSG_ALL[lang_selected][203]
#define MSG_SD_OPEN_FILE_FAIL MSG_ALL[lang_selected][204]
#define MSG_SD_FILE_OPENED MSG_ALL[lang_selected][205]
#define MSG_SD_SIZE MSG_ALL[lang_selected][206]
#define MSG_SD_FILE_SELECTED MSG_ALL[lang_selected][207]
#define MSG_SD_WRITE_TO_FILE MSG_ALL[lang_selected][208]
#define MSG_SD_PRINTING_BYTE MSG_ALL[lang_selected][209]
#define MSG_SD_NOT_PRINTING MSG_ALL[lang_selected][210]
#define MSG_SD_ERR_WRITE_TO_FILE MSG_ALL[lang_selected][211]
#define MSG_SD_CANT_ENTER_SUBDIR MSG_ALL[lang_selected][212]
#define MSG_STEPPER_TOO_HIGH MSG_ALL[lang_selected][213]
#define MSG_ENDSTOPS_HIT MSG_ALL[lang_selected][214]
#define MSG_ERR_COLD_EXTRUDE_STOP MSG_ALL[lang_selected][215]
#define MSG_ERR_LONG_EXTRUDE_STOP MSG_ALL[lang_selected][216]
#define MSG_BABYSTEPPING_X MSG_ALL[lang_selected][217]
#define MSG_BABYSTEPPING_Y MSG_ALL[lang_selected][218]
#define MSG_BABYSTEPPING_Z MSG_ALL[lang_selected][219]
#define MSG_SERIAL_ERROR_MENU_STRUCTURE MSG_ALL[lang_selected][220]
#define MSG_LANGUAGE_NAME MSG_ALL[lang_selected][221]
#define MSG_LANGUAGE_SELECT MSG_ALL[lang_selected][222]
#define MSG_PRUSA3D MSG_ALL[lang_selected][223]
#define MSG_PRUSA3D_FORUM MSG_ALL[lang_selected][224]
#define MSG_PRUSA3D_HOWTO MSG_ALL[lang_selected][225]
#define MSG_SELFTEST_ERROR MSG_ALL[lang_selected][226]
#define MSG_SELFTEST_PLEASECHECK MSG_ALL[lang_selected][227]
#define MSG_SELFTEST_NOTCONNECTED MSG_ALL[lang_selected][228]
#define MSG_SELFTEST_HEATERTHERMISTOR MSG_ALL[lang_selected][229]
#define MSG_SELFTEST_BEDHEATER MSG_ALL[lang_selected][230]
#define MSG_SELFTEST_WIRINGERROR MSG_ALL[lang_selected][231]
#define MSG_SELFTEST_ENDSTOPS MSG_ALL[lang_selected][232]
#define MSG_SELFTEST_MOTOR MSG_ALL[lang_selected][233]
#define MSG_SELFTEST_ENDSTOP MSG_ALL[lang_selected][234]
#define MSG_SELFTEST_ENDSTOP_NOTHIT MSG_ALL[lang_selected][235]
#define MSG_SELFTEST_OK MSG_ALL[lang_selected][236]
#define MSG_STATS_TOTALFILAMENT MSG_ALL[lang_selected][237]
#define MSG_STATS_TOTALPRINTTIME MSG_ALL[lang_selected][238]
#define MSG_STATS_FILAMENTUSED MSG_ALL[lang_selected][239]
#define MSG_STATS_PRINTTIME MSG_ALL[lang_selected][240]
#define MSG_SELFTEST_START MSG_ALL[lang_selected][241]
#define MSG_SELFTEST_CHECK_ENDSTOPS MSG_ALL[lang_selected][242]
#define MSG_SELFTEST_CHECK_HOTEND MSG_ALL[lang_selected][243]
#define MSG_SELFTEST_CHECK_X MSG_ALL[lang_selected][244]
#define MSG_SELFTEST_CHECK_Y MSG_ALL[lang_selected][245]
#define MSG_SELFTEST_CHECK_Z MSG_ALL[lang_selected][246]
#define MSG_SELFTEST_CHECK_BED MSG_ALL[lang_selected][247]
#define MSG_SELFTEST_CHECK_ALLCORRECT MSG_ALL[lang_selected][248]
#define MSG_SELFTEST MSG_ALL[lang_selected][249]
#define MSG_SELFTEST_FAILED MSG_ALL[lang_selected][250]
#define MSG_STATISTICS MSG_ALL[lang_selected][251]
#define MSG_USB_PRINTING MSG_ALL[lang_selected][252]
#define LANGUAGE_NAME 221
#define LANGUAGE_SELECT 222
#define LANG_NUM 5
char* CAT2(const char *s1,const char *s2);
char* CAT4(const char *s1,const char *s2,const char *s3,const char *s4);
#endif //LANGUAGE_ALL.H
#ifndef LANGUAGE_ALL_H
#define LANGUAGE_ALL_H
#define LANG_NUM (5)
extern unsigned char lang_selected;
#define LANG_TABLE_SELECT_EXPLICIT(TABLE, LANG) ((const char*)(pgm_read_ptr(TABLE + (LANG))))
#define LANG_TABLE_SELECT(TABLE) LANG_TABLE_SELECT_EXPLICIT(TABLE, lang_selected)
extern const char* const MSG_ACC_LANG_TABLE[LANG_NUM];
#define MSG_ACC LANG_TABLE_SELECT(MSG_ACC_LANG_TABLE)
extern const char* const MSG_ACTIVE_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_ACTIVE_EXTRUDER LANG_TABLE_SELECT(MSG_ACTIVE_EXTRUDER_LANG_TABLE)
extern const char* const MSG_ADJUSTZ_LANG_TABLE[LANG_NUM];
#define MSG_ADJUSTZ LANG_TABLE_SELECT(MSG_ADJUSTZ_LANG_TABLE)
extern const char* const MSG_AMAX_LANG_TABLE[LANG_NUM];
#define MSG_AMAX LANG_TABLE_SELECT(MSG_AMAX_LANG_TABLE)
extern const char* const MSG_AUTHOR_LANG_TABLE[LANG_NUM];
#define MSG_AUTHOR LANG_TABLE_SELECT(MSG_AUTHOR_LANG_TABLE)
extern const char* const MSG_AUTORETRACT_LANG_TABLE[LANG_NUM];
#define MSG_AUTORETRACT LANG_TABLE_SELECT(MSG_AUTORETRACT_LANG_TABLE)
extern const char* const MSG_AUTOSTART_LANG_TABLE[LANG_NUM];
#define MSG_AUTOSTART LANG_TABLE_SELECT(MSG_AUTOSTART_LANG_TABLE)
extern const char* const MSG_AUTOTEMP_LANG_TABLE[LANG_NUM];
#define MSG_AUTOTEMP LANG_TABLE_SELECT(MSG_AUTOTEMP_LANG_TABLE)
extern const char* const MSG_AUTO_HOME_LANG_TABLE[LANG_NUM];
#define MSG_AUTO_HOME LANG_TABLE_SELECT(MSG_AUTO_HOME_LANG_TABLE)
extern const char* const MSG_A_RETRACT_LANG_TABLE[LANG_NUM];
#define MSG_A_RETRACT LANG_TABLE_SELECT(MSG_A_RETRACT_LANG_TABLE)
extern const char* const MSG_BABYSTEPPING_X_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEPPING_X LANG_TABLE_SELECT(MSG_BABYSTEPPING_X_LANG_TABLE)
extern const char* const MSG_BABYSTEPPING_Y_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEPPING_Y LANG_TABLE_SELECT(MSG_BABYSTEPPING_Y_LANG_TABLE)
extern const char* const MSG_BABYSTEPPING_Z_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEPPING_Z LANG_TABLE_SELECT(MSG_BABYSTEPPING_Z_LANG_TABLE)
extern const char* const MSG_BABYSTEP_X_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEP_X LANG_TABLE_SELECT(MSG_BABYSTEP_X_LANG_TABLE)
extern const char* const MSG_BABYSTEP_Y_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEP_Y LANG_TABLE_SELECT(MSG_BABYSTEP_Y_LANG_TABLE)
extern const char* const MSG_BABYSTEP_Z_LANG_TABLE[LANG_NUM];
#define MSG_BABYSTEP_Z LANG_TABLE_SELECT(MSG_BABYSTEP_Z_LANG_TABLE)
extern const char* const MSG_BED_LANG_TABLE[LANG_NUM];
#define MSG_BED LANG_TABLE_SELECT(MSG_BED_LANG_TABLE)
extern const char* const MSG_BED_DONE_LANG_TABLE[LANG_NUM];
#define MSG_BED_DONE LANG_TABLE_SELECT(MSG_BED_DONE_LANG_TABLE)
extern const char* const MSG_BED_HEATING_LANG_TABLE[LANG_NUM];
#define MSG_BED_HEATING LANG_TABLE_SELECT(MSG_BED_HEATING_LANG_TABLE)
extern const char* const MSG_BEGIN_FILE_LIST_LANG_TABLE[LANG_NUM];
#define MSG_BEGIN_FILE_LIST LANG_TABLE_SELECT(MSG_BEGIN_FILE_LIST_LANG_TABLE)
extern const char* const MSG_BROWNOUT_RESET_LANG_TABLE[LANG_NUM];
#define MSG_BROWNOUT_RESET LANG_TABLE_SELECT(MSG_BROWNOUT_RESET_LANG_TABLE)
extern const char* const MSG_CALIBRATE_BED_LANG_TABLE[LANG_NUM];
#define MSG_CALIBRATE_BED LANG_TABLE_SELECT(MSG_CALIBRATE_BED_LANG_TABLE)
extern const char* const MSG_CALIBRATE_BED_RESET_LANG_TABLE[LANG_NUM];
#define MSG_CALIBRATE_BED_RESET LANG_TABLE_SELECT(MSG_CALIBRATE_BED_RESET_LANG_TABLE)
extern const char* const MSG_CARD_MENU_LANG_TABLE[LANG_NUM];
#define MSG_CARD_MENU LANG_TABLE_SELECT(MSG_CARD_MENU_LANG_TABLE)
extern const char* const MSG_CHANGE_SUCCESS_LANG_TABLE[LANG_NUM];
#define MSG_CHANGE_SUCCESS LANG_TABLE_SELECT(MSG_CHANGE_SUCCESS_LANG_TABLE)
extern const char* const MSG_CHANGING_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_CHANGING_FILAMENT LANG_TABLE_SELECT(MSG_CHANGING_FILAMENT_LANG_TABLE)
extern const char* const MSG_CNG_SDCARD_LANG_TABLE[LANG_NUM];
#define MSG_CNG_SDCARD LANG_TABLE_SELECT(MSG_CNG_SDCARD_LANG_TABLE)
extern const char* const MSG_CONFIGURATION_VER_LANG_TABLE[LANG_NUM];
#define MSG_CONFIGURATION_VER LANG_TABLE_SELECT(MSG_CONFIGURATION_VER_LANG_TABLE)
extern const char* const MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE1_LANG_TABLE[LANG_NUM];
#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE1 LANG_TABLE_SELECT(MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE1_LANG_TABLE)
extern const char* const MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE2_LANG_TABLE[LANG_NUM];
#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE2 LANG_TABLE_SELECT(MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE2_LANG_TABLE)
extern const char* const MSG_CONTRAST_LANG_TABLE[LANG_NUM];
#define MSG_CONTRAST LANG_TABLE_SELECT(MSG_CONTRAST_LANG_TABLE)
extern const char* const MSG_CONTROL_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL LANG_TABLE_SELECT(MSG_CONTROL_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACTF_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACTF LANG_TABLE_SELECT(MSG_CONTROL_RETRACTF_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_RECOVER_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT_RECOVER LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_RECOVER_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_RECOVERF_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT_RECOVERF LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_RECOVERF_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_RECOVER_SWAP_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT_RECOVER_SWAP LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_RECOVER_SWAP_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_SWAP_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT_SWAP LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_SWAP_LANG_TABLE)
extern const char* const MSG_CONTROL_RETRACT_ZLIFT_LANG_TABLE[LANG_NUM];
#define MSG_CONTROL_RETRACT_ZLIFT LANG_TABLE_SELECT(MSG_CONTROL_RETRACT_ZLIFT_LANG_TABLE)
extern const char* const MSG_COOLDOWN_LANG_TABLE[LANG_NUM];
#define MSG_COOLDOWN LANG_TABLE_SELECT(MSG_COOLDOWN_LANG_TABLE)
extern const char* const MSG_CORRECTLY_LANG_TABLE[LANG_NUM];
#define MSG_CORRECTLY LANG_TABLE_SELECT(MSG_CORRECTLY_LANG_TABLE)
extern const char* const MSG_COUNT_X_LANG_TABLE[LANG_NUM];
#define MSG_COUNT_X LANG_TABLE_SELECT(MSG_COUNT_X_LANG_TABLE)
extern const char* const MSG_DISABLE_STEPPERS_LANG_TABLE[LANG_NUM];
#define MSG_DISABLE_STEPPERS LANG_TABLE_SELECT(MSG_DISABLE_STEPPERS_LANG_TABLE)
extern const char* const MSG_DWELL_LANG_TABLE[LANG_NUM];
#define MSG_DWELL LANG_TABLE_SELECT(MSG_DWELL_LANG_TABLE)
extern const char* const MSG_E_LANG_TABLE[LANG_NUM];
#define MSG_E LANG_TABLE_SELECT(MSG_E_LANG_TABLE)
extern const char* const MSG_ENDSTOPS_HIT_LANG_TABLE[LANG_NUM];
#define MSG_ENDSTOPS_HIT LANG_TABLE_SELECT(MSG_ENDSTOPS_HIT_LANG_TABLE)
extern const char* const MSG_ENDSTOP_ABORT_LANG_TABLE[LANG_NUM];
#define MSG_ENDSTOP_ABORT LANG_TABLE_SELECT(MSG_ENDSTOP_ABORT_LANG_TABLE)
extern const char* const MSG_ENDSTOP_HIT_LANG_TABLE[LANG_NUM];
#define MSG_ENDSTOP_HIT LANG_TABLE_SELECT(MSG_ENDSTOP_HIT_LANG_TABLE)
extern const char* const MSG_ENDSTOP_OPEN_LANG_TABLE[LANG_NUM];
#define MSG_ENDSTOP_OPEN LANG_TABLE_SELECT(MSG_ENDSTOP_OPEN_LANG_TABLE)
extern const char* const MSG_END_FILE_LIST_LANG_TABLE[LANG_NUM];
#define MSG_END_FILE_LIST LANG_TABLE_SELECT(MSG_END_FILE_LIST_LANG_TABLE)
extern const char* const MSG_ERROR_LANG_TABLE[LANG_NUM];
#define MSG_ERROR LANG_TABLE_SELECT(MSG_ERROR_LANG_TABLE)
extern const char* const MSG_ERR_CHECKSUM_MISMATCH_LANG_TABLE[LANG_NUM];
#define MSG_ERR_CHECKSUM_MISMATCH LANG_TABLE_SELECT(MSG_ERR_CHECKSUM_MISMATCH_LANG_TABLE)
extern const char* const MSG_ERR_COLD_EXTRUDE_STOP_LANG_TABLE[LANG_NUM];
#define MSG_ERR_COLD_EXTRUDE_STOP LANG_TABLE_SELECT(MSG_ERR_COLD_EXTRUDE_STOP_LANG_TABLE)
extern const char* const MSG_ERR_KILLED_LANG_TABLE[LANG_NUM];
#define MSG_ERR_KILLED LANG_TABLE_SELECT(MSG_ERR_KILLED_LANG_TABLE)
extern const char* const MSG_ERR_LINE_NO_LANG_TABLE[LANG_NUM];
#define MSG_ERR_LINE_NO LANG_TABLE_SELECT(MSG_ERR_LINE_NO_LANG_TABLE)
extern const char* const MSG_ERR_LONG_EXTRUDE_STOP_LANG_TABLE[LANG_NUM];
#define MSG_ERR_LONG_EXTRUDE_STOP LANG_TABLE_SELECT(MSG_ERR_LONG_EXTRUDE_STOP_LANG_TABLE)
extern const char* const MSG_ERR_NO_CHECKSUM_LANG_TABLE[LANG_NUM];
#define MSG_ERR_NO_CHECKSUM LANG_TABLE_SELECT(MSG_ERR_NO_CHECKSUM_LANG_TABLE)
extern const char* const MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM_LANG_TABLE[LANG_NUM];
#define MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM LANG_TABLE_SELECT(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM_LANG_TABLE)
extern const char* const MSG_ERR_NO_THERMISTORS_LANG_TABLE[LANG_NUM];
#define MSG_ERR_NO_THERMISTORS LANG_TABLE_SELECT(MSG_ERR_NO_THERMISTORS_LANG_TABLE)
extern const char* const MSG_ERR_STOPPED_LANG_TABLE[LANG_NUM];
#define MSG_ERR_STOPPED LANG_TABLE_SELECT(MSG_ERR_STOPPED_LANG_TABLE)
extern const char* const MSG_ESTEPS_LANG_TABLE[LANG_NUM];
#define MSG_ESTEPS LANG_TABLE_SELECT(MSG_ESTEPS_LANG_TABLE)
extern const char* const MSG_EXTERNAL_RESET_LANG_TABLE[LANG_NUM];
#define MSG_EXTERNAL_RESET LANG_TABLE_SELECT(MSG_EXTERNAL_RESET_LANG_TABLE)
extern const char* const MSG_EXTRUDE_LANG_TABLE[LANG_NUM];
#define MSG_EXTRUDE LANG_TABLE_SELECT(MSG_EXTRUDE_LANG_TABLE)
extern const char* const MSG_Enqueing_LANG_TABLE[LANG_NUM];
#define MSG_Enqueing LANG_TABLE_SELECT(MSG_Enqueing_LANG_TABLE)
extern const char* const MSG_FACTOR_LANG_TABLE[LANG_NUM];
#define MSG_FACTOR LANG_TABLE_SELECT(MSG_FACTOR_LANG_TABLE)
extern const char* const MSG_FAN_SPEED_LANG_TABLE[LANG_NUM];
#define MSG_FAN_SPEED LANG_TABLE_SELECT(MSG_FAN_SPEED_LANG_TABLE)
extern const char* const MSG_FILAMENTCHANGE_LANG_TABLE[LANG_NUM];
#define MSG_FILAMENTCHANGE LANG_TABLE_SELECT(MSG_FILAMENTCHANGE_LANG_TABLE)
extern const char* const MSG_FILAMENT_SIZE_EXTRUDER_0_LANG_TABLE[LANG_NUM];
#define MSG_FILAMENT_SIZE_EXTRUDER_0 LANG_TABLE_SELECT(MSG_FILAMENT_SIZE_EXTRUDER_0_LANG_TABLE)
extern const char* const MSG_FILAMENT_SIZE_EXTRUDER_1_LANG_TABLE[LANG_NUM];
#define MSG_FILAMENT_SIZE_EXTRUDER_1 LANG_TABLE_SELECT(MSG_FILAMENT_SIZE_EXTRUDER_1_LANG_TABLE)
extern const char* const MSG_FILAMENT_SIZE_EXTRUDER_2_LANG_TABLE[LANG_NUM];
#define MSG_FILAMENT_SIZE_EXTRUDER_2 LANG_TABLE_SELECT(MSG_FILAMENT_SIZE_EXTRUDER_2_LANG_TABLE)
extern const char* const MSG_FILE_PRINTED_LANG_TABLE[LANG_NUM];
#define MSG_FILE_PRINTED LANG_TABLE_SELECT(MSG_FILE_PRINTED_LANG_TABLE)
extern const char* const MSG_FILE_SAVED_LANG_TABLE[LANG_NUM];
#define MSG_FILE_SAVED LANG_TABLE_SELECT(MSG_FILE_SAVED_LANG_TABLE)
extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM];
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE)
extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM];
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE)
extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM];
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE)
extern const char* const MSG_FLOW_LANG_TABLE[LANG_NUM];
#define MSG_FLOW LANG_TABLE_SELECT(MSG_FLOW_LANG_TABLE)
extern const char* const MSG_FLOW0_LANG_TABLE[LANG_NUM];
#define MSG_FLOW0 LANG_TABLE_SELECT(MSG_FLOW0_LANG_TABLE)
extern const char* const MSG_FLOW1_LANG_TABLE[LANG_NUM];
#define MSG_FLOW1 LANG_TABLE_SELECT(MSG_FLOW1_LANG_TABLE)
extern const char* const MSG_FLOW2_LANG_TABLE[LANG_NUM];
#define MSG_FLOW2 LANG_TABLE_SELECT(MSG_FLOW2_LANG_TABLE)
extern const char* const MSG_FREE_MEMORY_LANG_TABLE[LANG_NUM];
#define MSG_FREE_MEMORY LANG_TABLE_SELECT(MSG_FREE_MEMORY_LANG_TABLE)
extern const char* const MSG_HEATING_LANG_TABLE[LANG_NUM];
#define MSG_HEATING LANG_TABLE_SELECT(MSG_HEATING_LANG_TABLE)
extern const char* const MSG_HEATING_COMPLETE_LANG_TABLE[LANG_NUM];
#define MSG_HEATING_COMPLETE LANG_TABLE_SELECT(MSG_HEATING_COMPLETE_LANG_TABLE)
extern const char* const MSG_HOMEYZ_LANG_TABLE[LANG_NUM];
#define MSG_HOMEYZ LANG_TABLE_SELECT(MSG_HOMEYZ_LANG_TABLE)
extern const char* const MSG_HOMEYZ_DONE_LANG_TABLE[LANG_NUM];
#define MSG_HOMEYZ_DONE LANG_TABLE_SELECT(MSG_HOMEYZ_DONE_LANG_TABLE)
extern const char* const MSG_HOMEYZ_PROGRESS_LANG_TABLE[LANG_NUM];
#define MSG_HOMEYZ_PROGRESS LANG_TABLE_SELECT(MSG_HOMEYZ_PROGRESS_LANG_TABLE)
extern const char* const MSG_HOTEND_OFFSET_LANG_TABLE[LANG_NUM];
#define MSG_HOTEND_OFFSET LANG_TABLE_SELECT(MSG_HOTEND_OFFSET_LANG_TABLE)
extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM];
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE)
extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM];
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE)
extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM];
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE)
extern const char* const MSG_INIT_SDCARD_LANG_TABLE[LANG_NUM];
#define MSG_INIT_SDCARD LANG_TABLE_SELECT(MSG_INIT_SDCARD_LANG_TABLE)
extern const char* const MSG_INSERT_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_INSERT_FILAMENT LANG_TABLE_SELECT(MSG_INSERT_FILAMENT_LANG_TABLE)
extern const char* const MSG_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_KILLED_LANG_TABLE[LANG_NUM];
#define MSG_KILLED LANG_TABLE_SELECT(MSG_KILLED_LANG_TABLE)
extern const char* const MSG_LANGUAGE_NAME_LANG_TABLE[LANG_NUM];
#define MSG_LANGUAGE_NAME LANG_TABLE_SELECT(MSG_LANGUAGE_NAME_LANG_TABLE)
#define MSG_LANGUAGE_NAME_EXPLICIT(LANG) LANG_TABLE_SELECT_EXPLICIT(MSG_LANGUAGE_NAME_LANG_TABLE, LANG)
extern const char* const MSG_LANGUAGE_SELECT_LANG_TABLE[LANG_NUM];
#define MSG_LANGUAGE_SELECT LANG_TABLE_SELECT(MSG_LANGUAGE_SELECT_LANG_TABLE)
#define MSG_LANGUAGE_SELECT_EXPLICIT(LANG) LANG_TABLE_SELECT_EXPLICIT(MSG_LANGUAGE_SELECT_LANG_TABLE, LANG)
extern const char* const MSG_LOADING_COLOR_LANG_TABLE[LANG_NUM];
#define MSG_LOADING_COLOR LANG_TABLE_SELECT(MSG_LOADING_COLOR_LANG_TABLE)
extern const char* const MSG_LOADING_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_LOADING_FILAMENT LANG_TABLE_SELECT(MSG_LOADING_FILAMENT_LANG_TABLE)
extern const char* const MSG_LOAD_EPROM_LANG_TABLE[LANG_NUM];
#define MSG_LOAD_EPROM LANG_TABLE_SELECT(MSG_LOAD_EPROM_LANG_TABLE)
extern const char* const MSG_LOAD_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_LOAD_FILAMENT LANG_TABLE_SELECT(MSG_LOAD_FILAMENT_LANG_TABLE)
extern const char* const MSG_M104_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M104_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M104_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_M105_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M105_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M105_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_M109_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M109_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M109_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_M115_REPORT_LANG_TABLE[LANG_NUM];
#define MSG_M115_REPORT LANG_TABLE_SELECT(MSG_M115_REPORT_LANG_TABLE)
extern const char* const MSG_M119_REPORT_LANG_TABLE[LANG_NUM];
#define MSG_M119_REPORT LANG_TABLE_SELECT(MSG_M119_REPORT_LANG_TABLE)
extern const char* const MSG_M200_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M200_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M200_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_M218_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M218_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M218_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_M221_INVALID_EXTRUDER_LANG_TABLE[LANG_NUM];
#define MSG_M221_INVALID_EXTRUDER LANG_TABLE_SELECT(MSG_M221_INVALID_EXTRUDER_LANG_TABLE)
extern const char* const MSG_MAIN_LANG_TABLE[LANG_NUM];
#define MSG_MAIN LANG_TABLE_SELECT(MSG_MAIN_LANG_TABLE)
extern const char* const MSG_MAX_LANG_TABLE[LANG_NUM];
#define MSG_MAX LANG_TABLE_SELECT(MSG_MAX_LANG_TABLE)
extern const char* const MSG_MIN_LANG_TABLE[LANG_NUM];
#define MSG_MIN LANG_TABLE_SELECT(MSG_MIN_LANG_TABLE)
extern const char* const MSG_MOTION_LANG_TABLE[LANG_NUM];
#define MSG_MOTION LANG_TABLE_SELECT(MSG_MOTION_LANG_TABLE)
extern const char* const MSG_MOVE_01MM_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_01MM LANG_TABLE_SELECT(MSG_MOVE_01MM_LANG_TABLE)
extern const char* const MSG_MOVE_10MM_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_10MM LANG_TABLE_SELECT(MSG_MOVE_10MM_LANG_TABLE)
extern const char* const MSG_MOVE_1MM_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_1MM LANG_TABLE_SELECT(MSG_MOVE_1MM_LANG_TABLE)
extern const char* const MSG_MOVE_AXIS_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_AXIS LANG_TABLE_SELECT(MSG_MOVE_AXIS_LANG_TABLE)
extern const char* const MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE1_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE1 LANG_TABLE_SELECT(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE1_LANG_TABLE)
extern const char* const MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE2_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE2 LANG_TABLE_SELECT(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE2_LANG_TABLE)
extern const char* const MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE3_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE3 LANG_TABLE_SELECT(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE3_LANG_TABLE)
extern const char* const MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE4_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE4 LANG_TABLE_SELECT(MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE4_LANG_TABLE)
extern const char* const MSG_MOVE_E_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_E LANG_TABLE_SELECT(MSG_MOVE_E_LANG_TABLE)
extern const char* const MSG_MOVE_E1_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_E1 LANG_TABLE_SELECT(MSG_MOVE_E1_LANG_TABLE)
extern const char* const MSG_MOVE_E2_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_E2 LANG_TABLE_SELECT(MSG_MOVE_E2_LANG_TABLE)
extern const char* const MSG_MOVE_X_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_X LANG_TABLE_SELECT(MSG_MOVE_X_LANG_TABLE)
extern const char* const MSG_MOVE_Y_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_Y LANG_TABLE_SELECT(MSG_MOVE_Y_LANG_TABLE)
extern const char* const MSG_MOVE_Z_LANG_TABLE[LANG_NUM];
#define MSG_MOVE_Z LANG_TABLE_SELECT(MSG_MOVE_Z_LANG_TABLE)
extern const char* const MSG_NO_LANG_TABLE[LANG_NUM];
#define MSG_NO LANG_TABLE_SELECT(MSG_NO_LANG_TABLE)
extern const char* const MSG_NOT_COLOR_LANG_TABLE[LANG_NUM];
#define MSG_NOT_COLOR LANG_TABLE_SELECT(MSG_NOT_COLOR_LANG_TABLE)
extern const char* const MSG_NOT_LOADED_LANG_TABLE[LANG_NUM];
#define MSG_NOT_LOADED LANG_TABLE_SELECT(MSG_NOT_LOADED_LANG_TABLE)
extern const char* const MSG_NOZZLE_LANG_TABLE[LANG_NUM];
#define MSG_NOZZLE LANG_TABLE_SELECT(MSG_NOZZLE_LANG_TABLE)
extern const char* const MSG_NOZZLE1_LANG_TABLE[LANG_NUM];
#define MSG_NOZZLE1 LANG_TABLE_SELECT(MSG_NOZZLE1_LANG_TABLE)
extern const char* const MSG_NOZZLE2_LANG_TABLE[LANG_NUM];
#define MSG_NOZZLE2 LANG_TABLE_SELECT(MSG_NOZZLE2_LANG_TABLE)
extern const char* const MSG_NO_CARD_LANG_TABLE[LANG_NUM];
#define MSG_NO_CARD LANG_TABLE_SELECT(MSG_NO_CARD_LANG_TABLE)
extern const char* const MSG_NO_MOVE_LANG_TABLE[LANG_NUM];
#define MSG_NO_MOVE LANG_TABLE_SELECT(MSG_NO_MOVE_LANG_TABLE)
extern const char* const MSG_OFF_LANG_TABLE[LANG_NUM];
#define MSG_OFF LANG_TABLE_SELECT(MSG_OFF_LANG_TABLE)
extern const char* const MSG_OK_LANG_TABLE[LANG_NUM];
#define MSG_OK LANG_TABLE_SELECT(MSG_OK_LANG_TABLE)
extern const char* const MSG_ON_LANG_TABLE[LANG_NUM];
#define MSG_ON LANG_TABLE_SELECT(MSG_ON_LANG_TABLE)
extern const char* const MSG_PAUSE_PRINT_LANG_TABLE[LANG_NUM];
#define MSG_PAUSE_PRINT LANG_TABLE_SELECT(MSG_PAUSE_PRINT_LANG_TABLE)
extern const char* const MSG_PICK_Z_LANG_TABLE[LANG_NUM];
#define MSG_PICK_Z LANG_TABLE_SELECT(MSG_PICK_Z_LANG_TABLE)
extern const char* const MSG_PID_C_LANG_TABLE[LANG_NUM];
#define MSG_PID_C LANG_TABLE_SELECT(MSG_PID_C_LANG_TABLE)
extern const char* const MSG_PID_D_LANG_TABLE[LANG_NUM];
#define MSG_PID_D LANG_TABLE_SELECT(MSG_PID_D_LANG_TABLE)
extern const char* const MSG_PID_I_LANG_TABLE[LANG_NUM];
#define MSG_PID_I LANG_TABLE_SELECT(MSG_PID_I_LANG_TABLE)
extern const char* const MSG_PID_P_LANG_TABLE[LANG_NUM];
#define MSG_PID_P LANG_TABLE_SELECT(MSG_PID_P_LANG_TABLE)
extern const char* const MSG_PLANNER_BUFFER_BYTES_LANG_TABLE[LANG_NUM];
#define MSG_PLANNER_BUFFER_BYTES LANG_TABLE_SELECT(MSG_PLANNER_BUFFER_BYTES_LANG_TABLE)
extern const char* const MSG_PLEASE_WAIT_LANG_TABLE[LANG_NUM];
#define MSG_PLEASE_WAIT LANG_TABLE_SELECT(MSG_PLEASE_WAIT_LANG_TABLE)
extern const char* const MSG_POSITION_UNKNOWN_LANG_TABLE[LANG_NUM];
#define MSG_POSITION_UNKNOWN LANG_TABLE_SELECT(MSG_POSITION_UNKNOWN_LANG_TABLE)
extern const char* const MSG_POWERUP_LANG_TABLE[LANG_NUM];
#define MSG_POWERUP LANG_TABLE_SELECT(MSG_POWERUP_LANG_TABLE)
extern const char* const MSG_PREHEAT_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT LANG_TABLE_SELECT(MSG_PREHEAT_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS LANG_TABLE_SELECT(MSG_PREHEAT_ABS_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS0_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS0 LANG_TABLE_SELECT(MSG_PREHEAT_ABS0_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS012_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS012 LANG_TABLE_SELECT(MSG_PREHEAT_ABS012_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS1_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS1 LANG_TABLE_SELECT(MSG_PREHEAT_ABS1_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS2_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS2 LANG_TABLE_SELECT(MSG_PREHEAT_ABS2_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS_BEDONLY_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS_BEDONLY LANG_TABLE_SELECT(MSG_PREHEAT_ABS_BEDONLY_LANG_TABLE)
extern const char* const MSG_PREHEAT_ABS_SETTINGS_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_ABS_SETTINGS LANG_TABLE_SELECT(MSG_PREHEAT_ABS_SETTINGS_LANG_TABLE)
extern const char* const MSG_PREHEAT_NOZZLE_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_NOZZLE LANG_TABLE_SELECT(MSG_PREHEAT_NOZZLE_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA LANG_TABLE_SELECT(MSG_PREHEAT_PLA_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA0_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA0 LANG_TABLE_SELECT(MSG_PREHEAT_PLA0_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA012_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA012 LANG_TABLE_SELECT(MSG_PREHEAT_PLA012_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA1_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA1 LANG_TABLE_SELECT(MSG_PREHEAT_PLA1_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA2_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA2 LANG_TABLE_SELECT(MSG_PREHEAT_PLA2_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA_BEDONLY_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA_BEDONLY LANG_TABLE_SELECT(MSG_PREHEAT_PLA_BEDONLY_LANG_TABLE)
extern const char* const MSG_PREHEAT_PLA_SETTINGS_LANG_TABLE[LANG_NUM];
#define MSG_PREHEAT_PLA_SETTINGS LANG_TABLE_SELECT(MSG_PREHEAT_PLA_SETTINGS_LANG_TABLE)
extern const char* const MSG_PREPARE_LANG_TABLE[LANG_NUM];
#define MSG_PREPARE LANG_TABLE_SELECT(MSG_PREPARE_LANG_TABLE)
extern const char* const MSG_PRESS_LANG_TABLE[LANG_NUM];
#define MSG_PRESS LANG_TABLE_SELECT(MSG_PRESS_LANG_TABLE)
extern const char* const MSG_PRINT_ABORTED_LANG_TABLE[LANG_NUM];
#define MSG_PRINT_ABORTED LANG_TABLE_SELECT(MSG_PRINT_ABORTED_LANG_TABLE)
extern const char* const MSG_PRUSA3D_LANG_TABLE[LANG_NUM];
#define MSG_PRUSA3D LANG_TABLE_SELECT(MSG_PRUSA3D_LANG_TABLE)
extern const char* const MSG_PRUSA3D_FORUM_LANG_TABLE[LANG_NUM];
#define MSG_PRUSA3D_FORUM LANG_TABLE_SELECT(MSG_PRUSA3D_FORUM_LANG_TABLE)
extern const char* const MSG_PRUSA3D_HOWTO_LANG_TABLE[LANG_NUM];
#define MSG_PRUSA3D_HOWTO LANG_TABLE_SELECT(MSG_PRUSA3D_HOWTO_LANG_TABLE)
extern const char* const MSG_REBOOT_LANG_TABLE[LANG_NUM];
#define MSG_REBOOT LANG_TABLE_SELECT(MSG_REBOOT_LANG_TABLE)
extern const char* const MSG_RECTRACT_LANG_TABLE[LANG_NUM];
#define MSG_RECTRACT LANG_TABLE_SELECT(MSG_RECTRACT_LANG_TABLE)
extern const char* const MSG_REFRESH_LANG_TABLE[LANG_NUM];
#define MSG_REFRESH LANG_TABLE_SELECT(MSG_REFRESH_LANG_TABLE)
extern const char* const MSG_RESEND_LANG_TABLE[LANG_NUM];
#define MSG_RESEND LANG_TABLE_SELECT(MSG_RESEND_LANG_TABLE)
extern const char* const MSG_RESTORE_FAILSAFE_LANG_TABLE[LANG_NUM];
#define MSG_RESTORE_FAILSAFE LANG_TABLE_SELECT(MSG_RESTORE_FAILSAFE_LANG_TABLE)
extern const char* const MSG_RESUME_PRINT_LANG_TABLE[LANG_NUM];
#define MSG_RESUME_PRINT LANG_TABLE_SELECT(MSG_RESUME_PRINT_LANG_TABLE)
extern const char* const MSG_RESUMING_LANG_TABLE[LANG_NUM];
#define MSG_RESUMING LANG_TABLE_SELECT(MSG_RESUMING_LANG_TABLE)
extern const char* const MSG_RETRACT_LANG_TABLE[LANG_NUM];
#define MSG_RETRACT LANG_TABLE_SELECT(MSG_RETRACT_LANG_TABLE)
extern const char* const MSG_SD_CANT_ENTER_SUBDIR_LANG_TABLE[LANG_NUM];
#define MSG_SD_CANT_ENTER_SUBDIR LANG_TABLE_SELECT(MSG_SD_CANT_ENTER_SUBDIR_LANG_TABLE)
extern const char* const MSG_SD_CANT_OPEN_SUBDIR_LANG_TABLE[LANG_NUM];
#define MSG_SD_CANT_OPEN_SUBDIR LANG_TABLE_SELECT(MSG_SD_CANT_OPEN_SUBDIR_LANG_TABLE)
extern const char* const MSG_SD_CARD_OK_LANG_TABLE[LANG_NUM];
#define MSG_SD_CARD_OK LANG_TABLE_SELECT(MSG_SD_CARD_OK_LANG_TABLE)
extern const char* const MSG_SD_ERR_WRITE_TO_FILE_LANG_TABLE[LANG_NUM];
#define MSG_SD_ERR_WRITE_TO_FILE LANG_TABLE_SELECT(MSG_SD_ERR_WRITE_TO_FILE_LANG_TABLE)
extern const char* const MSG_SD_FILE_OPENED_LANG_TABLE[LANG_NUM];
#define MSG_SD_FILE_OPENED LANG_TABLE_SELECT(MSG_SD_FILE_OPENED_LANG_TABLE)
extern const char* const MSG_SD_FILE_SELECTED_LANG_TABLE[LANG_NUM];
#define MSG_SD_FILE_SELECTED LANG_TABLE_SELECT(MSG_SD_FILE_SELECTED_LANG_TABLE)
extern const char* const MSG_SD_INIT_FAIL_LANG_TABLE[LANG_NUM];
#define MSG_SD_INIT_FAIL LANG_TABLE_SELECT(MSG_SD_INIT_FAIL_LANG_TABLE)
extern const char* const MSG_SD_INSERTED_LANG_TABLE[LANG_NUM];
#define MSG_SD_INSERTED LANG_TABLE_SELECT(MSG_SD_INSERTED_LANG_TABLE)
extern const char* const MSG_SD_NOT_PRINTING_LANG_TABLE[LANG_NUM];
#define MSG_SD_NOT_PRINTING LANG_TABLE_SELECT(MSG_SD_NOT_PRINTING_LANG_TABLE)
extern const char* const MSG_SD_OPENROOT_FAIL_LANG_TABLE[LANG_NUM];
#define MSG_SD_OPENROOT_FAIL LANG_TABLE_SELECT(MSG_SD_OPENROOT_FAIL_LANG_TABLE)
extern const char* const MSG_SD_OPEN_FILE_FAIL_LANG_TABLE[LANG_NUM];
#define MSG_SD_OPEN_FILE_FAIL LANG_TABLE_SELECT(MSG_SD_OPEN_FILE_FAIL_LANG_TABLE)
extern const char* const MSG_SD_PRINTING_BYTE_LANG_TABLE[LANG_NUM];
#define MSG_SD_PRINTING_BYTE LANG_TABLE_SELECT(MSG_SD_PRINTING_BYTE_LANG_TABLE)
extern const char* const MSG_SD_REMOVED_LANG_TABLE[LANG_NUM];
#define MSG_SD_REMOVED LANG_TABLE_SELECT(MSG_SD_REMOVED_LANG_TABLE)
extern const char* const MSG_SD_SIZE_LANG_TABLE[LANG_NUM];
#define MSG_SD_SIZE LANG_TABLE_SELECT(MSG_SD_SIZE_LANG_TABLE)
extern const char* const MSG_SD_VOL_INIT_FAIL_LANG_TABLE[LANG_NUM];
#define MSG_SD_VOL_INIT_FAIL LANG_TABLE_SELECT(MSG_SD_VOL_INIT_FAIL_LANG_TABLE)
extern const char* const MSG_SD_WORKDIR_FAIL_LANG_TABLE[LANG_NUM];
#define MSG_SD_WORKDIR_FAIL LANG_TABLE_SELECT(MSG_SD_WORKDIR_FAIL_LANG_TABLE)
extern const char* const MSG_SD_WRITE_TO_FILE_LANG_TABLE[LANG_NUM];
#define MSG_SD_WRITE_TO_FILE LANG_TABLE_SELECT(MSG_SD_WRITE_TO_FILE_LANG_TABLE)
extern const char* const MSG_SELFTEST_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST LANG_TABLE_SELECT(MSG_SELFTEST_LANG_TABLE)
extern const char* const MSG_SELFTEST_BEDHEATER_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_BEDHEATER LANG_TABLE_SELECT(MSG_SELFTEST_BEDHEATER_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_ALLCORRECT_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_ALLCORRECT LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_ALLCORRECT_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_BED_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_BED LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_BED_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_ENDSTOPS_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_ENDSTOPS LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_ENDSTOPS_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_HOTEND_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_HOTEND LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_HOTEND_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_X_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_X LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_X_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_Y_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_Y LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_Y_LANG_TABLE)
extern const char* const MSG_SELFTEST_CHECK_Z_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_CHECK_Z LANG_TABLE_SELECT(MSG_SELFTEST_CHECK_Z_LANG_TABLE)
extern const char* const MSG_SELFTEST_ENDSTOP_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_ENDSTOP LANG_TABLE_SELECT(MSG_SELFTEST_ENDSTOP_LANG_TABLE)
extern const char* const MSG_SELFTEST_ENDSTOPS_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_ENDSTOPS LANG_TABLE_SELECT(MSG_SELFTEST_ENDSTOPS_LANG_TABLE)
extern const char* const MSG_SELFTEST_ENDSTOP_NOTHIT_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_ENDSTOP_NOTHIT LANG_TABLE_SELECT(MSG_SELFTEST_ENDSTOP_NOTHIT_LANG_TABLE)
extern const char* const MSG_SELFTEST_ERROR_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_ERROR LANG_TABLE_SELECT(MSG_SELFTEST_ERROR_LANG_TABLE)
extern const char* const MSG_SELFTEST_FAILED_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_FAILED LANG_TABLE_SELECT(MSG_SELFTEST_FAILED_LANG_TABLE)
extern const char* const MSG_SELFTEST_HEATERTHERMISTOR_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_HEATERTHERMISTOR LANG_TABLE_SELECT(MSG_SELFTEST_HEATERTHERMISTOR_LANG_TABLE)
extern const char* const MSG_SELFTEST_MOTOR_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_MOTOR LANG_TABLE_SELECT(MSG_SELFTEST_MOTOR_LANG_TABLE)
extern const char* const MSG_SELFTEST_NOTCONNECTED_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_NOTCONNECTED LANG_TABLE_SELECT(MSG_SELFTEST_NOTCONNECTED_LANG_TABLE)
extern const char* const MSG_SELFTEST_OK_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_OK LANG_TABLE_SELECT(MSG_SELFTEST_OK_LANG_TABLE)
extern const char* const MSG_SELFTEST_PLEASECHECK_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_PLEASECHECK LANG_TABLE_SELECT(MSG_SELFTEST_PLEASECHECK_LANG_TABLE)
extern const char* const MSG_SELFTEST_START_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_START LANG_TABLE_SELECT(MSG_SELFTEST_START_LANG_TABLE)
extern const char* const MSG_SELFTEST_WIRINGERROR_LANG_TABLE[LANG_NUM];
#define MSG_SELFTEST_WIRINGERROR LANG_TABLE_SELECT(MSG_SELFTEST_WIRINGERROR_LANG_TABLE)
extern const char* const MSG_SERIAL_ERROR_MENU_STRUCTURE_LANG_TABLE[LANG_NUM];
#define MSG_SERIAL_ERROR_MENU_STRUCTURE LANG_TABLE_SELECT(MSG_SERIAL_ERROR_MENU_STRUCTURE_LANG_TABLE)
extern const char* const MSG_SETTINGS_LANG_TABLE[LANG_NUM];
#define MSG_SETTINGS LANG_TABLE_SELECT(MSG_SETTINGS_LANG_TABLE)
extern const char* const MSG_SET_HOME_OFFSETS_LANG_TABLE[LANG_NUM];
#define MSG_SET_HOME_OFFSETS LANG_TABLE_SELECT(MSG_SET_HOME_OFFSETS_LANG_TABLE)
extern const char* const MSG_SET_ORIGIN_LANG_TABLE[LANG_NUM];
#define MSG_SET_ORIGIN LANG_TABLE_SELECT(MSG_SET_ORIGIN_LANG_TABLE)
extern const char* const MSG_SILENT_MODE_OFF_LANG_TABLE[LANG_NUM];
#define MSG_SILENT_MODE_OFF LANG_TABLE_SELECT(MSG_SILENT_MODE_OFF_LANG_TABLE)
extern const char* const MSG_SILENT_MODE_ON_LANG_TABLE[LANG_NUM];
#define MSG_SILENT_MODE_ON LANG_TABLE_SELECT(MSG_SILENT_MODE_ON_LANG_TABLE)
extern const char* const MSG_SOFTWARE_RESET_LANG_TABLE[LANG_NUM];
#define MSG_SOFTWARE_RESET LANG_TABLE_SELECT(MSG_SOFTWARE_RESET_LANG_TABLE)
extern const char* const MSG_SPEED_LANG_TABLE[LANG_NUM];
#define MSG_SPEED LANG_TABLE_SELECT(MSG_SPEED_LANG_TABLE)
extern const char* const MSG_STATISTICS_LANG_TABLE[LANG_NUM];
#define MSG_STATISTICS LANG_TABLE_SELECT(MSG_STATISTICS_LANG_TABLE)
extern const char* const MSG_STATS_FILAMENTUSED_LANG_TABLE[LANG_NUM];
#define MSG_STATS_FILAMENTUSED LANG_TABLE_SELECT(MSG_STATS_FILAMENTUSED_LANG_TABLE)
extern const char* const MSG_STATS_PRINTTIME_LANG_TABLE[LANG_NUM];
#define MSG_STATS_PRINTTIME LANG_TABLE_SELECT(MSG_STATS_PRINTTIME_LANG_TABLE)
extern const char* const MSG_STATS_TOTALFILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_STATS_TOTALFILAMENT LANG_TABLE_SELECT(MSG_STATS_TOTALFILAMENT_LANG_TABLE)
extern const char* const MSG_STATS_TOTALPRINTTIME_LANG_TABLE[LANG_NUM];
#define MSG_STATS_TOTALPRINTTIME LANG_TABLE_SELECT(MSG_STATS_TOTALPRINTTIME_LANG_TABLE)
extern const char* const MSG_STEPPER_TOO_HIGH_LANG_TABLE[LANG_NUM];
#define MSG_STEPPER_TOO_HIGH LANG_TABLE_SELECT(MSG_STEPPER_TOO_HIGH_LANG_TABLE)
extern const char* const MSG_STOPPED_LANG_TABLE[LANG_NUM];
#define MSG_STOPPED LANG_TABLE_SELECT(MSG_STOPPED_LANG_TABLE)
extern const char* const MSG_STOP_PRINT_LANG_TABLE[LANG_NUM];
#define MSG_STOP_PRINT LANG_TABLE_SELECT(MSG_STOP_PRINT_LANG_TABLE)
extern const char* const MSG_STORE_EPROM_LANG_TABLE[LANG_NUM];
#define MSG_STORE_EPROM LANG_TABLE_SELECT(MSG_STORE_EPROM_LANG_TABLE)
extern const char* const MSG_SUPPORT_LANG_TABLE[LANG_NUM];
#define MSG_SUPPORT LANG_TABLE_SELECT(MSG_SUPPORT_LANG_TABLE)
extern const char* const MSG_SWITCH_PS_OFF_LANG_TABLE[LANG_NUM];
#define MSG_SWITCH_PS_OFF LANG_TABLE_SELECT(MSG_SWITCH_PS_OFF_LANG_TABLE)
extern const char* const MSG_SWITCH_PS_ON_LANG_TABLE[LANG_NUM];
#define MSG_SWITCH_PS_ON LANG_TABLE_SELECT(MSG_SWITCH_PS_ON_LANG_TABLE)
extern const char* const MSG_TAKE_EFFECT_LANG_TABLE[LANG_NUM];
#define MSG_TAKE_EFFECT LANG_TABLE_SELECT(MSG_TAKE_EFFECT_LANG_TABLE)
extern const char* const MSG_TEMPERATURE_LANG_TABLE[LANG_NUM];
#define MSG_TEMPERATURE LANG_TABLE_SELECT(MSG_TEMPERATURE_LANG_TABLE)
extern const char* const MSG_TUNE_LANG_TABLE[LANG_NUM];
#define MSG_TUNE LANG_TABLE_SELECT(MSG_TUNE_LANG_TABLE)
extern const char* const MSG_UNKNOWN_COMMAND_LANG_TABLE[LANG_NUM];
#define MSG_UNKNOWN_COMMAND LANG_TABLE_SELECT(MSG_UNKNOWN_COMMAND_LANG_TABLE)
extern const char* const MSG_UNLOAD_FILAMENT_LANG_TABLE[LANG_NUM];
#define MSG_UNLOAD_FILAMENT LANG_TABLE_SELECT(MSG_UNLOAD_FILAMENT_LANG_TABLE)
extern const char* const MSG_USB_PRINTING_LANG_TABLE[LANG_NUM];
#define MSG_USB_PRINTING LANG_TABLE_SELECT(MSG_USB_PRINTING_LANG_TABLE)
extern const char* const MSG_USERWAIT_LANG_TABLE[LANG_NUM];
#define MSG_USERWAIT LANG_TABLE_SELECT(MSG_USERWAIT_LANG_TABLE)
extern const char* const MSG_VE_JERK_LANG_TABLE[LANG_NUM];
#define MSG_VE_JERK LANG_TABLE_SELECT(MSG_VE_JERK_LANG_TABLE)
extern const char* const MSG_VMAX_LANG_TABLE[LANG_NUM];
#define MSG_VMAX LANG_TABLE_SELECT(MSG_VMAX_LANG_TABLE)
extern const char* const MSG_VMIN_LANG_TABLE[LANG_NUM];
#define MSG_VMIN LANG_TABLE_SELECT(MSG_VMIN_LANG_TABLE)
extern const char* const MSG_VOLUMETRIC_LANG_TABLE[LANG_NUM];
#define MSG_VOLUMETRIC LANG_TABLE_SELECT(MSG_VOLUMETRIC_LANG_TABLE)
extern const char* const MSG_VOLUMETRIC_ENABLED_LANG_TABLE[LANG_NUM];
#define MSG_VOLUMETRIC_ENABLED LANG_TABLE_SELECT(MSG_VOLUMETRIC_ENABLED_LANG_TABLE)
extern const char* const MSG_VTRAV_MIN_LANG_TABLE[LANG_NUM];
#define MSG_VTRAV_MIN LANG_TABLE_SELECT(MSG_VTRAV_MIN_LANG_TABLE)
extern const char* const MSG_VXY_JERK_LANG_TABLE[LANG_NUM];
#define MSG_VXY_JERK LANG_TABLE_SELECT(MSG_VXY_JERK_LANG_TABLE)
extern const char* const MSG_VZ_JERK_LANG_TABLE[LANG_NUM];
#define MSG_VZ_JERK LANG_TABLE_SELECT(MSG_VZ_JERK_LANG_TABLE)
extern const char* const MSG_WATCH_LANG_TABLE[LANG_NUM];
#define MSG_WATCH LANG_TABLE_SELECT(MSG_WATCH_LANG_TABLE)
extern const char* const MSG_WATCHDOG_RESET_LANG_TABLE[LANG_NUM];
#define MSG_WATCHDOG_RESET LANG_TABLE_SELECT(MSG_WATCHDOG_RESET_LANG_TABLE)
extern const char* const MSG_X_LANG_TABLE[LANG_NUM];
#define MSG_X LANG_TABLE_SELECT(MSG_X_LANG_TABLE)
extern const char* const MSG_XSTEPS_LANG_TABLE[LANG_NUM];
#define MSG_XSTEPS LANG_TABLE_SELECT(MSG_XSTEPS_LANG_TABLE)
extern const char* const MSG_X_MAX_LANG_TABLE[LANG_NUM];
#define MSG_X_MAX LANG_TABLE_SELECT(MSG_X_MAX_LANG_TABLE)
extern const char* const MSG_X_MIN_LANG_TABLE[LANG_NUM];
#define MSG_X_MIN LANG_TABLE_SELECT(MSG_X_MIN_LANG_TABLE)
extern const char* const MSG_Y_LANG_TABLE[LANG_NUM];
#define MSG_Y LANG_TABLE_SELECT(MSG_Y_LANG_TABLE)
extern const char* const MSG_YES_LANG_TABLE[LANG_NUM];
#define MSG_YES LANG_TABLE_SELECT(MSG_YES_LANG_TABLE)
extern const char* const MSG_YSTEPS_LANG_TABLE[LANG_NUM];
#define MSG_YSTEPS LANG_TABLE_SELECT(MSG_YSTEPS_LANG_TABLE)
extern const char* const MSG_Y_MAX_LANG_TABLE[LANG_NUM];
#define MSG_Y_MAX LANG_TABLE_SELECT(MSG_Y_MAX_LANG_TABLE)
extern const char* const MSG_Y_MIN_LANG_TABLE[LANG_NUM];
#define MSG_Y_MIN LANG_TABLE_SELECT(MSG_Y_MIN_LANG_TABLE)
extern const char* const MSG_Z_LANG_TABLE[LANG_NUM];
#define MSG_Z LANG_TABLE_SELECT(MSG_Z_LANG_TABLE)
extern const char* const MSG_ZPROBE_OUT_LANG_TABLE[LANG_NUM];
#define MSG_ZPROBE_OUT LANG_TABLE_SELECT(MSG_ZPROBE_OUT_LANG_TABLE)
extern const char* const MSG_ZPROBE_ZOFFSET_LANG_TABLE[LANG_NUM];
#define MSG_ZPROBE_ZOFFSET LANG_TABLE_SELECT(MSG_ZPROBE_ZOFFSET_LANG_TABLE)
extern const char* const MSG_ZSTEPS_LANG_TABLE[LANG_NUM];
#define MSG_ZSTEPS LANG_TABLE_SELECT(MSG_ZSTEPS_LANG_TABLE)
extern const char* const MSG_Z_MAX_LANG_TABLE[LANG_NUM];
#define MSG_Z_MAX LANG_TABLE_SELECT(MSG_Z_MAX_LANG_TABLE)
extern const char* const MSG_Z_MIN_LANG_TABLE[LANG_NUM];
#define MSG_Z_MIN LANG_TABLE_SELECT(MSG_Z_MIN_LANG_TABLE)
extern const char* const WELCOME_MSG_LANG_TABLE[LANG_NUM];
#define WELCOME_MSG LANG_TABLE_SELECT(WELCOME_MSG_LANG_TABLE)
extern char* CAT2(const char *s1,const char *s2);
extern char* CAT4(const char *s1,const char *s2,const char *s3,const char *s4);
#endif //LANGUAGE_ALL.H

View file

@ -271,6 +271,22 @@
#define MSG_HOMEYZ_PROGRESS "Calibrating Z"
#define MSG_HOMEYZ_DONE "Calibration done"
#define MSG_CALIBRATE_BED "Calibrate bed"
#define MSG_CALIBRATE_BED_RESET "Reset bed calibration"
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE1 "Calibrating the machine."
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE2 "Please move the Z carriage up"
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE3 "to the end stoppers."
#define MSG_MOVE_CARRIAGE_TO_THE_TOP_LINE4 "Click when done."
#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE1 "Are both left and right Z carriages"
#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP_LINE2 "touching the end stops?"
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 "Searching calibration"
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2 "point "
#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3 "of 4"
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 "Improving calibration"
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 "point "
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3 "of 9"
#endif // LANGUAGE_EN_H

View file

@ -0,0 +1,761 @@
#include "Marlin.h"
#include "Configuration.h"
#include "language_all.h"
#include "mesh_bed_calibration.h"
#include "mesh_bed_leveling.h"
#include "stepper.h"
#include "ultralcd.h"
// #include "qr_solve.h"
extern float home_retract_mm_ext(int axis);
static inline void go_xyz(float x, float y, float z, float fr)
{
plan_buffer_line(x, y, z, current_position[E_AXIS], fr, active_extruder);
st_synchronize();
}
static inline void go_xy(float x, float y, float fr)
{
plan_buffer_line(x, y, current_position[Z_AXIS], current_position[E_AXIS], fr, active_extruder);
st_synchronize();
}
static inline void go_to_current(float fr)
{
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], fr, active_extruder);
st_synchronize();
}
static inline void update_current_position_xyz()
{
current_position[X_AXIS] = st_get_position_mm(X_AXIS);
current_position[Y_AXIS] = st_get_position_mm(Y_AXIS);
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
// At the current position, find the Z stop.
inline void find_bed_induction_sensor_point_z()
{
bool endstops_enabled = enable_endstops(true);
bool endstop_z_enabled = enable_z_endstop(false);
// move down until you find the bed
current_position[Z_AXIS] = -10;
go_to_current(homing_feedrate[Z_AXIS]/60);
// we have to let the planner know where we are right now as it is not where we said to go.
update_current_position_xyz();
// move up the retract distance
current_position[Z_AXIS] += home_retract_mm_ext(Z_AXIS);
go_to_current(homing_feedrate[Z_AXIS]/60);
// move back down slowly to find bed
current_position[Z_AXIS] -= home_retract_mm_ext(Z_AXIS) * 2;
go_to_current(homing_feedrate[Z_AXIS]/(4*60));
// we have to let the planner know where we are right now as it is not where we said to go.
update_current_position_xyz();
enable_endstops(endstops_enabled);
enable_z_endstop(endstop_z_enabled);
}
// Search around the current_position[X,Y],
// look for the induction sensor response.
// Adjust the current_position[X,Y,Z] to the center of the target dot and its response Z coordinate.
#define FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS (8.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_Z_STEP (0.5f)
inline bool find_bed_induction_sensor_point_xy()
{
float feedrate = homing_feedrate[X_AXIS] / 60.f;
bool found = false;
{
float x0 = current_position[X_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
float x1 = current_position[X_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
float y0 = 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 i;
if (x0 < X_MIN_POS)
x0 = X_MIN_POS;
if (x1 > X_MAX_POS)
x1 = X_MAX_POS;
if (y0 < Y_MIN_POS)
y0 = Y_MIN_POS;
if (y1 > Y_MAX_POS)
y1 = Y_MAX_POS;
nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP));
enable_endstops(false);
bool dir_positive = true;
// go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
// Continously lower the Z axis.
endstops_hit_on_purpose();
enable_z_endstop(true);
while (current_position[Z_AXIS] > -10.f) {
// Do nsteps_y zig-zag movements.
current_position[Y_AXIS] = y0;
for (i = 0; i < nsteps_y; current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++ i) {
// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
dir_positive = ! dir_positive;
if (endstop_z_hit_on_purpose())
goto endloop;
}
for (i = 0; i < nsteps_y; current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++ i) {
// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
dir_positive = ! dir_positive;
if (endstop_z_hit_on_purpose())
goto endloop;
}
}
endloop:
// SERIAL_ECHOLN("First hit");
// we have to let the planner know where we are right now as it is not where we said to go.
update_current_position_xyz();
// Search in this plane for the first hit. Zig-zag first in X, then in Y axis.
for (int8_t iter = 0; iter < 3; ++ iter) {
if (iter > 0) {
// Slightly lower the Z axis to get a reliable trigger.
current_position[Z_AXIS] -= 0.02f;
go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
}
// Do nsteps_y zig-zag movements.
float a, b;
enable_endstops(false);
enable_z_endstop(false);
current_position[Y_AXIS] = y0;
go_xy(x0, current_position[Y_AXIS], feedrate);
enable_z_endstop(true);
found = false;
for (i = 0, dir_positive = true; i < nsteps_y; current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++ i, dir_positive = ! dir_positive) {
go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
if (endstop_z_hit_on_purpose()) {
found = true;
break;
}
}
update_current_position_xyz();
if (! found) {
// SERIAL_ECHOLN("Search in Y - not found");
continue;
}
// SERIAL_ECHOLN("Search in Y - found");
a = current_position[Y_AXIS];
enable_z_endstop(false);
current_position[Y_AXIS] = y1;
go_xy(x0, current_position[Y_AXIS], feedrate);
enable_z_endstop(true);
found = false;
for (i = 0, dir_positive = true; i < nsteps_y; current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++ i, dir_positive = ! dir_positive) {
go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
if (endstop_z_hit_on_purpose()) {
found = true;
break;
}
}
update_current_position_xyz();
if (! found) {
// SERIAL_ECHOLN("Search in Y2 - not found");
continue;
}
// SERIAL_ECHOLN("Search in Y2 - found");
b = current_position[Y_AXIS];
current_position[Y_AXIS] = 0.5f * (a + b);
// Search in the X direction along a cross.
found = false;
enable_z_endstop(false);
go_xy(x0, current_position[Y_AXIS], feedrate);
enable_z_endstop(true);
go_xy(x1, current_position[Y_AXIS], feedrate);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose()) {
// SERIAL_ECHOLN("Search X span 0 - not found");
continue;
}
// SERIAL_ECHOLN("Search X span 0 - found");
a = current_position[X_AXIS];
enable_z_endstop(false);
go_xy(x1, current_position[Y_AXIS], feedrate);
enable_z_endstop(true);
go_xy(x0, current_position[Y_AXIS], feedrate);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose()) {
// SERIAL_ECHOLN("Search X span 1 - not found");
continue;
}
// SERIAL_ECHOLN("Search X span 1 - found");
b = current_position[X_AXIS];
// Go to the center.
enable_z_endstop(false);
current_position[X_AXIS] = 0.5f * (a + b);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
found = true;
#if 1
// Search in the Y direction along a cross.
found = false;
enable_z_endstop(false);
go_xy(current_position[X_AXIS], y0, feedrate);
enable_z_endstop(true);
go_xy(current_position[X_AXIS], y1, feedrate);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose()) {
// SERIAL_ECHOLN("Search Y2 span 0 - not found");
continue;
}
// SERIAL_ECHOLN("Search Y2 span 0 - found");
a = current_position[Y_AXIS];
enable_z_endstop(false);
go_xy(current_position[X_AXIS], y1, feedrate);
enable_z_endstop(true);
go_xy(current_position[X_AXIS], y0, feedrate);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose()) {
// SERIAL_ECHOLN("Search Y2 span 1 - not found");
continue;
}
// SERIAL_ECHOLN("Search Y2 span 1 - found");
b = current_position[Y_AXIS];
// Go to the center.
enable_z_endstop(false);
current_position[Y_AXIS] = 0.5f * (a + b);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
found = true;
#endif
break;
}
}
enable_z_endstop(false);
return found;
}
// Search around the current_position[X,Y,Z].
// It is expected, that the induction sensor is switched on at the current position.
// Look around this center point by painting a star around the point.
inline bool improve_bed_induction_sensor_point()
{
static const float search_radius = 8.f;
bool endstops_enabled = enable_endstops(false);
bool endstop_z_enabled = enable_z_endstop(false);
bool found = false;
float feedrate = homing_feedrate[X_AXIS] / 60.f;
float center_old_x = current_position[X_AXIS];
float center_old_y = current_position[Y_AXIS];
float center_x = 0.f;
float center_y = 0.f;
for (uint8_t iter = 0; iter < 4; ++ iter) {
switch (iter) {
case 0:
destination[X_AXIS] = center_old_x - search_radius * 0.707;
destination[Y_AXIS] = center_old_y - search_radius * 0.707;
break;
case 1:
destination[X_AXIS] = center_old_x + search_radius * 0.707;
destination[Y_AXIS] = center_old_y + search_radius * 0.707;
break;
case 2:
destination[X_AXIS] = center_old_x + search_radius * 0.707;
destination[Y_AXIS] = center_old_y - search_radius * 0.707;
break;
case 3:
default:
destination[X_AXIS] = center_old_x - search_radius * 0.707;
destination[Y_AXIS] = center_old_y + search_radius * 0.707;
break;
}
// Trim the vector from center_old_[x,y] to destination[x,y] by the bed dimensions.
float vx = destination[X_AXIS] - center_old_x;
float vy = destination[Y_AXIS] - center_old_y;
float l = sqrt(vx*vx+vy*vy);
float t;
if (destination[X_AXIS] < X_MIN_POS) {
// Exiting the bed at xmin.
t = (center_x - X_MIN_POS) / l;
destination[X_AXIS] = X_MIN_POS;
destination[Y_AXIS] = center_old_y + t * vy;
} else if (destination[X_AXIS] > X_MAX_POS) {
// Exiting the bed at xmax.
t = (X_MAX_POS - center_x) / l;
destination[X_AXIS] = X_MAX_POS;
destination[Y_AXIS] = center_old_y + t * vy;
}
if (destination[Y_AXIS] < Y_MIN_POS) {
// Exiting the bed at ymin.
t = (center_y - Y_MIN_POS) / l;
destination[X_AXIS] = center_old_x + t * vx;
destination[Y_AXIS] = Y_MIN_POS;
} else if (destination[Y_AXIS] > Y_MAX_POS) {
// Exiting the bed at xmax.
t = (Y_MAX_POS - center_y) / l;
destination[X_AXIS] = center_old_x + t * vx;
destination[Y_AXIS] = Y_MAX_POS;
}
// Move away from the measurement point.
enable_endstops(false);
go_xy(destination[X_AXIS], destination[Y_AXIS], feedrate);
// Move towards the measurement point, until the induction sensor triggers.
enable_endstops(true);
go_xy(center_old_x, center_old_y, feedrate);
update_current_position_xyz();
center_x += current_position[X_AXIS];
center_y += current_position[Y_AXIS];
}
// Calculate the new center, move to the new center.
center_x /= 4.f;
center_y /= 4.f;
current_position[X_AXIS] = center_x;
current_position[Y_AXIS] = center_y;
enable_endstops(false);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
enable_endstops(endstops_enabled);
enable_z_endstop(endstop_z_enabled);
return found;
}
// Search around the current_position[X,Y,Z].
// It is expected, that the induction sensor is switched on at the current position.
// Look around this center point by painting a star around the point.
#define IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS (8.f)
inline bool improve_bed_induction_sensor_point2(bool lift_z_on_min_y)
{
float center_old_x = current_position[X_AXIS];
float center_old_y = current_position[Y_AXIS];
float a, b;
enable_endstops(false);
{
float x0 = center_old_x - IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS;
float x1 = center_old_x + IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS;
if (x0 < X_MIN_POS)
x0 = X_MIN_POS;
if (x1 > X_MAX_POS)
x1 = X_MAX_POS;
// Search in the X direction along a cross.
enable_z_endstop(false);
go_xy(x0, current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
enable_z_endstop(true);
go_xy(x1, current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose())
return false;
a = current_position[X_AXIS];
enable_z_endstop(false);
go_xy(x1, current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
enable_z_endstop(true);
go_xy(x0, current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose())
return false;
b = current_position[X_AXIS];
// Go to the center.
enable_z_endstop(false);
current_position[X_AXIS] = 0.5f * (a + b);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
}
{
float y0 = center_old_y - IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS;
float y1 = center_old_y + IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS;
if (y0 < Y_MIN_POS)
y0 = Y_MIN_POS;
if (y1 > Y_MAX_POS)
y1 = Y_MAX_POS;
// Search in the Y direction along a cross.
enable_z_endstop(false);
go_xy(current_position[X_AXIS], y0, homing_feedrate[X_AXIS] / 60.f);
if (lift_z_on_min_y) {
// The first row of points are very close to the end stop.
// Lift the sensor to disengage the trigger. This is necessary because of the sensor hysteresis.
go_xyz(current_position[X_AXIS], y0, current_position[Z_AXIS]+5.f, homing_feedrate[Z_AXIS] / 60.f);
// and go back.
go_xyz(current_position[X_AXIS], y0, current_position[Z_AXIS], homing_feedrate[Z_AXIS] / 60.f);
}
if (lift_z_on_min_y && (READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING) == 1) {
// Already triggering before we started the move.
// Shift the trigger point slightly outwards.
a = current_position[Y_AXIS] - 1.5f;
} else {
enable_z_endstop(true);
go_xy(current_position[X_AXIS], y1, homing_feedrate[X_AXIS] / 60.f);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose())
return false;
a = current_position[Y_AXIS];
}
enable_z_endstop(false);
go_xy(current_position[X_AXIS], y1, homing_feedrate[X_AXIS] / 60.f);
enable_z_endstop(true);
go_xy(current_position[X_AXIS], y0, homing_feedrate[X_AXIS] / 60.f);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose())
return false;
b = current_position[Y_AXIS];
// Go to the center.
enable_z_endstop(false);
current_position[Y_AXIS] = 0.5f * (a + b);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
}
return true;
}
#define MESH_BED_CALIBRATION_SHOW_LCD
bool find_bed_offset_and_skew()
{
// Reusing the z_values memory for the measurement cache.
// 7x7=49 floats, good for 16 (x,y,z) vectors.
float *pts = &mbl.z_values[0][0];
float *vec_x = pts + 3 * 4;
float *vec_y = vec_x + 3;
float *cntr = vec_y + 3;
memset(pts, 0, sizeof(float) * 7 * 7);
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
lcd_implementation_clear();
lcd_print_at_PGM(0, 0, MSG_FIND_BED_OFFSET_AND_SKEW_LINE1);
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Collect the rear 2x3 points.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
for (int k = 0; k < 4; ++ k) {
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
lcd_print_at_PGM(0, 1, MSG_FIND_BED_OFFSET_AND_SKEW_LINE2);
lcd_implementation_print(k+1);
lcd_print_at_PGM(0, 2, MSG_FIND_BED_OFFSET_AND_SKEW_LINE3);
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
int i, j;
switch (k) {
case 0: i = 1; j = 0; break;
case 1: i = 2; j = 1; break;
case 2: i = 1; j = 2; break;
case 3: i = 0; j = 1; break;
}
float *pt = pts + k * 3;
// Go up to z_initial.
go_to_current(homing_feedrate[Z_AXIS] / 60.f);
// Go to the measurement point position.
mbl.get_meas_xy(i, j, current_position[X_AXIS], current_position[Y_AXIS], true); // use default, uncorrected coordinates
go_to_current(homing_feedrate[X_AXIS] / 60.f);
if (! find_bed_induction_sensor_point_xy())
return false;
find_bed_induction_sensor_point_z();
pt[0] = current_position[X_AXIS];
pt[1] = current_position[Y_AXIS];
pt[2] = current_position[Z_AXIS];
// Start searching for the other points at 3mm above the last point.
current_position[Z_AXIS] += 3.f;
cntr[0] += pt[0];
cntr[1] += pt[1];
cntr[2] += pt[2];
}
// Average the X and Y vectors. They may not be perpendicular, if the printer is built incorrectly.
{
float len;
// Average the center point.
cntr[0] *= 1.f/4.f;
cntr[1] *= 1.f/4.f;
cntr[2] *= 1.f/4.f;
// Average the X vector.
vec_x[0] = (pts[3 * 1 + 0] - pts[3 * 3 + 0]) / 2.f;
vec_x[1] = (pts[3 * 1 + 1] - pts[3 * 3 + 1]) / 2.f;
len = sqrt(vec_x[0]*vec_x[0] + vec_x[1]*vec_x[1]);
if (0) {
// if (len < MEAS_NUM_X_DIST) {
// Scale the vector up to MEAS_NUM_X_DIST lenght.
float factor = MEAS_NUM_X_DIST / len;
vec_x[0] *= factor;
vec_x[0] *= factor;
} else {
// The vector is longer than MEAS_NUM_X_DIST. The X/Y axes are skewed.
// Verify the maximum skew?
}
// Average the Y vector.
vec_y[0] = (pts[3 * 2 + 0] - pts[3 * 0 + 0]) / 2.f;
vec_y[1] = (pts[3 * 2 + 1] - pts[3 * 0 + 1]) / 2.f;
len = sqrt(vec_y[0]*vec_y[0] + vec_y[1]*vec_y[1]);
if (0) {
// if (len < MEAS_NUM_Y_DIST) {
// Scale the vector up to MEAS_NUM_X_DIST lenght.
float factor = MEAS_NUM_Y_DIST / len;
vec_y[1] *= factor;
vec_y[1] *= factor;
} else {
// The vector is longer than MEAS_NUM_X_DIST. The X/Y axes are skewed.
// Verify the maximum skew?
}
// Fearlessly store the calibration values into the eeprom.
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0), cntr [0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4), cntr [1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0), vec_x[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4), vec_x[1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0), vec_y[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4), vec_y[1]);
#if 0
SERIAL_ECHOLN("Calibration done.");
SERIAL_ECHO("Center: ");
SERIAL_ECHO(cntr[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(cntr[1]);
SERIAL_ECHO(", x: ");
SERIAL_ECHO(vec_x[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_x[1]);
SERIAL_ECHO(", y: ");
SERIAL_ECHO(vec_y[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_y[1]);
SERIAL_ECHOLN("");
#endif
}
return true;
}
bool improve_bed_offset_and_skew(int8_t method)
{
// Reusing the z_values memory for the measurement cache.
// 7x7=49 floats, good for 16 (x,y,z) vectors.
float *pts = &mbl.z_values[0][0];
float *vec_x = pts + 2 * 9;
float *vec_y = vec_x + 2;
float *cntr = vec_y + 2;
memset(pts, 0, sizeof(float) * 7 * 7);
bool endstops_enabled = enable_endstops(false);
bool endstop_z_enabled = enable_z_endstop(false);
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
lcd_implementation_clear();
lcd_print_at_PGM(0, 0, MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1);
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Collect a matrix of 9x9 points.
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
int ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
int iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag
// Print the decrasing ID of the measurement point.
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
lcd_print_at_PGM(0, 1, MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2);
lcd_implementation_print_at(7, 1, mesh_point+1);
lcd_print_at_PGM(0, 2, MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3);
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Move up.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
enable_endstops(false);
enable_z_endstop(false);
go_to_current(homing_feedrate[Z_AXIS]/60);
// Go to the measurement point.
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
mbl.get_meas_xy(ix, iy, current_position[X_AXIS], current_position[Y_AXIS], false);
go_to_current(homing_feedrate[X_AXIS]/60);
// Find its Z position by running the normal vertical search.
// delay_keep_alive(3000);
find_bed_induction_sensor_point_z();
// delay_keep_alive(3000);
// Improve the point position by searching its center in a current plane.
int8_t n_errors = 3;
for (int8_t iter = 0; iter < 4; ++ iter) {
bool found = false;
switch (method) {
case 0: found = improve_bed_induction_sensor_point(); break;
case 1: found = improve_bed_induction_sensor_point2(iy == 0); break;
default: break;
}
if (! found) {
if (n_errors -- == 0) {
// Give up.
goto canceled;
} else {
// Try to move the Z axis down a bit to increase a chance of the sensor to trigger.
current_position[Z_AXIS] -= 0.025f;
enable_endstops(false);
enable_z_endstop(false);
go_to_current(homing_feedrate[Z_AXIS]);
}
}
}
// delay_keep_alive(3000);
float *pt = pts + 2 * (ix + iy * 3);
pt[0] = current_position[X_AXIS];
pt[1] = current_position[Y_AXIS];
cntr[0] += pt[0];
cntr[1] += pt[1];
}
// Average the X and Y vectors. They may not be perpendicular, if the printer is built incorrectly.
// Average the center point.
cntr[0] *= 1.f/9.f;
cntr[1] *= 1.f/9.f;
// Average the X vector.
vec_x[0] = (pts[2 * 2 + 0] - pts[2 * 0 + 0] + pts[2 * 5 + 0] - pts[2 * 3 + 0] + pts[2 * 8 + 0] - pts[2 * 6 + 0]) / 6.f;
vec_x[1] = (pts[2 * 2 + 1] - pts[2 * 0 + 1] + pts[2 * 5 + 1] - pts[2 * 3 + 1] + pts[2 * 8 + 1] - pts[2 * 6 + 1]) / 6.f;
// Average the Y vector.
vec_y[0] = (pts[2 * 6 + 0] - pts[2 * 0 + 0] + pts[2 * 7 + 0] - pts[2 * 1 + 0] + pts[2 * 8 + 0] - pts[2 * 2 + 0]) / 6.f;
vec_y[1] = (pts[2 * 6 + 1] - pts[2 * 0 + 1] + pts[2 * 7 + 1] - pts[2 * 1 + 1] + pts[2 * 8 + 1] - pts[2 * 2 + 1]) / 6.f;
#if 1
// Fearlessly store the calibration values into the eeprom.
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0), cntr [0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4), cntr [1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0), vec_x[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4), vec_x[1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0), vec_y[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4), vec_y[1]);
#endif
#if 0
// and let us know the result.
SERIAL_ECHOLN("Calibration done.");
SERIAL_ECHO("Center: ");
SERIAL_ECHO(cntr[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(cntr[1]);
SERIAL_ECHO(", x: ");
SERIAL_ECHO(vec_x[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_x[1]);
SERIAL_ECHO(", y: ");
SERIAL_ECHO(vec_y[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_y[1]);
SERIAL_ECHOLN("");
#endif
enable_endstops(endstops_enabled);
enable_z_endstop(endstop_z_enabled);
return true;
canceled:
enable_endstops(endstops_enabled);
enable_z_endstop(endstop_z_enabled);
return false;
}
void reset_bed_offset_and_skew()
{
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+0), 0x0FFFFFFFF);
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+4), 0x0FFFFFFFF);
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +0), 0x0FFFFFFFF);
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +4), 0x0FFFFFFFF);
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +0), 0x0FFFFFFFF);
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +4), 0x0FFFFFFFF);
}
static const float[9][2] PROGMEM bed_points = {
};
bool calculate_machine_skew_and_offset_LS(
// Matrix of 9 2D points (18 floats)
float *pts,
// Resulting correction matrix.
float *vec_x,
float *vec_y,
float *cntr,
// Temporary values, 49-18-(2*3)=25 floats
float *temp
{
{
// Create covariance matrix for A, collect the right hand side b.
float A[3][3] = { 0.f };
float b[3] = { 0.f };
float acc;
for (uint8_t r = 0; r < 3; ++ r) {
for (uint8_t c = 0; c < 3; ++ c) {
acc = 0;
for (uint8_t i = 0; i < 9; ++ i) {
float a = (r == 2) ? 1.f : pts[2 * i + r];
float b = (c == 2) ? 1.f : pts[2 * i + c];
acc += a * b;
}
A[r][c] = acc;
}
acc = 0.f;
for (uint8_t i = 0; i < 9; ++ i) {
float a = (r == 2) ? 1.f : pts[2 * i + r];
float b = pgm_read_float(&coeff2[i][0]);
acc += a * b;
}
b[r] = acc;
}
// Solve the linear equation for ax, bx, cx.
float x[3] = { 0.f };
for (uint8_t iter = 0; iter < 100; ++ iter) {
x[0] = (b[0] - A[1] * x[1] - A[2] * x[2]) / A[0];
x[1] = (b[1] - A[0] * x[0] - A[2] * x[2]) / A[1];
x[2] = (b[2] - A[0] * x[0] - A[1] * x[1]) / A[2];
}
// Store the result to the output variables.
vec_x[0] = x[0];
vec_y[0] = x[1];
cntr[0] = x[2];
// Recalculate b for the y values.
for (uint8_t r = 0; r < 3; ++ r) {
acc = 0.f;
for (uint8_t i = 0; i < 9; ++ i) {
float a = (r == 2) ? 1.f : pts[2 * i + r];
float b = pgm_read_float(&coeff2[i][1]);
acc += a * b;
}
b[r] = acc;
}
// Solve the linear equation for ay, by, cy.
x[0] = 0.f, x[1] = 0.f; x[2] = 0.f;
for (uint8_t iter = 0; iter < 100; ++ iter) {
x[0] = (b[0] - A[1] * x[1] - A[2] * x[2]) / A[0];
x[1] = (b[1] - A[0] * x[0] - A[2] * x[2]) / A[1];
x[2] = (b[2] - A[0] * x[0] - A[1] * x[1]) / A[2];
}
// Store the result to the output variables.
vec_x[1] = x[0];
vec_y[1] = x[1];
cntr[1] = x[2];
}
// Normalize the vectors. We expect, that the machine axes may be skewed a bit, but the distances are correct.
// l shall be very close to 1 already.
float l = sqrt(vec_x[0]*vec_x[0] + vec_x[1] * vec_x[1]);
vec_x[0] /= l;
vec_x[1] /= l;
l = sqrt(vec_y[0]*vec_y[0] + vec_y[1] * vec_y[1]);
vec_y[0] /= l;
vec_y[1] /= l;
// Invert the transformation matrix made of vec_x, vec_y and cntr.
}

View file

@ -0,0 +1,11 @@
#ifndef MESH_BED_CALIBRATION_H
#define MESH_BED_CALIBRATION_H
extern void find_bed_induction_sensor_point_z();
extern bool find_bed_induction_sensor_point_xy();
extern bool find_bed_offset_and_skew();
extern bool improve_bed_offset_and_skew(int8_t method);
extern void reset_bed_offset_and_skew();
#endif /* MESH_BED_CALIBRATION_H */

View file

@ -1,4 +1,5 @@
#include "mesh_bed_leveling.h"
#include "Configuration.h"
#ifdef MESH_BED_LEVELING
@ -13,6 +14,77 @@ void mesh_bed_leveling::reset() {
z_values[y][x] = 0;
}
static inline bool vec_undef(const float v[2])
{
const uint32_t *vx = (const uint32_t*)v;
return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF;
}
void mesh_bed_leveling::get_meas_xy(int ix, int iy, float &x, float &y, bool use_default)
{
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))
};
if (use_default || vec_undef(cntr) || vec_undef(vec_x) || vec_undef(vec_y)) {
// Default, uncorrected positions of the calibration points. Works well for correctly built printers.
x = float(MESH_MIN_X) + float(MEAS_NUM_X_DIST) * float(ix) - X_PROBE_OFFSET_FROM_EXTRUDER;
//FIXME
//x -= 5.f;
y = float(MESH_MIN_Y) + float(MEAS_NUM_Y_DIST) * float(iy) - Y_PROBE_OFFSET_FROM_EXTRUDER;
} else {
#if 0
SERIAL_ECHO("Running bed leveling. Calibration data: ");
SERIAL_ECHO(cntr[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(cntr[1]);
SERIAL_ECHO(", x: ");
SERIAL_ECHO(vec_x[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_x[1]);
SERIAL_ECHO(", y: ");
SERIAL_ECHO(vec_y[0]);
SERIAL_ECHO(",");
SERIAL_ECHO(vec_y[1]);
SERIAL_ECHOLN("");
#endif
x = cntr[0];
y = cntr[1];
if (ix < 1) {
x -= vec_x[0];
y -= vec_x[1];
} else if (ix > 1) {
x += vec_x[0];
y += vec_x[1];
}
if (iy < 1) {
x -= vec_y[0];
y -= vec_y[1];
} else if (iy > 1) {
x += vec_y[0];
y += vec_y[1];
}
#if 0
SERIAL_ECHO("Calibration point position: ");
SERIAL_ECHO(x);
SERIAL_ECHO(",");
SERIAL_ECHO(y);
SERIAL_ECHOLN("");
#endif
}
}
#if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1
// Works for an odd number of MESH_NUM_X_POINTS and MESH_NUM_Y_POINTS
void mesh_bed_leveling::upsample_3x3()

View file

@ -21,11 +21,13 @@ public:
void upsample_3x3();
#endif
float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); }
float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); }
static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); }
static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); }
float get_meas_x(int i) { return float(MESH_MIN_X) + float(MEAS_NUM_X_DIST) * float(i); }
float get_meas_y(int i) { return float(MESH_MIN_Y) + float(MEAS_NUM_Y_DIST) * float(i); }
// Measurement point for the Z probe.
// If use_default=true, then the default positions for a correctly built printer are used.
// Otherwise a correction matrix is pulled from the EEPROM if available.
static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default);
void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; }

View file

@ -23,7 +23,7 @@
* Rambo Pin Assignments 1.3
******************************************************************/
#if MOTHERBOARD == 302
#define MINI-RAMBO
#define MINI_RAMBO
#endif
#if MOTHERBOARD == 301 || MOTHERBOARD == 302
@ -109,7 +109,7 @@
#else
#define HEATER_2_PIN -1
#endif
#ifdef MINI-RAMBO
#ifdef MINI_RAMBO
#define ELECTRONICS "RAMBo13a"

View file

@ -86,6 +86,7 @@ static bool old_z_min_endstop=false;
static bool old_z_max_endstop=false;
static bool check_endstops = true;
static bool check_z_endstop = false;
int8_t SilentMode;
@ -209,16 +210,35 @@ void checkHitEndstops()
}
}
void endstops_hit_on_purpose()
bool endstops_hit_on_purpose()
{
bool hit = endstop_x_hit || endstop_y_hit || endstop_z_hit;
endstop_x_hit=false;
endstop_y_hit=false;
endstop_z_hit=false;
return hit;
}
void enable_endstops(bool check)
bool endstop_z_hit_on_purpose()
{
bool hit = endstop_z_hit;
endstop_z_hit=false;
return hit;
}
bool enable_endstops(bool check)
{
bool old = check_endstops;
check_endstops = check;
return old;
}
bool enable_z_endstop(bool check)
{
bool old = check_z_endstop;
check_z_endstop = check;
endstop_z_hit=false;
return old;
}
// __________________________
@ -496,7 +516,7 @@ ISR(TIMER1_COMPA_vect)
#endif
count_direction[Z_AXIS]=-1;
CHECK_ENDSTOPS
if(check_endstops && ! check_z_endstop)
{
#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
@ -531,6 +551,21 @@ ISR(TIMER1_COMPA_vect)
}
}
// Supporting stopping on a trigger of the Z-stop induction sensor, not only for the Z-minus movements.
#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
if(check_z_endstop) {
// Check the Z min end-stop no matter what.
// Good for searching for the center of an induction target.
bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
if(z_min_endstop && old_z_min_endstop) {
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
step_events_completed = current_block->step_event_count;
}
old_z_min_endstop = z_min_endstop;
}
#endif
#ifndef ADVANCE
if ((out_bits & (1<<E_AXIS)) != 0) { // -direction
REV_E_DIR();

View file

@ -72,9 +72,12 @@ void st_wake_up();
void checkHitEndstops(); //call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered
void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homing and before a routine call of checkHitEndstops();
bool endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homing and before a routine call of checkHitEndstops();
bool endstop_z_hit_on_purpose();
void enable_endstops(bool check); // Enable/disable endstop checking
bool enable_endstops(bool check); // Enable/disable endstop checking. Return the old value.
bool enable_z_endstop(bool check);
void checkStepperErrors(); //Print errors detected by the stepper

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,8 @@
#ifdef ULTRA_LCD
void lcd_update();
// Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
void lcd_update_enable(bool enable);
void lcd_init();
void lcd_setstatus(const char* message);
void lcd_setstatuspgm(const char* message);
@ -23,7 +25,6 @@
void lcd_loading_color();
void lcd_force_language_selection();
void lcd_sdcard_stop();
void lcd_calibration();
bool lcd_detected(void);
@ -36,6 +37,9 @@
static void lcd_selftest_error(int _error_no, const char *_error_1, const char *_error_2);
static void lcd_menu_statistics();
extern bool lcd_calibrate_z_end_stop_manual();
extern void lcd_diag_show_end_stops();
#ifdef DOGLCD
extern int lcd_contrast;
void lcd_setcontrast(uint8_t value);
@ -154,4 +158,16 @@ char *ftostr5(const float &x);
char *ftostr51(const float &x);
char *ftostr52(const float &x);
extern void lcd_implementation_clear();
extern void lcd_printPGM(const char* str);
extern void lcd_print_at_PGM(uint8_t x, uint8_t y, const char* str);
extern void lcd_implementation_print(const char *str);
extern void lcd_implementation_print(int8_t i);
extern void lcd_implementation_print_at(uint8_t x, uint8_t y, int8_t i);
extern void lcd_implementation_print(int i);
extern void lcd_implementation_print_at(uint8_t x, uint8_t y, int i);
extern void lcd_implementation_print(float f);
extern void lcd_implementation_print_at(uint8_t x, uint8_t y, const char *str);
#endif //ULTRALCD_H

View file

@ -567,12 +567,12 @@ static void lcd_implementation_display()
lcd.display();
}
static void lcd_implementation_clear()
void lcd_implementation_clear()
{
lcd.clear();
}
/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
static void lcd_printPGM(const char* str)
void lcd_printPGM(const char* str)
{
char c;
while((c = pgm_read_byte(str++)) != '\0')
@ -580,6 +580,55 @@ static void lcd_printPGM(const char* str)
lcd.write(c);
}
}
void lcd_print_at_PGM(uint8_t x, uint8_t y, const char* str)
{
lcd.setCursor(x, y);
char c;
while((c = pgm_read_byte(str++)) != '\0')
{
lcd.write(c);
}
}
void lcd_implementation_print(int8_t i)
{
lcd.print(i);
}
void lcd_implementation_print_at(uint8_t x, uint8_t y, int8_t i)
{
lcd.setCursor(x, y);
lcd.print(i);
}
void lcd_implementation_print(int i)
{
lcd.print(i);
}
void lcd_implementation_print_at(uint8_t x, uint8_t y, int i)
{
lcd.setCursor(x, y);
lcd.print(i);
}
void lcd_implementation_print(float f)
{
lcd.print(f);
}
void lcd_implementation_print(const char *str)
{
lcd.print(str);
}
void lcd_implementation_print_at(uint8_t x, uint8_t y, const char *str)
{
lcd.setCursor(x, y);
lcd.print(str);
}
/*
20x4 |01234567890123456789|