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

Auto bed leveling using piezo discs

by elenhinan Mar 3, 2015
Download All Files

Thing Apps Enabled

Please Login to Comment

What circuit did you use? I see two schematics on the page and I don't know which one is better.

Hey! Awesome work!! Could you attach some BOM please?

Thanking in advance!

Thank you for this thing! Thumbs up to you!

  • Sent from 3D Geeks: Thingiverse Browser for Android

Could I rig an ultrasonic sensor to sense the distance from the top of the nosel to the bed? If so how would I interface it with the printers software to be automated and/or control the x y and z axis.

I would us ardunio pro mini and anet a8

Hi! Could you provide the link, where have you got this X-carriage and hot end mount? Thanks

Solidoodle E3D v6 bowden mount with radial fan

many thanks. nice job

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.

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

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.

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.



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.

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 :)

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.

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.

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.

.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

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.

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!

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?