Using piezo disks for automatic bed leveling on 3D printers

11 Sep 2019 - tsp
Last update 27 Nov 2021
Reading time 12 mins

Updated: How to wire correctly (at the end of the blog entry)

Update August 2021: New firmware available for the board

What is bed leveling and how can it be performed?

What is bed leveling? The idea behind bed leveling is to give a machine (for example a 3D printer as in the following case, a CNC mill or any other machine) a way to sense the layout of the machine bed or building plate. When not using bed leveling one normally assumes a given bed layout - for example on a 3D printer one assumes that the bed is leveled and perfectly parallel to the 3D printer axis, the same on a mill. It is also assumed to be at a given z offset relative to the z axis endstops. Zero along the X and Y axis is normally determined via any other mean (for example using mechanical endstop switches or inductive, capacitive, ultrasonic or optical sensors). This raises the requirement for the build plate to be as parallel to the build axis as possible - which is of course always a good idea if you’re not using one of the infinite size beds built around tilted conveyor belts. On the other hand there are many machines where one manipulates the bed - for example on 3D printers one might change the coating on which on prints, at CNC mills one might add additional clamping mechanisms although it’s normally assumed there that these are precise and that the workpiece is resting on the build plate itself.

To gain more precision than having a calibrated system one can perform a measurement of the build surface (and for CNC machines of the workpiece and it’s orientation if one does multiple manufacturing steps on different machines) before each build or on a periodic schedule. This allows the control software to adjust itself to changes in machine geometry. Of course this doesn’t mean one should ignore mechanical precision, a machine should as usual be as precise as possible - but it allows to compensate for different errors or gain more precision than would be possible with a mechanical solution.

At 3D printers bed leveling is typically performed by a variety of methods:

Leveling via touch probe (The first try)

Note: This section describes the first try that seemed to work somewhat at first but had to be modified later on (as described below).

The following article describes some experiments and solutions to do bed leveling via a touch probe. The basic idea is to sense the contact between the 3D printer nozzle or a milling tool and the printer bed or machine table. On a 3D printer one cannot use a simple conductive probe (i.e. sense the contact between the nozzle and a conducting bed) since one normally uses a non conductive coating as described above. To overcome that problem one can use pressure sensors. Since they are readily available I’ve tried to use piezo disks as sensors. They are cheaply available in huge quantities and are salvageable from electronic waste like watches, cheap microphones, classical guitar and violin pickups, etc. The are basically manufactured by attaching a layer of piezoelectric material onto a metal plate and connected on the top of the sandwich as well as on the metal plate.

The effect being used is the piezoelectric effect. This effect can occur in materials that change polarization with mechanical stresses (i.e. average charge carriers are moved inside the material in case of stress changes). The model normally used to describe the piezoelectric effect assumes that one can calculate the balance point for positive and negative charges - and as soon as one applies stress to the material it deforms which leads to the formation or change of the dipole moment inside the material. Polarization changes then lead to a change in electrical potential and thus in voltage - which again leads to a small current. The piezoelectric effect can be used to measure (i.e. mechanical stress leads to induced voltage) or inversely to induce deformation by applying voltage. The latter method is used in some high precision machines like scanning tunneling microscopes or high precision mills. It’s also used in cheap watches to generate the buzzing noises. The direct effect that is used for bed leveling sensors on the other hand is also used in microphones, accelerometers and other stuff seen on a day to day basis.

There are two possible placements for the piezo disks. Since the printer I’ve built already had an finished and not easily changeable printing head I’ve decided to add the piezo disks below the build surface. This is possible since the build plate is not too huge - the idea was to put one piezo disk into every corner and rest the whole weight of the mounting frame for the heatbed onto these disks. Since the disks have welded and soldered cables on top I’ve added a small spacer (using some cents) above the piezoelectric layer and put the table on top of them. After that I’ve connected all four piezo disks in parallel for the easiest and cheapest solution. That might not be a good idea in every case since - under some circumstances and geometries - it’s entirely possible of occurring voltages to cancel out.

The next problem when connecting piezos to microcontrollers was that they produce positive and negative voltage depending on the direction of deformation. Since the idea was to use an single rail ADC for measuring (i.e. the ADC functionality of the AVR itself) a voltage divider consisting of two $1 M\Omega$ resistors is added. This provides biasing of the piezo discs such that one can measure positive and negative voltage spikes. One can of course use different voltage dividers. Lower resistor values lead to higher leakage current and less sensitivity, higher resistor values to higher sensitivity of the system. One shouldn’t use that approach when using other piezo sensors - because their voltage spikes can be way to high for the AVR and it’s internal protective circuits to handle - but using the piezo disks directly with the biasing resistors attached works pretty well.

Most simple schematic

Touch event (touch and release)

This way one can simply run normal bed leveling

Measured grid - probing points at the 0 X axis are wrong because the table was not
that large

One just has to tune the thresholds to prevent triggering because of external noise and vibrations - and to stay sensitive enough for the slow touch during the probing moves. In case simple thresholding does not work:

If this is still not enough one could in theory perform event fitting (i.e. try to fit an function that models charging and discharging of the circuit during a touch event) to discriminate touch events a piezo sensor might not be the right choice.

And additional upgrade would be to sample all piezo disks separately. This would also allow absolute position determination of the touch event.

Update: Increasing sensitivity and working with manufacturing differences

As turned out the system as described above was not nearly as sensitive as it could be and has a dead section in about 20 percent of the plate. This turned out to be caused by manufacturing and wiring differences with the piezo disks. To solve that problem each piezo disk has been attached to it’s own analog digital converter. This has first been tried with an ATMega328P. The system can now also report the signal shape for all four disks. As one can see the centerline of one of the piezos is shifted towards lower voltage. This caused the system to oscillate sometimes and caused the lower voltage disk to be way less sensitive then the other disks.

Running the same system with 4 channels and the same frequency allows more reliable detection of touch events and being less sensitive to external vibrations like passing cars or trains.

Modified schematic

Simple PCB with 4 independent channels

Touch event of all 4 disks

As one can see the design also has been modified to allow I2C communication for configuration and calibration as well as reading measurement data and flashing with an suited I2C bootloader as well as ICSP programming. The board also has an option to add an local 5V DC-DC regulator as well as an additional input for a traditional bed leveling sensor. This allows to run detection in coincidence mode to provide increased noise immunity for larger Z travel distances (i.e. trigger only whenever the standard z level sensor and the piezo sensors trigger). One can also support switching between piezo and classical mode.

All KiCad design files are available on GitHub.

A really good manufacturer for PCBs for hobbyist quantities is PCBWay.

Material used

Note: All links are Amazon affiliate links. This pages author profits from all qualified purchases

Update 2: Some test code for the board

Some test code for the board presented above using the Arduino IDE (for easy deployment) has been uploaded as a GIST. This code does not supply connectivity via I2C.

Update 3: New mount for heatbed

After some months of operation using a rather hackish setup I’ve decided to add a new mounting frame below my heated bed. This has been done because the load distribution onto the piezo sensors has not been equal - to counter that I’ve added an rigid aluminum mounting frame with four M3 screws that allow the frame to rest directly onto the piezo disks at an adjustable distance. Another additional feature of the mounting frame is that it solves my previous mounting problem - my heatbed had just been attached to the table using Kapton tape which has lead to some problems when unmounting and remounting the heatbed after reapplying the print surface since the positioning on the piezos is somewhat critical. The only problem solved currently using Kapton is the mounting of the piezo disks onto the base table. Since the lower side of the sensors is kept at ground potential I’ve not added Kapton below the sensors themselves.

New bed mounting frame

Extendable feet

Frame mounted on the printer

This article is tagged: Electronics, DIY, Projects, 3D Printing

Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support