diff --git "a/IMPETOM-Cl\303\255nico/Interfaz.py" "b/IMPETOM-Cl\303\255nico/Interfaz.py"
new file mode 100644
index 0000000000000000000000000000000000000000..15d7e0249d058019b4d116ba782754727b8c4ab1
--- /dev/null
+++ "b/IMPETOM-Cl\303\255nico/Interfaz.py"
@@ -0,0 +1,1162 @@
+import threading
+import time
+import tkinter.ttk
+from tkinter import *
+from tkinter import messagebox
+from PIL import Image, ImageTk
+from _datetime import date
+import re
+from ImpetomC import ImpetomC
+from ImpetomCError import ImpetomCError
+from ImpetomCElectrodeError import ImpetomCElectrodeError
+from datetime import datetime
+import winsound
+
+"""
+Clase que genera la interfaz gráfica de la aplicación
+"""
+
+"""
+Variables globales de la aplicación
+"""
+
+arduinoImpetom = 0 # 0 indica arduinoImpetom desconectado, 1 indica que esta conectado
+Reconstruir = False
+mode = "Setup"
+img = Image.open('imagenInicial.jpg')
+sclRangeEnable = False
+
+"""
+Funciones para validación de datos de entrada
+"""
+
+def validateName():
+    """
+    Funcion que valida el nombre del paciente ingresado
+    :return: 0 si existe algun error, 1 si el nombre es correcto (el campo lblNameError no esta vacio)
+    """
+
+    ret=0
+    patName = txtName.get("1.0", END)
+    if len(patName) <=1 :
+        lblNameError.config(text="Este campo no puede estar vacío")
+    else:
+        ret=1
+        lblNameError.config(text="")
+    return ret
+
+def validateCI():
+    """
+    Funcion que valida la CI del paciente ingresado
+    :return: 0 si existe algun error, 1 si la CI es correcta (el campo lblNameError no esta vacio)
+    """
+
+    ret = 0
+    patCi = txtCi.get("1.0", END).strip("\n")
+    lenCI=len(patCi)
+    if not re.match('^[0-9]*$',patCi):
+        lblCiError.config(text="La CI solo puede contener números")
+    elif lenCI <= 6 or lenCI > 8:
+        lblCiError.config(text="CI inválida")
+    else:
+        ret = 1
+        lblCiError.config(text="")
+    return ret
+
+def arduinoImpetomConected():
+    """
+    Funcion que verifica que el dispositivoImpetomC esta conectado
+    :return: 0 si existe algun error, 1 si no
+    """
+
+    ret = 1
+    global arduinoImpetom
+    if arduinoImpetom == 0:
+        try:  # Verifico que haya un arduino conectado al equipo al iniciar y si es el arduino de ImpetomC
+            ImpetomC.startUp()
+            arduinoImpetom = 1  # indicador que arduino Impetom está conectado
+            lblError.config(text="", bg='white')
+        except ImpetomCError as e:
+            lblError.config(text=str(e), bg='white')
+            arduinoImpetom = 0
+            ret = 0
+    return ret
+
+def validateSexoBiologico():
+    """
+    Funcion que valida el sexp biologico del paciente ingresado
+    :return: 0 si existe algun error, 1 si no
+    """
+
+    ret = 0
+    patSex = cmbBioSex.get().lower()
+    if patSex == "seleccionar":
+        lblBioSexError.config(text="Seleccione una opción válida")
+    else:
+        lblBioSexError.config(text="")
+        ret = 1
+    return ret
+
+def validateBirthDate():
+    """
+    Funcion que valida la fecha de nacimiento del paciente ingresado
+    :return: 0 si existe algun error, 1 si no
+    """
+
+    ret = 0
+    txtBDate = str(txtBirthDate.get("1.0", 'end-1c'))
+    try:
+        datetime.strptime(txtBDate, "%d-%m-%Y")
+        lblBirthDateError.config(text="")
+        ret = 1
+    except ValueError:
+        lblBirthDateError.config(text="La fecha debe ser dd-mm-yyyy")
+    finally:
+        return ret
+
+def validateMedida():
+    """
+    Función que valida la entrada de los datos de medida de circunferencia del tórax,
+    El dato debe ser un número entre 100 y 2000mm
+    """
+
+    ret = 0
+    fantomaMed = txtMedida.get("1.0", END).strip("\n")
+    lenFantomaMed = len(fantomaMed)
+    if not re.match('^[0-9]*$', fantomaMed):
+        lblMedidaError.config(text="Este campo solo puede contener números positivos")
+    elif lenFantomaMed <= 2:  # Verifico que el número sea mayor que 100 mm
+        lblMedidaError.config(text="El perímetro debe ser mayor o igual a 100 mm")
+    elif lenFantomaMed >= 5:
+        lblMedidaError.config(text="El perímetro es demasiado grande")
+    else:
+        ret = 1
+        lblMedidaError.config(text="")
+        if lenFantomaMed == 4:
+            intFantomaMed = int(fantomaMed)
+            if intFantomaMed >= 2000:
+                lblMedidaError.config(text="El perímetro es demasiado grande")
+                ret = 0
+
+    return ret
+
+def validateMedidaZ():
+    """
+    Función que valida la altura de colocación del cinturon, debe estar entre 10 mm y 999mm
+    """
+
+    ret = 0
+    fantomaMedZ = txtMedidaZ.get("1.0", END).strip("\n")
+    fantomaMedZ = fantomaMedZ.strip("-")  # Para validar ints > 0 y < 0 con la misma regExp
+    lenFantomaMedZ = len(fantomaMedZ)
+    lblMedidaZError.place(x=(265 / 1200) * screenWidth, y=(560 / 750) * screenHeight)
+    if not re.match('^[0-9]*$', fantomaMedZ):
+        lblMedidaZError.config(
+            text="La altura de colocación del cinturón debe ser un número entero medido desde la apófisis del esternón")
+    elif lenFantomaMedZ < 1 or lenFantomaMedZ > 3:  #
+        lblMedidaZError.config(text="La referencia de altura no es válida")
+    else:
+        ret = 1
+        lblMedidaZError.config(text="")
+    return ret
+
+"""
+Eventos para botones Start y Stop
+"""
+
+def btnStartClicked():
+    """
+    Evento del botón start
+    """
+
+    global Reconstruir, arduinoImpetom
+    if validateName() +validateCI() + arduinoImpetomConected() + validateSexoBiologico() + validateBirthDate() + validateMedida() + validateMedidaZ() == 7:
+        Reconstruir = True
+        txtMedida.config(state='disable')
+        txtMedidaZ.config(state='disable')
+        txtName.config(state='disable')
+        txtCi.config(state='disable')
+        btnIncTime.config(state='disable')
+        btnIncTime2.config(state='disable')
+        btnDecTime.config(state='disable')
+        btnDecTime2.config(state='disable')
+        btnStart.config(state='disable')
+        lblTimeError.config(text="Presione Stop para cambiar esta opción")
+        btnReconstruccion.config(state='disable')
+        btnSetup.config(state='disable')
+        cmbModel.config(state='disable')
+        lblModeMessage.config(text='Presione Stop para cambiar esta opción')
+        btnCalibrar.config(state='disable')
+        btnReset.config(state='disable')
+        threading.Thread(target=reloadImage).start()
+
+
+def btnStopClicked():
+    """
+    Evento del botón Stop
+    """
+
+    global Reconstruir
+    Reconstruir = False
+    time.sleep(4)
+    txtMedida.config(state='normal')
+    txtMedidaZ.config(state='normal')
+    txtName.config(state='normal')
+    txtCi.config(state='normal')
+    btnIncTime.config(state='normal')
+    btnIncTime2.config(state='normal')
+    btnDecTime.config(state='normal')
+    btnDecTime2.config(state='normal')
+    btnStart.config(state='normal')
+    btnStop.config(state='disable')
+    lblTimeError.config(text="")
+    lblModeMessage.config(text='')
+    btnCalibrar.config(state='normal')
+    btnReset.config(state='normal')
+    if mode == "Setup":
+        btnReconstruccion.config(state='normal')
+    else:
+        btnSetup.config(state='normal')
+    cmbModel.config(state='readonly')
+
+def btnResetClicked():
+    """
+    Evento para el botón reset
+    """
+
+    global img, photo
+    lblDate.config(text="Fecha:      " + str(date.today().strftime("%b-%d-%Y")))
+    btnReset.config(state='disable')
+    ImpetomC.reset()
+    img = Image.open('imagenInicial.jpg')
+    photo = ImageTk.PhotoImage(img)
+    lblImg.config(text="", image=photo, width=(700 / 1200) * screenWidth, height=(500 / 750) * screenHeight)
+    cmbModel.current(0)
+    lblpRangeValue.config(text=initialPValue)
+    lblGananciaValue.config(text=initialGValue)
+    lblVmaxValue.config(text=initialVmaxValue)
+    lblVminValue.config(text=initialVminValue)
+    lblSaveTimeValue.config(text=initialSaveTimeValue)
+    lblError.config(text="", bg="white")
+    btnSetupClicked()
+    rbtnSclOptionsDisable.select()
+    if tkinter.messagebox.askyesno("Reset", "Desea también eliminar los datos del paciente?"):
+        txtName.delete("1.0", "end")
+        txtCi.delete("1.0", "end")
+        txtMedida.delete("1.0", "end")
+        txtMedidaZ.delete("1.0", "end")
+        txtBirthDate.delete("1.0", "end")
+        cmbBioSex.current(0)
+
+"""
+Esta función se encarga de actualizar las imágenes en lblImg 
+"""
+
+def reloadImage():
+    """
+    Esta funcion es la encargada de actualizar las imagenes en la etiqueta lblImg
+    """
+
+    global img, photo, arduinoImpetom, Reconstruir, bpWeight, screenWidth, sclRangeEnable, mode
+    ti = time.time()
+    while Reconstruir:
+        try:
+            medida = txtMedida.get("1.0", END).strip("\n")
+            medidaZ = txtMedidaZ.get("1.0", END).strip("\n")
+            vmax = float(lblVmaxValue.cget("text"))
+            vmin = float(lblVminValue.cget("text"))
+            pvalue = round(float(lblpRangeValue.cget("text")), 2)
+            frecValue = str(30000 - int(lblGananciaValue.cget("text")) * 100)
+            shape = cmbModel.get().lower()
+            pacBDate = str(datetime.strptime(txtBirthDate.get("1.0", 'end-1c'), "%d-%m-%Y").strftime("%Y%m%d"))
+            pacSex = cmbBioSex.get()
+            ImpetomC.generarImagenTomografica(vmax=vmax, screenWidth=screenWidth, sclEnable=sclRangeEnable, vmin=vmin,
+                                              mode=mode, shape=shape, p=pvalue, frecuenciaDDS=frecValue)
+            tf = time.time()
+            elapsedTime = int(tf - ti)
+            img = Image.open('IMG.jpg')
+            photo = ImageTk.PhotoImage(img)
+            lblImg.config(text="", image=photo)
+            lblError.config(text="", bg='#2b70e4')
+            if elapsedTime > int(float(lblSaveTimeValue.cget('text')) * 60):  # Conversión de minutos a segundos
+                ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END),
+                                                        pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex,
+                                                        pacBirthDate=pacBDate, medida=medida, shape=shape,
+                                                        medidaZ=medidaZ, mode=mode)
+                ti = time.time()
+            if Reconstruir:
+                btnStop.config(state='normal')
+        except ImpetomCError as e:  # errores por problemas de conexion del dispositivo Arduino
+            lblError.config(text=str(e) + " Por favor verifique la conexión y presione start nuevamente", bg='white')
+            winsound.Beep(440, 500)
+            Reconstruir = False
+            arduinoImpetom = 0  # arduino ImpetomC no está conectado
+            btnStopClicked()
+            ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END),
+                                                    pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex,
+                                                    pacBirthDate=pacBDate, medida=medida, shape=shape, medidaZ=medidaZ,
+                                                    mode=mode)
+        except ImpetomCElectrodeError as e:  # Errores detectados sobre los electrodos
+            lblError.config(text=str(e), bg='white', fg='#f00')
+            tf = time.time()
+            elapsedTime = int(tf - ti)
+            img = Image.open('IMG.jpg')
+            photo = ImageTk.PhotoImage(img)
+            lblImg.config(text="", image=photo)
+            if e.regularGanancia and elapsedTime > int(float(lblSaveTimeValue.cget(
+                    'text')) * 60):  # Para errores de regular ganancia se guarda la imágen, si son errores de falso contacto no se guarda la imágen
+                ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END),
+                                                        pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex,
+                                                        pacBirthDate=pacBDate, medida=medida, shape=shape,
+                                                        medidaZ=medidaZ, mode=mode)
+                ti = time.time()
+            elif not e.regularGanancia:
+                winsound.Beep(440, 500)
+            if Reconstruir:
+                btnStop.config(state='normal')
+        except RuntimeError:  # Se esta recontruyendo la imagen y se presiona el botón de salir
+            time.sleep(5)
+            root.destroy()
+
+"""
+Funciones botones p del jac
+"""
+maxPValue = 0.9
+minPValue = 0.05
+def incPRange():
+    """
+    Evento del boton ">" de p
+    """
+
+    enableDecpRange()
+    pRangeValue = float(lblpRangeValue.cget("text"))
+    pRangeValue += 0.01
+    if pRangeValue >= maxPValue:
+        pRangeValue = maxPValue
+        disbleIncpRange()
+    lblpRangeValue.config(text=str(round(pRangeValue,2)))
+
+def incPRange2():
+    """
+    Evento del boton ">>" de p
+    """
+
+    enableDecpRange()
+    pRangeValue = float(lblpRangeValue.cget("text"))
+    pRangeValue += 0.1
+    if pRangeValue >= maxPValue:
+        pRangeValue = maxPValue
+        disbleIncpRange()
+    lblpRangeValue.config(text=str(round(pRangeValue,2)))
+
+def decPRange():
+    """
+    Evento del boton "<" de p
+    """
+
+    enableIncpRange()
+    pRangeValue = float(lblpRangeValue.cget("text"))
+    pRangeValue -= 0.01
+    if pRangeValue <= minPValue:
+        pRangeValue = minPValue
+        disableDecpRange()
+    lblpRangeValue.config(text=str(round(pRangeValue,2)))
+
+def decPRange2():
+    """
+    Evento del boton "<<" de p
+    """
+
+    enableIncpRange()
+    pRangeValue = float(lblpRangeValue.cget("text"))
+    pRangeValue -= 0.1
+    if pRangeValue <= minPValue:
+        pRangeValue = minPValue
+        disableDecpRange()
+    lblpRangeValue.config(text=str(round(pRangeValue,2)))
+
+def enableIncpRange():
+    """
+    Permite habilitar los botones ">>" y ">" de p
+    """
+
+    btnIncpRange.config(state="normal")
+    btnIncpRange2.config(state="normal")
+
+def enableDecpRange():
+    """
+    Permite habilitar los botones "<" y "<<" de p
+    """
+
+    btnDecpRange.config(state="normal")
+    btnDecpRange2.config(state="normal")
+
+def disbleIncpRange():
+    """
+    Permite deshabilitar los botones ">>" y ">" de p
+    """
+
+    btnIncpRange.config(state="disable")
+    btnIncpRange2.config(state="disable")
+
+def disableDecpRange():
+    """
+        Permite deshabilitar los botones "<" y "<<" de p
+    """
+
+    btnDecpRange.config(state="disable")
+    btnDecpRange2.config(state="disable")
+
+"""
+Eventos de los botones para el manejo de la ganancia
+"""
+
+maxGananciaValue = 5
+minGananciaValue = -20
+
+def incGanancia():
+    """
+        Evento del boton ">" de la ganancia del sistema
+    """
+
+    enableDecGanancia()
+    gananciaValue = int(lblGananciaValue.cget("text"))
+    gananciaValue += 1
+    if gananciaValue >= maxGananciaValue:
+        gananciaValue = maxGananciaValue
+        disableIncGanancia()
+    lblGananciaValue.config(text=gananciaValue)
+
+def incGanancia2():
+    """
+        Evento del boton ">>" de la ganancia del sistema
+    """
+
+    enableDecGanancia()
+    gananciaValue = int(lblGananciaValue.cget("text"))
+    gananciaValue += 5
+    if gananciaValue >= maxGananciaValue:
+        gananciaValue = maxGananciaValue
+        disableIncGanancia()
+    lblGananciaValue.config(text=gananciaValue)
+
+def decGanancia():
+    """
+    Evento del boton "<" de la ganancia del sistema
+    """
+
+    enableIncGanancia()
+    gananciaValue = int(lblGananciaValue.cget("text"))
+    gananciaValue -= 1
+    if gananciaValue <= minGananciaValue:
+        gananciaValue =minGananciaValue
+        disableDecGanancia()
+    lblGananciaValue.config(text=gananciaValue)
+
+def decGanancia2():
+    """
+    Evento del boton "<<" de la ganancia del sistema
+    """
+
+    enableIncGanancia()
+    gananciaValue = int(lblGananciaValue.cget("text"))
+    gananciaValue -= 5
+    if gananciaValue <= minGananciaValue:
+        gananciaValue = minGananciaValue
+        disableDecGanancia()
+    lblGananciaValue.config(text=gananciaValue)
+
+def enableIncGanancia():
+    """
+    Permite habilitar los botones ">>" y ">" de ganancia
+    """
+
+    btnIncGanancia.config(state="normal")
+    btnIncGanancia2.config(state="normal")
+
+def enableDecGanancia():
+    """
+    Permite habilitar los botones "<<" y "<" de ganancia
+    """
+
+    btnDecGanancia.config(state="normal")
+    btnDecGanancia2.config(state="normal")
+
+def disableIncGanancia():
+    """
+    Permite deshabilitar los botones ">>" y ">" de ganancia
+    """
+
+    btnIncGanancia.config(state="disable")
+    btnIncGanancia2.config(state="disable")
+
+def disableDecGanancia():
+    """
+    Permite deshabilitar los botones "<<" y "<" de ganancia
+    """
+
+    btnDecGanancia.config(state="disable")
+    btnDecGanancia2.config(state="disable")
+
+"""
+Funciones botones para el valor de Vmax
+"""
+
+maxVMAXvalue = 5
+minVMAXvalue = -20
+
+def incVmax():
+    """
+    Evento del boton ">" de vmax
+    """
+
+    enableDecVmax()
+    vmaxValue = float(lblVmaxValue.cget("text"))
+    vmaxValue += 0.1
+    if vmaxValue >= maxVMAXvalue:
+        vmaxValue = maxVMAXvalue
+        disableIncVmax()
+    lblVmaxValue.config(text=str(round(vmaxValue,1)))
+
+def incVmax2():
+    """
+    Evento del boton ">>" de vmax
+    """
+
+    enableDecVmax()
+    vmaxValue = float(lblVmaxValue.cget("text"))
+    vmaxValue += 1
+    if vmaxValue >= maxVMAXvalue:
+        vmaxValue = maxVMAXvalue
+        disableIncVmax()
+    lblVmaxValue.config(text=str(round(vmaxValue,1)))
+
+def decVmax():
+    """
+    Evento del boton "<" de vmax
+    """
+    enableIncVmax()
+    vmaxValue = float(lblVmaxValue.cget("text"))
+    vmaxValue -= 0.1
+    if vmaxValue <= minVMAXvalue:
+        vmaxValue = minVMAXvalue
+        disableDecVmax()
+    if vmaxValue > float(lblVminValue.cget("text")):
+        lblVmaxValue.config(text=str(round(vmaxValue,1)))
+
+def decVmax2():
+    """
+    Evento del boton "<<" de vmax
+    """
+
+    enableIncVmax()
+    vmaxValue = float(lblVmaxValue.cget("text"))
+    vmaxValue -= 1
+    if vmaxValue <= minVMAXvalue:
+        vmaxValue = minVMAXvalue
+        disableDecVmax()
+    if vmaxValue > float(lblVminValue.cget("text")):
+        lblVmaxValue.config(text=str(round(vmaxValue,1)))
+
+def enableIncVmax():
+    """
+    Permite habilitar los botones ">>" y ">" de vmax
+    """
+
+    btnIncVmax.config(state="normal")
+    btnIncVmax2.config(state="normal")
+
+def enableDecVmax():
+    """
+    Permite habilitar los botones "<<" y "<" de vmax
+    """
+
+    btnDecVmax.config(state="normal")
+    btnDecVmax2.config(state="normal")
+
+def disableIncVmax():
+    """
+    Permite deshabilitar los botones ">>" y ">" de vmax
+    """
+
+    btnIncVmax.config(state="disable")
+    btnIncVmax2.config(state="disable")
+
+def disableDecVmax():
+    """
+    Permite deshabilitar los botones "<<" y "<" de vmax
+    """
+
+    btnDecVmax.config(state="disable")
+    btnDecVmax2.config(state="disable")
+
+"""
+Funciones botones para el valor de Vmin
+"""
+
+maxVMINValue = 0
+minVMINValue = -40
+
+def incVmin():
+    """
+    Evento del boton ">" de vmin
+    """
+
+    enableDecVmin()
+    VminValue = float(lblVminValue.cget("text"))
+    VminValue += 0.1
+    if VminValue >= maxVMINValue:
+        VminValue = maxVMINValue
+        disableIncVmin()
+    if VminValue < float(lblVmaxValue.cget("text")):
+        lblVminValue.config(text=str(round(VminValue,1)))
+
+def incVmin2():
+    """
+    Evento del boton ">>" de vmin
+    """
+
+    enableDecVmin()
+    VminValue = float(lblVminValue.cget("text"))
+    VminValue += 1
+    if VminValue >= maxVMINValue:
+        VminValue = maxVMINValue
+        disableIncVmin()
+    if VminValue < float(lblVmaxValue.cget("text")):
+        lblVminValue.config(text=str(round(VminValue,1)))
+
+def decVmin():
+    """
+    Evento del boton "<" de vmin
+    """
+
+    enableIncVmin()
+    VminValue = float(lblVminValue.cget("text"))
+    VminValue -= 0.1
+    if VminValue <= minVMINValue:
+        VminValue = minVMINValue
+        disableDecVmin()
+    lblVminValue.config(text=str(round(VminValue,1)))
+
+def decVmin2():
+    """
+    Evento del boton "<<" de vmin
+    """
+
+    enableIncVmin()
+    VminValue = float(lblVminValue.cget("text"))
+    VminValue -= 1
+    if VminValue <= minVMINValue:
+        VminValue = minVMINValue
+        disableDecVmin()
+    lblVminValue.config(text=str(round(VminValue,1)))
+
+def enableIncVmin():
+    """
+    Permite habilitar los botones ">>" y ">" de vmin
+    """
+
+    btnIncVmin.config(state="normal")
+    btnIncVmin2.config(state="normal")
+
+def enableDecVmin():
+    """
+    Permite habilitar los botones "<<" y "<" de vmin
+    """
+
+    btnDecVmin.config(state="normal")
+    btnDecVmin2.config(state="normal")
+
+def disableIncVmin():
+    """
+    Permite deshabilitar los botones ">>" y ">" de vmin
+    """
+
+    btnIncVmin.config(state="disable")
+    btnIncVmin2.config(state="disable")
+
+def disableDecVmin():
+    """
+    Permite deshabilitar los botones "<<" y "<" de vmin
+    """
+
+    btnDecVmin.config(state="disable")
+    btnDecVmin2.config(state="disable")
+
+
+"""
+Funciones para actualizar el modo (Reconstruction o Setup) en pantalla
+"""
+
+def btnReconstruccionClicked():
+    """
+    Evento del boton modo Reconstruccion
+    """
+
+    global mode
+    mode = "Reconstruccion"
+    lblModeValue.config(text="Reconstrucción")
+    btnReconstruccion.config(state='disabled')
+    btnSetup.config(state='normal')
+
+def btnSetupClicked():
+    """
+    Evento del boton modo Setup
+    """
+    global mode
+    mode = "Setup"
+    lblModeValue.config(text=mode)
+    btnReconstruccion.config(state='normal')
+    btnSetup.config(state='disabled')
+
+"""
+Funciones para obtener el vector de datos homogéneo
+"""
+
+def calibrar():
+    """
+    Evento del boton calibrar
+    """
+    ImpetomC.actualizarVectorDeDatosHomogeneo()
+    btnReset.config(state="normal")
+
+"""
+Funciones botones Saved Timed
+"""
+
+maxTimeValue= 120
+minTimeValue = 0.5
+def incTime():
+    """
+    Evento del boton ">" de tiempo entre imagenes guardadas
+    """
+
+    enableDecTime()
+    timeValue = float(lblSaveTimeValue.cget("text"))
+    if timeValue == minTimeValue:
+      timeValue = 1
+    else:
+        timeValue += 1
+    if timeValue >= maxTimeValue:
+        timeValue = maxTimeValue
+        disbleIncTime()
+    lblSaveTimeValue.config(text=str(round(timeValue)))
+
+def incTime2():
+    """
+    Evento del boton ">>" de tiempo entre imagenes guardadas
+    """
+
+    enableDecTime()
+    timeValue = float(lblSaveTimeValue.cget("text"))
+    if timeValue == minTimeValue:
+        timeValue = 5
+    else:
+        timeValue += 5
+    if timeValue >= maxTimeValue:
+        timeValue = maxTimeValue
+        disbleIncTime()
+    lblSaveTimeValue.config(text=str(round(timeValue)))
+
+def decTime():
+    """
+    Evento del boton "<" de tiempo entre imagenes guardadas
+    """
+
+    enableIncTime()
+    timeValue = float(lblSaveTimeValue.cget("text"))
+    timeValue -= 1
+    if timeValue < minTimeValue:
+        timeValue = minTimeValue
+        lblSaveTimeValue.config(text=str(round(timeValue,1)))
+        disableDecTime()
+    else:
+        lblSaveTimeValue.config(text=str(round(timeValue)))
+
+def decTime2():
+    """
+    Evento del boton "<<" de tiempo entre imagenes guardadas
+    """
+
+    enableIncTime()
+    timeValue = float(lblSaveTimeValue.cget("text"))
+    timeValue -= 5
+    if timeValue < minTimeValue:
+        timeValue = minTimeValue
+        lblSaveTimeValue.config(text=str(round(timeValue,1)))#redondea para colocar 0.5 en pantalla
+        disableDecTime()
+    else:
+        lblSaveTimeValue.config(text=str(round(timeValue)))
+
+def enableIncTime():
+    """
+    Permite habilitar los botones ">>" y ">" del tiempo entre imagenes guardadas
+    """
+
+    btnIncTime.config(state="normal")
+    btnIncTime2.config(state="normal")
+
+def enableDecTime():
+    """
+    Permite habilitar los botones "<<" y "<" del tiempo entre imagenes guardadas
+    """
+
+    btnDecTime.config(state="normal")
+    btnDecTime2.config(state="normal")
+
+def disbleIncTime():
+    """
+    Permite deshabilitar los botones ">>" y ">" del tiempo entre imagenes guardadas
+    """
+    btnIncTime.config(state="disable")
+    btnIncTime2.config(state="disable")
+
+def disableDecTime():
+    """
+    Permite deshabilitar los botones "<<" y "<" del tiempo entre imagenes guardadas
+    """
+
+    btnDecTime.config(state="disable")
+    btnDecTime2.config(state="disable")
+
+
+"""
+Funciones de los radioButtons de BP
+"""
+
+def enableScaleOptions():
+    """
+    Evento del radio button para habilitar las opciones del rango de escala
+    """
+
+    global sclRangeEnable
+    sclRangeEnable = True
+    enableIncVmin()
+    enableIncVmax()
+    enableDecVmin()
+    enableDecVmax()
+
+
+def disableScaleOptions():
+    """
+    Evento del radio button para deshabilitar las opciones del rango de escala
+    """
+
+    global sclRangeEnable
+    sclRangeEnable = False
+    disableDecVmin()
+    disableDecVmax()
+    disableIncVmax()
+    disableIncVmin()
+
+"""
+Función para el control del evento de cierre de la aplicación
+"""
+
+def onClose():
+    """
+    Evento de cierre de la aplicacion
+    """
+    if tkinter.messagebox.askyesno("Salir","Está seguro que desea salir?"):
+        global Reconstruir
+        if Reconstruir:
+            Reconstruir=False
+            time.sleep(5)# esto es para que pueda finalizar el programa sin tirar error. Es por si se cierra el programa, con el programa updeteando la imagen
+        root.destroy()
+
+"""
+Armado de la interfaz
+Como nota general, se uso para la escala de la pantalla 1200 (width) y 750 (height), por eso se ven esos números en todo el código de aquí en más.
+Esto es porque para la versión incial de la interfaz se utilizó una con ese tamaño y se logró colocar todos los widgets quedando la interfaz agradable a la vista
+"""
+
+if __name__ == '__main__':
+
+    root = Tk()
+    root.title("Impetom-C app")
+    screenWidth = root.winfo_screenwidth()
+    screenHeight = root.winfo_screenheight()
+    rootSize = str(screenWidth) + "x" + str(screenHeight)
+    root.geometry(rootSize)
+
+    root.protocol("WM_DELETE_WINDOW", onClose)  # manejo del evento de cierre por la cruz de la interfaz
+    root.resizable(width=False, height=False)  # el usuario no puede cambiar el tamaño de la ventana
+
+    """
+    Info Impetom + logo fing
+    """
+
+    # Se agrega imagen de fondo de la app
+    bg = PhotoImage(file="fondo_Impetom.png")  # color azul fondo #2b70e4 amarillo #eccc6e
+    # Create Canvas
+    canvas1 = Canvas(root, width=screenWidth, height=screenHeight)
+    canvas1.place(x=0, y=0)
+    canvas1.create_image((0 / 1200) * screenWidth, 0, image=bg, anchor="nw")
+
+    """
+    Datos del paciente
+    #f00 es el color rojo para cualquier SO
+    """
+    lblPatient = Label(root, text="Datos del paciente", bg='#2b70e4', fg='white', font=("Helvetica", 12, "bold"))
+    lblPatient.place(x=(30 / 1200) * screenWidth, y=(20 / 750) * screenHeight)
+
+    lblDate = Label(root, text="Fecha:      " + str(date.today().strftime("%b-%d-%Y")), bg='#2b70e4', fg='white',
+                    font=("Helvetica", 10, "bold"))
+    lblDate.place(x=(330 / 1200) * screenWidth, y=(20 / 750) * screenHeight)
+
+    lblName = Label(root, text="Nombre:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold"))
+    lblName.place(x=(50 / 1200) * screenWidth, y=(50 / 750) * screenHeight)
+    txtName = Text(root, width=30, height=1)
+    txtName.place(x=(105 / 1200) * screenWidth, y=(50 / 750) * screenHeight)
+    lblNameError = Label(root, fg='red', text="Este campo es obligatorio", bg='#2b70e4', font=("Helvetica", 8, "bold"))
+    lblNameError.place(x=(100 / 1200) * screenWidth, y=(75 / 750) * screenHeight)
+
+    lblCi = Label(root, text="CI:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold"))
+    lblCi.place(x=(50 / 1200) * screenWidth, y=(100 / 750) * screenHeight)
+    txtCi = Text(root, width=15, height=1)
+    txtCi.place(x=(100 / 1200) * screenWidth, y=(100 / 750) * screenHeight)
+    lblCiError = Label(root, fg='red', text="Este campo es obligatorio", bg='#2b70e4', font=("Helvetica", 8, "bold"))
+    lblCiError.place(x=(100 / 1200) * screenWidth, y=(125 / 750) * screenHeight)
+
+    lblSexoBiologico = Label(root, text="Sexo:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold"))
+    lblSexoBiologico.place(x=(310 / 1200) * screenWidth, y=(50 / 750) * screenHeight)
+    cmbBioSex = tkinter.ttk.Combobox(root, values=['Seleccionar', 'M', 'F', 'Otro'], state='readonly', width=10)
+    cmbBioSex.place(x=(350 / 1200) * screenWidth, y=(50 / 750) * screenHeight)
+    lblBioSexError = Label(root, text="Este campo es obligatorio", fg='red', bg='#2b70e4', font=("Helvetica", 8, "bold"))
+    lblBioSexError.place(x=(315 / 1200) * screenWidth, y=(75 / 750) * screenHeight)
+    cmbBioSex.current(0)
+
+    lblBirthDate = Label(root, text="Fecha de nacimiento:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold"))
+    lblBirthDate.place(x=(215 / 1200) * screenWidth, y=(100 / 750) * screenHeight)
+    txtBirthDate = Text(root, width=10, height=1)
+    txtBirthDate.place(x=(350 / 1200) * screenWidth, y=(100 / 750) * screenHeight)
+    lblBirthDateError = Label(root, text="Formato : dd-mm-yyyy", fg='red', bg='#2b70e4', font=("Helvetica", 8, "bold"))
+    lblBirthDateError.place(x=(315 / 1200) * screenWidth, y=(125 / 750) * screenHeight)
+
+    """
+    Imagen inicial en la app
+    """
+
+    photo = ImageTk.PhotoImage(img)
+    lblImg = Label(root, image=photo, width=(700 / 1200) * screenWidth, height=(500 / 750) * screenHeight)
+    lblImg.place(x=(445 / 1200) * screenWidth, y=(175 / 750) * screenHeight)
+
+    """
+    botones Start, Stop, Calibrar y Reset
+    """
+
+    btnStart = Button(root, text="Start", padx=15, pady=2, command=btnStartClicked)
+    btnStart.place(x=(1030 / 1200) * screenWidth, y=(690 / 750) * screenHeight)
+
+    btnStop = Button(root, text="Stop", padx=10, pady=2, command=btnStopClicked, state='disable')
+    btnStop.place(x=(1090 / 1200) * screenWidth, y=(690 / 750) * screenHeight)
+
+    btnCalibrar = Button(root, text="Calibrar", command=calibrar)
+    btnCalibrar.place(x=(400 / 1200) * screenWidth, y=(690 / 750) * screenHeight)
+
+    btnReset = Button(root, text="Reset", command=btnResetClicked, state='disable')
+    btnReset.place(x=(1100 / 1200) * screenWidth, y=(145 / 750) * screenHeight)
+
+    """
+    Control de modo de cambio de modo
+    """
+
+    lblMode = Label(root, text="Modo: ", bg='#2b70e4', font=("Helvetica", 12, "bold"))
+    lblMode.place(x=(140 / 1200) * screenWidth, y=(170 / 750) * screenHeight)
+    lblModeValue = Label(root, text=mode, bg='#2b70e4', font=("Helvetica", 12))
+    lblModeValue.place(x=(190 / 1200) * screenWidth, y=(170 / 750) * screenHeight)
+
+    btnReconstruccion = Button(root, text="Reconstrucción", command=btnReconstruccionClicked,
+                               font=("Helvetica", 10, "bold"))
+    btnReconstruccion.place(x=(110 / 1200) * screenWidth, y=(195 / 750) * screenHeight)
+
+    btnSetup = Button(root, text="Setup", padx=10, command=btnSetupClicked, state='disable', font=("Helvetica", 10, "bold"))
+    btnSetup.place(x=(210 / 1200) * screenWidth, y=(195 / 750) * screenHeight)
+
+    lblModeMessage = Label(root, fg='#f00', bg='white')
+    lblModeMessage.place(x=(80 / 1200) * screenWidth, y=(225 / 750) * screenHeight)
+
+    """
+    Opciones para la reconstrucción 
+    Primero el valor p
+    """
+    lblImgOptions = Label(root, text="Opciones de imagen", font=("Helvetica", 10, "bold"), bg='white')
+    lblImgOptions.place(x=(130 / 1200) * screenWidth, y=(245 / 750) * screenHeight)
+
+    lblp = Label(root, text="p", bg='white')
+    lblp.place(x=(177 / 1200) * screenWidth, y=(270 / 750) * screenHeight)
+    initialPValue = "0.2"
+    lblpRangeValue = Label(root, text=initialPValue, bg='white')  # p=0.25 para setup
+    lblpRangeValue.place(x=(175 / 1200) * screenWidth, y=(295 / 750) * screenHeight)
+
+    btnIncpRange = Button(root, text=">", command=incPRange)
+    btnIncpRange.place(x=(250 / 1200) * screenWidth, y=(295 / 750) * screenHeight)
+
+    btnIncpRange2 = Button(root, text=">>", command=incPRange2)
+    btnIncpRange2.place(x=(275 / 1200) * screenWidth, y=(295 / 750) * screenHeight)
+
+    btnDecpRange = Button(root, text="<", command=decPRange)
+    btnDecpRange.place(x=(100 / 1200) * screenWidth, y=(295 / 750) * screenHeight)
+
+    btnDecpRange2 = Button(root, text="<<", command=decPRange2)
+    btnDecpRange2.place(x=(67 / 1200) * screenWidth, y=(295 / 750) * screenHeight)
+
+    """
+    Control para la frecuencia (ganancia)
+    """
+    lblGanancia = Label(root, text="Ganancia", bg='white')
+    lblGanancia.place(x=(160 / 1200) * screenWidth, y=(330 / 750) * screenHeight)
+    initialGValue = "-10"
+    lblGananciaValue = Label(root, text=initialGValue, bg='white')
+    lblGananciaValue.place(x=(175 / 1200) * screenWidth, y=(355 / 750) * screenHeight)
+
+    btnIncGanancia = Button(root, text=">", command=incGanancia)
+    btnIncGanancia.place(x=(250 / 1200) * screenWidth, y=(355 / 750) * screenHeight)
+
+    btnIncGanancia2 = Button(root, text=">>", command=incGanancia2)
+    btnIncGanancia2.place(x=(275 / 1200) * screenWidth, y=(355 / 750) * screenHeight)
+
+    btnDecGanancia = Button(root, text="<", command=decGanancia)
+    btnDecGanancia.place(x=(100 / 1200) * screenWidth, y=(355 / 750) * screenHeight)
+
+    btnDecGanancia2 = Button(root, text="<<", command=decGanancia2)
+    btnDecGanancia2.place(x=(67 / 1200) * screenWidth, y=(355 / 750) * screenHeight)
+
+    """
+    Control del rango de escala
+    """
+
+    lblSclRangeOptions = Label(root, text="Control de rango de escala", font=("Helvetica", 10, "bold"), bg='white')
+    lblSclRangeOptions.place(x=(110 / 1200) * screenWidth, y=(400 / 750) * screenHeight)
+
+    rbtnSclOptionsEnable = Radiobutton(root, text="On", variable=0, value=1, command=enableScaleOptions, bg='white')
+    rbtnSclOptionsEnable.place(x=(280 / 1200) * screenWidth, y=(400 / 750) * screenHeight)
+
+    rbtnSclOptionsDisable = Radiobutton(root, text="Off", variable=0, value=2, command=disableScaleOptions, bg='white')
+    rbtnSclOptionsDisable.place(x=(320 / 1200) * screenWidth, y=(400 / 750) * screenHeight)
+    rbtnSclOptionsDisable.select()
+    """
+    Control Vmax
+    """
+
+    lblVmax = Label(root, text=" Valor máximo", bg='white')
+    lblVmax.place(x=(145 / 1200) * screenWidth, y=(425 / 750) * screenHeight)
+    initialVmaxValue = "0.5"
+    lblVmaxValue = Label(root, text=initialVmaxValue, bg='white')
+    lblVmaxValue.place(x=(175 / 1200) * screenWidth, y=(450 / 750) * screenHeight)
+
+    btnIncVmax = Button(root, text=">", command=incVmax)
+    btnIncVmax.place(x=(250 / 1200) * screenWidth, y=(450 / 750) * screenHeight)
+
+    btnIncVmax2 = Button(root, text=">>", command=incVmax2)
+    btnIncVmax2.place(x=(275 / 1200) * screenWidth, y=(450 / 750) * screenHeight)
+
+    btnDecVmax = Button(root, text="<", command=decVmax)
+    btnDecVmax.place(x=(100 / 1200) * screenWidth, y=(450 / 750) * screenHeight)
+
+    btnDecVmax2 = Button(root, text="<<", command=decVmax2)
+    btnDecVmax2.place(x=(67 / 1200) * screenWidth, y=(450 / 750) * screenHeight)
+
+    """
+    Control Vmin
+    """
+
+    lblVmin = Label(root, text=" Valor mínimo", bg='white')
+    lblVmin.place(x=(145 / 1200) * screenWidth, y=(480 / 750) * screenHeight)
+    initialVminValue = "-5.5"
+    lblVminValue = Label(root, text=initialVminValue, bg='white')
+    lblVminValue.place(x=(175 / 1200) * screenWidth, y=(510 / 750) * screenHeight)
+
+    btnIncVmin = Button(root, text=">", command=incVmin)
+    btnIncVmin.place(x=(250 / 1200) * screenWidth, y=(510 / 750) * screenHeight)
+
+    btnIncVmin2 = Button(root, text=">>", command=incVmin2)
+    btnIncVmin2.place(x=(275 / 1200) * screenWidth, y=(510 / 750) * screenHeight)
+
+    btnDecVmin = Button(root, text="<", command=decVmin)
+    btnDecVmin.place(x=(100 / 1200) * screenWidth, y=(510 / 750) * screenHeight)
+
+    btnDecVmin2 = Button(root, text="<<", command=decVmin2)
+    btnDecVmin2.place(x=(67 / 1200) * screenWidth, y=(510 / 750) * screenHeight)
+
+    """
+    Control del Modelo
+    """
+
+    lblContorno = Label(root, text="Especificaciones de contorno", font=("Helvetica", 10, "bold"), bg='white')
+    lblContorno.place(x=(110 / 1200) * screenWidth, y=(550 / 750) * screenHeight)
+
+    lblModel = Label(root, text="Forma", bg='white')
+    lblModel.place(x=(160 / 1200) * screenWidth, y=(575 / 750) * screenHeight)
+
+    cmbModel = tkinter.ttk.Combobox(root, values=['Thorax', 'Circle'], state='readonly')
+    cmbModel.place(x=(120 / 1200) * screenWidth, y=(600 / 750) * screenHeight)
+    cmbModel.current(0)  # el valor inicial de comboBox es Thorax
+
+    """
+    Control de Medida
+    """
+
+    lblMedida = Label(root, text="Perímetro (mm)", bg='white')
+    lblMedida.place(x=(260 / 1200) * screenWidth, y=(575 / 750) * screenHeight)
+
+    txtMedida = Text(root, width=4, height=1)
+    txtMedida.place(x=(280 / 1200) * screenWidth, y=(600 / 750) * screenHeight)
+
+    lblMedidaError = Label(root, text="Campo obligatorio", fg='#f00', bg='white')
+    lblMedidaError.place(x=(265 / 1200) * screenWidth, y=(620 / 750) * screenHeight)
+
+    """
+    Control de Medida_Z
+    """
+
+    lblMedidaZ = Label(root, text="Altura (mm)", bg='white')
+    lblMedidaZ.place(x=(350 / 1200) * screenWidth, y=(575 / 750) * screenHeight)
+
+    txtMedidaZ = Text(root, width=4, height=1)
+    txtMedidaZ.place(x=(360 / 1200) * screenWidth, y=(600 / 750) * screenHeight)
+
+    lblMedidaZError = Label(root, text="Campo obligatorio", fg='#f00', bg='white')
+    lblMedidaZError.place(x=(345 / 1200) * screenWidth, y=(550 / 750) * screenHeight)
+
+    """
+    Control de tiempos para guardado de imágenes para historia clínica
+    """
+
+    lblSaveTime = Label(root, text="Tiempo de guardado (min)", font=("Helvetica", 10, "bold"), bg='white')
+    lblSaveTime.place(x=(100 / 1200) * screenWidth, y=(635 / 750) * screenHeight)
+    initialSaveTimeValue = "5"
+    lblSaveTimeValue = Label(root, text=initialSaveTimeValue, bg='white')
+    lblSaveTimeValue.place(x=(175 / 1200) * screenWidth, y=(665 / 750) * screenHeight)
+
+    btnIncTime = Button(root, text=">", command=incTime)
+    btnIncTime.place(x=(250 / 1200) * screenWidth, y=(665 / 750) * screenHeight)
+
+    btnIncTime2 = Button(root, text=">>", command=incTime2)
+    btnIncTime2.place(x=(275 / 1200) * screenWidth, y=(665 / 750) * screenHeight)
+
+    btnDecTime = Button(root, text="<", command=decTime)
+    btnDecTime.place(x=(100 / 1200) * screenWidth, y=(665 / 750) * screenHeight)
+
+    btnDecTime2 = Button(root, text="<<", command=decTime2)
+    btnDecTime2.place(x=(67 / 1200) * screenWidth, y=(665 / 750) * screenHeight)
+
+    lblTimeError = Label(root, text="", fg='#f00', bg='white')
+    lblTimeError.place(x=(100 / 1200) * screenWidth, y=(700 / 750) * screenHeight)
+
+    """
+    Por problemas con Arduino al inicio de la aplicación
+    #2b70e4es el color azul de la imagen del banner
+    """
+
+    lblError = Label(root, text="", bg='#2b70e4', font=("Helvetica", 10, "bold"), fg="red")
+    lblError.place(x=(440 / 1200) * screenWidth, y=(150 / 750) * screenHeight)
+    disableScaleOptions()  # Comienzo el programa con la escala deshabilitada
+    try:
+        ImpetomC.startUp()
+        arduinoImpetom = 1  # Indicador que arduinoImpetom esta conectado
+    except ImpetomCError as e:
+        lblError.config(text=str(e) + " Revise la conexión al dispositivo y presione Start", bg='white')
+        arduinoImpetom = 0
+
+    root.mainloop()