写了个算分压电阻阻值的MATLAB小程序

2019-07-14 03:09发布

最近常遇到板子上电源部分需要几个电阻分压器的情况,写了个小程序来实现在指定电阻阻值系列内(E6~E192),选择尽量少的电阻种类实现需要的分压比例。
测试于MATLAB 2012a/2014b和Octave。 程序第一部分定义了需要计算的分压比例、对应的允许误差、系统中已经存在的固定电阻、阻值系列、最大迭代次数。
之后生成电阻系列的所有阻值。E48~E192系列的阻值基本是按照对数排列的,用logspace生成即可;E6~E24系列是用E24的取值间隔选取得到的。
把阻值系列中所有可以得到的分压比例,按对目标分压比例的误差排列,选择出符合误差要求的部分。
最后对这些在误差范围内的选择做随机搜索,查找使用尽量少数量的电阻种类能够完成的一种组合。 %% Optimize Resistance Dividers % K.O.Carnivist % 2015.6.18 %% Input: the only cell to defined by users % Define devider ratio values to solve and corresponding error limits. % For each row, [Devider ratio, Max error]. input_list = ... [5.0 / 0.8 - 1, 0.02; ... 1.0 / 0.6 - 1, 0.02; ... 1.8 / 0.83 - 1, 0.02; ... 2.5 / 0.6 - 1, 0.02; ... 3.3 / 0.6 - 1, 0.02]; % Define fixed resistors included in the system. fixed_list = ... [12]; % Resistor series. % Available values: 6, 12, 24, 48, 96, 192. res_series_name = 48; % Maximum number of iterations of the optimization loop max_iter = 100000; %% Calculate resistor series % res_series stores the available values of resistors in a column. if res_series_name >= 48 res_series = floor(logspace(2, 3, res_series_name + 1) + 0.5)'; res_series = res_series(1: end - 1); res_series(res_series == 919) = 920; else res_series = [100, 110, 120, 130, 150, 160, 180, 200, 220, 240, 270, 300, 330, 360, 390, 430, 470, 510, 560, 620, 680, 750, 820, 910]'; res_series = res_series(1:24/res_series_name:24); end clear res_series_name; %% Calculate resistance divider pairs results = []; % Each cell stores the available value pairs of a divider (two same values for fixed resistors). errors = []; % Each cell stores the corresponding relative error (zeros for fixed resistors). % Find available value pairs of dividers. for i = 1:size(input_list, 1) % These are temporary variables. divider_ratio = input_list(i, 1); max_error = input_list(i, 2); % R1 and R2 are vectors available values in the spedified series. Divider = R1 / R2. % Normalize R1 or R2 if the ratio is too small or too large. if (divider_ratio >= 1) R1 = kron(res_series, 10 .^ (floor(log10(divider_ratio)-1):floor(log10(divider_ratio)+1))); R1 = R1(:); R2 = res_series; else R1 = res_series; R2 = kron(res_series, 10 .^ -(floor(log10(divider_ratio)-1):floor(log10(divider_ratio)+1))); R2 = R2(:); end % Build an array of all the available pairs in the resistor series. R1_temp = kron(R1, ones(size(R2))); R2 = kron(ones(size(R1)), R2); R1 = R1_temp; clear R1_temp; divider_array = R1 ./ R2; % Sort by error. [Y, I] = sort(abs(log(divider_array ./ divider_ratio))); % Add valid pairs and errors. disp_num = find(Y <= log(1 + max_error), 1, 'last'); results{i} = uint32([R1(I(1:disp_num)), R2(I(1:disp_num))]); errors{i} = Y(1:disp_num); end clear res_series divider_ratio max_error R1 R2 divider_array Y I disp_num; % For fixed resistors. for i = 1:length(fixed_list) results{size(input_list, 1) + i} = [fixed_list(i), fixed_list(i)]; errors{ size(input_list, 1) + i} = 0; end %% Find the optimized selection of resistors % Initialize num_of_pairs = uint32(size(results, 2)); num_of_input = uint32(zeros(1, num_of_pairs)); now_index = uint32(zeros(1, num_of_pairs)); R_output = uint32(zeros(num_of_pairs, 2)); error_output = zeros(num_of_pairs, 1); R_max = 0; for i = 1:num_of_pairs R_max = max(R_max, max(max(results{i}))); end for i = 1:num_of_pairs for j = 1:size(results{i}, 1) results{i} = [results{i}; ... kron(double(results{i}(j, :)), ... 10 .^ (1:floor(log10(double(R_max) / ... double(results{i}(j, 1)))))')]; errors{i} = [errors{i}; ... kron(errors{i}(j), ... ones(floor(log10(double(R_max) / ... double(results{i}(j, 1)))), 1))]; end end clear R_max; for i = 1:num_of_pairs num_of_input(i) = size(results{i}, 1); now_index(i) = randi(double(num_of_input(i))); R_output(i, :) = results{i}(now_index(i), :); error_output(i) = errors{i}(now_index(i)); end now_num_of_res = num_of_pairs * 2 + 1; now_max_error = inf; % Loop count = uint32(0); count_to_disp = 1; tic; for count = 1:max_iter % Select one pair of resistors to change index_to_change = randi(double(num_of_pairs)); % Random now_index(index_to_change) = randi(double(num_of_input(index_to_change))); R_output(index_to_change, :) = results{index_to_change}(now_index(index_to_change), :); error_output(index_to_change) = errors{index_to_change}(now_index(index_to_change)); % Check if it is the optimized selection if (length(unique(R_output)) < now_num_of_res) || ... ((length(unique(R_output)) == now_num_of_res) && (max(error_output) < now_max_error)) now_num_of_res = length(unique(R_output)); now_max_error = max(error_output); fprintf('Result of %g resistors in %g attempts: ', now_num_of_res, count); for i = 1:num_of_pairs fprintf('%8d %8d %8.2f%% ', R_output(i, 1), R_output(i, 2), error_output(i) * 100); end end if (count >= count_to_disp) fprintf('loop %g in %g seconds. ', count, toc); count_to_disp = count_to_disp * 10; end end clear i j; clear num_of_pairs num_of_input; clear now_index now_num_of_res now_max_error; clear R_output error_output; clear count count_to_disp max_iter; clear index_to_change; clear R_output error_output