Control de dispositivos a través del módulo USB del PIC18F45/2550

Si ya tienes funcionando algo con PICBASICPRO, y queres que te funcione bajo los nuevos sistemas operativos o estás programando en VB.net te sirve perfectamente. Es decir los programas hechos con picbasicpro que son hechos con easyHID son compatibles con mi ejemplo.
 
Moyano Jonathan, muchas gracias por tu respuesta, cuando tenga los componentes en mis manos hago unas pruebas y estare avisando

Gracias.
 
Hola muchachos....
Saludos a todos.
Soy el nuevo por aquí...
He leído durante dos días.. desde el post 1 hasta este.. ufff muy interesante

Que gran comunidad, aportan, dan ideas, usan ideas, una retroalimentación muy buena.
Espero en lo futuro aportar a la comunidad.

En esta ocasión acudo a ustedes con el siguiente problema:

Mi objetivo:
*Mover un motor de paso, tipo unipolar, a través del puerto USB del computador usando el 18F4550 y un programa en visualB_6.

Como bien para empezar decidí por usar el com virtual que se genera con el 18F4550
Usando el compilador CCS y las respectivas librerias usb_cdc.h y usb_desc_cdc.h

Lo anterior lo realice con éxito, instalando el mchpcdc.inf. Y listo aparece muy bonito en administrador de hardware mi puerto COM virtual.

En la parte de visualB_6 hice un pequeño entorno asi como este:

1_560.jpg



Este es el código del pic:

Código:
#include <18F4550.h>


#FUSES HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL3,USBDIV,CPUDIV1,VREGEN,NOPBADEN
#use delay(clock=48000000) //Microcontroller Clock Frequency 48MHz

#define USB_CON_SENSE_PIN PIN_C2
#include <usb_cdc.h>  

void main()
{

//Variables
int8 BobinaA, BobinaB, BobinaC, BobinaD;
short Girar_D, Girar_I;

OUTPUT_A(0);  // Inicializacion de los puertos
OUTPUT_B(0);            
OUTPUT_C(0);
OUTPUT_D(0);            
OUTPUT_E(0);

// Secuencia de Giro del Motor.
   BobinaA=0b00000011; 
   BobinaB=0b00000110; 
   BobinaC=0b00001100; 
   BobinaD=0b00001001;

usb_init_cs();  
while(true)
     {
      usb_task();
      if (usb_attached())
          {
          output_low(PIN_C0);  // (Apaga LED Rojo)
          output_high(PIN_C1); // (Enciende LED Verde)
          }    
         else
            {
            output_high(PIN_C0); //(Enciende LED Rojo)
            output_low(PIN_C1);  //(Apaga LED Verde)
            }
      if(usb_cdc_connected())
         {
          if (usb_enumerated())
              { 
               if(usb_cdc_kbhit())
                  {
                   if(usb_cdc_getc()=='d')
                      {
                       printf(usb_cdc_putc,"Dale Derecha");
                       Girar_D=true; 
                       Girar_I=false;
                      }
                   if(usb_cdc_getc()=='i')
                      {
                       printf(usb_cdc_putc,"Dale Izquierda");
                       Girar_I=true; 
                       Girar_D=false;
                      }
                   if(usb_cdc_getc()=='s')
                      {
                       printf(usb_cdc_putc,"No Girar"); 
                       Girar_I=false;
                       Girar_D=false;
                       output_d(0);       //Desenergiza las bobinas
                      }                  
                  }
              }
         }
     if (Girar_D) //Bandera Girar Derecha
         {
          output_d(BobinaA);
          delay_ms(80);
          output_d(BobinaB);
          delay_ms(80);
          output_d(BobinaC);
          delay_ms(80);
          output_d(BobinaD);
          delay_ms(80);       
         }
     if (Girar_I) //Bandera Girar Derecha
         {
          output_d(BobinaD);
          delay_ms(80);
          output_d(BobinaC);
          delay_ms(80);
          output_d(BobinaB);
          delay_ms(80);
          output_d(BobinaA);
          delay_ms(80);       
         }
} //fin while
} //fin!

Este es el código en visualB_6:

Código:
Option Explicit

Private Sub Form_Load()
puerto.AddItem "COM1"
puerto.AddItem "COM2"
puerto.AddItem "COM3"
puerto.AddItem "COM4"
puerto.AddItem "COM5"
puerto.AddItem "COM6"
puerto.ListIndex = 0
    MSComm1.Settings = "9600,N,8,1"
    MSComm1.OutBufferSize = 1
    MSComm1.InBufferSize = 14
    MSComm1.InputMode = comInputModeText
    MSComm1.InputLen = 14
    MSComm1.RThreshold = 8
Timer1.Interval = 1000
Timer1.Enabled = True
End Sub


Private Sub MSComm1_OnComm()
 
Dim InBuff As String
  Select Case MSComm1.CommEvent
         Case comEvReceive
              Debug.Print MSComm1.InBufferSize
              InBuff = MSComm1.Input
              MSComm1.InBufferCount = 0  'Vacia el buffer de recepción
              Debug.Print MSComm1.InBufferSize
              Debug.Print InBuff
              Recibir.Text = ""
              Recibir.Text = Left$(InBuff, 14)
  End Select
End Sub

Private Sub Timer1_Timer()
DoEvents 'Para que windows y el programa pueda realizar otras cosas
     If MSComm1.PortOpen = True Then
        estado.BackColor = &HFF00& 'Verde
        Debug.Print "Conectado"
        Label3.Caption = "USB ON"
        MSComm1.PortOpen = False 'Se cierra el puerto y se abre
        MSComm1.PortOpen = True  'si permite abrirlo es porque el puerto existe
                                 'y esta conectado, sino, genera un error
        Exit Sub
     Else
     estado.BackColor = &HFF& 'rojo
     Debug.Print "Desconectado"
     Label3.Caption = "USB OFF"
     End If
End Sub

Private Sub conectar_Click()
    If MSComm1.PortOpen = False Then
        'determina el puerto que hemos seleccionado.
        If puerto.ListIndex = 0 Then
            MSComm1.CommPort = 1
            End If
        If puerto.ListIndex = 1 Then
            MSComm1.CommPort = 2
            End If
        If puerto.ListIndex = 2 Then
            MSComm1.CommPort = 3
            End If
        If puerto.ListIndex = 3 Then
            MSComm1.CommPort = 4
            End If
        If puerto.ListIndex = 4 Then
            MSComm1.CommPort = 5
            End If
        If puerto.ListIndex = 5 Then
            MSComm1.CommPort = 6
            End If
    End If
    MSComm1.PortOpen = True
End Sub

Private Sub Detener_Click()
    Timer1.Enabled = False
    If MSComm1.PortOpen = True Then
       MSComm1.Output = "s"
       MSComm1.OutBufferCount = 0 'Vacia el buffer de transmisión
       Debug.Print "MSComm1.OutBufferCount"; MSComm1.OutBufferCount
    End If
    Timer1.Enabled = True
End Sub

Private Sub Girar1_Click()
    Timer1.Enabled = False
    If MSComm1.PortOpen = True Then
       MSComm1.Output = "d"
       MSComm1.OutBufferCount = 0 'Vacia el buffer de transmisión
       Debug.Print "MSComm1.OutBufferCount"; MSComm1.OutBufferCount
    End If
    Timer1.Enabled = True
End Sub

Private Sub Girar2_Click()
    Timer1.Enabled = False
    If MSComm1.PortOpen = True Then
       MSComm1.Output = "i"
       MSComm1.OutBufferCount = 0 'Vacia el buffer de transmisión
       Debug.Print "MSComm1.OutBufferCount"; MSComm1.OutBufferCount
    End If
    Timer1.Enabled = True
End Sub

Private Sub Form_Unload(Cancel As Integer)
If MSComm1.PortOpen = True Then
   MSComm1.PortOpen = False
End If
End Sub

Esto es el diagnostico:

-El programa en visual permite elegir el puerto COM a usar y conectarse a el. Esto funciona sin problemas.

-El pic se identifica con el host intercambia descriptores y todo lo demas, pide al driver etc.. Esto funciona sin problemas.

Pero cuando en visual presionas un botón, el pic debería responder a ese botón, devolver un mensaje a visual y ejecutar la rutina correspondiente.

Lo anterior se realiza, pero no como debería, me explico:

--Supón que presionas el botón "Girar Derecha" en visual, este debe mandarle al pic la letra "d", el pic debe identificar que letra le llego, si es la letra "d" manda un mensaje a visual que dice "Dale Derecha", ademas, activa la bandera para girar a la derecha, luego el pic debe salir de ese IF, ver que bandera tiene activada, y comenzar la rutina de energizar las bobinas para mover el motor.

Lo anterior no se realiza hasta que presionas el botón en visual dos o tres veces
Si presionas el botón una vez, el pic queda en stand-by
Si presionas el botón una segunda vez, el pic sigue en stand-by
Si presionas el botón una tercera vez, el pic mueve el motor...

Cuando depuro el programa en proteus, dándole pausa a la simulación e ir al código, para ver que esta haciendo en ese supuesto "stand-by" me encuentro que el pic esta en la siguiente instrucción dentro de usb_cdc.h:

Código:
...
...
////////////////// END USB CONTROL HANDLING //////////////////////////////////

////////////////// BEGIN USB<->RS232 CDC LIBRARY /////////////////////////////

char usb_cdc_getc(void) {
   char c;

   while (!usb_cdc_kbhit()) {}

   c=usb_cdc_get_buffer_status_buffer[usb_cdc_get_buffer_status.index++];
   if (usb_cdc_get_buffer_status.index >= usb_cdc_get_buffer_status.len) {
      usb_cdc_get_buffer_status.got=FALSE;
      usb_flush_out(USB_CDC_DATA_OUT_ENDPOINT, USB_DTS_TOGGLE);
   }

   return(c);
}
...
...

Esta pegado en esta línea while (!usb_cdc_kbhit()) {} :eek: :eek: :eek:

Que la traducción seria algo así: "Mientras NO se hayan recibido uno o mas datos quédate aquí"

La ayuda del CCS dice que: usb_cdc_kbhit() - Returns TRUE if there is one or more character received and waiting in the receive buffer.

Pero se supone que estoy enviando 1 dato (un carácter)
Por qué el pic se queda en esta línea?
Por qué al presionar el botón mas de dos veces el pic hace lo que debe?
Cómo corrijo que solo al presionar una vez el botón el pic haga lo que debe?

Alguna idea, sugerencia, comentario...?

Adjunto c1a9r8l0os.rar

Contiene:
Codigo en C para CCS
Codigo en VisualB_6
Arhivo en Proteus para simular
Archivo .cof para correr en proteus
Drivers mchpcdc.inf

Como todavía no he podido solventar este problema, tengo unos días leyendo sobre HID y sobre el modo BULK usando mpusbapi.dll, ambos me gusta, me inclino mas por el HID solo, sin tener que instalar nada, lo difícil viene en la parte del software, pero con unos ejemplos que encontré, plus los ejemplos que publicó el amigo moyano, he estado entendiendo cada vez mas...
Sin embargo, me gustaría mucho resolver este problema, me tiene la cabeza dando vueltas.


PDTA== Comentario off-topic, como hago para que en el post no se vea la imagen 1.jpg que esta adjuntado al post
 

Adjuntos

  • 1_560.jpg
    1_560.jpg
    13.4 KB · Visitas: 286
  • c1a9r8l0os_546.rar
    51.1 KB · Visitas: 334
Dejame unos días que vea tu código , pero al parecer es un problema que recide en el PIC más que nada.

Este problema yo lo tuve , pero se me solucionó cuando empecé con HID la verdad nunca lo solucioné pero dejame que vea como puedo ayudarte.

Mientras es mejor que consultes con meta sobre ese programa que has hecho vos ya que el tiene más experiencia con el uso del puerto serie.

PD: No creo que ese bucle te haga esperar el tiempo como para que tengas que apretar 2 veces..
 
Hola a todos

Acá les dejo unas fotos de mi nuevo entrenador:

tiene:

- RS232
- USB
- 8 entradas
- 8 saidas
- Buzzer y LED indicador
- Memoria EEPROM.
- 3 potenciómetros
- 1 relé (correjir posición en la placa)
 

Adjuntos

  • imagen035_463.jpg
    imagen035_463.jpg
    248.3 KB · Visitas: 201
  • imagen037_372.jpg
    imagen037_372.jpg
    244 KB · Visitas: 183
  • imagen039_100.jpg
    imagen039_100.jpg
    266.5 KB · Visitas: 221
  • imagen040_136.jpg
    imagen040_136.jpg
    300.7 KB · Visitas: 257
Muy bueno Moyano.

Al final se hizo realidad.

Menudo trabajo de meses te has montado.

Felicidades.

Desde que sepa manjear el USB que no tengo ni idea, haré un entrenador para mi.

Suerte con el proyecto y el manual.
 
Gracias Moyano por responder. :)

Este problema yo lo tuve , ... la verdad nunca lo solucioné pero déjame que vea como puedo ayudarte.

Que alivio saber que otra persona también tuvo este problema, en verdad pensé que era yo, que hacia algo mal, que compilaba mal, etc.... ya mi cerebro no daba mas pensando que podría ser.

He probado varias cosas:
-Si quito la linea while (!usb_cdc_kbhit()) {} el programa responde al presionar una sola vez el botón, pero cuando presionas otro botón no responde a nada, se queda haciendo lo que el primer botón le dijo que hiciera.

-Si cambio la instrucción y le quito la negación (!)... while (usb_cdc_kbhit()) {} hace lo mismo.

Voy a decirle a meta que vea este post, a ver que puede sugerir.

Muchas Gracias moyano por tomarte la molestia de leer el código.

...se me solucionó cuando empecé con HID...

:LOL: Por ese camino voy yo, leyendo HID etc.. pero la verdad no quiero huirle al problema, quiero solucionar esto, y también usar HID sabiendo que con CDC también funcionó.


Y felicidades moyano por tu entrenador USB....
 
Muchas gracias por su comentario sobre la placa. De a pocó comenzaré a hacer el manual sobre usb y espero que se aclaren los problemas que vallan surgiendo.
La totalidad del manual estará hecha en VB.net que luego con ayuda de ustedes migraré a VC#. VC++ no lo voy a integrar a mi manual ya que me es demasiado engorroso.
 
Estoy empezando a leer FAT32 y SD card para ver que se puede hacer en el futuro con USB......pero será más adelante.


PD: El manual lo desarrollaré bajo Visual Studio proffesional edition ya que no tengo el VB.net Express aparte.
 
No te preocupes por el manual. Hazlo sin prisas pero sin pausas a VB .net que me entre todos lo pasamos a VC# y si se puede VC++ también.
 
Para VC# habría que pasar el módulo de comunicaciones que es el encargado de leer la .dll y comunicarnos con el dispositivo.

Estoy en proceso de crear el manual pero me falta ayuda para que quede bonito en power point...
Osea manejo muy poco el power point.
 
No te procupes, en poco tiempo lo cogerás fácil. Uso el 2007. Si quieres lo hace rápido en Word (de prueba), después yo mismo lo paso a PowerPoint (para probarlo) para que lo veas.

Empesé así como usted mismo, al final aprendí con la esperiencia de aprender como se maneja. No es para preocuparse, si quieres inténtalo que así se consigue aprender, a usar elPowerPoint, luego yo me necargaré de los efectos.
 
Si estoy tratando de agarrar la mano.

Te dejo más o menos algo que hecho hasta ahora y que me convenció por el lado de la estética
 

Adjuntos

  • presentacin1_157.pdf
    293.4 KB · Visitas: 547
Muy buena presentación. Poco a poco se consigue.

Para crear más diapositivas en blanco, pulsa "Control + M".

Pulsa sobre esa diapositiva con el botón derecho del ratón, en el menú emergente pulsa diseño de diapositiva.

Tendrás modos de presentar las diapositivas predefinidas para que se te hagan más fácil.
 
Hola a todos

Para los que querían el manual acá les dejo algo de lo que estoy haciendo:

Está hecho en word ya que la complejidad del tema no daba para hacerlo en power point.

Tengo algo de 18 páginas que es lo que pude hacer hasta ahora pero me falta muchisimo por desarrollar.

El manual final tendrá aproximadamente 300 o un poco más de páginas.

Las ideas o consejos sobre cosas que quieren que le agregue al manual de USB vallan diciendomelas en el foro.

Espero hacer el manual lo más pronto posible aunque todo depende de como esté de tiempo.
 

Adjuntos

  • pic18f2550_y_usb_134.pdf
    816.8 KB · Visitas: 675
hola amigos ! me interesa mucho esto que estan haciendo ! , yo solo conozco un lenguaje ! Delphi ! , si les interesa para ver si lo podemos portar a este lenguaje entonces me sumo ! , solo un pequeño punto es el inconveniente mio ! soy programador junior ! , espero me respondan !
 
Enarabuena Moyano Jonathan:

Menudo trabajo y tiempo te has currado el manual. Va tomando forma, veo que eres el pionero en hacer estas cosas y con estiloincluido.

Sigue así campeón.
 
Atrás
Arriba