Advertisement
314K

Lab 2b - gas sensor

Mar 22nd, 2025
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 7.23 KB | None | 0 0
  1. clear
  2. close all
  3. clc
  4.     % PROCESS_GRAPHENE_DATA
  5.     % 1) Loads data (time, R, concentration)
  6.     % 2) Splits data into on/off intervals
  7.     % 3) Fits 'on' intervals with a log function
  8.     % 4) Fits 'off' intervals with an exponential function
  9.     % 5) Stores results in a cell array and plots them
  10.  
  11.     %% 1. Load data
  12.     % data.txt must contain columns: time(sec), resistance(Ohm), concentration(ppm)
  13.     data = load('data.txt');
  14.     t = data(:,1)./1;    % time in seconds (or use t/60 if you prefer minutes)
  15.     R = data(:,2)./1000;    % resistance
  16.     C = data(:,3);    % concentration
  17.  
  18.     %% 2. Identify gas "on" vs. "off" intervals
  19.     onThreshold = 0.1;      % user-defined threshold for "gas on"
  20.     gasOn = (C > onThreshold);
  21.  
  22.     % Find indices where we transition from on->off or off->on
  23.     switchPoints = find(diff(gasOn) ~= 0);
  24.  
  25.     % We'll store intervals in a cell array. Each element is a struct with:
  26.     %   startIndex, endIndex, isOn
  27.     intervals = {};
  28.     startIdx = 1;
  29.     currentState = gasOn(1);
  30.  
  31.     for i = 1:length(switchPoints)
  32.         endIdx = switchPoints(i);
  33.         intervals{end+1} = struct('startIndex', startIdx, ...
  34.                                   'endIndex',   endIdx, ...
  35.                                   'isOn',       currentState);
  36.         % Next interval will begin after the switch
  37.         startIdx = endIdx + 1;
  38.         currentState = ~currentState;
  39.     end
  40.     % The last interval goes from startIdx to the end of the data
  41.     if startIdx <= length(t)
  42.         intervals{end+1} = struct('startIndex', startIdx, ...
  43.                                   'endIndex',   length(t), ...
  44.                                   'isOn',       currentState);
  45.     end
  46.  
  47.     %% 3. Prepare a cell array to store fits
  48.     % We'll store, for each interval k:
  49.     %   fits{k}.type       = 'growth' or 'decay'
  50.     %   fits{k}.startIndex
  51.     %   fits{k}.endIndex
  52.     %   fits{k}.fitParams
  53.     %   fits{k}.fitModel   = 'A + B ln(t+1)' or 'C + D exp(-k t)'
  54.     %   fits{k}.timeFit, fits{k}.RFit   (for plotting)
  55.     fits = cell(length(intervals),1);
  56.  
  57.     %% 4. Fit each interval
  58.     figure('Name','Graphene Growth/Decay Fits','NumberTitle','off');
  59.     hold on; grid on;
  60.     bluef = [0 0 1 0.1];
  61.     plot(t, R,'color',bluef, 'DisplayName','Raw data');  % raw data in background
  62.  
  63.     for kInt = 1:length(intervals)
  64.         sIdx = intervals{kInt}.startIndex;
  65.         eIdx = intervals{kInt}.endIndex;
  66.  
  67.         % Extract the subset of data for this interval
  68.         subset_t = t(sIdx:eIdx);
  69.         subset_R = R(sIdx:eIdx);
  70.  
  71.         % We'll shift time so the start of the interval is t=0
  72.         t0 = subset_t(1);
  73.         shifted_t = subset_t - t0;  % so it goes from 0 up to (end - start)
  74.  
  75.         % We'll do a finer grid for plotting the fit
  76.         fine_t = linspace(0, shifted_t(end), 200);
  77.  
  78.         if intervals{kInt}.isOn
  79.             % "Growth" interval => fit a log function
  80.             % R(t) = A + B*ln( (t - t0) + 1 ), but since shifted_t = t - t0,
  81.             % effectively: R(t) = A + B * ln( shifted_t + 1 )
  82.  
  83.             % Use MATLAB's 'fit' with a custom fittype
  84.             growthModel = fittype(@(A,B,x) A + B*log(x + 1), ...
  85.                                   'independent','x','coefficients',{'A','B'});
  86.             % Initial guesses
  87.             A0 = subset_R(1);
  88.             % Avoid dividing by zero if the interval is very short
  89.             if shifted_t(end) == 0
  90.                 B0 = 0;
  91.             else
  92.                 B0 = (subset_R(end) - subset_R(1)) / log(shifted_t(end) + 1 + eps);
  93.             end
  94.  
  95.             fitGrowth = fit(shifted_t, subset_R, growthModel, 'StartPoint',[A0, B0]);
  96.  
  97.             % Evaluate the fit for plotting
  98.             Rfit = fitGrowth.A + fitGrowth.B * log(fine_t + 1);
  99.  
  100.             % Store in fits cell
  101.             fits{kInt}.type       = 'growth';
  102.             fits{kInt}.startIndex = sIdx;
  103.             fits{kInt}.endIndex   = eIdx;
  104.             fits{kInt}.fitModel   = 'R(t) = A + B ln(t+1)';
  105.             fits{kInt}.fitParams  = [fitGrowth.A, fitGrowth.B];
  106.             fits{kInt}.timeFit    = t0 + fine_t;   % shift back to original time scale
  107.             fits{kInt}.RFit       = Rfit;
  108.  
  109.             % Plot the fit
  110.             plot(fits{kInt}.timeFit, fits{kInt}.RFit, '-', 'LineWidth',1.5, ...
  111.                  'DisplayName', sprintf('Log fit (interval %d)', kInt));
  112.  
  113.         else
  114.             % "Decay" interval => fit an exponential function
  115.             % R(t) = C + D * exp(-k * (t - t0))
  116.             % with shifted_t = t - t0, that becomes: R(t) = C + D * exp(-k * shifted_t)
  117.  
  118.             decayModel = fittype(@(C,D,k,x) C + D.*exp(-k.*x), ...
  119.                                  'independent','x','coefficients',{'C','D','k'});
  120.             % Initial guesses
  121.             C0 = subset_R(end);             % final (plateau) value
  122.             D0 = subset_R(1) - subset_R(end);
  123.             k0 = 0.01;  % guess a small positive rate
  124.  
  125.             fitDecay = fit(shifted_t, subset_R, decayModel, 'StartPoint',[C0, D0, k0]);
  126.  
  127.             % Evaluate the fit for plotting
  128.             Rfit = fitDecay.C + fitDecay.D * exp(-fitDecay.k * fine_t);
  129.  
  130.             % Store in fits cell
  131.             fits{kInt}.type       = 'decay';
  132.             fits{kInt}.startIndex = sIdx;
  133.             fits{kInt}.endIndex   = eIdx;
  134.             fits{kInt}.fitModel   = 'R(t) = C + D exp(-k t)';
  135.             fits{kInt}.fitParams  = [fitDecay.C, fitDecay.D, fitDecay.k];
  136.             fits{kInt}.timeFit    = t0 + fine_t;
  137.             fits{kInt}.RFit       = Rfit;
  138.  
  139.             % Plot the fit
  140.             plot(fits{kInt}.timeFit, fits{kInt}.RFit, '-', 'LineWidth',1.5, ...
  141.                  'DisplayName', sprintf('Exp fit (interval %d)', kInt));
  142.         end
  143.     end
  144.  
  145.     xlabel('Time (s)');
  146.     ylabel('Resistance (k\Omega)');
  147.     legend('Location','best');
  148.     title('Graphene Oxide Resistance Growth/Decay Fits');
  149.     hold off;
  150.  
  151.     %% 5. Display final results in the Command Window
  152.     fprintf('\n======= Fit Results by Interval =======\n');
  153.     for kInt = 1:length(intervals)
  154.         switch fits{kInt}.type
  155.             case 'growth'
  156.                 A_(kInt) = fits{kInt}.fitParams(1);
  157.                 B_(kInt) = fits{kInt}.fitParams(2);
  158.                 fprintf('Interval %d (Growth): A = %.4g, B = %.4g\n', kInt, A_(kInt), B_(kInt));
  159.             case 'decay'
  160.                 C_(kInt) = fits{kInt}.fitParams(1);
  161.                 D_(kInt) = fits{kInt}.fitParams(2);
  162.                 k_(kInt) = fits{kInt}.fitParams(3);
  163.                 fprintf('Interval %d (Decay): C = %.4g, D = %.4g, k = %.4g\n', kInt, C_(kInt), D_(kInt), k_(kInt));
  164.         end
  165.     end
  166. ftype()
  167.     %% calculating stuff for lab report
  168.    
  169. for i = 1:length(fits)
  170.     R0(i) = fits{i}.RFit(1);
  171.     Rend(i) = fits{i}.RFit(end);
  172.     delta(i) = Rend(i) - R0(i);
  173.     R90(i) = R0(i) + delta(i).*0.9;
  174.     if mod(i,2) == 1
  175.         index(i) = find(fits{i}.RFit > R90(i), 1);
  176.     else
  177.         index(i) = find(fits{i}.RFit < R90(i), 1);
  178.     end
  179.     T0(i) = fits{i}.timeFit(1);
  180.     T90(i) = fits{i}.timeFit(index(i))-T0(i);
  181.    
  182.     S(i) = abs(delta(i))./min([R0(i) Rend(i)]).*100;
  183. end
  184.  
  185. T90
  186. S
  187.  
  188. %%
  189. function ftype()
  190. set(gca,'FontSize',13,'fontWeight','bold')
  191. set(findall(gcf,'type','text'),'FontSize',13,'fontWeight','bold')
  192. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement