(Final) Tuning the Elegoo Mars

After investigating the Z-height inaccuracy on the Elegoo Mars, and applying the official motor replacement sent to me by Elegoo (they have the best user support!) I was left with one unanswered question – what causes the last, quite small (roughly 2 %) linear error on the models’ height?

I started to measure the movement of the arm using an indicator, however, all the measurements looked good. I even measured the original screw using an optical microscope (see the raw data). It is pretty good – it features practically no jitter and only small linear error (0.2 mm/150 mm) which could be easily compensated in software.

Then I printed a large staircase (see photo below) which revealed the fact I was missing – the error is not linear. The printer prints some levels higher and some lower. The cause is in the combination of the long printing arm and the Z-rail. The Z-rail provides good guidance in the direction of the axis movement, however, it does not preserve the parallelity of the carriage and the axis. It means the carriage can “wobble a little bit” during the movent which translates into an observable difference in the Z-height on the end of the long arm (see illustration below). The reason I did not get the problem with an indicator was that I was measuring too close to the screw. My bad – there’s not plenty of places you can mount the indicator on the printer and I went with the easiest one…

There is no easy fix, however, as tuning Elegoo Mars become my hobby in the last few months, I decided to rebuild the Z-axis. You can see the results below:

I machined the new axis column and mounted two linear rails there. The columns are scraped so they are perpendicular to the display – currently, the perpendicularity is withing 0.03 mm/150 mm. I am not sure if it is an improvement over the original rail as I forgot to measure it. Also, the new rails were shifted so the linear rails are in a plane of the screw – this arrangement should minimize the wobbling of the carriages caused by the screw pushing to them.

I also decided to switch to a ball screw instead of the original one. Precision was not the main reason here – the original screw is pretty good and also featured practically no backlash when I used a casted nut. However, the casted nut has a too tight fit and squeaked occasionally. It was also an opportunity to use a proper screw housing with proper bearing. It also allowed me to mount the motor using a flexible coupling, thus to mitigate resonances from the motor. I used 1204 screw with appropriate FK10 housing.

I also changed the stepper driver to Trinamic TMC2025 – it supports StealthChop – a special current chopping, which allows the motor to move practically silently. I also changed the fan for quiet one.

Note that the modification are not final yet – some prototyped 3D printed components need to be properly machined (this is mostly as a proof-of-concept) and the wiring needs to be tidied a little.


The most noticeable improvement is the reduction of noise during printing. The printer is quieter than many laptops. I have also verified the printer produces square models that fit nicely together – and most importantly have the correct height. However, there is minimal or no improvement in the surface finish – it stays pretty much the same (as there is not much to improve anyway). So if you are printing minis and not functional pieces do no bother with such tuning.

If you are interested, you can download the CAD files for modification: https://a360.co/36D6BHS.

Did you enjoyed the post? Consider supporting me on Kofi:

Getting Rid Off The Elephant Foot On Elegoo Mars

In one of my previous posts, I examined the XY precision of the Elegoo Mars printer. If you are not aware of the “exposure bleeding”, please read the post first. There was one problem though; ChiTuBox does not support compensation for exposure bleeding. Therefore, your models can be slightly overgrown and most importantly, when you print directly on the build plate, there is en elephant foot – the first layer are roughly by 0.1-0.4 mm larger than they are supposed to be. This is due to the long exposure period of the first layers.

I wrote a simple command-line utility, which I call ElegooMarsUtility, in September. The utility can read an already sliced file and compensate for the exposure bleeding by eroding the image (imagine removing a few pixels on the edges of white areas). You can find the utility on its GitHub page.

I posted about this utility on the Elegoo FB Group, however, people seem to struggle with the usage of command-line tools. Finally, I found a little spare time, so I programmed a simple (and probably lame) GUI for the tool, so people can use it. I hope it will do the job. It is a single form window, where you enter your compensation values in pixels, specify the input and output files and hit the run button. After a while (depending on the size of the input file) you get a compensated file.

If you use Windows, you can download the utility here, if you use Pip. Unfortunately, the Windows version is bloated and takes few seconds to start, however, there is not much I can do about it – it is the price for having a single executable. If you install the tool on Windows using Pip, the startup will be instant.

Also, if you like the tool (or my other work) consider supporting me on Ko-FI. Supporting me allows me to buy hardware and resing which goes into my research and experiments.

Most importantly; the utility works with the anti-aliased files (thanks to fookatchu and his wonderful library for handling the sliced files) and allows you to specify compensation for the bottom layers and the normal layers. This allows you to get rid of the elephant’s foot.

What compensation values you should put in? It depends on your resin and exposure time. The best way is to experiment. Personally, for Elegoo Gray I use an exposure of 8 seconds, bottom layer exposure 30 seconds, the bottom layer compensation is 6 and the normal layer compensation is 1.

One last think about the compensation. Currently, the tool compensates only for exposure bleeding. However, there could be also an error caused by the UV-light rays not exposing the resing perpendicular to the build plate, but under a slight angle (as the light source is more a point than a surface). I was not able to measure the impact of this effect on the size of the components – in theory, the worst-case scenario is that the error is 0.02 mm on the sides (based on the light source geometry and the layer thickness). The error depends on the position of the object on a build plate – objects placed in the middle are effected less than the objects on the sides. If it proofs that this error is significant, I will implement it into the tool. However, as we are dealing with compensation less than a pixel, it requires some experimenting with partial exposure.

Testing the precision of Elegoo Mars – Volume 5: What’s wrong with the Z-axis and how to fix it? (finally)

After publishing yesterday’s post I observed a strange thing – the lid of my Elegoo Mars came off during printing. The encoder I mounted on top of the Z-axis bounced it off. That was strange, how? And then it hit me. I have never, ever measured backlash of the bearings of the lead screw. I have only measured the backlash of the screw itself. Well, I think a video is worth more than a thousand words:

There is a play roughly 2 mm in the housing of the lead screw! I disassembled the printer:

The cause is clear – even the motor has a lead screw as shaft and therefore, you would assume it is designed for axial load, it is not. There are ordinary ball bearings (no axial nor angle contact bearings) and most importantly – there is a spring washer tensioning the bearings – just like in an ordinary stepper designed for purely radial load. This is, in my opinion, a clear failure of the motor manufacturer MOCOC TECH. Also, there is another source of problems – the silencer – as the screw is mounted in the motor and the rubber silencer is soft. The silencer probably prevents from resonating with the top plate of the printer and also creates a flexible element which can compensate for the axial misalignment of the screw and the nut.

When you combine this flexible play in the screw with my observation about forces present during printing, you get imprecise print height – up to the size of the play of the screw. It can shrink or squeeze your layers arbitrarily.

What is the solution? There are three solutions in my mind:

  • dirty & cheap – get two M8 washers, put them in the motor’s rotor, remove the spring washer and tightened motor body screws carefully to slightly tension the ball bearings. Also, remove the silent block. This is a solution for roughly 3 CZK. Warning: This is a dirty solution. Deep groove ball bearings are not designed for axial load nor tensioning. Also by removing the silent block, you remove flexible element which could compensate for misalignment of the screw and the nut. Your risk shorter life of the bearing, screw, and nut. On the other hand, the speeds and axial loads on Elegoo Mars are not that big, so you might be OK for years with this solution.
  • better solution – get a pair of axial bearings F8-19G and use them instead of the ball bearing. Pretention them either as in the previous case or with a hard spring washer.
  • The best solution – build separate housing for the screw with contact angle bearings and connect the motor via flexible shaft coupler. This solution provides noise reduction using the silencer. However, when you try this it might be worth it to rebuild the Z-axis to use a linear rail as the Elegoo solution of the Z-axis has a high effect-to-cost ratio, however, I can measure about 0.2 mm of play when I apply reasonable forces by hand.

As the G8-19G bearings are not available at my local store and I had to order them, I applied the dirty & cheap fix to find out what improvement can I get. Spoiler: a huge one.

I printed the test pieces from my previous posts (volume 1, volume 3, volume 4) and the problem practically disappeared. Compare the real size of the test piece before and after:

The full dataset can be found in this table (new measurements are from sample 10).

Most notably what changed is that if an error is introduced in a layer, it is compensated by the others. Therefore absolute precision is preserved. See that all the test pieces got practically the same height.

If you look at test piece 11, you’ll see it is quite distorted. It is the sample surrounded by a full plate of material. There was noticeable distortion, however, it was different compared to the previous cases. The overall test piece height was preserved, but the layers surrounded by material were a little bit higher. Just like first layers of other pieces. This is probably due to the effect I described in volume 4 (recommend reading before continuing). The effect is that the resin is viscous and as the build plate sinks, it has to push away the resin. When I introduced the delay to allow the resin to flow away and to settle the build plate in place I got much more precise pieces. On the simple pieces, even the first layers got the correct height. On the pieces with extra material, the distortion is still there, however it is much less significant. I believe by introducing even longer delay, we can get much more precise (I plan to do this experiment).

What struggles me is that instead of 3 mm I got 2.9 mm – pretty constantly. Therefore, I printed another staircase – 0.5 mm steps, 15 mm in total height (sample 15). I also got less – 14.7 mm. Currently, I have no idea what is this caused by – it not a constant error (not coming from incorrect bed leveling) and it is too large for shrinkage (2 % – epoxy or polyurethane resins have shrinkage less than 0.5 % and I don’t expect printer resin to be that different). Maybe tensioned bearings with misaligned screws cause step loses on the stepper. I am also not sure the error is linear – I’ll have to run many more tests. Any ideas what could it be caused by?

On the topic of lost steps – before the first print I releveled the build plate. When the print started, the build platform started to move down as expected. The build plate touched the bottom of the VAT and the stepper still continued – by the sound it clearly lost some steps. I am sure I have leveled my bed correctly. I leveled it against empty VAT. Is it possible the printer FW moves the platform a little bit below the zero point to pretention the Z-Axis to mitigate the problem with flexible housing of the screw? I don’t know, but this also something I would like to explore in the future.

After all, even there are still open questions I consider my Elegoo Mars to be used as I intended when buying it – to produce precise functional mechanical components.

Testing the precision of Elegoo Mars – Volume 4: More observation, no solutions

Since the last post I have made many more experiments regarding the Z-issue on Elegoo Mars.

First, I tried to mount an indicator to the Z-axis. I mounted it in the middle of the arm carrying the print bed and printed my test model. To analyze the results, I aimed my phone camera to the printer to capture the measurements. I performed both dry and an actual print run. You can find the whole, uncut footage of the experiment here (warning, it is really boring):

Then I took the footage and put the numbers in a table (direct link to the table):

Continue reading “Testing the precision of Elegoo Mars – Volume 4: More observation, no solutions”

Testing the precision of Elegoo Mars – Volume 3: New view on the Z-axis problem

In the previous post, I observed squashing of the prints in the Z-direction near the build plate (roughly first 20 layers). I have discussed the problem on the Elegoo group on facebook and some of the people suggested it might be related to viscosity or surface tension of the resin itself – when a thin layer of resin forms it can either push the build platform away from the print due to viscosity or it can pull the platform closer due to the surface tension. Therefore, I run some experiments.

I appended the results of my experiments to the table starting with sample 6 (direct link to the table):

There are several interesting outcomes. First, when I introduced a 40-second delay before exposure (sample 7) I was expecting to get things better if the problem is caused by the viscosity of the resin, which is pushing the build plate away. However, I would say it had nearly the opposite effect.

So I tried the opposite – to increase the drop speed. I observed no difference in the result. It might be caused by not actually increasing the speed – there might be a software limit in the firmware and I haven’t measured the actual speed.

The last experiment is the most interesting one. I tried to print the full print bed of the material with the staircase:

The object around the staircase is only 1.5 mm tall, the staircase is 3 mm tall. The first layers of this sample (number 9) have the height of the first layers nearly good (it might be related to the precision of leveling), however, once the object ends, it gets flat. See the graphs in the table and a photo:

I have then tried to print just a frame around the build plate, however, the results were the same as in previous experiments. Therefore the problem is not related to the lead screw (as it happens practically on an arbitrary height) and occurs whenever a large surface area of a layer is printed. It means that printing on supports is not the solution to the problem! Imagine printing a box – when the flat bottom ends, the walls near the bottom get distorted. Tilting the prints could help, however, it requires supports and on many of my planned parts, it is undesirable to put the supports on the sides as they are functional surfaces which should not be distorted (or it might be too much work to polish them up).

Interestingly enough there is one more observation – the layer height distortion happens only when the dense layer ends – in my test case the layers between 0-1.5 mm have a rather good thickness. From the table, it seems like the effect takes place once there is a vertical gap between large surface area on a build plate and the FEP film between 0.1-0.5 mm. However, I have no explanation of the phenomenon yet. Last what I struggle with is the fact that if it would be simple FEP film deflection, it wouldn’t cause a change in the total object height. I would expect the object to have the correct height as the other layers will be a little taller. This leads me to an idea of actually losing steps on the stepper driving the Z-axis. But I have not verified yet.

Do you have some observation, ideas? Please let me know! If you try to reproduce my experiments, let me know!

Testing the precision of Elegoo Mars – Volume 2: XY plane

As I mentioned in the previous post I am for printing precise mechanical components with Elegoo Mars. I have already tested the dimensional accuracy in the Z-axis direction. If I omit the precision problem near the build platform, it is sufficient enough.

The dimensional precision of the printed components in the XY direction is affected by the following constraints:

  • the display itself. Here I assume it is precise enough. If not, I could tweak display size in the slicer.
  • Exposure and “overgrowth”. If you cure the resin for a long period of time, some of the UV light gets reflected from the resin itself and therefore it exposes the resin around the exposed area. This leads to a bigger outer and smaller inner dimension. There are two ways to compensate for it – you can lower the exposition time or you can compensate in the slicer.
  • Linear shrinkage of the resin. Like all resins (epoxy, polyurethane, etc.) even the UV curable resin change their dimensions (usually shrink) during curing. Usually, the manufacturer provides information about shrinkage in the datasheet or you can try to measure it and compensate for it.

I have a rule – in the CAD I design the components as they should be in reality. I do not want to put any compensation in my CAD models. I want the manufacturing process to take care of them: e.g. the slicer does it itself or I have a script to post-process my CAD models. Luckily, ChiTuBox can compensate for all the sources above.

To compensate for LCD size, you can directly change its parameters in the default setting dialogue of the print. See image below. However, I think there is no need to do that.

To compensate for the overgrowth, you can only tune the exposure time in the ChiTuBox menu. However, this has a problem that incompletely cured layers, which don’t overgrow are in some cases not strong enough to support the print. Fox example with Elegoo Gray, exposure time of 4 seconds leads to quite precise components. However, if there are massive planes, the risk of breaking the prints are quite high.

Luckily, if you export the profile and open it in a text editor, you find out it is just a plain text file with key-value pairs. There are two interesting keys: edgeCompensationPixel and edgeCompensationTimePercent. I expect the first one to shrink the sliced by the given number of pixels using the traditional erode operation on images. It can be used to compensate for the overgrowth. The second one seems to scale the entire slice – which can be used to compensate for resin shrinkage. You just edit the values and import the profile back. A little inconvenient, but better than nothing.

Actually, the previous two paragraphs are not true. The compensation feature does not work and the experiments below are results of bad labeling of my files (I mismatched the exposure settings in them). I plan to publish a new post with corrected results and alternative solution soon.

To find the right values I modeled a simple test piece (Fusion 360 model):

These pieces should form a press-fit – they should go inside each other but the joint should hold and it should require some force to put them together.

Then I printed them twice for every setting – one set aligned to X and Y axes, one set tilted by 30 degrees in the Z-direction. The tilted set should verify how the joint behaves when it is not a nice straight line but is formed out of pixels. The printing was time-consuming as you have to print for each setting separately – I haven’t hacked the printer and process to support multi-exposure prints.

My results for Elegoo Gray are 5.5 seconds exposure time and edgeCompensationPixel is 2. I did not compensate for shrinkage as it is probably insignificant for the size of my prints. This gives me nice results really close to expected size and expected fits:

The only downside right now is that ChiTuBox does not support separate compensation for the first layers which are over-exposed to stick well to the build platform. Hope it will be available in the future along with the option to specify compensation parameters in the GUI.

Testing the precision of Elegoo Mars – Volume 1: Z-axis

I have recently bought a new SLA printer – Elegoo Mars. For 250 € it is a wonderful device (I have to admit there are some minor flaws, but for the price).

I am interested in making precise mechanical components with it. Small teaser – you can make herringbone gears with module M0.5 or even M0.3. Wonderful. However, during my experiments, I have found a strange behavior regarding the height of the components. It seems like the first 5 layers have a wrong height. Therefore, I prepared a test piece and performed some measurements.

The test piece is simple – it is a staircase with steps of 0.2 mm in the Z-axis and 1 mm in the horizontal plane. Then I printed the piece several times and measured the height of the steps.

Numbers 1, 2 and 4 were printed directly on the bed. Piece number 4 was printed on supports (3 mm height). See, that pieces 1, 2 and 4 seem to have a thin beginning. My measurements confirm that (direct link to the table):

As you can see the printer is quite precise, however, there seems to be something wrong with the first 1 mm of the Z-axis – once I lift the model on the supports, the problem disappears. Note that I sanded the bottom of the lifted model, as the overhangs are always a little bit convex. I examined the sliced files with Photon File Validator and they seem fine. Therefore there has to be something wrong in the printer – either buggy firmware or hardware error.

I haven’t found the cause of the problem yet – do you have any ideas what could it cause? Does your printer feature the same behavior? Test it and let me know. Here is the Fusion model: https://a360.co/2NlHemW.

DIY Through Hole Plating of PCBs

PCBs in China are dirt cheap. There’s no doubt about that. However, sometimes I’d like to have PCB right away and I also like to challenge myself in mastering technologies. That’s probably why I occasionally experiment with a DIY fabrication of PCBs. I have a nice workflow, where I can make 6/6 mil double-sided PCBs under 45 minutes of time and roughly 15 minutes of work. There’s however one limitation – my vias are soldered through-hole wires.

I’ve been thinking about though hole plating for several years. The general procedure is simple – you have to activate non-copper surfaces (make them conductive) and then you apply standard electroplating procedure. You can find many tutorials on the internet, however, most of the require hard-to-get chemicals for the activation solution. Few weeks ago, I noticed that the local electronic component supplier had started to sell Kontakt Chemie Graphit – a conductive paint. It’s basically a colloidal graphite in an organic solution. It is supposed to be used for making surfaces conductive to prevent static electricity discharges. This could be perfect for activation of the non-copper surfaces! So I gathered all the necesery chemicals and equipment and made a test run.


Continue reading “DIY Through Hole Plating of PCBs”

Testing the WiFi range of ESP32

I have a project, which requires long distance (approximately 1 km) communication, in my mind. Recently I got super excited about ESP32, so I thought why not to use it. After all, CNLorh has shown us that ESP8266 has a surprising range – over a kilometer.

I wrote a simple program for two ESP32s using PlatformIO and the Arduino framework (as working with wifi in ESP-IDF is kinda hell). Here you can find code for the master device, and here for the slave. Basically, Master setups AP, slave connects and the master sends UDP packets. If the slave receives a packet, it toggles an LED. That’s it.

The MH-ET LIVE module

The MH-ET LIVE module

The first test was unsuccessful. I took two MH-ET LIVE D1 modules and went outside. When I went around a corner of 4 storey building, the connection was lost. Sight-to-sight I was able to communicate on 150 meters.

Then I found out ESP32 supports the WiFi LR protocol. By using this protocol it should be possible to sacrifice communication speed and gain increased the range. This protocol can be easily enabled by calling the following function after the WiFi peripheral has started:

esp_wifi_set_protocol( WIFI_IF_AP, WIFI_PROTOCOL_LR )
esp_wifi_set_protocol( WIFI_IF_STA, WIFI_PROTOCOL_LR )

I did a second test. I could walk around the building and the communication was perfect. I didn’t observe a single glitch. Sight to sight I was able to communicate up to 200 meter. If I put the master roughly 2 meters above the ground, I could get 240 meters. Improvement, but not significant. However the reliability of the connection drastically improved with the LR procol. The connection was much better, however it was still rather a disappointment.

As a last resort I tried different hardware – I tried to cut PCB under antenna on the MH_ET LIVE D1 modules and I also tried to use the original ESP32 DevKit-C modules. I got roughly the same results. No improvement.

The MH-ET LIVE module after modification

The MH-ET LIVE module after modification

The last thing left to do was to make the same test with an access points instead one of the ESP32s. I used TP-LINK TL-WR741n. Guess what – no improvement. I got exactly the same results.

To conclude – even ESP32 is a great chip, I am not going to use it for long-range communication. I am aware, that my experiment does not feature controlled environment and a fancy setup. However, this is all I got time for. Have you done some range tests on your own? What are you results? Please, share in the comments or send me an email.

Rotational encoders on the cheap – the capacitive way

Rotational encoders are definitely a must-have even in hobby robotics. When you want an encoder in your project, you have many options:

  • traditional optical encoders (IRCs) – precise, fast, not so cheap and big
  • “ball-mouse like” optical encoders – cheap, fast, reasonably big, poor resolution
  • magnetic encoders – small, wonderful resolution, not so fast and expensive
  • etc.

With two projects in my mind (one really up budget, the second one requiring really small and really fast (>100kHz) encoders) I thought: why not to build a capacitive encoder? Basically a variable capacitor whose capacitance determines the position. It could be cheap (etched on a PCB) and really fast. So I decided to explore possibilities of this approach.


As usual, I started with an overview of existing solutions. Surprisingly, it is hard to find any reasonable resources. I found only two types of existing projects – professional solutions without any documentation for scientific purposes and a really nasty hobby projects which are far-far away from any reasonable results. There was only one exception – Elm Chan’s laser projector, which uses a capacitive encoder for galvanometer feedback.

In his project, he uses a diode bridge and a high frequency AC voltage (>8 MHz) to measure a capacity difference of two capacitors. The circuit should produce a small voltage on a output proportional to the difference. However, I wasn’t able to reproduce his results. My circuit produced a lot of noise and was practically useless. Clearly I am not an analog guy. So I decided to do it in more digital way.

First prototype

The idea is simple – I create a plate capacitor with half-circle electrodes by etching a pattern on main PCB and on a small PCB carried by motor shaft. Then I use the 555 timer in an astable configuration with the plate capacitor for timing. The circuit will produce a square-wave signal with a period proportional to the overlap of the electrodes and therefore, proportional to the shaft position. The frequency can be measured using a timer on a MCU in the input-capture mode. Simple, right?

First prototype of capacitive encoder

After designing a simple PCB, which you can find here, I etched it and populated it. To protect the electrodes from a short and also to create as small spacing as possible (to increase capacity) I covered one of the electrodes with a transparent tape. The diameter of the semicircles is 15 mm (and therefore the active area is roughly 88 mm2. Based on resistor values I used, and the frequency I obtained, the capacity of this capacitor is about 8 pF – 5 times more then I expected (the tape is probably a better dielectric then I expected).

The first tests looked promising – I was able to measure a position, however the whole system was quite noisy and especially sensitive to touch – and mechanical stress. This is probably due to movement of the plates – event they lie on a the tape, if you squeeze them a little, they move closer together and it leads to big increase in the capacity. I also think this setup is quite sensitive to air humidity and temperature. Also it does not allow for continuous rotation because of the wire connecting one electrode to the main PCB. I was thinking about connecting the the other electrode via the motor shaft and the motor case, however, one of my friends had a nice idea (thanks Jiří).

Second prototype

The idea behind second prototype is quite simple – do not move the electrodes, move with a semi-circle of a good dielectric material between two fixed plates. The electrodes are fixed and therefore it is easier to maintain a fixed distance between them. Also, even if the dielectric semicircle does not maintain a constant distance from the electrodes, it makes no difference as the ratio of air and dielectric is the same (and that’s what affects the capacity). For the material I used FR-4 – it is easy to get and has 4 times bigger dielectric constant than air.

Second prototype

Second prototype

I also tried to make two electrodes for the second prototype to get rid of humidity and temperature dependency – I wanted to measure a capacity difference by measuring two capacities and making the compensation in MCU. However it wasn’t a good idea to put the two 555 timers on the other sides of PCB. Even with a decent battery of capacitors, they interfered in their function and produced an instability in the oscillation.

The other side of PCB with a ground plane and without the second 555 timer

When I got rid of one of the second timer and also introduced a ground plane on the other side of the circular electrodes I was surprised with results. To test the capacitor I used ESP32 with a motor control timer in the input capture mode. This timer’s clock tick at 80 MHz and feature a 32 bit counter. First, I arranged the resistors of the 555 timer to get a frequency around 100 kHz (I was aming for really fast encoders). With this setup, the timer makes roughly 800 ticks per period. As the capacitor still has a capacity even when there is no dielectric, the low period was 720 tics and the high period was 860 period – i.e. I got resolution of 140 positions. When the encoder is stable, there is a surprisingly small noise – only +-1 tick. Also I let the encoder run for over two hours and there was no drift in the position. You might think – 140 positions isn’t much, but I can read it at 100 kHz! When I lower the frequency (or if I could get the timers in ESP32 to tick faster) I am able to increase the resolution. So basically it is a trade off between speed and resolution.

What about continuous rotation?

If you read carefully and think a little, there is one small glitch in my setup – I am only able to detect position in the range 0-180° and no more. If I continue the movement above this range, I am not able to tell if I continue or if I am returning back as the capacity decreases the same way on the both sides. There is however a simple solution, which I unfortunately haven’t tested yet.

Electrode pattern

You need two electrodes A and B and a dielectric disk taking 2/3 of the full circle (semi transparent in the image). In this configuration you can always tell in which direction you move.


I would call my work as “proof-of-concept”. I think ultra fast capacitive encoders are feasible if you can measure period fast enough or you make Elm Chan’s circuit to work and use ADC instead. The capacitive encoder can be also a dirty-cheap solution – you need only a space on PCB, two 555 timer, 4 resistors and 4 capacitors. As the capacity of my plate capacitor is roughly 10 pF I think you could reduce its size 2 or 3 times and still get reliable results so not much of a space is necessary.

But always remember – time is money and an “expensive” solution in a form of a magnetic encoder IC might be in the end the cheapest solution.