PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schnittstelle für PAN101(Sensor einer optischen Maus)



Javik
15.08.2006, 10:39
Hi!

Ich möchte für meinen Roboter zur Positionsbestimmung den Bewegungssensor aus einer Optischen Maus verwenden!
Ich hab mir schon mal eine Zugelegt. da war ein PAN101 Chip drin.
Soweit kein Problem man findet auch ein Datenblatt http://www.pixart.com.tw/upload/PAN101B_V14_20051121170156.pdf

Ich möchte den PAN101 nun über die Serielle Schnitstelle auslesen die er bereit stellt. Die Quadratur Signale sind mir zu "belastend" für meinen AATMega32.
OKay zuerst dachte ich mir, dass das mit der Schnittstelle gar nich so schwer sein kann ;) es hörte sich so nach SPI an.
Jetzt das Problem: der PAN101 hat nur eine Datenleitung SDIO die je nach dem Input oder Output ist!
Für eine "Normale" SPI Kommunikation braucht man so viel ich weis aber 2 Datenleitungen. eine die an den MISO und eine die an den MOSI Pin meines ATMega 32 kommt.
als erste Lösung dachte ich mir, dass ich einfach MISO und MOSI vom Atmega an den SDIO Pin des PAN101 hänge.
kann das funktionieren?

bei meinen ersten Tests hat das leider nicht Funktioniert. ich denke es liegt daran, dass beim SPI Protokoll GLEICHZEITIG geschrieben (über MOSI) und gelesen (über MISO) wird... stimmt das so weit?
weil bei meinen tests hab ichs irgendwann so hingefummelt gehabt, dass ich immer das empfangen habe, was ich auch gesendet hab (da waren MISO und MOSI zusammen an SDIO gehängt)

Ich wäre sehr froh wenn ich nur irgendwo nen Fehler hätte, weil dann könnte ich SPI verwenden und müsste nicht eine Eigene Schnittstelle Programmieren. denn genau daran knapper ich gerade. Und ich schaffs einfach nicht die Schnittstelle so hinzubekommen!
Kann mir vlt jemand tipps dazu geben?
(im Datenblatt ist alles beschrieben)
Grüße Javik

Javik
15.08.2006, 13:21
So ich hab jetzt hier mal einen Ansatz den ich auf meinem ATMega 32 mit 14745600Mhz programmiert habe:




volatile unsigned char tim0=0;
volatile unsigned char c=0;
volatile unsigned char data=0b10100001;

ISR(TIMER0_OVF_vect){
TCNT0=249;//alle 3,75µs
//bei TCNT0 =0 tim0 wird in fosc/8 schritten hochgezählt! 0,54µs

//Clockleitung Toggeln
PORTB^=(1<<SCK);
//Sorgt dafür, das immer erst nach einmal High low an der CLOCKleitung üder die Datenleitung das nächste Bit rausgegeben wird
if(tim0==0){
tim0++;
//Data wird ausgegeben
if(data&(1<<c)) {PORTB|=(1<<MOSI); }else {PORTB&=~(1<<MOSI);}
if (c<7) {
//damit beim nächsten aufrufen das nächste Bit rausgegeben wird
c++;
} else {
//wenn das Byte raus is wird das nächste gesendet, wenn das auch gesendet wurde wird der interrupt abgeschalten und ein Beendet signal ans LCD ausgegeben(eine 1)
c=0;
if (data==0b10100001) {data=0b01011110;} else {TIMSK&=~(1<<TOIE0);c=0;LCD_ausgabe_int(0,3,1);}
}
}else{
tim0=0;
}

}



Der Timer ist mit einem Prescaler von 8 eingestellt und wird einfach nach einer kurzen Anfangssequenz(LED blicken) angemacht.
Dann sollte er ja eigentlich die Daten senden?!
Es funktioniert auf jedenfall so noch nicht...

Jango
15.09.2006, 20:54
Ich beschäftige mich erst seit einigen Minuten damit.
Möchte auch den Sensor, a la c't Bot verwenden und in meiner Billig Maus ist auch ein PAN101.
Jetzt hab ich in der PS/2 Spec auf Wikipedia gelesen, dass PS2 im Prinzip auch SPI is mit Daten-, Clockleitung und Vcc/Gnd.
Vielleicht einfach dort MISO und SCK anschliessen?!

Schaue mir den Kram aber nochmal in Ruhe an.. :-)

Nachtrag: Im Schaltplan des ct Bot zur Maus ist übrigens genau das angezapft. SDIO und SCK sind zum AVR geführt, wobei SDIO vom Pan mit dem MISO vom AVR verbunden ist. MOSI wird nicht verbunden. Sollte also so gehen.

Javik
16.09.2006, 19:36
Hmm ja ich bin leider auch noch nicht weitergekommen damit!
Ich weis nur, dass beim c't Bot ja auch so ein ähnlicher Chip ausgelesen wird. könnte man denn nicht die Routine die beim c't Bot dabei ist auf den PAN101 umschreiben?

das Problem ist meiner Meinung nach, dass man erst mal was schicken muss, damit der PAN überhaupt reagiert und was zurückschickt.
allerdings weis ich nicht woran man bemerken sollte, dass der PAN reagiert. das macht es extrem schwer das ganze per try and error zu lösen.
ich hatt in letzter Zeit weinig Zeit daran weiter zu arbeiten, es is auch ziemlich frustrierend wenn einfach nix zurückkommt ;)
ich bin jederzeit froh über neue Erkenntnisse oder irgendwas was weiterhelfen könnte!
poste doch mal deine Erfahrungen mit der Kommunikation zum PAN!
würd mich freuen wenn wir das zusammen hinkriegen würden!
Grüße Javik

Jango
16.09.2006, 23:05
Habs heute Abend hinbekommen nach einigem Gewurschtel.
Werte morgen den Code und ein paar Kommentare posten(, allerdings in BASCOM Basic.)

Gute Nacht,
Jango

Javik
17.09.2006, 07:03
Wow das ging schnell!
Ich freu mich auf deinen Code! Bascom is kein Problem.
Ich kann beide Sprachen wäre das okay wenn ich ihn übersetze in C?
(dann passt das auch in die Kategorie rein hier ^^)

Grüße Javik

Jango
17.09.2006, 14:55
Hi,

ich habe meine Erfahrungen mit dem PAN101 in einem neuen Thread https://www.roboternetz.de/phpBB2/viewtopic.php?p=212224 (Sensoren) gepostet.

Ich hoffe, es hilft, bei Fragen, nur zu. Ich werde mich unter der Woche dann ans montieren und Auswerten während der Fahrt machen.

Tschö,
Jango

Javik
18.09.2006, 19:55
Hey Leute hatte gerade den Durchbruch auch dank Jangos Basic Code;)

Ich habe den Code mit einem PAN3101 getestet.
Der PAN3101 ist quasi der kleine Bruder vom PAN101. er hat nur 8 PINs und nur eine Serielle Schnittstelle(ohne Quadratur Ausgänge) aber ansonsten hat er sogar mehr Register zum beschreiben als der PAN101.

Sehr nützlich ist da zB ein Register in dem ein Byte werd liegt der die Untergrundbeschaffenheit bewertet (0 schleecht - 255 guut). aber ansonsten sind da viele sachen doppelt drin ^^

Naja ich will damit nur sagen, dass wenn jemand meinen Code mit dem PAN101 verwenden will, er die Registeradressen noch auf den PAN101 umschreiben muss (das gilt vor allem für pan_init !)
Aber anosnten sollte das Hinhaun!

Nachfolgender Code ist hat auf meinem ATMega 32 mit 14,7456Mhz super funktioniert.
Die LCD Routinen sind nur zur Ausgabe gedacht. An die Stellen soll sich jeder seinen eigenen Code zur Ausgabe der Daten setzen ;)




#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#include <util/delay.h>

//#include <mouse.c>
#include <lcd.h>
#include <lcd.c>


//hier kann die PINconfiguration angepasst 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 Datenblatt S.12 Write Operation
pan_writeByte(data);
//_delay_ms(4);
}



/*!
* 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 !!

*/
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


//Reset PAN3101
pan_write(0x00,0x80);
// kein Sleep modus
pan_write(0x00,0x01);
}


int main(void){
unsigned char ino;
signed char x,y;

pan_init();
lcd_init(LCD_DISP_ON);
lcd_clrscr();

//bisschen warten bevors losgeht ;)
for(ino=0;ino<20;ino++){_delay_ms(255);}

while(1){

ino=pan_read(0x16);

if(ino&(1<<7)){ //wenn 7tes bit gesetzt ist wurde die Maus bewegt => bewegungsdaten abfragen
x=pan_read(0x17);

y=pan_read(0x18);

lcd_ausgabe_int(0,2,x);
lcd_ausgabe_int(4,2,y);
}

_delay_ms(250);
_delay_ms(250);

}


return 0;
}



ansonsten bin ich für Kritik offen :) und freue mich über Fragen ;)

Grüße Javik