Posts with «loudness» label

Precision rectifier

The log amplifier that I’ve spent the last several days understanding (posts a, b, c) is not the only non-linear circuit needed for a loudness detector.  We also need to convert the audio input signal into a slowly changing amplitude signal that we can take the logarithm of.  As I discussed in the first post on log amps, I had rejected true-RMS converter chips as too expensive for the application (though the original application has gone away), and decided to try a rectifier and low-pass filter.

[Incidentally, my son is now looking at a different processor chip, the KL25 from Freescale (an ARM Cortex chip), which has a 16-bit ADC that is much faster than the ATMega’s, so the entire loudness-detector could be done in software, except for a one-op-amp preamplifier.  With a  16-bit ADC, we can get almost 90dB of range without needing a log amplifier. We’re planning to order a development board that is compatible with Arduino shields (but has lots more I/O pins available) and that has an accelerometer on the board.  Amazingly, the development board is only $13, about half the price of an Arduino.]

A single diode does not work for our rectifier needs in the loudness circuit, because diodes don’t turn on until the voltage across them is at least a “diode drop” (about 0.7v for silicon diodes and 0.45v for Schottky diodes).  However, the simple circuit for the log amplifier is also the circuit for a precision rectifier:

This circuit is both a log amplifier and a precision rectifier. If Vb is set to a constant voltage, then Vout1 varies as log(Vb–Va). Vout2 is max(Va,Vb). 
The diode can be connected in the opposite direction, to get Vout2=min(Va,Vb) and Vout1 varying with log(Va–Vb).

The log-amplifier circuit I used in the previous posts had a transistor in place of the diode, so that the crucial voltage that was being exponentiated was referenced to the bias voltage, rather than the input. We also needed a compensation capacitor in parallel with the transistor to prevent oscillation in the negative feedback loop.

For the precision rectifier, we swap the inputs, so that Va is the signal input and Vb is a constant threshold voltage for the rectifier. We do not need (or want) the compensation capacitor, as that would cause the circuit to act as a unity gain amplifier at high frequency, rather than as a rectifier.

Because I did not happen to have any diodes, but had plenty of transistors, I experimented with the rectifier circuit using diode-connected bipolar transistors (collector and base connected together). Because the output of the rectifier is not directly driven by an op amp, I used unity-gain buffers to isolate the test circuitry (Arduino analog inputs or BitScope oscilloscope) from the amplifier:

Test circuit for low-speed testing of precision rectifier circuit. Here the NPN transistor is used as a diode, in the opposite direction as in the first schematic, so Vout should be min(Vin, Vbias)

My initial test setup did not have the unity-gain buffer for Vin, but I found that one of my Arduino analog input pins was quite low impedance and was discharging my capacitor. Switching to a different pin helped, but I eventually decided to avoid that kluge and use a unity-gain buffer instead.

I tried several different values for R2. The most predictable effect of changing the value is a change in the range over which the rectifier operates. Clipping occurs because the output of the op amp is limited to be between the rails of the power supply. The feedback transistor is conducting when the rectifier is following the input, so the op amp output has to be substantially lower than Vout.  The function implemented is max(Vclip, min(Va,Vbias)).  Vclip should go down as R2 is increased (at about 60mV for each factor of 10 in resistance—the same shift as in the log amplifier).

Here are a couple of plots of Vout vs. Vin for the S9018 transistor:

(click to embiggen) With a 1kΩ resistor, the clipping voltage is fairly high, and we have a somewhat limited range for the rectifier.  The offset voltage for the rectifier between the output and the input is much less than the resolution of the Arduino ADC (about 5mV).

(click to embiggen) With a 10kΩ resistor, the clipping voltage is lower, giving us more range for the rectifier.

Using a PNP transistor instead of an NPN has the effect of reversing the diode and producing Vout=min(Vclip, max(Vin, Vbias)):

(click to embiggen) With an S9012 PNP transistor and a 1kΩ resistor, we get clipping at the high end.

(click to embiggen) With a 10kΩ resistor we get a larger range.

So why not go for a very large resistor and maximize the range? From a DC perspective this looks like a win (though it is hard to see in the limit how Vbias would affect the result if the resistance went to infinity).  Of course, the problem is with high-frequency response.  Consider the difference between the S9018 NPN transistor with a 1kΩ resistor and a 330kΩ resistor:

(click to embiggen) With an S9018 NPN transistor and a 330kΩ resistor at 1kHz. Note the overshoot when the rectifier shuts off.

(click to embiggen) Fairly clean signal with a S9018 NPN transistor and a 10kΩ resistor at 1kHz.

(click to embiggen) With a 1kΩ resistor, there is very little overshoot as the rectifier turns off, but we can see a bit of a problem when the rectifier turns back on.

There is a problem with the rectifier turning on slowly, because Vout has to move all the way from the top rail down to the bias voltage, and the op amp has a slew-rate limitation. This phenomenon can be seen more clearly at a higher frequency:

(click to embiggen) The S9018 NPN transistor with a 10kΩ resistor and a 15kHz input signal. The overshoot as the rectifier turns off is about 50mV, and the turn-on delay is about 8µsec. The turn-on delay does not vary much with the input resistance, unlike the turn-off overshoot.

I believe that the overshoot as the rectifier turns off is due to capacitance, as adding a small feedback capacitor in parallel with the diode increases the overshoot substantially:

(click to embiggen) With a 33pF capacitor in parallel with the diode (an S9018 NPN transistor), a 10kΩ resistor, and a 15kHz input, the overshoot goes up to about 290mV from 50mV without the capacitor. The turn-on delay is masked somewhat by the high-frequency feedback.

Note: the S9018 has the best high-frequency response (if you consider 15kHZ high frequency) of any of the transistors I looked, probably because it has the lowest capacitance. For example, with a 10kΩ resistor the S9013 NPN has 120mV of overshoot at 15kHz, instead of only 50mV, and the S9012 PNP has -180mV. With a 1kΩ resistor, I can’t measure the overshoot on any of these three transistors. So the limited range with a 1kΩ resistor is compensated for by the much cleaner turn-off behavior.  I should be able to get better range by using a fast-response Schottky diode instead of diode-connected transistor.

Of course, the turn-on behavior is a bigger problem and one that can’t be fixed by playing with the resistor or the diode, because the problem is with the large voltage swing needed from the op amp in order to turn on. There are standard solutions that limit the voltage swing, but I think I’ll leave that for a later blog post.


Filed under: Circuits course, Data acquisition Tagged: Arduino, BitScope, KL25Z, log amplifier, loudness, op amp, rectifier

Precision rectifier

The log amplifier that I’ve spent the last several days understanding (posts a, b, c) is not the only non-linear circuit needed for a loudness detector.  We also need to convert the audio input signal into a slowly changing amplitude signal that we can take the logarithm of.  As I discussed in the first post on log amps, I had rejected true-RMS converter chips as too expensive for the application (though the original application has gone away), and decided to try a rectifier and low-pass filter.

[Incidentally, my son is now looking at a different processor chip, the KL25 from Freescale (an ARM Cortex chip), which has a 16-bit ADC that is much faster than the ATMega's, so the entire loudness-detector could be done in software, except for a one-op-amp preamplifier.  With a  16-bit ADC, we can get almost 90dB of range without needing a log amplifier. We're planning to order a development board that is compatible with Arduino shields (but has lots more I/O pins available) and that has an accelerometer on the board.  Amazingly, the development board is only $13, about half the price of an Arduino.]

A single diode does not work for our rectifier needs in the loudness circuit, because diodes don’t turn on until the voltage across them is at least a “diode drop” (about 0.7v for silicon diodes and 0.45v for Schottky diodes).  However, the simple circuit for the log amplifier is also the circuit for a precision rectifier:

This circuit is both a log amplifier and a precision rectifier. If Vb is set to a constant voltage, then Vout1 varies as log(Vb–Va). Vout2 is max(Va,Vb). 
The diode can be connected in the opposite direction, to get Vout2=min(Va,Vb) and Vout1 varying with log(Va–Vb).

The log-amplifier circuit I used in the previous posts had a transistor in place of the diode, so that the crucial voltage that was being exponentiated was referenced to the bias voltage, rather than the input. We also needed a compensation capacitor in parallel with the transistor to prevent oscillation in the negative feedback loop.

For the precision rectifier, we swap the inputs, so that Va is the signal input and Vb is a constant threshold voltage for the rectifier. We do not need (or want) the compensation capacitor, as that would cause the circuit to act as a unity gain amplifier at high frequency, rather than as a rectifier.

Because I did not happen to have any diodes, but had plenty of transistors, I experimented with the rectifier circuit using diode-connected bipolar transistors (collector and base connected together). Because the output of the rectifier is not directly driven by an op amp, I used unity-gain buffers to isolate the test circuitry (Arduino analog inputs or BitScope oscilloscope) from the amplifier:

Test circuit for low-speed testing of precision rectifier circuit. Here the NPN transistor is used as a diode, in the opposite direction as in the first schematic, so Vout should be min(Vin, Vbias)

My initial test setup did not have the unity-gain buffer for Vin, but I found that one of my Arduino analog input pins was quite low impedance and was discharging my capacitor. Switching to a different pin helped, but I eventually decided to avoid that kluge and use a unity-gain buffer instead.

I tried several different values for R2. The most predictable effect of changing the value is a change in the range over which the rectifier operates. Clipping occurs because the output of the op amp is limited to be between the rails of the power supply. The feedback transistor is conducting when the rectifier is following the input, so the op amp output has to be substantially lower than Vout.  The function implemented is max(Vclip, min(Va,Vbias)).  Vclip should go down as R2 is increased (at about 60mV for each factor of 10 in resistance—the same shift as in the log amplifier).

Here are a couple of plots of Vout vs. Vin for the S9018 transistor:

(click to embiggen) With a 1kΩ resistor, the clipping voltage is fairly high, and we have a somewhat limited range for the rectifier.  The offset voltage for the rectifier between the output and the input is much less than the resolution of the Arduino ADC (about 5mV).

(click to embiggen) With a 10kΩ resistor, the clipping voltage is lower, giving us more range for the rectifier.

Using a PNP transistor instead of an NPN has the effect of reversing the diode and producing Vout=min(Vclip, max(Vin, Vbias)):

(click to embiggen) With an S9012 PNP transistor and a 1kΩ resistor, we get clipping at the high end.

(click to embiggen) With a 10kΩ resistor we get a larger range.

So why not go for a very large resistor and maximize the range? From a DC perspective this looks like a win (though it is hard to see in the limit how Vbias would affect the result if the resistance went to infinity).  Of course, the problem is with high-frequency response.  Consider the difference between the S9018 NPN transistor with a 1kΩ resistor and a 330kΩ resistor:

(click to embiggen) With an S9018 NPN transistor and a 330kΩ resistor at 1kHz. Note the overshoot when the rectifier shuts off.

(click to embiggen) Fairly clean signal with a S9018 NPN transistor and a 10kΩ resistor at 1kHz.

(click to embiggen) With a 1kΩ resistor, there is very little overshoot as the rectifier turns off, but we can see a bit of a problem when the rectifier turns back on.

There is a problem with the rectifier turning on slowly, because Vout has to move all the way from the top rail down to the bias voltage, and the op amp has a slew-rate limitation. This phenomenon can be seen more clearly at a higher frequency:

(click to embiggen) The S9018 NPN transistor with a 10kΩ resistor and a 15kHz input signal. The overshoot as the rectifier turns off is about 50mV, and the turn-on delay is about 8µsec. The turn-on delay does not vary much with the input resistance, unlike the turn-off overshoot.

I believe that the overshoot as the rectifier turns off is due to capacitance, as adding a small feedback capacitor in parallel with the diode increases the overshoot substantially:

(click to embiggen) With a 33pF capacitor in parallel with the diode (an S9018 NPN transistor), a 10kΩ resistor, and a 15kHz input, the overshoot goes up to about 290mV from 50mV without the capacitor. The turn-on delay is masked somewhat by the high-frequency feedback.

Note: the S9018 has the best high-frequency response (if you consider 15kHZ high frequency) of any of the transistors I looked, probably because it has the lowest capacitance. For example, with a 10kΩ resistor the S9013 NPN has 120mV of overshoot at 15kHz, instead of only 50mV, and the S9012 PNP has -180mV. With a 1kΩ resistor, I can’t measure the overshoot on any of these three transistors. So the limited range with a 1kΩ resistor is compensated for by the much cleaner turn-off behavior.  I should be able to get better range by using a fast-response Schottky diode instead of diode-connected transistor.

Of course, the turn-on behavior is a bigger problem and one that can’t be fixed by playing with the resistor or the diode, because the problem is with the large voltage swing needed from the op amp in order to turn on. There are standard solutions that limit the voltage swing, but I think I’ll leave that for a later blog post.


Filed under: Circuits course, Data acquisition Tagged: Arduino, BitScope, KL25Z, log amplifier, loudness, op amp, rectifier

Logarithmic amplifier again

Yesterday, in Logarithmic amplifier, I ended with the following plot:

(click plot to see larger version) The cloud of points is broad enough to be consistent with slightly different parameter values.

I was bothered by the broad cloud of points, and wanted to come up with a better test circuit—one that would give me more confidence in the parameters.  It was also quite difficult to get close to Vbias—the closest this could measure was one least-significant-bit of the DAC away (about 5mV).  A factor of 512 from the largest to the smallest signal is 54dB, but only about the upper 40dB of that was good enough data for fitting (and very little time was spent at near the Vbias value).

I think that part of the problem with the cloud was that the input signal was changing fairly quickly, and the Arduino serializes its ADC, so that the input and output are measured about 120µsec apart.  I decided to use a very simple slow-changing signal: a capacitor charging toward Vbias through a large resistor.  My first attempt used a 1MΩ resistor and a 10µF capacitor, for a 10-second time constant:

Output voltage from log amplifier (with 3x gain in second stage) as capacitor charges. (click picture for larger version) One fit uses the Arduino-measured Vin and Vbias voltages, the other attempts to model the RC charging as well. What are the weird glitches?

The capacitor charging should be a smooth curve exponential decay to Vbias, so the log amplifier output should be a straight line with time. There were two obvious problems with this first data—the output was not a straight line and there were weird glitches about every 15–20 seconds.

The non-straight curve comes from the capacitor not charging to Vbias. Even when the capacitor was given lots of time to charge, it remained stubbornly below the desired voltage. In think that the problem is leakage current: resistance in parallel with the capacitor. The voltage was about 1% lower than expected, which would be equivalent to having a 100MΩ resistor in parallel with the capacitor.  I can well believe that I have sneak paths with that sort of resistance on the breadboard as well as in the capacitor.

According to Cornell Dublier, a capacitor manufacturer, a typical parallel resistance for a 10µF aluminum electrolytic capacitor would be about 10MΩ [http://www.cde.com/catalogs/AEappGUIDE.pdf‎]:

Typical values are on the order of 100/C MΩ with C in μF, e.g. a 100 μF capacitor would have an Rp of about 1 MΩ.

So I may be lucky that I got as close to Vbias as I did.

The glitches had a different explanation: they were not glitches in the log amplifier circuit, but in the 5V power supply being used as a reference for the ADC on the Arduino board—I had forgotten how bad the USB power is coming out of my laptop, though I had certainly observed the 5V supply dropping for a second about every 20 seconds on previous projects.  The drop in the reference for the ADC results in a bogus increase in the measured voltages.  That problem was easy to fix: I plugged in the power supply for the Arduino rather than running off the USB power, so I had a very steady voltage source using the Arduino’s on-board regulator.

(click picture for larger version) With a proper power supply, I get a clean charge and the output is initially a straight line, but I’m still not getting close to Vbias. Again the blue fit uses the measured Vin and Vbias voltages, while the green curve tries to fit an RC decay model. Note the digitization noise on the measured inputs towards the end of the charging time.

To solve the problem of the leakage currents, I tried going to a larger capacitor and smaller resistor to get a similar RC time constant. At that point I had not found and read the Cornell Dublier application note, though I suspected that the parallel resistance might scale inversely with the capacitor size, in which case I would be facing the same problem no matter how I chose the R-vs-C tradeoff. Only reducing the RC time constant would work for getting me closer to Vbias.

Using a 47kΩ resistor and a 470µF capacitor worked a bit better, but the time constant was so long that I got impatient:

(click image for larger version) The blue fit is again using the measured Vin and Vbias, and has a pretty good fit. The green fit using an RC charge model does not seem quite as good a fit.

The calibration of 9.7mV/dB seems pretty good, so the 409mV range of the recording corresponds to a 42dB range. The line is straighter, but I’m still not getting as close to Vbias as I’d like.

I then tried a smaller RC time constant (hoping that the larger current with the same capacitor would result in getting closer to Vbias, and so testing a larger dynamic range on the log amplifier). I tried 16kΩ with the 470µF capacitor:

(click image to embiggen) I’m now getting a clear signal from the log amplifier even after the input voltage has gotten less than one least-significant-bit away from Vbias (the blue fit). I found it difficult to fit parameters for modeling the RC charge (the green fit).

The two models I fit to the data give me somewhat different mV/dB scales, though both fit the data fairly well. The blue curve fits better up to about 65 seconds, then has quantization problems. Using that estimate of 9.8mV/dB and the 560mV range of the output, we have a dynamic range here of 57dB. There is still some flattening of the curve—we aren’t quite getting to the Vbias value, but it is pretty straight for the first 50 seconds.

Note: the parallel resistance of the capacitors would not explain the not-quite-exponential behavior we saw in the RC time constant lab, since those measurements were discharging the capacitor to zero. A parallel resistance would just change the time constant, not the final voltage.

I was using the Duemilanove board for the log-amplifier tests. I retried with the Uno board, to see if differences in the ADC linearity make a difference in the fit:

(click to embiggen) Using the Uno Arduino board I still had trouble with the fit, and the Uno ADC seems to be noisier than the Duemilanove ADC. The missing parts of the blue curve are where the Uno board read the input as having passed Vbias.

The 625 mV range over 250 seconds corresponds to about 69dB, assuming that the 9.1 mV/dB calibration is reasonably accurate (and 64dB if the earlier 9.8mV/dB calibration is better).
My measurements of the log amplifier do not seem to yield a very consistent mV/dB parameter, with values from 9.1mV/dB to 9.8mV/dB using just the Arduino measurements (and even less consistency when a model of RC charging is used).  I’m not sure how I can do more consistent measurements with the equipment I have.  Anyone have any ideas?
Incidentally, my son has decided not to include a microphone in his project.  The silicon MEMS mic was small enough, but the op amp chip for the analog processing was too big for the small board area he had left in his layout, and he decided that the loudness detector was not valuable enough for the board area and parts cost. I believe that his available board area shrunk a little today, because he discovered that the keep-away check had not been turned on in the Eagle design-rule checker.  Turning it on indicated that he had packed the capacitors too close in places, and he had to spread them out. (At least, I think that’s what he told me—I’ve not been following his PC board layout very closely.)
I’m still interested in learning about log amplifiers and precision rectifiers, so I’m still going to breadboard the components of the design and test them out.  I’m not sure when I’ll ever use the knowledge, since the Applied Circuits course does not cover the nonlinear behavior of pn junctions nor the forward-voltage drop of diodes (we don’t use diodes in the course).


Filed under: Circuits course, Data acquisition Tagged: Arduino, BitScope, i-vs-v-plot, log amplifier, loudness, op amp

Logarithmic amplifier again

Yesterday, in Logarithmic amplifier, I ended with the following plot:

(click plot to see larger version) The cloud of points is broad enough to be consistent with slightly different parameter values.

I was bothered by the broad cloud of points, and wanted to come up with a better test circuit—one that would give me more confidence in the parameters.  It was also quite difficult to get close to Vbias—the closest this could measure was one least-significant-bit of the DAC away (about 5mV).  A factor of 512 from the largest to the smallest signal is 54dB, but only about the upper 40dB of that was good enough data for fitting (and very little time was spent at near the Vbias value).

I think that part of the problem with the cloud was that the input signal was changing fairly quickly, and the Arduino serializes its ADC, so that the input and output are measured about 120µsec apart.  I decided to use a very simple slow-changing signal: a capacitor charging toward Vbias through a large resistor.  My first attempt used a 1MΩ resistor and a 10µF capacitor, for a 10-second time constant:

Output voltage from log amplifier (with 3x gain in second stage) as capacitor charges. (click picture for larger version) One fit uses the Arduino-measured Vin and Vbias voltages, the other attempts to model the RC charging as well. What are the weird glitches?

The capacitor charging should be a smooth curve exponential decay to Vbias, so the log amplifier output should be a straight line with time. There were two obvious problems with this first data—the output was not a straight line and there were weird glitches about every 15–20 seconds.

The non-straight curve comes from the capacitor not charging to Vbias. Even when the capacitor was given lots of time to charge, it remained stubbornly below the desired voltage. In think that the problem is leakage current: resistance in parallel with the capacitor. The voltage was about 1% lower than expected, which would be equivalent to having a 100MΩ resistor in parallel with the capacitor.  I can well believe that I have sneak paths with that sort of resistance on the breadboard as well as in the capacitor.

According to Cornell Dublier, a capacitor manufacturer, a typical parallel resistance for a 10µF aluminum electrolytic capacitor would be about 10MΩ [http://www.cde.com/catalogs/AEappGUIDE.pdf‎]:

Typical values are on the order of 100/C MΩ with C in μF, e.g. a 100 μF capacitor would have an Rp of about 1 MΩ.

So I may be lucky that I got as close to Vbias as I did.

The glitches had a different explanation: they were not glitches in the log amplifier circuit, but in the 5V power supply being used as a reference for the ADC on the Arduino board—I had forgotten how bad the USB power is coming out of my laptop, though I had certainly observed the 5V supply dropping for a second about every 20 seconds on previous projects.  The drop in the reference for the ADC results in a bogus increase in the measured voltages.  That problem was easy to fix: I plugged in the power supply for the Arduino rather than running off the USB power, so I had a very steady voltage source using the Arduino’s on-board regulator.

(click picture for larger version) With a proper power supply, I get a clean charge and the output is initially a straight line, but I’m still not getting close to Vbias. Again the blue fit uses the measured Vin and Vbias voltages, while the green curve tries to fit an RC decay model. Note the digitization noise on the measured inputs towards the end of the charging time.

To solve the problem of the leakage currents, I tried going to a larger capacitor and smaller resistor to get a similar RC time constant. At that point I had not found and read the Cornell Dublier application note, though I suspected that the parallel resistance might scale inversely with the capacitor size, in which case I would be facing the same problem no matter how I chose the R-vs-C tradeoff. Only reducing the RC time constant would work for getting me closer to Vbias.

Using a 47kΩ resistor and a 470µF capacitor worked a bit better, but the time constant was so long that I got impatient:

(click image for larger version) The blue fit is again using the measured Vin and Vbias, and has a pretty good fit. The green fit using an RC charge model does not seem quite as good a fit.

The calibration of 9.7mV/dB seems pretty good, so the 409mV range of the recording corresponds to a 42dB range. The line is straighter, but I’m still not getting as close to Vbias as I’d like.

I then tried a smaller RC time constant (hoping that the larger current with the same capacitor would result in getting closer to Vbias, and so testing a larger dynamic range on the log amplifier). I tried 16kΩ with the 470µF capacitor:

(click image to embiggen) I’m now getting a clear signal from the log amplifier even after the input voltage has gotten less than one least-significant-bit away from Vbias (the blue fit). I found it difficult to fit parameters for modeling the RC charge (the green fit).

The two models I fit to the data give me somewhat different mV/dB scales, though both fit the data fairly well. The blue curve fits better up to about 65 seconds, then has quantization problems. Using that estimate of 9.8mV/dB and the 560mV range of the output, we have a dynamic range here of 57dB. There is still some flattening of the curve—we aren’t quite getting to the Vbias value, but it is pretty straight for the first 50 seconds.

Note: the parallel resistance of the capacitors would not explain the not-quite-exponential behavior we saw in the RC time constant lab, since those measurements were discharging the capacitor to zero. A parallel resistance would just change the time constant, not the final voltage.

I was using the Duemilanove board for the log-amplifier tests. I retried with the Uno board, to see if differences in the ADC linearity make a difference in the fit:

(click to embiggen) Using the Uno Arduino board I still had trouble with the fit, and the Uno ADC seems to be noisier than the Duemilanove ADC. The missing parts of the blue curve are where the Uno board read the input as having passed Vbias.

The 625 mV range over 250 seconds corresponds to about 69dB, assuming that the 9.1 mV/dB calibration is reasonably accurate (and 64dB if the earlier 9.8mV/dB calibration is better).
My measurements of the log amplifier do not seem to yield a very consistent mV/dB parameter, with values from 9.1mV/dB to 9.8mV/dB using just the Arduino measurements (and even less consistency when a model of RC charging is used).  I’m not sure how I can do more consistent measurements with the equipment I have.  Anyone have any ideas?
Incidentally, my son has decided not to include a microphone in his project.  The silicon MEMS mic was small enough, but the op amp chip for the analog processing was too big for the small board area he had left in his layout, and he decided that the loudness detector was not valuable enough for the board area and parts cost. I believe that his available board area shrunk a little today, because he discovered that the keep-away check had not been turned on in the Eagle design-rule checker.  Turning it on indicated that he had packed the capacitors too close in places, and he had to spread them out. (At least, I think that’s what he told me—I’ve not been following his PC board layout very closely.)
I’m still interested in learning about log amplifiers and precision rectifiers, so I’m still going to breadboard the components of the design and test them out.  I’m not sure when I’ll ever use the knowledge, since the Applied Circuits course does not cover the nonlinear behavior of pn junctions nor the forward-voltage drop of diodes (we don’t use diodes in the course).


Filed under: Circuits course, Data acquisition Tagged: Arduino, BitScope, i-vs-v-plot, log amplifier, loudness, op amp

Logarithmic amplifier

My son wanted to design a circuit to convert microphone inputs to loudness measurements usable by an Arduino (or other ATMega processor).  We discussed the idea together, coming up with a few different ideas.

The simplest approach would be to amplify the microphone then do everything digitally on the Arduino. There are several features of this approach:

  • The analog circuit is about as simple as we can get: a DC-blocking capacitor and an amplifier.  This would only need one op amp, one capacitor, and 2 resistors (plus something to generate a bias voltage—perhaps another op amp, perhaps a low-drop-out regulator).
  • Using digital processing, he can do true RMS voltage computation, and whatever low-pass filtering to smooth the result that he wants.
  • He can’t sample very fast on the ATMega processor, so high frequencies would not be handled properly.  He might be able to sample at 9kHz (about as fast as the ADC operates), but that limits him to 4.5kHz. For his application, that might be good enough, so this doesn’t kill the idea.
  • He’d like to have a 60dB dynamic range (say from 50dB to 110dB) or more, but the ADC in the ATMega is only a 10-bit converter, so a 60dB range would require the smallest signal to be ±½LSB, which is at the level of the quantization noise.  With careful setting of the gain for the microphone preamp, one might be able to get 55dB dynamic range, but that is pushing it a bit.  The resolution would be very good at maximum amplitude, but very poor for quiet inputs.

Although the mostly digital solution has not been completely ruled out, he wanted to know what was possible with analog circuits.  We looked at two main choices:

  • True-RMS converter chips (intended for multimeters).  These do all the analog magic to convert an AC signal to a DC signal with the same RMS voltage.  Unfortunately, they are expensive (over $5 in 100s) and need at least a 5v power supply (he is planning to use all 3.3v devices in his design).  Also true RMS is a bit of overkill for his design, as log(amplitude) would be good enough.
  • Using op amps and discrete components to make an amplifier whose output is the logarithm of the amplitude of the input.  Together we came up with the following block diagram:

Block diagram of the loudness circuit. (drawn with SchemeIt).

We then spent some time reading on the web how to make good rectifier circuits and logarithmic amplifiers. I’ll do a post later about the rectifier circuits, since there are many variants, but I was most interested in the logarithmic amplifier circuits, which rely on the exponential relationship between current and voltage on a pn junction—often the emitter-base junction of a bipolar transistor.

My son wanted to know what the output range of the log amplifier would be and whether he would need another stage of amplification after the log amplifier. Unfortunately, the theory of the log amplifier uses the Shockley ideal diode equation, which needs the saturation current of the pn junction—not something that is reported for transistors.  There is also a “non-ideality” parameter, that can only be set empirically.  So we couldn’t compute what the output range would be for a log amplifier.

Today I decided to build a log amplifier and see if I could measure the output.  I also wanted to figure out what sort of dynamic range he could get from a log amp. Here is the circuit I ended up with, after some tweaking of parameters:

The top circuit is just a bias voltage generator to create a reference voltage from a single supply. I’m working off of 5v USB power, so I set the reference to 2.5v. He might want to use a 1.65v reference, if he is using 3.3v power.
The bottom circuit is the log amplifier itself.

I chose a PNP transistor so that Vout would be more positive as the input current got further from Vbias.  I have 6 different PNP transistors from the Iteadstudio assortment of 11 different transistors, and I chose the A1015 rather arbitrarily, because it had the lowest current gain. I should probably try each of the other PNP transistors in this circuit, to see how sensitive the circuit is to the transistor characteristics.  I suspect it is very sensitive to them.

The circuit only works if the collector-base junction is reverse-biased (the usual case for bipolar transistors), so that the collector current is determined by the base current. The emitter-base junction may be either forward or reverse biased.  Note that if Vin is larger than Vbias, the collector-base junction becomes forward-biased, the negative input of the op amp is slightly above Vbias, and the op amp output hits the bottom rail.

As long as Vin stays below Vbias, the current through R2 should be , and the output voltage should be for some constants A and B that depend on the transistor. Note that changing R2 just changes the offset of the output, not the scaling, so the range of the output is not adjustable without a subsequent amplifier.

The 1000pF capacitor across the transistor was not part of the designs I saw on the web, but I needed to add it to suppress high-frequency (around 3MHz) oscillations that occurred. The oscillations were strongest when the current through R2 was large, and the log output high.  I first tried adding a base-emitter capacitor, which eliminated the oscillations, but I still has some lower-frequency oscillations when the transistor was shutting off (very low currents).  Moving the capacitor to be across the whole transistor as shown in the schematic cleaned up both problems.

I put ramp and sine wave inputs into the log amplifier.  The waveforms were generated with the Bitscope function generator, which does not allow setting the offset very precisely—there is only an 8-bit DAC generating the waveform.  Here is a sample waveform:

Click picture for larger image. The green trace is the input, the yellow trace is the output. The horizontal axis in the middle is at 2.5V for the input (so the input is always below 2.5V) and at 3V for the output. The scale is 1V/division for the input and 50mV/division for the output.  [And all those values should be visible in the saved snapshot, but they aren't.]

The ripple on the output is mainly artifacts of the low-resolution of the BitScope A-to-D converter—smoothing of multiple reads is done, but there is a lot of quantization noise. According to my analog scope there are still some 24MHz noise around, but it seems to be from the Vbias source—adding a 4.7µF capacitor between Vbias and +5V (adjacent pins on the op amp) cleaned things up a lot on the analog scope, without affecting the BitScope traces.

Using the cursors on the BitScope, I was able to measure the output voltages for input voltages of Vbias-0.5V, Vbias-1V, and Vbias-2.5V.  From these, I concluded that the scaling factor for the output was about 3.1–3.2 mv/dB.  The output was 3±0.07V, so the dynamic range is 140mV/(3.2 mv/dB), or about 44dB.  We can see the logarithmic response in an X-Y plot of the output vs the input:

(Click for larger image) Output vs. input of the log amplifier. Note that the output is the log of Vbias-Vin, so the log curve looks backwards here.  It’s a shame that BitScope throws away the grid on XY plots, as the axes are still meaningful.

I also tried using an external oscillator, so that I could get better control of the offset voltage, and thus (perhaps) a better view of the dynamic range. I could fairly reliably get an output range of about 200mV, without the hysteresis that occurs when the collector-base junction gets forward biased. That would be over 60dB of dynamic range, which should be fine.

I should be able to adjust the voltage offset of the amplifier by changing R2. Increasing R2 reduces the current, which should lower the voltage. I tried several different values for R2 and measured the maximum output voltage, using the same input throughout:

1kΩ 3.106v
10kΩ 3.056v
100kΩ 2.992v
1MΩ 2.936v

The 60dB difference in current produces a 170mV difference in output, for 2.83 mV/dB.

Oops, those weren’t quite all the same, as the load from the resistor changes the input. Adding a unity-gain buffer driving the inputs and adjusting the input so that the output of the unity gain buffer has a slight flat spot at 0V gives me a new table:

1kΩ 3.12v
10kΩ 3.06v
100kΩ 3.00v
1MΩ 2.94v
5.6MΩ 2.90v

which is consistent with 3mV/dB. I was not able to extend this to lower resistances, as I started seeing limitations on the output current of the op amp. But it is clear that the amplifier can handle a 75dB range of current, with pretty good log response.

An Arduino input is about 5mV/count, so the resolution feeding the output of the log amplifier directly into the Arduino would be about 1.7dB/count. We could use a gain of 4 without saturating an op amp (assuming that we use 2.5V as the center voltage still), for about a 0.4 dB resolution. More reasonably, we could use a gain of 3 to get a resolution of about 0.54dB/count.

I tried that, getting the following table:

1kΩ 4.46v
10kΩ 4.28v
100kΩ 4.10v
1MΩ 3.91v
5.6MΩ 3.78v

This table is consistent with 9.1 mv/dB, for a resolution of about 0.54 dB/step on the Arduino.

I tried using the Arduino to collect the same data and fit with gnuplot:

(click plot to see larger version) The gnuplot fit agrees fairly well with the measurements made with the BitScope for 5 resistor values. The resolution of the Arduino DAC limits the ability to measure the dynamic range, and the cloud of points is broad enough to be consistent with slightly different parameter values.

The next thing for me to do on the log amp is probably to try different PNP transistors, to see how that changes the characteristics. My son will probably want to use a surface-mount transistor, so we’ll have to find one that is also available as a through-hole part, so that we can check the log amplifier calibration.


Filed under: Data acquisition Tagged: Arduino, BitScope, i-vs-v-plot, log amplifier, loudness, op amp

Logarithmic amplifier

My son wanted to design a circuit to convert microphone inputs to loudness measurements usable by an Arduino (or other ATMega processor).  We discussed the idea together, coming up with a few different ideas.

The simplest approach would be to amplify the microphone then do everything digitally on the Arduino. There are several features of this approach:

  • The analog circuit is about as simple as we can get: a DC-blocking capacitor and an amplifier.  This would only need one op amp, one capacitor, and 2 resistors (plus something to generate a bias voltage—perhaps another op amp, perhaps a low-drop-out regulator).
  • Using digital processing, he can do true RMS voltage computation, and whatever low-pass filtering to smooth the result that he wants.
  • He can’t sample very fast on the ATMega processor, so high frequencies would not be handled properly.  He might be able to sample at 9kHz (about as fast as the ADC operates), but that limits him to 4.5kHz. For his application, that might be good enough, so this doesn’t kill the idea.
  • He’d like to have a 60dB dynamic range (say from 50dB to 110dB) or more, but the ADC in the ATMega is only a 10-bit converter, so a 60dB range would require the smallest signal to be ±½LSB, which is at the level of the quantization noise.  With careful setting of the gain for the microphone preamp, one might be able to get 55dB dynamic range, but that is pushing it a bit.  The resolution would be very good at maximum amplitude, but very poor for quiet inputs.

Although the mostly digital solution has not been completely ruled out, he wanted to know what was possible with analog circuits.  We looked at two main choices:

  • True-RMS converter chips (intended for multimeters).  These do all the analog magic to convert an AC signal to a DC signal with the same RMS voltage.  Unfortunately, they are expensive (over $5 in 100s) and need at least a 5v power supply (he is planning to use all 3.3v devices in his design).  Also true RMS is a bit of overkill for his design, as log(amplitude) would be good enough.
  • Using op amps and discrete components to make an amplifier whose output is the logarithm of the amplitude of the input.  Together we came up with the following block diagram:

Block diagram of the loudness circuit. (drawn with SchemeIt).

We then spent some time reading on the web how to make good rectifier circuits and logarithmic amplifiers. I’ll do a post later about the rectifier circuits, since there are many variants, but I was most interested in the logarithmic amplifier circuits, which rely on the exponential relationship between current and voltage on a pn junction—often the emitter-base junction of a bipolar transistor.

My son wanted to know what the output range of the log amplifier would be and whether he would need another stage of amplification after the log amplifier. Unfortunately, the theory of the log amplifier uses the Shockley ideal diode equation, which needs the saturation current of the pn junction—not something that is reported for transistors.  There is also a “non-ideality” parameter, that can only be set empirically.  So we couldn’t compute what the output range would be for a log amplifier.

Today I decided to build a log amplifier and see if I could measure the output.  I also wanted to figure out what sort of dynamic range he could get from a log amp. Here is the circuit I ended up with, after some tweaking of parameters:

The top circuit is just a bias voltage generator to create a reference voltage from a single supply. I’m working off of 5v USB power, so I set the reference to 2.5v. He might want to use a 1.65v reference, if he is using 3.3v power.
The bottom circuit is the log amplifier itself.

I chose a PNP transistor so that Vout would be more positive as the input current got further from Vbias.  I have 6 different PNP transistors from the Iteadstudio assortment of 11 different transistors, and I chose the A1015 rather arbitrarily, because it had the lowest current gain. I should probably try each of the other PNP transistors in this circuit, to see how sensitive the circuit is to the transistor characteristics.  I suspect it is very sensitive to them.

The circuit only works if the collector-base junction is reverse-biased (the usual case for bipolar transistors), so that the collector current is determined by the base current. The emitter-base junction may be either forward or reverse biased.  Note that if Vin is larger than Vbias, the collector-base junction becomes forward-biased, the negative input of the op amp is slightly above Vbias, and the op amp output hits the bottom rail.

As long as Vin stays below Vbias, the current through R2 should be , and the output voltage should be for some constants A and B that depend on the transistor. Note that changing R2 just changes the offset of the output, not the scaling, so the range of the output is not adjustable without a subsequent amplifier.

The 1000pF capacitor across the transistor was not part of the designs I saw on the web, but I needed to add it to suppress high-frequency (around 3MHz) oscillations that occurred. The oscillations were strongest when the current through R2 was large, and the log output high.  I first tried adding a base-emitter capacitor, which eliminated the oscillations, but I still has some lower-frequency oscillations when the transistor was shutting off (very low currents).  Moving the capacitor to be across the whole transistor as shown in the schematic cleaned up both problems.

I put ramp and sine wave inputs into the log amplifier.  The waveforms were generated with the Bitscope function generator, which does not allow setting the offset very precisely—there is only an 8-bit DAC generating the waveform.  Here is a sample waveform:

Click picture for larger image. The green trace is the input, the yellow trace is the output. The horizontal axis in the middle is at 2.5V for the input (so the input is always below 2.5V) and at 3V for the output. The scale is 1V/division for the input and 50mV/division for the output.  [And all those values should be visible in the saved snapshot, but they aren't.]

The ripple on the output is mainly artifacts of the low-resolution of the BitScope A-to-D converter—smoothing of multiple reads is done, but there is a lot of quantization noise. According to my analog scope there are still some 24MHz noise around, but it seems to be from the Vbias source—adding a 4.7µF capacitor between Vbias and +5V (adjacent pins on the op amp) cleaned things up a lot on the analog scope, without affecting the BitScope traces.

Using the cursors on the BitScope, I was able to measure the output voltages for input voltages of Vbias-0.5V, Vbias-1V, and Vbias-2.5V.  From these, I concluded that the scaling factor for the output was about 3.1–3.2 mv/dB.  The output was 3±0.07V, so the dynamic range is 140mV/(3.2 mv/dB), or about 44dB.  We can see the logarithmic response in an X-Y plot of the output vs the input:

(Click for larger image) Output vs. input of the log amplifier. Note that the output is the log of Vbias-Vin, so the log curve looks backwards here.  It’s a shame that BitScope throws away the grid on XY plots, as the axes are still meaningful.

I also tried using an external oscillator, so that I could get better control of the offset voltage, and thus (perhaps) a better view of the dynamic range. I could fairly reliably get an output range of about 200mV, without the hysteresis that occurs when the collector-base junction gets forward biased. That would be over 60dB of dynamic range, which should be fine.

I should be able to adjust the voltage offset of the amplifier by changing R2. Increasing R2 reduces the current, which should lower the voltage. I tried several different values for R2 and measured the maximum output voltage, using the same input throughout:

1kΩ 3.106v
10kΩ 3.056v
100kΩ 2.992v
1MΩ 2.936v

The 60dB difference in current produces a 170mV difference in output, for 2.83 mV/dB.

Oops, those weren’t quite all the same, as the load from the resistor changes the input. Adding a unity-gain buffer driving the inputs and adjusting the input so that the output of the unity gain buffer has a slight flat spot at 0V gives me a new table:

1kΩ 3.12v
10kΩ 3.06v
100kΩ 3.00v
1MΩ 2.94v
5.6MΩ 2.90v

which is consistent with 3mV/dB. I was not able to extend this to lower resistances, as I started seeing limitations on the output current of the op amp. But it is clear that the amplifier can handle a 75dB range of current, with pretty good log response.

An Arduino input is about 5mV/count, so the resolution feeding the output of the log amplifier directly into the Arduino would be about 1.7dB/count. We could use a gain of 4 without saturating an op amp (assuming that we use 2.5V as the center voltage still), for about a 0.4 dB resolution. More reasonably, we could use a gain of 3 to get a resolution of about 0.54dB/count.

I tried that, getting the following table:

1kΩ 4.46v
10kΩ 4.28v
100kΩ 4.10v
1MΩ 3.91v
5.6MΩ 3.78v

This table is consistent with 9.1 mv/dB, for a resolution of about 0.54 dB/step on the Arduino.

I tried using the Arduino to collect the same data and fit with gnuplot:

(click plot to see larger version) The gnuplot fit agrees fairly well with the measurements made with the BitScope for 5 resistor values. The resolution of the Arduino DAC limits the ability to measure the dynamic range, and the cloud of points is broad enough to be consistent with slightly different parameter values.

The next thing for me to do on the log amp is probably to try different PNP transistors, to see how that changes the characteristics. My son will probably want to use a surface-mount transistor, so we’ll have to find one that is also available as a through-hole part, so that we can check the log amplifier calibration.


Filed under: Data acquisition Tagged: Arduino, BitScope, i-vs-v-plot, log amplifier, loudness, op amp