Setup to find data corruption and general clean up

This data corruption problem is very difficult.  Just changing the code
a little bit changes whether the problem even happens and what is
affected.  I need these changes in the main branch so I can operate with
the extra debug code always available and turned on.

Everything is setup such that if M100 is turned off or DEBUG(ECHO) is
turned off, the code is not affected.   M100 has been made a little bit
more inteligent so it can display the serial command buffers in a more
meaningful way (because the data corruption seems to often times end up
in that area).
This commit is contained in:
Roxy-3D 2017-04-15 19:14:40 -05:00 committed by Roxy-3D
parent e519e95953
commit 5e9726530f
4 changed files with 118 additions and 86 deletions

View file

@ -41,7 +41,7 @@
* Also, there are two support functions that can be called from a developer's C code. * Also, there are two support functions that can be called from a developer's C code.
* *
* uint16_t check_for_free_memory_corruption(char * const ptr); * uint16_t check_for_free_memory_corruption(char * const ptr);
* void M100_dump_free_memory(char *ptr, char *sp); * void M100_dump_routine( char *title, char *start, char *end);
* *
* Initial version by Roxy-3D * Initial version by Roxy-3D
*/ */
@ -52,7 +52,9 @@
#if ENABLED(M100_FREE_MEMORY_WATCHER) #if ENABLED(M100_FREE_MEMORY_WATCHER)
#define TEST_BYTE ((uint8_t) 0xE5) #define TEST_BYTE ((char) 0xE5)
extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
extern char* __brkval; extern char* __brkval;
extern size_t __heap_start, __heap_end, __flp; extern size_t __heap_start, __heap_end, __flp;
@ -78,7 +80,7 @@ char* top_of_stack() {
// Count the number of test bytes at the specified location. // Count the number of test bytes at the specified location.
int16_t count_test_bytes(const uint8_t * const ptr) { int16_t count_test_bytes(const uint8_t * const ptr) {
for (uint16_t i = 0; i < 32000; i++) for (uint16_t i = 0; i < 32000; i++)
if (ptr[i] != TEST_BYTE) if (((char) ptr[i]) != TEST_BYTE)
return i - 1; return i - 1;
return -1; return -1;
@ -118,8 +120,20 @@ int16_t count_test_bytes(const uint8_t * const ptr) {
} }
safe_delay(25); safe_delay(25);
SERIAL_CHAR('|'); // Point out non test bytes SERIAL_CHAR('|'); // Point out non test bytes
for (uint8_t i = 0; i < 16; i++) for (uint8_t i = 0; i < 16; i++) {
SERIAL_CHAR(ptr[i] == TEST_BYTE ? ' ' : '?'); char ccc;
ccc = (char) ptr[i];
if ( &ptr[i]>=&command_queue[0][0] && &ptr[i]<&command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command
if ( ccc<' ' || ccc>0x7e) // buffer area
ccc = ' ';
}
else
if (ccc != TEST_BYTE) // If not display data in the command buffer
ccc = '?'; // area, we flag bytes that don't match the test byte
else
ccc = ' ';
SERIAL_CHAR(ccc);
}
SERIAL_EOL; SERIAL_EOL;
ptr += 16; ptr += 16;
safe_delay(25); safe_delay(25);
@ -220,7 +234,7 @@ void init_free_memory(uint8_t *ptr, int16_t size) {
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n"); SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
for (uint16_t i = 0; i < size; i++) { for (uint16_t i = 0; i < size; i++) {
if (ptr[i] != TEST_BYTE) { if (((char) ptr[i]) != TEST_BYTE) {
SERIAL_ECHOPAIR("? address : 0x", hex_word((uint16_t)ptr + i)); SERIAL_ECHOPAIR("? address : 0x", hex_word((uint16_t)ptr + i));
SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i])); SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
} }
@ -288,7 +302,9 @@ int check_for_free_memory_corruption(char *title) {
// while ( !READ(63)) // while ( !READ(63))
// idle(); // idle();
safe_delay(20); safe_delay(20);
#ifdef M100_FREE_MEMORY_DUMPER
M100_dump_routine( " Memory corruption detected with sp<Heap\n", (char *)0x1b80, 0x21ff ); M100_dump_routine( " Memory corruption detected with sp<Heap\n", (char *)0x1b80, 0x21ff );
#endif
} }
// Scan through the range looking for the biggest block of 0xE5's we can find // Scan through the range looking for the biggest block of 0xE5's we can find

View file

@ -284,6 +284,7 @@
#if ENABLED(M100_FREE_MEMORY_WATCHER) #if ENABLED(M100_FREE_MEMORY_WATCHER)
void gcode_M100(); void gcode_M100();
void M100_dump_routine( char *title, char *start, char *end);
#endif #endif
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
@ -359,7 +360,11 @@ static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
uint8_t commands_in_queue = 0; // Count of commands in the queue uint8_t commands_in_queue = 0; // Count of commands in the queue
static uint8_t cmd_queue_index_r = 0, // Ring buffer read position static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
cmd_queue_index_w = 0; // Ring buffer write position cmd_queue_index_w = 0; // Ring buffer write position
#if ENABLED(M100_FREE_MEMORY_WATCHER)
char command_queue[BUFSIZE][MAX_CMD_SIZE]; // Necessary so M100 Free Memory Dumper can show us the commands and any corruption
#else // This can be collapsed back to the way it was soon.
static char command_queue[BUFSIZE][MAX_CMD_SIZE]; static char command_queue[BUFSIZE][MAX_CMD_SIZE];
#endif
/** /**
* Current GCode Command * Current GCode Command
@ -9561,6 +9566,10 @@ void process_next_command() {
if (DEBUGGING(ECHO)) { if (DEBUGGING(ECHO)) {
SERIAL_ECHO_START; SERIAL_ECHO_START;
SERIAL_ECHOLN(current_command); SERIAL_ECHOLN(current_command);
#if ENABLED(M100_FREE_MEMORY_WATCHER)
SERIAL_ECHOPAIR("slot:", cmd_queue_index_r);
M100_dump_routine( " Command Queue:", &command_queue[0][0], &command_queue[BUFSIZE][MAX_CMD_SIZE] );
#endif
} }
// Sanitize the current command: // Sanitize the current command:

View file

@ -1330,14 +1330,18 @@ void MarlinSettings::reset() {
SERIAL_ECHOPAIR("EEPROM can hold ", (int)((UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values))); SERIAL_ECHOPAIR("EEPROM can hold ", (int)((UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values)));
SERIAL_ECHOLNPGM(" meshes.\n"); SERIAL_ECHOLNPGM(" meshes.\n");
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X " STRINGIFY(GRID_MAX_POINTS_X)); SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y " STRINGIFY(GRID_MAX_POINTS_Y)); SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y);
SERIAL_ECHOLNPGM("UBL_MESH_MIN_X " STRINGIFY(UBL_MESH_MIN_X)); SERIAL_ECHOPGM("UBL_MESH_MIN_X " STRINGIFY(UBL_MESH_MIN_X));
SERIAL_ECHOLNPGM("UBL_MESH_MIN_Y " STRINGIFY(UBL_MESH_MIN_Y)); SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X );
SERIAL_ECHOPGM("UBL_MESH_MIN_Y " STRINGIFY(UBL_MESH_MIN_Y));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y );
SERIAL_ECHOLNPGM("UBL_MESH_MAX_X " STRINGIFY(UBL_MESH_MAX_X)); SERIAL_ECHOPGM("UBL_MESH_MAX_X " STRINGIFY(UBL_MESH_MAX_X));
SERIAL_ECHOLNPGM("UBL_MESH_MAX_Y " STRINGIFY(UBL_MESH_MAX_Y)); SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X);
SERIAL_ECHOPGM("UBL_MESH_MAX_Y " STRINGIFY(UBL_MESH_MAX_Y));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y);
SERIAL_ECHOLNPAIR("MESH_X_DIST ", MESH_X_DIST); SERIAL_ECHOLNPAIR("MESH_X_DIST ", MESH_X_DIST);
SERIAL_ECHOLNPAIR("MESH_Y_DIST ", MESH_Y_DIST); SERIAL_ECHOLNPAIR("MESH_Y_DIST ", MESH_Y_DIST);

View file

@ -102,8 +102,6 @@
* specified height, no correction is applied and natural printer kenimatics take over. If no * specified height, no correction is applied and natural printer kenimatics take over. If no
* number is specified for the command, 10mm is assumed to be reasonable. * number is specified for the command, 10mm is assumed to be reasonable.
* *
* G # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
*
* H # Height Specify the Height to raise the nozzle after each manual probe of the bed. The * H # Height Specify the Height to raise the nozzle after each manual probe of the bed. The
* default is 5mm. * default is 5mm.
* *
@ -117,6 +115,10 @@
* the bed and use this feature to select the center of the area (or cell) you want to * the bed and use this feature to select the center of the area (or cell) you want to
* invalidate. * invalidate.
* *
* J # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
*
* j EEPROM Dump This function probably goes away after debug is complete.
*
* K # Kompare Kompare current Mesh with stored Mesh # replacing current Mesh with the result. This * K # Kompare Kompare current Mesh with stored Mesh # replacing current Mesh with the result. This
* command literally performs a diff between two Meshes. * command literally performs a diff between two Meshes.
* *
@ -303,7 +305,7 @@
// The simple parameter flags and values are 'static' so parameter parsing can be in a support routine. // The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
static int g29_verbose_level, phase_value = -1, repetition_cnt, static int g29_verbose_level, phase_value = -1, repetition_cnt,
storage_slot = 0, map_type, grid_size_G ; //unlevel_value = -1; storage_slot=0, map_type, grid_size;
static bool repeat_flag, c_flag, x_flag, y_flag; static bool repeat_flag, c_flag, x_flag, y_flag;
static float x_pos, y_pos, measured_z, card_thickness = 0.0, ubl_constant = 0.0; static float x_pos, y_pos, measured_z, card_thickness = 0.0, ubl_constant = 0.0;
@ -378,24 +380,9 @@
} }
} }
/* if (code_seen('J')) {
if (code_seen('U')) { if (grid_size<2 || grid_size>5) {
unlevel_value = code_value_int(); SERIAL_PROTOCOLLNPGM("ERROR - grid size must be between 2 and 5");
//if (!WITHIN(unlevel_value, 0, 7)) {
// SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
// return;
//}
}
*/
if (code_seen('G')) {
uint8_t grid_size_G = code_has_value() ? code_value_int() : 3;
if (grid_size_G < 2) {
SERIAL_PROTOCOLLNPGM("ERROR - grid size must be 2 or more");
return;
}
if (grid_size_G > GRID_MAX_POINTS_X || grid_size_G > GRID_MAX_POINTS_Y) {
SERIAL_PROTOCOLLNPGM("ERROR - grid size can NOT exceed GRID_MAX_POINTS_X nor GRID_MAX_POINTS_Y");
return; return;
} }
tilt_mesh_based_on_probed_grid(code_seen('O') || code_seen('M')); tilt_mesh_based_on_probed_grid(code_seen('O') || code_seen('M'));
@ -567,7 +554,7 @@
// When we are fully debugged, the EEPROM dump command will get deleted also. But // When we are fully debugged, the EEPROM dump command will get deleted also. But
// right now, it is good to have the extra information. Soon... we prune this. // right now, it is good to have the extra information. Soon... we prune this.
// //
if (code_seen('J')) g29_eeprom_dump(); // EEPROM Dump if (code_seen('j')) g29_eeprom_dump(); // EEPROM Dump
// //
// When we are fully debugged, this may go away. But there are some valid // When we are fully debugged, this may go away. But there are some valid
@ -692,11 +679,9 @@
LEAVE: LEAVE:
#if ENABLED(ULTRA_LCD)
lcd_reset_alert_level(); lcd_reset_alert_level();
LCD_MESSAGEPGM(""); LCD_MESSAGEPGM("");
lcd_quick_feedback(); lcd_quick_feedback();
#endif
ubl.has_control_of_lcd_panel = false; ubl.has_control_of_lcd_panel = false;
} }
@ -997,18 +982,26 @@
} }
bool g29_parameter_parsing() { bool g29_parameter_parsing() {
#if ENABLED(ULTRA_LCD) bool err_flag = false;
LCD_MESSAGEPGM("Doing G29 UBL!"); LCD_MESSAGEPGM("Doing G29 UBL!");
lcd_quick_feedback(); lcd_quick_feedback();
#endif
x_flag = code_seen('X') && code_has_value(); x_flag = code_seen('X') && code_has_value();
y_flag = code_seen('Y') && code_has_value();
x_pos = x_flag ? code_value_float() : current_position[X_AXIS]; x_pos = x_flag ? code_value_float() : current_position[X_AXIS];
y_pos = y_flag ? code_value_float() : current_position[Y_AXIS];
repeat_flag = code_seen('R') ? code_value_bool() : false;
bool err_flag = false; y_flag = code_seen('Y') && code_has_value();
y_pos = y_flag ? code_value_float() : current_position[Y_AXIS];
repetition_cnt = 0;
repeat_flag = code_seen('R');
if (repeat_flag) {
repetition_cnt = code_has_value() ? code_value_int() : GRID_MAX_POINTS_X*GRID_MAX_POINTS_Y;
if (repetition_cnt < 1) {
SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
return UBL_ERR;
}
}
g29_verbose_level = code_seen('V') ? code_value_int() : 0; g29_verbose_level = code_seen('V') ? code_value_int() : 0;
if (!WITHIN(g29_verbose_level, 0, 4)) { if (!WITHIN(g29_verbose_level, 0, 4)) {
@ -1017,8 +1010,8 @@
} }
if (code_seen('G')) { if (code_seen('G')) {
grid_size_G = code_has_value() ? code_value_int() : 3; grid_size = code_has_value() ? code_value_int() : 3;
if (!WITHIN(grid_size_G, 2, 10)) { if (!WITHIN(grid_size, 2, 5)) {
SERIAL_PROTOCOLLNPGM("Invalid grid probe points specified.\n"); SERIAL_PROTOCOLLNPGM("Invalid grid probe points specified.\n");
err_flag = true; err_flag = true;
} }
@ -1032,11 +1025,27 @@
if (!WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS)) { if (!WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS)) {
SERIAL_PROTOCOLLNPGM("Invalid X location specified.\n"); SERIAL_PROTOCOLLNPGM("Invalid X location specified.\n");
err_flag = true; err_flag = true;
SERIAL_PROTOCOLPAIR("\nx_flag = ", x_flag); // These print blocks are only useful because sometimes the
SERIAL_PROTOCOLPAIR("\nx_pos = ", x_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[X_AXIS]);
SERIAL_PROTOCOLPAIR("\nX_MIN_POS = ", X_MIN_POS);
SERIAL_PROTOCOLPAIR("\nX_MAX_POS = ", X_MAX_POS);
SERIAL_PROTOCOLPAIR("\nRAW_X_POSITION() = ", RAW_X_POSITION(x_pos));
SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS));
SERIAL_PROTOCOL("\n");
} }
if (!WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS)) { if (!WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS)) {
SERIAL_PROTOCOLLNPGM("Invalid Y location specified.\n"); SERIAL_PROTOCOLLNPGM("Invalid Y location specified.\n");
err_flag = true; err_flag = true;
SERIAL_PROTOCOLPAIR("\ny_flag = ", y_flag); // These print blocks are only useful because sometimes the
SERIAL_PROTOCOLPAIR("\ny_pos = ", y_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[Y_AXIS]);
SERIAL_PROTOCOLPAIR("\nY_MIN_POS = ", Y_MIN_POS);
SERIAL_PROTOCOLPAIR("\nY_MAX_POS = ", Y_MAX_POS);
SERIAL_PROTOCOLPAIR("\nRAW_Y_POSITION() = ", RAW_Y_POSITION(y_pos));
SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS));
SERIAL_PROTOCOL("\n");
} }
if (err_flag) return UBL_ERR; if (err_flag) return UBL_ERR;
@ -1068,11 +1077,6 @@
} }
#endif #endif
repetition_cnt = repeat_flag ? (code_has_value() ? code_value_int() : 9999) : 1;
if (repetition_cnt < 1) {
SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
return UBL_ERR;
}
map_type = code_seen('O') && code_has_value() ? code_value_int() : 0; map_type = code_seen('O') && code_has_value() ? code_value_int() : 0;
if (!WITHIN(map_type, 0, 1)) { if (!WITHIN(map_type, 0, 1)) {
@ -1365,9 +1369,8 @@
} }
void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map) { void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map) {
// do all mesh points unless R option has a value of 1 or more if (!code_seen('R')) // fine_tune_mesh() is special. If no repetion count flag is specified
repetition_cnt = code_seen('R') && code_has_value() ? code_value_byte() : GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y; repetition_cnt = 1; // we know to do exactly one mesh location. Otherwise we use what the parser decided.
if (repetition_cnt == 0) repetition_cnt = GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y;
mesh_index_pair location; mesh_index_pair location;
uint16_t not_done[16]; uint16_t not_done[16];
@ -1448,7 +1451,7 @@
lcd_implementation_clear(); lcd_implementation_clear();
} while (location.x_index >= 0 && location.y_index >= 0 && --repetition_cnt); } while (location.x_index >= 0 && location.y_index >= 0 && (--repetition_cnt>0));
FINE_TUNE_EXIT: FINE_TUNE_EXIT:
@ -1466,16 +1469,16 @@
} }
void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) { void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
int8_t grid_G_index_to_xpos[grid_size_G], // UBL MESH X index to be probed int8_t grid_G_index_to_xpos[grid_size], // UBL MESH X index to be probed
grid_G_index_to_ypos[grid_size_G], // UBL MESH Y index to be probed grid_G_index_to_ypos[grid_size], // UBL MESH Y index to be probed
i, j ,k, xCount, yCount, G_X_index, G_Y_index; // counter variables i, j ,k, xCount, yCount, xi, yi; // counter variables
float z_values_G[grid_size_G][grid_size_G]; float z_values_G[grid_size][grid_size];
linear_fit *results; linear_fit *results;
for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++) for (yi = 0; yi < grid_size; yi++)
for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++) for (xi = 0; xi < grid_size; xi++)
z_values_G[G_X_index][G_Y_index] = NAN; z_values_G[xi][yi] = NAN;
uint8_t x_min = GRID_MAX_POINTS_X - 1, uint8_t x_min = GRID_MAX_POINTS_X - 1,
x_max = 0, x_max = 0,
@ -1494,26 +1497,26 @@
} }
} }
if (x_max - x_min + 1 < grid_size_G || y_max - y_min + 1 < grid_size_G) { if (x_max - x_min + 1 < grid_size || y_max - y_min + 1 < grid_size) {
SERIAL_ECHOPAIR("ERROR - probeable UBL MESH smaller than grid - X points: ", x_max - x_min + 1); SERIAL_ECHOPAIR("ERROR - probeable UBL MESH smaller than grid - X points: ", x_max - x_min + 1);
SERIAL_ECHOPAIR(" Y points: ", y_max - y_min + 1); SERIAL_ECHOPAIR(" Y points: ", y_max - y_min + 1);
SERIAL_ECHOLNPAIR(" grid: ", grid_size_G); SERIAL_ECHOLNPAIR(" grid: ", grid_size);
return; return;
} }
// populate X matrix // populate X matrix
for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++) { for (xi = 0; xi < grid_size; xi++) {
grid_G_index_to_xpos[G_X_index] = x_min + G_X_index * (x_max - x_min) / (grid_size_G - 1); grid_G_index_to_xpos[xi] = x_min + xi * (x_max - x_min) / (grid_size - 1);
if (G_X_index > 0 && grid_G_index_to_xpos[G_X_index - 1] == grid_G_index_to_xpos[G_X_index]) { if (xi > 0 && grid_G_index_to_xpos[xi - 1] == grid_G_index_to_xpos[xi]) {
grid_G_index_to_xpos[G_X_index] = grid_G_index_to_xpos[G_X_index - 1] + 1; grid_G_index_to_xpos[xi] = grid_G_index_to_xpos[xi - 1] + 1;
} }
} }
// populate Y matrix // populate Y matrix
for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++) { for (yi = 0; yi < grid_size; yi++) {
grid_G_index_to_ypos[G_Y_index] = y_min + G_Y_index * (y_max - y_min) / (grid_size_G - 1); grid_G_index_to_ypos[yi] = y_min + yi * (y_max - y_min) / (grid_size - 1);
if (G_Y_index > 0 && grid_G_index_to_ypos[G_Y_index - 1] == grid_G_index_to_ypos[G_Y_index]) { if (yi > 0 && grid_G_index_to_ypos[yi - 1] == grid_G_index_to_ypos[yi]) {
grid_G_index_to_ypos[G_Y_index] = grid_G_index_to_ypos[G_Y_index - 1] + 1; grid_G_index_to_ypos[yi] = grid_G_index_to_ypos[yi - 1] + 1;
} }
} }
@ -1526,14 +1529,14 @@
#undef PROBE_Y_FIRST #undef PROBE_Y_FIRST
#if ENABLED(PROBE_Y_FIRST) #if ENABLED(PROBE_Y_FIRST)
#define PR_OUTER_VAR xCount #define PR_OUTER_VAR xCount
#define PR_OUTER_NUM grid_size_G #define PR_OUTER_NUM grid_size
#define PR_INNER_VAR yCount #define PR_INNER_VAR yCount
#define PR_INNER_NUM grid_size_G #define PR_INNER_NUM grid_size
#else #else
#define PR_OUTER_VAR yCount #define PR_OUTER_VAR yCount
#define PR_OUTER_NUM grid_size_G #define PR_OUTER_NUM grid_size
#define PR_INNER_VAR xCount #define PR_INNER_VAR xCount
#define PR_INNER_NUM grid_size_G #define PR_INNER_NUM grid_size
#endif #endif
bool zig = PR_OUTER_NUM & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION bool zig = PR_OUTER_NUM & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
@ -1601,9 +1604,9 @@
//do_blocking_move_to_xy(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]], ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]); //do_blocking_move_to_xy(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]], ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]);
// least squares code // least squares code
double xxx9[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 }, double xxx5[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 },
yyy9[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 }, yyy5[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 },
zzz9[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01}, zzz5[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01},
xxx0[] = { 0.0, 0.0, 1.0 }, // Expect [0,0,0.1,0] xxx0[] = { 0.0, 0.0, 1.0 }, // Expect [0,0,0.1,0]
yyy0[] = { 0.0, 1.0, 0.0 }, yyy0[] = { 0.0, 1.0, 0.0 },
zzz0[] = { 0.1, 0.1, 0.1 }, zzz0[] = { 0.1, 0.1, 0.1 },
@ -1611,10 +1614,10 @@
yyy[] = { 0.0, 1.0, 0.0, 1.0 }, yyy[] = { 0.0, 1.0, 0.0, 1.0 },
zzz[] = { 0.05, 0.05, 0.15, 0.15 }; zzz[] = { 0.05, 0.05, 0.15, 0.15 };
results = lsf_linear_fit(xxx9, yyy9, zzz9, COUNT(xxx9)); results = lsf_linear_fit(xxx5, yyy5, zzz5, COUNT(xxx5));
SERIAL_ECHOPAIR("\nxxx9->A =", results->A); SERIAL_ECHOPAIR("\nxxx5->A =", results->A);
SERIAL_ECHOPAIR("\nxxx9->B =", results->B); SERIAL_ECHOPAIR("\nxxx5->B =", results->B);
SERIAL_ECHOPAIR("\nxxx9->D =", results->D); SERIAL_ECHOPAIR("\nxxx5->D =", results->D);
SERIAL_EOL; SERIAL_EOL;
results = lsf_linear_fit(xxx0, yyy0, zzz0, COUNT(xxx0)); results = lsf_linear_fit(xxx0, yyy0, zzz0, COUNT(xxx0));