Electronics > Beginners

Digital adjustable resistor

**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

Go to full version