Autolevel, homing and manual control problems

edited November 2015 in Repetier-Firmware
Ok, so I've got z-probe installed on Prusa i3 clone and it's working, more or less.

First problem:
Let's assume previous print ended at z = 100mm, there is no min z endstop, because probe is connected there. After power up:
G28 ; this homes X and Y (not Z, understandable - no height data)
G32 ; this also works fine
G28 ; again, now X, Y and Z are homed (correctly)
G1 Z1 F100; I believe this should cause "rise head by 1mm" so we should have Z=1mm - but instead, nozzle finishes this command at Z=101mm (position before G32 + 1mm)

Second problem, while running G32 command, after completing each sample point, head is lifted all the way up, to the original position . Seriously, what for? It takes ages to complete if nozzle was high after power up. IMHO it should move up only by Z_PROBE_BED_DISTANCE.

Third: If no min endstop is installed, it's possible to move nozzle manually below 0, is there a way to change this, so it wouldn't be possible?

Fourth: If z-probe/autolevel (G32) is started when nozzle is <= 0 (z-probe is correctly triggered), it will be grinding platform between sample points. Shouldn't active probe signal tell FV that it's dangerous to move head until it's lifted?

Fifth: Can z-probe be used as min-z-endstop for homing, before G32/29 is executed?

FV version 0.92.5, z-probe/autolevel config as follows:

#define Z_PROBE_Z_OFFSET 0.65
#define UI_BED_COATING 1
#define Z_PROBE_PULLUP 0
#define Z_PROBE_ON_HIGH 0
#define Z_PROBE_X_OFFSET 70
#define Z_PROBE_Y_OFFSET -10
#define Z_PROBE_SPEED 2
#define Z_PROBE_XY_SPEED 150
#define Z_PROBE_HEIGHT 1.0
#define Z_PROBE_X1 -30
#define Z_PROBE_Y1 20
#define Z_PROBE_X2 110
#define Z_PROBE_Y2 20
#define Z_PROBE_X3 50
#define Z_PROBE_Y3 160


  • G32 normally starts at a defined height (Z_PROBE_BED_DISTANCE), but that requires homing before. Deltas do it at least that way.

    G1 Z1 goes to Z=1 in absolute mode or one up in relative mode. But you should try M114 after G32 to see what printer thinks where it is.

    Without z homing and z endstops you get no range safety. Printer simply does not know where it is in reality.

    For some z probe types you can use them as z min endstop. But only if it triggers by pressing the nozzle itself. In all other cases you would trigger too early and get a gap between bed and nozzle, which is not what you want.
  • edited November 2015
    M114 after second homing gives:
    Recv: X:0.00 Y:0.00 Z:0.000 E:0.0000
    But I've noticed something more, if printer is in absolute coordinates mode G1 Z1 F100 works as expected, if I switch printer to relative mode (G91), then nozzle is raised to (original position + 1).

    Oh I know that without endstops there is no way to tell where nozzle is after powerup, but since we have z-probe, I believe that there is a solution to this:
    • Power up
    • G28 - If no hw endstops are present and z-probe is present, then (if user configured printer like this?) use it as endstop to find where bed level is.
      • if probe is triggered, rise it by Z_PROBE_BED_DISTANCE
      • home x&y, then position probe over the bed and lower it;
      • and now, since we know Z_PROBE_Z_OFFSET, we can tell where bed is, so software endstops can work.
      • Set X=Y=0;
    • Then G32/29 can map the bed with reasonable speed;

    Sure I don't want gap between bed and extruder, but the again - we know size of this gap (Z_PROBE_Z_OFFSET), so using this info printer can establish correct coordinate boundaries.

    PS.: I've found very useful code commented in Printer::runZProbe(), that optimizes how G32 works. It would be nice to have it's presence controlled by some preprocessor directive in configuration.h. ;)

  • I've took liberty of writing code for Z-Homing using z-probe. But since I have no idea how internals of FV work, this code can be buggy, or some important aspects could be omitted. It does however work for me. It should be added at the beginning of Printer::homeZAxis for cartesian printers.
    Code intended for usage with inductive sensor triggered before extruder can touch platform.
    XY Homing *MUST* be executed before Z-Homing, as Z-Homing will require valid XY coordinates to
    move probe into P0 position.
    No ifdef, compiler should optimize this anyway
    float probeX = EEPROM::zProbeX1();
    float probeY = EEPROM::zProbeY1();


    // Check if probe is triggered, if it is, probe is too low. So rise it by Z_PROBE_BED_DISTANCE.
    if (digitalRead(Z_PROBE_PIN) == Z_PROBE_ON_HIGH)
    PrintLine::moveRelativeDistanceInSteps(0, 0, Z_PROBE_BED_DISTANCE * axisStepsPerMM[Z_AXIS], 0, EEPROM::zProbeSpeed(), true, true);

    // but probe could be outside bed area, to be sure - move it to P0 position
    moveTo(probeX, probeY, IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeXYSpeed());

    // And check again it's status, it could move from outise the bed so signal before could be invalid
    if (digitalRead(Z_PROBE_PIN) == Z_PROBE_ON_HIGH)
    PrintLine::moveRelativeDistanceInSteps(0, 0, Z_PROBE_BED_DISTANCE * axisStepsPerMM[Z_AXIS], 0, EEPROM::zProbeSpeed(), true, true);

    // Check probe again, if it's still triggered, this means something is wrong
    if (digitalRead(Z_PROBE_PIN) == Z_PROBE_ON_HIGH)

    steps = 2 * (Printer::zMaxSteps - Printer::zMinSteps);


    stepsRemainingAtZHit = -1;
    PrintLine::moveRelativeDistanceInSteps(0, 0, -steps, 0, EEPROM::zProbeSpeed(), true, true);

    if(stepsRemainingAtZHit < 0)

    currentPositionSteps[Z_AXIS] = zMinSteps + (axisStepsPerMM[Z_AXIS] * EEPROM::zProbeZOffset());
    moveTo(0, 0, 0, IGNORE_COORDINATE, EEPROM::zProbeXYSpeed());
  • Nice try. Also I have some doubts on the correctness in some details.

    First you must know some z probes need some action to be able to measure, so you must enable/disable z probe. This should of course only happen in safe height so we are again at a point where you assume you get always a valid signal. I assume you have some induction sensor that does not need to be engaged like mechanical sensors.

    We could always move up a safety margin like you do. That of course leaves the risk that we stopped so high that we hit upper limit. So we can say if we need to engange z sensor we are lost to insecurity as we can not know if we could do it and if we want to be safe that this works going up may crash. So I guess we need to introduce a new parameter Z_PROBE_TYPE and disallow this for mechanical z probes.

    Then we need xy homing before z probing. If we git the floor we want to go up first. So I think it would be good to move your z probe hit on start at the beginning of the homing sequence so we home xy with nozzle not hitting floor.

    At the end you set zMinSteps + zProbeZOffset
    zProbeZOffset is bed coating thickness. What you need is also EEPROM::zProbeHeight() which is the distance between nozzle and trigger. I would suggest using the runZProbe instead and then se z like you do. This includes all offsets and would also run engange/disangange script if needed.

    What do you think about this solution?
  • Well, like I've said - I don't know how repetier exactly works.

    I would vote for ignoring mechanical probes all together for this function. So, few words of warning should be added to documentation/configurator (if it will be integrated). People who compile their own versions should read these anyway.

    My code moves carriage up only if probe is triggered (and only by max of Z_PROBE_BED_DISTANCE * 2), so I don't believe that there is a risk of hitting top limits, unless z-probe is faulty.

    As for using runZProbe(), I've initially thought that sequence of G28+G32+G28 would do the trick (it almost did), but G32 came out not to be very fast if initial Z position was high, and introduced problem with relative movement after homing - mentioned earlier. As far as I can tell, runZProbe() will try to find bed level, and then will go back to initial position - not exactly what I want to do when homing. But if You prefer to adapt runZProbe for homing, I would not object, I'm not specialist here. But I would like to have any z-homing method even without endstops on z-axis (as an option).

    And one more thing, would it be possible to integrate code for ADC keypad written by axelsp into main branch? It would simplify lifes of people like me, who have these cheap chinese printers with this weird chinese solutions, and want to run them on original repetier.

  • Do you have a link to the ADC patch so I can see it? I'm not aware of it yet. Main problem is that it requires reading ADC which is done in a timer interrupt for repetier so using direct polling is forbidden.Plus I have no such keypad, but adding a existing solution may be possible if it is good.
  • Sure I do, changes are described in modiefied.txt

    And one more question, how safe is using interrupt driven keypads? I was thinking about creating yet another controller module connected via i2c, and using interrupt to signal key state changes.

  • There is no interrupt driven keypad. We always use polling. I'd prevent I2C if possible. If we poll a byte it return only when the byte is received, If you get communication errors it can block the whole  system and polling is much slower then direct contacted switches.
  • Direct connected buttons would be better, but since I have 8 buttons, encoder, 7 LEDs and one display driven by parallel bus - 8 signal pins available on Melzi aux connector may be not enough. So I've thought about integrating all of them into one module controlled by another 328p (or some other avr) connected by i2c or serial port. But i2c is faster and addressable.

    I suppose I'll rewrite i2c communication code so it would be fully asynchronous and eliminate any polling on communication buses. TWI interrupt has lower priority than any of the timers, and these avrs support clock stretching, so this shouldn't interfere with timers. But will know for sure when hardware will be operational. In worst case scenario it will not work correctly, and prototypes are build to test such things.
Sign In or Register to comment.