Electronics > Beginners

Digital adjustable resistor

<< < (16/17) > >>

BrianHG:
One note, if you want a digital attenuation, you should not be using fixed resistors with matched R2R values.  It is a waste as proper logarithmic constant impedance versions can be done with the right resistors and wiring.  Also, a proper 6 bit logarithmic attenuation, IE: set to a true 1.5db per lsb step, would offer the equivilant to a 16bit linear digital resistor.

Spread sheets/calculators exist for these resistor values.

Ignore this post if you just need a linear programmable resistor instead of a programmable attenuation.

Nominal Animal:
Here's an idea for the series configuration, using n-MOSFETs.  I don't know if this works, but perhaps the experienced members here could tell.  I did simulate it, and it seems to work.

Let's say the series resistor set is between Vin and Vout, with Vin > Vout.
You use an n-channel power MOSFET with low Rds(on) to short out each resistor.  Each will have a high-value resistor (say, 1M) between gate and source, so by default they are non-conducting.  (The idea is that we just need to pump some current into the gate to short out each resistor.)

Microcontroller GND is at Vin, and Vcc at Vin+4V.  On each GPIO output, you have the gate of a P-channel MOSFET (like DMP610DL that can withstand (Vout-Vin)-4V drain-source and gate-source voltages, with low enough gate threshold voltage so it can be switched at -4V; the currents are tiny).  Their sources are connected to Vcc, and drains are connected (via current-limiting resistors) to the gates of the n-channel MOSFETs.

When the GPIO is high or tri-state/floating, the p-MOSFET gate and source are at the same potential, so it does not conduct.  Then, the n-MOSFET gate also has its gate and source at the same potential, so it does not conduct either, and the resistor is enabled (not shorted).

When the GPIO is low, the p-MOSFET has Vgs=-4V, so it conducts.  This lifts the n-MOSFET gate to at least 4V higher than its source (more, if the voltage has dropped in the preceding resistors).

eslavko:
Relay are still to bulky and all optocouplers suggested are to slow! Switching time in 5ms! I need to change resistance inside 100us window when PWM/PDM signal is in low state.

And to be more clear.
We have around 10 devices and I want just to upgrade them. The populated PCB cost around $150. The device as is have 11 bits in one leg and 13 bits in other leg (can simulate two resistors). But in present state have only one bit on each leg ON. So one leg can have 11 values, and other one 13 values. 
If I manage to make parallel resistor to cover required range the update is just firmware change and resistors change on PCB. To make both legs with 12 bits I need to cut one trace and make one bridge. Using serial resistors, relays optocouplers it's near impossible to use existing PCB.
So is it possible to get required range from 12 bits?

Zero999:

--- Quote from: eslavko on October 09, 2022, 06:05:39 am ---Relay are still to bulky and all optocouplers suggested are to slow! Switching time in 5ms! I need to change resistance inside 100us window when PWM/PDM signal is in low state.

And to be more clear.
We have around 10 devices and I want just to upgrade them. The populated PCB cost around $150. The device as is have 11 bits in one leg and 13 bits in other leg (can simulate two resistors). But in present state have only one bit on each leg ON. So one leg can have 11 values, and other one 13 values. 
If I manage to make parallel resistor to cover required range the update is just firmware change and resistors change on PCB. To make both legs with 12 bits I need to cut one trace and make one bridge. Using serial resistors, relays optocouplers it's near impossible to use existing PCB.
So is it possible to get required range from 12 bits?

--- End quote ---

Those relays are not bulky. They're tiny compared to the size of resistors required to dissipated the required power.

You should have stated the speed in first place. It's possible to get faster isolated gate drivers, but it's going to be very difficult to make something that fast, because the resistors form a RC time constants with the parasitic capacitances of the MOSFETs.

Nominal Animal:

--- Quote from: eslavko on October 09, 2022, 06:05:39 am ---So is it possible to get required range from 12 bits?
--- End quote ---
The math says, when using selectable resistors in parallel, "all resistances in the upper half of your resistance range must be provided by individual resistors".

If the maximum resistance is 3000 Ohms, and you use 12 resistors linearly/evenly distributed between 1500 and 3000, your resolution at the upper end is 1500/(12-1) ≃ 136 Ohms.  The minimum resistance is then 179 Ohms, with 190 to 642 Ohms covered with better than 1 Ohm resolution.

If the maximum resistance is 4500 Ohms, and you use 10 resistors linearly/evenly distributed between 2250 and 4500, your resolution at the upper end is 2250/(10-1) = 250 Ohms.  The minimum resistance is then 322 Ohms, with the dense coverage from 346 Ohms to 1000 Ohms or so.

To cover the bottom end of your range, you'd need additional resistors, which just increases the step size at the upper half of the range.

In real life, we do not usually need a linear distribution of resistors, but an 1/N distribution (because for example I=U/R).  To see what kind of set of parallel resistances you can make, I suggest you start with the highest resistance you need, then the next highest, and so on.  The following simple Python program will tell you all the possible parallel combinations, in sorted order:

--- Code: ---#!/usr/bin/python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: CC0-1.0

if __name__ == '__main__':
    from sys import stdout, stderr, argv

    if len(argv) < 3:
        stderr.write('\n')
        stderr.write('Usage: %s [ -h | --help ]\n' % argv[0])
        stderr.write('       %s RESISTANCES...\n' % argv[0])
        stderr.write('\n')
        exit(0)

    R = [ float(argv[k]) for k in range(1, len(argv)) ]
    N = len(R)

    R.sort()
    value = []
    for k in range(1, 2**N):
        invsum = 0.0
        for n in range(0, N):
            if (k & (2**n)) > 0:
                invsum += 1.0 / R[n]
        value.append(1.0/invsum)
    value.sort()

    stdout.write('Resistors:')
    for n in range(0, N):
        stdout.write(' %.6f' % R[n])

    stdout.write('\nPossible parallel resistances:\n')

    for k in range(0, 2**N - 1):
        stdout.write("%.9f\n" % value[k])

--- End code ---
Running
    python3 parallel.py 4500 4200 3950 3750 3600
tells you that they can be combined to the following parallel combinations:

--- Code: ---794.959030140
965.526606786
980.554406289
995.260663507
1008.817269687
1020.253372145
1253.747134544
1277.890466531
1300.326583932
1304.347826087
1319.389215842
1327.731092437
1347.611827142
1354.838709677
1375.545851528
1401.577020558
1836.734693878
1883.443708609
1923.701298701
1938.461538462
1981.132075472
2000.000000000
2035.582822086
2045.454545455
2103.550295858
2172.413793103
3600.000000000
3750.000000000
3950.000000000
4200.000000000
4500.000000000

--- End code ---
Notice the huge gap between 2172 and 3600?  That is because as the math says, "all resistances in the upper half of your resistance range must be provided by individual resistors".  Since I didn't have any between 2250 and 3600, there's a huge gap in there.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod