Autor Tema: Control de dispositivos a través del módulo USB del PIC18F4550  (Leído 4382 veces)

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

Desconectado c1ar8l0os

  • PIC10
  • *
  • Mensajes: 2
Hola muchachos....
Saludos a todos.
Soy el nuevo por aquí... :grin:

Este es mi 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:




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: [Seleccionar]
    ...
    ...
    ////////////////// 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()) {}  :z)

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...?

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.

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.

Gracias de antemano.
« Última modificación: 12 de Junio de 2009, 21:34:52 por c1ar8l0os »

Desconectado rodrigo_control2009

  • PIC12
  • **
  • Mensajes: 54
    • Blog  de la  Orden del  temple
Re: Control de dispositivos a través del módulo USB del PIC18F4550
« Respuesta #1 en: 18 de Julio de 2009, 22:09:57 »
Hola no se si ya encontraste  el problema te agradecería si me  la  puedes  enviar.
Yo  tb estoy haciendo algo pareceido y  utilizo las  sgte rutinas aunq  esta en una tarea rtos y funciona relativamente bien pero con errores. Para que otros  te  ayuden es bueno  que  agregues  parte del codigo que exactamente usas   asi es más probable que te respondan.

void addbufferrecusb(){
usb_task();
if (usb_enumerated()){
if usb_cdc_kbhit()) recepcion=usb_cdc_getc();
if (recepcíon !=0x00){usb_cdc_putc (recepcion);
switch(recepcion){
case  xxxxx
break;
default:
bufferrecusb[xbufferrecusb++]=recepcion;
}
}
}
recepcion=0x00;
rtos_yield();
}

Esta  rutina comunmente la he  visto en bucles  do{ xxxxx } while(true); como parte de un  main()
“El hombre ideal, sería persa de origen, árabe de religión, iraquí por cultura, hebreo por experiencia, cristiano por conducta, hindú por perspicacia, sufí por su estilo de vida, angélico por su moral y divino por sus ideas y conocimiento, destinado a la eternidad”

Desconectado c1ar8l0os

  • PIC10
  • *
  • Mensajes: 2
Re: Control de dispositivos a través del módulo USB del PIC18F4550
« Respuesta #2 en: 01 de Agosto de 2009, 16:13:44 »
Hola rodrigo.

No logré solucionar el problema, depuré el programa muchas veces sin solventar el inconveniente.
Yo había seleccionado la clase CDC como una opción relativamente sencilla en la comunicaciones PC-PIC, pero en realidad no es obligatorio que sea CDC.

Así que decidí optar por otra clase, y desarrollé el programa en HID, la programación del PIC no cambió mucho, donde me costo un poco mas fué en la parte de Visual Basic con HID.

Pero gracias a esta inteligente mujer de 51 años Jan Axelson () y su libro "USB Complete: Everything You Need to Develop Custom USB Peripherals" Second Edition, y a los códigos aportados en su página www.lvr.com, logré desarrollar un sistema PC-PIC usando la clase HID totalmente funcional y sin problemas.

De todas formas a continuación te coloco el código en VisualB_6 y en CCS que usé para CDC.

Este es el código en VisualB_6:

Código: [Seleccionar]
        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

Este es el código en CCS:

Código: [Seleccionar]
        #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!
« Última modificación: 01 de Agosto de 2009, 16:28:04 por c1ar8l0os »


 

anything