Autor Tema: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#  (Leído 14407 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado washi_w_z_r

  • PIC10
  • *
  • Mensajes: 20
PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« en: 13 de Octubre de 2009, 15:34:27 »
Hola a todos, aqui les dejo una parte de mi proyecto de tesis, que trata del estudio de las ondas fotopletismograficas de un oximetro de pulso.

Para el presente proyecto nos enfocaremos en obtener las ondas fotopletismograficas de un oximetro de pulso, pero veamos algo de oximetria:

El oximetro de pulso monitorea de forma no invasiva la saturación de la hemoglobina arterial,  estos se basan en la absorción diferencial de la luz para determinar el porcentaje de saturación de oxigeno de la hemoglobina en la sangre arterial.

Para obtener esta absorción diferencial de la luz se utiliza un sensor que transmite dos longitudes de onda: Luz roja de 660nm  y Luz infrarroja de 905nm.

Observemos la siguiente figura 1:



Lo que haremos es incidir una luz (roja ó infrarroja) sobre el dedo indice de la mano izquierda, como muestra la figura 1,  del cual obtendremos las ondas fotopletismograficas.

La onda fotopletismografica del oximetro de pulso representa el cambio de volumen del flujo sanguíneo

La onda fotopletismografica del oximetro de pulso  en un órgano o extremidad  se ve afectada por muchas  variables, por ejemplo la luz ambiental, ruido, niveles anormales de hemoglobina, función del ritmo y promedio del pulso cardíaco, tez del paciente, movimiento no controlado del cuerpo, lo cual influye en el monitoreo y diagnostico del estado del paciente.

Estas ondas se muestran en la fig 2:



Teniendo esta pequeña introducción para el proyecto que a continuación  les presento, nuestros objetivos serán
      -   Diseñar un circuito capaz de recibir una señal através del fotodiodo detector
      -   Realizaremos Adaptación de señal proveniente del fotodiodo
      -   Realizaremos cálculos para diseñar los filtros analógicos
      -   Realizaremos una etapa de amplificación y suma se señal
      -   Realizaremos un programa en el pic18f4550 para adquirir datos analógicos y enviarlos mediante USB
      -   Finalmente realizaremos un programa que adquiera datos provenientes del PIC.
Antes de nada, usaremos :
    - Un sensor para adultos de la empresa DOLPHIN.
    - TL082 para las diferentes etapas( filtrado amplificacion y suma)
    - Una fuente ATX del cual obtendremos los voltajes simetricos +-12v para los opams, +5v para el pic
    - Un Pic18f4550
    - El programa C# 2005
    - Pickit 2, para programar el pic
    - Usaremos el lenguaje C para realizar el soft del pic

Empezeeeeeeemos  :-/ :

SEÑAL EN EL FOTODIODO RECEPTOR
La señal proveniente del fotodiodo produce una corriente que es función lineal de la intensidad de la luz, siendo esta corriente medida como densidad de potencia óptica incidente, para ello necesitaremos convertir esta “corriente” a voltaje, conseguiremos ello mediante un conversor de corriente a tensión:


Para obtener la resistencia Rf tenemos que definir cuanto deseamos obtener a la salida del OPAM, seria ideal obtener una señal entre 0v a 5v para efectos de la adquisición y conversión con el ADC del PIC,  veamos entonces:
      -   En primera instancia los OPAMS TL082 estarán alimentados con voltaje  de 0v (pìn4) y 5v (pin8).
      -   Esta alimentación produce una salida de 200mV con Rf =20M?.
      -¿Cómo halle esta resistencia?: de la siguiente manera:
Veamos el siguiente cuadro que nos da algunas caracteristicas del sensor:



como observamos en el esuqema del conversor de corriente a tension se tiene las siguientes ecuaciones:
Se tiene configuracion inversora por ello:



•   Se tiene que VD=0 , por ello:


•   Por otro lado para determinar la corriente que incide en el fotodiodo se tiene:
     o   La potencia producida por el fotodiodo es:

       

     o   La corriente producida por el diodo es:


   Consideramos una tensión de salida de 200mW, por ello se tiene:


•   Por ello escogemos una resistencia de 20MΩ (valor comercial), con lo que nuestro esquema será:



Siendo la alimentacion en los opams TL082 con una fuente simple,  y al ver experimentalmente que se atenua la señal a medida que esta entra en dichos filtros , ademas que si la etapa de filtrado es alta ( me refiero a etapas de mayor a 8vo orden) esta ateunara la señal, por ejm yo obtuve 2v a la salida del conversor V-I y a la salida de los filtros obtuve 200mv o menos en algunos casos.

Por ello se debe tener cuidado en colocar etapas de amplificacion ya que estas tambien amplifican tanto la señal DC como la señal AC en este caso.
-    ¿Porque  uso ±12V?, mas adelante veremos  que al usar filtros, estos atenúan la señal.
-   Bien ahora tenemos la señal vista en osciloscopio


De la figura anterior observamos que nuestra onda fotopletismografica esta "MODULADA" con otra frecuencia de 44khz, se ve claramente en la parte inferior es la onda que buscamos.
FILTROS ANALOGICOS
Observando la señal del fotodiodo en la cual se encuentra nuestra onda fotopletismografica.

Nuestro objetivo es obtener la onda fotopletismografica, sabemos que el cuerpo Humano produce una frecuencia de 60hz, la red eléctrica en Perú es de 60Hz, además si ampliamos la señal de la figura arriba mencionada vemos que nuestra onda esta modulada con otra de 44Khz.

Para eliminar estas frecuencias necesitamos realizar filtraje:

-   filtro pasa-altas: con el fin de eliminar la componente DC , la frecuencia de corte se fija en 0.5Hz
-   filtro pasa-bajas: con el fin de eliminar las frecuencias altas , la frecuencia de corte se fija en 3.5Hz
Bien como ya definimos las frecuenciaqs de corte , empezmos a diseñar los filtros analogicos, para ello usaremos la configuracion SALLEN KEY  veamos para un filtro pasa-baja de 2do orden:


Para un filtro pasa-alta de 2do orden:

Cuyas funciones de transferencia son:

Desconectado washi_w_z_r

  • PIC10
  • *
  • Mensajes: 20
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #1 en: 13 de Octubre de 2009, 17:04:33 »
Respectivamente, ahora bien la ventaja de esta configuración SALLEN KEY es que podemos colocar resistencias y capacitores de la  misma magnitud nominal y con ello  nos enfocamos en el denominador con el objetivo de igualarlo a cero obteniendo:


En ambos casos se obtiene una frecuencia de resonancia f0,  para el caso del filtro pasa altos se tiene:



Para las frecuencias anteriormente especificadas los valores de las resistencias son demasiadas altas del orden de los megaohm, ello trae la perdida de la señal.

Los valores que yo use son :
filtro pasa-altas 2do orden de: R= 150k y C=440nf (dos cap de 220nF de poliéster en paralelo),obteniendo  la siguiente señal:



filtro pasa-bajas 2do orden de: R= 360k y C=440nf (dos cap de 220nF de poliéster en paralelo),obteniendo  la siguiente señal:


Filtro pasa.altas de 8vo orden: R= 130k y C=440nf (dos cap de 220nF de poliéster en paralelo),obteniendo la siguiente señal:


Notas Aclaratorias:
- Al sensor se envia una señal para encienda el fotodiodo emisor rojo, con ello obtenemos una señal fotoletismografica AC y
  otra DC, lo mismo sucede cuando encendemos el fotodiodo emisor infrarrojo.
- La señal AC nos muestra el cambio en flujo sanguineo ( en este caso el dedo indice de la mano izq), esta señal AC es la que vemos en los diferentes figuras arriba mostradas.
- La señal DC si bien para nuestros propositos la eliminamos, esta señal contiene la variacion de la respiracion.
- La señal AC fue obtenida siguiendo las etapas: CONVERSOR I-V ---> FILTRO PASA-ALTAS 2DO ORDEN ---> FILTRO PASABAJA DE SEGUNDO ORDEN ---> ETAP DE PRE-AMPLIFICADO ---> FILTRADO 8VO ORDEN, como observamos en el siguiente esquema:

- Como estamos realizando un tratamiento a esta señal observamos en el osciloscopio que nuestra señal alcanza los 200mV, en este punto lo dejamos con este valor, al cual le añadiremos una etapa sencilla de suma y otra de amplificacion, para obtener un voltaje adecuado para la captura en el ADC del pic.
« Última modificación: 13 de Octubre de 2009, 17:08:44 por washi_w_z_r »

Desconectado washi_w_z_r

  • PIC10
  • *
  • Mensajes: 20
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #2 en: 13 de Octubre de 2009, 17:38:37 »
PROGRAMACION EN EL PIC:
Aqui les dejo mi prog en el pic:

Código: C#
  1. /////////////////////////////////////////////////////////////////////////////
  2. //DECLARANDO DISPOSITIVO A USAR
  3. ////////////////////////////////////////////////////////////////////////////
  4. #include <18f4458.h>
  5. /////////////////////////////////////////////////////////////////////////////
  6. //DECLARANDO ADC
  7. ////////////////////////////////////////////////////////////////////////////
  8. #device ADC=12   // ADC DE 10 BITS
  9. /////////////////////////////////////////////////////////////////////////////
  10. //DECLARANDO FUSES   :  20MHZ DE OSC  
  11. ////////////////////////////////////////////////////////////////////////////
  12. #fuses HSPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV2,VREGEN,NOPBADEN,NOBROWNOUT
  13. /////////////////////////////////////////////////////////////////////////////
  14. //CONFIGURANDO A 48MHZ NECESARIOS PARA USAR EL USB 2.0
  15. ////////////////////////////////////////////////////////////////////////////
  16. #use delay(clock=48000000)
  17.  
  18. /////////////////////////////////////////////////////////////////////////////
  19. //LIBRERIAS DE CONFIGURACION DEL USB
  20. /////////////////////////////////////////////////////////////////////////////
  21. #define USB_HID_DEVICE     FALSE             //deshabilitamos el uso de las directivas HID
  22. #define USB_EP1_TX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
  23. #define USB_EP1_RX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
  24. #define USB_EP1_TX_SIZE    8                 //size to allocate for the tx endpoint 1 buffer
  25. #define USB_EP1_RX_SIZE    3                 //size to allocate for the rx endpoint 1 buffer
  26.  
  27. ///////////////////////////////////////////////////////////////////////////////
  28. #define USB_CON_SENSE_PIN PIN_E3  
  29. /////////////////////////////////////////////////////////////////////////////
  30. //
  31. // If you are using a USB connection sense pin, define it here.  If you are
  32. // not using connection sense, comment out this line.  Without connection
  33. // sense you will not know if the device gets disconnected.
  34. //       (connection sense should look like this:
  35. //                             100k
  36. //            VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
  37. //                     |
  38. //                     +----/\/\/\/\/\-----GND
  39. //                             100k
  40. //        (where VBUS is pin1 of the USB connector)
  41. //
  42. /////////////////////////////////////////////////////////////////////////////
  43.  
  44. #include <pic18_usb.h>     //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
  45. #include <USB_ADC_TESIS.h>         //Configuración del USB y los descriptores para este dispositivo
  46. #include <usb.c>           //handles usb setup tokens and get descriptor reports
  47. /////////////////////////////////////////////////////////////////////////////
  48. //DEFINICION DE VARIABLES PARA EL USO ADC
  49. ////////////////////////////////////////////////////////////////////////////
  50. #define DERECHA 0
  51.  
  52. #byte TRISA = 0xF92
  53. #byte TRISD = 0xF95
  54. #byte ADCON2 = 0xFC0
  55. #byte ADCON0 = 0xFC2
  56. #byte ADCON1 = 0xFC1
  57. #byte ADRESL = 0xFC3
  58. #byte ADRESH = 0xFC4
  59. #byte ValorH = 0x028
  60. #byte ValorL = 0x029
  61. ////////////////////////////////////////////////////////////////////////////
  62. // DEFINICION DE VARIABLES PARA CONTROL DE CONEX USB
  63. //////////////////////////////////////////////////////////////////////////
  64. //*** CONTROL DE CONEX USB ***//
  65. #define LEDV    PIN_B6
  66. #define LEDR    PIN_B7
  67.  
  68. //*** CONTROL LED SENSOR ***//
  69. #define LED_ROJO PIN_C1
  70. #define LED_INFR PIN_C0
  71. //*** CONTROL DE SEÑALES AC-DC***//
  72. #define CONTROL_0 PIN_D0   //SEÑAL ROJO_AC_4
  73. #define CONTROL_1 PIN_D1   //SEÑAL INFR_AC_4
  74. #define CONTROL_2 PIN_D2   //SEÑAL ROJO_DC
  75. #define CONTROL_3 PIN_D3   //SEÑAL INFR_DC
  76.  
  77. //*** ESTADOS SALIDA DE PINES ***//
  78. #define LED_ON  output_high
  79. #define LED_OFF output_low
  80.  
  81.  
  82. ///////////////////////////////////////////////////////////////////////////
  83. // PARAMETROS: ENVIO Y RECEPCION DATOS ATRAVES DEL USB
  84. //////////////////////////////////////////////////////////////////////////
  85. #define modo      recibe[0]
  86. #define param1    recibe[1]
  87. #define param2    recibe[2]
  88.  
  89. /////////////////////////////////////////////////////////
  90. void main(void) {
  91.    ///////////////////////
  92.    //VARIABLES PARA EL ADC
  93.    ///////////////////////
  94.    int recibe[3];                  //declaramos variables
  95.    long value;
  96.    int i;
  97.    int8 Buffer_ADC[8];
  98.    int SPO_1[3]=
  99.    {
  100.    255,254,20
  101.    };
  102.  
  103.     LED_OFF(LEDV);                   //encendemos led rojo
  104.     LED_ON(LEDR);
  105.    // CONFIGURANDO CANALES ANALOGICOS
  106.    setup_adc_ports(AN0_TO_AN1_ANALOG);
  107.    // CONFIGURANDO RELOJ DE CONVERSION
  108.    setup_adc(ADC_CLOCK_DIV_64 );  
  109.    //CONFIGURANDO TIPO DE JUSTIFICACION
  110.     #asm
  111.      bcf 0xFC0,7   // ADFM <- 0 justificacion derecha
  112.     #endasm
  113.     //CONFIGURANDO TIEMPO DE ADQUISICION
  114.     #asm          // configura Tacq = 2Tad
  115.      bsf 0xFC0,3
  116.      bsf 0xFC0,4
  117.      bsf 0xFC0,5
  118.     #endasm
  119.  
  120.      
  121.    usb_init_cs();  // inciamos y apagamos el modulo USB , ahora depende de usb_task();
  122.    
  123.    while (TRUE)
  124.    {
  125.       usb_task();   //habilita periferico usb e interrupciones
  126.  
  127.       if(usb_enumerated())          //si el PicUSB está configurado
  128.       {
  129.         if (usb_kbhit(1))          //si el endpoint de salida contiene datos del host
  130.          {
  131.             usb_get_packet(1, recibe, 3); //cojemos el paquete de tamaño 3bytes del EP1 y almacenamos en recibe
  132.             switch (modo)
  133.             {  
  134.                
  135.                case 0:
  136.                {
  137.                   if (param1 == 0) {LED_OFF(LEDV); LED_OFF(LEDR);} //apagamos los leds
  138.                   if (param1 == 1) {LED_ON(LEDV); LED_OFF(LEDR);} //encendemos led verde
  139.                   if (param1 == 2) {LED_OFF(LEDV); LED_ON(LEDR);} //encendemos led rojo
  140.                   break;
  141.                }
  142.                
  143.                case 1:
  144.                {
  145.                   usb_put_packet(1,SPO_1,3,USB_DTS_TOGGLE);  //probar si envia un paquete
  146.                   break;
  147.                }
  148.                
  149.                case 2:
  150.                {
  151.                //LED_ON(LEDV);
  152.                 /////////////////////////////////////////////////////////
  153.                 /// CONTROL DE MUX ROJO                               ///
  154.                 /////////////////////////////////////////////////////////
  155.                 ///   ENCENDIDO LED ROJO - ACTIVAR MUX ROJO_AC_4      ///
  156.                 /////////////////////////////////////////////////////////
  157.                 LED_ON(LED_ROJO);   // ENCIENDO LED ROJO
  158.                 LED_OFF(LED_INFR);  // APAGO LED INFRARROJO
  159.                 /////////////////////////////////////////////
  160.                 LED_OFF(CONTROL_0);   // ACTIVO MUX_ROJO_AC_4
  161.                 LED_ON(CONTROL_1);   //  DESACTIVO MUX_INFR_AC_4
  162.                 LED_ON(CONTROL_2);   // DESACTIVO MUX_ROJO_DC
  163.                 LED_ON(CONTROL_3);   //DESACTIVO MUX_INFR_DC
  164.                 ///////////////////////////////
  165.                 /// configurar canal AN0     //
  166.                 ///////////////////////////////
  167.                set_adc_channel(0);   // elegimos canal a convertir
  168.                 delay_us(50);
  169.                 value=read_adc();         // LEEMOS LA CONVERISION DEL ADC
  170.                 Buffer_ADC[0]=ValorH;      //ALMACENAMOS BITS MSB
  171.                 Buffer_ADC[1]=ValorL;      //ALMACENAMOS BITS LSB
  172.                 delay_us(50);
  173.                 set_adc_channel(0);   // elegimos canal a convertir
  174.                 delay_us(50);
  175.                 value=read_adc();         // LEEMOS LA CONVERISION DEL ADC
  176.                 Buffer_ADC[2]=ValorH;      //ALMACENAMOS BITS MSB
  177.                 Buffer_ADC[3]=ValorL;      //ALMACENAMOS BITS LSB
  178.                 delay_us(50);
  179.                 set_adc_channel(0);   // elegimos canal a convertir
  180.                 delay_us(50);
  181.                 value=read_adc();         // LEEMOS LA CONVERISION DEL ADC
  182.                 Buffer_ADC[4]=ValorH;      //ALMACENAMOS BITS MSB
  183.                 Buffer_ADC[5]=ValorL;      //ALMACENAMOS BITS LSB
  184.                 delay_us(50);
  185.                 set_adc_channel(0);   // elegimos canal a convertir
  186.                 delay_us(50);
  187.                 value=read_adc();         // LEEMOS LA CONVERISION DEL ADC
  188.                 Buffer_ADC[6]=ValorH;      //ALMACENAMOS BITS MSB
  189.                 Buffer_ADC[7]=ValorL;      //ALMACENAMOS BITS LSB
  190.                 set_adc_channel(0);   // elegimos canal a convertir
  191.                 delay_us(50);
  192.                 usb_put_packet(1,Buffer_ADC,8,USB_DTS_TOGGLE);
  193.                 //LED_OFF(LEDV);
  194.                 break;
  195.               }
  196.  
  197.                            
  198.             }
  199.          }
  200.       }
  201.    }
  202. }

Bien explicando en lineeas generales:
-  Yo uso el pic 18f4458 que tiene 12 bits de ADC , pero pòdemos usar el pic 18f4550 con el mismo codigo sin ningun problema.
-  Lo que hace el codigo es que cada vez que el PC le pida valores del ADC este leera 4 valores y lo enviara a la PC.
-  Algunas de la directivas , por ejemplo #define CONTROL_0 PIN_D0   //SEÑAL ROJO_AC_4
#define CONTROL_1 PIN_D1   //SEÑAL INFR_AC_4, es debido a que en mi proyecto yo requiero visualizar las cuatro ondas es decir : del fotoemisor rojo las ondas AC y DC , del fotoemisor infrarrojo las ondas AC y DC , para ello uso un multiplexor analogico ADG411 con el cual selecciono la onda deseada.
- Para el presente proyecto en este foro solo visualizaremos la señal Rojo_AC.
- Antes de seguir les dejo imagenes de mis placas tanto las que diseñe en EAGLE 5.40 y las reales asi como los respectivos archivos.


http://img203.imageshack.us/img203/7240/placafiltrossealreal.jpg
http://img527.imageshack.us/img527/2018/placafiltrossealeagle.jpg
http://img131.imageshack.us/img131/6790/placamultiplexacionampl.jpg
http://img162.imageshack.us/img162/6790/placamultiplexacionampl.jpg
http://img101.imageshack.us/img101/1251/placafuentereal.jpg
http://img202.imageshack.us/img202/8489/placafuenteeagle.jpg
http://img397.imageshack.us/img397/9671/placapicreal.jpg
http://img202.imageshack.us/img202/6085/placapiceagle.jpg

Desconectado washi_w_z_r

  • PIC10
  • *
  • Mensajes: 20
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #3 en: 13 de Octubre de 2009, 18:03:14 »
PROGRAMACION C#
Lo primero sera crear un nuevo proyecto, esto lo c#

http://img440.imageshack.us/img440/2555/cpaso1.jpg

Colocamos el nombre del proyecto y  la ubicación en este caso el nombre del proyecto es “ONDAS_PLETISMOGRAFICAS” y esta localizado en la unidad “D “con el nombre de ONDAS, aclarando que el mismo C# dará el nombre a “Solution Name”, por ello no lo cambiamos.

http://img440.imageshack.us/img440/6893/cpaso2.jpg

Damos OK y esperamos a que el soft cree los objetos, métodos y el diseño del proyecto.

Quedara así:

http://img440.imageshack.us/img440/3711/cpaso3.jpg

Hacemos click en esta herramienta la cual desplegara:

http://img440.imageshack.us/img440/4205/cpaso4.jpg

Buscamos el componente “button” “groupbox”, deslizamos estos componentes al objeto “Form1”, apretamos F4 para desplegar las propiedades  de los componentes y empezamos a diseñar nuestro programa, el cual quedara en primera instancia así:

http://img440.imageshack.us/img440/9308/cpaso5.jpg

http://img440.imageshack.us/img440/2471/cpaso6.jpg

Dentro de la carpeta de nuestro proyecto copiamos el DLL Graph components, este lo podrán encontrar en la pagina CODEPROJECT, cuyo autor nos autoriza a usar su maravilloso graficador.

Bien una vez obtenido este DLL, procedemos a colocarlo en nuestro toolbox para ello realizamos la siguiente operación:

Nos dirigimos a la herramienta ToolBox, hacemos anticlik y escogemos “choose item”
http://img440.imageshack.us/img440/2551/cpaso7.jpg

Después elegimos NET components y buscamos la ubicación del DLL que nos hemos bajado algo así:
http://img440.imageshack.us/img440/650/cpaso8.jpg

Apretamos “open”, después aceptamos en la ventana choose toolbox ítems, y desplegamos en la pestaña toolbox --- All Windows forms:
http://img440.imageshack.us/img440/4774/cpaso9.jpg

Como observamos ya contamos con el componente ploter que es esencial para nuestro proyecto.

Ahora nuestra ventana queda así

http://img440.imageshack.us/img440/2032/cpaso10.jpg


Si bien hasta ahora solo hemos diseñado es hora de programar, para ello haremos anticlik en el “Form1” y nos iremos  a “view code”

http://img440.imageshack.us/img440/21/cpaso11.jpg

Automáticamente el programa nos traslada al código principal ósea:

http://img440.imageshack.us/img440/6127/cpaso12.jpg

OK detengámonos un rato y pesemos algo, tenemos el prog C#, tenemos el prog en el PIC, tenemos el driver del PIC,  además el mpusbapi.dll, pero nos falta los, OK vayamos por partes.

-   Primero el mpusbapi.dll es un DLL que nos permite realizar  tareas en el PIC, entonces ¿Cómo lo enlazo para que este haga las funciones en el PIC? , para ello crearemos una clase denominada PICUSBAPI
-   Volvamos al C#, dentro de esta ultima figura nos dirigimos ala derecha a la pestaña “Solution Explorer” es decir:


http://img440.imageshack.us/img440/5066/cpaso13.jpg

-   Hacemos anticlik en :
http://img70.imageshack.us/img70/1079/cpaso14.jpg

-   Escogemos Add- New Item, haciendo esto se desplegara:
http://img70.imageshack.us/img70/5694/cpaso15.jpg

-   Escogemos “Class” y le damos un nombre en este caso “PicUsbApi”, dentro de esta clase definiremos, el tamaño de bytes que enviamos y recibimos

-   Demos una mirada solo a las funciones del mpusbapi.dll que usaremos

Abrir Pipe: nos permite abrir la conexión con el PIC, acotando algo cuando observamos DWORD seleccion = 0; significa que si estamos usando un solo pic , este pic sera seleccionado con “DWORD seleccion = 0” , en mi caso llege a usar en un determinado momento dos pic , con ello el segundo pic sera seleccionado con “DWORD seleccion = 1”, pero atentos a algo, para usar el mpusbapi con dos pic tendremos que:

“Crear dos clases, una que contenga el PID&VID del primer pic con el DWORD selección=0; y otra clase que contenga el otro PID&VID del segundo pic con el DWORD selección =1”.

Para terminar con esta  parte, las clases que yo implemente los denomine PicUSBApi y PIC_18usbapi, cada una de ellas maneja un dispositivo PIC.

Cerrar Pipe: cierra la conexión entre la PC y el Pic18f4550

Envio Paquete y Recibo: Paquete nos permite enviar y recibir bytes desde la PC al PIC y viceversa.

LedPic: con esta método enviaremos ordenes al PIC, en este caso enviaremos 3bytes, el primer byte que pide al PIC realizar lo que este en el “case 1”, en este caso apagar o prendera cierto Led.

PideDatos_ADC_ROJO_4_PIC1: como recordaran en mi placa de filtros yo tengo varias etapas, esta se refiere a la etapa de cuarto orden del filtro de octavo orden (espero se entienda) , del cual yo visualizare la onda, para ello pido al pic que ejecute el “case 2”

public float[] RecibeDatos_ADC_ROJO_4_PIC1: para ejecutar este metodo nosotros no solo lo llamaremos, sino tendremos que pasar  un valor para que esta funcion nos devuelva los bytes que queremos, traduciendo si no le enviamos algo esta funcion no devolvera nada, por ello lo declaramos como “public float[] “ , dento del argumento de este metodo se encuentra (uint velo) , que desde nuestro codigo principal le enviaremos un valor del tipo uint, seguidamente creamos un arreglo de 8 posiciones, al cual llamamos recibe_adc_rojo_4_pic1, dentro del cual almacenamos los valores recibidos desde el pic, y lo devolvemos con la instrucción return recibe_adc_rojo_4_pic1;

-   Muy bien ya implementamos nuestra clase PicUSBApi , el cual queda así:
Código: [Seleccionar]
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using PVOID = System.IntPtr;
using DWORD = System.UInt32;

namespace ONDAS_PLETISMOGRAFICAS
{
     unsafe public class PICUSBAPI
        {
            #region DEFINICION DE STRINGS ENDPOINT , VID_PID
            string vid_pid_norm = "vid_04d8&pid_0052";
            string out_pipe = "\\MCHP_EP1";
            string in_pipe = "\\MCHP_EP1";
            #endregion

            #region FUNCIONES IMPORTADAS DE LA DLL: mpusbapi.dll
            [DllImport("mpusbapi.dll")]
            private static extern DWORD _MPUSBGetDLLVersion();
            [DllImport("mpusbapi.dll")]
            private static extern DWORD _MPUSBGetDeviceCount(string pVID_PID);
            [DllImport("mpusbapi.dll")]
            private static extern void* _MPUSBOpen(DWORD instance, string pVID_PID, string pEP, DWORD dwDir, DWORD dwReserved);
            [DllImport("mpusbapi.dll")]
            private static extern DWORD _MPUSBRead(void* handle, void* pData, DWORD dwLen, DWORD* pLength, DWORD dwMilliseconds);
            [DllImport("mpusbapi.dll")]
            private static extern DWORD _MPUSBWrite(void* handle, void* pData, DWORD dwLen, DWORD* pLength, DWORD dwMilliseconds);
            [DllImport("mpusbapi.dll")]
            private static extern DWORD _MPUSBReadInt(void* handle, DWORD* pData, DWORD dwLen, DWORD* pLength, DWORD dwMilliseconds);
            [DllImport("mpusbapi.dll")]
            private static extern bool _MPUSBClose(void* handle);
            #endregion
           
            void* myOutPipe;
            void* myInPipe;

            #region ABRIR CERRAR PUERTO
            // METODO ABRIR PIPE//

            public void AbrirPipe()
            {
                DWORD seleccion = 0;
                myOutPipe = _MPUSBOpen(seleccion, vid_pid_norm, out_pipe, 0, 0);
                myInPipe = _MPUSBOpen(seleccion, vid_pid_norm, in_pipe, 1, 0);
            }
            public void CerrarPipe()
            {
                _MPUSBClose(myOutPipe);
                _MPUSBClose(myInPipe);
            }
            //METODOS ENVIO RECEPCION PAQUETES
            private void EnvioPaquetes(byte* SendPacket, DWORD SendLength)
            {
                uint sendelay = 4000000000;
                DWORD SendDataLength;
                _MPUSBWrite(myOutPipe, (void*)SendPacket, SendLength, &SendDataLength, sendelay);
            }

            private void ReciboPaquete(byte* ReceiveData, DWORD* ReceiveLentgh)
            {
                uint ReceiveDelay = 4000000000;
                DWORD ExpectReceiveLength = *ReceiveLentgh;
                _MPUSBRead(myInPipe, (void*)ReceiveData, ExpectReceiveLength, ReceiveLentgh, ReceiveDelay);
            }
            //METODO PRENDER APAGAR LEDS //
            public void LedPic(uint Led)
            {
                byte* send_buf = stackalloc byte[2];
                send_buf[0] = 0x00;
                send_buf[1] = (byte)Led;
                EnvioPaquetes(send_buf, 2);
            }
            #endregion
         
            #region ENVIO-RECIBO SEÑALES INDIVIDUALES
            //METODO RECIBE ENVIA DATOS ADC PIC 1
            //SEÑAL ROJO_AC_4
            public void PideDatos_ADC_ROJO_4_PIC1()
            {
                byte* Envio_Buff = stackalloc byte[2];
                Envio_Buff[0] = 0x02;
                Envio_Buff[1] = 0; //No implementado
                EnvioPaquetes(Envio_Buff, 2);
            }
            public float[] RecibeDatos_ADC_ROJO_4_PIC1(uint velo)
            {
                uint veloH;
                veloH = velo / 2;
                DWORD RecvLength = 8;
                float[] recibe_adc_rojo_4_pic1 = new float[8];
                byte* recibir_buff = stackalloc byte[8];
         
                ReciboPaquete(recibir_buff, &RecvLength);
               
                recibe_adc_rojo_4_pic1[0] = recibir_buff[0];
                recibe_adc_rojo_4_pic1[1] = recibir_buff[1];
                recibe_adc_rojo_4_pic1[2] = recibir_buff[2];
                recibe_adc_rojo_4_pic1[3] = recibir_buff[3];
                recibe_adc_rojo_4_pic1[4] = recibir_buff[4];
                recibe_adc_rojo_4_pic1[5] = recibir_buff[5];
                recibe_adc_rojo_4_pic1[6] = recibir_buff[6];
                recibe_adc_rojo_4_pic1[7] = recibir_buff[7];
             
               
                return recibe_adc_rojo_4_pic1;
            }
            //METODO RECIBE ENVIA DATOS ADC PIC 1
            //SEÑAL ROJO_AC_8
            public void PideDatos_ADC_ROJO_8_PIC1()
            {
                byte* Envio_Buff = stackalloc byte[2];
                Envio_Buff[0] = 0x03;
                Envio_Buff[1] = 0; //No implementado
                EnvioPaquetes(Envio_Buff, 2);
            }
            public float[] RecibeDatos_ADC_ROJO_8_PIC1(uint velo)
            {
             
                uint veloH;
                veloH = velo / 2;
                DWORD RecvLength = 8;
                float[] recibe_adc_rojo_8_pic1 = new float[8];
                byte* recibir_buff = stackalloc byte[8];
                ReciboPaquete(recibir_buff, &RecvLength);
                recibe_adc_rojo_8_pic1[0] = recibir_buff[0];
                recibe_adc_rojo_8_pic1[1] = recibir_buff[1];
                recibe_adc_rojo_8_pic1[2] = recibir_buff[2];
                recibe_adc_rojo_8_pic1[3] = recibir_buff[3];
                recibe_adc_rojo_8_pic1[4] = recibir_buff[4];
                recibe_adc_rojo_8_pic1[5] = recibir_buff[5];
                recibe_adc_rojo_8_pic1[6] = recibir_buff[6];
                recibe_adc_rojo_8_pic1[7] = recibir_buff[7];
                return recibe_adc_rojo_8_pic1;
            }
            //METODO ENVIA-RECIBE DATOS ADC PIC1
            // SEÑAL: INFR_AC_4
            public void PideDatos_ADC_INFR_AC_4_PIC1()
            {
                byte* Envio_Buff = stackalloc byte[2];
                Envio_Buff[0] = 0x04;
                Envio_Buff[1] = 0;
                EnvioPaquetes(Envio_Buff, 2);
            }
            public float[] RecibeDatos_ADC_INFR_AC_4_PIC1(uint velo)
            {
                uint veloH;
                veloH = velo / 2;
                DWORD RecvLength = 8;
                float[] recibe_adc_infr_ac_4_pic1 = new float[8];
                byte* recibir_buff = stackalloc byte[8];
                ReciboPaquete(recibir_buff, &RecvLength);
                recibe_adc_infr_ac_4_pic1[0] = recibir_buff[0];
                recibe_adc_infr_ac_4_pic1[1] = recibir_buff[1];
                recibe_adc_infr_ac_4_pic1[2] = recibir_buff[2];
                recibe_adc_infr_ac_4_pic1[3] = recibir_buff[3];
                recibe_adc_infr_ac_4_pic1[4] = recibir_buff[4];
                recibe_adc_infr_ac_4_pic1[5] = recibir_buff[5];
                recibe_adc_infr_ac_4_pic1[6] = recibir_buff[6];
                recibe_adc_infr_ac_4_pic1[7] = recibir_buff[7];
                return recibe_adc_infr_ac_4_pic1;
            }
            //METODO ENVIA RECIBE DATOS ADC PIC1
            // SEÑAL: INFR_AC_8
            public void PideDatos_ADC_Infr_AC_8_PIC1()
            {
                byte* Envio_Buff = stackalloc byte[2];
                Envio_Buff[0] = 0x05;
                Envio_Buff[1] = 0;
                EnvioPaquetes(Envio_Buff, 2);
            }
            public float[] RecibeDatos_ADC_Infr_AC_8_PIC1(uint velo)
            {
                uint veloH;
                veloH = velo / 2;
                DWORD RecvLength = 8;
                float[] recibe_adc_infr_ac_8_pic1 = new float[8];
                byte* recibir_buff = stackalloc byte[8];
                ReciboPaquete(recibir_buff, &RecvLength);
                recibe_adc_infr_ac_8_pic1[0] = recibir_buff[0];
                recibe_adc_infr_ac_8_pic1[1] = recibir_buff[1];
                recibe_adc_infr_ac_8_pic1[2] = recibir_buff[2];
                recibe_adc_infr_ac_8_pic1[3] = recibir_buff[3];
                recibe_adc_infr_ac_8_pic1[4] = recibir_buff[4];
                recibe_adc_infr_ac_8_pic1[5] = recibir_buff[5];
                recibe_adc_infr_ac_8_pic1[6] = recibir_buff[6];
                recibe_adc_infr_ac_8_pic1[7] = recibir_buff[7];
                return recibe_adc_infr_ac_8_pic1;
            }
            //METODO ENVIA-RECIBE DATOS
            // SEÑAL ROJO_DC
            public void PideDatos_ADC_Rojo_DC_PIC1()
            {
                byte* Envio_Buff = stackalloc byte[2];
                Envio_Buff[0] = 0x06;
                Envio_Buff[1] = 0;
                EnvioPaquetes(Envio_Buff, 2);
            }
             public float[] RecibeDatos_ADC_Rojo_DC_PIC1(uint velo)
             {
                 uint veloH;
                 veloH = velo / 2;
                 DWORD RecvLength = 8;
                 float[] recibe_adc_rojo_dc_pic1 = new float[8];
                 byte* recibir_buff = stackalloc byte[8];
                 ReciboPaquete(recibir_buff, &RecvLength);
                 recibe_adc_rojo_dc_pic1[0] = recibir_buff[0];
                 recibe_adc_rojo_dc_pic1[1] = recibir_buff[1];
                 recibe_adc_rojo_dc_pic1[2] = recibir_buff[2];
                 recibe_adc_rojo_dc_pic1[3] = recibir_buff[3];
                 recibe_adc_rojo_dc_pic1[4] = recibir_buff[4];
                 recibe_adc_rojo_dc_pic1[5] = recibir_buff[5];
                 recibe_adc_rojo_dc_pic1[6] = recibir_buff[6];
                 recibe_adc_rojo_dc_pic1[7] = recibir_buff[7];
                 return recibe_adc_rojo_dc_pic1;
             }
             //METODO ENVIA-RECIBE DATOS
             // SEÑAL INFR_DC
             public void PideDatos_ADC_Infr_DC_PIC1()
             {
                 byte* Envio_Buff = stackalloc byte[2];
                 Envio_Buff[0] = 0x07;
                 Envio_Buff[1] = 0;
                 EnvioPaquetes(Envio_Buff, 2);
             }
             public float[] RecibeDatos_ADC_Infr_DC_PIC1(uint velo)
             {
                 uint veloH;
                 veloH = velo / 2;
                 DWORD RecvLength = 8;
                 float[] recibe_adc_infr_dc_pic1 = new float[8];
                 byte* recibir_buff = stackalloc byte[8];
                 ReciboPaquete(recibir_buff, &RecvLength);
                 recibe_adc_infr_dc_pic1[0] = recibir_buff[0];
                 recibe_adc_infr_dc_pic1[1] = recibir_buff[1];
                 recibe_adc_infr_dc_pic1[2] = recibir_buff[2];
                 recibe_adc_infr_dc_pic1[3] = recibir_buff[3];
                 recibe_adc_infr_dc_pic1[4] = recibir_buff[4];
                 recibe_adc_infr_dc_pic1[5] = recibir_buff[5];
                 recibe_adc_infr_dc_pic1[6] = recibir_buff[6];
                 recibe_adc_infr_dc_pic1[7] = recibir_buff[7];
                 return recibe_adc_infr_dc_pic1;
             }
             //METODO ENVIA-RECIBE DATOS
             // SEÑAL LUZ_DC
             public void PideDatos_ADC_Luz_DC_PIC1()
             {
                 byte* Envio_Buff = stackalloc byte[2];
                 Envio_Buff[0] = 0x08;
                 Envio_Buff[1] = 0;
                 EnvioPaquetes(Envio_Buff, 2);
             }
             public float[] RecibeDatos_ADC_Luz_DC_PIC1(uint velo)
             {
                 uint veloH;
                 veloH = velo / 2;
                 DWORD RecvLength = 8;
                 float[] recibe_adc_luz_dc_pic1 = new float[8];
                 byte* recibir_buff = stackalloc byte[8];
                 ReciboPaquete(recibir_buff, &RecvLength);
                 recibe_adc_luz_dc_pic1[0] = recibir_buff[0];
                 recibe_adc_luz_dc_pic1[1] = recibir_buff[1];
                 recibe_adc_luz_dc_pic1[2] = recibir_buff[2];
                 recibe_adc_luz_dc_pic1[3] = recibir_buff[3];
                 recibe_adc_luz_dc_pic1[4] = recibir_buff[4];
                 recibe_adc_luz_dc_pic1[5] = recibir_buff[5];
                 recibe_adc_luz_dc_pic1[6] = recibir_buff[6];
                 recibe_adc_luz_dc_pic1[7] = recibir_buff[7];
                 return recibe_adc_luz_dc_pic1;
             }
            #endregion
         }
}
-   Es hora de volver al código principal, para usar la clase que hemos creado haremos los siguiente:
PICUSBAPI usbapi = new PICUSBAPI();
         PicUSB_18API usb_18api = new PicUSB_18API();
-   Recordemos nuestro “form” y sus componentes en la siguiente imagen


http://img70.imageshack.us/img70/3162/cpaso16.jpg

-   Damos doble click en el botón “Abrir” y escribimos lo siguiente:
 
Código: [Seleccionar]
usbapi.AbrirPipe();
            usbapi.LedPic(0x00);
http://img70.imageshack.us/img70/2180/cpaso17.jpg
-   Hacemos lo propio en los demás botones y el código queda así:
Código: [Seleccionar]
private void btnCerrar_Click(object sender, EventArgs e)
        {
            usbapi.CerrarPipe();
        }

        private void btnRojo_Click(object sender, EventArgs e)
        {
            usbapi.LedPic(0x02);
        }

        private void btnVerde_Click(object sender, EventArgs e)
        {
            usbapi.LedPic(0x01);
        }
-   OK, empecemos a recibir y plotear los datos, primero declaramos en la parte public Form1(), lo siguiente:
-   Con ello decimos que usamos un solo canal del ploter, pero podemos inicializar hasta ocho canales, en la Pág. de codeprojet conde sacamos este ploteador les dirá mas detalles del mismo.
-   Bien para poder plotear necesitamos la ayuda de un timer, este lo encontramos en las herramientas del “TOOLBOX”, arrastrando el mismo queda así en nuestro panel :
http://img70.imageshack.us/img70/1828/cpaso18.jpg

-   Bien hacemos doble click en el timer y colocamos el siguiente cod:
Código: [Seleccionar]
//PEDIMOS AL PIC 1 INICIALIZAR EL MODULO ADC ROJO AC_4TO
            usbapi.PideDatos_ADC_ROJO_4_PIC1();
            //-----  CREAMOS UN ARREGLO PARA ALMACENAR DATOS
            float[] Resultado = new float[8];
            //-----  ALMACENAMOS LOS DATOS PROVENIENTES DEL ADC DEL PIC 1
            Resultado = usbapi.RecibeDatos_ADC_ROJO_4_PIC1(4);
           
            //-----  CREAMOS UN BUFFER AUXILIAR PARA GRAFICAR DATOS
           
            float[] Buff_Aux = new float[4];
            Buff_Aux[0] = ((Resultado[0] + Resultado[1] * 256) * 5 / 4096);
            Buff_Aux[1] = ((Resultado[2] + Resultado[3] * 256) * 5 / 4096);
            Buff_Aux[2] = ((Resultado[4] + Resultado[5] * 256) * 5 / 4096);
            Buff_Aux[3] = ((Resultado[6] + Resultado[7] * 256) * 5 / 4096);
           
            plotter1.Channels[0].CurrentValue = Buff_Aux[0] / 25;
            plotter1.UpdateDisplay();
            plotter1.Channels[0].CurrentValue = Buff_Aux[1] / 25;
            plotter1.UpdateDisplay();
            plotter1.Channels[0].CurrentValue = Buff_Aux[2] / 25;
            plotter1.UpdateDisplay();
            plotter1.Channels[0].CurrentValue = Buff_Aux[3] / 25;
            plotter1.UpdateDisplay();
-   Describiendo un poco el cod anterior :
o   primero pedimos datos  al PIC , nótese las funciones que desarrollamos en la clase usbapi estarán presentes, un vistazo a ello
o   segundo creamos un arreglo donde almacenaremos nuestros bytes provenientes del pic al cual llamamos “Resultado”
o   En este arreglo “Resultado “ almacenamos los bytes provenientes del pic, pero solo hemos recibido los bytes ADRESH y ADRESL , entonces lo convertiremos a voltaje mediante la siguiente conversión:
Buff_Aux[0] = ((Resultado[0] + Resultado[1] * 256) * 5 / 4096);

En las posiciones Buff_Aux[0], Buff_Aux[0] ,Buff_Aux[0], haremos similar tarea
o   Es hora de plotear, lo haremos con un bucle for de la siguiente manera:
for (i = 0; i < 4; i++)
            {
                plotter1.Channels[0].CurrentValue = Buff_Aux[0] / 25;
                plotter1.UpdateDisplay();
   }

Un detalle, colocamos plotter1.UpdateDisplay con el cual mostraremos los datos, de no colocar esta instrucción nuestro ploter no hara nada.

o   Para llamar al timer deberemos hacer doble click en el botón Plotter y colocamos :

timer1.Start();

o   Bien ya ploteamos y observamos el siguiente video:
[/youtube]


Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #4 en: 13 de Octubre de 2009, 23:12:52 »
Muy buen trabajo.  ;-)

Felicitaciones.
El papel lo aguanta todo

Desconectado AKENAFAB

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3227
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #5 en: 13 de Octubre de 2009, 23:52:06 »
Buenisimo! :-/ :-/ :-/

Felicitaciones!

 :-/ :-/ :-/ :-/ :-/ :-/

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #6 en: 14 de Octubre de 2009, 01:52:59 »
Es impresionante. Muchas gracias

Desconectado NANO1985

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
    • Desarrollos Tecnologicos - Tucuman - Argentina
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #7 en: 14 de Octubre de 2009, 02:20:26 »
felicitaciones por semejante proyecto!... saludos  8)
"La inquebrantable voluntad de vencer"
"hay dos cosas infinitas... El universo y la Estupidez humana" Albert Einstein
 "El sabio actua sin anhelos, permanece sosegado,... así no es afectado por el resultado de sus acciones sean éstas el triunfo o el fracaso"
- UNIVERSIDAD TECNOLOGICA NACIONAL - FACULTAD REGIONAL TUCUMAN -

Desconectado barral

  • PIC10
  • *
  • Mensajes: 37
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #8 en: 14 de Octubre de 2009, 03:42:30 »
Impresionante proyecto e impecable explicación. Felicidades

Desconectado wilfo

  • PIC10
  • *
  • Mensajes: 7
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #9 en: 24 de Octubre de 2009, 13:48:02 »
Fenomenal..!..

Muy buena explicación ..y esa libreria PicUsbApi ¿donde la puedo descargar?

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #10 en: 24 de Octubre de 2009, 14:12:10 »
Excelente trabajo que tienes

Felicitaciones!!! y todo siga yendo bien :-/ :-/
.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #11 en: 24 de Octubre de 2009, 15:54:04 »
Felicidades excelente proyecto, sobre todo una aplicación diferente de lo que común mente se tiene oportunidad de ver por la web :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/

Desconectado ema

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1078
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #12 en: 12 de Noviembre de 2009, 18:41:43 »
Excelente proyecto. Felicitaciones por tu esfuerzo. :-/ :-/ :-/

Saludos

Desconectado washi_w_z_r

  • PIC10
  • *
  • Mensajes: 20
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #13 en: 02 de Enero de 2010, 13:01:03 »
Gracias a todos por sus comentarios, pero esto no lo hubiese realizado  sin la ayuda de la diversidad de articulos asi como de tutoriales en todo el foro.

Att.
Washington.


Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: PROYECTO: FOTOPLETISMOGRAFIA-->USB-->C#
« Respuesta #14 en: 02 de Mayo de 2010, 11:30:36 »
Dejo aquí el link a otro Oxímetro de pulso muy chulo:
Oxímetro de pulso