Friday, July 30, 2010

Making an Optimal Log Pot

Introduction

After taking a look at the famed "The Secrete Life of Pots" again, I realized that it might be useful for me to make my own blend pot.  I have discovered that the blend pot I have unfortunately does not cross the streams the way it should.  At the center detent, both pots are at full volume.  Deviating in either direction lowers the volume of one of the pots.  So this means that I will be much louder in the middle than at either of the extremes, which is undesirable.

The author mentions that it is possible to get arbitrarily close to a logarithmic pot, so I decided to bust out Matlab and see if that was true.

Method

First I verified that the calculations were indeed correct.  Actually I found a small typo in them.  He uses two different definitions of the b variable that are reciprocals of each other.  On the graph, the numbers say "b=0,1,2,3,4,5,6" when, going by the previous calculations, "b=1/0, 1/1, 1/2, 1/3, 1/4, 1/6" to produce the graph shown.  The actual equations were correct, both the resistor-based and the ratio-based.

Secondly, what should a log pot actually look like?  Incidentally, the plot is actually an exponential 10^x graph.  The plot will look like a line on a semi-log plot.  But which part of this plot should we choose?  Each section looks different, and wider range will have a different curve than a smaller one.  After reading the Wikipedia article on sound pressure, I decided to pick the range from 0-60db (10^(0...60/20) as my target range.  This represents the range from silent to coming close to hearing damage.  And that's what we want right? :)

After that, I used the "fminunc" (for function minimize unconstrained) function in Matlab to minimize the difference between the chosen log plot and the attempt to copy it.  The independent variable was b.

Results

It is not quite true that you can get arbitrarily close to the log pot, at least not with this choice for the log pot curve.  I used two methods for the error calculation: least sum of absolute value and least sum of squares.  Here are the results.



Running the minimization on both methods produced values of
b = 0.0574 for the least sum of absolute value of errors
b = 0.0709 for the least sum of squared errors

So the resistor at the wiper should be 5.74% or 7.09% of the total resistance of the pot, depending on which method of optimisation you choose.  

Here are the plots for those values.


Conclusion

As you can see, the plots are fairly close, but by no means perfect.  To the ear, you probably couldn't tell very much difference. 

As mentioned in TSLoP, using this method severely drops the resistance of the load to the pickup.  Also it changes the resistance depending on wiper position.  So you probably would want to put an opamp buffer or something in between the pickup and the fake log pot.

The drop in resistance is by a factor of 0.0543 for the ABS result and 0.0662 for the LSQ result in the worst position (1/(1+1/b) from TSLoP).  The worst position is full volume, since there will be no top resistor in series with the parallel pair. So we're talking about turning a 500K pot into 27K or 33K at the worst wiper position.  Still easily drive from an opamp, but pretty nasty for a pickup.

I'm considering adding a couple of opamps to the circuit so that I can take a dual-ganged linear pot and turn it into a dual log pot where one is the opposite of the other.  That's hard to explain.  Just look at the graph.



That way the volume should remain pretty constant as you sweep from one side to the other.



Now if only I could find one with a center detent...

Code used for calculating follows...

function G = logpot(b) % logpot accepts one row matrix "b" that contains % all values of "b" for which a dataset should be generated % It returns the "ideal log gain" followed by the generated % datasets for the b values provided. % setup pot position values a = repmat(linspace(0,1,50)', size(b), 1); % replicate b to match a's height b = repmat(b, 50, 1); % do the math G = 1./ ((ones(size(a))-a)./a + (ones(size(a))-a)./b + ones(size(b))); % create our "ideal log gain" (0-60dB) glog = logspace(0,60/20,50); glog = glog ./ max(glog); % concatenate "ideal log gain" with the generated datasets G = [ glog' G ]; ---------------------------------------- The command to do the optimisation is fminunc(@myfun, 1/6) This is the function used in the optimisation to calculate total error. function f = myfun(b) % function is % 1 %--------------------- % _1-a_ + _1-a_ + 1 % b a % precalculated to make things faster. % a = linspace(0,1,50); % a1 = 1-a % a2 = (1-a)/a a1 =[ 1.0000 0.9796 0.9592 0.9388 0.9184 0.8980 0.8776 0.8571 0.8367 0.8163 0.7959 0.7755 0.7551 0.7347 0.7143 0.6939 0.6735 0.6531 0.6327 0.6122 0.5918 0.5714 0.5510 0.5306 0.5102 0.4898 0.4694 0.4490 0.4286 0.4082 0.3878 0.3673 0.3469 0.3265 0.3061 0.2857 0.2653 0.2449 0.2245 0.2041 0.1837 0.1633 0.1429 0.1224 0.1020 0.0816 0.0612 0.0408 0.0204 0 ]; a2 =[ Inf 49.0004 24.5004 16.3337 12.2504 9.8004 8.1671 6.9997 6.1248 5.4443 4.8999 4.4545 4.0833 3.7693 3.5001 3.2667 3.0626 2.8825 2.7224 2.5788 2.4499 2.3333 2.2272 2.1304 2.0417 1.9600 1.8846 1.8149 1.7500 1.6897 1.6334 1.5806 1.5312 1.4848 1.4411 1.4000 1.3611 1.3243 1.2895 1.2564 1.2250 1.1952 1.1667 1.1395 1.1136 1.0889 1.0652 1.0425 1.0208 1.0000 ]; % glog is a 0-60 db curve normalized to 0-1 % glog = logspace(0,60/20,50); glog = glog ./ max(glog) glog =[ 0.0010 0.0012 0.0013 0.0015 0.0018 0.0020 0.0023 0.0027 0.0031 0.0036 0.0041 0.0047 0.0054 0.0063 0.0072 0.0083 0.0095 0.0110 0.0126 0.0146 0.0168 0.0193 0.0222 0.0256 0.0295 0.0339 0.0391 0.0450 0.0518 0.0596 0.0687 0.0791 0.0910 0.1048 0.1207 0.1389 0.1600 0.1842 0.2121 0.2442 0.2812 0.3237 0.3728 0.4292 0.4942 0.5690 0.6551 0.7543 0.8685 1.0000 ]; %f = 1./ ( a1./b + a2 ); f1 = 1./ ( a1./b + a2 ) - glog; f = sum(abs(f1)); %f = sum(f1.^2); ---------------------------------------- This is the code I used to generate the main results graph plot(100*linspace(0,1,50)', 100*logpot([0.0574 0.0709])); xlabel('Wiper Position (%)'); ylabel('Gain (%)'); legend('Real Log 0-60 dB', 'Simulated b=0.0574 (Least ABS)', 'Simulated b=0.0709 (Least Squares)', 'Location', 'NorthWest'); title('Simulated Log Pots');


Thanks for reading,
Bill

No comments:

Post a Comment