7:40 timestamp would be appreciated.
Some other descriptions of your system might be:
Fuzzy logic[1]
Unary ADC extension[2]
Multi-[voltage-]windowed ADC
Floating point precision ADC[3]
etc.
[1] As an array of variables, which take values of "true" and "false", but also varying levels of "truthiness" between those bounds; often as a probability, but in the case as a proportion.
[2] Perhaps not as appreciated as it should be: the classic LM3914 LED bargraph display driver, is a 10-bit unary flash ADC.
- It has a voltage divider chain, setting a series of reference/threshold voltages.
- It has exactly as many comparators, and the output is instantaneous (i.e., propagation delay of the comparators -- typical for its time, fractional microsecond).
- The output of the comparators has not been encoded in any way, and the reference series is a linear progression.
- Therefore, the output is a sorted count-the-ones (thermometer code) value. In other words, every digit has a significance of 1, no matter its position; it's a non-positional number system; unary.
It also has a dot-graph mode, in which case it is a... kind of oddly positional system, but that's less helpful here.
(Real flash ADCs, use an encoder to produce binary output, or whatever they happen to; weird things like gray code have been popular IIRC. They're not at all common for board-level integration purposes these days, AFAIK.)
[3] We can generalize further from the above, and consider the unary result (as whichever inputs are fully "true", in the "fuzzy" sense) as the exponent offsetting a proportional mantissa (which takes some logic to select it from whichever element is not saturated). This is kind of an abuse, because, floating point has a multiplicative exponent, whereas this system is additive only -- but I think the analogy is arguably apt, as we see the same relationship between the unary number and a conventional (positional) number.
And a point for sake of discussion: it's not sacrificing ADC resolution in any way whatsoever. It's
extending it (hence the second term at the top). In this case, 4 unary digits (uh, they're not bits... uits?
... oh right,
units) adds two bits, effectively extending the 10-bit ADC (this was a regular ATMEGA Arduino right? I didn't check for that detail) to 12, more or less.
Downsides to the system:
- Saturation is not perfect. RRIO opamps only saturate within some margin of their supplies, sometimes a fixed offset (particularly bipolar types), others proportional to load current (which is positive (output-sinking) for all amps for Vin > Vcc).
- The supply isn't perfect either. Vcc is being used as a reference, so it's "dirtied" in a sense, from all the op-amps running off it. Their supply currents cause voltage drops, and change in the input signal causes partial response on other channels, and corresponding disturbance at the supply. (This probably explains, in part, the lumpy saturation waveforms seen on the scope, and the dips seen on the readout.)
- Alsoooooo... you're using, not just resistors, but a shitton of resistor dividers. So, the headline claim is...a bit disingenuous.
...which I can [mostly] excuse for sake of memes, of course it's gonna clickbait, right?
So, we could improve it by:
- Add an analog switch to change the input scale
This multiplies the input by some gain factor (<> 1 as needed, and if you want to use op-amps vs. those vile-nasty resistor dividers!), thus implementing floating point as such. Negative ranges would have to be extended with bipolar (+/-) supplies to get the voltage range (including down to / a teensy bit below zero, to avoid amp saturation issues), including an inverter to restore the positive (unsigned) ADC range. You never get any more bits in the mantissa, but you get true floating point with a binary (or other base, however you dimension the dividers) exponent.
This is actually of some commercial importance: some audio systems (sound cards etc.) use this mechanism (both ADC and DAC, though probably more at DACs, I'm not sure exactly?). If some fractional bits are added to the exponent, it can be used for volume control without loss of dynamic range -- simply add/subtract a volume gain (in dB or whatever) to the exponent, and the signal is still there, in all its 16 bits or whatever of glory (at least until it disappears beneath the input/output buffer's noise floor). Or, really, if you don't mind cranking the multiplication, you can have whatever accuracy of exponent, and rescale the mantissa (by a factor [0.5 ... 2) say, for a binary exponent) at the cost of minimal rounding error.
Another benefit is, with audio signals often being very peaky, a lot of information is recorded both in the mantissa and exponent; sometimes this is used directly at the ADC, with an exponential sequence of thresholds: "mu law" encoding. This was used back in the day to improve the bandwidth efficiency of digital trunk (telephone) lines; and, I suppose it's still relevant today, albeit in less direct ways (like, today we have whole-ass lossy codecs that discard tons more information, without losing vocal fidelity).
Alternately (and more directly equivalent):
- Add a selectable offset
Treat the input node as a summing junction. But, unlike a linear op-amp, our amp has a chunky (heavily quantized) output, and we measure the remainder. The summing node ranges 0..5V; when it's below this range, we decrement the output, or above, increment. Thus leaving some hysteresis where the input can hover inbetween thresholds, but also giving a potentially unlimited range, at least if we don't mind that the input has a current-mode characteristic or whatever. (That is, if we have an input voltage, through a series resistor, now we get a current; or vice-versa if current into a shunt resistor.)
And we supply this offset from a DAC, so that there's no messy op-amp saturation, the level is precise (reference-derived) and etc.
This in turn, is equivalent to a counting-type ADC, i.e.: simply hook a free-running digital counter (0...MAX) to a DAC and let it spin; when its output meets the above criteria (input within range), copy the result. More exactly, as described, it's an up-down relative count, but a counter nonetheless. Either way will work, of course you'd probably just do it this [relative] way in software, it's easier, faster and smoother.
The DAC can have a binary input, so that we aren't wasting GPIO pins, and it only requires a single ADC input, no sampling skew incurred (which is probably the other part of the dropouts in your plotting output?) (and, only requiring N samples required to slew over an input step change of N * Vref).
And it only needs the one op-amp to sum the input with the DAC output.
oof.wav
airhorns.wav
But seriously -- it's a good demonstration of how to invent something, and which, with a little refinement, leads into perfectly practical methods such as above. Thanks for showing it off. I probably take issue with exact things in the video (which, again admittedly, I skipped through, and anyway, some of that is just stylistic choice for the video), but it's far from useless as you can see.
There are still some sticky points, with matching up the ADC/DAC range -- if a given DAC bit is too wide, there will be missing bits (the (xx)FF or (xx+1)00 step is anomalously wide), or if too narrow, there will be missing bits ((xx)FE jumps straight to (xx+1)00 or whatever), or the measurement is unstable (dithering between the two codes because the range is never met on either side of the exact input). And the DAC must be extremely precise, so as to preserve the LSBs' accuracy -- i.e. the VREF steps need to be accurately "full scale" to within an LSB of the ADC's range. Which is kinda another way to say the same thing.
So hey, there you go.
On a related note, if you cascade the amps rather than stack them, you get a log amp instead. Which is another way to implement a (true) floating point measurement. Every amp that is railed, is another decimal place (read in unary, expressing whatever number base the stages are wired in, i.e. each stage's gain, ideally 2.000... for binary, etc.), and the first proportional one gives the mantissa. (All lower-gain stages give the respective fraction of the same mantissa, so aren't interesting.)
This is used -- with somewhat less precision as it doesn't matter -- in IF (intermediate frequency) amp "strips" in some radio receivers. By taking the (arithmetic) sum of all amp outputs, the output magnitude is more-or-less log(input), and so changes in amplitude are passed with modest fidelity (i.e., it's an amplitude detector), and the mean level simply gives signal strength in dB (times a constant).
Or wired another way: say we use a sample-and-hold, and instead of cascading amps, we use a single amp and loop it onto itself -- with the S&H as an analog "D flip-flop" (i.e., output takes value of input only on rising edge). And suppose we simply take a 1-bit ADC (a comparator at VREF/2) each step, because it's cheap. Finally, we subtract 0 or VREF/2 from the signal each time, corresponding to the result of the comparator. Now we have a SAR (successive approximation register) ADC, although not quite a SAR as that properly uses a full-width DAC I think; but it produces one bit per cycle all the same. This is most likely what's used in most CMOS ADCs (using charges coupled between capacitors, to save on op-amps), and in particular, can be pipelined trivially: make a matrix of such stages, sequencing the input between the first amp in each chain, all the rest being cycled to their own outputs; and latching the comparator outputs into shift registers to record the bit results as a continuous bit-stream. Add some compensation and encoding (typically packing bits into LVDS pairs or buses), and you have a typical modern high-speed ADC.
(I don't know the exact details of those faster ADCs (pipelining is typically used >20Msps or something like that), and they're notoriously secretive with their tricks of course. The ATXMEGA series (and maybe MEGA0 by extension, I don't know?) does seem to have the (single amp loop, non-pipelined) version, with control features including adding additional sample or multiplication cycles -- without shifting out the result, delaying and gaining it instead. The hardware is probably not much more advanced than that of the ATMEGA (it's 3.3 instead of 5V, and 30 instead of 20MHz F_CPU), but the sample rate is ~30x higher; a substantial improvement. It's also 12 bit, and has much improved INL/DNL.)
Tim