PROGRAMACION C#
Lo primero sera crear un nuevo proyecto, esto lo c#
http://img440.imageshack.us/img440/2555/cpaso1.jpgColocamos 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.jpgDamos 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.jpgHacemos click en esta herramienta la cual desplegara:
http://img440.imageshack.us/img440/4205/cpaso4.jpgBuscamos 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.jpghttp://img440.imageshack.us/img440/2471/cpaso6.jpgDentro 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.jpgDespués elegimos NET components y buscamos la ubicación del DLL que nos hemos bajado algo así:
http://img440.imageshack.us/img440/650/cpaso8.jpgApretamos “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.jpgComo 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.jpgSi 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.jpgAutomáticamente el programa nos traslada al código principal ósea:
http://img440.imageshack.us/img440/6127/cpaso12.jpgOK 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í:
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:
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í:
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:
//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]