Microprocessor based meter project

GroupDIY Audio Forum

Help Support GroupDIY Audio Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
You could add a resistor, capacitor and clipping diodes to the input attenuation network to pre-distort the signal going into the ADC to increase dynamic range. And I suppose you could connect it to a pin to make it programmable  as I believe someone (joaquins?) was pondering.

More specifically, your attenuation network is something like a 100n cap, 68k and then two 22k to +5V and ground to bias. Right? So at the intersection of those three resistors add a 10k and 10u cap in series and then two diodes in parallel but in opposite orientations connected to ground. So when the signal level is low, you get no additional attenuation but at higher levels the signal starts to clip and you get more attenuation.

Yes, the signal will be distorted but it doesn't matter because you are ultimately just going to have a table of thresholds for each LED that corresponds to whatever level. So you just calibrate it once and adjust the threshold values in your table accordingly.

Also, someone mentioned that when you start switching channels to read from multiple analog inputs at the same time, you can read garbage data because the ADC can take time to settle. If you use Arduino, it has something called "high speed mode" which can affect that behavior. Search for the ADHSM bit in the corresponding Atmel datasheet. Although if you're just alternating between two inputs I don't think it will be a problem because the inputs won't have time to drift off too much.
 
squarewave said:
You could add a resistor, capacitor and clipping diodes to the input attenuation network to pre-distort the signal going into the ADC to increase dynamic range. And I suppose you could connect it to a pin to make it programmable  as I believe someone (joaquins?) was pondering.
Yes the input will be cap coupled and biased up to roughly 1/2 supply voltage.

Adding clamp diodes and trying to perform a crude log conversions of their nonlinear clamp voltage is possible but unlikely to be accurate enough to be acceptable for a meter. One expects a degree of accuracy when reporting available headroom. If all you want is blinky lights and don't care about accuracy it could work.

I experimented with a programmable pad that could use a processor pin to attenuate high level signals (for a mic input). Processors do not generally like logic inputs that float at indeterminate levels, since CMOS logic can draw excessive current if input is neither high nor low. I worked around that by setting up the pin as an A/D input so it could sit at indeterminate levels, but not sampling it by the A/D. For my mic input I was either floating a resistor or pulling a resistor to +V so it worked... An audio pad meter front end, "might" work similarly if DC operating point shift can be accommodated.
More specifically, your attenuation network is something like a 100n cap, 68k and then two 22k to +5V and ground to bias. Right? So at the intersection of those three resistors add a 10k and 10u cap in series and then two diodes in parallel but in opposite orientations connected to ground. So when the signal level is low, you get no additional attenuation but at higher levels the signal starts to clip and you get more attenuation.
AKA a diode break circuit. When dealing with a processor voltage rail of 3.3V, the 0.45-0.6V diode threshold is a large fraction.  I do not discourage you from trying that but I wouldn't try it, again for accuracy and repeatability reasons. A production design should not have major component sensitivities.
Yes, the signal will be distorted but it doesn't matter because you are ultimately just going to have a table of thresholds for each LED that corresponds to whatever level. So you just calibrate it once and adjust the threshold values in your table accordingly.
Perhaps if you generate a unique look up table for those exact parts and operate at constant temperature (diode thresholds change with temperature).  Again, go ahead and try it, a clever outside the box idea.. (back in the day I would have tried a cheap transistor array for repeatable diode junctions, like I did for many log conversions.)
Also, someone mentioned that when you start switching channels to read from multiple analog inputs at the same time, you can read garbage data because the ADC can take time to settle. If you use Arduino, it has something called "high speed mode" which can affect that behavior. Search for the ADHSM bit in the corresponding Atmel datasheet. Although if you're just alternating between two inputs I don't think it will be a problem because the inputs won't have time to drift off too much.
The mechanism is not related to the A/D conversion time which completely variable. The trade off for faster conversion time is less LSB accuracy so you can have fast or accurate, pick one.

The ghosting I was talking about is dominated by pin input capacitance. If one sample has the pin up near 3V and the next sample is at 1.65V it will take finite time to get there. This only becomes visible as an error when an input is dead quiet , and switching from a loud input.  A much slower conversion, allows a longer settling time (also adjustable IIRC) but that causes different issues... I was commutating between 6 inputs (4 active at a time to support solo switching two channels).

Again a single input meter will not have these multiplexed input issues.

JR
 
  Couldn't I use two digital inputs and just let one clip? One without (or little) attenuation feeding it with a high value resistor so clipping current is under control, the other with the desired attenuation. Both biased from the same DC so the offset doesn't need to be corrected between the two of them.

  I mean, is there something horribly wrong with let the input clip? If so, I could add an extra set of diodes handle the clipping current and still be in business with this approach.

JS
 
joaquins said:
  Couldn't I use two digital inputs and just let one clip? One without (or little) attenuation feeding it with a high value resistor so clipping current is under control, the other with the desired attenuation. Both biased from the same DC so the offset doesn't need to be corrected between the two of them.

  I mean, is there something horribly wrong with let the input clip? If so, I could add an extra set of diodes handle the clipping current and still be in business with this approach.

JS
Yes for a simple low count or only one input meter.... In general I would want to securely clamp the input to prevent adjacent inputs from corrupting each other from  dumped error currents but external clamps should work.

Internal clamp current has to go somewhere and internal clamps are only designed to prevent harming the chip not preventing errors.

This is generally unworkable when trying to make a single longer digital word from two inputs for playback, but for metering which is far less precise, you should be able to alternate relatively seamlessly and pick up a few bits at either end.

JR
 
I've been following your posts, you're full of neat electronics tricks but this one takes the cake:
JohnRoberts said:
I experimented with a programmable pad that could use a processor pin to attenuate high level signals (for a mic input). Processors do not generally like logic inputs that float at indeterminate levels, since CMOS logic can draw excessive current if input is neither high nor low. I worked around that by setting up the pin as an A/D input so it could sit at indeterminate levels, but not sampling it by the A/D. For my mic input I was either floating a resistor or pulling a resistor to +V so it worked...

So you used the microcontroller's internal pullup resistor as the "bottom" resistor in a  voltage divider/pad you can switch on and off under processor control by turning on/off the activate-pullup-resistor bit.  I would have never thought to do that (or if I did, I'd wonder about the tolerance of that internal resistor). If you didn't get a patent, you should have at least submitted a writeup for a "design ideas" column in an electronics trade magazine. I'm sure you still can still do that.
 
benb said:
I've been following your posts, you're full of neat electronics tricks but this one takes the cake:
nah, just another idea on the wood pile.
So you used the microcontroller's internal pullup resistor as the "bottom" resistor in a  voltage divider/pad you can switch on and off under processor control by turning on/off the activate-pullup-resistor bit.
I don't think so... In fact pull up is probably a small current source. (at least on the microchip processors I work with) so very unlikely to serve as a linear resistance.

For my mic pad I used a real external resistor that was either floating or inparallel with high gain pullup resistor to +V. (cheap microphone with an open drain output that gets loaded with a R to +V... gain range on these cheap chinese mics is not very tight.
I would have never thought to do that (or if I did, I'd wonder about the tolerance of that internal resistor). If you didn't get a patent, you should have at least submitted a writeup for a "design ideas" column in an electronics trade magazine. I'm sure you still can still do that.
yawn... already have 9 patents and just abandoned my last one because thousands of dollars were due for the maintenance fee.
(and I'm cheap)

I used to read the design ideas when I was just starting out, but these days I don't even read the trade magazines.

I have notebooks of old ideas I never finished, which means they were little more than mental masturbation.

JR

PS: I recently thought of designing a smart battery charger... perfect project for a microprocessor, BUT I could buy a commercial unit in a nice package for $39 with free shipping.  ::)  That was easy.  8)
 
  This would do then, diodes could be 4.7V zener (for my 5V micro) or even 3.9V ones if I really want to be sure not to get over the rails, 4.7 seems a bit tight, even worse if the rail is not quite 5V. Or just conventional diodes as they will clamp the voltage to something safe and not much current at all should be left for the internal clamps with a last resistor before the converter (R6)

  I choose about 30dB attenuation so I have some overlap between the ranges while getting a decent dynamic range. This would allow me to implement some hysteresis for changing ranges so I don't need to do it so often. I guess the overlapping could be greater if looking for precision or lower if aiming for the higher dynamic range.

  The other option could be to use 2 analog inputs with two resistors as JR suggested with only one, leave them floating for no attenuation or send one low and one high, so DC offset is small, but there would still be some change in the DC level unless matched resistors or trimming is used. This last reason is why I ruled this one out, as it's quite necessary to shift ranges as fast as possible to avoid loosing fast peaks, which are quite hard to catch already in a tiny-micro based meter.

JS
 

Attachments

  • Input circuit.png
    Input circuit.png
    5.5 KB
joaquins said:
  I choose about 30dB attenuation so I have some overlap between the ranges while getting a decent dynamic range. This would allow me to implement some hysteresis for changing ranges so I don't need to do it so often. I guess the overlapping could be greater if looking for precision or lower if aiming for the higher dynamic range.

  The other option could be to use 2 analog inputs with two resistors as JR suggested with only one, leave them floating for no attenuation or send one low and one high, so DC offset is small, but there would still be some change in the DC level unless matched resistors or trimming is used. This last reason is why I ruled this one out, as it's quite necessary to shift ranges as fast as possible to avoid loosing (sic) fast peaks, which are quite hard to catch already in a tiny-micro based meter.

You’re trying to do high-dynamic range metering, like HDR on a CMOS image sensor. And you’re getting killed by the settling time of the mux in front of the ADC, as you switch from a high-gain to a low-gain setting and of course from left to right channel.

Get a cheap external ADC. If you use a standard audio type with I2S, get a micro with an I2S interface. (Yes, they exist.) Those micros seem to all have a limit of 48 kHz sampling (there’s a reason, which is not important) but who cares for metering. Trailing-edge audio ADCs are way cheap. These ADCs mean you don’t need to do this HDR switching/clipping stuff.  16 bits of resolution oughta be enough for metering. (A proper DSP chip will support higher sampling rates, but now you’re getting really complicated.)

You can also get a multichannel ADC of whatever resolution you like. Get a 4-channel 12-bit job with an SPI interface. Make sure it can sample all eight channels simultaneously.  (Transfer to the micro is, of course, one channel at a time.)  Channel 0 is left high-gain, channel 1 is left low gain, channel 2 is right high-gain, channel 3 is left low-gain.  Your micro cycles through each channel. Read left high-gain, if it clipped or is above a threshold, read the low-gain channel too, make a 16-bit word out of the results. Repeat for the right channel. Do the averaging on the 16-bit word.

Advanced homework assignment: do the whole thing in a small FPGA (like Lattice XO2). Five bucks, and you get a lot of pins to drive your metering LEDs without the external shift registers and without Charlieplexing or other muxing technique.
 
Andy Peters said:
You’re trying to do high-dynamic range metering, like HDR on a CMOS image sensor. And you’re getting killed by the settling time of the mux in front of the ADC, as you switch from a high-gain to a low-gain setting and of course from left to right channel.

Get a cheap external ADC. If you use a standard audio type with I2S, get a micro with an I2S interface. (Yes, they exist.) Those micros seem to all have a limit of 48 kHz sampling (there’s a reason, which is not important) but who cares for metering. Trailing-edge audio ADCs are way cheap. These ADCs mean you don’t need to do this HDR switching/clipping stuff.  16 bits of resolution oughta be enough for metering. (A proper DSP chip will support higher sampling rates, but now you’re getting really complicated.)
+1  you can source a cheap 16b codec for around $1.08 in 1k quantity. For some reason stereo codecs are cheaper than mono A/D on digikey. perhaps because they are so widely used in consumer gear.
You can also get a multichannel ADC of whatever resolution you like. Get a 4-channel 12-bit job with an SPI interface. Make sure it can sample all eight channels simultaneously.  (Transfer to the micro is, of course, one channel at a time.)  Channel 0 is left high-gain, channel 1 is left low gain, channel 2 is right high-gain, channel 3 is left low-gain.  Your micro cycles through each channel. Read left high-gain, if it clipped or is above a threshold, read the low-gain channel too, make a 16-bit word out of the results. Repeat for the right channel. Do the averaging on the 16-bit word.

Advanced homework assignment: do the whole thing in a small FPGA (like Lattice XO2). Five bucks, and you get a lot of pins to drive your metering LEDs without the external shift registers and without Charlieplexing or other muxing technique.
The 4 channel meter I did for APB console was performed by the 12b internal A/Ds inside a cheap PIC....  the digital meter had a cheaper BOM than the old analog meter circuitry it replaced but with extra features.

A single $5 FPGA might have been cost comparable when you add in the several LED SR latches and extra logic PS rail, but i don't know how to design FPGA... might be a good project for a young person to pick up a merchantable skill that could be useful later...

JR

PS: When I designed a digitally controlled analog automatic mixer (again using a single PIC) I had to resist the temptation to connect a few cheaps codecs and be all digital,,, while the $1 codecs are not going to win any hifi awards. The cheap codecs were cheaper than the DPOTs I used for gain control.

 
JohnRoberts said:
+1  you can source a cheap 16b codec for around $1.08 in 1k quantity.
...
JR
  No, I can't, not here where I am. If I would be going for production overseas or live in a country with the components availability Europe or USA I would probably agree.

  While I agree that using an external converter or different parts would do the job easier and maybe better, I'm trying to solve it inside the single micro for a single reason, availability. For some of you an ADC is in your door the next day (or two) after an element14 order, for me is more like 2 month and a ton of paper work and extra custom and mailing fees. Making it work with just an arduino and trivial parts (LEDs, diodes, resistors, caps and stop counting) is a real advantage for a lot of DIYers, the hard part to get would be the arduino which is quite widely available, and if you can get the LEDs you better do something else completely.

  I have now another ongoing project which uses a TI converter, a boost converter, battery powered with it's management and 5V supply, raspberry as central piece and other stuff around, I don't fear for complexity, I just acknowledge that is just not possible for everybody, which I'd like this project to be.

  In the other hand, I'm quite happy with the dynamic range I got with a single input, well over 40dB, 9 LEDs in 6dB steps, which is about the theoretical limit for the 10 bits ADC. As I said I couldn't test the precision as there is too much noise where I have it, just a protoboard right next to my computer, I'd like to do so and if not good enough I guess with better processing should do the trick but now I don't even have a shielded cable to feed the signal in, this was a late night thing to give a kickstart to this. All this with only 4 external passives plus the LEDs and it's resistors. I don't think the extra complexity and trouble justifies the external serial devices or VHDL/Verilog which would make unaccessible for newbies to implement tweaks on the code. I would totally go for a PIC if it's demo-boards had the availability Atmel's have.

I'd keep on to it in when I can, I'd like to try the extra LEDs and the precision and see how I'm doing.

JS
 
Andy Peters said:
Advanced homework assignment: do the whole thing in a small FPGA (like Lattice XO2). Five bucks, and you get a lot of pins to drive your metering LEDs without the external shift registers and without Charlieplexing or other muxing technique.

OK, in the Money-Where-Your-Mouth-Is Department ...

Like pretty much everyone else here, I think I can design an ADC and DAC that's as good as anything we can buy. So I designed one. Two of the parts on the board require some intelligence for configuration, plus it has a simple user interface (buttons for operation control, LEDs for status), so the first thought was to use an SiLabs 8051. That's the simple solution. The 8051 has an on-board ADC, perfect for the input meter function (for the audio ADC side), and it can scan buttons and with a muxing scheme drive LEDs or maybe use SPI LED drivers.

But then I started to get into the weeds. What is the audio ADC's reference, so one can do a proper measure of input level as seen by that ADC? Do I need a reference for the micro's ADC that is "better" than what is built in? What's the gain structure of the whole thing anyhow?

That's when I remembered that the SiLab's ARM devices (EFM32 and Si3M, which are all pretty cheap) have USARTs which can be configured to work as an I2S slave. Just route the ADC BCLK, LRCLK and data lines to the micro and there it is.  Except when configured as an I2S slave, the maximum sample rate supported (actually the limit is in the BCLK) by these micros is 48 kHz. Grrr!

What about using programmable logic for the I2S part? Easy. But then why glue that part to a micro when the whole thing can be rolled up into a small FPGA?  Oh, wow, Xilinx Spartan3AN (XC3S50AN) is too expensive at $15. Lattice has the MachXO2 devices, and the moderate size part (LCMXO2-1200) in a 100-pin TQFP is $7. And unlike the Xilinx, it doesn't need a separate 1.2 V core supply, as it has an onboard regulator.  Bonus! MachXO2 has an onboard "Embedded Function Block" with two I2C ports, an SPI port, a timer and a good amount of user flash memory. Bonus 2! Lattice has a small microcontroller core called Mico8 you can put into an FPGA!

After spending too much time trying to work out the Mico8 toolchain, I gave up, realizing that what I was doing really didn't need a micro. Squirting configuration data into a peripheral chip over I2C or SPI can be done with a hardware state machine.  Plus why make the design bigger, fitting in the micro?

Next up: EFB. Cool, it has a timer, which maybe I can use to detect the frequency of incoming word clock. Except, no, it doesn't have that kind of capture feature. So it's easy enough to write that code in VHDL. A counter runs on the system clock. Word clock input is synchronized to that clock, and on every rising edge of word clock you capture the counter value and reset it. The counter value tells you your word clock frequency. If the counter rolls over, you flag that as "no word clock present."

Cool, EFB has I2C and SPI ports which I can use to configure those peripherals. Except: the access to those ports is through a WISHBONE (open-source) bus interface, which just adds a level of crap to the whole thing. And basically the idea of a "general purpose SPI core" is dumb, as it's always easier to just embed the shift registers into the larger control logic instead of trying to go through some standard bus interface. Once you realize that there's no such thing as an "SPI standard," and that some slaves have really idiotic requirements, and that the number of bits you need to shift is design dependent, you just end up forgetting about a core and just writing an interface to the part you're controlling.  So, EFB out, and two interfaces to the two peripherals that need configuration.

User interface operation is straightforward. Buttons are debounced. There is a button that selects the ADC sample rate, another button that enables external word clock sync (only if word clock is present) and a third button chooses which digital input is used by the DAC section. Status LEDs show the current operating state.

Back to the metering.
An I2S slave receiver deserializes the data from the ADC into the left and right channel data, which are then synchronized to the global clock. Data are rectified and I throw away the eight LSbs, because 16 bits is more than enough for a meter.

I wrote a low-pass filter (averager) and a peak detector (with peak hold) in VHDL. The output of each hit a bank of comparators, one per meter segment. (I chose 32 segments per meter.) The peak meter and the average meter were ORed to get the final meter drive.

At first I instantiated two meter circuits (averager, peak detect, comparator bank) but that was wasteful, since the I2S data gives me one channel at a time. So I removed one of the meter circuits, fed the deserialized/rectified data into the remaining one, and LRCLK tells me which channel sample is in the meter at a time. (Remember the meter calculations take much less than a sample time.) Then to save some FPGA pins, the metering is multiplexed into four banks of 16 segments.

The FPGA design uses 62 of the 80 I/O pins available, about half of the registers, 84% of the slices, and three of the seven block RAMs present in the LCMXO2-1200 device.



I'm laying out the PCB now and I hope to have that done by the end of the week. So maybe by the first of the year I'll have it all built up and I'll post details and a video of the meter as well as the VHDL source.
 

Latest posts

Back
Top