Last weekend I finally decided to implement a Z probe on my Mendel90. I frequently swap the mirror I use as a print surface, and I think the wooden frame of the M90 expands and contracts a small amount as well – whatever the reason, my Z height does fluctuate slightly and this was my primary motivation, automatically setting the bed plane was a secondary (though welcome) benefit.
This was supposed to be a quick and dirty implementation, then I could get back to the new printer design – as ever, the reality turned out to be more involved.
I had a couple of 9g servos laying around, and mechanical end-switches, so a servo controlled arm seemed the obvious solution. I’m not an OpenSCAD expert, so modifying NopHeads original file was out of the question in the time I had available. Fortunately I already had a (mostly) completed copy of NopHeads X carriage in Sketchup (I had planed to adapt it for an E3D V6), so adding a bracket for the servo didn’t take too long, and a simple arm to attach the switch to.
Just add a servo and switch.
Build
These servos require three electrical connections (you may have different wire colours):
- +5 volts (red)
- Gnd (brown)
- PWM (orange)
5v and Ground I took direct from my power supply, the PWM signal needs to go to a PWM capable pin on the Smoothiboard (in this case 3.25).
Sorry, bad photo from my phone, but you can just make out that my switch has one of those lever arms (with a roller on the end), in theory the lever action should provide greater resolution, so a more accurate measurement. In practice I found the opposite, measuring my Z offset I never got the same figure twice. I can only assume the flat metal arm was bending, I removed the arm and started getting repeatable measurements..
EDIT
So I got that the wrong way around, I finally worked out that having a lever just amplifies any variations in the micro switch tipping point (the position where the switch tips from open to closed). Let’s say that the switch can tip between states within a 0.01 mm window (without using a lever), that means that consecutive measurements using that switch may vary by up to 0.01 mm (most micro switches would be better than that figure), but then you add a lever with a 10:1 advantage, now to move the switch by 0.01 mm the other end of your arm (measuring the position of the heat bed, in this case) has moved 0.1 mm, so your accuracy (or repeatability) just got ten times worse.
Configuring Smoothiware
Before we can configure the Z probe itself, we need to add a switch module to control the servo…
# Switch module for servo control
switch.servo.enable true #
switch.servo.input_on_command M280 # M280 S7.5 would be midway
switch.servo.input_off_command M281 # same as M280 S0 0% duty cycle, effectively off
switch.servo.output_pin 3.25 # must be a PWM capable pin
switch.servo.output_type hwpwm # H/W pwm output settable with S parameter in the input_on_comand
#switch.servo.pwm_period_ms 20 # set period to 20ms (50Hz) default is 50Hz
(from the Smoothie Wiki, switch examples)
Most these small servos turn just over 180 degrees max (some a bit less), the S parameter specifies the pulse width of the PWM signal, that instructs the servo what angle to turn to (S5 = 0 degrees, S10 = 180 degrees)
So to control the servo, you can use the following G codes (or specify any other S value between 5 and 10).
M280 S0 – turn servo off
M280 S5 – move to 0 degrees
M280 S7.5 – move to 90 degrees
M280 S10 – move to 180 degrees
Or that’s the theory, at least. When I tried to test this my servo would only move in one direction, whatever I tried. I spent the best part of a day trying different servos, different pins, different configuration settings, before I thought to update my Smoothieboard to the latest edge firmware – problem solved.
I could have a rant at this point, about the frustrating things that are missing from the otherwise excellent Smoothie documentation, if I did then the lack of any change documentation for the firmware would be near the top of my list!
So with a working servo, now we just enable the Z probe section in the configuration file, mine looks like this:
# =========================================================================================
# Z probe
# =========================================================================================
zprobe.enable true # set to true to enable a zprobe
zprobe.probe_pin 1.28^ # pin probe is attached to if NC remove the !
zprobe.slow_feedrate 1.8 # mm/sec probe feed rate
#zprobe.debounce_count 100 # set if noisy
zprobe.fast_feedrate 75 # move feedrate mm/sec
zprobe.probe_height 4.96 # how much above bed to start/finish probe
# adjust this figure to tweak final Z height
# associated with zprobe the leveling strategy to use
leveling-strategy.three-point-leveling.enable true # a leveling strategy that probes three points to define a plane and keeps the Z parallel to that plane
leveling-strategy.three-point-leveling.point1 89,184 # the first probe point (x,y) optional may be defined with M557
leveling-strategy.three-point-leveling.point2 3,5 # the second probe point (x,y)
leveling-strategy.three-point-leveling.point3 162,5 # the third probe point (x,y)
leveling-strategy.three-point-leveling.home_first true # home the XY axis before probing
leveling-strategy.three-point-leveling.tolerance 0.03 # the probe tolerance in mm, anything less that this will be ignored, default is 0.03mm (no, I have no idea what this refers to either)
leveling-strategy.three-point-leveling.probe_offsets -43.25,12.7,0 # the probe offsets from nozzle, must be x,y,z, (sign is opposite of what you would expect, and don't enter a Z offset here))
leveling-strategy.three-point-leveling.save_plane false # set to true to allow the bed plane to be saved with M500 default is false
(see bottom of this post for explanation of zprobe.probe_height)
The 3 probe points ideally are the 3 corners of an equilateral triangle (the largest you can comfortably fit on your print bed).
Usage
A manual procedure could be like this (adjust the M280 S values to suite your servo):
- move print head to a suitable Z height (to leave clearance for the probe)
- M280 S8 – probe down
- G32 – run the Z probe procedure
- M280 S12 – probe up
At this point your Z plane is set, you just need to home to Z, then you’re good to print, however this needs to be Z height relative to the first probe point. You can do that like this:
- G1 X89 Y184 – moves head to X,Y coordinates of first probe point
- manually drop nozzle to Z = 0 (use a sheet of paper, or your normal method to get the gap correct)
- M306 Z0 – sets the current height to Z = 0
These settings will stay in force until your printer is reset (or you can save the plane to EEPROM with M500).
A better strategy would be to automate this in your start G code, and probe before every print (it can run while the print bed heats up, so adds no time to a print). The following is my start G code (Z probe section in blue):
M80 ; PSU on
G4 P1000 ; wait 1 second for power to stabalise
M140 S[first_layer_bed_temperature] ; set bed temp and don't wait
G1 Z25 ; move up 25mm to ensure room to drop probe
M280 S8 ; probe down
G32 ; run Z probe (finish height is set in config file)
M280 S12 ; probe arm up
G92 Z16.2 ; set Z (probe offset (11.2) plus probe finish height)
G4 P1000 ; wait 1 second (see comment below)
M280 S0 ; probe servo off <<< if this immediately follows M280 S12 the servos switches off before the probe retract has finished
M190 S[first_layer_bed_temperature] ; set bed temp and wait
M104 S[first_layer_temperature] ; set extruder temp, no wait
G1 X150 Y0 ; move 150mm along the front edge
G1 Z0 ; drop nozzle to prevent ooze
M109 S[first_layer_temperature] ; set extruder temp and wait
G1 Z[first_layer_height] ; move nozzle to print height
G1 X10 F12000 E7 ; Wipe (move toward origin as fast as firmware permits, extruding 7mm)
So where did that G92 Z16.2 figure come from?
I started with “zprobe.probe_height 5” in my config file, so I know that after a G32 command the Z height will be 5mm (you can confirm this with M114), but this is 5mm from Z probe to print bed (not hot-end nozzle to print bed). So perform a manual height adjustment to find your real Z = 0, now the Z height returned by M114 (-11.2 in my case) is your Z offset (the difference in height between the probe, and the hot end). So G92 Zn sets the Z height to value n (11.2 + 5 = 16.2).
In Slic3r I have multiple profiles (different filaments, different print surfaces, etc), so rather than edit every profile it makes sense to make any fine adjustment of Z in one place only (hence in my config file it now says “zprobe.probe_height 4.96”)
Good writeup.
I have a queston about the offsets “leveling-strategy.three-point-leveling.probe_offsets”.
If the nozzle is at X0 Y0 and the sensor is at X25 Y25 is the offset negative or positive?
Hey Scott, sorry for the delay – seems I hadn’t set WordPress to email me when anyone entered a comment
If I set my nozzle at x=0, my sensor is at x=-43.25
In “leveling-strategy.three-point-leveling.probe_offsets” this is set as a negative offset (-43.25)
So in your example, with an offset of X25, Y25, Z0, the config file would read:
leveling-strategy.three-point-leveling.probe_offsets 25,25,0
Thanks much!
On my printer leveling tries to work but does not seem to compensate sufficiently for “out of true” conditions. Currently I have to offset set to 0,0,0 since it’s not related to the Z offset. I set Z with G30 Z1.2 after running G32 and returning to the first point used for leveling. On a flat plane the relative compensation should be the same.
I’ve gone through the code and may need to break down and get the compiler set up.
Talked to Arthur about this once but didn’t get any answers.
Hello, I could reallllllly use your help.
So I have an inductive sensor on my bed and I have a 4 point adjustment heated bed. Will it still work with this method? I get the results:
SENDING:G32
DEBUG: P0:-0.0012
DEBUG: P1:-0.2032
DEBUG: P2:-1.3205
DEBUG: plane normal= -0.005586, 0.005071, 0.999972
Probe completed, bed plane defined
_______________
But even with this, for some reason I swear I don’t see my steppers compensating.
The type of sensor, or number of bed leveling points, shouldn’t affect this. That output looks normal, so try watching your Z stepper(s) during one layer of a print.
To make it obvious you can put an exaggerated tilt on the bed surface, as a test.
I see them moving, but they just don’t move enough or they move too much. I can see it trying to compensate but no matter what I do I can’t get uniform first layers. It’s killing my prints and honestly killing my enthusiasm for anything smoothie…The wiki doesn’t really describe well enough how to add multi-point bed leveling which is what I used with ramps and got great results.