PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Maus-Sensorik



MrSpock
25.04.2008, 15:51
Hallo zusammen,
ich habe jetzt hier seit einigen Tagen ziemlich viel über die Maussensorik gelesen. Mein Ziel ist es das Quadratur-Signal einer optischen Maus abzugreifen und dann über die serielle Schnittstelle an den PC geben.

Ich habe mir jetzt speziell den H2000 von Agilent angeschaut.
Zwei kleine Fragen sind noch über geblieben.

Die relevanten Pins des Agilent-ICs sind ja die Pins 2 bis 5. Diese sind mit XA, XB, YA und YB bezeichnet. Mit diesen muss ich doch dann die Richtung und die Positionsänderung selbst bestimmen, oder?
Wie bestimme ich dabei eigentlich die Richtung?

Dann meine zweite kleine Frage. Ist die serielle Schnittstelle schnell genug für mein Vorhaben? Oder ist die Abtastrate der Maus zu hoch, so dass bei der Übertragung an den PC über die serielle Schnittstelle Positionsinformationen nicht übermittelt werden können ?

Ich kenne mich bisher mit Elektronik noch nicht so aus, daher diese vielleicht für euch trivialen Fragen ;).

Vielen Dank und beste Grüße,
MrSpock.

Superhirn
25.04.2008, 17:01
Warum nimmst nicht PS/2?
aus diesem forum hab ich einen code rauskopiert der die ganze ps2 schnittstelle auf einem avr emuliert. geht perfekt.

seriell reicht.

CSR
25.04.2008, 17:11
also wenn ich mir das mathematisch überleg ist die richtung eigenlich nur der vektor
also vektor von A nach B
kannste berechnen mit
B-A
halt immer in den zwei dimensionen

hier würd ich sagen:

XB-XA
YB-YA

das müsste dein 2D-Vektor sein

grüße

oberallgeier
25.04.2008, 18:37
... aus diesem forum hab ich einen code rauskopiert der die ganze ps2 schnittstelle auf einem avr emuliert. geht perfekt.

seriell reicht.Würdest Du bitte diese Quelle nennen? Such ich schon lange. Wie hast Du das am AVR gemacht?

Danke im Voraus

mare_crisium
26.04.2008, 08:19
Hi, Oberallgeier,

ein gutes Beispiel für PS2 am INT0-Interrupt findest Du in der AVR0313.pdf. Man kann ein PS2-Dienstprogramm auch von einem Timer-INT treiben lassen; der muss dann aber mit hoher Frequenz (ca. 40kHz) laufen.

Ciao,

mare_crisium

oberallgeier
26.04.2008, 09:59
Hallo mare_crisium,
lang nicht mehr von Dir gelesen :).

Danke für den Hinweis

... PS2 am INT0-Interrupt ... in der AVR0313.pdf... Muss ich mir laden. Ich hatte vor einiger Zeit mit PS2 oder einer Maus am RS232 rumgestöpselt - und entnervt aufgegeben.


... PS2 auch von einem Timer-INT treiben lassen ... Frequenz (ca. 40kHz) ...Na ja, mein (Standard-) Timer an meinem Mini-Projekt mit dem 168/20MHz läuft mit schlappen 20 kHz. 40 kHz . . . dann hab ich ja grad mal 500 Maschinenzyklen zwischen zwei Interrupts . . . ts ts ts

mare_crisium
26.04.2008, 17:09
Buon giorno, Oberallgeier,

schick' mir 'ne PN, wenn Du die AN nicht finden solltest. Das mit dem 45kHz läuft bei mir auf einem ATmega8 mit 8MHz schon ganz gut. Ist zwar, wie Du schon erkannt hast, etwas knapp, hat aber den Vorteil, dass man mit demselben AT mehrere PS2-Geräte steuern und abfrage kann. Die Ergebnisse gehen dann auf Anfrage per TWI an den Host.

Ciao,

mare_crisium

oberallgeier
26.04.2008, 18:09
Hallohh mare_crisium,

es handelt sich wohl um das AVR313 ! ? "AVR313: Interfacing the PCAT Keyboard " - weil ich ein *0313* nicht gefunden hatte.

mare_crisium
27.04.2008, 02:52
Jau, Oberallgeier,

genau die (AVR313) isses!!

Ciao,

mare_crisium

MrSpock
27.04.2008, 16:46
Hallo zusammen,

zunächst erst einmal vielen Dank für eure Antworten.

PS2 wollte ich eigentlich nicht nehmen, da dann die Ansteuerung unter Windows wohl schwieriger werden wird. Die serielle Schnittstelle wäre da halt das einfachste.
Aber reicht die Performance der seriellen Schnittstelle dafür aus?
(Oder würde der optische Sensor mehr Daten liefern, als man über die serielle Schnittstelle verschicken kann?)

Wenn man die PS2-Schnittstelle nehmen würde, dann bräuchte man den AVR, um das Signal entsprechend für die PS2 Schnittstelle umzuwandeln, oder?

Wie ihr seht, bin ich noch recht unerfahren auf diesem Gebiet.
Freue mich schon auf eure Antworten.

Euer MrSpock

Superhirn
27.04.2008, 17:43
hi

i hab jetzt wieder zeit zum schreiben. ps2 ist gemeint damit du nicht die quadratursignale aus der maus nehmen musst sondern direkt die daten geschickt bekommst.

zu dem ganzen code gibs auch einen originalautor nur der muss mir bitte verzeihen weil ich finde ihn nicht auf die schnelle.

ps2.c

/************************************************** *************************
* Copyright (C) 2008 by Thomas Gruebler and CRCT *
* thomas a t gruebler d o t at *
* www.crct-robots.eu *
************************************************** *************************/

#include "ps2.h"

unsigned char ps2_wait_long_for_clck_lo (unsigned char clkpin) // PS/2: Bis zu 10ms auf CLCK=LO warten
{
unsigned int ms = 1100;
while ((ms--)!=0)
{ // wenn der Timer läuft
if (!PS2_CLCK_IS_HI) return 0x00; // und CLCK geht auf LO -> Return OK
_delay_ms(0.01);
}
return (0xFF); // Timer abgelaufen -> Return Timeout
}


unsigned char ps2_wait_for_clck_lo (unsigned char clkpin) // PS/2: Bis zu 50µs auf CLCK=LO warten
{
unsigned int us = 50000; // Timer 0 Preload 50µs
while ((us--)!=0)
{ // wenn der Timer läuft
if (!PS2_CLCK_IS_HI) return 0x00; // und CLCK geht auf LO -> Return OK
_delay_us(.001);
}
return (0xFF); // Timer abgelaufen -> Return Timeout
}

unsigned char ps2_wait_for_clck_hi (unsigned char clkpin) // PS/2: Bis zu 50µs auf CLCK=HI warten
{
unsigned int us = 50000; // Timer 0 Preload 50µs
while ((us--)!=0)
{ // wenn der Timer läuft
if (PS2_CLCK_IS_HI) return 0x00; // und CLCK geht auf LO -> Return OK
_delay_us(.001);
}
return (0xFF); // Timer abgelaufen -> Return Timeout
}

unsigned char ps2_send (unsigned char val, unsigned char clkpin, unsigned char datapin)
{
unsigned char i = -1;
unsigned char pb = 0;

PS2_CLCK_LO; // setze CLCK LO
delay_us(100); // warte 100µs
PS2_DATA_LO; // setze CLCK LO, DATA LO
delay_us(25); // warte 25µs
PS2_CLCK_HI; // setze CLCK HI, DATA LO

if (ps2_wait_long_for_clck_lo(clkpin)) goto ps2_send_error; // 10ms auf fallende Flanke (CLCK) warten

for (i=0; i<8; i++)
{ // Datenbits LSB->MSB
if (val & 0x01)
{ // Bit ist 1
pb++; // Parityzähler erhöhen
PS2_DATA_HI; // Datenleitung HI sezen
}
else
{ // Bit ist 0
PS2_DATA_LO; // Datenleitung LO setzen
}
if (ps2_wait_for_clck_hi(clkpin)) goto ps2_send_error; // 50µs auf steigende Flanke (CLCK) warten
if (ps2_wait_for_clck_lo(clkpin)) goto ps2_send_error; // 50µs auf fallende Flanke (CLCK) warten
val = val >> 1;
}

if (pb & 0x01) // PB ungerade?
PS2_DATA_LO; // -> kein Parity Bit
else // PB gerade?
PS2_DATA_HI; // -> Parity Bit
if (ps2_wait_for_clck_hi(clkpin)) goto ps2_send_error; // 50µs auf steigende Flanke (CLCK) warten
if (ps2_wait_for_clck_lo(clkpin)) goto ps2_send_error; // 50µs auf fallende Flanke (CLCK) warten

i++;
PS2_DATA_HI; // CLCK und DATA freigeben
PS2_CLCK_HI; // CLCK und DATA freigeben
if (ps2_wait_for_clck_hi(clkpin)) goto ps2_send_error; // 50µs auf steigende Flanke (CLCK) warten
if (ps2_wait_for_clck_lo(clkpin)) goto ps2_send_error; // 50µs auf fallende Flanke (CLCK) warten

PS2_CLCK_LO; // CLCK LO setzen (Bus blockieren)
return (0); // Fehlerfrei

ps2_send_error: // Fehlerhandling
PS2_CLCK_LO; // CLCK LO setzen (Bus blockieren)
return (i); // Fehlernummer zurückgeben

}

unsigned char ps2_read (unsigned char * buffer, unsigned char len, unsigned char bytes_read, unsigned char clkpin, unsigned char datapin)
{
unsigned char i;
bytes_read = 0; // Anzahl gelesener Zeichen
PS2_CLCK_HI; // CLCK freigeben

while (bytes_read < len)
{
buffer[bytes_read] = 0;
for (i=1; i<=11; i++)
{
if (i==1) //beim Startbit
{ if (ps2_wait_long_for_clck_lo(clkpin)) goto ps2_read_error; } //10ms auf fallende Flanke (CLCK) warten
else //sonst
{ if (ps2_wait_for_clck_lo(clkpin)) goto ps2_read_error; } //50µs auf fallende Flanke (CLCK) warten

if (i>=2 && i<=9)
{ // wenn Datenbit
if (PS2_DATA_IS_HI) // HI
buffer[bytes_read] = (buffer[bytes_read]>>1) | 0x80;
else // LO
buffer[bytes_read] = (buffer[bytes_read]>>1) | 0x00;
}
if (ps2_wait_for_clck_hi(clkpin)) goto ps2_read_error; // 50µs auf steigende Flanke (CLCK) warten
}
bytes_read++; // Bytezähler erhöhen
}

PS2_CLCK_LO; // CLCK LO setzen (Bus blockieren)
return (0); // Fehlerfrei

ps2_read_error: // Fehlerhandling
PS2_CLCK_LO; // CLCK LO setzen (Bus blockieren)
return (i); // Fehlernummer zurückgeben
}

void fatal_error (unsigned char errcode, unsigned int addinfo)
{
// Fehlerbehandlung hier rein....
LEDP ^= (1<<LED3); //Led3 toggeln

// while (1) {}
}

void maus_init(unsigned char clkpin, unsigned char datapin)
{

unsigned char c=0,i=0; // Hilfsvariablen


if (ps2_send(0xFF, MOUSE)) fatal_error(0x01,0x00); // PS/2 Cmd: Reset
delay_ms(20); // 20ms warten

if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x02,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x03,c); // auf Quittung (ACK/$FA) prüfen
delay_ms(1000); // 1s warten (50*20ms)
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x04,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xAA) fatal_error(0x05,c); // auf BAT-Quittung ($AA) prüfen
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x06,0x00); // auf Lesefehler von PS/2 prüfen (Device ID überspringen)


delay_ms(1000); // 1s warten (50*20ms)
if (ps2_send(0xF3, MOUSE)) fatal_error(0x17,0x00); // PS/2 Cmd: Set Sample Rate
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x18,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x19,c); // auf Quittung (ACK/$FA) prüfen

delay_ms(1000); // 1s warten (50*20ms)
if (ps2_send(200, MOUSE)) fatal_error(0x1A,0x00); // 200 Samples per second
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x1B,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x1C,c); // auf Quittung (ACK/$FA) prüfen


delay_ms(1000); // 1s warten (50*20ms)
if (ps2_send(0xE8,MOUSE)) fatal_error(0x07,0x00); // PS/2 Cmd: Set Resolution
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x08,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x09,c); // auf Quittung (ACK/$FA) prüfen

delay_ms(1000); // 1s warten (50*20ms)
if (ps2_send(0x03, MOUSE)) fatal_error(0x0A,0x00); // Resolution 2 = 4 counts/mm = 2 Impulse pro Zahn
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x0B,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x0C,c); // auf Quittung (ACK/$FA) prüfen
delay_ms(1000); // 1s warten (50*20ms)
if (ps2_send(0xF0, MOUSE)) fatal_error(0x0D,0x00); // PS/2 Remote Mode einschalten
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE)) fatal_error(0x0E,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x0F,c); // auf Quittung (ACK/$FA) prüfen

}

ps2.h

/************************************************** *************************
* Copyright (C) 2008 by Thomas Gruebler and CRCT *
* thomas a t gruebler d o t at *
* www.crct-robots.eu *
*
* Belegung Stecker in der Maus
* Gruen | Weis | Rot | 2x Schwarz
* Clock Data VCC GND
************************************************** *************************/

#ifndef PS2_H
#define PS2_H

#include "global.h"

#include "main.h"

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
unsigned char head;
char rwheel;
char lwheel;
} ps2_movement_type;

// #define PS2_CLCK_IS_HI (PINC & (1<<PC1))
// #define PS2_DATA_IS_HI (PINC & (1<<PC0))
// #define PS2_CLCK_LO DDRC |= (1<<PC1)
// #define PS2_CLCK_HI DDRC &= ~(1<<PC1)
// #define PS2_DATA_LO DDRC |= (1<<PC0)
// #define PS2_DATA_HI DDRC &= ~(1<<PC0)

#define PS2_CLCK_IS_HI (PINC & (1<<clkpin))
#define PS2_DATA_IS_HI (PINC & (1<<datapin))
#define PS2_CLCK_LO DDRC |= (1<<clkpin)
#define PS2_CLCK_HI DDRC &= ~(1<<clkpin)
#define PS2_DATA_LO DDRC |= (1<<datapin)
#define PS2_DATA_HI DDRC &= ~(1<<datapin)

#define MOUSE1 PC1, PC0
#define MOUSE2 PC3, PC2
#define MOUSE clkpin, datapin

unsigned char ps2_wait_long_for_clck_lo (unsigned char clkpin);
unsigned char ps2_wait_for_clck_lo (unsigned char clkpin);
unsigned char ps2_wait_for_clck_hi (unsigned char clkpin);
unsigned char ps2_send (unsigned char val, unsigned char clkpin, unsigned char datapin);
unsigned char ps2_read (unsigned char * buffer, unsigned char len, unsigned char bytes_read, unsigned char clkpin, unsigned char datapin);
void fatal_error (unsigned char errcode, unsigned int addinfo);

void maus_init(unsigned char clkpin, unsigned char datapin);

#endif


beispiel für den auslesecode:

char xl = 0;
char yl = 0;

char xr = 0;
char yr = 0;

unsigned char c=0,i=0; // Hilfsvariablen
ps2_movement_type moved; // Bewegungsmeldung


//PS/2 Daten auslesen++++++++++++++++++

if (ps2_send(0xEB, MOUSE1)) fatal_error(0x0A,0x00); // READ DATA Command
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE1)) fatal_error(0x0B,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x0C,c);

if (!ps2_read((unsigned char*)&moved,3,c, MOUSE1))
{
//Maus1 daten auslesen
yl =(char)moved.lwheel;
xl =(char)moved.rwheel;
}

if (ps2_send(0xEB, MOUSE2)) fatal_error(0x0A,0x00); // READ DATA Command
delay_ms(20); // 20ms warten
if (ps2_read(&c,1,i, MOUSE2)) fatal_error(0x0B,0x00); // auf Lesefehler von PS/2 prüfen
if (c != 0xFA) fatal_error(0x0C,c);

if (!ps2_read((unsigned char*)&moved,3,c, MOUSE2))
{
//Maus2 daten auslesen
yr =(char)moved.lwheel;
xr =(char)moved.rwheel;
}


mein code ist gegenüber zum original so das man 2 mäuse ansteuern kann und keine timer braucht.

für richtigkeit und funktion übernehme ich natürlich keine haftung. ging bei mir aber ganz gut

lg

crawl
28.04.2008, 16:00
die links währen vll auch net schlecht

http://www.atmel.com/dyn/resources/prod_documents/doc1235.pdf

http://www.casainho.net/tiki-download_file.php?fileId=6


und vll noch

http://www.cyberresearch.com/content/tutorials/tutorial16.htm

http://helicron.net/avr/quadrature/

http://en.wikipedia.org/wiki/Rotary_encoder#Incremental_rotary_encoder


......

wie im H2000 abgebildet angeschlossen und dann wie in dem helicron avr-code beschrieben in einer isr abgefangen

bis zu 7 mal kann eine impuls kommen danach kommt eine neue messung ... wichtig ist zu erkennen wer eher drann ist
daraus erbibt sich +1 oder -1 und das addierst du dann auf x bzw. y

fertig ... eigentlich ziemlich genial ... aus ner ausgedienten optischen maus ein roboter bauen asuro mäßig ... fragt sich wie gut die optische verfolgung ist


btw. meine billig ir-laser maus funzt am pc noch aus 10 cm entfernung
... nerfig fürs umsetzen ... gut für roboter


-----------------------
achso falls es nicht rausgekommen ist ps2 is zwar so net schlecht aber wohl mit der Wurst nach dem Schinken gschmissen wie man so sagt

MrSpock
29.04.2008, 12:23
Vielen Dank für die Links. Die sehen auf dem ersten Blick sehr interessant aus (werde mir die nachher mal genauer durchlesen).

Aber um noch mal auf die serielle Schnittstelle zurückzukommen. Haltet ihr eine Serielle Schnittstelle für nicht geeignet? Informationsverluste?
Btw. wie schnell werden die Daten über die PS2 Schnittstelle verschickt?

Viele Grüße,
MrSpock

oberallgeier
29.04.2008, 14:32
Hallo MrSpock,

eine gute Beschreibung der Anwendung eines Maussensors für die Positionsbestimmung ist hier zu finden (http://www.heise.de/ct/06/13/226/). Ich hatte das (noch) nicht ausprobiert, kann also selber nix genaueres darüber sagen.

crawl
30.04.2008, 10:36
nett .. .den kann man evtl direkt mal nachbauen

MrSpock
01.05.2008, 18:16
Wow. Das sieht wirklich recht interessant aus, allgemein der Roboter.
Mich zieht es momentan auch eher wieder in die Richtung, auch wenn es komplizierter ist.
Was ich besonders interessant finde, ist dass mit dem chip auch die Bilder auslesen kann. Das geht ja mit dem kleineren nicht.

Daher bin ich hier auf der Seite auch gerade am Suchen (und finden..) nach Artikeln in diese Richtung :).