Aporte (arduino). Obtener datos de un mouse microsoft optico 1.1a

Mi primer post fue preguntando cosas, asi que les quiero aportar pruebas que hice por ahi a alguien le sirve.

Esto es en lo que estoy ahora, haciendo pruebas, estoy usando un arduino Pro Micro (que es una onda leonardo pero en chiquito). Basicamente lo copado es que soporta HID (puse OTG pero bien me aclararon Nuyel y Scooter que no era asi), lo que lo deja hacer mil cosas con mouses, teclados, joysticks, a comparacion del arduino uno que (basicamente) no lo soporta.


La idea es que me serviria para hacer un seguimiento de un robotito con ruedas que tiene que escapar de un laberinto, ya que los motores no siempre andan a la misma velocidad y un largo etc, necesitas una manera de que sigan una linea recta.

Esto mas 3 sensores de ultrasonidos (dos para los costados para mantenerlo alineado a la pared, y uno adelante para ver cuanto le falta para chocar contra la pared), deberia servirle para escapar del laberinto.

Con el Arduino UNO no funciona (ver primer imagen)

Con el Arduino Pro Micro (y creo que cualquier arduino compatible con leonardo) funciona (ver la segunda y tercera imagen de abajo). El tema es que soporte OTG (en realidad no es exactamente OTG, pero es mas o menos la idea).

Les aviso que van a tener problemas para hacerlo funcionar, a veces no les va a detectar el arduino hasta que quede andando bien.

Los codigos fueron obtenidos de este post en instructables (copiar y pegar en sus navegadores) instructables.com/id/Optical-Mouse-Odometer-for-Arduino-Robot/?comments=all#CHU8F1IIDCXE3L2
 

Adjuntos

  • newiyNu.jpg
    newiyNu.jpg
    89.1 KB · Visitas: 29
  • QK97g4X.jpg
    QK97g4X.jpg
    45.3 KB · Visitas: 26
  • y4pWvnP.jpg
    y4pWvnP.jpg
    86.4 KB · Visitas: 22
Última edición:
Ohh, ya vi, esto implementa el PS/2 que es un protocolo serie simple, antes cuando comprabas un ratón USB algunos incluían el adaptador para conectarlos al PS/2. Ya se me hacía raro que mencionaras el OTG cuando el Leonardo tiene USB nativo, pero no OTG.

Debería haber otro inconveniente por el que no haya funcionado en el UNO.
 
Ohh, ya vi, esto implementa el PS/2 que es un protocolo serie simple, antes cuando comprabas un ratón USB algunos incluían el adaptador para conectarlos al PS/2. Ya se me hacía raro que mencionaras el OTG cuando el Leonardo tiene USB nativo, pero no OTG.

Debería haber otro inconveniente por el que no haya funcionado en el UNO.

Si disculpas por mis pocos conocimientos, pense que usaba alguna caracteristica del ATmega32u4.

El ATmega32u4 se ha incorporado en la comunicación USB, eliminando la necesidad de un procesador secundario. Esto permite que el Leonardo a comparecer a un ordenador conectado como un ratón y el teclado, además de una virtual (CDC) de serie / COM puerto.

//en.wikipedia.org/wiki/USB_human_interface_device_class

Se comunica por protocolo PS/2 como bien dices, el usuario que subio el ejemplo y su libreria modificada, lo oriento al mouse microsoft intellimouse 1.1a el cual mediante adaptador funcionaba como PS/2. Lamentablemente no puso el codigo para habilitar la ruedita del mouse, y poder aprovechar ese sensor.

//computer-engineering.org/ps2mouse/

Intente hacer andar un mouse ps2, comun a bolita (usando todas las librerias y ejemplos que encontre), pero no tuve suerte, pero puede ser que mi viejo mouse a bolita ya este estropeado.

La idea es usar el mouse para rastrear por donde va el robot (vehiculo), mas 3 sensores ultrasonicos (si quieres pongo el codigo de ejemplo), 2 sensores por costado para alinearse con la pared, y un sensor delantero para evitar que choque con la pared delantera.

Mi problema ahora son los motores y su controlador, como cite en el otro post.
 

Adjuntos

  • 523a1765757b7f5c6e8b4567.png
    523a1765757b7f5c6e8b4567.png
    390.8 KB · Visitas: 22
  • kNarGZd.jpg
    kNarGZd.jpg
    36.3 KB · Visitas: 17
  • rz8D7JI.jpg
    rz8D7JI.jpg
    94.8 KB · Visitas: 16
  • Pie7Ztp.jpg
    Pie7Ztp.jpg
    107.4 KB · Visitas: 19
  • 3HzoR9w.jpg
    3HzoR9w.jpg
    88.6 KB · Visitas: 18
Última edición:
Necesitas un ratón mixto USB ps2.
Cada vez hay menos, últimamente sólo hay USB puros que no valdrán para ese uso.

Ya me extrañaba que fuera USB otg; que yo sepa sólo el DUE lo es.
 
Necesitas un ratón mixto USB ps2.
Cada vez hay menos, últimamente sólo hay USB puros que no valdrán para ese uso.

Ya me extrañaba que fuera USB otg; que yo sepa sólo el DUE lo es.

Con el Pro Micro te deja hacer estas cosas (aunque especificamente nose si es OTG, creo que seria HID el termino correcto). Reitero no tengo muchos conocimientos en el tema, mi vocabulario no es preciso como quisiera.

//learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/example-2-hid-mouse-and-keyboard
 
Última edición:
Es al revés.
En un arduino NO PUEDES USAR UN RATÓN USB. Es el arduino el que hace de ratón USB en un PC.
Lo mismo que el leonardo porque a fin de cuentas lo que tienes es un leonardo en otro formato.
Eso es lo que dice el enlace que has puesto. Que con el arduino emulas un ratón. No al revés.

Si que podrías si el ratón es ps2 convertirlo a USB con el arduino, por decir algo. Al revés NO.

Aún quedan ratones mixtos USB ps2. Esos te valdrían. Uno puso USB no.

Sólo el DUE, que yo sepa, es USB otg . A lo mejor otros lo hacen.
 
Última edición:
Es al revés.
En un arduino NO PUEDES USAR UN RATÓN USB. Es el arduino el que hace de ratón USB en un PC.
Lo mismo que el leonardo porque a fin de cuentas lo que tienes es un leonardo en otro formato.
Eso es lo que dice el enlace que has puesto. Que con el arduino emulas un ratón. No al revés.

Si que podrías si el ratón es ps2 convertirlo a USB con el arduino, por decir algo. Al revés NO.

Aún quedan ratones mixtos USB ps2. Esos te valdrían. Uno puso USB no.

Sólo el DUE, que yo sepa, es USB otg . A lo mejor otros lo hacen.

Mil gracias por la aclaracion.
 
Como has dicho si el ratón es mixto es como si fuese USB, para el caso lo mismo da. Pero si es puro usb no funcionará ni a tiros.
 
En el caso de un ratón de bolita puedes simplemente usar el encoder directamente (aunque ocuparás más pines), es cosa de desoldar el controlador del ratón y buscar los pines que vienen de los sensores ópticos, de ahí usas el encoder rotacional directamente.

Lo que yo quisiera ver es como usar el sensor de rastreo óptico de los ratones ópticos directamente, creo que el que tenía por ahí funcionaba por SPI, voy a ver si puedo lograr algo con él, también quisiera incorporarlo a un carro para conocer su velocidad con respecto al suelo.
 
No lo se seguro pero creo que el ratón va dando mensajes del tipo
"100 más en X"
"43 menos en Y"
La pega es que no sabes si gira o no...
Si adelanta o atrasa si, pero para ir hacia los lados no veo del todo claro el algoritmo. El sensor tendrá que estar fuera del eje de las ruedas; si giras el ratón sobre su eje no se mueve. Así cuando gires dará movimiento transversal, multiplicando por la distancia al eje puedes hacerte una idea del ángulo de giro.
 
Si, un adaptador pasivo.
En su día habían adaptadores PS2 a serie

Te encontre otro mouse que no es microsoft que es ps2 y es optico

M6Vjmhs.jpg


Ire subiendo informacion a este post revisenlo en 30 minutos.


En el caso de un ratón de bolita puedes simplemente usar el encoder directamente (aunque ocuparás más pines), es cosa de desoldar el controlador del ratón y buscar los pines que vienen de los sensores ópticos, de ahí usas el encoder rotacional directamente.

Lo que yo quisiera ver es como usar el sensor de rastreo óptico de los ratones ópticos directamente, creo que el que tenía por ahí funcionaba por SPI, voy a ver si puedo lograr algo con él, también quisiera incorporarlo a un carro para conocer su velocidad con respecto al suelo.

Lei ejemplos que hacen lo que tu dices, buscan chips de mouses conocidos e intentan decodificarlos (disculpen mi vocabulario), el tema es que como bien dices llevan mas patas. (acabo de ver y este no es exactamente el ejemplo que queria mostrarte, pero lo dejo aqui por si a alguien le resulta util).

http://blog.jgc.org/2012/09/conversion-of-cheap-optical-mouse-to.html

Lo mejor es usar la libreria "standard" de los PS/2 y sacar informacion de sus conectores.

http://computer-engineering.org/ps2mouse/

http://playground.arduino.cc/ComponentLib/Ps2mouse

Donde

1 - Datos
2 - No conectado
3 - Tierra
4 - Vcc (+5V)
5 - Reloj
6 - Not connected

PS2_connector_close_up-numbers_PNr%C2%B00054b.jpg


ps2photo.jpg


En mi caso lo tome directamente desde las salidas del mouse y como veran arriba estas varian segun el mouse, pero por lo general es

Rojo -Vcc
Negro o azul -(tierra)
blanco o amarillo -datos
Verde o el restante -clock o reloj

Desconozco como seria para usar el rotacional como dices, en mi caso seria ideal hacer andar el codigo para que me tome la ruedita del mouse.


Este en teoria seria el codigo para un ps/2 comun.
Código:
/*
 * an arduino sketch to interface with a ps/2 mouse.
 * Also uses serial protocol to talk back to the host
 * and report what it finds.
 */

/*
 * Pin 5 is the mouse data pin, pin 6 is the clock pin
 * Feel free to use whatever pins are convenient.
 */
#define MDATA 5
#define MCLK 6

/*
 * according to some code I saw, these functions will
 * correctly set the mouse clock and data pins for
 * various conditions.
 */
void gohi(int pin)
{
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH);
}

void golo(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void mouse_write(char data)
{
  char i;
  char parity = 1;

  //  Serial.print("Sending ");
  //  Serial.print(data, HEX);
  //  Serial.print(" to mouse\n");
  //  Serial.print("RTS");
  /* put pins in output mode */
  gohi(MDATA);
  gohi(MCLK);
  delayMicroseconds(300);
  golo(MCLK);
  delayMicroseconds(300);
  golo(MDATA);
  delayMicroseconds(10);
  /* start bit */
  gohi(MCLK);
  /* wait for mouse to take control of clock); */
  while (digitalRead(MCLK) == HIGH)
    ;
  /* clock is low, and we are clear to send data */
  for (i=0; i < 8; i++) {
    if (data & 0x01) {
      gohi(MDATA);
    } 
    else {
      golo(MDATA);
    }
    /* wait for clock cycle */
    while (digitalRead(MCLK) == LOW)
      ;
    while (digitalRead(MCLK) == HIGH)
      ;
    parity = parity ^ (data & 0x01);
    data = data >> 1;
  }  
  /* parity */
  if (parity) {
    gohi(MDATA);
  } 
  else {
    golo(MDATA);
  }
  while (digitalRead(MCLK) == LOW)
    ;
  while (digitalRead(MCLK) == HIGH)
    ;
  /* stop bit */
  gohi(MDATA);
  delayMicroseconds(50);
  while (digitalRead(MCLK) == HIGH)
    ;
  /* wait for mouse to switch modes */
  while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW))
    ;
  /* put a hold on the incoming data. */
  golo(MCLK);
  //  Serial.print("done.\n");
}

/*
 * Get a byte of data from the mouse
 */
char mouse_read(void)
{
  char data = 0x00;
  int i;
  char bit = 0x01;

  //  Serial.print("reading byte from mouse\n");
  /* start the clock */
  gohi(MCLK);
  gohi(MDATA);
  delayMicroseconds(50);
  while (digitalRead(MCLK) == HIGH)
    ;
  delayMicroseconds(5);  /* not sure why */
  while (digitalRead(MCLK) == LOW) /* eat start bit */
    ;
  for (i=0; i < 8; i++) {
    while (digitalRead(MCLK) == HIGH)
      ;
    if (digitalRead(MDATA) == HIGH) {
      data = data | bit;
    }
    while (digitalRead(MCLK) == LOW)
      ;
    bit = bit << 1;
  }
  /* eat parity bit, which we ignore */
  while (digitalRead(MCLK) == HIGH)
    ;
  while (digitalRead(MCLK) == LOW)
    ;
  /* eat stop bit */
  while (digitalRead(MCLK) == HIGH)
    ;
  while (digitalRead(MCLK) == LOW)
    ;

  /* put a hold on the incoming data. */
  golo(MCLK);
  //  Serial.print("Recvd data ");
  //  Serial.print(data, HEX);
  //  Serial.print(" from mouse\n");
  return data;
}

void mouse_init()
{
  gohi(MCLK);
  gohi(MDATA);
  //  Serial.print("Sending reset to mouse\n");
  mouse_write(0xff);
  mouse_read();  /* ack byte */
  //  Serial.print("Read ack byte1\n");
  mouse_read();  /* blank */
  mouse_read();  /* blank */
  //  Serial.print("Sending remote mode code\n");
  mouse_write(0xf0);  /* remote mode */
  mouse_read();  /* ack */
  //  Serial.print("Read ack byte2\n");
  delayMicroseconds(100);
}

void setup()
{
  Serial.begin(9600);
  mouse_init();
}

/*
 * get a reading from the mouse and report it back to the
 * host via the serial line.
 */
void loop()
{
  char mstat;
  char mx;
  char my;

  /* get a reading from the mouse */
  mouse_write(0xeb);  /* give me data! */
  mouse_read();      /* ignore ack */
  mstat = mouse_read();
  mx = mouse_read();
  my = mouse_read();

  /* send the data back up */
  Serial.print(mstat, BIN);
  Serial.print("\tX=");
  Serial.print(mx, DEC);
  Serial.print("\tY=");
  Serial.print(my, DEC);
  Serial.println();
  delay(20);  /* twiddle */
}

y este para el intellimouse (que uso yo en el ejemplo), pero no lo pude hacer andar con este codigo (incluye ruedita del mouse)

Código:
/* Modified mouse initialization to accomondate for
 * Intellimouse vertical wheel (scroll) 
 * by DGar 02/05/2014
 */

/*
 * an arduino sketch to interface with a ps/2 mouse.
 * Also uses serial protocol to talk back to the host
 * and report what it finds.
 */

/*
 * Pin 5 is the mouse data pin, pin 6 is the clock pin
 * Feel free to use whatever pins are convenient.
 */
#define MDATA 5
#define MCLK 6

/*
 * according to some code I saw, these functions will
 * correctly set the mouse clock and data pins for
 * various conditions.
 */
void gohi(int pin)
{
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH);
}

void golo(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void mouse_write(char data)
{
  char i;
  char parity = 1;

  //  Serial.print("Sending ");
  //  Serial.print(data, HEX);
  //  Serial.print(" to mouse\n");
  //  Serial.print("RTS");
  /* put pins in output mode */
  gohi(MDATA);
  gohi(MCLK);
  delayMicroseconds(300);
  golo(MCLK);
  delayMicroseconds(300);
  golo(MDATA);
  delayMicroseconds(10);
  /* start bit */
  gohi(MCLK);
  /* wait for mouse to take control of clock); */
  while (digitalRead(MCLK) == HIGH)
    ;
  /* clock is low, and we are clear to send data */
  for (i=0; i < 8; i++) {
    if (data & 0x01) {
      gohi(MDATA);
    } 
    else {
      golo(MDATA);
    }
    /* wait for clock cycle */
    while (digitalRead(MCLK) == LOW)
      ;
    while (digitalRead(MCLK) == HIGH)
      ;
    parity = parity ^ (data & 0x01);
    data = data >> 1;
  }  
  /* parity */
  if (parity) {
    gohi(MDATA);
  } 
  else {
    golo(MDATA);
  }
  while (digitalRead(MCLK) == LOW)
    ;
  while (digitalRead(MCLK) == HIGH)
    ;
  /* stop bit */
  gohi(MDATA);
  delayMicroseconds(50);
  while (digitalRead(MCLK) == HIGH)
    ;
  /* wait for mouse to switch modes */
  while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW))
    ;
  /* put a hold on the incoming data. */
  golo(MCLK);
  //  Serial.print("done.\n");
}

/*
 * Get a byte of data from the mouse
 */
char mouse_read(void)
{
  char data = 0x00;
  int i;
  char bit = 0x01;

  //  Serial.print("reading byte from mouse\n");
  /* start the clock */
  gohi(MCLK);
  gohi(MDATA);
  delayMicroseconds(50);
  while (digitalRead(MCLK) == HIGH)
    ;
  delayMicroseconds(5);  /* not sure why */
  while (digitalRead(MCLK) == LOW) /* eat start bit */
    ;
  for (i=0; i < 8; i++) {
    while (digitalRead(MCLK) == HIGH)
      ;
    if (digitalRead(MDATA) == HIGH) {
      data = data | bit;
    }
    while (digitalRead(MCLK) == LOW)
      ;
    bit = bit << 1;
  }
  /* eat parity bit, which we ignore */
  while (digitalRead(MCLK) == HIGH)
    ;
  while (digitalRead(MCLK) == LOW)
    ;
  /* eat stop bit */
  while (digitalRead(MCLK) == HIGH)
    ;
  while (digitalRead(MCLK) == LOW)
    ;
  /* put a hold on the incoming data. */
  golo(MCLK);
  //  Serial.print("Recvd data ");
  //  Serial.print(data, HEX);
  //  Serial.print(" from mouse\n");
  return data;
}

void mouse_init()
{ char mouseId;
   
  gohi(MCLK);
  gohi(MDATA);
  //  Serial.print("Sending reset to mouse\n");
  mouse_write(0xff);
  mouse_read();  /* ack byte */
  //  Serial.print("Read ack byte1\n");
  mouse_read();  /* blank */
  mouse_read();  /* blank */
  //  Serial.print("Setting sample rate 200\n");
  mouse_write(0xf3);  /* Set rate command */
  mouse_read();  /* ack */
  mouse_write(0xC8);  /* Set rate command */
  mouse_read();  /* ack */
  //  Serial.print("Setting sample rate 100\n");
  mouse_write(0xf3);  /* Set rate command */
  mouse_read();  /* ack */
  mouse_write(0x64);  /* Set rate command */
  mouse_read();  /* ack */
  //  Serial.print("Setting sample rate 80\n");
  mouse_write(0xf3);  /* Set rate command */
  mouse_read();  /* ack */
  mouse_write(0x50);  /* Set rate command */
  mouse_read();  /* ack */
  //  Serial.print("Read device type\n");
  mouse_write(0xf2);  /* Set rate command */
  mouse_read();  /* ack */
  mouse_read();  /* mouse id, if this value is 0x00 mouse is standard, if it is 0x03 mouse is Intellimouse */
  //  Serial.print("Setting wheel\n");
  mouse_write(0xe8);  /* Set wheel resolution */
  mouse_read();  /* ack */
  mouse_write(0x03);  /* 8 counts per mm */
  mouse_read();  /* ack */
  mouse_write(0xe6);  /* scaling 1:1 */
  mouse_read();  /* ack */
  mouse_write(0xf3);  /* Set sample rate */
  mouse_read();  /* ack */
  mouse_write(0x28);  /* Set sample rate */
  mouse_read();  /* ack */
  mouse_write(0xf4);  /* Enable device */
  mouse_read();  /* ack */

  //  Serial.print("Sending remote mode code\n");
  mouse_write(0xf0);  /* remote mode */
  mouse_read();  /* ack */
  //  Serial.print("Read ack byte2\n");
  delayMicroseconds(100);
}

void setup()
{
  Serial.begin(9600);
  mouse_init();
}

/*
 * get a reading from the mouse and report it back to the
 * host via the serial line.
 */
void loop()
{
  char mstat;
  char mx;
  char my;
  char mz;

  /* get a reading from the mouse */
  mouse_write(0xeb);  /* give me data! */
  mouse_read();      /* ignore ack */
  mstat = mouse_read();
  mx = mouse_read();
  my = mouse_read();
  mz = mouse_read();

  /* send the data back up */
  Serial.print(mstat, BIN);
  Serial.print("\tX=");
  Serial.print(mx, DEC);
  Serial.print("\tY=");
  Serial.print(my, DEC);
  Serial.print("\tZ=");
  Serial.print(mz, DEC);
  Serial.println();
  delay(20);  /* twiddle */
}



No lo se seguro pero creo que el ratón va dando mensajes del tipo
"100 más en X"
"43 menos en Y"
La pega es que no sabes si gira o no...
Si adelanta o atrasa si, pero para ir hacia los lados no veo del todo claro el algoritmo. El sensor tendrá que estar fuera del eje de las ruedas; si giras el ratón sobre su eje no se mueve. Así cuando gires dará movimiento transversal, multiplicando por la distancia al eje puedes hacerte una idea del ángulo de giro.

Por lo que lei (aunque quizas entendi mal), mientras no se mueve (es decir no detecte cambios) no hace nada, si se mueve compara su estado anterior con el actual y le dice hacia que lado se movio y cuanto.

Disculpen si me equivoco en las cosas, intento aportar en lo posible, con mis errores inclusive.
 
Última edición:
Si no son nuevos, hay muchos ps2 puros o mixtos ps2 USB.
Si vas a la tienda a comprar uno ahora lo normal es que sea USB puro .
 
Si no son nuevos, hay muchos ps2 puros o mixtos ps2 USB.
Si vas a la tienda a comprar uno ahora lo normal es que sea USB puro .

Si. Bien lo habías aclarado tú.
En su momento cuando microsoft diseño este parche, eran muy comunes.

Si te fijas en una parte de este texto http://computer-engineering.org/ps2mouse/
Le pregunta si es un mouse microsoft. Si no obtiene respuesta lo toma como un mouse ps2 común.

Código:
Host:  F3  Set Sample Rate   : Attempt to Enter Microsoft
Mouse: FA  Acknowledge       : Scrolling Mouse mode
Host:  C8  decimal 200       :
Mouse: FA  Acknowledge       :
Host:  F3  Set Sample Rate   :
Mouse: FA  Acknowledge       :
Host:  64  decimal 100       :
Mouse: FA  Acknowledge       :
Host:  F3  Set Sample Rate   :
Mouse: FA  Acknowledge       :
Host:  50  decimal 80        :
Mouse: FA  Acknowledge       :
Host:  F2  Read Device Type  :
Mouse: FA  Acknowledge       :
Mouse: 00  Mouse ID          : Response 03 if microsoft scrolling mouse
Para seguir aportando al tema, el tipo del ejemplo queria poner 2 mouses, uno en cada rueda asi la presicion era mayor.

http://www.researchgate.net/publica...ning_for_Mobile_Robots_Using_Two_Optical_Mice

Yo me conformo con poner un mouse en el frente.
También serviría para detectar si se termina la superficie, hay un escalón, o si esta en una mesa, etc.

---------- Actualizado ----------

Conseguí varios mouses con bolita ps2, cuando tenga un tiempo me pongo a jugar con ellos y les aviso si hay progresos.

ESk6NKz.jpg
 
Última edición por un moderador:
Atrás
Arriba