TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: rachelies en 24 de Abril de 2010, 07:03:49
-
Hola a todos.
Estoy intentando hacer algo parecido a un joystick, con un pic18f2455, conectado por usb al pc, utilizando los descriptores hid, y apoyandome en varias ideas que he visto en este y otros foros. El tema es que tengo un par de potenciometros conectados a la entrada AN0 y AN1, con una resolucion de 10bits, y esto correspondería al eje X e Y, y 16 botones que de momento para las pruebas los tengo con unos valores fijos. El problema es que con sólo mover el potenciometro un poco, cuando pasa de 0V a 0.2V, se desplaza el eje al otro extremo, no se mueve de forma progresiva según el potenciometro, sino que parece digital y con solo mover un poco el potenciometro se sitúa al otro extremo de los ejes. Pongo aqui el código en C de CCS y el HID Descriptor para ver si alguien me puede ayudar y darme una idea sobre lo que hago mal. Muchas gracias:
#include <18F4550.h>
#device ADC=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#DEFINE USB_HID_DEVICE TRUE
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8
#include <pic18_usb.h>
#include <.\include\usb_gamepad_HID3.h> //USB Configuration and Device descriptors for this USB device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <ctype.h>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main(void) {
long valor0,valor1;
long out_data[3];
set_tris_A(0b0000001);
setup_adc_ports(AN0_to_AN1);
setup_adc(ADC_CLOCK_DIV_64);
usb_init_cs();
while (TRUE) {
usb_task();
if (usb_enumerated())
{
output_high(PIN_B4);
set_adc_channel(0);
delay_us(15);
valor0=read_adc();
set_adc_channel(1);
delay_us(15);
valor1=read_adc();
{
out_data[0]=valor0; // Ejes X y Y
out_data[1]=valor1;
out_data[2]=0b1010101010101010;
usb_put_packet(1,out_data,6,USB_DTS_TOGGLE);
}
}
}
}0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
0x09, 0x05, // usage Device is a gamepad
0xA1, 0x01, // collection (application) This collection encompasses the report format
0x09, 0x01, // usage (pointer) Choose the key code usage page
0xA1, 0x00, // collection (physical) Physical collection
0x09, 0x30, // usage (X) X direction of pointer
0x09, 0x31, // usage (Y) Y direction of pointer
0x15, 0x00, // logical minimum (0)
0x25, 0x7F, // logical maximum (127)
0x35, 0x00, // PHYSICAL minimum (0)
0x45, 0x7F, // PHYSICAL maximum (127)
0x75, 0x10, // report size (8)
0x95, 0x02, // report count (2) Two reports, eight bit each
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection
0x05, 0x09, // usage page (buttons) Choose the “button” usage page
0x19, 0x01, // usage minimum (1) There are three buttons
0x29, 0x10, // usage maximum (16)
0x15, 0x00, // logical minimum (0) Each button is represented by one bit
0x25, 0x01, // logical maximum (1)
0x95, 0x10, // report count (16) Three reports, one bit each
0x75, 0x01, // report size (1)
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection
-
El error está en que usb_put_packet recibe arreglos de 8 bits y tú le estás entregando un arreglo long.
-
Muchas gracias por la respuesta.
Creo que ayer lo probé todo con 8 bits y me hacía lo mismo, volveré a probar.
¿Cómo haría el usb_put_packet para envíar un valor de 16 bits? He visto un proyecto similar del que tengo el .hex, y trabaja con el conversor A/D a 10bits, y en el HID Descriptor está todo definido como 10bits.
Gracias y un saludo
-
No puedes enviar lo que tú quieras, tienes que enviar lo que estás describiendo en el descriptor de reporte.
Veo otro problema...
0x15, 0x00, // logical minimum (0)
0x25, 0x7F, // logical maximum (127)
0x35, 0x00, // PHYSICAL minimum (0)
0x45, 0x7F, // PHYSICAL maximum (127)
No conozco mucho de los reportes de joystick, pero ahí estás indicando que tu dato sólo llegará a 127 (7 bits) y tú quieres enviar 10.
usb_put_packet() puede modificarse para enviar cualquier cosa, pero el contenido enviado siempre debe estar conforme al descriptor de reportes.
-
Si, lo he puesto de 7 bits, ahora mismo voy a probar con 8bits, y en cuanto me funcione correctamente pasaré a 10bits. Ayer probando con 8bits me pasaba lo mismo, que con mover un poco el potenciometro ya saltaba hasta el extremo del eje. ¿Puede ser problema de configuración del conversor A/D debido a la velocidad seleccionada del pic?
Gracias
-
No. Si tienes una medición de 8 bits y la envías a algo que la interpretará como 7 bits, el bit más significativo será truncado.
Luego entonces, si el ADC está midiendo 0b01111111 (127) y mueves el stick y cambia a 0b10000000 (128), lo que el receptor verá es:
1111111 (127)
0000000 (0)
Si configuras un dato a 7 bits, envíalo a 7 bits.
-
OK, comprendido.
Aqui pego el código con el que estoy probando ahora y sigue haciendo lo mismo: con nada que mueva el potenciometro se me va a fondo de escala.
#include <18F4550.h>
#device ADC=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#DEFINE USB_HID_DEVICE TRUE
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8
#include <pic18_usb.h>
#include <.\include\usb_gamepad_HID2a.h> //USB Configuration and Device descriptors for this USB device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <ctype.h>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
int8 valor;
int8 out_data[3];
void main(void) {
set_tris_A(0b0000001);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
usb_init_cs();
while (TRUE) {
usb_task();
if (usb_enumerated())
{
output_high(PIN_B4);
set_adc_channel(0);
delay_us(20);
valor=read_adc();
{
out_data[0]=valor; // Ejes X y Y
out_data[1]=valor;
out_data[2]=0b10101010;
usb_put_packet(1,out_data,3,USB_DTS_TOGGLE);
}
}
}
}0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
0x09, 0x05, // usage Device is a gamepad
0xA1, 0x01, // collection (application) This collection encompasses the report format
0x09, 0x01, // usage (pointer) Choose the key code usage page
0xA1, 0x00, // collection (physical) Physical collection
0x09, 0x30, // usage (X) X direction of pointer
0x09, 0x31, // usage (Y) Y direction of pointer
0x15, 0x00, // logical minimum (0)
0x26, 0xFF, 0x00, // logical maximum (255)
0x35, 0x00, // PHYSICAL minimum (0)
0x46, 0xFF, 0x00 // PHYSICAL maximum (255)
0x75, 0x08, // report size (8)
0x95, 0x02, // report count (2) Two reports, eight bit each
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection
0x05, 0x09, // usage page (buttons) Choose the “button” usage page
0x19, 0x01, // usage minimum (1) There are three buttons
0x29, 0x08, // usage maximum (8)
0x15, 0x00, // logical minimum (0) Each button is represented by one bit
0x25, 0x01, // logical maximum (1)
0x95, 0x08, // report count (8) Three reports, one bit each
0x75, 0x01, // report size (1)
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection
-
Lo he modificado todo para trabajar solamente con el ejeZ, sin botones ni nada, a 8 bits, y ¡¡¡funciona!!!
Por lo menos ya estoy más tranquilo e iré añadiendo ejes poco a poco.
Un saludo