repetier / Repetier-Firmware

Firmware for Arduino based RepRap 3D printer.
815 stars 734 forks source link

Just sharing G30 and G32 mods #1016

Closed JoeScotty closed 4 years ago

JoeScotty commented 4 years ago

Hi, did two modifications at G30 and G32 which I just want to share. I'm not sure if they have negative effects for other setups.

My setup is: cartesian, 2 extruders, BLTouch

1) G30: If I call G30 without parameters and the current ZPosition is too low, the BLTouch needle can't deploy. BLTouch blinks for alarm. In some cases further movement was stopped, but I also had cases, where the alarm was not detected and BLTouch crashed into the bed.

The mod is to lift Zposition if the currect position is below optimumProbingHeight.
(Here I did not care about the "height" you worked with in calculating optimumProbingHeight)

```C#
//GCodes.cpp

void __attribute__((weak)) GCode_30(GCode* com) {
#if Z_PROBE_TYPE
// G30 [Pn] [S]
// G30 (the same as G30 P3) single probe set Z0
// G30 S1 Z<real_z_pos> - measures probe height (P is ignored) assuming we are at real height Z
// G30 H<height> R<offset> Make probe define new Z and z offset (R) at trigger point assuming z-probe measured an object of H height.
uint8_t p = (com->hasP() ? (uint8_t)com->P : 3);
if (p & 1) {

    //If Z Pos < optimumProbingHeight (= Min. nozzle distance in EEPROM), move Z up to optimumProbingHeight
    if (Motion1::currentPosition[Z_AXIS] < ZProbeHandler::optimumProbingHeight()) {
        Com::printF("G30- Z up to probing height");
        Motion1::setTmpPositionXYZ(IGNORE_COORDINATE, IGNORE_COORDINATE, ZProbeHandler::optimumProbingHeight());
        Motion1::moveByOfficial(Motion1::tmpPosition, Motion1::moveFeedrate[Z_AXIS], false);
    } 

    ZProbeHandler::activate();
}
.....
```

2) G32: when using a grid for probing positions, the positions are tested for reachability by ZProbe. If a certain position is not allowed, probing this position is skipped. My ZProbe has a Yoffset=35. This means all Y-Positions < 35 are not allowed for probing. If I have a grid of 3 and bed size of 200x200, the probing positions (X/Y) 0/0, 100/0, 200/0 are skipped. Only positions x/100 and x/200 are probed. The modification is not to use the bed min and max positions to specify the grid area but to use the reachable ZProbe area for calculating the GRID positions. This results in a bigger probing area and hopefully more precision in levelling.

```C#
//LevelingMethod.cpp

bool Leveling::measure() {
float pos[NUM_AXES];
//mod
float tOffMinX, tOffMaxX, tOffMinY, tOffMaxY;

Plane plane;
PlaneBuilder builder;
builder.reset();
PrinterType::getBedRectangle(xMin, xMax, yMin, yMax);
// Sanity check for bad eeprom config
if (xMin == xMax || yMin == yMax) {
    return false;
}
xMin += Z_PROBE_BORDER;
xMax -= Z_PROBE_BORDER;
yMin += Z_PROBE_BORDER;
yMax -= Z_PROBE_BORDER;

//mod equation for area reachable for ZProbe:
// Ymin_ZP =    Max(Ymin - tOffMaxY + Z_PROBE_BORDER + ZPOffsetY, Ymin) 
// Ymax_ZP =    Min(Ymax - tOffMinY - Z_PROBE_BORDER + ZPOffsetY, Ymax) 
// Xmin_ZP =    Max(Xmin - tOffMaxX + Z_PROBE_BORDER + ZPOffsetX, Xmin) 
// Xmax_ZP =    Min(Xmax - tOffMinX - Z_PROBE_BORDER + ZPOffsetX, Xmax) 

// Z_PROBE_BORDER is already calculated above in xMin, xMax, ..

// get get Min and Max Offsets from tools (without Zprobe Offsets)
Tool::minMaxOffsetForAxis(X_AXIS, tOffMinX, tOffMaxX);
Tool::minMaxOffsetForAxis(Y_AXIS, tOffMinY, tOffMaxY);
// calc Min and Max coordinates defining the area reachable by ZProbe
xMin = RMath::max(xMin - tOffMaxX + ZProbeHandler::xOffset() , xMin);
xMax = RMath::min(xMax - tOffMinX + ZProbeHandler::xOffset() , xMax);
yMin = RMath::max(yMin - tOffMaxY + ZProbeHandler::yOffset() , yMin);
yMax = RMath::min(yMax - tOffMinY + ZProbeHandler::yOffset() , yMax);

updateDerived();
.....

```

Regards

repetier commented 4 years ago

Not sure if this independent increase of z is a good idea. The bltouch version of z probe has a test at activate that is supposed to catch the starting too low case:

void ZProbeHandler::activate() {
...
    ZProbeServo.setPosition(647, 0);     // deploy pin
    HAL::delayMilliseconds(deployDelay); // give time to deploy
    if (isAlarmOn()) {                   // to close to bed, alarm triggered already from deploy, so raise 5mm
        Com::printWarningFLN(PSTR("Z-probe triggered before probing - raising z!"));
        cPos[Z_AXIS] += 5.0;
        Motion1::moveByOfficial(cPos, Motion1::moveFeedrate[Z_AXIS], false);
        Motion1::waitForEndOfMoves();
        disableAlarmIfOn();
    }

You said you had cases where it was not detected. So I take this that it worked more or less but not all the time. deployDelay might be too low in that case so it did not start. Normally it should be ok to only raise z when the problem exists. The problem I see is that user might want to start lower and often this is not a real problem.

Regarding the grid idea. I thought that the extrapolation to unmeasured points would be a good idea. That way we get interpolations over the complete bed while with your solution outside measured area we stay at last value measured. Both have it's pros and cons. For bed leveling it would be a pro. For distortion it is not sure. There is no guarantee that extrapolation is more precise then keeping last value. That depends on the shape. So in favour of easy solution I will copy your code here for next update. I think it is the better of the two solutions.

JoeScotty commented 4 years ago

Thanks for your feedback!

Regarding the independant increase I also think this is for my setup only. I'll try to reproduce the case where the BLTouch alarm was not detected. If I find it, I'll let you know.

Regarding grid: I thought that extrapolation would be the same with or without my mod. My thoughts were: At the (extreme) example below with ZProbe being left and above T2 there are red areas at the bed, which are unallowed for the ZProbe. Performing G32 with a 3x3 Grid only the 4 green positions will be probed, the red ones will be skipped and you have to extrapolate the unmeasured area. With the mod the complete allowed area wil be used, all 9 grid positions can be probed and you still have to extrapolate the unmeasured area. But the unmeasured area is much smaller than before, so extrapolation should be more precise. Of course the effect will become smaller with increasing Grid positions.

grafik

JoeScotty commented 4 years ago

Aah, now I probably found why youe were talking about extra - and interpolation - you probably missed the xMax = RMath::min(..... , xMax); for avoiding to leave the original area, right?

repetier commented 4 years ago

I think I did understand you fully. What I meant is there is a function that would have computed the z for the red marked not measured points so later Z would be interpolated over the complete area. With only a few measured points this can of course be a very bad interpolation. One point why I voted for your solution. Here if you leave the green area it will keep z correction from where you cross the border - no extrapolation for the rest of the bed. So the comment is what would be in general better - extrapolate over all bed or better measurement and keep values from border and no extrapolation (also we could further extrapolate if wanted). But I think extrapolating is too dangerous if we do it more then needed. For deltas we need it a bit more but most position are off the round table anyway.

JoeScotty commented 4 years ago

Regarding BLTouch Alarm detection:

The deployDelay makes the difference if the BLTouch alarm is detected or not. Tried to find the limit down to 25ms interval: If the DeployDelay is bigger than 625 ms, the Alarm is not detected and the BLTouch crashes into bed. If smaller than 600ms, the alarm was detected and printer was stopped (continue with M999).

It was really that way (I expected it behaves safer by increasing the Deploydelay)

What happes in case of detected alarm (tested DeployDelay range 200-600 ms)

What happens in case of not detected alarm (tested DeployDelay range 625-1000 (probably also more)

So the code part you mentioned above detects the situation but does not stop the printer. Let me know if there are more tests necessary to solve this.

Regarding extrapolation versa keeping value when leaving the measurement area border: I could only imagine something like that: If you calculate an average plane basing on the measured values, the extrapolation could be done using this plane. But is it worth doing all the math to reach this?

JoeScotty commented 4 years ago

Had no good feeling that smaller delays worjk better than bigger delays.

Maybe I found something, if I interpreted correctly: In the existing code when BLTouch can't deploy and delivers an alarm, Z is raised by 5mm, the alarm is disabled, but the movement Z down to the bed is not stopped.

void ZProbeHandler::activate() {
     .....  
    ZProbeServo.setPosition(647, 0);     // deploy pin
    HAL::delayMilliseconds(deployDelay); // give time to deploy

    if (isAlarmOn()) {                   // to close to bed, alarm triggered already from deploy, so raise 5mm
        Com::printWarningFLN(PSTR("Z-probe triggered before probing - raising z!"));
        cPos[Z_AXIS] += 5.0;
        Motion1::moveByOfficial(cPos, Motion1::moveFeedrate[Z_AXIS], false);
        Motion1::waitForEndOfMoves();
        disableAlarmIfOn();
    }
    ......

In my tests this worked: After clearing the alarm the needle is deployed again and probing could be performed. If an BLTouch alarm is detected again, the needle seems to be really blocked and the printer is stopped (not sure if I implemented this correctly):

    ....
    if (isAlarmOn()) {                      
        Com::printWarningFLN(PSTR("Z-probe triggered before probing - raising z!"));
        cPos[Z_AXIS] += 5.0;                
        Motion1::moveByOfficial(cPos, Motion1::moveFeedrate[Z_AXIS], false); // raise Z by 5mm
        Motion1::waitForEndOfMoves();
        disableAlarmIfOn();                     // clear alarm
        HAL::delayMilliseconds(deployDelay);    // give time to clear Alarm. deployDelay is not the best choice, better new delay parameter?
        ZProbeServo.setPosition(647, 0);        // 2nd try to deploy pin after increasing Z
        HAL::delayMilliseconds(deployDelay);    // give time to deploy
        if (isAlarmOn()) {                      // if BLTouch gives Alarm again, needle is blocked, stop printer
            Motion1::waitForEndOfMoves();       // this avoids hard moves with very high feedrates and lost steps (where do they come from? only happens in case distortion correction is active.
            GCode::fatalError(PSTR("Z-Probe again triggered before probing! Printer Stopped for avoiding Bed crash")); // Z is raised to Z=30, probably by the fatalError 
            return;
        }    
    }
    .....

Maybe not the most elegant way, but as a first step it works for my setup.

repetier commented 4 years ago

Have updated firmware where the fix is added. Seems to work good. Tested with blocked probe and it was correctly adjusted.