PIC Encoder USB

A diferencia de otros proyectos hemos de hacer un programa para el PIC y otro para el PC. Ambos programas serán enfocados para el modo (o clase) CDC, es decir, como un puerto serie virtual de comunicaciones.

Usaremos el PIC 18F4550 pero siempre podrás utilizar cualquiera de la serie 18Fxx5x (18F2455/2550/4455/4550). Ese '5' en posición penúltima entre las 'x' significa que soporta comunicación USB. Sólo has de cambiar el nombre del PIC por el que tu quieras utilizar de los 4 posibles mencionados.

Las entradas A y B sirve para la construcción de un encoder tipo foto barrera, usando por ejemplo dos TCST 1103. También puedes hacerlo con sensores Hall digitales, entonces puedes quitar el 74LS14 que hacen de acondicionador de la señales del encoder. Y también es válido para encoders mecánicos llamados "tipo potenciómetro" porque el programa funciona por bucle infinito en vez de interrupción hardware. Para cualquier tipo de duda sobre la construcción o uso de un encoder haz clic aquí.

Contiene el driver CDC para todas las versiones de Windows, los fuentes y ejecutables para PC y PIC, esquema y todo lo necesario. Esta probado en Windows XP (32 bits) y Windows 7 (64 bits).

La Alimentación:

Hemos de tener en cuenta cómo vamos a alimentar el circuito. Puedes usar la alimentación que da el propio USB, entonces todos los VCC son comunes y van conectados entre ellos. Si alimentas de forma externa no has de conectar el VCC del USB por eso pongo * Ver texto en la imagen. Por otra parte, aunque no lo pongo en el esquema, es siempre necesario poner un condensador de 100nF lo más cercano posible a la alimentación del PIC, es decir, entre VCC y GND del propio PIC.

El oscilador:

Haz clic aquí para ver cómo se configura los "#Fuses". En este esquema he puesto un cristal de 20MHz, pero puedes cambiarlo por otro de 4, 8, 12, 16, 20 ó 24. Para frecuencias mayores de 24MHz no se puede usar un cristal de cuarzo sino un oscilador externo. Como usamos el USB hemos de prestar atención al valor del cristal. Necesitamos 48MHz para las comunicaciones USB y de esto se encarga un PLL interno que tienen los PIC18Fxx5x. Dicho PLL transforma los 4, 8,... 24MHz en los 48MHz que necesitamos. De hecho, poniendo un cristal de sólo 4MHz puedes hacer funcionar el micro a 48MHz, simplemente cambiando la configuración de los "#fuses". En mi caso particular configuro de esta manera cualquier proyecto, tenga o no USB, para que funcione a la máxima velocidad este tipo de PICs.

VUSB:

Verás en el esquema un condensador electrolítico de 47uF conectado a la patilla número 18; esa patilla se llama VUSB. El condensador que pongamos en esa patilla sirve para estabilizar la tensión interna del USB dentro del PIC. Poner ese condensador es importante, si no, no funcionará la comunicación USB o te daría fallos intermitentes. Puedes ponerle cualquier condensador que sea mayor de 220nF.

A continuación se muestra el programa hecho en CCS C (PIC C) para el PIC Encoder USB en clase CDC.

Programa CCS:

The translation could modify the code. Use the code without translating.
#include <18F4550.h>           // Usamos el PIC 18F4550, pero puedes declarar cualquiera de los 18Fxx5x
                                           
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN  // Cristal a 20MHz.
                               // * Ver texto para otras configuraciones del cristal.           
#use delay(clock=48000000)     // El PLL interno siempre ha de ser de 48MHz. (No es el cuarzo)
#include <usb_cdc.h>               
                                     
#Byte PortA = 0xF80            // Dirección del puerto A para la familia 18Fxx5x.
#Byte PortB = 0xF81            // Dirección del puerto B para la familia 18Fxx5x.
#Byte PortC = 0xF82            // Dirección del puerto C para la familia 18Fxx5x.
#Byte PortD = 0xF83            // Dirección del puerto D para la familia 18Fxx5x (Sólo 40/44 pines).
#Byte PortE = 0xF84            // Dirección del puerto E para la familia 18Fxx5x.
void main()
{
   Port_B_Pullups(FALSE);       // Configuración para el PIC 18F4550.
   Setup_ADC_Ports(NO_ANALOGS); // Sin comparadores ni ADCs, todo digital, etc...
   Setup_adc(ADC_CLOCK_DIV_2);
   Setup_spi(SPI_SS_DISABLED);
   Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   Setup_timer_1(T1_DISABLED);
   Setup_timer_2(T2_DISABLED,0,1);
   Setup_comparator(NC_NC_NC_NC);
   Setup_vref(FALSE);
  
   Set_Tris_A(0b11111111);      // Puerto A todo entradas (en este caso no usamos el Puerto A).
   Set_Tris_B(0b11111111);      // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
   Set_Tris_C(0b11111111);      // Puerto C todo entradas (en este caso no usamos el Puerto C).
   Set_Tris_D(0b11111111);      // Puerto D todo entradas (en este caso no usamos el Puerto D).
   Set_Tris_E(0b11111111);      // Puerto E todo entradas (en este caso no usamos el Puerto E).
   
   usb_cdc_init();              // Carga el modo CDC (Puerto virtual de comunicaciones).
   usb_init();                  // Carga el manejo del USB.
   
   char Buffer[20];             // Declaramos (sobradamente) un buffer de 20 bytes.
   int16   x=0;    // X será el contador.
   int16   enc=0;  // Se almacenará el valor actual de RB0 y RB1, hasta la siguiente comparación.
   int16   aux=0;  // Se almacenará el valor anterior de RB0 y RB1, hasta la siguiente comparación.
   
   while(!usb_cdc_connected())  // El PIC espera hasta enlazar con el PC a través del USB.
   {
   }
   
   while (TRUE)
   {
      usb_task();
          
      if (usb_enumerated())
      {
         sprintf(Buffer, "%05lu", x); // Convierte X (número) en una cadena (texto) de 5 cifras en ASCII.
                                      // Esta cadena mostrará de 00000 hasta 65535.
         printf(usb_cdc_putc, Buffer);// Envía la cadena de 5 bytes (ASCII correspondiente al número).
      
         aux=enc;               // Igualamos 'AUX' y 'ENC' para luego comparar cuando cambie 'ENC'.
         enc=PortB & 3;         // Aislamos RA0 y RA1 como un número de 2 bits y se carga en la variable 'ENC'.
          
         if ((aux==2)&&(enc==3))// Si en la comparación hay flanco de subida,
         {  
            x++;                // entonces incrementar una unidad el valor de X.
         }
          
         if ((aux==3)&&(enc==2))// Si en la comparación hay flanco de bajada,
         {  
            x--;                // entonces decrementar una unidad el valor de X.
         }
          
      }               
   }   
}

En este programa puedes aumentar la resolución de lectura del encoder hasta un factor de por cuatro. Para ver cómo se hace cliquea aquí.

Drivers y VID&PID.

Una vez programado el PIC lo conectaremos al USB. Windows detectará un elemento nuevo y entre ellos se producirá una pequeña comunicación para saber qué es lo que quiere conectarse al PC. Si es la primera vez que haces esto te pedirá el driver para la clase CDC, es decir, el puerto virtual de comunicaciones. El driver lo encontrarás en el proyecto para descargar, el enlace lo tienes justo debajo de la imagen del esquema electrónico.

El programa CCS C está configurado con un VID&PID único, que ha de coincidir con el VID&PID del driver. Los valores son: VID = 04D8 y PID = 000A. Es importante esta parte porque si no coinciden los datos no podría funcionar. Si así fuese, Windows te informaría a la hora de instalar el driver que no encuentra el adecuado.

A tener en cuenta:

En la carpeta "..\PICC\Drivers" de tu CCS hay un fichero llamado "usb_desc_cdc.h". Ese fichero contiene el VID&PID que ha de coincidir con el del driver que te pedirá Windows cuando conectes el PIC al PC. Dentro del fichero "usb_desc_cdc.h" el VID&PID ha de ser como verás a continuación, si no tendrías que modificarlo:

#define  USB_CONFIG_PID       0x000A
#define  USB_CONFIG_VID       0x04D8 

De todas formas en el zip de descarga pongo ese fichero con el VID&PID que comento.

Si no es la primera vez que haces esto.

A la hora de instalar el driver te puedes encontrar que no lo instala bien porque hay varias versiones anteriores con el mismo nombre y cada uno de ellos con un VID&PID distinto. Para resolver este problema se ha de desinstalar todos los que encuentres referente a nuestro PIC USB. Se puede hacer desde el "Panel de Control", aunque es un poco engorroso.

¿En qué puerto COM está mi PIC Encoder USB?

Una vez conectado el PIC, como lo hemos programado en modo o clase CDC se crea un nuevo puerto virtual de comunicaciones. En Windows XP lo encontrarás de la siguiente manera:

Ves a: Inicio > Panel de Control > (Vista clásica) > Sistema > Hardware > Administrador de Dispositivos > Puertos Com & LPT > y pulsas en el símbolo '+', ahí verás la referencia al puerto COM seguido de un número.

Estando en el mismo lugar, si quieres puedes cambiar el número del COM, pulsando con el botón derecho al puerto de comunicaciones donde esté tu PIC Encoder USB y le das a "Propiedades", después pulsas en la pestaña "Configuración de puerto".

En la opción "Opciones avanzadas" verás justo abajo a la izquierda de esa ventana te permite cambiar el número de puerto COM a otro. Si vieras que tu PIC encoder está en un puerto COM superior a 8, fuérzalo para que esté en cualquier otro menor y además has de evitar utilizar puertos reales (suele ser el COM1 y a veces también el COM2). También evita si es posible cualquiera que esté en uso. Si ves que está en uso pero no está conectado el elemento que usa ese puerto, entonces puedes utilizarlo (hazlo sólo si tienes experiencia). Es compartir el puerto mientras esos dos elementos no estén juntos. Esto último es peligroso si no se tiene conciencia de lo que se está haciendo. Si este fuera tu caso buscar un puerto vacío y que no sea el Com1 ni el Com2 y menor de 9. El Com3 muchas veces suele ser utilizado para el Modem tipo Dial-Up, así que mejor no usar este puerto tampoco.

Puedes crearte un verdadero problema si usas un mismo número de puerto para dos o más cosas que ya están en uso al mismo tiempo, así que ándate con ojo. Aunque no suele ser necesario es mejor reiniciar una vez hecho los cambios.

Comunicándome con el PIC Encoder USB.

El programa es muy sencillo, echemos un ojo.

Programa en FreeBasic para el PC, en clase CDC:

The translation could modify the code. Use the code without translating.
Dim As String Cadena, Tecla
Screen 12
                                          ' Abre el puerto de comunicaciones COM4. * Ver texto.
Open Com "COM4:9600, N, 8, 1, CD0, CS0, DS0, RS" For Binary As #1 
While Tecla <> Chr(27)                    ' Para salir del programa pulsamos la tecla escape (ESC).
      Tecla = InKey()                     ' Si una tecla es pulsada el valor se almacena en Tecla.
      Cadena = Input (5, #1)              ' Espera a la llegada de los 5 bytes. (Ni uno más ni uno
                                          ' menos. Esto es importante) * Ver texto. 
      Locate 10,10: Print Cadena; "     " ' Imprime el resultado en pantalla.
Wend      
Close #1                                  ' Cierra el puerto de comunicaciones.
End

Sea en el lenguaje de programación que programes los detalles importantes son los mismos:

  • Se trata de abrir el puerto de comunicaciones en el que esté el PIC Encoder USB, en mi caso es el COM4. En tu caso puede ser otro.
  • El PIC nos estará enviando esos 5 bytes que representarán los valores comprendidos entre 00000 y 65535. Lo hace en modo texto (string), por eso sale cinco ceros. Son las posiciones posibles del encoder. Si quieres otra resolución has de hacer los cambios necesarios tanto en el PIC como en el programa del PC. Es importante que si el PIC envía 5 bytes, el programa del PC espere esos 5 bytes; ni uno más y ni uno menos. Porque si quieres modificar el programa del PC y usar otra resolución y/o introduces "retornos de carro" o "nueva línea", es decir, los caracteres no imprimibles chr(13) y chr(10) no funcionará. Todos estos detalles, a la hora de modificar o adaptar a tu proyecto has de tenerlo presente.

Si no funciona a la primera.

A continuación enumero una lista de posibles problemas con la posible solución.

El PIC:

* Antes de poner el marcha el invento, reinicia el PC! Una vez reiniciado ves directo al invento. Me pasa muchas veces que hasta que no reinicio no me funcionan ciertas cosas, especialmente en Windows XP, a partir de Windows 7 es muy raro tenerlo que hacer.

* Que la configuración de los "Fuses" se corresponda con el cristal de cuarzo que uses. Por otra parte, aunque es muy raro que falle un cristal, prueba otro para descarta este posible fallo.

* Repasar las conexiones. Antes de hacer esto, si llevas mucho tiempo delante del circuito, es mejor "desconectarse" yendo a beber un poco de agua, ver tele, o ir a dar una vuelta. A veces no conseguimos ver un pequeño fallo porque cuando estamos mucho rato delante de algo que no funciona sólo vemos lo que queremos ver (bucle infinito), es como estar delante de una ilusión óptica. Cuando esto sucede es mejor desconectar para que el cerebro pueda reordenarse y así tener otra perspectiva de las cosas al tomarlo de nuevo.

* Tener puesto un condensador mayor de 220nF en VUSB (patilla 18) del PIC. Yo uso 47uF y me funciona perfecto.

* Comprobar que D+ y D- se corresponda correctamente entre el USB y el PIC.

* Compartir las masas (GND) del USB y el PIC. De paso, si no has puesto algún condensador de unos 100nF en la alimentación del PIC (cerca de éste), pónselo.

* El Reset del PIC (patilla 1) esté polarizado a positivo a través de una resistencia.

El Programa:

* Repito porque es importante: Si no te funciona a la primera, lo primero de todo es reiniciar el PC, especialmente en Windows XP.

* Asegúrate de que has configurado bien el puerto de comunicaciones en el programa del PC y que el puerto no presente conflictos con otros elementos.

* Si el paso anterior está correcto, fuerza a cambiar en el Panel de Control a otro número de puerto COM (arriba en esta página explico cómo hacerlo) y después pones ese número nuevo de puerto COM en el programa del PC.

* Puedes descargar el proyecto y hacerlo todo de forma directa, tal como está en el zip de descarga, teniendo en cuenta que usas un puerto COM libre, cambiando si no es el COM4 a otro en el programa del PC. Si no te funciona tal y como está en el zip de descarga, has reiniciado y repasado todo, lo único que se me ocurre sería problemas de compatibilidad. Puedo garantizar el funcionamiento en Windows XP (Professional y Home, en 32 bits) y Windows 7 (64 bits).

Bibliografía y agradecimientos.

Voy a enumerar una serie de personas y grupos a las que agradezco el material intelectual que comparten con todo el mundo y que yo también me he servido. Casi todos los enlaces te llevarán al mundo de los PICs y el USB:

* Pedro PalitroqueZ Mis primeros pasos con el PIC 18F4550.

* RedRaven http://picmania.garcia-cuervo.net/usb_3_cdctransfers.php

* MigSantiago http://www.migsantiago.com

* Slalen del foro http://www.todopic.com.ar

* J1M hobbypic (antiguamente ese era el nombre de su web).

[J1M fue al parecer quien abrió camino sobre el tema PIC USB en foros de habla hispana.]

* Moyano Jonathan (creo que no tiene pagina web, pongo algo que le represente):

http://www.forosdeelectronica.com/f24/control-dispositivos-traves-modulo-usb-pic18f2550-17458/