This discussion: http://music-electronics-forum.com/t30634/ introduced the idea of using a two channel recording interface as the hardware for a device to measure the impedance of guitar pickups. Commercial software was used to demonstrate the feasibility of the idea. Now I have written software for the task in a platform/hardware independent way and tested it on a mac with my duet 2. It should work on other systems/hardware, although usually there are some glitches in getting something like this fully functional. The language used is python, or actually the ipython/scipy/numpy package that provides free functionality similar to Matlab or IDL. The audio interface is handled by the pyaudio package, which provides an interface to the cross platform portAudio C routines.
Random 24 bit integers are converted to analog and sent to the test setup. Two 24 bit samples are measured to allow the voltage across and current through the pickup to be measured. Cross spectral analysis is used to determine an answer that is independent of the details of the output waveform.
This Version 0 works only with 24 bit hardware. Obviously 16 or 32 bit hardware would be easier to support in software since those sizes match native word sizes, but is this necessary? The sampling rate is 44100 Hz; it might be nice to go to 96000, but with the control implemented here, the antialiasing filter on the D/A remains set to 20KHz even when faster sampling is used, and so there is no significant advantage.
Before describing how to obtain the necessary software and set it up (later post), here is what it does:
Assuming that ipython is running in a terminal window, here is how to use module pan to measure pickup impedance:
Load the pickup analysis module, pan.py:
import pan
Measure the impedance of a pickup, after connecting it as described in a later post:
sc1 = pan.imp(pan.d24, 1000)
d24 is a dicionary containing some parameters controlling the process. 1000 is the requested number of individual sample measurements to average. sc1 is a name assigned to the object for this measurement. This object contains the parameters and results. You can have an indefinite number of measurements (objects) active at once. A plot of the impedance is made. (More on this below)
The name 'noname' appears on the plot. If you want to keep this data, you should give it a name. It need not be sc1, but could be something longer such as model number/serial number, etc. Here is how to give it a name:
sc1.pdict['pickup'] = 'sc1'
or whatever name you want instead of "sc1".
The dictionary pdict of object sc1 contains many other parameters.
Now redo the plot so that it appears with the name:
pan.plotZ(sc1, 20000.)
(This plot is attached to this post.)
Save the object sc1:
pan.save(sc1, 'sc1')
The first argument is the object name; the second is the file name. It can be restored into another python session. (sc1 = pan.restore('sc1')) Measurements are saved in a directory that you specify when you set up pan. (More on this below.)
The plot can be saved to a file using the right most icon in the lower bar of the plot window.
Now measure another pickup, with a different object name in order to keep the results of the first for easy comparison. First open another:
figure(2)
Then the next measurement is very much like the first:
(There is a minor bug in this process with a work around described in a later post.)
hb1 = pan.imp(pan.d24, 1000)
hb1.pdict['pickup'] = 'hb1'
pan.plotZ(hb1, 20000.)
(plot attached)
pan.save(hb1, 'hb1')
The blue and red lines on the plots show where the resonance occurs, formally defined as the frequency where the angle crosses zero; this is the same as the imaginary part crossing zero, since it is the tangent of the angle. Lcoil is derived from a linear least squares fit to the very low frequencies of the imaginary part, and Rcoil is derived in a similar way from the real part. The relevant equation for deriving the capacitance, 2*pi*f = 1/sqrt(Lcoil*Rcoil) is not quite accurate enough because of the effects of eddy currents. Thus, a model for eddy currents has been derived and a non linear least squares fit near the peak is used to derive a better value for C. Once C has been derived, it can be removed from the measured impedance, revealing the effects of the eddy currents. If there were no eddy currents, the yellow line would lie on the dashed gray line, and the green line would lie on the dot-dashed gray line.
It can be seen that the effects of eddy currents on the single coil and the humbucker are different. This is because the conductivity and permeability of steel and alnico are different. There is a way to see a direct comparison, showing just the lower frequencies most important to the sound with this command:
pan.plotEC(hb1, sc1, 3000.)
(plot attached )
Each impedance is divided by the inductance of the pickup to take out the effect of different overall impedances to facilitate the comparison between the two. You can adjust the upper frequency range as desired.
Random 24 bit integers are converted to analog and sent to the test setup. Two 24 bit samples are measured to allow the voltage across and current through the pickup to be measured. Cross spectral analysis is used to determine an answer that is independent of the details of the output waveform.
This Version 0 works only with 24 bit hardware. Obviously 16 or 32 bit hardware would be easier to support in software since those sizes match native word sizes, but is this necessary? The sampling rate is 44100 Hz; it might be nice to go to 96000, but with the control implemented here, the antialiasing filter on the D/A remains set to 20KHz even when faster sampling is used, and so there is no significant advantage.
Before describing how to obtain the necessary software and set it up (later post), here is what it does:
Assuming that ipython is running in a terminal window, here is how to use module pan to measure pickup impedance:
Load the pickup analysis module, pan.py:
import pan
Measure the impedance of a pickup, after connecting it as described in a later post:
sc1 = pan.imp(pan.d24, 1000)
d24 is a dicionary containing some parameters controlling the process. 1000 is the requested number of individual sample measurements to average. sc1 is a name assigned to the object for this measurement. This object contains the parameters and results. You can have an indefinite number of measurements (objects) active at once. A plot of the impedance is made. (More on this below)
The name 'noname' appears on the plot. If you want to keep this data, you should give it a name. It need not be sc1, but could be something longer such as model number/serial number, etc. Here is how to give it a name:
sc1.pdict['pickup'] = 'sc1'
or whatever name you want instead of "sc1".
The dictionary pdict of object sc1 contains many other parameters.
Now redo the plot so that it appears with the name:
pan.plotZ(sc1, 20000.)
(This plot is attached to this post.)
Save the object sc1:
pan.save(sc1, 'sc1')
The first argument is the object name; the second is the file name. It can be restored into another python session. (sc1 = pan.restore('sc1')) Measurements are saved in a directory that you specify when you set up pan. (More on this below.)
The plot can be saved to a file using the right most icon in the lower bar of the plot window.
Now measure another pickup, with a different object name in order to keep the results of the first for easy comparison. First open another:
figure(2)
Then the next measurement is very much like the first:
(There is a minor bug in this process with a work around described in a later post.)
hb1 = pan.imp(pan.d24, 1000)
hb1.pdict['pickup'] = 'hb1'
pan.plotZ(hb1, 20000.)
(plot attached)
pan.save(hb1, 'hb1')
The blue and red lines on the plots show where the resonance occurs, formally defined as the frequency where the angle crosses zero; this is the same as the imaginary part crossing zero, since it is the tangent of the angle. Lcoil is derived from a linear least squares fit to the very low frequencies of the imaginary part, and Rcoil is derived in a similar way from the real part. The relevant equation for deriving the capacitance, 2*pi*f = 1/sqrt(Lcoil*Rcoil) is not quite accurate enough because of the effects of eddy currents. Thus, a model for eddy currents has been derived and a non linear least squares fit near the peak is used to derive a better value for C. Once C has been derived, it can be removed from the measured impedance, revealing the effects of the eddy currents. If there were no eddy currents, the yellow line would lie on the dashed gray line, and the green line would lie on the dot-dashed gray line.
It can be seen that the effects of eddy currents on the single coil and the humbucker are different. This is because the conductivity and permeability of steel and alnico are different. There is a way to see a direct comparison, showing just the lower frequencies most important to the sound with this command:
pan.plotEC(hb1, sc1, 3000.)
(plot attached )
Each impedance is divided by the inductance of the pickup to take out the effect of different overall impedances to facilitate the comparison between the two. You can adjust the upper frequency range as desired.
Comment