sábado, 3 de diciembre de 2016

Final Project

Team members

Hidalgo Rodríguez Ana Karen
Rodríguez Matrínez José Alberto
Varela Romero Carol

Description

The spirometer is a measuring instrument used in medicine to determine lung volumes and capacities. Flow measurement was performed during ventilation from the readings of a differential pressure sensor. The Lilly configuration was used for spirometer design (Figure 1). The signal conditioning circuit was designed for proper acquisition using Arduino. Data transmission to the computer was done wirelessly. The digital processing of the obtained signal was done with a graphical interface in Matlab.


Figure 1. Lilly configuration pneumotach. 
Obtained from: http://www.pftforum.com/blog/pneumotach-accuracy/



Physical Laws
Respiratory Flow

Air moves from a region of high pressure to another of lower pressure, gas exchange is possible by the difference of pressures. In the lungs, inspiration occurs when the alveolar pressure falls below atmospheric pressure as a negative pressure is generated due to the movement of the diaphragm and the walls of the chest, the expiration is carried out passively when the work required to overcome the friction resistance is lost.

In the turbulent flow the particles move heterogeneously across the flow, bumping against each other, causing fast and continuous flow mixing. The turbulence is described by the Reynolds number, that is calculated using equation (1).

(1)

Where:
ⲣ: density of the flux [kg / m3]
V: characteristic velocity of the fluid [m/s]
u: kinematic velocity of the fluid [kg/m*s]x10-5
D: diameter of the pipe through which the fluid flows [m]
v: dynamic flow velocity [m2/s]x10-5

If the Reynolds number is less than 2000 the flow will be laminar and if it is greater than 4000, the flow will be turbulent.

Objective

  • Tobacco kills up to half of its consumers.
  • Tobacco users who die prematurely deprive their families of income, increase the cost of health care and hinder economic development.
  • Most smokers who know the dangers of tobacco want to quit. Counseling and medication can double the likelihood that a smoker who wants to quit will get it.
  • There is no smoking cessation assistance in a quarter of low-income countries.
The objective of the project is to design a prototype spirometer that is capable of measuring the respiratory flow from a differential pressure and transmit the data obtained wirelessly to the computer for further processing, so smokers are aware of their progress and remain motivated to move forward. 

Technical Data

Bandwidth: 0-10 Hz
Device amplification ratio: 63 000
CMRR:118

Components

  • 1 MPX2200DP: silicon piezoresistive pressure sensor.
    http://www.kosmodrom.com.ua/pdf/MPX2200.pdf
  • 1 AD620: low cost, high accuracy instrumentation amplifier.
    http://www.analog.com/media/en/technical-documentation/data-sheets/AD620.pdf

  • 3 OPA2277: High-Precision, Low-Noise Operational Amplifier
    http://www.ti.com/lit/ds/symlink/opa2277-ep.pdf

  • Capacitors: 3x1uF, 820nF
  • Resistors: 18Ω, 2x15KΩ, 2x2.2KΩ, 2x1KΩ, 22KΩ, 1.5KΩ, 3x330Ω, 2x4.7KΩ 
  • Arduino Leonardo: integrated USB HID Arduino board.
    https://www.arduino.cc/en/Main/ArduinoBoardLeonardo
Software Tools:
  • MATLAB: software to analyse and design systems and products; used in machine learning, signal processing, image processing, computer vision, communications, computational finance, control design, robotics, and more.
    https://www.mathworks.com/products/matlab.html
  • Eagle PCB Design: software to bring designs to live by creating Printed Circuit Boards (PCB).
    https://cadsoft.io/

Instructions

Signal Acquisition:
For the pressure measurements the silicon piezoresistive pressure sensor MPX220DP was used, which provides a precise and linear pressure output proportional to the applied pressure. The sensitivity of the sensor is 0.2 mV / kPa and with a dynamic differential pressure range of 0 to 200 kPa. 

Signal conditioning:
Pre-amplification: an instrumentation amplifier AD620 was used to amplify the signal approximately 2,700 times, since the signal in the exit of the sensor is extremely small. The resistance for the amplifier was calculated using equation (2) shown below, the resulting resistance was 18 ohms.
(2)
Filtering: The filtering was performed with a low-pass filter of second order, with a cutoff frequency of 10Hz, of unity gain to filter the signal noise. The Sallen-Key configuration was chosen for its great performance. The values ​​of capacitors and resistors were obtained from the transfer function shown in the equation (3).
(3)
Amplification: the amplification step was implemented in order to obtain a signal on a range of 5v between the minimum pressure and the maximum pressure mesured, a gain of 23 was calculated, a non-inverting amplifier was used and the resistances were calculated using the equation (4) shown below. Establishing R1 = 1Kohm, the calculated resistance was 22Kohms.
G=1+R2/R1 (4)
Compensation: finally an adder was done to eliminate the offset generated in the previous stages and to avoid damages for the Arduino. The inputs of the adder were the signal and 3v to carry the signal above 0v.
Figure 2 shows the acquisition and conditioning schematic circuit.


Figure 2. Acquisition and conditioning schematic circuit.

Printed circuit board: The software Eagle PCB Design was used to translate the circuit to a printed circuit board (PCB), the PCB design is shown in Figure 3.

Figure 3. Acquisition and conditioning board circuit.

Data transmission: The final voltage signal of the analog electronic circuit (ADC) was sent to the A0 port of an Arduino Leonardo, to be discretized by a 10-bit analog-to-digital converter whose acquisition was transmitted (in pairs of data: Amplitude in number of bits and time in milliseconds) by serial communication to a remote computer through Xbee devices.

Signal processing: The digital processing of the obtained signal was realized in Matlab, and was carried out in two stages: the remote acquisition and store of a new signal from the spirometer; and executing a data processing of the stored signal. 
For the first stage, a function activates the serial communication with the port to which the Xbee receiver is connected to the computer and displays in real time a graph with the number of bits of the ADC corresponding to each sample on the vertical axis, and the time in milliseconds in which it was acquired on the horizontal axis. 
In the second stage, by displaying a dialog box, two vectors are imported into the workspace ( "x" containing the number of amplitude bits of each sample and "t" which stores the time in milliseconds where each sample was acquired).
A second-order Butterworth low-pass filter with a cutoff frequency of 1 Hz was applied to the vector signal x to reduce the high frequency component noise generated by the Arduino. 
Equation (5) was applied to each element of the vector "x" to convert it to voltage, since the Arduino assigns a value of 1024 bits for an input of 5V and from 0 to 0 V. 
(5)

To convert the amplitude of the voltage signal to pressure, the known offset of the signal was removed and its amplitude divided by the total gain of the analog electronic circuit to estimate the voltage differential output of the pressure sensor, which was finally converted to pressure based on its sensitivity reported in its datasheet ie 0.2 mV per 1 kPa as shown in equation (6).
(6)
Where:

P: is each element of the pressure signal vector in Pascal (It represents the difference of pressures between both sides of the resistive membrane of the spirometer head).

Vin: is each element of the voltage signal vector obtained by equation 5.

Vof: is the offset voltage provided by the electronic circuit of the spirometer.

G: is the total gain of the electronic circuit of the spirometer.

%*******************Code for digital processing******************************

%To carry out digital processing, just have to implement this code in Matlab.

function varargout = interfaz_espirometro(varargin)
% INTERFAZ_ESPIROMETRO MATLAB code for interfaz_espirometro.fig
%      INTERFAZ_ESPIROMETRO, by itself, creates a new INTERFAZ_ESPIROMETRO or raises the existing
%      singleton*.
%
%      H = INTERFAZ_ESPIROMETRO returns the handle to a new INTERFAZ_ESPIROMETRO or the handle to
%      the existing singleton*.
%
%      INTERFAZ_ESPIROMETRO('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in INTERFAZ_ESPIROMETRO.M with the given input arguments.
%
%      INTERFAZ_ESPIROMETRO('Property','Value',...) creates a new INTERFAZ_ESPIROMETRO or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before interfaz_espirometro_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to interfaz_espirometro_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help interfaz_espirometro

% Last Modified by GUIDE v2.5 05-Dec-2016 08:01:42

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @interfaz_espirometro_OpeningFcn, ...
                   'gui_OutputFcn',  @interfaz_espirometro_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before interfaz_espirometro is made visible.
function interfaz_espirometro_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to interfaz_espirometro (see VARARGIN)

% Choose default command line output for interfaz_espirometro
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes interfaz_espirometro wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = interfaz_espirometro_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
AdquisicionDatos();


% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[Archivo,Ruta]=uigetfile({'*.mat'},'Abrir archivo');
importfile(Archivo);    %importar al workspace
t = evalin('base','t'); %importar desde el workspace
x = evalin('base','x');
t=t-t(1); %Iniciar en el tiempo 0s
%%Filtrar señal
%plot(t,x);
%title('Señal original')
%xlabel('Tiempo [s]');
%ylabel('Número de bits');
Fs=81;
orden=2;
freccorte=1;
d=fdesign.lowpass('N,F3dB',orden,freccorte,Fs);
Hbutter=design(d,'butter','SystemObject',true);
y=step(Hbutter,x);
%figure();
%plot(t,y);
%title('Señal filtrada');
%xlabel('Tiempo [s]');
%ylabel('Número de bits');
%Pasar señal a voltaje
y=y.*5/1024;
%figure();
%plot(t,y);
%title('Señal de voltaje');
%xlabel('Tiempo [s]');
%ylabel('Voltaje [V]');
%ubicar picos para encontrar un ciclo espiracion/inspiracion
%hold on
[p,l]=findpeaks(y);
%stem(t(l),p);
i=1;
while p(i)<4.0 
    i=i+1;   
end  %en i queda la localizacion en el vector de picos, del pico de la primer espiracion
j=l(i); %en j queda la localización en la señal, del pico de la primer espiracion
pico_espiracion=j;
while (y(j-1)<y(j))&&((y(j)-y(j-1))>0.001);
    j=j-1;
end
inicio_espiracion=j; %indice donde está el inicio de la primer espiracion
offset=y(j);
%remover offset a la señal
y=y-offset;
%figure();
%plot(t,y);
%title('señal sin offset');
%encontrar final de la espiracion
i=pico_espiracion;
while y(i)>0
    i=i+1;
end
fin_espiracion=i;
while y(i)<0
    i=i+1;
end
fin_inspiracion=i;
%plotear un cilo espiracion/inspiracion
%figure()
%plot(t(inicio_espiracion:fin_inspiracion),y(inicio_espiracion:fin_inspiracion));
%title('Ciclo ventilatorio');
%axis tight
%Pasar a curva de presión
G=60390; %Ganancia del circuito analógico 2745x22
y=y./G;
presion=y.*(1000/0.0002);
%figure();
%plot(t(inicio_espiracion:fin_inspiracion),presion(inicio_espiracion:fin_inspiracion));
%title('Curva de presión');
%xlabel('Tiempo [s]');
%ylabel('Presión [Pa]');
%axis tight
%Recortar señal de tiempo y presion a solo lo de un ciclo inspiratorio
t_1=t(inicio_espiracion:fin_inspiracion);
t_1=t_1-t_1(1);
presion=presion(inicio_espiracion:fin_inspiracion);
%pasar a flujo
%Presion=flujo x resistencia
resistencia=0.06; %(Pa*s)/L
flujo=resistencia*presion;
%figure();
axes(handles.axes4);
plot(t_1,flujo);
%title('Curva de flujo');
xlabel('Tiempo [s]');
ylabel('Flujo [L/s]');
axis tight
grid on
%pasar a volumen
volumen=cumtrapz(t_1,flujo);
%figure();
axes(handles.axes7);
plot(t_1,volumen);
%title('Curva de volumen');
xlabel('Tiempo [s]');
ylabel('Volumen [L]');
axis tight
grid on
%Curva de presion volumen
%figure();
axes(handles.axes8);
plot(volumen,flujo);
%title('Curva de flujo-volumen');
xlabel('Volumen [L]');
ylabel('Flujo [L/s]');
axis tight
grid on
aux=t(fin_espiracion)-t(inicio_espiracion); %obtener tiempo de espiracion
set(handles.edit1,'String',aux); %desplegar tiempo de inspiracion
aux=t(fin_inspiracion)-t(fin_espiracion); %obtener tiempo de inspiracion
set(handles.edit2,'String',aux); %desplegar tiempo de inspiracion




% --- Executes on slider movement.
function slider2_Callback(hObject, eventdata, handles)
% hObject    handle to slider2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on slider movement.
function slider3_Callback(hObject, eventdata, handles)
% hObject    handle to slider3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider3_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
% hObject    handle to slider1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes on slider movement.
function slider5_Callback(hObject, eventdata, handles)
% hObject    handle to slider5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider5_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes on slider movement.
function slider4_Callback(hObject, eventdata, handles)
% hObject    handle to slider4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider


% --- Executes during object creation, after setting all properties.
function slider4_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)



function edit1_Callback(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double


% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit2_Callback(hObject, eventdata, handles)
% hObject    handle to edit2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit2 as text
%        str2double(get(hObject,'String')) returns contents of edit2 as a double


% --- Executes during object creation, after setting all properties.
function edit2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


%*****************Code has finished************************************ 

%Previously, you have to had alredy saved this function with the name:  AdquisicionDatos

function AdquisicionDatos
    close all; clear all; clc
   
    fh = figure('Visible','off','Position',[200 200 1000 500]);
    movegui(fh,'center')
        ha = axes('Units', 'pixels', 'Position',[50, 50, 590, 400]);
       
        sth1 = uicontrol(fh, 'Style', 'text',...                    % print time
            'Position',[690 390 270 60], 'BackgroundColor', 'w',...
            'FontSize', 30, 'ForegroundColor', [0 0 1]);
       
        tbh1 = uicontrol(fh, 'Style', 'togglebutton',...            % on/off
            'Position', [690 330 80 40], 'FontSize', 14,...
            'Callback', {@tbh1_Callback});
       
        pbh1 = uicontrol(fh, 'Style', 'pushbutton',...              % reset
            'Position', [785 330 80 40], 'String', 'Reset',...
            'FontSize', 14, 'Callback', {@pbh1_Callback});
       
        pbh2 = uicontrol(fh, 'Style', 'pushbutton',...              % reset
            'Position', [880 330 80 40], 'String', 'Guardar',...
            'FontSize', 13, 'Callback', {@pbh2_Callback});
       
        sth2 = uicontrol(fh, 'Style', 'text',...                    % print time
            'Position',[690 210 270 100], 'FontSize', 12,...
            'HorizontalAlignment', 'Left');

    set([fh, ha, sth1, tbh1, pbh1, pbh2, sth2], 'Units', 'normalized');
   
    puerto = 'COM4';
    delete(instrfind({'Port'},{puerto}))
    s1 = serial(puerto, 'BaudRate', 9600);

    [f, i, t_ant, t, x] = inicio(tbh1, sth1, sth2, pbh2);
    [plotGraph, ymin, ymax, scrollWidth] = plot_inicio(ha, t, x);
   
    set(fh,'Visible','on')
   
% *********************************************************************
% ********** Boton ON/OFF
    function tbh1_Callback(hObject, eventdata)   
        tb_edo = get(hObject, 'Value');
        %Boton estado ON
        if tb_edo == get(hObject, 'Max')
            f = 1;
            set(tbh1, 'String', 'Off');     %Etiqueta On a Off
            %Se abre el puerto y se inicia la comunicacion serial
            set(sth2, 'String', sprintf('Estableciendo la comunicacion con el puerto: %s',puerto));
            pause(1)
            fopen(s1);
            for j=1:1:100
                data=fscanf(s1,'%f');
            end
            clear all
            set(sth2, 'String', sprintf('Adquiriendo datos...'));
            while f == 1 % ON (adquisición y despliegue)
                i = i+1;
                data = fscanf(s1,'%f');
                    t(i,1) = data(1);
                    x(i,1) = data(2);      
                    if ((data(1)-t_ant) >= 100)
                        set(sth1, 'String', sprintf('%d [ms]', data(1)));
                        if(t(i)>scrollWidth)  
                            set(plotGraph(1),'XData',t(t > t(i)-scrollWidth),...
                                'YData',x(t > t(i)-scrollWidth));
                            set(ha, 'XLim', [t(i)-scrollWidth t(i)], 'YLim', [ymin ymax]);
                        else
                            set(plotGraph(1),'XData', t,'YData',x);
                            set(ha, 'XLim', [0 scrollWidth], 'YLim', [ymin ymax]);
                        end
                        t_ant = data(1);
                        drawnow
                    end
            end
        end
        %Boton estado OFF
        if tb_edo == get(hObject,'Min')
            set(sth2, 'String', sprintf('Cerrando la comunicacion con el puerto: %s',puerto));
            pause(1)
            %Se cierra el puerto serial
                fclose(s1);
                f = 0;
            t = t/1000;
            set(sth1, 'String', sprintf('%0.3f [s]', t(i)));
            set(pbh2, 'Enable', 'On');
            set(tbh1, 'Enable', 'Off');
            reset(ha);
            ymin = 0; ymax = 1023;
            set(plotGraph(1),'XData',t,'YData',x);
            set(ha, 'Box', 'on', 'XLim', [min(t) max(t)], 'YLim', [ymin ymax],...
                'XGrid', 'on', 'YGrid', 'on');
            set(get(ha,'XLabel'),'String','t [s]','FontSize',12,...
            'FontWeight','bold')
            Fs=length(x)/(max(t)-min(t));
            set(sth2, 'String', sprintf('Frecuencia de muestreo:\t%.2f', Fs));
        end
    end

% % *************************************************************
    function pbh1_Callback(hObject, eventdata) % RESET
        set(sth2, 'String', sprintf('Espere mientras carga configuraciones iniciales'));
        pause(1)
        [f, i, t_ant, t, x] = inicio(tbh1, sth1, sth2, pbh2);
        [plotGraph, ymin, ymax, scrollWidth] = plot_inicio(ha, t, x);
        set(sth2, 'String', sprintf('Listo'));
    end

    function pbh2_Callback(hObject, eventdata) % GUARDAR
        fileName = datestr(now, 'yymmddHHMMSS');
        uisave({'t', 'x'}, fileName);
    end
% % ***************************************************************
    function [f, i, t_ant, t, x] = inicio(tbh, sth1, sth2, pbh2)
       
        f = 0; i = 0;
        t_ant = 0;
        t = 0; x = 0;
        set(pbh2, 'Enable', 'Off');
        set(sth1, 'String', '0 [ms]');
        set(sth2, 'String', {''});
        set(tbh, 'String', 'On', 'Enable', 'on', 'Value', 0);
       
    end

    function [plotGraph, ymin, ymax, scrollWidth] = plot_inicio(ha, t,...
            x)
        ymin = 0; ymax = 1023; %Eje Y maximo y minimo
        scrollWidth = 5000;  % [ms] % 5000 milisegundos
        plotGraph = plot(ha, t, x);
        set(plotGraph(1),'LineWidth',2)
        set(ha, 'Box', 'on', 'XLim', [0 scrollWidth], 'YLim', [ymin ymax],...
            'XGrid', 'on', 'YGrid', 'on');
        set(get(ha,'XLabel'),'String','t [ms]','FontSize',12,...
            'FontWeight','bold')
    end
end


%**********************Code has finished******************************


Results

In Figure 4 it is shown in pneumotacograph that was designed to obtain a laminar flow.



Figure 4. Pneumotacograph.

The PCB with the stages of amplification, filtering and compensation is shown in Figure 5.


Figure 5. Circuit in printed circuit board.


In Figure 6, the graphic interface with which the data transmitted from the spirometer to the computer was received is shown.




Figure 6. GUI for receiving wirelessly transmitted data.

Figure 7 shows the signal acquired in the previous step, given its amplitude in number of bits and time in seconds; it is affected by noise from high frequency components.


Figure 7. Original signal in number of bits and time in seconds.

In Figure 8 the previous signal is observed after the implementation of a Butterworth pass lows filter of second order and cutoff frequency of 1 Hz. The difference is remarkable, noting that the signal of physiological relevance is clearer.


Figure 8. Filtered signal.

The signal converted to its amplitude, from number of bits to voltage is observed in Figure 9. This is imperative to obtain the pressure difference at each point of the measurement. Also there can be observed detected peaks in signal which function to cut the signal in just one ventilatory cycle.

Figure 9. Spirometry signal with amplitude in voltage and time in seconds.
In Figure 10, the signal without acquisition offset is presented. 


 Figure 10. Spirometry signal without offset, with amplitude in pressure and time in seconds.
 In Figure 11, graph shows one ventilatory cycle with amplitude in voltage and time in seconds.
 Figure 11. Spirometry signal of  one ventilatory cycle, with amplitude in pressure and time in seconds.
 In Figure 12, graph shows one ventilatory cycle with amplitude in pressure and time in seconds.
 Figure 12. Spirometry signal of  one ventilatory cycle, with amplitude in pressure and time in seconds.
  
In Figure 13, there can be observed the curve of one ventilatory cycle with amplitude in flow and time in seconds. 

 Figure 13. Spirometry signal of  one ventilatory cycle, with amplitude in flow and time in seconds.
 In Figure 14, there can be observed the curve of one ventilatory cycle with amplitude in volume and time in seconds. 
 

 Figure 14. Spirometry signal of  one ventilatory cycle, with amplitude in flow and time in seconds.
 In Figure 15, there can be observed the curve of one ventilatory cycle with amplitude in flow against volume. 
 Figure 14. Spirometry signal of  one ventilatory cycle, with amplitude in flow against  flow.
Complete digital processing allows getting a similar result to the next, presented in Figure 15.
  
Figure 15. Graphic User Interface with result of processing one spirometry. 
The following link shows the working prototype:


Conclusions

Biomedical instrumentation, as a branch of biomedical engineering, is constantly facing the challenge of developing and implementing techniques and technologies that fit the needs of clinical practice and improve its quality.
From the measurement of a physical phenomenon it is possible to register others by indirect calculation.
It is important to take care that each stage works, the mechanical phase, the electronic phase and the processing phase.






No hay comentarios:

Publicar un comentario