Mando recreativa multijugador

Buenas
Quería compartir con el foro el proyecto de mando arcade con Arduino Pro Micro.

Después de mucho buscar por google como hacer un mando arcade con Arduino Leonardo (Arduino micro lleva el mismo procesador), sólo he encontrado la manera de hacerlo con un sólo jugador (1 mando y, entre 2 y 4 botones).
Como quería hacerlo para poder colocarlo en mi arcade de 2 jugadores con 6 botones cada uno, por tanto necesitaba 10 botones para jugador 1, 10 para jugador 2, 2 para monedas, 2 para 2 “start 1 y 2”, 1 para “escape”, 1 para “configuración” y 2 para botones “pinball” total: 28 botones.
Con la manera de hacerlo que encontré en muchas páginas me faltaban pines para poder implementarlo, ya que los botones iban en modo directo (pin-botón-masa), por lo que se me ocurrió de hacerlo en modo matriz.
Después de leer bastante sobre matrices de teclado, se me planteó el problema de la doble lectura y las pulsaciones de 2 teclas o más a la vez, que sólo funcionaban si eran de la misma fila, y que al leer de la matriz puede leer un pin de una columna que no corresponda a la tecla pulsada. Esto lo solucioné mediante diodos de manera que sólo pudiese leer el estado HIGH en una dirección.

El código es bastante sencillo.
Básicamente consiste en poner a HIGH secuencialmente los pines fila que alimentan cada set (1 al 4). Cuando un set está en HIGH se lee secuencialmente el estado los pines de las columnas (1 a 8 ) y si está a HIGH es que el botón (fila,columna) está pulsado y si está a LOW es que está liberado. Cada acción envía la tecla correspondiente. Cada par fila-columna se convierte en un índice para leer cada tecla en la matriz de teclas. El código está comentado.

/* Mando arcade USB con Arduino Pro Micro ATmega32u4.
   Disponibles 32 teclas configurables. Matriz de 8x4.
   Con las posibilidades del Arduino Micro se puede elevar el número de teclas.
   Libreria "Keyboard.h" incluida en el IDE.
   No tiene efecto ghosting.
*/

#include <Keyboard.h>

#define numButtons 32 // Define el número de botones

//VARIABLES DEL PROGRAMA
byte scanPin[] = {2, 3, 4, 5, 6, 7, 8, 9}; //Matriz [8] con los pines para lectura del estado de las teclas
byte pinKeys[] = {10, 16, 14, 15}; //Matriz [4] para los pines activados en el escaneo de teclas

//IMPORTANTE: Mandar las pulsaciones en minúculas, si no, envia un SHIFT también
byte Keys[numButtons] = {
  //PRIMER SET 1-8
  KEY_UP_ARROW, //    P1 Arriba (Flecha Arriba)
  KEY_DOWN_ARROW, //  P1 Abajo (Flecha Abajo E0)
  KEY_LEFT_ARROW, //  P1 Izquierda (Flecha Izquierda)
  KEY_RIGHT_ARROW, // P1 Derecha (Flecha Derecha) E0
  KEY_LEFT_CTRL, //   P1 Botón 1 (Ctr Izquierdo)
  KEY_LEFT_ALT, //    P1 Botón 2 (Alt)
  ' ', //             P1 Botón 3 (Espacio)
  KEY_LEFT_SHIFT, //  P1 Botón 4 (May izquierda)

  //SEGUNDO SET 8-16
  'r', //             P2 Arriba (r)
  'f', //             P2 Abajo (f)
  'd', //             P2 Izquierda (d)
  'g', //             P2 Derecha (g)
  'a', //             P2 Botón 1 (a)
  's', //             P2 Botón 2(s)
  'q', //             P2 Botón 3 (q)
  'w', //             P2 Botón 4 (w)

  //TERCER SET
  '1', //             GLOBAL START PLAYER 1 (1)
  '2', //             GLOBAL START PLAYER 2 (2)
  't', //t            P1 Botón 5 (t)
  'z', //z            P1 Botón 6 (z)
  KEY_RIGHT_CTRL, //  P2 Botón 5 (Ctr derecho)
  'm', //             P2 Botón 6 (m)
  KEY_ESC, //         GLOBAL ESC
  KEY_TAB, //         GLOBAL Tab

  //CUARTO SET
  '5', //             GLOBAL Coin 1 (5)
  '6', //             GLOBAL Coin 2 (6)
  'p', //             GLOBAL Pause (p)
  '4', //             Por definir (4)
  '3', //             Por definir (3)
  KEY_RETURN, //      GLOBAL Enter
  '7', //             Por definir (7)
  '8' //              Por definir (8)
};


void setup()  {
  //Configuración
  //Configura los pines para el escaneo de teclas
  for (byte n = 0; n < 4; n++) {
    pinMode(pinKeys[n], OUTPUT); //Configura los pines como salida
    digitalWrite(pinKeys[n], LOW);//Los escribe en bajo
  }
  for  (byte n = 0; n < 8; n++) {
    pinMode(scanPin[n], INPUT); //Configura los pines como entrada
  }
  Keyboard.begin(); //Inicia el teclado
}

void loop()  {
  //Escaneo de teclas
  for (int i = 1; i < 5; i++) //Bucle que levanta HIGH los pines de salida uno por uno
  {
    digitalWrite(pinKeys[i - 1], HIGH); //Levanta a HIGH el pin correspondiente
    for (int j = 1; j < 9; j++)
    {
      //Escanea los pines  de la matriz para ver el estado de las teclas
      //delay(10); //Evita los rebotes
      int state = digitalRead(scanPin[j - 1]); //Lee el estado de uno de los 8 pines de lectura
      byte indice = (j * i) + ((i - 1) * (8 - j)) - 1; //Índice de códigos teclas de la matriz
      char valorKey = Keys[indice];

      if (state == HIGH) //Si hay lectura de +5 es que la tecla (i,j) está pulsada
      {
        Keyboard.press(valorKey);  //Envia la tecla como presionada
      }
      else //Si no hay lectura es que la tecla (i,j) NO está pulsada
      {
        Keyboard.release(valorKey);  //Suleta la tecla
      }
    } //Next a j
    digitalWrite(pinKeys[i - 1], LOW); //Vuelve a LOW el pin correspondiente
  }//Next a i
}

El esquema de conexionado es el siguiente:
Por claridad y espacio, he puesto sólo el set 1 (recuadro de lineas y puntos), el set 2, 3 y 4 son exactamente iguales sólo que el cable rosa va al pin correspondiente del Arduino (en este caso el set 2 al pin 16, el set 3 al pin 14, y el set 4 al pin 15).
Es imprescindible colocar las resistencias de 10Kohm, son resistencias PULL-DOWN


Foto del esquema

Y una imagen del cacharrillo montado con la maraña de cables:


Foto del montaje

Ni que decir tiene que hay que instalar los drivers para el ATmega32u4 en el sistema operativo donde se va a colocar el mando. Los driver vienen en las carpetas del IDE de Arduino.
En Ubuntu 16, tanto el bootloader como la interfaz USB las ha detectado automáticamente, pero en Windows 7 he tenido que descargar los drivers para la detección del bootloader (necesario para subir el programa al Arduino). Los drivers los he descargado de la siguiente dirección:
Arduino_Boards

La grabación hay que realizarla de una manera especial (por lo menos a mi entender).
Tutorials pro-micro--fio-v3-hookup-guide
En esta página está muy bien explicado. Pero para los que no se lleven bien con el inglés...
Para meter el Ardunio en modo "programación" hay que puentear el pin RST y GND. Recomiendo soldar un botón entre ambos pines para mayor comodidad (el Leonardo lo lleva). Una vez pulsado (o puenteado) el ordenador detectará un nuevo hardware y hay que instalar los drivers de la página anterior (una vez descomprimido navegar por las carpetas hasta el driver ...Carpeta donde se haya descomprimido\Arduino_Boards-master\sparkfun\avr\signed_driver)

Una vez instalado correctamente el driver en Windows, pulsamos de nuevo el botón reset (o puenteamos) y en el IDE saldrá un puerto COM. Hay que ir rápido a seleccionarlo ya que en este modo el Arduino sólo está 8 segundos. Dejarlo seleccionado aunque desaparezca (en el IDE abajo aparecerá Arduino… en COMx). Pulsamos subir y cuando la barra de compilación hay terminado inmediatamente pulsar (o puentear) el reset. Con esto el programa subirá dando el IDE el mensaje de"subido".
Los drivers para que funcione como teclado están en el propio IDE de Arduino en ..\la carpeta de instalación\arduino-1.x.x\drivers)

Repito, en mi Ubuntu 16 no he tenido que instalar nada.

Ante mi falta de experiencia en Leonardos y Micros la primer vez "brickeé" el Arduino, en la página anterior hay instrucciones para "desbrickearlo".

Ojo con los errores cuando se trabaja con Leonardo o Micro ya que al detectarlo como teclado si manda pulsaciones caóticas puede que el ordenador se haga incontrolable. Como me pasó, lo solucioné así (tras varios intentos). Buscar el error en el código, darle a subir, cuando esté terminando la compilación, enchufar el USB, darle al reset del Arduino inmediatamente, cruzar los dedos y esperar a "subido" (si hay otra manera mejor, no la he encontrado).

Seguro que se puede mejorar, puede que haya algún error, pero lo tengo funcionando un mes y por el momento va perfecto.

Bueno por unos 10€ una interfaz para el panel de la recreativa totalmente configurable y DIY ( lo importante para mi). Espero que sirva de ayuda a alguien.

Estas usando el enlace de la página no el Url de la thumbnail
usa la segunda URL y edítalos por favor.

Editado el primero y eliminado el segundo post.

Gracias Surbyte por la aclaración.

pepepotero hola, copile tu codigo y me error en la linea KEY_UP_ARROW