Pages: [1]   Go Down
Author Topic: Simular Teclado  (Read 2768 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
I Love YaBB 2!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Se podria simular un teclado con el arduino?
Logged

Forum Administrator
MMX
Offline Offline
Edison Member
*****
Karma: 37
Posts: 1139
hallo kompis
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

este es un problema que pasa por tener la definicion de dispositivo dentro de Arduino. Es decir, que tendria que haber algo que identificase a Arduino como un teclado y, no lo hay.

Con la ultima version (Arduino NG) existe alguna posibilidad, pero no le hemos metido mano.

La ultima solucion seria que los drivers del USB fueran open source y se pudiesen reescribir para que comunicasen con el sistema operativo como si fuera un teclado.

Te sientes con fuerzas para probar?

/David
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
I Love YaBB 2!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Que drivers usb los que hay dentro del arduino?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

casualmente yo necesitaba hacer algo parecido, y lo he conseguido haciendo algunas "chapucillas". En concreto, estaba interesado en conectar un Joystick de una Megadrive al PC para poder jugar al MAME (un emulador de maquinas arcade) simulado el teclado.

Hay dos soluciones, la "facil" y la "elegante". Yo opte por la "facil", porque soy nuevo en lo de Arduino y la electronica en general, y porque en realidad solo queria comprobar si funciona (ya he pedido un mando arcade profesional). La solucion:

1. Conectar el arduino al mando. Para arduino desarrole un pequeño sketch capaz de leer el estado de los controles (no entro en detalle)
2. Enviar cada movimiento (cambio de estado) del mando/botones al puerto serie. Por ejemplo, si el usuario pulsa el boton A, arduino escriben en el puerto serie "+A\n", cuando deja de pulsarlo, escribe un "-B\n", etc.
3. En el PC (Windows XP), tengo un programa leyendo del puerto serie (desarrollo a medida tambien), y convierte cada uno de los mensajes que lee en eventos del teclado de windows, enviandolos a la cola de mensajes del sistema con SendInput(). He tenido algun problemilla con caracteres especiales (cursores) y por el hecho de que el programa al que quiero hacer llegar las pulsaciones de teclado (MAME) utiliza DirectX para leerlo, pero ayer por fin consegui jugar la primera partida.

Si esa solucion te basta, puedo hacerte llegar el codigo fuente del sketch y del programa windows para enviar pulsaciones. Lo tengo en casa y ahora no puedo acceder, esta noche le echare un vistazo.

La opcion "elegante", y que estuve a punto de probar cuando no habia manera de que el programa en DirectX me reaccionase a los eventos de teclado, es hacer pasar al Arduino por un teclado USB (como comentan arriba). Efectivamente, yo estuve mirando por Internet y no encontre nada que hiciese que Arduino pudiese pasar por un teclado USB, pero encontre un codigo de Objective Development que no es mas que un firmware USB. Tengo mis dudas de que pueda funcionar (Arduino ya se identifica como tal en el canal USB, y no se si es posible reescribirlo a bajo nivel para que se identifique como teclado y, en ese caso, si luego podria utilizarse otra vez como arduino -upload de programas- sin hacer algo mas que resetearlo).

Aqui tienes el enlace:

http://www.obdev.at/products/avrusb/index.html

El codigo original es para un ATMel8, creo, asi que teoricamente deberia funcionar con cambios menores (siempre y cuando se pueda hacer lo que te comento en el parrafo anterior), modificandolo para que utilice los PINs de comunicacion segun la placa arduino. El codigo es libre para desarrollo y pruebas -creo, la licencia de uso de los ID de vendor, etc. del USB estan en esa web- y trae esquemas de conexion de circuito, etc.

       Espero que eso sirva. Si alguien ve que esta opcion es un poco imposible (que arduino no pueda hacerse pasar por dos dispositivos USB al mismo tiempo), le agradeceria que me lo comentase, y asi salgo de dudas

       Un saludo,
       Jose
« Last Edit: October 31, 2006, 03:48:08 pm by primijos » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Aunque no entiendo mucho de esto, este programa (http://carl.kenner.googlepages.com/glovepie) creo que puede ayudar en la redirección a directx de las entradas de Arduino.
« Last Edit: December 07, 2006, 01:23:31 pm by rashomon » Logged

Forum Administrator
MMX
Offline Offline
Edison Member
*****
Karma: 37
Posts: 1139
hallo kompis
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

primijos: puedes dar mas informacion de tu experimento con el joystick? Estoy seguro de que mucha gente se beneficiaria de el. En concreto el software que simula clicks de teclado seria perfecto para muchas aplicaciones.

Un saludo,

/David
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


      Hola,

      disculpad, se me paso volver e incluir la info O:-) Ahi va:


Como os decia, mi experimento consistio en conectar un joystick de una megadrive a arduino y emular pulsaciones de teclado a partir de los movimientos del joystick. La informacion de los pins del joystick la saque de aqui:

http://pinouts.ru/Game/genesiscontroller_pinout.shtml

A partir de ahi conecte los pins al arduino, con el siguiente mapeo:

Joystick - Arduino
========
P1 - A1
P2 - D2
P3 - D3
P4 - D4
P5 - 5V
P6 - D6
P7 - D7
P8 - GND
P9 - D5

Siendo Px el Pin X en el conector del joystick, Ax=pin Analog X, Dx = pin Digital X, 5V = pin 5V y GND = pin GND en el arduino.

El programa -cutre, sin optimizar, etc.- para leer las señales del joystick y enviarlas por el puerto serie al arduino es este:

/* Megadrive joystick <-> keyboard interface
 * -----------------------------------------
 *
 * @author: Jose Oliver Segura
 */





int pin1 = 1;
//#define pin1 1
int pin2 = 2;
int pin3 = 3;
int pin4 = 4;
int pin6 = 6;
int pin7 = 7;
int pin9 = 5;

int up     = 0;
int down   = 0;
int left   = 0;
int right  = 0;
int aButt  = 0;
int bButt  = 0;
int cButt  = 0;
int sButt  = 0;

char buttStatus[] = {'-','+'};

void setup(){
  Serial.begin(115200);
  pinMode(pin1, INPUT);
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);
  pinMode(pin4, INPUT);
  pinMode(pin6, INPUT);
  pinMode(pin7, OUTPUT);
  pinMode(pin9, INPUT);
}

void readSignals() {
  digitalWrite(pin7,0);
  int aButtStat = !digitalRead(pin6);
  int sButtStat = !digitalRead(pin9);
  digitalWrite(pin7,1);
  int uStat = !(analogRead(pin1) > 100);
  int dStat = !digitalRead(pin2);
  int lStat = !digitalRead(pin3);
  int rStat = !digitalRead(pin4);
  int bButtStat = !digitalRead(pin6);
  int cButtStat = !digitalRead(pin9);
  if (uStat!=up) {
    up = uStat;
    Serial.print(buttStatus[up]);
    Serial.println("u");
  }
  if (dStat!=down) {
    down = dStat;
    Serial.print(buttStatus[down]);
    Serial.println("d");
  }  
  if (lStat!=left) {
    left = lStat;
    Serial.print(buttStatus
);
    Serial.println("l");
  }  
  if (rStat!=right) {
    right = rStat;
    Serial.print(buttStatus
);
    Serial.println("r");
  }  
  if (aButtStat!=aButt) {
    aButt = aButtStat;
    Serial.print(buttStatus[aButt]);
    Serial.println("a");
  }  
  if (bButtStat!=bButt) {
    bButt = bButtStat;
    Serial.print(buttStatus[bButt]);
    Serial.println("b");
  }
  if (cButtStat!=cButt) {
    cButt = cButtStat;
    Serial.print(buttStatus[cButt]);
    Serial.println("c");
  }
  if (sButtStat!=sButt) {
    sButt = sButtStat;
    Serial.print(buttStatus[sButt]);
    Serial.println("s");
  }      
}
  

void loop() {
   readSignals();
  
}


Como se ve, lee las señales y envia +/- para indicar pulsacion/liberacion de tecla, seguido de una letra que indica la tecla o movimiento de joystick: u,d,l,r => arriba,abajo,izquierda,derecha, a,b,c=>disparo a,b,c, s=>select.

En el PC, programe un pequeño programa en C utilizando el visual C express edition gratuito de MS, que simplemente lee del puerto serie y cada vez que encuentra una pulsacion/liberacion de tecla, genera un evento sintetico de teclado. Os lo incluyo en el siguiente post porque estoy llegando al maximo de caracteres de este mensaje :-/
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... continuado... ahi va el programa en C para la parte del PC:

#define _WIN32_WINNT 0x501

#include <windows.h>
#include <winuser.h>
#include <stdio.h>




int main(int argc, char *argv[])
{
   DCB dcb;
   HANDLE hCom;
   BOOL fSuccess;
   //char *pcCommPort = "COM1";
   char *pcCommPorts[10] = {"COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","COM10"};
   //char *pcCommPort;
   char *pcCommPort = "\\\\.\\COM10";
   char message[256];
   /*CString pcCommPort(_T("COM10"));*/
   /*LPCWSTR pcCommPort = L"COM10";*/

   //for (int i=0;i<11;i++) {
         //pcCommPort = pcCommPorts;
   printf("opening port: %s\n",pcCommPort);
   hCom = CreateFile(pcCommPort,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    NULL, // no security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    0,    // not overlapped I/O
                    NULL  // hTemplate must be NULL for comm devices
                    );

   if (hCom == INVALID_HANDLE_VALUE)
   {
       // Handle the error.
         FormatMessage(      FORMAT_MESSAGE_FROM_SYSTEM,
                                    0,
                                    GetLastError(),
                                    0,
                                    message,
                                    256,
                                    NULL);
         printf ("CreateFile failed with error %d for port %s: %s.\n", GetLastError(),pcCommPort,message);
       return (1);
   }
   //}

   // Build on the current configuration, and skip setting the size
   // of the input and output buffers with SetupComm.

   fSuccess = GetCommState(hCom, &dcb);

   if (!fSuccess)
   {
      // Handle the error.
      printf ("GetCommState failed with error %d.\n", GetLastError());
      return (2);
   }

   // Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.

   dcb.BaudRate = CBR_115200;     // set the baud rate
   dcb.ByteSize = 8;             // data size, xmit, and rcv
   dcb.Parity = NOPARITY;        // no parity bit
   dcb.StopBits = ONESTOPBIT;    // one stop bit

   fSuccess = SetCommState(hCom, &dcb);

   if (!fSuccess)
   {
      // Handle the error.
      printf ("SetCommState failed with error %d.\n", GetLastError());
      return (3);
   }

   printf ("Serial port %s successfully reconfigured.\n", pcCommPort);
   unsigned long readed = 0;
   char buff[128];

   INPUT input[2];
   input[0].type=INPUT_KEYBOARD;
   input[0].ki.wVk=65;
   //input[0].ki.wScan=KEYEVENTF_SCANCODE;
   input[0].ki.wScan=0;
   input[0].ki.dwFlags=0;
   input[0].ki.time=0;
   input[0].ki.dwExtraInfo=GetMessageExtraInfo();

   input[1].type=INPUT_KEYBOARD;
   input[1].ki.wVk=65;
   //input[0].ki.wScan=KEYEVENTF_SCANCODE;
   input[0].ki.wScan=0;
   input[1].ki.dwFlags=KEYEVENTF_KEYUP;
   input[1].ki.time=0;
   input[1].ki.dwExtraInfo=GetMessageExtraInfo();

   INPUT *theInput;

   while(1) {
   ReadFile(hCom, buff, 4,&readed, 0);
         if (readed>0) {
               buff[readed]='\0';
               printf("read %d bytes: <<%s>>\n",readed,buff);
               switch (buff[0]) {
                     case '+':
                           theInput = &input[0];
                           break;
                     case '-':
                           //printf("Sending keyup event\n");
                           theInput = &input[1];
                           break;
               }
               switch(buff[1]) {
                     case 'u':
                           //theInput->ki.wVk=VK_UP;
                           theInput->ki.wVk=0x55;
                           //theInput->ki.wVk=  Microsoft.DirectX.DirectInput.Key.
                           break;
                     case 'd':
                           theInput->ki.wVk=0x44;
                           //theInput->ki.wVk=VK_DOWN;
                           break;
                     case 'l':
                           theInput->ki.wVk=0x4C;
                           //theInput->ki.wVk=VK_LEFT;
                           break;
                     case 'r':
                           theInput->ki.wVk=0x52;
                           //theInput->ki.wVk=VK_RIGHT;
                           break;
                     case 'a':
                           theInput->ki.wVk=VK_LCONTROL;
                           break;
                     case 'b':
                           theInput->ki.wVk=VK_LMENU;
                           break;
                     case 'c':
                           theInput->ki.wVk=VK_SPACE;
                           break;
                     case 's':
                           theInput->ki.wVk=0x31;
                           break;
               }
               theInput->ki.wScan=MapVirtualKey(theInput->ki.wVk, 0);

               printf("Sending input: <<%s>>\n",buff);
               if (SendInput(1,theInput,sizeof(INPUT))!=1) {
                        FormatMessage(      FORMAT_MESSAGE_FROM_SYSTEM,
                                          0,
                                          GetLastError(),
                                          0,
                                          message,
                                          256,
                                          NULL);
               printf ("SendInput failed with error: %s.\n", GetLastError(),message);
               }
         }
   }
   return (0);
}



====

Y eso es todo. Hay que asegurarse de arrancar este programa antes de abrir el MAME, y en principio, con esta configuracion, se puede jugar al MAME usando el joystick de la megadrive, gracias a Arduino. Gracias por el invento este, la verdad es que no tengo ni idea de electronica, etc., pero me lo estoy pasando pipa destripando todos los cacharros viejos que tengo por casa y jugando con ellos. Ahora estoy con un DVD viejo, que ya no lee los discos, que quiero vaciar para utilizar como carcasa para un mediacenter que me estoy montando, y seguramente utilizare el frontal (display LCD y sensor de infrarojos) para leer el mando a distancia con arduino y enviar las señales a freevo/mythtv, etc. De momento me estoy peleando un poco para decodificar el RC5 que envia el mando a distancia, que parece que es un poco "sui generis" smiley

Espero que os sirva el tema del joystick.

Saludos!
Jose
Logged

Forum Administrator
MMX
Offline Offline
Edison Member
*****
Karma: 37
Posts: 1139
hallo kompis
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

tienes algunas fotos de como hiciste las conexiones y demas? Con esta informacion haremos un articulo en la web.

/David
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pues la verdad es que no tengo ninguna foto (casi mejor, porque el montaje estaba "attachado" a una caja de filtros de fumar con cinta aislante...). Ahora no lo tengo montado, pues estoy usando el Arduino para investigar el tema del RC5, pero tengo pedido otro que me deberia llegar esta semana. Si no se retrasa, volvere a hacer el montaje y os mandare algunas fotos.

Saludos,
Jose
Logged

Pages: [1]   Go Up
Jump to: