bool ThreePointStrategy::handleGcode(Gcode *gcode) { if(gcode->has_g) { // G code processing if(gcode->g == 29) { // test probe points for level if(!test_probe_points(gcode)) { gcode->stream->printf("Probe failed to complete, probe not triggered or other error\n"); } return true; } else if( gcode->g == 31 ) { // report status if(this->plane == nullptr) { gcode->stream->printf("Bed leveling plane is not set\n"); }else{ gcode->stream->printf("Bed leveling plane normal= %f, %f, %f\n", plane->getNormal()[0], plane->getNormal()[1], plane->getNormal()[2]); } gcode->stream->printf("Probe is %s\n", zprobe->getProbeStatus() ? "Triggered" : "Not triggered"); return true; } else if( gcode->g == 32 ) { // three point probe // first wait for an empty queue i.e. no moves left THEKERNEL->conveyor->wait_for_idle(); // clear any existing plane and compensation delete this->plane; this->plane= nullptr; setAdjustFunction(false); if(!doProbing(gcode->stream)) { gcode->stream->printf("Probe failed to complete, probe not triggered or other error\n"); } else { gcode->stream->printf("Probe completed, bed plane defined\n"); } return true; } } else if(gcode->has_m) { if(gcode->m == 557) { // M557 - set probe points eg M557 P0 X30 Y40.5 where P is 0,1,2 int idx = 0; float x = NAN, y = NAN; if(gcode->has_letter('P')) idx = gcode->get_value('P'); if(gcode->has_letter('X')) x = gcode->get_value('X'); if(gcode->has_letter('Y')) y = gcode->get_value('Y'); if(idx >= 0 && idx <= 2) { probe_points[idx] = std::make_tuple(x, y); }else{ gcode->stream->printf("only 3 probe points allowed P0-P2\n"); } return true; } else if(gcode->m == 561) { // M561: Set Identity Transform with no parameters, set the saved plane if A B C D are given delete this->plane; if(gcode->get_num_args() == 0) { this->plane= nullptr; // delete the compensationTransform in robot setAdjustFunction(false); gcode->stream->printf("saved plane cleared\n"); }else{ // smoothie specific way to restore a saved plane uint32_t a,b,c,d; a=b=c=d= 0; if(gcode->has_letter('A')) a = gcode->get_uint('A'); if(gcode->has_letter('B')) b = gcode->get_uint('B'); if(gcode->has_letter('C')) c = gcode->get_uint('C'); if(gcode->has_letter('D')) d = gcode->get_uint('D'); this->plane= new Plane3D(a, b, c, d); setAdjustFunction(true); } return true; } else if(gcode->m == 565) { // M565: Set Z probe offsets float x= 0, y= 0, z= 0; if(gcode->has_letter('X')) x = gcode->get_value('X'); if(gcode->has_letter('Y')) y = gcode->get_value('Y'); if(gcode->has_letter('Z')) z = gcode->get_value('Z'); probe_offsets = std::make_tuple(x, y, z); return true; } else if(gcode->m == 500 || gcode->m == 503) { // M500 save, M503 display float x, y, z; gcode->stream->printf(";Probe points:\n"); for (int i = 0; i < 3; ++i) { std::tie(x, y) = probe_points[i]; gcode->stream->printf("M557 P%d X%1.5f Y%1.5f\n", i, x, y); } gcode->stream->printf(";Probe offsets:\n"); std::tie(x, y, z) = probe_offsets; gcode->stream->printf("M565 X%1.5f Y%1.5f Z%1.5f\n", x, y, z); // encode plane and save if set and M500 and enabled if(this->save && this->plane != nullptr) { if(gcode->m == 500) { uint32_t a, b, c, d; this->plane->encode(a, b, c, d); gcode->stream->printf(";Saved bed plane:\nM561 A%lu B%lu C%lu D%lu \n", a, b, c, d); }else{ gcode->stream->printf(";The bed plane will be saved on M500\n"); } } return true; } #if 0 else if(gcode->m == 9999) { // DEBUG run a test M9999 A B C X Y set Z to A B C and test for point at X Y Vector3 v[3]; float x, y, z, a= 0, b= 0, c= 0; if(gcode->has_letter('A')) a = gcode->get_value('A'); if(gcode->has_letter('B')) b = gcode->get_value('B'); if(gcode->has_letter('C')) c = gcode->get_value('C'); std::tie(x, y) = probe_points[0]; v[0].set(x, y, a); std::tie(x, y) = probe_points[1]; v[1].set(x, y, b); std::tie(x, y) = probe_points[2]; v[2].set(x, y, c); delete this->plane; this->plane = new Plane3D(v[0], v[1], v[2]); gcode->stream->printf("plane normal= %f, %f, %f\n", plane->getNormal()[0], plane->getNormal()[1], plane->getNormal()[2]); x= 0; y=0; if(gcode->has_letter('X')) x = gcode->get_value('X'); if(gcode->has_letter('Y')) y = gcode->get_value('Y'); z= getZOffset(x, y); gcode->stream->printf("z= %f\n", z); // tell robot to adjust z on each move setAdjustFunction(true); return true; } #endif } return false; }
bool ZGridStrategy::handleGcode(Gcode *gcode) { string args = get_arguments(gcode->get_command()); // G code processing if(gcode->has_g) { if( gcode->g == 31 ) { // report status // Bed ZGrid data as gcode: gcode->stream->printf(";Bed Level settings:\r\n"); for (int x=0; x<this->numRows; x++) { gcode->stream->printf("X%i",x); for (int y=0; y<this->numCols; y++) { gcode->stream->printf(" %c%1.2f", 'A'+y, this->pData[(x*this->numCols)+y]); } gcode->stream->printf("\r\n"); } return true; } else if( gcode->g == 32 ) { //run probe // first wait for an empty queue i.e. no moves left THEKERNEL->conveyor->wait_for_empty_queue(); this->setAdjustFunction(false); // Disable leveling code if(!doProbing(gcode->stream)) { gcode->stream->printf("Probe failed to complete, probe not triggered or other error\n"); } else { this->setAdjustFunction(true); // Enable leveling code gcode->stream->printf("Probe completed, bed grid defined\n"); } return true; } } else if(gcode->has_m) { switch( gcode->m ) { // manual bed ZGrid calbration: M370 - M375 // M370: Clear current ZGrid for calibration, and move to first position case 370: { this->setAdjustFunction(false); // Disable leveling code this->cal[Z_AXIS] = std::get<Z_AXIS>(this->probe_offsets) + zprobe->getProbeHeight(); if(gcode->has_letter('X')) // Rows (X) this->numRows = gcode->get_value('X'); if(gcode->has_letter('Y')) // Cols (Y) this->numCols = gcode->get_value('Y'); this->calcConfig(); // Run calculations for Grid size and allocate grid memory this->homexyz(); for (int i=0; i<probe_points; i++) { this->pData[i] = 0.0F; // Clear the ZGrid } this->cal[X_AXIS] = 0.0f; // Clear calibration position this->cal[Y_AXIS] = 0.0f; this->in_cal = true; // In calbration mode } return true; // M371: Move to next manual calibration position case 371: { if (in_cal) { this->move(this->cal, slow_rate); this->next_cal(); } } return true; // M372: save current position in ZGrid, and move to next calibration position case 372: { if (in_cal) { float cartesian[3]; int pindex = 0; THEKERNEL->robot->get_axis_position(cartesian); // get actual position from robot pindex = int(cartesian[X_AXIS]/this->bed_div_x + 0.25)*this->numCols + int(cartesian[Y_AXIS]/this->bed_div_y + 0.25); this->move(this->cal, slow_rate); // move to the next position this->next_cal(); // to not cause damage to machine due to Z-offset this->pData[pindex] = cartesian[Z_AXIS]; // save the offset } } return true; // M373: finalize calibration case 373: { // normalize the grid this->normalize_grid_2home(); this->in_cal = false; this->setAdjustFunction(true); // Enable leveling code } return true; // M374: Save grid case 374: { char gridname[5]; if(gcode->has_letter('S')) // Custom grid number snprintf(gridname, sizeof(gridname), "S%03.0f", gcode->get_value('S')); else gridname[0] = '\0'; if(this->saveGrid(gridname)) { gcode->stream->printf("Grid saved: Filename: /sd/Zgrid.%s\n",gridname); } else { gcode->stream->printf("Error: Grid not saved: Filename: /sd/Zgrid.%s\n",gridname); } } return true; case 375: { // Load grid values char gridname[5]; if(gcode->has_letter('S')) // Custom grid number snprintf(gridname, sizeof(gridname), "S%03.0f", gcode->get_value('S')); else gridname[0] = '\0'; if(this->loadGrid(gridname)) { this->setAdjustFunction(true); // Enable leveling code gcode->stream->printf("Grid loaded: /sd/Zgrid.%s\n",gridname); } else { gcode->stream->printf("Error: Grid not loaded: /sd/Zgrid.%s\n",gridname); } } return true; /* case 376: { // Check grid value calculations: For debug only. float target[3]; for(char letter = 'X'; letter <= 'Z'; letter++) { if( gcode->has_letter(letter) ) { target[letter - 'X'] = gcode->get_value(letter); } } gcode->stream->printf(" Z0 %1.3f\n",getZOffset(target[0], target[1])); } return true; */ case 565: { // M565: Set Z probe offsets float x= 0, y= 0, z= 0; if(gcode->has_letter('X')) x = gcode->get_value('X'); if(gcode->has_letter('Y')) y = gcode->get_value('Y'); if(gcode->has_letter('Z')) z = gcode->get_value('Z'); probe_offsets = std::make_tuple(x, y, z); } return true; case 500: // M500 saves probe_offsets config override file gcode->stream->printf(";Load default grid\nM375\n"); case 503: { // M503 just prints the settings float x,y,z; gcode->stream->printf(";Probe offsets:\n"); std::tie(x, y, z) = probe_offsets; gcode->stream->printf("M565 X%1.5f Y%1.5f Z%1.5f\n", x, y, z); break; } return true; } } return false; }