-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmesh_builder.cc
More file actions
417 lines (370 loc) · 14.3 KB
/
mesh_builder.cc
File metadata and controls
417 lines (370 loc) · 14.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/*
* mesh_builder.c
*
* Created on: Sept 14, 2018
* Author: cyberwizzard
*/
#include "mesh_builder.h"
#include <stdio.h>
#include <curses.h>
#include "main.h"
#include "machine.h"
#include "utility.h"
#include "tui.h"
// Mesh points
ty_meshpoint mesh [MESH_SIZE_Y][MESH_SIZE_X];
int mesh_builder_stepsize = 0; // Step size for lowering or raising the head
void mesh_builder_print_mesh_status(WINDOW *wnd, int y, int x, int y_sel, int x_sel, double t_hotend, double t_bed);
void mesh_builder_destroy_win(WINDOW *local_win)
{
/* box(local_win, ' ', ' '); : This won't produce the desired
* result of erasing the window. It will leave it's four corners
* and so an ugly remnant of window.
*/
wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
/* The parameters taken are
* 1. win: the window on which to operate
* 2. ls: character to be used for the left side of the window
* 3. rs: character to be used for the right side of the window
* 4. ts: character to be used for the top side of the window
* 5. bs: character to be used for the bottom side of the window
* 6. tl: character to be used for the top left corner of the window
* 7. tr: character to be used for the top right corner of the window
* 8. bl: character to be used for the bottom left corner of the window
* 9. br: character to be used for the bottom right corner of the window
*/
wrefresh(local_win);
delwin(local_win);
}
void mesh_builder_print_status_bar(int row, int stepsize) {
//const char *banner = "[AWSD] Move mesh point [F2] Fill Row [F3] Fill Column [F4] Fill All [Up/Down] Raise/lower head [Left/Right] Change step size: %s";
const char *banner = "[F5] Download mesh [F6] Upload mesh [F10] Quit [AWSD] Move mesh point [Up/Down] Raise/lower head [Left/Right] Change step size: %s";
const char *step0 = "[1mm] 0.1mm 0.01mm";
const char *step1 = "1mm [0.1mm] 0.01mm";
const char *step2 = "1mm 0.1mm [0.01mm]";
const char *step = (stepsize==0?step0:((stepsize==1)?step1:step2));
mvprintw(row, 0, banner, step);
refresh();
}
int mesh_builder() {
int keepgoing = 1; // Flag to terminate the input loop
int x_pos = 0; // Current position within the mesh
int y_pos = 0; // Current position within the mesh
int x_sel = 0; // Selection in the mesh to potentially activate to calibrate next
int y_sel = 0; // Selection in the mesh to potentially activate to calibrate next
float xyspeed = 4000.0f; // Speed when moving from point to point in the mesh
int ch; // Integer to hold the key scancode during the input loop
float zraise = 0.0f; // How far should the head be raised during moves from corner to corner?
float z_offset = 7.0f; // The offset of the Z axis using G92, this allows us to get below the optoflag
double t_hotend = 0; // Temperature of the hotend, periodically polled and printed in mesh overview
double t_bed = 0; // Temperature of the bed, periodically polled and printed in mesh overview
// Input loop variables
mesh_builder_stepsize = 1; // 0 = 1mm, 1 = 0.1mm, 2 = 0.01mm
float step = 0.1f;
// Inititialize the mesh array so the X and Y coordinates of each mesh point are known
for (int y=0; y<MESH_SIZE_Y; y++) {
for (int x=0; x<MESH_SIZE_X; x++) {
mesh[y][x].valid = 0;
mesh[y][x].x = MESH_MIN_X + ((float)x * (MESH_MAX_X - MESH_MIN_X)) / (MESH_SIZE_X - 1);
mesh[y][x].y = MESH_MIN_Y + ((float)y * (MESH_MAX_Y - MESH_MIN_Y)) / (MESH_SIZE_Y - 1);
mesh[y][x].z = 0.0f;
}
}
// Start curses and all windows
tui_init(1, &mesh_builder_print_status_bar);
// Print the overview of mesh points
mesh_builder_print_mesh_status(overview_win, y_pos, x_pos, y_sel, x_sel, t_hotend, t_bed);
// Start by homing all axis on the machine
wprintw(cmd_win,"Homing all axis\n");
wrefresh(cmd_win);
//ASSERT(home_xyz());
// Home all axis by raising Z first to avoid scraping the tape
{
ASSERT(override_zpos(0.0f));
ASSERT(set_z(4.0f,0,MAX_SPEED_Z));
ASSERT(home_xy());
ASSERT(home_z());
}
// How far can the head be lowered from the Z end stop?
{
int zoi = 0;
// int utility_ask_int(WINDOW *wnd, string q, int *ans, int def, int min, int max, int step)
if(!utility_ask_int(cmd_win, "How far can the toolhead be lowered below the Z end-stop in mm?", &zoi, DEFAULT_BOUND_Z, 0, LOWER_BOUND_Z, 1)) goto stop;
z_offset = (float)zoi;
wprintw(cmd_win,"Using %.2f mm as the absolute lowest position\n", -z_offset);
wrefresh(cmd_win);
}
// Raise height for XY moves (assuming the bed is below the Z opto position for all XY, this is likely 0 for everyone)
{
int zoi = 0;
if(!utility_ask_int(cmd_win, "During XY moves, how far should the toolhead be raised compared to the Z end-stop?", &zoi, DEFAULT_RAISE_Z, 0, 10, 1)) goto stop;
zraise = (float)zoi;
wprintw(cmd_win,"Using %.2f mm as the repositioning height\n", zraise);
wrefresh(cmd_win);
}
// Pre-heat support for hotend and bed; levelling should be done at (almost) operating temperatures to
// ensure the mechanics are at the correct dimensions when building the mesh.
{
int temp = 0;
if(!utility_ask_int(cmd_win, "Pre-heat hot-end to which temperature?", &temp, PREHEAT_TEMP_HOTEND, 0, MAX_TEMP_HOTEND, 1)) goto stop;
wprintw(cmd_win,"Setting hot-end to %i°C\n", temp);
wrefresh(cmd_win);
set_hotend_temperature((double)temp);
if(!utility_ask_int(cmd_win, "Pre-heat bed to which temperature?", &temp, PREHEAT_TEMP_BED, 0, MAX_TEMP_BED, 1)) goto stop;
wprintw(cmd_win,"Setting bed to %i°C\n", temp);
wrefresh(cmd_win);
set_bed_temperature((double)temp);
}
// Disable the bed leveling logic so the machine reverts to linear motion
ASSERT(mesh_disable());
// Disable the software end-stops so the machine can lower the head below the Z end-stop
ASSERT(enable_soft_endstops(false));
// Apply the Z offset so we can lower the toolhead during leveling (0 is now -z_offset below the Z end-stop)
ASSERT(override_zpos(z_offset));
// Move Z up to whatever the movement height is
ASSERT(set_z(zraise+z_offset));
// Move to point (0,0) in the mesh
ASSERT(set_position(mesh[0][0].x,mesh[0][0].y,get_z(),0,xyspeed));
// Input loop
// Print the status bar
mesh_builder_print_status_bar(LINES-1, mesh_builder_stepsize);
wrefresh(overview_win);
// Set the timeout for getch() so the temperature gets updated every now and then
timeout(2000);
while(keepgoing) {
int update = 0; // Flag to trigger the mesh Z height to be updated and the mesh overview refreshed
if(mesh_builder_stepsize < 0 || mesh_builder_stepsize > 2) {
wprintw(cmd_win,"Invalid step size detected: %i\n", mesh_builder_stepsize);
goto stop;
}
// Read a keyboard press
ch = getch();
// Correct the scan code for special keys like the arrow keys (consisting of 2 keystrokes)
if ( ch == 0 || ch == 224 )
ch = 256 + getch();
// Handle the key press
switch(ch) {
case ERR:
// Timeout on input loop, update temperature
ASSERT(get_temperature(&t_hotend, &t_bed));
update = 1;
break;
case 'q': // Quit the control loop
wprintw(cmd_win,"Hint: to quit, press F10 (instead of Q)\n");
break;
case KEY_F10:
keepgoing = 0;
// Raise the head
set_z(zraise+z_offset);
// Move to origin
set_position(0,0,get_z(),0,xyspeed);
break;
case KEY_LEFT:
if(mesh_builder_stepsize > 0) mesh_builder_stepsize--;
switch(mesh_builder_stepsize) {
case 0: step = 1.0f; break;
case 1: step = 0.1f; break;
case 2: step = 0.01f; break;
}
// Print the status bar
mesh_builder_print_status_bar(LINES-1, mesh_builder_stepsize);
break;
case KEY_RIGHT:
if(mesh_builder_stepsize < 2) mesh_builder_stepsize++;
switch(mesh_builder_stepsize) {
case 0: step = 1.0f; break;
case 1: step = 0.1f; break;
case 2: step = 0.01f; break;
}
// Print the status bar
mesh_builder_print_status_bar(LINES-1, mesh_builder_stepsize);
break;
case KEY_DOWN: {
float z = get_z();
z -= step;
if(z < 0) {
wprintw(cmd_win,"Warning: could not lower toolhead further, switch to a smaller step size\n");
} else {
// Lower the head
wprintw(cmd_win,"Setting Z to %.2f\n", z-z_offset);
ASSERT(set_z(z,0,MAX_SPEED_Z));
}}
// Toolhead moved, mark this point now as valid
if(!mesh[y_pos][x_pos].valid) mesh[y_pos][x_pos].valid = 1;
update = 1; // Update the mesh state
break;
case KEY_UP: {
float z = get_z();
z += step;
if(z > 50.0f) {
wprintw(cmd_win,"Warning: could not raise toolhead further, switch to a smaller step size\n");
} else {
// Raise the head
wprintw(cmd_win,"Setting Z to %.2f\n", z-z_offset);
ASSERT(set_z(z,0,MAX_SPEED_Z));
}}
// Toolhead moved, mark this point now as valid
if(!mesh[y_pos][x_pos].valid) mesh[y_pos][x_pos].valid = 1;
update = 1; // Update the mesh state
break;
case 'a':
// Move 'left' on the mesh selection
if(x_sel > 0) {
x_sel--;
update = 1; // Update the mesh state
}
break;
case 'd':
// Move 'right' on the mesh selection
if(x_sel < MESH_SIZE_X-1) {
x_sel++;
update = 1; // Update the mesh state
}
break;
case 'w':
// Move 'up' on the mesh selection
if(y_sel < MESH_SIZE_Y-1) {
y_sel++;
update = 1; // Update the mesh state
}
break;
case 's':
// Move 'down' on the mesh selection
if(y_sel > 0) {
y_sel--;
update = 1; // Update the mesh state
}
break;
case 10:
// Enter key - switch selection
if(x_sel != x_pos || y_sel != y_pos) {
// Selection changed - get the current Z and store it (relatively to the Z end-stop, which was shifted up by z_offset)
mesh[y_pos][x_pos].z = get_z() - z_offset;
// Update position to selection
x_pos = x_sel;
y_pos = y_sel;
wprintw(cmd_win, "Moving to mesh point (%i,%i) @ (%.1f,%.1f)\n", x_pos, y_pos, mesh[y_pos][x_pos].x, mesh[y_pos][x_pos].y);
// Raise Z and move to new position
set_z(zraise+z_offset);
set_position(mesh[y_pos][x_pos].x,mesh[y_pos][x_pos].y,get_z(),0,xyspeed);
set_z(mesh[y_pos][x_pos].z+z_offset);
// Update the overview
mesh_builder_print_mesh_status(overview_win, y_pos, x_pos, y_sel, x_sel, t_hotend, t_bed);
}
break;
case KEY_F5:
{
int zoi = 0;
int errcode = 0;
// Load the mesh from the printer
wprintw(cmd_win, "Preparing to download mesh from printer...\n");
// int utility_ask_int(WINDOW *wnd, string q, int *ans, int def, int min, int max, int step)
if(!utility_ask_int(cmd_win, "Which mesh should be loaded from printer EEPROM? Use -1 to use the currently active mesh instead.", &zoi, -1, -1, 20, 1)) goto stop;
// Download mesh from printer
if((errcode = mesh_download(zoi, mesh, cmd_win))) {
if(errcode == 1) {
wprintw(cmd_win, "ERROR: No valid CSV line found in first 4kB of mesh response!\n");
} else if(errcode == 3) {
wprintw(cmd_win, "ERROR: Incorrect number of columns (X points) found! Expected: %i\n", MESH_SIZE_X);
} if(errcode == 4) {
wprintw(cmd_win, "ERROR: Incorrect number of rows (Y points) found! Expected: %i\n", MESH_SIZE_Y);
} else {
wprintw(cmd_win, "ERROR: Unknown error during download: %i\n", errcode);
}
} else {
wprintw(cmd_win, "Downloaded mesh successfully\n");
}
// Redraw the mesh overview
update = 1;
// Ask to align the toolhead to get started
bool ans = false;
if(!utility_ask_bool(cmd_win, "Mesh loaded; move toolhead to loaded Z position?", &ans, false)) goto stop;
if(ans) {
// Move to current Z height in mesh
wprintw(cmd_win,"Setting Z to %.2f\n", mesh[y_pos][x_pos].z);
ASSERT(set_z(mesh[y_pos][x_pos].z+z_offset));
} else {
wprintw(cmd_win,"Not moving current Z height; downloaded mesh point updated\n");
}
}
break;
case KEY_F6:
{
int zoi = 0;
int errcode = 0;
// Load the mesh from the printer
wprintw(cmd_win, "Preparing to upload mesh to printer...\n");
// int utility_ask_int(WINDOW *wnd, string q, int *ans, int def, int min, int max, int step)
if(!utility_ask_int(cmd_win, "Which mesh slot should the mesh be saved into printer EEPROM? Use -1 to only upload.", &zoi, -1, -1, 20, 1)) goto stop;
// Upload mesh from printer
if((errcode = mesh_upload(zoi, mesh, cmd_win))) {
wprintw(cmd_win, "ERROR: Unknown error during download: %i\n", errcode);
} else {
wprintw(cmd_win, "Uploaded mesh successfully\n");
}
}
break;
case 410:
// Resize event
tui_resize();
break;
default: // Unknown keypress
wprintw(cmd_win,"Invalid key: %i\n", ch);
}
// Update the mesh if requested
if (update) {
// Get the current Z and store it in the mesh (so the view will update)
mesh[y_pos][x_pos].z = get_z() - z_offset;
// Re-print the overview
mesh_builder_print_mesh_status(overview_win, y_pos, x_pos, y_sel, x_sel, t_hotend, t_bed);
}
// When we are all done, update the screen
wrefresh(cmd_win);
wrefresh(overview_win);
}
stop:
// Remove the window for the serial output and its pointer
mesh_builder_destroy_win(serial_border);
mesh_builder_destroy_win(serial_win);
serial_win = NULL;
// Destroy the status panel
mesh_builder_destroy_win(cmd_win);
endwin();
printf("Mesh Builder terminated\n");
return 0;
}
/**
* Print the mesh status overview
* @param wnd Window to print the question and feedback in
* @param y active Y point in the mesh
* @param x active X point in the mesh
* @param y selected Y point in the mesh
* @param x selected X point in the mesh
*/
void mesh_builder_print_mesh_status(WINDOW *wnd, int y, int x, int y_sel, int x_sel, double t_hotend, double t_bed) {
wprintw(wnd, "\nMesh size (X*Y): %i x %i - Bounds (mm): (%0.2f, %0.2f) x (%0.2f, %0.2f) - Hotend: %.02f °C - Bed: %.02f °C\n",
MESH_SIZE_X, MESH_SIZE_Y, MESH_MIN_X, MESH_MIN_Y, MESH_MAX_X, MESH_MAX_Y, t_hotend, t_bed);
for (int yy = MESH_SIZE_Y - 1; yy >= 0; yy--) {
for (int xx = 0; xx < MESH_SIZE_X; xx++) {
if(mesh[yy][xx].valid) {
if(x == xx && y == yy)
wprintw(wnd, "[%6.2f] ", mesh[yy][xx].z);
else if(x_sel == xx && y_sel == yy)
wprintw(wnd, "<%6.2f> ", mesh[yy][xx].z);
else
wprintw(wnd, " %6.2f ", mesh[yy][xx].z);
} else {
if(x == xx && y == yy)
wprintw(wnd, " [ * ] ");
else if(x_sel == xx && y_sel == yy)
wprintw(wnd, " < * > ");
else
wprintw(wnd, " * ");
}
}
wprintw(wnd, "\n");
}
wprintw(wnd, "Active point: [%i, %i] ", x, y);
if (x != x_sel || y != y_sel)
wprintw(wnd, " - Selected point: <%i, %i> (press enter to activate and move the head) ", x_sel, y_sel);
}