Inhaltsverzeichnis
Grundsätzliches
Computermäuse bieten sich als Entfernungs- und Geschwindigkeitsmesser in autonomen Robotern geradezu an. Die Entwicklung weg von den "Kugelmäusen" hin zu optischen Sensoren hat viele Probleme beseitigt, welche diese Bausteine jetzt hochinterressant erscheinen lassen:
- berührungslos
- billig
- hochintegriert und einfach zu beschalten
Die optischen Mäuse verfügen über eine kleine CCD-"Kamera" von 16x16 bis 30x30 Pixeln. Damit wird ein mikroskopisches Bild des Untergrundes aufgenommen. Über den Vergleich zweier aufeinander folgender Bilder mittels eines integrierten DSPs wird eine Bewegungs-Information errechnet, welche die Bewegungsrichtung (2 Achsen) und Entfernung beinhaltet. Viele dieser Sensorchips haben noch einen "Kompatibilitätsmodus", welcher Quadratur-Signale wie eine Kugelmaus zur Verfügung stellt. Die neueren Chips verzichten darauf immer häufiger.
In einer Maus findet man in aller Regel den Sensorchip selber und einen Controller, der das Sensorsignal auswertet und in ein PS/2 oder USB-Signal umwandelt.
Sehr verbreitet in der Anfangszeit der optischen Mäuse waren die Sensoren von Agilent ADNS2051. Die Chips in vielen Billigmäusen sind dazu kompatibel, auch wenn die Bezeichnungen abweichen. In den meisten Billigmäusen (< 7€) finden sich der PAN101 oder der kleine Bruder PAN3101 von Pixart.
Häufig kann über den SDIO-Anschluss auch das Sensorbild ausgelesen werden, was praktisch zur Anpassung einer Geänderten Optik ist.
Anschluss (elektrisch)
Der Anschluss über SDIO ist relativ simpel. Man braucht muss zwei PINS dazu identifizieren, Clock und SDIO. Der Takt wird vom Controller vorgegeben, damit kann dann Bitweise gelesen oder geschrieben werden. Die Sensorchips haben in aller Regel auch ein paar Konfigurations-Register, in denen Betriebsmodus und Auflösung eingestellt werden können.
Für die Quadratur-Ausgänge muss man 4 leitungen am Chip identifizieren.
seriell über SDIO
Über Quadratur-Ausgänge
Auswertung (Software)
Hier bitte Codebeispiele einfügen, anhand derer man einen Einstieg finden kann.
seriell über SDIO
Der hier vorgestellte Code ist in C geschrieben. Er ermöglicht es einen PAN3101 oder,
nach kleinen Änderungen bei den Registern, einen PAN101 (großer Bruder des PAN3101)
zu beschreiben und auszulesen.
Das Main Programm liest immer wieder die DeltaXund DeltaY Register ein, wobei auch
eventuelle Überläufe überprüft werden und addiert diese zu den Positionsvariablen
posx und posy. Diese können dann ausgegeben werden.
#define DDR_SCK DDRB /*!< DDR fuer Maus-SCLK */ #define DDR_SDA DDRA /*!< DDR fuer Maus-SDA */ #define PORT_SCK PORTB /*!< PORT fuer Maus-SCK */ #define PORT_SDA PORTA /*!< PORT fuer Maus-SDA */ #define PIN_SDA PINA /*!< PIN fuer Maus-SDA */ #define SCK_PIN (1<<PB0) /*!< PIN nummer fuer Maus-SCK */ #define SDA_PIN (1<<PA0) /*!< PIN nummer fuer Maus-SDA */ /*! * Uebertraegt ein Byte an den Sensor * @param data das Byte */ void pan_writeByte(unsigned char data){ signed char i; DDR_SDA|= SDA_PIN; // SDA auf Output for (i=7; i>=0; i--){ PORT_SCK &= ~SCK_PIN; //SCK auf Low, Daten vorbereiten if(data&(1<<i)){ //Bit rausschieben PORT_SDA|=SDA_PIN; }else{ PORT_SDA&=~SDA_PIN; } PORT_SCK |= SCK_PIN; // SCK =1 Sensor uebernimmt auf steigender Flanke _delay_us(1); //Sensor Zeit lassen um Bit zu holen } DDR_SDA &=~ SDA_PIN; //HI-Z state PORT_SDA &=~ SDA_PIN; } /*! * Liest ein Byte vom Sensor * @return das Byte */ unsigned char pan_readByte(void){ signed char i; unsigned char data=0; _delay_us(3); //Sensor Zeit lassen um die Daten aus dem Register zu holen for (i=7; i>-1; i--){ PORT_SCK &= ~SCK_PIN; // SCK =0 Sensor bereitet Daten auf fallender Flanke vor ! _delay_us(1); //Sensor kurz zeit lassen PORT_SCK |= SCK_PIN; // SCK =1 Daten lesen auf steigender Flanke if(PIN_SDA&SDA_PIN){ //BIT einlesen data |= (1<<i); }else{ data &=~ (1<<i); } } return data; } /*! * Uebertraegt ein write-Kommando an den Sensor * @param adr Adresse * @param data zu schreibendes byte */ void pan_write(unsigned char adr, unsigned char data){ adr|=(1<<7); pan_writeByte(adr); //rl MSB muss 1 sein für Write Operation pan_writeByte(data); } /*! * Schickt ein Lesekommando an den Sensor * und liest ein Byte zurueck * @param adr die Adresse * @return der registerwert */ unsigned char pan_read(unsigned char adr){ pan_writeByte(adr); return pan_readByte(); } /*! * Initialisiere PAN3101 !! Muss unbedingt ganz am ANFANG von main stehen, sonst gibts FEHLER !! (wenn der PAN3101 sich initialisiert hat, bevor der Controler SCK und SDA auf Output gestellt hat) Deshalb kann es auch sinnvoll sein die Powerup Zeit in den Config Bits auf 4ms zu stellen oder noch besser mit Boden zu arbeiten. */ void pan_init(void){ DDR_SCK |= SCK_PIN; // SCK auf Output DDR_SDA |= SDA_PIN; //SDA auf Output PORT_SCK |= SCK_PIN; // SCK auf high PORT_SDA|= SDA_PIN; //SDA auf high // hier müssen bei Umstellung auf PAN101 die entsprechenden Register gesetzt werden //Reset PAN3101 pan_write(0x00,0x80); // kein Sleep modus pan_write(0x00,0x01); } int main(void){ unsigned char ino; signed char x,y; signed short posx=0,posy=0; //ganz an den Anfang damit der Controller schneller asl der PAN ist um Fehler zu vermeiden pan_init(); //Individuelle Port Configuration und Initialisierung initialisierung(); lcd_init(LCD_DISP_ON); lcd_clrscr(); while(1){ //Endlosschleife ino=pan_read(0x16); //wenn 7tes bit vom Register 0x16 gesetzt ist wurde die Maus bewegt => Bewegungsdaten abfragen if(ino&(1<<7)){ //Deltax Register auslesen x=pan_read(0x17); //und zu der Positionvariable addieren posx=posx+x; /* Nachschaun ob das Überlauf-Bit im Register 0x16 gesetzt ist wenn das der Fall ist muss je nach Vorzeichen der Deltax Variable x noch 128 (überlauf nach oben) dazugezählt oder eben 128 abgezogen werden */ if(ino&(1<<3)){ if(x<0){ posx-=128; }else{ posx+=128; } } //ab hier nochmal das Gleiche für die yRichtung y=pan_read(0x18); posy=posy+y; if(ino&(1<<4)){ if(y<0){ posy-=128; }else{ posy+=128; } } } //hier kann jeder seine Ausgabevariante selber wählen ;) lcd_ausgabe_int(0,3,posx); lcd_ausgabe_int(7,3,posy); } return 0; }
Das Programm wurde mit einem PAN3101 auf einem ATMega32 mit 14,7456 Mhz getestet und lief problemlos.
über Quadratur-Ausgänge
Autor/en
- Reinald
- Javik