Code for logarithmic volume control

Hi,

Does anyone have a snippet of the code that can do logarithmic change? I'm building Arudino based volume controller that will do so via Digital Pot IC.

Thanks! :slight_smile:

Don't logarithmic pots exist? Otherwise many of the steps are just wasted.

CrossRoads:
Don't logarithmic pots exist? Otherwise many of the steps are just wasted.

I couldn't find any digital logarithmic pots (do they exist?) besides I already ordered some MCP4241 (10K, 50K and 100K)...

try this

void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");
  
  float scale = 127/2.77;    
  
  for (int i=0; i< 255; i++)
  {
    float y = scale * log(i);
    Serial.print(i);
    Serial.print('\t');
    Serial.println(y);
  }
}

void loop() 
{
}

output

0	inf
1	0.00
2	31.78
3	50.37
4	63.56
5	73.79
6	82.15
7	89.22
8	95.34
9	100.74
10	105.57
...
245	252.22
246	252.41
247	252.60
248	252.78
249	252.97
250	253.15
251	253.33
252	253.52
253	253.70
254	253.88

or

for (int i=0; i< 255; i++)
  {
    float y = 255- a * log(255-i);  // more dynamic in the end
    Serial.print(i);
    Serial.print('\t');
    Serial.println(y);
  }

Stereo too.

DS1801 is digital.

robtillaart:
or

for (int i=0; i< 255; i++)

{
   float y = 255- a * log(255-i);  // more dynamic in the end
   Serial.print(i);
   Serial.print('\t');
   Serial.println(y);
 }

Awesome! Thank you very much!!! :smiley:

CrossRoads:
http://www.digikey.com/product-search/en?vendor=0&keywords=audio+taper+digital+potentiometer

Stereo too.

DS1801 is digital.

Oops... Pulled trigger too soon on linear, didn't see that one :frowning: Oh well, thanks the info tho! I'll get that one for my next project

CrossRoads:
http://www.digikey.com/product-search/en?vendor=0&keywords=audio+taper+digital+potentiometer

Stereo too.

DS1801 is digital.

BTW Is 45K a good value for line audio control? I wasn't sure which resistance is best for this (10K,50K or 100K)?

Are you feeding the audio thru the pot to divide it down?
Then 1.5V/45000 = 33uA, not much load on the source.

Are you instead using it to divide down 5V as reference for something else? Might go for lower value to get a little more current flow and perhaps be less susceptible to noise.

CrossRoads:
Are you feeding the audio thru the pot to divide it down?
Then 1.5V/45000 = 33uA, not much load on the source.

Are you instead using it to divide down 5V as reference for something else? Might go for lower value to get a little more current flow and perhaps be less susceptible to noise.

I'm trying to control volume of audio signal coming from computer monitor and into powered speaker. Basically I have TiVo that sends AV signal via HDMI into 30" monitor. Monitor separates audio from the signal and outputs it via line-out (3.5mm cable). Since neither monitor or speaker have remote control I want to build one with Arudino.

So you're using the pot as a voltage divider then.
I'd go with 10K on that.

CrossRoads:
So you're using the pot as a voltage divider then.
I'd go with 10K on that.

Sounds good! Thank you!

robtillaart:
or

for (int i=0; i< 255; i++)

{
    float y = 255- a * log(255-i);  // more dynamic in the end
    Serial.print(i);
    Serial.print('\t');
    Serial.println(y);
  }

I finally got digital pot (10K, 128 steps) and I have one more question. How do I avoid "inf" and "nan" values? Here's my code adapted to 7 bit Digital Pot...

void volUp(){
  float scale=64/2.77;
 for (int i=0;i<128;i++ ) {
  float y=127- scale*log(127-i);  // more dynamic in the end
  Serial.print (i);
  Serial.print ('\t');
  Serial.println (y);
  writeMCP4241(0,y);
  delay (100);
 }
}
0	15.08
1	15.26
2	15.44
3	15.63
4	15.82
5	16.00
6	16.19
7	16.39
8	16.58
9	16.77
10	16.97
11	17.17
12	17.37
13	17.57
14	17.78
15	17.98
16	18.19
17	18.40
18	18.61
19	18.82
20	19.04
21	19.25
22	19.47
23	19.69
24	19.92
25	20.14
26	20.37
27	20.60
28	20.83
29	21.07
30	21.30
31	21.54
32	21.78
33	22.03
34	22.28
35	22.53
36	22.78
37	23.03
38	23.29
39	23.55
40	23.82
41	24.08
42	24.35
43	24.63
44	24.90
45	25.18
46	25.47
47	25.75
48	26.05
49	26.34
50	26.64
51	26.94
52	27.25
53	27.56
54	27.87
55	28.19
56	28.51
57	28.84
58	29.17
59	29.51
60	29.85
61	30.20
62	30.55
63	30.91
64	31.27
65	31.64
66	32.02
67	32.40
68	32.79
69	33.18
70	33.59
71	34.00
72	34.41
73	34.84
74	35.27
75	35.71
76	36.16
77	36.61
78	37.08
79	37.56
80	38.04
81	38.54
82	39.05
83	39.57
84	40.10
85	40.64
86	41.20
87	41.77
88	42.35
89	42.95
90	43.57
91	44.20
92	44.85
93	45.52
94	46.21
95	46.93
96	47.66
97	48.42
98	49.20
99	50.01
100	50.85
101	51.72
102	52.63
103	53.57
104	54.56
105	55.58
106	56.66
107	57.78
108	58.97
109	60.22
110	61.54
111	62.94
112	64.43
113	66.03
114	67.74
115	69.59
116	71.60
117	73.80
118	76.23
119	78.96
120	82.04
121	85.60
122	89.81
123	94.97
124	101.62
125	110.99
126	127.00
127	inf
128	nan

Also not sure how do I get 0 value in the beginning? :slight_smile:

  1. Subtract 15 from everything.
  2. Stop before 128. 0x7F, 0b01111111. 7 bits is 0 to 127.

CrossRoads:

  1. Subtract 15 from everything.
  2. Stop before 128. 0x7F, 0b01111111. 7 bits is 0 to 127.

Thanks! I'll give it a try. Btw looks like there's built in function to check for inf and Nan: isinf() is isnan().

logarithm function is only defined for positive numbers. You are trying to calculate the logarithm of zero and negative numbers. Don't do it.

If you don't try the bogus calculation in the first place, then you don't need to check for it afterwards.

If you want to calculate log(127-i), then you cannot use i=127. You need to stop your loop at 126.

Thank you for your help! It works great for increasing volume! How would I modify formula to logarithmically decrease it? :slight_smile:

From what I gather, a "logarithmic" volume control is not really logarithmic but exponential.

You could use a pow() or exp() function, but if I were you, I would just make my own such function.

bratan:
Thank you for your help! It works great for increasing volume! How would I modify formula to logarithmically decrease it? :slight_smile:

With the examples given you should be able to figure out. That will also help you to understand it in its essence.
Do not try to code directly but first try to understand current code by making a graph on paper.

Then make a graph of the desired function on paper and derive the formula,