Sign in to follow this  
Jack_Aubrey

EL arduino joy ....

Recommended Posts

Bueno chicos, estoy aqui una vez mas para lloraros.... no consigo que esto furrule ni a tiros... mejor dicho no consigo que furrule como yo quiero y es que por ahora lo unico que he conseguido es que parezca las luces de una discoteca. Todos y cada uno de los botones se encienden y apagan en una rapida sucesion; y para colmo de males los ejes parecen utilizados por un tio con parkinson volando a traves de una tormenta y con la cabina movida por el soft de Logikal.....

 

 

La cosa es que lo que creia que iba a ser la leche de dificil acaba siendo lo mas facil del mundo, formatear el chip de comunicaciones del arduino y ponerle tu propio .hex es mas facil de lo que parece, conseguir montar el programa que lea, organize y mande la info... es de locos :xd:

 

El hardware lo estaba montando con todos los pines de salidas con resistencias en pull down, conectando despues a una matriz con diodos antes de todos los botones y toggles. Solo un pin de salida no tendria pull down ni diodo que seria el de los ejes.

Aqui os pongo el codigo que he montado, como advertencia tengo que decir que utilizo la manipulacion directa de los puertos de la arduino y que por tanto es complicado de leer.

 

 

typedef struct
{
    int8_t  x; /**< Current absolute joystick X position, as a signed 8-bit integer */
    int8_t  y; /**< Current absolute joystick Y position, as a signed 8-bit integer */
    int8_t  z; /**< Current absolute joystick Z position, as a signed 8-bit integer */
    int8_t  Rx;
    int8_t  Ry;
    int8_t  Rz;
    uint8_t Button1;  // botones del 0 al 7
    uint8_t Button2;  //botones del 8 al 11 y 4 huecos
    uint8_t Button3;  //toggles del 0 al 7
    uint8_t Button4;  //toggles del 8 al 15
    uint8_t Button5;  //toggles del 16 al 23
    uint8_t Button6;  //toggles del 24 al 31
    uint8_t Button7;  //toggles del 32 al 39
} USB_JoystickReport_Data_t;

USB_JoystickReport_Data_t joyReport;


void setup()
{
  int i;
  Serial.begin(115200);
  for (i=2; i<13; i++)
  {
    pinMode(i, OUTPUT);
  }  
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(A4,INPUT);
  pinMode(A5,INPUT);
  poneracero ();
}

void loop ()
{
  while(1)
  {
    analogico();        // al tener un ligero delay loop al
                        //reiniciarse considero que he dejado
                        //tiempo para hacer una lectura limpia
                        //de los analogicos
    botonesytoggles();  //leo y los organizo
    Serial.write((uint8_t *)&joyReport,13); //mando la lectura
                                            //realizada
  }
}

void poneracero()  //pone a cero la el reporte
{                  
  for (int i=0; i<13; i++)
  {
    ((uint8_t*)&joyReport)[i]=0;
  }
}

void analogico()            //leo los ejes
{
  PORTB = B00010000;
  for (int i=0; i<6; i++)
  {
    ((int8_t *)&joyReport)[i] = analogRead(i);
  }
  PORTB= B00000000; //pongo en LOW todo el puerto B
}

void botonesytoggles ()//aqui manipulo los botones para encajarlos
{            //en la bitmask correspondiente
  uint8_t apoyo;
  uint8_t modifica;
 
  PORTD = B00000100;  // a high el pin 2
  joyReport.Button1 = (PINC & B00111111); //asigno del tiron la lectura
  //del puerto C, la mascara es por seguridad ya que supongo todos
  //los puertos son de 8bits y por tanto esos dos high bits
  //me tienen loco ya que el puerto C son 6 entradas...
  PORTD = B00001000; // a high el pin 3
  apoyo = (PINC & B00111111); // lo del 63 ya esta explicado
  joyReport.Button1 |= (apoyo<<6);
  joyReport.Button2 = (apoyo>>2); // hasta aqui llegaron los
                                  //botones
  PORTD = B00010000; // a high el pin 4
  apoyo = (PINC & B00111111);
  PORTD = B00100000; // a high el pin 5
  modifica = (PINC & B00111111);
  joyReport.Button3 ^= (apoyo| (modifica<<6));
  PORTD = B01000000; // a high el pin 6
  apoyo = (PINC & B00111111);  
  joyReport.Button4 ^= ((apoyo<<4)|(modifica>>2));
  PORTD = B10000000; // a high el pin 7
  modifica = (PINC & B00111111);
  joyReport.Button5 ^= ((apoyo>>6)|(modifica<<2));
  PORTD = B00000000; // a low todo el puerto D
  PORTB = B00000001; // a high el pin 8 que es el pin 0 del puerto B
  apoyo = (PINC & B00111111);
  PORTB = B00000010; // a high el pin 9 que es el pin 1 del puerto B
  modifica = (PINC & B00111111);
  joyReport.Button6 ^= (apoyo|(modifica<<6));
  PORTB = B00000100; // a high el pin 10 que es el pin 2 del puerto B
  apoyo = (PINC & B00111111);
  joyReport.Button7 ^=  ((apoyo<<4)|(modifica>>2));
  PORTB = B00000000;
}
 

 

 

Bueno lo siguiente que me queda es releerme el codigo con tranquilidad, ver si se me ha escapado un gazapo y si no pues probar a usar en vez de resistencias en pulldown, resistencias en pull up.

Share this post


Link to post
Share on other sites

asi a bote pronto veo que no preguntas si alguna entrada a cambiado de estado, simplemente las procesas con el AND y por eso creo que se te enciendo y apagando todo de forma ciclica.

Share this post


Link to post
Share on other sites

Buenooo al carajo el codigo yo lo que quiero es soldar .....:xd:

 

Aqui unas muestras:

 

La pesadilla:

 

sl372891.jpg

 

La primera etapa del multiplexado....

 

sl372892.jpg

 

otra foto por si no se ve bien

 

sl372893.jpg

 

la segunda etapa ' aqui el monstruo acabado (al menos la parte multiplexadora...) it's alive!!!!

 

sl372894.jpg

 

otra foto mas del multiplexado

 

sl372895.jpg

 

 

y como s que Bender estara por ahi al acecho las intimidades del monstruo

sl372896.jpg

 

 

Bueno espero que os guste ver que ya va avanzado algo el proyecto.... proximamente le doy al codigo :xd:

Share this post


Link to post
Share on other sites

Hola Jack_Aubrey, en primer lugar darte las gracias por ir informando del proyecto.

A ver yo llevó bastante tiempo dándole vueltas en hacerme una cabina ya que dispongo de espacio.

He estado haciendo pruebas e intentando leer e informarme mucho sobre interruptores, del tipo ON ON , ON OFF ON, el que se queda medio etc, pulsadores.....placas.....

En principio he echo pruebas aprovechando la placa de un gamepad de ps2 con el adaptador de pc e interruptores on off on de 6 contactos y van bastante bien e incluso se le puede incorporar un par de leds.

Ojo con la electrónica estoy muy pez eh, empiezo a aclararme ahora un poco pero en cosas muy muy básicas.

La cuestión es que tengo varios arduinos, uno y mega y también llevó tiempo mirando de aprovechar las mismas para el proyecto y así tener más salidas, de programación también 0, así que mal voy,he echo algunas cosillas pero también muy básico.

La cuestión es que sí no me equivoco lo que estas intentando hacer con lo de la matriz es multiplicar las salidas de arduino y así con un sólo arduino disponer de muchísimas más salidas para poder tener interruptores y pulsadores para hacer los paneles no?

Vamos cómo sí fuese un cubo de estos que se hacen con muchos leds.

Joer vaya tocho me está quedando.....

Voy a buscarte una información que vi hace tiempo y te la pongo por aquí a ver

sí te puede (nos puede) interesar ya que sí no entendí mal es lo mismo que estas haciendo tú pero sin tener que soldar tanto.

Sí puedes aunque fuese en un papel o paint podrías poner simplificado gráficamente el concepto arduino-matriz-pulsador para ver cual es el sistema de conexión que lleva? sólo el ejemplo de un pulsador para hacerme una idea.

La cosa me imagino que vendría a ser cómo una placa leo con la complicación de que hay que programar pero con la ventaja de todas las opciones que se puede hacer programado no?

Buena voy a buscar eso y con tú permiso lo pongo para que lo veas y así mires sí sirve.

Share this post


Link to post
Share on other sites

Lo encontré.....Jejeje, no sabía que lo

había guardado en el mobil..Jejeje

 

http://heserral.wordpress.com/2010/06/09/shift-register-esa-pequena-maravilla/

 

------- http://heserral.wordpress.com/2010/06/09/shift-register-esa-pequena-maravilla/ ------------

 

 

Quizás este yo equivocado y tú ya

sabías esTo o simplemente no tiene

nada que ver con lo tuyo y cómo digo

estoy confundiendo cosas, pero sí es lo

que yo creo, hay explica la forma de

comunicarte con cada pin.

Saludos y ya me dirás.

Share this post


Link to post
Share on other sites

La idea es mas basica que usar los shift registers.... y es usar una matriz de diodos.... la idea es que la arduino tiene 20 pines i/o de los cuales dos los pierdes para comunicarte con el chip del usb y este con el ordenata; nos quedan 18 pues ahora seguimos sumergiendonos en el funcionamiento de la arduino y buscamos exprimir la velocidad al maximo...

 

Si solo tenemos 18 pines queremos sacarle el mayor provecho y por eso podemos pensar en los shift register o la matriz. La matriz lo bueno que tiene es que solo requiere de algunos diodos (sutilmente mas baratos que el shift register.... unos 70 centimos los 100 que me compre...). Por otro lado aparentemente es muy complicada porque hay que secueciar la lectura pero tambien lo debes hacer con los shifts register.... la idea es que con los shifts register y se puede llegar a numeros realmente altos de componentes.... y la matriz no tiene tantos.... pero "la batalla no ha hecho mas que empezar".

 

Ahora es cuando si seguimos buceando en la arduino nos enteramos que los pines se agrupan en puertos de 8 bits (y que es un bocabyte... 8 bocabits :xd: no puede contenerme.... ¿siguen existiendo los bocabits????), cada puerto tiene asociado o puede manipular entre 8 y 6 pines.... pero a costa de complicar mucho la programación .... y esto es porque pasamos de un lenguaje que nos es mas entendible a algo mas cercano al codigo maquina. Ahora tenemos un puerto en el que estan agrupados los pines A0 a A5 que son capaces de funcionar como analogicos y digitales... usando este puerto como lectura nos quedamos con 14 pines para escribir.... lo que nos deja una matriz de 12x6 (72 componentes) lo cual me es mas que de sobra ya que busco tener 6 ejes y unos 46 interruptores/conmutadores/rotaries ( en mi caso 13/20/7 respectivamente...)

 

Mi problema es que no doy pie con bola al respecto del codigo para la arduino ... pero ya tengo montado y funcional el del chip de usb.

Share this post


Link to post
Share on other sites

Lo que yo se es que el limite de directinput es de 8 ejes, 128 botones y un hat... el pq "propiedades de dispositivo" solo enseña 32 es una incognita, ademas tengo entendido, en este post lo pone, que aparentemente cada simulador/juego tiene un maximo de "elementos" por dispositivos.

 

Ademas te incluyo alguna que otra foto que el apocaleches se llevo por delante de las pruebas que hice con el chip de comunicaciones de la arduino.

 

La del "propiedades de dispositivo"

propiedadestocandoloswe.jpg

 

 

La del tope de botones que me dio por probar ... visto en el SVmapper:

 

svmapperorgasmico.jpg

 

y por ultimo la del Dview

 

diviewordago.jpg

 

Todas las fotos son del mismo dispositivo.

 

Por todo lo que te digo creo que lo interesante es averiguar el limite de "elementos" por dispositivos del Il2-1946, ya que es el simulador en el que especificamente quiero volar.

Edited by Jack_Aubrey

Share this post


Link to post
Share on other sites

Yo es que haciendo pruebas con un PIC, donde tienes que hacer a manubrio el archivo de descriptores, probe a poner mas de 32, tambien con una matriz, aunque los botones fisicamente no llegue a implementarlos, y directamente el dispositivo no se instalaba.

El arduino o la libreria del unojoy deben gestionar algo internamente que permite poner botones a casquijo

Share this post


Link to post
Share on other sites

Frajo no eres paleto.... es que esto es muy hardcore :xd: ... el dia que lo consiga y lo monte.... ese es el dia que sus flipareis, ya que mi intencion es montar un paso a paso para que todos (bueno casi todos ... que así me evito problemas posteriores :roto2h: ) lo que lo quieran intentar lo tengan mas facilico que yo :xd:

Share this post


Link to post
Share on other sites

En el hilo borrado creo que hablamos un rato de eso... pero quiero que comprendas que mi conocimiento del descriptor del usb es cuando menos el justo para hacerlo y poco mas... supongo que te podria decir algo mas si veo el codigo,pero seria por comparacion con el mio.

Share this post


Link to post
Share on other sites

Que ya te pondre yo el mio para que hagas la ingenieria inversa... que ahora mismo toy muy perroo!!.

a veces he pensado que no te funcionaba el dispositivo por fallo del descriptor mas que por fallos en otra parte.

Ya lo veremos ;)

Share this post


Link to post
Share on other sites

0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xA1, 0x01, // COLLECTION (Application)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x09, 0x35, // USAGE (Rz)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xC0, // END_COLLECTION
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x38, // USAGE_MAXIMUM (Button 56)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x38, // REPORT_COUNT (56)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None) Yo esto no lo use nunca para hacer funcionar los botones, pasaba del report count al input

0x81, 0x02, // INPUT (Data,Var,Abs)
0xC0, // END_COLLECTION

 

Aparte de la nota que te he puesto, la estructura del descriptor es un poco puñetera y yo probe ejemplos que la peña decia que funcaban pero a mi naranjas

 

 

Este es el descriptor de 1 eje de 10 bit de resolucion y 4 botones, veras como hice la estructura de usages y collections

0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x03, // Log Max (1023)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs) <- 10-bit axis
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x02, // USAGE_MAXIMUM (Button 2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs) <- Buttons * 2
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x03, // INPUT (Cnst,Var,Abs) <- Padding bits
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x02, // USAGE_MAXIMUM (Button 2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs) <- Buttons * 2
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x03, // INPUT (Cnst,Var,Abs) <- Padding bits
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION

 

El codigo del joy.c, quiero entender lo que hace, pero hay una cosa que lo mismo te puedes ahorrar.

Debes tener en cuenta que el report con al info del dispositivo se manda siempre y se manda siempre lleno al 100%

Asiq ue no tienes que calcular el tamaño que debes mandar en el reporte.

Si tienes 6 ejes de 8 bits, 56 botones, que son otros 7 bits, importante, mas otro byte vacio que hay que mandale siempre al HID para que se entere de que el reporte ha terminado, tu tienes que mandarle 14 bytes a piñon siempre y le quitas de andar calculando tamaños.

 

Cuando tu tratas las señales, miras un puerto, ¿esta alto? le pones su bit a 1, que no, se lo pones a 0. Ni compruebes el estado anterior del bit, lo cambias a piñon.

Para los ejes lees el puerto y el valor que te pase se lo metes a la variable que toque o la posicion del array del report que corresponda o como lo hagas, que no he identificado en el codigo como reunes la informacion de cada puerto.

Share this post


Link to post
Share on other sites

la idea del comprabar el estado anterior es solo en los toggles, en el resto se lo meto a piñon y lo que dices de los ejes es como lo he montado. Mañana me pondre un rato con el codigo a burrearlo un rato y tratare de montar algo mas descriptivo la respuesta que ponga aqui.

Share this post


Link to post
Share on other sites

uff me he dado cuenta que en verdad no conservo el estado de los toggles y que estos se vuelven locos y cambian siempre :xd:

 

digamos que lo que guardo en button es la respuesta logica de XOR a la pregunta de si cambia de posicion.... pero comparando con la anterior respuesta logica XOR y que es un mega fallo :xd:

Share this post


Link to post
Share on other sites

Para hacer eso debo tener un array de los estados anteriores de cada toggle (los estoy llamando permanentes ya que no son momentaneos .... pq no se que nombre en cristiano deberia usar... ¿conmutador??), compararlos con la lectura del estado actual y con la respuesta al XOR actuar...

Share this post


Link to post
Share on other sites

que no, si te dan alta, los pones en alto si te dan bajo los pones en bajo.

¿Que mas te da saber lo que tenian antes? ¿para que cuando los estados coincidan, no cambiarlos?, para que quieres esa logica si el codigo queda mucho mas sencillo y corto, que a la memoria del chip le biene de perlas, sin la comprobacion y funciona igual de bien.

 

Yo tuve que hacer una comprobacion del estado anterior para convertir un rotatorio de 12 posiciones en un conmutador rotatorio de 2 posiciones, de forma que girar a la derecha devuelve el input, de por ejemplo, el boton 1 y girar a la izquierda el del 2. Ademas tuve que tratar la señal por codigo para que en vez de devolver una pulsacion continua, el mismo pic pusiera el puerto en baja y parar la entrada de la señal del rotatorio. Cuando volvia a ponerse en alta es que se habia movido el conmutador, miraba que boton debia encender y paraba la señal de entrada.

 

Pero en los comutadores de dos posiciones, que parriba pulsa un boton y pabajo otro, comprobar el estado anterior es inutil, mas siendo comutadores momentaneos, de esos que la posicion de reposo es el centro, que es el off. Hazme caso, lee el puerto de entrada del conmutador y enciende un led con lo que te de. Con eso funciona perfect.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this