Multislope ADC

Making the most of non-ideal components in a non-ideal world.

Similar projects worth following
A precision analog-to-digital converter based on integrators, current switching, voltage-to-time conversion and the tried-and-tested multislope method.

Integrating ADCs are at the heart of every DMM with a resolution higher than 4.5 digits. Despite being able to deliver sub-ppm resolution, they are in principle uncomplicated and relatively easy to construct and operate. Resolutions greater than 6.5 digits can be obtained with a BOM cost of less than 100 Euros.

Armed with a few tubes of precision op-amps, integrated resistor networks and the computing power and GPIO control of the Raspberry Pi Pico, I embarked on an ongoing journey to build and characterize my own 6.5 digit multislope ADC.

Adobe Portable Document Format - 146.17 kB - 04/11/2023 at 19:51


  • Don't Shoot the Messenger!

    NNNI06/15/2023 at 19:07 0 comments

    After the successful experiments described in this log, I assumed that my troubles with the ADC were finally over and I was looking forward to seeing some useful readings. 

    After I replaced the troublesome and hard-to-find machine pin headers with regular pin headers, the board was ready for its first full power-up in almost 10 months. 

    I was glad to see that everything worked just fine. The sample rate of my scope leave something to be desired. 

    I set up the code to send a stream of data to my computer through USB serial, logged the charge balancing counts and residue counts before and after, and plotted the residue reading difference in Excel. 

    Almost as if I had made no changes to the board, the severe noise and banding was back, and I had no clue what was going on this time. 

    I brought out the calculator and elbow grease and manually checked the voltages on the input of the residue ADC, and made some interesting findings. 

    The first flat area, which is where the residue ADC makes a measurement of the integrator state before charge balancing, corresponded perfectly with the second residue variable, which is supposed to be the integrator voltage after charge balancing. The pre charge balancing value didn't correspond with the voltage at the ADC input at all. 

    This got me thinking. I realized that there was a dummy measurement made as soon as the Pi Pico was powered up, in order to put the state machine in dithering mode. During this time, the residue readings were not read and could possibly be clogging up DMA.

    Since I knew the second value being returned was correct, I kept that as such, and moved the first value up by one column in Excel and then plotted the difference. 

    To my surprise, the difference now corresponded perfectly with what was expected. Something was causing the first value being returned to be delayed by one reading. I made a crude diagram to show what was going on.

    One of my initial suspects was a software bug somewhere in the residue reading process, but it was not where I expected it to be!

  • Integrators, DAM Switches and Speed

    NNNI05/15/2023 at 22:17 0 comments

    Another line from The Art of Electronics (3rd Edition) caught my eyes. 

    More specifically, it’s easy to show that the ΔV term by itself yields the correct input voltage for a measurement whose duration equals a single clock cycle (i.e., Tmeas = 1/ fclk).

    Basically, if the integrator is allowed to charge up for a certain time period and the residue ADC reads the integrator voltage before and after measurement, you can get the original input voltage back using the formula: 

    Here, Vin is the input voltage to the integrator, R and C are the integrator resistor and capacitor values, dV is the resolution of the residue ADC and dt is the integration time. 

    If we can vary the integrating time correctly, we can measure full scale voltages like 10V with a short integration time (to prevent the integrator from saturating), and small voltages like 1uV by integrating for a longer time. Of course, you can't measure large voltages with a high resolution, so this is a floating-point conversion with a fixed resolution, which in this case is the resolution of the residue ADC. At each point in time, there is a specific input to output "gain", which increases with integration time and therefore "programmable". Of course, this requires knowledge of the input voltage to set the "gain" correctly. 

    Wouldn't it be nice to have a way to keep the integrator roughly zero to get a coarse reading, and using the residue ADC to do a fine reading? Oh wait...

    That brings us straight back to the multislope! The charge balancing keeps the integrator voltage roughly around zero while providing a count of the charge needed to do so, and the residue ADC reads integrator state before and after charge balancing to provide finer details. 

    Now this is not new information, since previous logs already went into depth about how the multislope topology works. I just found this new way of thinking quite interesting. 

    Let's consider some numbers. The integrator on the current multislope has a 10K resistor and a 1nF capacitor. The MCP3202 residue ADC has a 12-bit resolution, and with a reference voltage of 3.3V can resolve voltages of 1mV. Assuming a measurement cycle is 20ms (1 PLC), the residue reading has a resolution of 500nV according to the above formula. If the integration time is increased to 200ms (10 PLC), the resolution is improved to 50nV. If the integrating capacitor is reduced to 100pF, the same 500nV resolution can be achieved in 2ms. 

    The takeaway is that with faster integration, that is, smaller integrating capacitor, measurements can be sped up with fast charge balancing.

    Out of curiosity, I tried using the formula to crunch the numbers for the 34410A, which boasts 4.5 digit resolution in 20us. It's ADC has a 50K input resistor and a 47pF integrating capacitor and a 10-bit ADC referenced to 1V, so a 1mV residue resolution. For an integrating time of 20us, the resolution comes out to 100uV. in the 10V range, that gives a usable reading of 10.000V, which is 4.5 digits. 

    There are practical limitations to how fast currents can be switched, and the analog switches used to do the current steering are the limiting factor. The 74HC4053D used in the 34401A meter specifies a worst case switching time of 200ns, which is no good for speed. The 34410A solves this problem using an interesting circuit called a DAM switch, described in US patent 20050024119A1. I assume this circuit was used to overcome the limitations of regular analog switches and could handle the fast switching speeds.

  • Did You Hear That Whistling Sound, Too?

    NNNI05/06/2023 at 00:18 0 comments

    In my case, it was sadly not outer-space type music (Whoooooo!), but the slope scaler amplifier ringing. 

    The slope scaler amplifier scales the +/-5V integrator swing to a reasonable 0V to 3V that the residue ADC can digitize. However, even early on, I noticed that the scaler amp had a slight ring to it. I naively dismissed this, since "it's meant to be a DC amplifier anyway". This is potentially a problem, since the output could ring with a sudden load change, like when the residue ADC is sampling. 

    The simple fix would be to just add a capacitor across R47 and call it done. The value of said capacitor is key - too little won't fix the problem, and too much would just slow the op-amp down unnecessarily. The key is to find the right value. 

    Instead of my preferred method of trying different capacitor values, I tried to take a more analytical approach. The first step in doing that would be to determine the gain of the scaler amp. This sounds like an easy task, since it is basically an inverting configuration. The problem starts when you realize that the gain is less than one, since R47 is 15K and R44 and R45 in parallel (since they both return to a low impedance node) come out to 16K. How does a circuit with a gain of less than one oscillate?!

    The trick (kindly provided by a friend) here is to use something called the noise gain, which emulates input noise by connecting a voltage source in series with the op-amp's input terminals, changing it and seeing how the output changes. The output change for a given input change is the noise gain. This works regardless of the test source polarity or which input it is connected to. 

    All of the above circuits are basically the classic non-inverting configuration with a gain of:

    Thanks to the 1 term, the gain is always above (or at least equal to) 1, which makes a lot more sense from the ringing point of view. The noise gain is now 5.7dB. I employed LTspice to handle the mathematical heavy lifting from this point on. 

    I was able to find a model for the OPA197 (and verify it by doing a simple frequency response plot and seeing if it corresponded with the one in the datasheet) and simulate the above circuit. 

    The peaking in the frequency response before the gain rolls of below zero is a classic indicator for ringing. 

    I simulated the entire circuit, and to get the same ringing as I did in real life I had to add 25pF of capacitance to the summing junction node. 

    Now to the actual task of compensating it. I'm too embarrassed to reveal my own formula for a rough estimate, but it delivered 24pF, which was a little too much. 10pF worked perfectly. 

    After soldering a 10pF capacitor across R47, the results looked like this. 

    I found it highly amusing to see that theory and practice corresponded so perfectly for once. 

    Regarding the 25pF at the summing junction - the value seems suspiciously high to me. I can only assume that the same poor layout that messed with the residue ADC either created some extra capacitance at the summing junction or some stray inductance. Regardless, the ringing is now gone. 

    Apollo 10's space music turned out to be interference, by the way. 

  • A Path Forward

    NNNI04/30/2023 at 21:51 0 comments

    Most of the work on Multislope 3I concluded by late July 2022. I was on an informal deadline since I was due to move to Germany on the 15th of August that year to start my higher education. Although readings with a theoretical resolution of 10uV had been achieved, there were still a lot of unanswered questions, the biggest one being the source of severe noise and banding in the residue ADC readings. The residue ADC of choice was the MCP3202, which is a pretty interesting part.

    The below chart plots the residue readings (difference in integrator voltage before and after conversion) obtained. The +/-1000 count noise is highly unusual, and upon closer inspection, some banding is also visible. 

    Two of the biggest suspects were a bug in the software and PCB layout. To test the former, I desoldered the MCP3202 and put it on a Manhattan prototyping board to ensure neutral layout. 

    The MCP3202 IC has a somewhat complicated SPI transaction that had to be split into three transfers of a byte each. Recombining these bytes incorrectly could have possibly led to noise and banding. The input to the ADC was a simple 1K/1K divider connected between VCC and ground. With a neutral layout, I tested four apporaches:

    • PIO: I used the RP2040's PIO to set up a custom SPI interface, which let me get the data in a single 18-clock transaction. 
    • Original SPI code: I separated and re-compiled the code used in the original project and used it to get a conversion in three bytes. 
    • "Direct" SPI: The C/C++ SDK comes with a built-in function to read more than 8 bits "directly", although upon probing it does split the transaction into bytes. 
    • PIO with SPI pins: I had to change the wiring a little bit between PIO and SPI readings since the SPI pinout was slightly different. To make sure that the wiring changes didn't affect the readings, I set up PIO to operate from the SPI pins. 

    In all four cases, noise was quite acceptable and the readings showed no banding. The MCP3202's input was probed during sampling and the input spike settled within 1/10 of the SPI clock. 

    The above tests prove that a software bug could be ruled out, since all four approaches have very similar results, with non-PIO readings being slightly noisier. 

    Once again, I put the MCP3202 back on the original PCB and bodged some connections to the external Pi Pico. 

    The readings were now much worse, with banding being visible in histograms of a single run. This proves with reasonable certainty that the original layout was not optimal. 

    This was a four layer board, and the ground plane was on the bottom-most layer, two layers below the MCP3202. Signal and power traces were also routed freely below the part, which was clearly a mistake. 

    There were still a few more things I wanted to try. The first was a simple filter on the input, consisting of a 56 Ohm resistor and a 1nF capacitor (values copied from Jaromir's NVM). I also added an extra 470uF capacitor across the supply pin and ground. 

    The readings are now perfect - not a single bit of noise over three runs of 1000 samples! Looks like the previous poor results were caused by lack of proper layout and decoupling, which is on me. 

    The above test was performed on a slightly modified setup where I used some copper tape and an SMD adapter on the PCB itself, ready for future testing. 

  • Code overview

    dim04/22/2023 at 13:36 0 comments

    The RP2040 was chosen because of its ability to implement custom peripherals using PIO. As explained earlier the multislope topology requires a balancing act of the input in order to not saturate it as well as maintaining a constant number of switch transitions per reading in order to have a known amount of charge injected into the integrating capacitor, to calibrate it out later. This can be done using PWM, where the output of the comparator is used to change the duty cycle of the subsequent PWM cycle. The described can be implemented with bit banging on almost any microcontroller with some software know-how. But hanging up the CPU on several second long measurements is sub-optimal, so implementing it in PIO was more desirable with the added benefit of certainty in the timings and state transitions (since any jitter on the control signals can add up to big uncertainties in the measurements).

    The entire multislope algorithm, as well as its idle state (dithering) was fit into a single PIO state machine, almost filling up the available instruction storage, with 30 out of the available 32 instructions being used. Now, let’s take a look at how it was implemented. (It is assumed that the reader has some familiarity with the RP2040 PIO instruction set and architecture)

    .program ms
    .side_set 1
    ; 1 side set bit for the MEAS pin
    ; don't forget to enable auto push
    set pins 0 side 0
    mov X, !NULL side 0 ; set X to 0xFFFFFFFF
    out Y, 32 side 0 ; read the number desired counts
    irq wait 0 side 0 ; first residue reading
    out NULL, 32 side 0 ; stall until DMA finished reading the ADC
    jmp begining side 0 ; got to PWM
    set pins 0 side 0 ; turn switches off
    in X, 32 side 0 ; push PWM to FIFO
    irq wait 1 side 0 ; second residue reading
    out NULL, 32 side 0 ; stall until DMA finished reading the ADC
    jmp !OSRE start side 0 ; jump out of desaturation when the OSR has data
    set pins 1 side 0 [1] ; set pin polarity
    jmp pin dithHigh side 0 ; check if the integrator is still high
    jmp !OSRE start side 0 ; jump out of desaturation when the OSR has data
    set pins 2 side 0 ; set pin polarity
    jmp pin dithHigh side 0 ; check if the integrator is high
    jmp dithLow side 0 ; stay low
    set pins 1 side 1 ; set PWMA high, and PWMB low [01 clock cycles]
    jmp pin PWMhigh side 1 ; read comparator input, jump to pwm high state [01 clock cycles]
    set pins 2 side 1 ; turn off PWMA if the pin is low [01 clock cycles]
    jmp X-- PWMlow side 1 ; else jump to PWM low state [01 clock cycles] (if pin is low we decrement X)
    set pins 1 side 1 [15] ; keep PWMA high [02 clock cycles] + [28 clock cycles] = 30
    nop side 1 [11]
    set pins 2 side 1 ; set PWMA low, at the same time PWMB high [01 clock cycles]
    jmp Y-- beginning side 1 ; go to the beginning if y is not zero yet [01 clock cycles] = total 32
    jmp finish side 0 ; go to rundown when y is zero we don't care at this point anymore
    set pins 2 side 1 [15] ; set PWMA low [4 clock cycles] + [27 clock cycles] = 31
    nop side 1 [10]
    jmp Y-- beginning side 1 ; go to the beginning if y is not zero yet [01 clock cycles] = total 32
    jmp finish side 0

    When starting up PIO will start from the first instruction in the program, so it begins execution in `start`. Here we first set all the pins into a known state (all off).

    Next, using a trick with the binary operations PIO supports, we invert a NULL and store the result in the 32-bit X register. This fills up X with 1s. This is required in order to create a counter inside PIO, since we don’t have an i++ instruction, we need to get creative. By using the jump instruction with the x-- operator we can achieve the same thing just inverted. When the result of X will be shifted to the CPU, it will just perform an inversion on its end to get the count.

    The Y register is used to store the requested number of counts to perform, that is just read from the OSR (Output Shift Register, from the perspective of the CPU)....

    Read more »

  • The Future

    NNNI04/16/2023 at 21:26 0 comments

    Integrated ADCs are fast approaching the performance previously only achieved by integrating ADCs. The AD4630 is a fine example, with a 24-bit (slightly more than 7.5 digits) resolution at a 2Msps sample rate. With the right analog front end and some signal processing, performance comparable to 6.5 digit meters is possible. The AD4030, a close relative of the 4630, is reported to have true 8.5 digit linearity. I have acquired samples the AD4630 and plan to investigate it further in the future. 

    High-resolution integrated ADCs have not yet found use in bench multimeters, where advanced forms of the multislope ADC still operate. One of the more interesting implementations is found in the HP/Agilent/Keysight 34410A. The Art of Electronics has a short side-note about their multislope implementation that piqued my interest. 

    "Looking at Multislope IV waveforms with a scope, you see a much different beast. A1b has been replaced with a faster AD829 op-amp (120 MHz, 230 V/μs), with the integrating capacitor C1 reduced by 5x. A hardware engine forces the error integrator to produce consistent 10 Vpp ramps with a 2μs period, using coarse data from an 80MHz AD9283 converter digitizing the 10V ramp at 14 ns intervals, and fine data from an AD9200 10-bit converter with a limited 2V range, clocked at 75 ns intervals near zero volts. Slope changes and the counter record are made at 75 ns intervals, and the AD9200 makes starting and ending readouts with 0.02% resolution. As a result, a Multislope IV converter can measure 4.5 digits in 20μs (0.001 PLC), or 20× faster than Multislope III."

    (The Art of Electronics, page 921, footnote 61)

    The brief explanation leaves a lot to be desired, and acquiring a 34410A to reverse engineer is beyond my means as a student with no source of income. However, this description forms the basis of my plans for the next revision of the multislope ADC, called Multislope 4(IV). 

    Aside from excellent op-amps, TI recently released the TMUX113x series of analog switches. These feature incredibly low charge injection (1pC) and single ohm on-state resistances. The TMUX1133 matches the pinout of the 4053, while TMUX1134 has four switches. The latter opens up some interesting possibilities like using the fourth switch to short the integrator between measurement cycles, which would do wonders for dielectric absorption and save some PIO instructions.

  • Asides

    NNNI04/14/2023 at 22:21 0 comments


    Modern operational amplifiers are a marvel of analog design. They enable circuits on the razor edge of the analog and digital domains, like the multislope ADC described in this project. Right from the uA741 released in the late 1960s with a measly 7.5mV offset voltage, to the modern OPA140 (released by TI in 2010) with a 150μV offset voltage (and a 1μV/C drift to go with it), the analog semiconductor industry has seen astounding growth. CMOS processes for analog design have enabled "hybrid" chopper amplifiers like theADA4523 with single-digit microvolt offsets and 10s of nanovolts of temperature dependence. Going into the future, further developments in silicon processes and thoughtful mixed-signal design might facilitate the performance needed to unlock the 10th digit in DMMs. 

    Of course, there is no "all-rounder" op-amp. The limitations of one op-amp can be overcome by using a composite configuration as described. There is a lot of theory behind composite amplifiers and their stability, on which I will have to do more research to fully understand and implement to achieve better performance.


    The multislope ADC can easily be configured to self-calibrate drift of the reference amplifiers and zero error, with the addition of a multiplexer on the input. If the reference voltage is fed into the multislope ADC, it can compare the reading with a previous reading of the reference, which would indicate how much the reference amplifiers have drifted since the last calibration, since it is assumed that the reference is the most stable voltage in the circuit. By connecting the input multiplexer to ground, zero error can be measured. 

    Another trick here is to connect the input multiplexer before the input buffer op-amp. The high input impedance of the op-amp means there is little to no input current, so the multiplexer's on-state resistance errors are eliminated. 


    When this project started, my coding expertise was limited to Arduino C++. Of course, the AVR-based Arduino boards were not ideally suited to running a demanding application like the multislope ADC. I was introduced to both the Raspberry Pi Pico with the remarkable PIO peripheral and Dmytro, who is now probably one of the world's leading Pi Pico experts. Without their assistance, this project would not have reached the stage it is in today. 


    Falstad is an incredibly convenient and intuitive way to simulate circuits. I have encountered criticism for using it to simulate precision circuits like the multislope, since it does not account for a lot of real world non-idealities. To that, I will have to say that the goal of a Falstad simulation is not to accurately model the real world, but to quickly get a circuit up and running to do an "idiot check". Its real-time simulation also helps in understanding circuit functionality, with sliders being used to change parameters on the fly. 

    Have other people tried to make multislope ADCs?

    Yes! One of the most brilliant examples is Jaromir's Nanovoltmeter, which uses a DIY multislope ADC not very different from the one described here, exhibiting +/-0.25ppm non-linearity. Several others have been built and characterized, details can be found buried in various EEVBlog Forum threads. 

  • Putting Ideas Into Practice

    NNNI04/11/2023 at 22:28 0 comments

    The multislope ADC's potential 6.5 digit resolution means there are some finer details to the actual implementation.

    The first thing is the reference voltage. The go-to choice for high-accuracy bench DMMs is the LTZ1000. Given its price, availability and the large number of expensive supporting components required, it is not the best choice for a DIY approach. The LM399 is a popular part that is used in many 6.5 and 7.5 digit meters. It is more or less a simplified version of the LTZ1000 and costs around 20 Euros in single quantity. It consists of a Zener diode and a heater that maintains the diode at a constant temperature. Applying it is very simple, it only needs a heater supply and a current source to bias the Zener diode. The LM399 has now been superseded by the ADR1399

    Of course, in real life, the LM399 requires a little care and feeding. The heater pins are connected across the +/-15V supply. While starting up, the heater has a low resistance and can easily draw a few hundred milliamps, which can cause the supply voltages to droop. A constant current source could be added in series to the heater to prevent excessive startup current, but on this board I chose not to add an untested circuit. In normal operation, the heater draws around 20mA. The Zener diode is "bootstrapped" to the reference amplifier output. This ensures a constant voltage across the current setting resistors R6 and R7, leading to a stable Zener current and therefore a stable Zener voltage. D3 and R43 form part of the startup circuit to ensure that the reference does not start up the "wrong way", that is, forward biasing the Zener diode. R43 sets up a small trickle current on startup that correctly biases the Zener diode, after which the op-amp takes over through D3. R5 and C2 can be optionally populated if an ADR1399 is being used, which needs some external compensation to ensure good transient response. R1, RN1A and C3 provide some additional filtering to reduce reference noise. 

    The multislope requires two equal reference voltages of opposite polarity, which are derived from the reference. Feedback resistors could be selected to provide an exact voltage like 10V, but using a 2:1 divider simplifies the overall circuit and gives the input voltage a little more headroom. There are other ways to implement the bipolar references, like a cascaded non-inverting and inverting amplifier, but I chose the "constant current string" topology.

    The LM399's Zener voltage is fed into the input of U1A, which tries to maintain the same voltage across RN1B. Since the other end of RN1B is held at ground by U1B, the voltage across it is exactly the reference voltage. Since RN1E, RN1C and RN1D are of the same value, the same voltage is generated across them since the same current flows through them. This means the outputs of each op-amp are at +/- 2x Zener voltage and inherit some of the LM399's stability.

    The analog switch is a crucial part of the circuit. My choice was the SN74LV4053 from TI, which is a low voltage variant of the classic CD4053 SPDT analog switch IC. I've tested the LV4053, and it can switch up to several megahertz. Since it can run from a 3.3V supply, talking to it using a Raspberry Pi Pico is easy. The switches in the IC have an on-state resistance of 190 Ohms with a 3V supply and 30 Ohm matching between channels. Temperature coefficient is not specified. It is important that the analog switches have an on resistance that is much smaller than the V-to-I resistors. In this case, the latter are 10 kiloohms, so a 190 Ohm on resistance represents 2% of their resistance. Supposing the switches have a 5%/K temperature coefficient, the overall variation with temperature is just 0.0005%/K (5ppm/K), not including the temperature coefficient of the V-to-I resistors themselves. The ferrite beads prevent switching artefacts from making their way into ground or the summing junction, and the 100R/100pF filter serves to filter charge...

    Read more »

  • The "Ideal" Multislope Topology

    NNNI04/11/2023 at 22:26 0 comments

    I spent a lot of time thinking about how the integrator and current switching circuit topology found in all modern multislope implementations could be improved, but all roads led me back to the same place - the circuit is almost perfect as it is: 

    The circuit above shows a marked difference from the simulations posted in the previous log. As per tradition, the Falstad simulation of the above circuit is here.

    At the heart of the changes is the op-amp based integrator, which takes over from the plain capacitor. In this inverting configuration, the op-amp's inverting input forms a summing junction that is maintained at ground potential. This is one of the main elements that makes precision current switching possible. 

    Precision floating current sources are quite hard to construct. The Keithley 2002's multislope ADC features such current sources, at the cost of complexity and expensive precision resistors. Since the summing junction is held at 0V, a resistor connected to the summing junction acts like a single component V-to-I converter, with the current into the summing junction being the voltage across the resistor divided by the resistance. 

    The simple SPST switches have been replaced by SPDT switches. The central pole is connected to the "bottom" of the resistors, one terminal to the summing junction, and one to ground. It might seem like SPST switches would suffice, but if that were the case, the reference voltages (which are usually derived from an op-amp) would see a changing load between 0A and the reference current at several kilohertz. Precision op-amps, which are used to derive the reference voltages, usually have a low bandwidth and cannot respond quickly to load changes. This leads to reference instability and overall measurement inaccuracy. By using an SPDT switch to steer current between ground and the summing junction, a constant current is drawn from the reference voltage. This helps with accuracy and stability. All terminals of the switch are also held at a constant voltage, eliminating to a large extent a crippling parasitic effect present in almost all CMOS analog switches called charge injection.

  • Integrating ADCs: An Introduction

    NNNI04/11/2023 at 19:54 0 comments

    Integrating ADCs fall under the broad category of ADCs that convert voltage to time, which include voltage-to-frequency and voltage-to-duty cycle. The name itself implies that the mathematical function of integration takes place along the conversion process. The most convenient electronic building block to perform that task is the capacitor, the voltage across which is an integral of the input current over time, described by:

    Since an integrator is basically a first-order RC filter, most of the high frequency noise on the input is filtered out, leading to cleaner readings. On the other hand, the integrating action also means that conversion times are relatively slow.

    The simplest manifestation of an integrating ADC is the single-slope ADC, which consists of a current source feeding a capacitor, a comparator and some controlling circuitry. The input signal is fed into one input of the comparator, and the current source driven capacitor is connected to the other. External circuitry maintains the capacitor at 0V through a shorting switch. When the conversion starts, the shorting switch is opened and the capacitor charges through the current source. Since the charging current is constant, the voltage ramps up linearly. When the voltage across the capacitor equals the input voltage, the comparator signals the control circuitry to stop the conversion. It also shorts capacitor to reset it for the next cycle. The actual conversion from analog to digital takes place at the comparator output, which is a binary representation of the state of charge of the integrating capacitor. This is used to gate a series of clock pulses. The number of pulses is directly proportional to the voltage on the capacitor, and therefore the input voltage. 

    Here's a link to a Falstad simulation. 

    Although straightforward, this simplistic method is not without its flaws. Integrating ADCs rely heavily on the integrating capacitor being stable with time and temperature. There is one other undesirable property of capacitors that can affect linearity - dielectric absorption. Increasing precision also places demands on the comparator, which needs to have a low offset voltage and low input noise. Although the absolute value of the offset voltage can be calibrated out, its variation with temperature is harder to account for. Input noise also affects the repeatability of the comparison. The latter effect is practically never mentioned in datasheets and determining it can be trickier than that of op-amps.

    Dual-slope ADCs solve both of these problems to a large extent. A current proportional to the input voltage is allowed to charge the integrating capacitor for a fixed time period. The voltage on the capacitor after this time is proportional to the input voltage. The capacitor is then discharged through a constant current source. The discharge time is proportional to the input voltage and can be digitized in a similar manner as the single-slope. 

    (The Art of Electronics, pg. 915 Figure 13.43)

    The above diagram from The Art of Electronics explains the dual-slope conversion process. 

    Since the process now involves two slopes - one to charge the capacitor to a voltage proportional to the input voltage and the other to discharge it down to zero - the effects of dielectric absorption are seen on both slopes and have a smaller effect on the readings. Since the slopes start and end at the same voltage, comparator offset cancels out. 

    Here's another Falstad simulation of a dual-slope ADC. 

    The limitations of dual-slope ADCs occur at the higher and lower end of the measurement range. At the lower and, resolution is limited by measurable integrator swing, clock resolution and the noise floor. At the upper end, the integrator needs larger output swings for the larger input voltages, risking saturation. Another subtle disadvantage the dual-slope shares with the single-slope is that measurement time is proportional...

    Read more »

View all 10 project logs

Enjoy this project?



Kuba Sunderland-Ober wrote 05/01/2023 at 02:46 point

A quite decent multislope ADC can use just about any switches by switching current instead of voltage. The trick is to have a closed loop that adjusts the operating voltage for zero charge injection. Once you have current switching, it's not a long shot to use transistor pairs for switching. There, the trick is to switch the base currents from either leg into a current sense resistor, so that the base current is compensated for.

In most general terms, as long as you can ovenize the thing, really low cost industry standard op-amps that were around for decades will provide surprisingly good performance. Not necessarily practical in a production instrument, but for a hobby one-off it's perfect :)

I agree with others that RP2040 is just about perfect for this application. It makes for a great inguard, and the outguard could be just about any Linux board. Control via a USB isolator and an optocoupler for mains frequency reference and optional external trigger - that way outguard is not even necessary, it can be just one's PC.

  Are you sure? yes | no

NNNI wrote 05/01/2023 at 09:42 point

I would definitely consider using discrete transistor pairs a long shot, since base-current compensating circuitry will add to complexity. There is also the matter of transistor switching times (base storage charge, etc.) and level shifting 3.3V logic to whatever the transistor switch needs. Since current steering provides the same advantages to integrated analog switch ICs, I would consider them a more practical solution. 

Ovenization is also somewhat excessive and might actually lead to more problems than solutions. The ratio stability of the resistor network is plenty good enough for consistent 6.5 digit readings, and the reference drift with temperature (if designed correctly) is also negligible. Very good results can be and have been achieved without ovenization. 

I'm still curious about the transistor pair switch, do you have a schematic for it?

  Are you sure? yes | no

Kuba Sunderland-Ober wrote 05/01/2023 at 18:09 point

Transistor current switches work in linear region. They don’t saturate. That’s how ECL is fast. 

  Are you sure? yes | no

John Wettroth wrote 04/22/2023 at 16:04 point

Cool project, I've dreamed about this looking at Multislope ADC timing diagrams.  Good luck in the contest!  You might want to look at Maxim's (now ADI) offerings in analog switches.  They also make premium switches in 4000 series pinouts- they "invented" the idea.  I defined these parts about 20 years ago as the switch apps guy and I think they are still better than the TI parts that you're using.  The first parts are simply the MAX405x series following the 4000 series numbers.  They have about 1/6 of the Ron, 1/10 the Ron flatness, lower C and comparable charge injection but likely more symmetric (see text later).  Maxim makes others in these pinouts  that will let you trade off other parameters for improvements in others.  These others  don't follow the simple numbering scheme but Maxim's web site has good parametric search tools.  For lowest charge injection, you shouldn't push on Ron too much.  Keep the on currents low or zero with good design, which I can see you're doing and you can get very good charge injection and symmetry.  Charge injection is caused by charging and discharging the gate C of the switch channels.  The very lowest charge injection parts have Ron's approaching 2K ohms.  Since N channels have lower Ron's for the same area as P channels (hole mobility is just lower), the gate C (charge) of the P's is higher and the symmetry of charge injection is not perfect.  In one case, you're charging a N and discharging a P and vise versa- you're also doing this with inherently asymmetric CMOS drivers- this gets pretty subtle.   You'll likely find the Maxim parts better in this area too.  I noted that you are maintaining even transitions high and low but be aware that this assumes symmetry.  Good luck.

  Are you sure? yes | no

NNNI wrote 04/22/2023 at 18:53 point

Thanks for the interesting comment! I took a look a the MAX405x series datasheet, the specs still don't match the part I've chosen for the next iteration of this project, the TMUX1134. However, I think it's still worth testing all parts and see what works best. 

  Are you sure? yes | no

John Wettroth wrote 04/22/2023 at 20:32 point

I was looking at the Vanilla TI versions in your PDF- I'll look at these newer guys.

I also wanted to say that I think its just brilliant to make use of PIO in Pico for  this application.  All the high end meters have a little FPGA or CPLD to do the logic- PIO is ideal and you still have two little ARMS to use.  One of the best applications of Pico that I've seen yet  next to generating video.  Good luck.

  Are you sure? yes | no

John Wettroth wrote 04/23/2023 at 12:57 point

I looked at the TI TMUX parts and I have to say that TI is on the ball with switches these days- 1 ohm and 1 pC is off the FOM charts. Generally these Q numbers apply at a specific bias and common mode, etc. Be weary of "too good to be true".

  Are you sure? yes | no

dim wrote 04/22/2023 at 21:31 point

As the one who recommended and programmed the PIO I am glad to hear you like the idea. I remember when NNNI told me about the timing requirements and his desire to keep it low cost, the only sensible option was the RP2040 to me. And I am very glad I took the challenge to implement it. It was a great way to learn the hardware and I hope my write-up will help people understand it more in-depth and start to use it more instead of just throwing ~~money~~ FPGAs at the problems.

  Are you sure? yes | no

John Wettroth wrote 04/22/2023 at 23:09 point

I am impressed you got it to fit in 32 instructions!  Nicely done.

  Are you sure? yes | no

NNNI wrote 04/23/2023 at 13:54 point

Regarding the TMUX113x - the nice thing about multislope is that it keeps both poles and the common pin all at close to zero volts, so the effect of charge injection is greatly reduced. Based on some experiments by other people, powering the TMUX113x with around +/-2.5V also reduced charge injection by a lot, although I'm not sure about the exact numbers. 

  Are you sure? yes | no

John Wettroth wrote 04/23/2023 at 14:50 point

Very Good.  The CM volts and rails affect a lot with analog switches.  In some exotic apps, its make sense to use unbalanced rails.  I think charge injection and dielectric absorption like effects are the real limitations of all these analog integrator schemes.  Watching with high interest.

  Are you sure? yes | no

macaba wrote 04/25/2023 at 10:33 point

For those who are interested, my testing with TMUX1133 in current switching applications (i.e. 0V on both drain/source) showed that zero charge injection is achieved at around +3.3V & -1.4V which is convenient for driving with 3.3V IO. Stunningly good part with excellent FOM.

  Are you sure? yes | no

Nikola Manolov wrote 04/20/2023 at 20:40 point

Oh this is one of the coolest projects I've seen in a long time. Not very practical since modern ADCs are really great, but it looks like great fun and a good way to practice. It would also look great on a CV. 

I cant wait to see how you continue that project. Best of luck.

  Are you sure? yes | no

NNNI wrote 04/21/2023 at 07:23 point

Thanks! Surprisingly basically all bench DMMs still use some form of multislope - Keithley 2000, 2001, 2002, HP/Agilent/Keysight 34401A, 34410A and 3458A, so I wouldn't say this ADC is dead yet! Although as I mentioned the AD4630 and AD4030 are close, but they have some quirks of their own, like the limited input range and the input sampling, both of which need an input stage that has to accommodate a wide input range (which multislope does automatically) and buffer the semi-capacitive inputs. 

  Are you sure? yes | no

Nikola Manolov wrote 04/21/2023 at 21:21 point

Oh yes, you are right, they are used in all high end multimeters. I believe that has more to do with the fact that its cheaper/quicker to improve the older designs for newer models than to change the architecture.
Or maybe I don't know enough about this topic and I'm missing important aspects like acquisition speed or dynamic range or something else. Its not my field, so iI accept corrections. 
Either way - I'm looking forward to seeing how you progress with this. Best of luck. 

  Are you sure? yes | no

Tom Nardi wrote 04/11/2023 at 20:02 point

Wasting no time with this entry, excited to see more.

  Are you sure? yes | no

NNNI wrote 04/11/2023 at 20:12 point

Thanks for the interest! Since this project is ongoing and has been going on for a while, do checkout the YouTube playlist and the Github repo for more! 

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates