Hey! This thing is still a Work in Progress. Files, instructions, and other stuff might change!

Auto bed leveling using piezo discs

by elenhinan, published

Auto bed leveling using piezo discs by elenhinan Mar 3, 2015
3 Share
Download All Files

Thing Apps Enabled

Order This Printed View All Apps


Use This Project

Give a Shout Out

If you print this Thing and display it in public proudly give attribution by printing and displaying this tag.

Print Thing Tag


Thing Statistics

10773Views 566Downloads Found in 3D Printer Accessories


Auto Bed Leveling using piezo electric discs for very high sensitivity.

Update v 0.2!

Now using a single piezo disc glued (temporarily at least) to the x-carriage (see image). With the piezo element glued between the two bearings gliding on the x-axis shafts, and tiny amount of twisting (like the hotend touching the bed) will ever so slightly bend the plastic in the x-carriage. Since the piezo is glued on top, this will bend as well creating a relatively large signal. Thus even a minuscule force acting upon the hot-end can be detected using some electronics. This solves the problem of the previous setup with differing sensitivity of the three piezo discs (due to the discs them self and/or the mechanical setup) in v 0.1. Auto leveling is now even better, giving a perfect first layer every time (as long as the nozzle has been wiped clean of plastic, that is).

New video:

Still to do: Electronics is rather sensitive to EMI, so I'm waiting for a metal case for it. Right now, it can trigger when probing too close to the x-axis stepper if it's moving, so a quick fix right now has been to add a pause (in firmware) after moving to the right x-y position before starting the z movement.

Old v 0.1 info:
Mounted between the bed springs and the z-stage, any force down on the bed can be registered and used as a probe signal. Hence one can measure when the hot-end touches the bed surface. No modification to the hot-end or carriage is therefore needed, and the probe is insensitive to temperature.

This is still a work in progress, so although it is working for me in it's current form, it needs constant tuning as the circuit is not yet perfected, and the mechanical mounts have some known issues. A new circuit and new mounts have been designed but not yet tested.

So far, I've tried to only use parts available from sparkfun. I'm guessing a total cost for all parts of less than $20 USD.

Video of version 0.1 doing bed height mapping : https://www.youtube.com/watch?v=Zn9X-WGBuvQ

Discussion at soliforum:


Print the v0.3 back, and two v0.3 fronts, one of the mirrored. Drill the smaller hole out to 3 mm, and the larger one to 4.5mm. Glue the piezo disc underneath using silicone glue. Use an m4 screw to center the lever on the holes in the bed-holder, and drill through the 3mm into the aluminium, so that you can use some m3 screws to fasten the levers to the bed-holder. The rest of the mounting should be self explanatory.

Since the sensors are very sensitive, the acceleration of the z-axis and the intertia of the bed can be enough to trigger the probe. It can therefore be helpful to disable z-jerk and decrease z acceleration. With repetier firmware, there's a seperate travel acceleration setting, so this is the script I use:

G0 Z10; goto 10mm z height to prevent crashing in bed
M202 Z30; set z acceleration
M207 Z0; disable z-jerk
G32 S0; auto level
M207 Z5; restore z-jerk
M202 Z300; restore z acceleration

More from 3D Printer Accessories

view more

All Apps

3D Print your file with 3D Hubs, the world’s largest online marketplace for 3D printing services.

App Info Launch App

Auto-magically prepare your 3D models for 3D printing. A cloud based 3D models Preparing and Healing solution for 3D Printing, MakePrintable provides features for model repairing, wall thickness...

App Info Launch App

Kiri:Moto is an integrated cloud-based slicer and tool-path generator for 3D Printing, CAM / CNC and Laser cutting. *** 3D printing mode provides model slicing and GCode output using built-in...

App Info Launch App
KiriMoto Thing App

With 3D Slash, you can edit 3d models like a stonecutter. A unique interface: as fun as a building game! The perfect tool for non-designers and children to create in 3D.

App Info Launch App

Print through a distributed network of 3D printing enthusiasts from across the US, at a fraction of the cost of the competitors. We want to change the world for the better through technology, an...

App Info Launch App

is this project still under development. is there a github or website with more info on the current method with only one piezo in use?


Right now I'm not doing any development. In my newest printer design the bed is much stiffer, so auto leveling isn't as critical anymore. You can search on reprap forum for piezo auto level, there are some folks there who has done some more work on the concept.

Mar 10, 2016 - Modified Mar 10, 2016

Nice work. A few remarks and questions:

Soldering piezo disks is not without risks - heating the piezo crystal above the Curie temperature leads to a loss of polarisation and thus impact reponse. Either use a very low melting point solder like wood metal, or use a conductive glue for best results.
If the disks come with prebonded wires, skip the above remark.

Did you consider to use force sensitive resistors (FSR) instead of the piezos? That would make the filtering and polarity-dependance obsolete.

Do you have to tune and balance the single piezos? I would imagine that, depending on where the nozzle makes an impact, the response of the three sensors varies considerably. How does the location of the impact to the three sensors influence the measured surface level - as a function of the location?

Just an idea: mount another active piezo close to the nozzle and let it vibrate at a suitable frequency. Then don't measure the impact but the sudden volume increase from the sensor piezos, then acting as microphones. Feasible?

Problem with sensitivity of three piezos solved now, by only using one by the extruder and using it as a strain gauge. I've ordered a regular strain gauge (7x4mm) to test if this can be used instead.

I saw elenhinan's thing when I was researching sensors for bed leveling and decided to try a modification where the sensor is effectively under the adjusting nut. This makes the force/movement slope much more rapid. With a bed contact speed of only 1mm/second I got an astonishing 8 volts output. Only a couple of hours ago I got it rock stable. Details on http://www.thingiverse.com/thing:1399512.

Piezo disk bed leveling for 3D printers

Nice design. Also good job documenting it, I have a tendency to delay documentation until later, and then forget it all together :(

How is the repeatability and accuracy?

The biggest problem at the moment is that it is too sensitive. Starting a bed mapping often fails and there are erratic misreadings. The main problem is shaking after an X or Y movement registering on the sensors.
At its best the repeatability and accuracy are very very good. A run of 5 G29s below.
14:01:18.234 : Z-probe:9.63 X:40.00 Y:40.00
14:01:29.890 : Z-probe:9.68 X:140.00 Y:95.00
14:01:41.453 : Z-probe:9.58 X:40.00 Y:130.00
14:01:46.265 : Z-probe average height:9.63
14:01:46.265 : X:40.00 Y:130.00 Z:10.000 E:0.0000
14:03:11.109 : Z-probe:9.61 X:40.00 Y:40.00
14:03:22.718 : Z-probe:9.67 X:140.00 Y:95.00
14:03:34.281 : Z-probe:9.58 X:40.00 Y:130.00
14:03:39.093 : Z-probe average height:9.62
14:03:39.093 : X:40.00 Y:130.00 Z:10.000 E:0.0000
14:03:55.671 : Z-probe:9.61 X:40.00 Y:40.00
14:04:07.281 : Z-probe:9.68 X:140.00 Y:95.00
14:04:18.843 : Z-probe:9.58 X:40.00 Y:130.00
14:04:23.656 : Z-probe average height:9.62
14:04:23.656 : X:40.00 Y:130.00 Z:10.000 E:0.0000
14:04:52.859 : Z-probe:9.61 X:40.00 Y:40.00
14:05:04.468 : Z-probe:9.68 X:140.00 Y:95.00
14:05:16.031 : Z-probe:9.58 X:40.00 Y:130.00
14:05:20.859 : Z-probe average height:9.62
14:05:20.859 : X:40.00 Y:130.00 Z:10.000 E:0.0000
14:05:39.062 : Z-probe:9.61 X:40.00 Y:40.00
14:05:50.671 : Z-probe:9.68 X:140.00 Y:95.00
14:06:02.234 : Z-probe:9.58 X:40.00 Y:130.00
14:06:07.046 : Z-probe average height:9.62
14:06:07.046 : X:40.00 Y:130.00 Z:10.000 E:0.0000
I am trying to tease out all the spuria from the mechanical and electrical (possible comparator oscillations) sources before asking Repetier for any tweaks like introducing or adjusting a delay before reading etc..

An option would be to switch off the sensor circuitry after it has done its job. Great work, congratulations!

What is DIA of piezo? I think that 27mm is more sensevity then 18mm.

So how does someone with little electronics knowledge get this setup with marlin on there 3d Printer.. where do I find the sensors? and PCB board. I love this idea.. I need to get this for my machine

Nov 16, 2015 - Modified Nov 16, 2015

Verified: OPA2340 can be a replacement part for the AD822. OPA2340 is cheaper about the two third of AD822 (at the Korean local store). I just tested the circuit with OPA2340 and it's equivalently working fine.

Nov 9, 2015 - Modified Nov 10, 2015

Now I'm happily printing bed-wide model with less stress. It works like a charm!

However when I try a second print just after the first print, this sensor becomes too sensitive, and any slight squeak in Z axis activates the sensor. I think it's because of the ambient temperature.

My first trial is adding an active cooling fan to the sensor circuit. It effectively cool down the ICs however the problem remained unsolved.

At a guess, the piezo discs become sensitive when they are heated. My printer is fully chambered printer and the ambient temperature raises about 50 deg (Celsius). In addition, the piezo discs are located under the bed, which is heated up to 110 deg. They are definitely placed at the harsh condition.

Nov 9, 2015 - Modified Nov 9, 2015



I added nozzle cleaning box and made script to get rid of ooze while probing.

I also modified the Marlin firmware to disable the repeated probing action. It seems that the low-pass filter malfunctions with two quick consecutive nozzle touches. Also, reduced Z axis speed at the second touch slows down the signal raise, results in inaccurate probing.

In detail, I modified run_z_probe() function in "Marlin_main.cpp" as follow.

static void run_z_probe() {
   feedrate = homing_feedrate[Z_AXIS];

   // move down until you find the bed
   float zPosition = -10;
   plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);

   /* Commented out to disable the repeated test in z probing.
       // we have to let the planner know where we are right now as it is not where we said to go.
   zPosition = st_get_position_mm(Z_AXIS);
   plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]);

   // move up the retract distance
   zPosition += home_retract_mm(Z_AXIS);
   plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);

   // move back down slowly to find bed
   feedrate = homing_feedrate[Z_AXIS]/4;
   zPosition -= home_retract_mm(Z_AXIS) * 2;
   plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);

   current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
   // make sure the planner knows where we are as it may be a bit different than we last said to move to
   plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);


This circuit (http://www.electroschematics.com/6023/vibration-sensor-circuit) looks like it would solve the polarity issue and can easily drive a relay circuit like I will need since my control board uses low (ground) for end stop detection. Here's another useful piezo detector circuit (http://www.engineersgarage.com/contribution/vibration-sensor-circuit-diagram) for reference.

You could try, if it works for you then it's a simpler circuit.

The reason mine is more complex is to filter out high frequency noise and eliminate signal drift from stray/cable capacitance due to cable movement. It also detects force, not vibrations/impact. Since it detects force, it's dependent on the direction of the force, hence the polarity of the piezos must be the same.

If you need to detect on falling edge (ground), you only need to switch pin 5 and 6 (+ and -) on the last op-amp. The led should then be off during normal operation, and on when detecting force/touch.

Oct 26, 2015 - Modified Oct 26, 2015
hatfieldta - in reply to elenhinan

Why are you detecting force vs. simple impact for auto-leveling? Can you post the full schematic of your latest circuit? The input and output sections are clipped in the photos above... I'd like to try both and see which one appears to best fit my application. Thanks!

Because my bed moves in the Z-direction, so when it starts to move it vibrates. This would trigger the circuit. Also, it should work better at low speeds (more accurate) than impact, which would probably need higher speeds. The impact should be close to a DC signal plus some slight ringing. The DC signal would be stronger and easier to filter out.

I came to this solution using some theory and some experimentation. It should be quite robust now, and hopefully give good repeatability.

The whole circuit can be seen if you click the fullscreen symbol in the upper right corner, it's only clipped in the gallery mode :)

Oct 22, 2015 - Modified Oct 22, 2015

Some update:
I made a PCB and tested the circuit (two OP-Amp ver.) and it seems to work fine.

During test, I found that piezo discs tend to have random polarity.
If I connect them to an oscilloscope and do some tap, some units show negative peak and others show positive peak. And the circuit only worked properly with negative peak ones. Also, packing up multiple units need to align their polarity.

Q: The circuit design was designed to handle the polarity problem? Did anybody find similar phenomenon?

Did you etch a PCB or did you have one produced? Or proto-pcb?

I used "Sample PCB service" from the local shop. I ordered 4 units and it costs approx. 70$.
I got 7 bare PCBs (they gave me some extra!) and soldered all components by myself.

I'll post the corresponding Eagle CAD design as a remix.

Oct 22, 2015 - Modified Oct 23, 2015
inornate - in reply to inornate

PS. The comment I wrote might be misread. I implemented four OpAmp ver. (=2*dual-OpAmp chips), not two OpAmps.

Good catch :) Didn't think to consider that the polarity of the cheap discs might be random, but it explains why one of my sets isn't working as it should.

No, the circuit is not designed to handle this, and I don't think it would be the right way to solve the problem either. I guess just buying 10 pieces and sorting them would be the best way.

Sep 17, 2015 - Modified Sep 17, 2015

My printer is a fixed bed cartesian printer ( http://xyzist.com/wp-content/uploads/2015/07/XYZist-2015_3DProtokor-Lincsolution_001.jpg ).

So this thing would be super effective, because there's no bed movement thus it will not be false-positive induced by bed inertia.
Also I found OPA2340 in my part storage and I'm planning to use it. It looks it have similar characteristic to AD822.

I'll report the progress occasionally.

PS. I'm now collaborating with the printer (in the picture above) company. Will this idea can be included in their product? I think their unique structure (bed fixed, XYZ all-in-one staging) and this sensor have an overwhelming synergy.

Good luck, I hope you get it up and running soon with good results.

I just changed the license from non-commercial to share alike, so it can now be used in a commercial product (http://creativecommons.org/licenses/by-sa/3.0/).

Is there a reason for changing OpAmp from LM358 to AD822?
May I use the LM358 to the new circuit? (with two opamps?)

AD822 is a rail-to-rail op-amp, so it can output 0-5 V with a 5V supply, whereas the LM358 can only output 0-3.5 V. So it makes the allowable voltage swing a bit tighter.

However, if you change the supply voltage to 12V, it won't matter. But then one would have to add a diode or voltage divider to the output so you don't fry the arduino.

Another solutions is to change the 2.5 V reference generated by R1 and R2 to something close to 3.5 / 2 = 1.75V by changing those resistors.

Ultimately, it should work fine with LM358 as well.

Thank you for your kind answer. If my understanding is right, it's matter of the maximum voltage the op-amp can output. I'll find a rail-to-rail type op-amp in my part box first, and if there aren't I'll try 12V supply. Thanks!

Great! I'm very inspired by this design. I got the same idea and searched Thingiverse.. and Voila! This project have been shown.

One quick question: Does multiple piezos are connected in parallel? Or each piezo requires their own circuitry?

Not a stupid question. The reason I went for the transimpedance amplifier is so you can wire a whole bunch of piezo's in parallel, and not need a dedicated circuit for each one. With a normal voltage amplifier, the signal would get weaker for each piezo in parallel.

Ah it was stupid question. Picture has the answer. It's parallel.

Added a new circuit I tested yesterday, with great success. Uses two dual op-amps. One as a buffer for single supply power, one transimpedance amplifier so stray capacitance and capacitance in wires can be ignored, one integrator (with very aggressive low pass filtering) and the last one for thresholding. Schottky diodes added to protect circuit from sudden voltage spikes, especially important when the unit is turned off and something is dropped on the build plate.

This circuit triggers very reliably, and is not affected by high frequency vibrations. I'll update the description when I've tested it more thoroughly, and maybe add some new video and screenshots from the oscilloscope.

Jul 29, 2015 - Modified Jul 29, 2015

.I think zoltrax printer use this methot...squarewave and decetor circuit it is very simple I add circuit picture made page..
N3 N4 squarewave generator , N1 N4 decetor... when touch antenna ( C2 and C3 connection point) squarewave short circuits to ground
via C2 and hand or nozzle..

I used this circuit another projects for dedects tampered glass and normal glass it is work well ...it can be used auolevel

Jul 28, 2015 - Modified Jul 28, 2015

I wonder if you sent a sinewave to non-detecting piezos if the detecting piezo would pick it up. Then when the head touched the board the sinewave would be dampened.
That way you would have a lot more control over the sensitivity.

Nevermind, I see in your reply to glennwest, you've already considered this.

how about the inverse. I notice my delta, there is audible vibration most likely from the fan, that gets damped the moment that
the hotend touches the bed. Why not intentionlly generate a waveform, then detect when it get damped. A Piezo transmitter, and
a piezo receiver. a narrow bandpass could be used. I'm thicking of a low pin count m0, with a/d d/a could do this well.

It's a good idea :)

I've played with similar ideas myself. Either generating a waveform in the plate, or at the hot end to check for dampening/transmittance at contact. It shouldn't be to hard with analog electronics either, but at the time I didn't have a oscillioscope so it would've been hard to debug.

Theoretically, I guess it would be possible to glue just one piezo element to the hot plate, send a sine wave, and then switch to listening mode and measure how quick it decays. If I had more time on my hands I would've like to try. At high frequency one should be able to repeat this some 10-100 times per second I guess.

which firmware ?

I use repetier firmware 0.92, but Marlin should work as well.

thanks for answer
I want to implement it my printer (like a mendel) I use repetier 0.91 I can update 0.92 but I want know How can I multiple probe point ? ( I watch your video your printer touch more then 3 points...)
I know only 3 points
could you share z probe code (configuration.h.) ..?

Repetier 0.91 should also work I think. But repetier can only do 3 point, I believe marlin can do more. But as long as the surface is flat, 3 will be enough as it only does an affine transform (linear). In the video I run repetier host bed height mapping. Sorry for the confusion.

Comments deleted.

No problems
thanks again..

Hi Elenhinan
I made it my printer circuit and sersors work well but My printer start printing 10mm above the table how can I calculate z probe hight or I didnt Z enstop
I connected my circuit output Z endstop input ( with relay)
where is the wrong ?

How did you connect it? I have z min endstop connected as usual, and configured the firmware to use the z max pin for probe. Check in firmware also if it should be inverted or not.

Maybe I'm just obtuse, but you've lost me here. You hooked your sensor output to where? I've also been looking for the circuit schematic which I'm sure I've seen somewhere other than the odd photo here on Thingiverse. I've got my V.3 parts printed and working on getting the platform modes into place soon. So, planning on how to hook this up as it seems to be a hugely helpful mod. I see the three wire connection which I assume is V+,GND, and OUTPUT. Then it looks like all three piezo sensors are simply hooked in parallel. I'm guessing the "script" bits are g-code that goes into repetier somewhere? I've looked at my config options and haven't found may of the settings, so I'm a bit nervous about needing to compile the firmware itself. Looking forward to this; thanks for the ground work!

Mar 22, 2015 - Modified Mar 22, 2015
elenhinan - in reply to ta1dr

Cool! Glad you were able to make it work.

Have you checked "Z-probe height" in firmware eeprom configuration (from repetier)?
I have these settings:

Z-probe height: -0.1mm

Z-probe x offset: 0.0

Z-probe y offset: 0.0

Max Z-probe bed distance: 5.0

Z-probe speed: 5.0

And then you need to run "G32 S0" to initialize the auto level algorithm

I'm waiting for an oscillioscope to arrive (about one month from now), when it arrives I'll hopefully have some free time to tweak the circuit more


I connect circuit 12 volt but it is oscillation when nozzle heater driving. remove 12 volt and connect 5volt now no any problems
I thing ...I need to z-endstop becuse printer didnt know Z axis zero point ...my auduino mega fired I need a new I will try ASAP
thanks for help...

Oh,it should really only be connected to 5V. It might be a good idea to connect a 10k resistor in series with the output just in case as well.

I add NPN transistor output when probe touch , it is send ground (like normaly open endstop) I repeair arduino

keep trying not to stand :-)

OK my system work well at 5volts and I use G32 S1 no any problems...
thanks again for help and share..

I am so going to incorporate this into my printer! I have a prusa i3 style with a z axis that moves the print head, rather than the build surface. Any thoughts on weather this should be mounted to the print head or the y axis build plate mount?

I have no experience with the prusa i3, but I imagine mounting it on the print head would be more difficult than the bed. Also, since the bed is stationary while probing, this would be ideal :)

I have a smartrapcore and I am really interrested in your design. In this printer, the bed moves up and down, thus I fear that the piezo will triger while moving so I plan to set it in the head (if I manage).

I found this circuit, do you think it will work for the piezo ?

I test LM393 module like this. It working only when you hit piezo very hard. In short amplifier needed.

That is interesting for the price but i dont know much about electronics. Did you try it?