eddy_em: (Костерок)
[personal profile] eddy_em
На днях должны подвезти спирт, и я смогу наконец-то подготовить криостат к тестовой откачке и, если течей не будет, испытанию холодом в наших условиях.
А для этого нужно иметь надежную систему сбора температур. Я уже писал о тестировании системы в жидком азоте. Теперь же решил откалибровать при помощи точного омметра и посмотреть, как датчики себя в комнатной температуре будут вести.

Для калибровки я просто повесил вместо терморезисторов один переменный резистор на 1.5кОм и, изменяя его сопротивление, проводил по нескольку замеров. Калибровочные данные получил простым скриптом (по сути, из него нужна только часть внутри if(MF)):
function data_stat(filename, msrd)
% prints some statistics
% also plot graphs

	MF = 0;
	if(nargin == 0) filename = 'tempout'; endif;
	if(nargin == 2) MF = 1; endif;
	D = dlmread(filename);
	if(isempty(D)) return; endif;
	printf("Some statistics:\n\n\trelative error for inner ADC:\n");

	Time = (D(:,1)*2^24+D(:,2))/1000;
	T = []; Rr = [];

	x = rel_error(D(:,[3 4 6:10]));
	printf("%f ", x);
	avrg = mean(x);
	printf("\t(aver: %f)\n", avrg);
	printf("\n\trelative error for outern ADC:\n\n");
	plot(Time, D(:,[3 4 6:10]));
	if(MF)
		R = dlmread(msrd);
		Rr = R(:,2);
		T = R(:,1)/1000;
		addlabels(Time, D(:,[3 4 6:10]), T, Rr);
	endif;
	Tit = sprintf("Internal 12-bit ADC, err=%f%%", avrg);
	xlabel("Time, s"); ylabel("R, ADU"); title(Tit);
	print -dpng -color int.png;
	close;

	x = rel_error(D(:,[11:18]));
	avrg = mean(x);
	printf("%f ", x);
	printf("\t(aver: %f)\n", avrg);
	printf("\n");
	plot(Time, D(:,[11:18]));
	if(MF)
		addlabels(Time, D(:,[11:18]), T, Rr);
	endif;
	Tit = sprintf("External 24-bit ADC, err=%f%%", avrg);
	xlabel("Time, s"); ylabel("R, ADU"); title(Tit);
	print -dpng -color ext.png;
	close

	meanline = mean(D(:,[11:18])')';
	diffs = mean(D(:,[11:18]) - meanline)  % average difference between mean line
	newD  = D(:,[11:18]) - diffs;
	plot(Time, newD);
	if(MF)
		addlabels(Time, newD, T, Rr);
	endif;
	Tit = sprintf("External 24-bit ADC, corrected");
	xlabel("Time, s"); ylabel("R, ADU"); title(Tit);
	print -dpng -color ext_corr.png;
	close
	if(MF)
		% R = K*ADU -> K = ADU \ R
		Kmul = []; Kadd = []; Kmul2 = [];
		for i = 11:18
		dat = interp1(Time, D(:,i), T);
		N = [ ones(size(dat)) dat dat.^2];
		K = N \ Rr;
		Kadd = [Kadd K(1)];
		Kmul = [Kmul K(2)];
		Kmul2= [Kmul2 K(3)];
		endfor
		%Kmul = median(Kmul);
		%Kadd = median(Rr - dat*Kmul);
		printf("coefficients:\n\tKadd = %s\n\tKmul = %s\n\tKmul2 = %s\n", num2str(Kadd), ...
			num2str(Kmul), num2str(Kmul2));
		printf("stat:\n\t = %g, sigma = %g\n\t = %g, sigma = %g\n", ...
			median(Kmul), std(Kmul), median(Kmul2), std(Kmul2));
		dd = D(:,[11:18]);
		newR  = dd.^2 .* Kmul2 + dd .* Kmul + Kadd;
		plot(Time, newR);
		addlabels(Time, newR, T, Rr);
		Tit = sprintf("External 24-bit ADC, corrected");
		xlabel("Time, s"); ylabel("R, Ohm"); title(Tit);
		print -dpng -color ext_corr_Ohm.png;
	endif
endfunction

function addlabels(Time, data, T, Rr)
%
% plot circles with R label
% - Time - original time labels
% - data - original data
% - T    - time labels for Rr
% - Rr   - measured resistance
%
	meanline = mean(data')';
	newDr = interp1(Time, meanline, T);
	%N = [ ones(size(Rr)) Rr Rr.^2];
	N = [ ones(size(Rr)) Rr ];
	K = N \ newDr
	%Y =  Rr.^2 * K(3) + Rr * K(2) + K(1);
	Y =  Rr * K(2) + K(1);
	hold on; plot(T, Y, '.');
	text(T+10, Y, num2str(Rr));
	%plot(Time, meanline, 'o');
	hold off;
endfunction


Сначала я пробовал линейную аппроксимацию, но получилось плохо. А вот квадратичная вполне хорошо легла. Вот что получилось:
calibration_corr_Ohm
Калибровка восьми каналов АЦП. Горизонтальные участки сплошной линии — показания АЦП; точки — измерение омметром.


Так как прецизионного термометра и термостата у меня нет, то, не мудрствуя лукаво, я решил "в лоб" воспользоваться формулой для преобразования сопротивления ТРД HEL-705 в температуру:
function Tout = H705(Rin)
% Converts resistance of TRD into T (degrC)

_alpha = 0.00375;
_beta = 0.16;
_delta = 1.605;
T = [-300:0.1:300];
_A = _alpha + _alpha*_delta/100.;
_B = -_alpha*_delta/1e4;
_C = zeros(size(T));
_C(find(T<0.)) = -_alpha*_beta/1e8;
rT = 1000.*(1 + _A*T + _B*T.^2 - _C.*T.^3*100. + _C.*T.^4);
Tout = interp1(rT, T, Rin, 'spline');
endfunction


Теперь нужно лишь накопить результаты и преобразовать отчеты в температуру:
function [Time T Tfxd] = get_T(filename, filter_treshold)
% convert ADU into T in Kelvins
% filename - name of file with temperature data
% filter_treshold - treshold level

	D = dlmread(filename);
	if(isempty(D)) return; endif;

	Time = (D(:,1)*2^24+D(:,2))/1000;

	% measured coefficients
	Kadd = [35.628     34.595     35.088     34.754     33.936     33.604     33.966     34.816];
	Kmul = [0.00014524 0.00014577  0.0001462 0.00014628 0.00014577 0.00014545 0.00014558 0.00014523];
	Kmul2 = [3.6789e-11  3.688e-11 3.6878e-11 3.6894e-11 3.6923e-11 3.6929e-11 3.6914e-11 3.6841e-11];
	Readed = D(:,[11:18]);
	nstr = [size(Readed, 1) 1];
	Kadd = repmat(Kadd, nstr);
	Kmul = repmat(Kmul, nstr);
	Kmul2 = repmat(Kmul2, nstr);
	R = Readed.^2 .* Kmul2 + Readed .* Kmul + Kadd;
	T = H705(R);

	% filtering
	if(nargin == 2)
		for i = 1:2
			DT = diff(T);
			[r c] = ind2sub(size(DT), find(DT < -filter_treshold));
			T(r+1, :) = [];
			R(r+1, :) = [];
			Time(r+1, :) = [];
		endfor
	endif

	plot(Time, R);
	Tit = sprintf("Resistance, \\Omega");
	xlabel("Time, s"); ylabel("R, \\Omega"); title(Tit);
	print -dpng -color resistance.png;
	close
	plot(Time, T);
	Tit = sprintf("Temperature, ^\\circ{}C");
	xlabel("Time, s"); ylabel("T, ^\\circ{}C"); title(Tit);
	print -dpng -color temperatures.png;
	close

	% calculate difference between thermometers
	Tavr = mean(T, 2);
	Tadd = mean(T - repmat(Tavr, [1 8]));
	Tfxd = T - repmat(Tadd,[size(T,1) 1]);
	plot(Time, Tfxd);
	Tit = sprintf("Temperature fixed to average value, ^\\circ{}C");
	xlabel("Time, s"); ylabel("T, ^\\circ{}C"); title(Tit);
	print -dpng -color temperatures_fixed.png;
	close
	printf("differences:\n"); printf("%g\n", -Tadd);
endfunction


Блок, помеченный как filtering нужен был, пока у меня в "показометре" был баг: периодически терялся 64-байтный буфер, передаваемый по USB. Баг этот я починил (я забыл проверять, ушли ли уже предыдущие данные, прежде чем посылать следующую порцию).

Вот что получается, когда снимаются показания при комнатной температуре:
temperatures
Не скорректированные на общее среднее показания.

Заметно, что ведут себя эти температуры очень скоррелированно, различаясь лишь аддитивно. Поэтому последняя часть предыдущей функции заодно выравнивает данные на общее среднее:
temperatures_fixed
Скорректированные на "общее среднее" температуры.

В пределах пяти сотых получается примерно одно и то же.

Ну и напоследок еще картинка. Я нагрел руками дюралевый стаканчик, в котором находились ТРД:
temperatures_fixed
Без термостата радужной картинки не получается.

April 2025

S M T W T F S
  1 23 45
67 89101112
13141516171819
20212223242526
27282930   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 22nd, 2025 05:14 pm
Powered by Dreamwidth Studios