function [] = RmonitoringSSP_v20170802()
%Resistance monitoring of silver sintering process
% Monitor electrical resistance with B2911A precise current source and/or
% 34420A nanovoltmeter for multiple samples. The connection is controlled
% with two Keithley 7700 multiplexer cards installed in a Keithley 2700 
% multimeter. The example code below is for monitoring 12 samples. The 
% temperature is monitored with Pt100 connected to a 34401A multimeter.
% The resistance range with this method is 1uOhm-20TOhm. The resistance is
% visualized in real time on PC screen. 
% This code is developed to monitor silver sintering process, and can be 
% used for similar purposes with necessary modifications.
% By Di Erick Xu, University of Waterloo, 2017.Aug.02

% Hardware: GPIB-USB cable, an Agilent B2911A, an Agilent 34420A, an
% Agilent 34401A, a Keithley 2700, and two Keithley 770x cards.

% Tags: GPIB, Digital multimeter, Multiplexer, Resistance monitoring,
% Silver sintering, Temperature monitoring,

%% initialzation
close all;
clear;
clc;
instrreset;

%% variable definations
totalMeasHour = 10; % Total measurement time in hours
totalMeasSec = totalMeasHour*60*60; % Total measurement time in seconds

sampleName = 'Demo4MathworksCentral';
targetTemp = '175C2h'; % The target temperature for the sintering process

sampleCHs = 201:212;  % Samples 1-12 are connected to Channels 1-12 of multiplexer Card 2  
NanoInputCH = 101; % Nanovoltmeter input is connected to Channel 1 of multiplexer Card 1 
NanoSenseCH = 213; % Nanovoltmeter sense is connected to Channel 13 of multiplexer Card 2 
CurrInCH = 102; % Sample current input leads are connected to Channel 2 of multiplexer Card 1
B2911ACH = 214; % B2911A is connected to Channel 14 of multiplexer Card 2

resistanceM = nan(1, length(sampleCHs)); % create an initial array of NaNs for resistance from B2911A manual mode
timeM = nan(1, length(sampleCHs)); % create an initial array of NaNs for the time for resistance measurements from B2911A manual R mode
resistanceA = nan(1, length(sampleCHs)); % create an initial array of NaNs for resistance from B2911A auto R mode
timeA = nan(1, length(sampleCHs)); % create an initial array of NaNs for the time for resistance measurements from B2911A auto R mode
resistance4 = nan(1, length(sampleCHs)); % create an initial array of NaNs for resistance from 34420A 4wire mode
time4 = nan(1, length(sampleCHs)); % create an initial array of NaNs for the time for resistance measurements from 34420A 4wire mode

temp = nan; % create an initial NaN for temperature
tempTime = nan; % create an initial NaN for the time for temperature measurements

fname=[datestr(now, 30) '_' sampleName '_' num2str(targetTemp)];

%% gpib connections
% A national instrument ('ni') gpib-usb adapter is used to connect PC with
% the instruments. The board number of the adapter is 0. The addresses of
% the 34401A multimeter, the 34420A nanovoltmeter, the Keithley 2700
% multiplexer with two 770x multiplexer cards, and the B2911A precise
% current source are 22, 23, 24, and 25, respectively, in this example.
tempmeter = gpib('ni', 0, 22);
nanovoltmeter = gpib('ni', 0, 23);
multiplexer = gpib('ni', 0, 24);
B2911A = gpib('ni', 0, 25);

% Open communication
fopen(multiplexer);
fopen(B2911A);
fopen(nanovoltmeter);
fopen(tempmeter);

%% reset and configure all the four devices
% reset and configure B2911A
fprintf(B2911A, '*rst');
fprintf(B2911A, '*opc?');
fscanf(B2911A);
fprintf(B2911A, '*cls');

% reset and configure the 34401A multimeter for temperature measurement
fprintf(tempmeter, '*rst');
fprintf(tempmeter, '*opc?');
fscanf(tempmeter);
fprintf(tempmeter, '*cls');
fprintf(tempmeter, 'CONFigure:TEMPerature FRTD');

% reset and open all channels of the 7700 Multiplexer cards in the Keithley 2700 multimeter
fprintf(multiplexer, '*rst');
fprintf(multiplexer, '*opc?');
fscanf(multiplexer);
fprintf(multiplexer, 'rout:open:all');
fprintf(multiplexer, '*opc?');
fscanf(multiplexer);

% reset and configure nanovoltmeter
fprintf(nanovoltmeter, '*rst');
fprintf(nanovoltmeter, '*opc?');
fscanf(nanovoltmeter);
fprintf(nanovoltmeter, '*cls');
fprintf(nanovoltmeter, 'conf:fres'); % configure nanovoltmeter in four wire resistance mode
fprintf(nanovoltmeter, 'sense:fres:ocom on'); % turn on offset compensation
fprintf(nanovoltmeter, 'sense:fres:range 1'); % Range: 1Ohm

%% monitoring starts
tic; % start timer

j = 0; % use j as a counter for the number of resistance measurement for each sample

while toc < totalMeasSec % no stop until total measurement time is reached
    j = j+1; % the current loop number
    %% Measurements
    for i = 1:length(sampleCHs) % The 12 samples in a for loop
        %%  connect the ith sample (potentially to B2911A, or 34420A, which are still disconnected at this point of the code)
        fprintf(multiplexer, ['rout:mult:clos (@', num2str(sampleCHs(i)), ')']);
        fprintf(multiplexer, '*opc?');
        fscanf(multiplexer);
        
        %% Manual resistance mode of B2911A
        % connect B2911A to the sample 
        fprintf(multiplexer, ['route:mult:clos (@', num2str(B2911ACH), ')']);
        fprintf(multiplexer, '*opc?');
        fscanf(multiplexer);
        
        % configure B2911A in manual resistance mode (for 10kOhm-20TOhm range 2wire resistance values)
        fprintf(B2911A, '*rst');
        fprintf(B2911A, ':SENSe:CURRent:PROTection 1e-7'); % set the current output limit to 100nA
        fprintf(B2911A, ':VOLTage 20'); % set the voltage output limit to 20V
        fprintf(B2911A, ':VOLTage:Range 20'); % set the voltage measurement range to 20V
        fprintf(B2911A, ':SENSe:CURRent:RANGe 1e-7 '); % set the current measurement range to 100nA
        fprintf(B2911A, ':SENSe:RESistance:MODE MAN'); % set B2911A to manual resistance mode
        fprintf(B2911A, ':SENS:FUNC "RES"'); % set B2911A to calculate resistance from the V and I it measures
        fprintf(B2911A, ':OUTPut 1'); % turn on the output
        fprintf(B2911A, ':SENS:RES:NPLC 1'); % number of power line cycle

        % take 20 readings from B2911A, take the average of the last 10 readings
        % There is an offset for the first measurement, and the signal 
        % shifts to a final stablized value in a few readings (<10), in
        % the manual resistance mode
        rawR = nan(1,20); 
        for ii = 1:20
            fprintf(B2911A, ':MEASure:RESistance? '); % ask B2911A to make a measurement
            rawStr = fscanf(B2911A); % save the reading (a string of digits) from B2911A to rawStr
            rawR(ii) = str2double(rawStr); % change the string to number format, and save to rawR
        end
        timeM(j, i) = toc; % save the current time to timeM
        resistanceM(j, i) = mean(rawR(11:20)); % save the average of the last 10 values of rawR to resistanceM

        %% Auto resistance mode of B2911A
        % configure B2911A in auto resistance mode (for <20kOhm range 2wire resistance values)        
        fprintf(B2911A, '*rst');
        fprintf(B2911A, ':SENSe:RESistance:MODE AUTO'); % set B2911A to auto R mode
        fprintf(B2911A, ':SENSe:RESistance:RANGe 2e4'); % set B2911A range to 20kOhm
        fprintf(B2911A, ':SENS:FUNC "RES"'); % set B2911A to calculate resistance from the V and I it measures
        fprintf(B2911A, ':SENS:RES:NPLC 1'); % number of power line cycle
        fprintf(B2911A, ':MEASure:RESistance? '); % ask B2911A to make a measurement

        rawStr = fscanf(B2911A); % save the reading (a string of digits) from B2911A to rawStr
        timeA(j, i) = toc; % save the current time to timeA
        resistanceA(j, i) = str2double(rawStr);  % change the string to number format, and save to resistanceA
        
        %% 4wire resistance mode with 34420A nanovoltmeter
        % Disconnect B2911A 
        fprintf(multiplexer, ['route:mult:open (@', num2str(B2911ACH), ')']);
        % Connect 34420A to the sample
        fprintf(multiplexer, ['route:mult:clos (@', ...
            num2str(NanoInputCH), ',', ...
            num2str(NanoSenseCH), ',', ...
            num2str(CurrInCH), ')']);
        fprintf(multiplexer, '*opc?');
        fscanf(multiplexer);
        
        fprintf(nanovoltmeter, 'read?'); % ask 34420A to make a measurement
        rawStr = fscanf(nanovoltmeter); % save the reading (a string of digits) from 34420A to rawStr
        time4(j, i) = toc; % save the current time to time4
        resistance4(j, i) = str2double(rawStr); % change the string to number format, and save to resistance4
        
        % Disconnect 34420A from the sample        
        fprintf(multiplexer, ['route:mult:open (@', ...
            num2str(NanoInputCH), ',', ...
            num2str(NanoSenseCH), ',', ...
            num2str(CurrInCH), ')']);
    end
    %% Visualization
    % plot resistance from the Manual resistance mode of B2911A
    resistanceM(resistanceM>1e30)=nan; % The reading is 9.9e37 when out of range, change such values to NaN
    ttM=timeM(max([1 j-200]):j, :);
    rrM=resistanceM(max([1 j-200]):j, :);
    semilogy(ttM, rrM); hold on; 
    
    % plot resistance from the Auto resistance mode of B2911A
    resistanceA(resistanceA>1e30)=nan; % The reading is 9.9e37 when out of range, change such values to NaN
    ttA=timeA(max([1 j-200]):j, :);
    rrA=resistanceA(max([1 j-200]):j, :);
    semilogy(ttA, rrA);  
    
    % plot resistance from the 4wire mode of 34420A nanovoltmeter
    resistance4(resistance4>1e30)=nan; % The reading is 9.9e37 when out of range, change such values to NaN
    tt4=time4(max([1 j-200]):j, :);
    rr4=resistance4(max([1 j-200]):j, :);
    semilogy(tt4, rr4);  
    
    title(['j: ' num2str(j) ', R1: ' num2str(min([resistanceM(j, 1), ...
        resistanceA(j, 1), resistance4(j, 1)])) ' Ohm, ' ...
        num2str(length(ttM(:, 1))/range(ttM(:, 1)),5) ' pts/s']);
    xlabel('Time [s]');ylabel('R [Ohm]');
    if j>10;
        a=axis;axis([min(ttM(:, 1)) max(tt4(:, end)) a(3:4)]);
    end
    drawnow;

    %% temperature
    fprintf(tempmeter, 'read?');
    temp(j) = str2double(fscanf(tempmeter));
    tempTime(j) = toc;
    
    %% Data save
    save([fname '.mat']);
    
end

%% close communication
fclose(multiplexer);
fclose(B2911A);
fclose(nanovoltmeter);
fclose(tempmeter);

%% Plot results
close all
figure
subplot(2,1,1)
colors = {[0.25 0.25 0],'m','c','r','g','b','k',[0.5 0.5 0],[0.5 0 0.5],...
    [0 0.5 0.5],[0.5 0 0],[0 0.5 0],[0 0 0.5],[0.5 0.5 0.5]};
for i = 1:12
    hM = loglog(timeM(:, i)/60, resistanceM(:, i), '-',timeM(:, i)/60, resistanceM(:, i), '.');
    hA = loglog(timeA(:, i)/60, resistanceA(:, i), '-',timeA(:, i)/60, resistanceA(:, i), '.');
    h4 = loglog(time4(:, i)/60, resistance4(:, i), '-',time4(:, i)/60, resistance4(:, i), '.');
    hold on;
    set(hM, 'Color', colors{i});
    set(hA, 'Color', colors{i});
    set(h4, 'Color', colors{i});
end

grid on;
xlabel('Time [min]');
ylabel('Resistance [Ohm]');
title(fname);

subplot(2,1,2)
semilogx(tempTime/60, temp);
xlabel('Time [min]');
ylabel('Temperature [°C]');

figwind=[30          64        1493         729];
set(gcf,'Position',figwind);
saveas(gcf,[fname '_fig'],'fig');

end

