Motivation: Measuring complex impedance as a function of frequency is usually done in the context of RF, but I care because the impedance of peizoelectric crystals has a large imaginary component which affects how to efficiently drive them and the resonant frequency. If you have a reactive load and do not want to worry about this, there are four-quadrant power supplies (they can sink as well as source current) which are specifically meant to amplify signals for driving this sort of thing.
There are real benchtop tools to measure impedance, but even used they usually start around $2k, so that’s out of the question for a hobby thing like this. I’ve also learned that there are impedence meters specifically for Peizoelectrics , so it’s neat to see that measuring peizoelectric impedance is common enough that there are devices built specifically for it.
What should peizoelectric impedance be in theory? The best resource I’ve found so far on peizoelectric circuit models is PDF Appendix C: the Rlc Circuit Model for A Piezoelectric Transducer, which gives a way to derive the relevant parameters from crystal geometry. I believe this reference is only applicable for airbacked crystals, when in reality almost all peizoelectric crystals are used in situations where they are connected to things. Peizoelectricity is a reversible process, so it stands to reason that attaching a load would add an inductor as the mechanical system would have momentum. This would definitely affect the electrical resonant frequency, but I haven’t had time to properly figure out this effect.
How am I measuring impedance? I’m just setting up a voltage bridge and driving it with a signal generator. The reference resistor keeps the total impedance nonnegledgible and mostly real, which is good because the signal generator can be weird when trying to source high currents or reactive loads. I actually had to increase the reference resistance from 100 Ohms to 1000 Ohms because V_in was starting to look like a triangle wave and this was affecting the results.
How am I automating this? Even though I’ve learned that trying to hook up electrical equipment to computers is usually a waste of time, I spent a day with my Rigol 1054Z and Koolertron JDS6600 signal generator getting this set up.
Communicating with the Rigol 1054Z can be done over USB (requiring the usbtmc kernel module on linux), and a typical way to do this is to open /dev/usbtmc0 (or whatever device the oscilloscope shows up as) as a file and write commands described in the communication module. The commands are described in the communication manual look like “:CHANnel1:COUPling AC”. I tried a bunch of things and what this guy is doing worked best: https://www.cibomahto.com/2010/04/controlling-a-rigol-oscilloscope-using-linux-and-python/. No ‘updated’ version of it in the comments worked better. Unfortunately, when playing around with this it seemed impossible to download more than 500 samples at a time with a single command over USB, despite the communication manual claiming the ability to download 1250000. Also downloading data which was not present on the screen appeared broken over USB.
Communicating over an ethernet cable uses the same commands as with USB and they can be sent with netcat. I ended up following this guide: https://www.theimpossiblecode.com/blog/rigol-ds1054z-screen-capture-linux/ but with python and sockets instead of netcat.
I would also like to mention https://github.com/pklaus/ds1054z, which can drive most of the oscilloscope’s functions over a computer with over a GUI and is the best software I’ve used for working with an oscilloscope.
As for the frequency generator, supposedly the accompanying CD (which I threw in the trash after unpacking it originally) had a communication manual in Chinese. Thankfully, some kind soul has put the google translated version online: https://www.eevblog.com/forum/testgear/anybody-know-anything-about-this-signal-generator/msg1442325/#msg1442325. This required a linux kernel module I did not have yet, ch341. Even more fortunately, someone has written a python wrapper to control these signal generators https://github.com/on1arf/jds6600_python, which actually works! A note, this requires ‘pyserial’ and will fail in a non-obvious way with the python module named ‘serial’.
Combining the two, I’ve written a python script that will set a frequency on the frequency generator, measure the voltage and phase difference for the setup, and produce a plot of the complex impedance of the load vs. frequency http://akmemorph.us/wp-content/uploads/2019/10/abc.py.
Results: A test with a 100 Ohm resistor:
I’m not sure to what extent the imaginary component is some error vs. due to an actual impedance of the resistor I am using. Still, it’s only a few percent.
The test with the capacitor went very well, with the predicted and actual impedance lying almost on top of each other.
I used it on a small peizoelectric buzzer, which clearly shows a resonance around 4.1 kHz. It would be neat to change the mechanical loading and see what happens to the resonance. I wasn’t able to detach the brass disk, which is used to make the sound louder, for comparison.
Impedance for the peizoelectric with a horn attached for ultrasonic cleaning advertised as resonant at 28kHz. It appears like there is a resonance there, but structure is a lot more complex than for the peizoelectric buzzer.
Future Work: There are a lot of ways this could be improved (sped up by testing multiple frequencies at once, improve the accuracy with auto ranging, have a better measurement of the reference impedance…) but I think it’s good enough for now. I’m most interested in getting this to work with some airbacked crystals for comparison.