Binary coded kind of log resistance

GroupDIY Audio Forum

Help Support GroupDIY Audio Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

ruffrecords

Well-known member
Joined
Nov 10, 2006
Messages
16,239
Location
Norfolk - UK
I am looking at binary relay control of the gain of one of my tube pre-amps. The gain needs to be varied from 10dB to 40dB in 5dB steps. The required gain setting resistance for each gain is as follows:

10dB    37K
15dB    12K3
20dB    5K6
25dB    2K85
30dB    1K5
35dB    820
40dB    430

A trivial way to achieve  this is to use a 3 to 8 decoder and connects its outputs to 7 relays each one of which connects in one of the above values.

But I am sure it can be done with fewer by operating  one or more relays and hence paralleling the resistors. In theory the minimum is 3 but I cannot find a set of 3 resistors which will achieve the above values. P.art of the reason is I need to achieve a 37K/430 to 1 span (that is 86 times) but the span of 3 bit is only 8 times. 5 bits would get me 64 times which could be close enough but I would like to do better. Another reason is there is already a resistor in parallel with these (a 47K) that cannot be removed as it is part of the dc feedback. This has much less of an effect at the higher gains but at the lower ones it means the values required are a lot higher.

For this reason it looks like it might be possible to achieve the range  25db to 40dB with two bits with reasonable accuracy and then maybe switch in some series resistors for the last three using another 2 bits.

I am sure this problem must have been addressed in the past but Google has not been much help. Any leads?

Cheers

Ian
 
An R/2R DAC naturally gives 6dB steps, no? (i.e. don't switch just the one resistor, design the whole voltage divider.)
 
Hello

This is not a voltage divider ? but a gain network ? you can't solve it with a R/2R network

This is nor a binary log (due to 47K paralleled ?)

My best bet for now is 6...
Series resistor with lower value fixed or parallel resistor with higher value fixed  :-\

Best
Zam
 
Binary will give you perfect linear steps. But there's no way to make log steps that i know of. You'll just have to add more relays and accept some error. Create a spreadsheet and fiddle. Maybe there's some clever arrangement that will save you 1 relay. But my guess is it will take more like 5 which means you're only saving 2 which probably isn't worth the error. If you're using a relay driver IC (like L9823), it's probably for 8 anyway.

Note that if you give up and decide to just use 7, you could alternatively make a 7 bit binary stepper and try to get higher resolution like 15  2 dB steps maybe depending on how much error you accept. Are you using a micro for this?

I did a binary relay gain stepper once (although the circuit was completely different from what you're doing). I used a conventional potentiometer to read the gain position, selected a bit code from a table and wrote it to the relay driver chip. I did 40 steps. I had to debounce of course. In fact, I came up with a really nice solution for debouncing a pot into steps. See code below. The trick was to simply move the threshold for the next step backward by a small amount (hyst) after changing the step. Sort of like moving the goal post you might say. Meaning as you turn the knob and it reaches the threshold for the next step, it switches steps but then changes the threashold for the previous step backward by a small amount so that to go back to the previous step you would have to actually move the knob back a few degrees. And also of course there's the usual deboucing time delay so that if you move the pot quickly it doesn't torture the relays. Works great.

Code:
--8<-- steppot.h --8<--
#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
 
struct steppot {
    uint16_t width; // should be roughly 1024 / num steps
    uint16_t hyst;  // should be roughly width * 0.1 or so
    uint16_t rval;
    uint16_t step;
    uint16_t thresh_hi;
    uint16_t thresh_lo;
    uint32_t time_last_change;
};

int steppot_init(struct steppot *sp, uint16_t width, uint16_t hyst);
int steppot_add_sample(struct steppot *sp, uint32_t aval);
    
#ifdef __cplusplus
}
#endif
--8<-- steppot.cpp --8<--
#include "Arduino.h"

#include "steppot.h"

/* do all integer math with multiplier
 * to compensate for loss of precision
 */
#define STEPPOT_MULT 10
#define THRESH_PERIOD 100

extern uint32_t ctime;

uint32_t time_last_thresh = 0;

int
steppot_init(struct steppot *sp, uint16_t width, uint16_t hyst)
{
    memset(sp, 0, sizeof(*sp));
    sp->width = width * STEPPOT_MULT;
    sp->hyst = hyst * STEPPOT_MULT;

    return 0;
}

int
steppot_add_sample(struct steppot *sp, uint32_t aval)
{
    uint16_t val = (aval & 0xffff) * STEPPOT_MULT;

    sp->rval = (sp->rval + val) / 2;

    if (ctime > time_last_thresh + THRESH_PERIOD) {
        time_last_thresh = ctime;

        if (sp->rval > sp->thresh_hi || sp->rval < sp->thresh_lo) {
            sp->time_last_change = ctime;
            sp->step = sp->rval / sp->width;
            val = sp->step * sp->width;
            sp->thresh_hi = val + sp->width + sp->hyst;
            sp->thresh_lo = val < sp->hyst ? 0 : val - sp->hyst;
        }       
    }

    return 0;
}

Although one issue with this is that there's no feedback from the pot. If you're only doing 12 steps or less, I suppose a switch would be better than a pot. I ended up temporarily highjacking the VU meter LEDs to display the steps as a sort of code. As you turn the knob you can hear the relays clicking and see LEDs momentarily showing a change.
 
ruffrecords said:
I am sure this problem must have been addressed in the past but Google has not been much help. Any leads?
Think of the math involved; a system of 8 equations with 8 unknowns. It has no solutions.
The way it is addressed generally is by cascading stages, each having increasing amplitude range, not necessarily powers of 2. Oscilloscopes and voltmeters use a scale of 1-2-5.
 
ruffrecords said:
My initial thought was a to use a hex coded switch.
Nice thought but no. Hex encoders aren't that common. Maybe you mean BCD but I've never seen a 3 bit one. Otherwise you'll have to use 4 bit and only use a quarter of travel?

I think you should just use 7 relays tied to a switch that has 7 positions and not try to get too cute. Anything more than 8 requires a micro controller.

Although another possibility would be to use a series of compariators (like in LED VU meters) to short relays in series with 2N7000 not unlike like the other thread about running LEDs in series.
 
Oh, just tuck a PGA under the bottle. You *know* it is a better mike interface, and you can talk digital to it, and the dB are all worked out for you, with precision.
 

Attachments

  • PGA2505-12AX7-42.gif
    PGA2505-12AX7-42.gif
    49.3 KB · Views: 22
there are digitally controlled mic preamps, perhaps look at a data sheet app note, but expect more than 3 bit control.

JR

PS: I vaguely recall a discrete digitally controlled preamp design on this forum years ago.  As I recall it was pretty complex, again more than 3 control bits.
 
ruffrecords said:
I am looking at binary relay control of the gain of one of my tube pre-amps. The gain needs to be varied from 10dB to 40dB in 5dB steps. The required gain setting resistance for each gain is as follows:
10dB    37K
15dB    12K3
20dB    5K6
25dB    2K85
30dB    1K5
35dB    820
40dB    430
IMO, it can be done if 3 pcs of dpdt relays are used.
 
abbey road d enfer said:
Think of the math involved; a system of 8 equations with 8 unknowns. It has no solutions.

It has one solution. IIRC, number of equations should be higher or equal to number of variables.
 
squarewave said:
Nice thought but no. Hex encoders aren't that common. Maybe you mean BCD but I've never seen a 3 bit one. Otherwise you'll have to use 4 bit and only use a quarter of travel?
I found plenty of hex coded rotaries. ELMA does one for example. I did mean hex because the overall plan is to include the line input but I did not want to unnecessarily complicate the basic question.. So you go from -60 to -30 mic input - then perhaps an off position - then -20 to +10 line all on the same 16 way switch.

Cheers

Ian
 
squarewave said:
I would be sincerely impressed if you could get within 20% of those target resistances.

Here you go.
BTW, I don't like this approach at all. Also, it should be analyzed which switch to use (MBB or BBM ).
 

Attachments

  • att 3 relays.png
    att 3 relays.png
    13.5 KB · Views: 84
moamps said:
Here you go.
BTW, I don't like this approach at all. Also, it should be analyzed which switch to use (MBB or BBM ).
Holy s**t! You nailed it. You must play a lot of Sudoku.

The second one is actually 12.6K but you could split the difference with the 5.6K and still be under 2% with the exception of the highest position (which is pretty convoluted network but is indeed 447 ohms) which is off by only 4%. But you could sacrifice a little bit of the 2.85K and probably get the whole thing below 3% or so. Then just trim the parallel 47K to hit the 40dB exactly.

I don't see why this shouldn't be used at all. It works. MBB or BBM doesn't matter. There's a 47K in parallel with the whole thing so there will never be an open circuit. The resting position (000) is 44K which is fabulous. What's not to like?

I would say more but I have a foot in my mouth.
 
Hey Moamps, what a GREAT solution. Absolutely perfect. I am not too concerned about accuracy of fractions of a dB - repeatability is more important. No need to worry about the network becoming momentarily open circuit - there is no dc flowing in it because it is connected via a 100uF cap. There is also a 1Meg bleed resistor across the network to ensure the cap is always charged. Now I just need to add the mic/line relay switching.

Cheers

Ian
 

Latest posts

Back
Top