Featured image of post 電子ボリュームICをAカーブ減衰特性で制御する

電子ボリュームICをAカーブ減衰特性で制御する

ボリューム(POT)をリモコン電子ボリュームに置き換えるためにその特性を電子ボリュームICで再現する。

ボリューム(POT)の減衰曲線

目標とするボリュームの減衰曲線は ALPS RK27 ボリュームの
A(15A)曲線(ボリューム50%位置で出力は入力の15%, 指数変化)を参考にします。

見た感じ3つの直線でできているので, ボリュームの減衰曲線も3つの直線で作ることにした。 TAPER

電子ボリュームIC LM1972の減衰特性

設定値 0~127, 128(mute)をLM1972に設定した時の減衰量グラフがFIGURE 3
途中から減衰ステップが0.5dB刻みから1.0dBへと変化する特性になっています。

2つの直線を組み合わせた関数で単純な1次関数ではないので,
目的の減衰特性を得るテーブルを用意するスクリプトを作る。 LM1972-006

Aカーブ減衰特性

GNU Octaveで電子ボリュームの設定値0から31とLM1972の設定値をAカーブで設定するテーブルを作るGNU Octave用減衰テーブル計算スクリプト を作った。
(注: 実際の15A曲線は使いにくかったので,これは15A曲線ではありません)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
%
% 電子ボリュームの減衰値を計算する
% http://ak1211.com
% Copyright (c) 2015 Akihiro Yamamoto
%
%
% This software is released under the MIT License.
% http://opensource.org/licenses/mit-license.php
%

%
% 減衰率-設定値表を作る
%

% LM1972の設定値 - 減衰量
global lm1972_table = [ 0.0 -0.5 -1.0 -1.5 -2.0 -2.5 -3.0 -3.5 -4.0 -4.5 -5.0 -5.5 -6.0 -6.5 -7.0 -7.5 -8.0 -8.5 -9.0 -9.5 -10.0 -10.5 -11.0 -11.5 -12.0 -12.5 -13.0 -13.5 -14.0 -14.5 -15.0 -15.5 -16.0 -16.5 -17.0 -17.5 -18.0 -18.5 -19.0 -19.5 -20.0 -20.5 -21.0 -21.5 -22.0 -22.5 -23.0 -23.5 -24.0 -24.5 -25.0 -25.5 -26.0 -26.5 -27.0 -27.5 -28.0 -28.5 -29.0 -29.5 -30.0 -30.5 -31.0 -31.5 -32.0 -32.5 -33.0 -33.5 -34.0 -34.5 -35.0 -35.5 -36.0 -36.5 -37.0 -37.5 -38.0 -38.5 -39.0 -39.5 -40.0 -40.5 -41.0 -41.5 -42.0 -42.5 -43.0 -43.5 -44.0 -44.5 -45.0 -45.5 -46.0 -46.5 -47.0 -47.5 -48.0 -49.0 -50.0 -51.0 -52.0 -53.0 -54.0 -55.0 -56.0 -57.0 -58.0 -59.0 -60.0 -61.0 -62.0 -63.0 -64.0 -65.0 -66.0 -67.0 -68.0 -69.0 -70.0 -71.0 -72.0 -73.0 -74.0 -75.0 -76.0 -77.0 -78.0 ];

%
% LM1972の設定値に対応したdBを返す
% 0 <= param <= 126
%
function retval = LM1972_decibel_of_set_values (param)
    global lm1972_table;
    retval = lm1972_table (param+1);
endfunction

%
% dBに対応したLM1972の設定値を返す
%
function retval = LM1972_set_values_of_decibel (dB)
    global lm1972_table;
    dB05 = 0.5*floor(dB/0.5);
    dB10 = floor(dB);
    if any (lm1972_table == dB05)
        retval = find (lm1972_table == dB05) - 1;
    elseif any (lm1972_table == dB10)
        retval = find (lm1972_table == dB10) - 1;
    else
        error ("out of bounds");
    end
endfunction

%
% PGA2311の設定値
%

%
% PGA2311の設定値に対応したdBを返す
% 1 <= N <= 255
%
function retval = PGA2311_decibel_of_set_values (N)
    retval = 31.5 - (0.5 * (255-N));
endfunction

%
% dBに対応したLM1972の設定値を返す
%
function retval = PGA2311_set_values_of_decibel (dB)
    if (-95.5 <= dB && dB <= 31.5)
        retval = floor(255 - (31.5-dB)/0.5);
    else
        error ("out of bounds");
    end
endfunction

%
% 作成する電子ボリュームマップベクタ
%
function retval = make_electric_volume_vect (rotation_travel, ideal_a_curve)
    % 電子ボリュームは3つの角度の関数で構成

    %
    % 1つめの関数
    %
    a = ideal_a_curve(1) / 0.5;
    p = 0;
    q = 0;
    f1 = a*(rotation_travel-p)+q;

    %
    % 2つめの関数
    %
    a = 1/2;    % 1 : 2
    p = 0.65;   % 65%
    q = 0.10;   % 10%
    f2 = a*(rotation_travel-p)+q;

    %
    % 3つめの関数
    %
    a = (1.0 - ideal_a_curve(30)) / (1.0 - 30/32);
    p = 1.0-(1/a);
    q = 0;
    f3 = a*(rotation_travel-p)+q;

    % 電子ボリュームカーブ
    evol_curve = max(f1, max(f2, f3));

    retval = evol_curve;
endfunction

%
%
%
format short g;
clf;

% ボリュームの段階数
volume_steps = 0:31;

% ボリューム段階[steps] - 回転位置[%]
rotation_travel = linspace (0.0, 1.0, length(volume_steps));

%
% 理想Aカーブボリューム
% y = exp(a*x) / exp(a)
% y = exp(a*x-a)
% y = exp(a(x-1))
%
% exp(a(x-1)) = y
% a(x-1) = log(y)
% a = log(y) / (x-1)
%
% 回転位置 50% は 出力電圧 15%
%
times_of_A = log(0.15) / (0.5-1);

% 理想Aカーブボリューム
ideal_a_curve = exp(times_of_A*(rotation_travel-1));

% 理想Aカーブボリュームのプロット
subplot (2,1,1);
hold on;
%plot (rotation_travel, ideal_a_curve, 'cm-@*')
plot (volume_steps, ideal_a_curve, 'cm-@*')

evol_curve = make_electric_volume_vect (rotation_travel, ideal_a_curve);

% 電子ボリュームカーブのプロット
%plot (rotation_travel, evol_curve, 'cb-@o')
plot (volume_steps, evol_curve, 'cb-@o')

% 目盛とか
axis ([ [min(volume_steps) max(volume_steps)], [0.0 1.0] ]);
grid minor;
xlabel ('volume steps');
ylabel ('Vout/Vin');
legend ('ideal A curved volume', 'electric volume curve', "location", 'north');
hold off;

% Aカーブボリュームのプロット
subplot (2,1,2);
hold on;
plot (volume_steps, 20*log10(ideal_a_curve), 'cm-@*')

%
% LM1972電子ボリュームのデシベル
%
evol_curve(1) = 10^(-78.0 / 20);  % ボリューム0は取りあえず -78dB
attenuetor_dB = 20 * log10 (evol_curve);
%
% LM1972の設定値
lm1972_param = arrayfun (@LM1972_set_values_of_decibel, attenuetor_dB);
% LM1972の減衰量
lm1972_att = arrayfun (@LM1972_decibel_of_set_values, lm1972_param);
%
printf ("// LM1972_attenuetor_dB\n")
printf ("%3.1f, ", lm1972_att)
printf("\n")
%

% LM1972電子ボリュームのプロット
plot (volume_steps, lm1972_att, "cb-@o;simulate LM1972 volume at decibel;")

%
% PGA2311電子ボリュームのデシベル
%
evol_curve(1) = 10^(-95.5 / 20);  % ボリューム0は取りあえず -95.5dB
attenuetor_dB = 20 * log10 (evol_curve);
%
% PGA2311の設定値
PGA2311_param = arrayfun (@PGA2311_set_values_of_decibel, attenuetor_dB);
% PGA2311の減衰量
PGA2311_att = arrayfun (@PGA2311_decibel_of_set_values, PGA2311_param);
%
printf ("// PGA2311_attenuetor_dB\n")
printf ("%3.1f, ", PGA2311_att)
printf("\n")
%


% PGA2311電子ボリュームのプロット
plot (volume_steps, PGA2311_att, "cg-@o;simulate PGA2311 volume at decibel;")

%
% 目盛とか
%
axis ([ [min(volume_steps) max(volume_steps)], [min(PGA2311_att) max(PGA2311_att)] ]);
grid minor;
xlabel ('volume steps');
ylabel ('attenuation [dB]');
legend ( 'ideal A curved volume','LM1972 volume steps of decibel', 'PGA2311 volume steps of decibel', "location", 'southeast');
hold off;

%
% 計算結果を出力
%

printf ("// lm1972_param\n")
printf ("%3d, ", lm1972_param)
printf("\n")
%
printf ("// PGA2311_param\n")
printf ("%3d, ", PGA2311_param)
printf("\n")

%print -Ggswin32c.exe foo.png

GNU Octave用減衰テーブル計算スクリプトで作ったテーブル

img

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// LM1972_attenuetor_dB
-78.0, -57.0, -51.0, -47.5, -45.0, -43.0, -41.5, -40.0, -39.0, -38.0, -37.0, -36.0, -35.5, -34.5, -34.0, -33.5, -30.0, -26.5, -24.0, -22.0, -20.5, -19.0, -18.0, -17.0, -13.5, -10.0, -7.5, -5.5, -4.0, -2.5, -1.5, 0.0,

// PGA2311_attenuetor_dB
-95.5, -57.0, -51.0, -47.5, -45.0, -43.0, -41.5, -40.0, -39.0, -38.0, -37.0, -36.0, -35.5, -34.5, -34.0, -33.5, -30.0, -26.5, -24.0, -22.0, -20.5, -19.0, -18.0, -17.0, -13.5, -10.0, -7.5, -5.5, -4.0, -2.5, -1.5, 0.0,

// lm1972_param
126, 105,  99,  95,  90,  86,  83,  80,  78,  76,  74,  72,  71,  69,  68,  67,  60,  53,  48,  44,  41,  38,  36,  34,  27,  20,  15,  11,   8,   5,   3,   0,

// PGA2311_param
  1,  78,  90,  97, 102, 106, 109, 112, 114, 116, 118, 120, 121, 123, 124, 125, 132, 139, 144, 148, 151, 154, 156, 158, 165, 172, 177, 181, 184, 187, 189, 192,

減衰曲線のグラフとAカーブ32段階電子ボリュームの減衰曲線のテーブルが得られた。
このあとでボリューム0は127=muteに書き換えます。 検討中の名残でLM1972とPGA2311の減衰設定値も出てますが
それぞれのグラフは重なっています。

チャンネルをLM1972に設定する

LM1972の2つの減衰器にはそれぞれに独立した値を設定できるのですが, 今回の目的はステレオ電子ボリュームなので両チャンネル(L/R)には同じ値を設定することにします。

LM1972-007

LM1972のDATA-INに Address Register(Byte 0)のbit7からbit0, 次に 設定値のbit7からbit0 を送り出します。

減衰値をLM1972に設定する

LM1972-002.png

  1. LOAD/SHIFTピンをLに
  2. DATA-INに最上位ビット(bit7)から設定値を送り出す
  3. CLOCKピンをHに
  4. 150ns以上待って
  5. CLOCKピンをLに
  6. 設定値を送り出す, CLOCKピンをH/Lにする作業を
    すべてのデーターを送り出すまで繰り返す
  7. LOAD/SHIFTピンをHに

これを行なう関数がこの部分

ステレオAカーブ電子ボリューム設定関数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//
//電子ボリュームをsetvolにする
//
elevol_t elevol_setvolume( elevol_t setvol )
{
    static const uint8_t tVolume[32] PROGMEM = {
        // lm1972_param
        127, 105,  99,  95,  90,  86,  83,  80,  78,  76,  74,  72,  71,  69,  68,  67,  60,  53,  48,  44,  41,  38,  36,  34,  27,  20,  15,  11,   8,   5,   3,   0,
    };
    elevol_t idx = elevol_validate_volume(setvol);
    uint8_t v = pgm_read_byte(&tVolume[idx]);
    //
    //IN1 : left
    //channel selection : 0
    //
    LM1972_write( 0, v );
    //
    //IN2 : right
    //channel selection : 1
    //
    LM1972_write( 1, v );

    return idx;
}

電子ボリュームコントローラソフトウェア

2チャンネル電子ボリュームIC(LM1972)を32段階ステレオ電子ボリュームとして使うプログラムです。


One thought on “電子ボリュームICをAカーブ減衰特性で制御する”

  • camiseta del valencia より:
  • 2017年4月20日 3:07 PM

    I am so grateful for your article.

    comments powered by Disqus

    This website uses cookies to improve your experience.
    このサイトは「Googleアナリティクス」を使用しています。
    Googleアナリティクスはデータの収集のためにCookieを使用しています。


    Built with Hugo
    テーマ StackJimmy によって設計されています。