Búsqueda personalizada

15 agosto 2006

Control de leds desde ratón - Arduino

Mas proyectos en: http://eduardomarin.es/node/2

Después de un primer intento para llevar a cabo un enlace directo entre ratón y Arduino, debido a problemas de comunicación entre los dos detallo la comunicación a través del pc.
Es una conexión muy parecida al enlace que ya hice entre teclado y el display de 8 segmentos, salvo que en esta ocasión, en vez de usar el programa terminal.exe implemento un controlador específico.
Pero, ¿cuál es la idea del invento?. Se trata de iluminar 4 leds, dispuestos en cruz, según se mueva el ratón. Así, si muevo el ratón hacia la izquierda, si iluminará el led de la izquierda. Si lo muevo hacia la derecha, se iluminará el de la derecha. Lo mejor de todo es que, aunque parezca algo sencillo y simple, tiene bastantes utilidades. Imaginemos poder mover un brazo mecánico mediante el uso del ratón y su rueda central :-) .
Para llevar a cabo esta tarea, primero había que conseguir hacer una lectura de los parámetros del ratón. Buscando en la red, encontré un driver ya implementado que solucionaba la ardua tarea de ponerse a rebuscar entre interrupciones y llamadas a bios. Esta librería, ratoli.h, puede encontrarse en la página del autor, pero no recuerdo dónde la encontré, así pues pego aquí el código:
/*

RATOLI.H:

-Llibreria amb rutines de control del Mouse.
-Ultima modificaci¢: 7-II-1995

*/
#include 

/* NOTA:    Valors de retorn de la funci¢ boto():
-----------------------------------------------
|  Valor:  |  Esquerra:  |  (Mig:)  |  Dret:  |
-----------------------------------------------
|    0     |     NO      |    NO    |   NO    |
|    1     |     SI      |    NO    |   NO    |
|    2     |     NO      |    NO    |   SI    |
|    3     |     SI      |    NO    |   SI    |
|    4     |     NO      |    SI    |   NO    |
|    5     |     SI      |    SI    |   NO    |
|    6     |     NO      |    SI    |   SI    |
|    7     |     SI      |    SI    |   SI    |
-----------------------------------------------
*/

union REGS rin,rout;

/*
-----------------------------------------------------------------------------
INITMOUSE: Inicialitza el mouse.
-----------------------------------------------------------------------------
*/
int InitMouse(void)
{
rin.x.ax=0;
int86(0x33,&rin,&rout);
return (rout.x.ax);            /* Retorna -1 si el mouse s'ha instalat. */                 /*         0 si no instalado*/
}

/*
-----------------------------------------------------------------------------
MOUSEOFF: Amaga el cursor del mouse.
-----------------------------------------------------------------------------
*/
void mouseoff(void)
{
rin.x.ax=2;
int86(0x33,&rin,&rout);
}

/*
-----------------------------------------------------------------------------
MOUSEON: Fa aparŠixer el cursor del mouse.
-----------------------------------------------------------------------------
*/
void mouseon(void)
{
rin.x.ax=1;
int86(0x33,&rin,&rout);
}

/*
-----------------------------------------------------------------------------
EIXX: Retorna la posici¢ horitzontal del mouse (depŠn de la ressoluci¢ del
text o dels gr…fics).
-----------------------------------------------------------------------------
*/
int eixx(void)
{
rin.x.ax=3;
int86(0x33,&rin,&rout);
return(rout.x.cx);
}

/*
-----------------------------------------------------------------------------
EIXY: Retorna la posici¢ vertical del mouse.
-----------------------------------------------------------------------------
*/
int eixy(void)
{
rin.x.ax=3;
int86(0x33,&rin,&rout);
return(rout.x.dx);
}

/*
-----------------------------------------------------------------------------
BOTO: Retorna l'estat dels botons. Veure la taula del principi per a saber
els valors exactes.
-----------------------------------------------------------------------------
*/
int boto(void)
{
rin.x.ax=3;
int86(0x33,&rin,&rout);
return(rout.x.bx);
}

/*
-----------------------------------------------------------------------------
SETMOUSEPOS: Col.loca el cursor del mouse en la posici¢ (x,y).
-----------------------------------------------------------------------------
*/
void SetMousePos(int x, int y)
{
rin.x.ax=4;
rin.x.cx=x;
rin.x.dx=y;
int86(0x33,&rin,&rout);
}


Por otra parte, debemos mandar datos a la placa Arduino, pero, esta vez, sin ayuda de terminal.exe, con lo cual debemos manejar los envíos y comunicaciones directamente. Lo primero que teníamos que hacer era conseguir mandar los datos correctamente. Dadas las características del puerto virtual USB-serial, se configuró para envío sobre 8 bits de datos, 1 bit de parada, no paridad y velocidad a 9600 bps. Despúes sólo quedaba mandar caracteres de control mediante la instrucción outport() sobre Arduino, y que éste interpretase correctamente el envío. El código sobre el pc quedaba entonces así:

/*     Nombre: Driver de rat¢n hacia Arduino control.c   */
/*      Escrito por: Eduardo Mar¡n Izquierdo   */
/* Basado  el env¡o puerto serie en source de: Craig Peacock  */
/*    Fecha:   14 - 8 - 2006    */

#include 
#include 
#include 
#include 
#define PORT1 0x3E8

/* Defines Serial Ports Base Address */
/* COM1 0x3F8    */
/* COM2 0x2F8     */
/* COM3 0x3E8     */
/* COM4 0x2E8     */

void main(void)
{
int c;
int ch;
int new_pos_x,new_pos_y,pos_x,pos_y;
outportb(PORT1 + 1 , 0);   /* Turn off interrupts - Port1 */

/*    PORT 1 - Communication Settings    */

outportb(PORT1 + 3 , 0x80);  /* SET DLAB ON */
outportb(PORT1 + 0 , 0x0C);  /* Set Baud rate - Divisor Latch Low Byte */
/* Default 0x03 =  38,400 BPS */
/*    0x01 = 115,200 BPS */
/*    0x02 =  57,600 BPS */
/*    0x06 =  19,200 BPS */
/*    0x0C =   9,600 BPS */
/*    0x18 =   4,800 BPS */
/*    0x30 =   2,400 BPS */
outportb(PORT1 + 1 , 0x00);  /* Set Baud rate - Divisor Latch High Byte */
outportb(PORT1 + 3 , 0x03);  /* 8 Bits, No Parity, 1 Stop Bit */
outportb(PORT1 + 2 , 0xC7);  /* FIFO Control Register */
outportb(PORT1 + 4 , 0x0B);  /* Turn on DTR, RTS, and OUT2 */

printf("Driver de rat¢n para Arduino\n");
printf("Por Eduardo Mar¡n\n");
printf("Pulse ESC para salir\n");

do {
new_pos_x=eixx();
if(new_pos_x>pos_x){
outportb(PORT1,'r');
}
else{
if(new_pos_xpos_y){
outportb(PORT1,'d');
}
else{
if(new_pos_y


Finalmente, y ya programando sobre Arduino, quedaba recibir los datos provenientes del código anterior. Sabiendo que los únicos carácteres de control eran aquellos que indicaban cuatro posibles direcciones (u,d,r,l; indicando: up, down, right, left), el código resultante es bastante sencillo. Si detectamos una 'u', entonces iluminaremos el led situado en la parte superior.
Observando el código, nos hacemos una idea de la solución:

/* Control de Leds desde teclado
* -------------
*
* Gracias a este programa podemos controlar un número de leds a partir
* del ratón del ordenador.
* 
* Autor: Eduardo Marín Izquierdo
* Fecha: 08-08-2006
*/

int pines [] = {12,11,10,9};
int Ledcontrol = 13;
byte caracter;
int retraso = 1;

void setup() {
int i;
pinMode (Ledcontrol,OUTPUT);
for (i=0; i<6; i++){
pinMode(pines[i],OUTPUT);
}
beginSerial(9600);  
}

void loop() {
caracter = serialRead();

if (caracter == 'l'){
digitalWrite(pines[0],HIGH);
delay(retraso);
digitalWrite(pines[0],LOW);
}
if (caracter == 'd'){
digitalWrite(pines[1],HIGH);
delay(retraso);
digitalWrite(pines[1],LOW);
}
if (caracter == 'u'){
digitalWrite(pines[2],HIGH);
delay(retraso);
digitalWrite(pines[2],LOW);
}
if (caracter == 'r'){
digitalWrite(pines[3],HIGH);
delay(retraso);
digitalWrite(pines[3],LOW);
}
}
Para hacerse una idea, el siguiente vídeo muestra la idea aquí expuesta.

2 comentarios:

Alonso Lazcano dijo...

hola. estuve mirando tu blog, esta bastante bueno en los proyectos de arduino.
hace poco adquirí también el arduino decimila, y he estado haciendo varias cosas, pero aun no entiendo como logro controlar cosas o hacer funcionar algo desde el computador, lo cual veo en tus proyectos, lograste hacer desde el primer momento.
hasta ahora lo único que he podido hacer es grabar programas y ejecutarlos desde arduino pero nada en relación al PC.
Si pudieras enviarme información, o algún link de un tutorial de donde tu aprendiste a controlar objetos desde el PC te lo agradecería bastante, por que mis conocimientos me están limitando en mis desarrollos electrónicos.

mi correo: alonso.lazcano58@gmail.com

saludos
gracias!

mariano dijo...

hola lo que pasa que este tipo sabe programar en "c" o "c++" lo que trenes que hacer es aprenderte alguons de estos lenguajes en especial los de control de puertos paralelo y serie y talves usb te recomiendo c++:
http://c.conclase.net/
un ide te recomiendo dev c++: http://www.bloodshed.net/devcpp.html