Hi,
das Thema Maussensor und RP6 intressiert mich auch. Bin da auch gerade dran... mal schauen obs was wird.
mfg
benx
Druckbare Version
Hi,
das Thema Maussensor und RP6 intressiert mich auch. Bin da auch gerade dran... mal schauen obs was wird.
mfg
benx
Hi andieh,
Das Bild sieht man nur, wenn man eingeloggt ist, oder was meintest du?Zitat:
das bild hätte mich jetzt auch interessiert
Den ADNS-2610 gibt es z.B. bei Segor für €3,20. Allerdings nutzt einem der Sensor alleine nicht viel, man braucht auf jeden Fall auch noch die Optiklinse und die zugehörige LED. Damit kommt man dann auf ca. 5€ bei Segor. Dafür kriegt man fast schon eine neue Maus, wo das auch schon alles drin ist. Im CC2 Forum hat man sich für den ADNS5020 entschieden, weil dieser in der Logitech RX250 verbaut ist. Diese Maus bekommt man für €7,95 bei Reichelt.Zitat:
öhm, wo kriegt man so nen sensor her, wenn man gerade nicht zufällig ne alte maus da hat
hi,
Wow so viele Antworten in nur einem Tag!!! Ich hätte nicht gedacht das ich mal so ein bedeutendes Thema eröffne. hi m.a.r.v.i.n braucht man nicht für den Maussensor ADNS1620 auch einen Oszillator oder so irgendwas? Das wäre dann nämlich auch in der Maus drin. Hey radbruch das mit dem I²C werde ich acuh mal ausprobieren vielleicht schaffen wir es ja ne Lösung zu finden. Könntest du mal den Schaltplan deines Adapters reinstellen? Und, der RP6 hat von dem Maussensor schon einigen Nutzen er könnte z.b. Die Geschwindigkeit einregeln, einregeln wie weit er noch drehen muss um die vorgegebene Drehung zu vollenden oder einfach die Daten auf einem Display anzeigen. Ausserdem geht es hier glaube ich eher um den Spaß beim Suchen einer Lösung als um den Nutzen. Übrigens andieh der Chip war bei mir auch nich identiefizierbar. Bei mir z.b stand A2620 drauf und ich hab im Internet gesucht und gesucht und dann hab ich durch zufall herausgekommen das es eigentlich ein ADNS2620 ist(Bei den Suchen kam immer nur was über Steckboards und Commodore Computer :D )
mfg Panzerfan
Hallo
Ich habe mal grob die Timeings der 26xx mit meinem 2051 verglichen. Bis auf die unterschiedlichen Verzögerungen scheint das gleich. Vor allem das Zusammenspiel von Takt und Daten ist gleich. Hier nun mein erster funktionierender Versuch:
wenn man die Maus bewegt werden die Daten zum RP6Loader gesendet :)Code:// RP6 liest optischen Maussensor aus (nur x/y)(Maussensor: ADNS-2051) 22.1.09 mic
#include "RP6RobotBaseLib.h"
#define clk_h DDRC |= 1; PORTC |= 1 // Für Anschluss an SDA/CLK am XBUS
#define clk_l DDRC |= 1; PORTC &= ~1 // clk - Pin 10
// data= Pin 12
#define data_h DDRC |= 2; PORTC |= 2 // Vcc - Pin 3
#define data_l DDRC |= 2; PORTC &= ~2 // GND - Pin 1
#define data_z DDRC &= ~2; PORTC &= ~2
#define data_in (PINC & 2)
/*
#define clk_h DDRA |= 1; PORTA |= 1 // Für Anschluss an ADC0/1
#define clk_l DDRA |= 1; PORTA &= ~1 // clk - ADC0
// data- ADC1
#define data_h DDRA |= 2; PORTA |= 2
#define data_l DDRA |= 2; PORTA &= ~2
#define data_z DDRA &= ~2; PORTA &= ~2
#define data_in (PINA & 2)
*/
void init( void)
{
data_z;
clk_h;
sleep(5);
clk_l;
mSleep(2000); //timeout adnr2051 erzwingen => reset
}
void write_data(uint16_t data)
{
uint8_t bit=16;
while(bit--)
{
if(data & (1<<bit)) {data_h;} else {data_l;} // Klammern sind hier muss!
sleep(5);
clk_h;
sleep(5);
clk_l;
sleep(5);
}
data_z;
sleep(20);
}
uint8_t read_data(uint8_t adr)
{
uint8_t bit, data;
bit=8;
while(bit--)
{
if(adr & (1<<bit)) {data_h;} else {data_l;}
sleep(5);
clk_h;
sleep(5);
clk_l;
sleep(5);
}
clk_l;
data_z;
sleep(20);
bit=8;
data=0;
while(bit--)
{
clk_h;
if(data_in) {data |= (1<<bit);}
sleep(5);
clk_l;
sleep(5);
}
sleep(20);
return(data);
}
int main(void)
{
uint8_t status;
initRobotBase();
init();
writeString_P("Produkt-ID: ");
writeInteger(read_data(0), 16);
writeString_P("\n\n\r");
while(1)
{
status=read_data(2);
if(status & 128) // Bewegung erkannt?
{
writeString_P("Status: "); // wenn Bit7 gesetzt ist
writeInteger(status, 16);
writeString_P(" x: ");
writeInteger(read_data(3), 10); // können die eingefrorenen Deltawerte
writeString_P(" y: "); // für x und y ausgelesen werden.
writeInteger(read_data(4), 10);
writeString_P("\n\r");
}
sleep(255);
}
while(0) // Testansteuerung
{
clk_h;
data_h;
mSleep(1000);
clk_l;
mSleep(1000);
clk_h;
data_l;
mSleep(1000);
clk_l;
mSleep(1000);
clk_h;
data_z;
mSleep(1000);
clk_l;
mSleep(1000);
}
return(0);
}
Das Programm verwendet zwei Funktionen:
write_data() sendet 16 Bits zur Maus. Bit15-8 sind dabei die Adresse, Bit7-0 die Daten. Bit15 für Schreibzugriff muss man selbst setzen!
read_data(adresse) liest Daten von der angegebenen Adresse. Dazu wird zuerst die Adresse gesendet, kurz gewartet und dann werden die Daten eingelesen.
Das Timeing ist noch nicht optimiert, Wartezeiten von 5 sleep()s dürften aber reichlich zuviel sein.
Der Chip in meiner Maus wurde mit digitalen Ausgängen genutzt, die Takt- und Datenpins waren mit GND verbunden. Ich habe sie einfach abgezwickt und das Kabel direkt auf die Pins gelötet. Vcc und GND sind geblieben:
Bild hier Bild hier
Das USB-Kabel steckt dann direkt im XBUS.
Ich glaube nicht das man die Maus sinnvoll zur Wegmessung/-berechnung nutzen kann, lasse mich aber gerne vom Gegenteil überzeugen.
Viel Spaß beim Nachbau.
[Edit]Noch ein kleines Update:
Bevor man mit dem Maussensor ein Foto machen kann sollte man die LED einschalten:
Bild hier
http://www.youtube.com/watch?v=Lhg-QdRft-A
Das funzt ja schon prima:
[NocheinEdit]Code://RP6 schaltet die LED einer optischen Maus (Maussensor: ADNS-2051) 22.1.09 mic
#include "RP6RobotBaseLib.h"
#define clk_h DDRC |= 1; PORTC |= 1 // Für Anschluss an SDA/CLK am XBUS
#define clk_l DDRC |= 1; PORTC &= ~1 // clk - Pin 10
// data= Pin 12
#define data_h DDRC |= 2; PORTC |= 2 // Vcc - Pin 3
#define data_l DDRC |= 2; PORTC &= ~2 // GND - Pin 1
#define data_z DDRC &= ~2; PORTC &= ~2
#define data_in (PINC & 2)
/*
#define clk_h DDRA |= 1; PORTA |= 1 // Für Anschluss an ADC0/1
#define clk_l DDRA |= 1; PORTA &= ~1 // clk - ADC0
// data- ADC1
#define data_h DDRA |= 2; PORTA |= 2
#define data_l DDRA |= 2; PORTA &= ~2
#define data_z DDRA &= ~2; PORTA &= ~2
#define data_in (PINA & 2)
*/
void init( void)
{
data_z;
clk_h;
sleep(5);
clk_l;
mSleep(1500); // timeout adnr2051 erzwingen zur Syncronisation
// kein Takt seit mehr als 0,9sec => reset
}
void write_data(uint16_t data)
{
uint8_t bit=16;
while(bit--)
{
if(data & (1<<bit)) {data_h;} else {data_l;} // Klammern sind hier muss!
sleep(5);
clk_h;
sleep(5);
clk_l;
sleep(5);
}
data_z;
sleep(20);
}
uint8_t read_data(uint8_t adr)
{
uint8_t bit, data;
bit=8;
while(bit--)
{
if(adr & (1<<bit)) {data_h;} else {data_l;}
sleep(5);
clk_h;
sleep(5);
clk_l;
sleep(5);
}
clk_l;
data_z;
sleep(20);
bit=8;
data=0;
while(bit--)
{
clk_h;
if(data_in) {data |= (1<<bit);}
sleep(5);
clk_l;
sleep(5);
}
sleep(20);
return(data);
}
int main(void)
{
uint8_t adresse, daten;
initRobotBase();
init();
writeString_P("Produkt-ID: ");
writeInteger(read_data(0), 16);
writeString_P("\n\n\r");
adresse=0x8a; // Registernr. + Bit7 gesetzt weil Kommando!
daten=0b00000001; // Bit0 gesetzt ist Sleep-Mode aus
//76543210
while(1)
{
write_data(256*adresse+daten); // Lampe an
mSleep(500);
write_data(256*adresse); // Lampe aus
init(); // Timeout erzwingen um PowerDown-Zeit zu umgehen
}
return(0);
}
Ist doch nicht sooo schwierig:
Zweimal der Scan einer Steuermarke auf einer Zigarettenschachtel, Maus wurde nicht bewegt. Das Dritte ist ein Scan aus einer Zeitschrift(Text).Code:[READY]
Produkt-ID: 2
Bilddaten des Maussensors:
0123456789abcdef
0 |#¤¤¤¤¤¤¤x××××××·|
1 |¤¤¤¤¤#¤¤¤x××××··|
2 |¤¤¤¤¤##¤¤xx×××··|
3 |¤¤¤¤¤##¤¤¤x×××··|
4 |x¤¤¤¤###¤¤¤x××··|
5 |x¤¤¤¤###¤¤¤x×××·|
6 |xx¤¤¤##¤#¤¤x××·×|
7 |xxx¤¤¤#¤¤¤¤x××·×|
8 |xxx¤¤#¤¤¤¤¤x××··|
9 |¤x×x¤¤¤¤¤¤¤x×···|
a |¤x×x¤¤¤¤¤xxx×···|
b |xx××x¤¤¤xxxx××··|
c |xx×××x¤xxxx××···|
d |×xx××xxxxx××····|
e |××××××xx××××····|
f |×××·×××××××·····|
[READY]
Produkt-ID: 2
Bilddaten des Maussensors:
0123456789abcdef
0 |#¤¤¤¤¤¤¤x××××××·|
1 |¤¤¤¤¤#¤¤¤x××××··|
2 |¤¤¤¤¤##¤¤x××××··|
3 |¤¤¤¤¤#¤¤¤¤x×××··|
4 |x¤¤¤¤###¤¤¤×××··|
5 |x¤¤¤¤¤##¤¤¤x×××·|
6 |xx¤¤¤##¤#¤¤x××·×|
7 |xxx¤¤¤#¤¤¤¤x××·×|
8 |¤xx¤¤¤¤¤¤¤xx××··|
9 |¤××x¤¤¤¤¤¤xx×···|
a |¤x×x¤¤¤¤¤xxx×···|
b |xx××x¤¤¤xxxx××··|
c |xxx××x¤xxxx××···|
d |××x××xxxxxx×····|
e |××××××xx××××····|
f |×××·×××××××·····|
[READY]
Produkt-ID: 2
Bilddaten des Maussensors:
0123456789abcdef
0 |×······×××······|
1 |×···············|
2 |x×··············|
3 |¤¤x·············|
4 |¤¤¤¤x×··········|
5 |¤¤¤#¤xx××·×·×××·|
6 |¤¤¤¤#¤¤¤xxx×××××|
7 |¤¤¤¤#¤¤¤¤xxx××××|
8 |¤¤¤¤¤¤¤¤xxx×××·×|
9 |¤¤###¤¤¤xxx×××××|
a |¤¤##¤¤¤¤xx×××××·|
b |¤¤¤¤¤¤xxxx××××··|
c |xxx¤¤¤xxxx×××···|
d |xxxx¤xxxxx×××···|
e |xxxxxxxxx×××××··|
f |xxxxxxxx×××××···|
Code:// RP6 liest ein 16x16 Pixelbild vom Maussensor ein (63 Helligkeitswerte) 22.1.09 mic
// Maussensor: ADNS-2051
#include "RP6RobotBaseLib.h"
#define clk_h DDRC |= 1; PORTC |= 1 // Für Anschluss an SDA/CLK am XBUS
#define clk_l DDRC |= 1; PORTC &= ~1 // clk - Pin 10
// data= Pin 12
#define data_h DDRC |= 2; PORTC |= 2 // Vcc - Pin 3
#define data_l DDRC |= 2; PORTC &= ~2 // GND - Pin 1
#define data_z DDRC &= ~2; PORTC &= ~2
#define data_in (PINC & 2)
/*
#define clk_h DDRA |= 1; PORTA |= 1 // Für Anschluss an ADC0/1
#define clk_l DDRA |= 1; PORTA &= ~1 // clk - ADC0
// data- ADC1
#define data_h DDRA |= 2; PORTA |= 2
#define data_l DDRA |= 2; PORTA &= ~2
#define data_z DDRA &= ~2; PORTA &= ~2
#define data_in (PINA & 2)
*/
void init( void)
{
data_z;
clk_h;
sleep(5);
clk_l;
mSleep(1500); // timeout adnr2051 erzwingen zur Syncronisation
// kein Takt seit mehr als 0,9sec => reset
}
void write_data(uint16_t data)
{
uint8_t bit=16;
while(bit--)
{
if(data & (1<<bit)) {data_h;} else {data_l;} // Klammern sind hier muss!
sleep(2);
clk_h;
sleep(2);
clk_l;
sleep(2);
}
data_z;
sleep(20);
}
uint8_t read_data(uint8_t adr)
{
uint8_t bit, data;
bit=8;
while(bit--)
{
if(adr & (1<<bit)) {data_h;} else {data_l;}
sleep(2);
clk_h;
sleep(2);
clk_l;
sleep(2);
}
clk_l;
data_z;
sleep(20);
bit=8;
data=0;
while(bit--)
{
clk_h;
if(data_in) {data |= (1<<bit);}
sleep(2);
clk_l;
sleep(2);
}
sleep(20);
return(data);
}
int main(void)
{
uint8_t adresse, daten, zeile, spalte;
uint8_t graustufen[6]={32, 184, 216, 120, 165, 35}; // " ·×x¤#"
initRobotBase();
init();
writeString_P("Produkt-ID: ");
writeInteger(read_data(0), 16);
writeString_P("\n\n\r");
adresse=0x8a; // Registernr. + Bit7 gesetzt weil Kommando!
daten=0b00000001; // Bit0 gesetzt ist Sleep-Mode aus
//76543210
write_data(256*adresse+daten); // Lampe an
mSleep(500);
daten=0b00001001; // Bit3 gesetzt startet PixelDump
//76543210
write_data(256*adresse+daten); // Pixeldump anfordern
writeString_P("Bilddaten des Maussensors:\n\r");
writeString_P(" 0123456789abcdef\n\r");
for(zeile=0; zeile<16; zeile++) // 16x16=256 Pixel lesen
{
writeInteger(zeile, 16);
writeString_P(" |");
for(spalte=0; spalte<16; spalte++)
{
read_data(0x0d);
//do daten=read_data(0x0c); while(!(daten & 128);
daten=read_data(0x0c);
writeChar(graustufen[daten/10]); // 63 ist maxwert, 6 graustufen
}
writeString_P("|\n\r");
}
adresse=0x8a; // Lampe aus, PixelDump fertig
write_data(256*adresse);
while(1); // Kunstwerk betrachten
return(0);
}
hi,
Wow radbruch das ist ja schon ziemlich gut. Bei mir funztz noch nich so denn ich hab den chip ausgelötet den Quarz wieder angelötet und noch ein paar Kabel dran, wenn ich aber anschließe geht der RP6 gar nicht an oder er stürzt ab. Jetzt hol ich mir ne billige Lasermaus von Logitech.
mfg Panzerfan
PS: Dass ich den Maussensor rausgelötet hab hat einen Grund. Grund:
Die Maus war eine Funkmaus deshalb konnte man nicht so einfach wie bei radbruch die Kabel anlöten und ausserdem war die Maus komplett in SMD und die Bauteile waren ziemlich aneinander.
Edit:
Noch ne Idee für radbruch:
man könnte doch mehrere aufnahmen von deinem Sensor aneinander reihen und dann hätte man villeicht ein ganzes Bild(Sensor halt immer ein bisschen verschieben) :-k
Hallo Maussensorfans :)
Obwohl ich schon immer mal mit einer optischen Maus spielen wollte kommt so langsam die Ernüchterung. Zur Wegmessung nicht geeignet würde ich sagen. Der Hauptgrund: Bei jedem Auslesen der Deltadaten (Wegänderung seit der letzten Abfrage) gibt es einen Rundungsfehler der sich enorm addiert. Das alleine wäre schon übel, richtig schlimm ist die verlorene Orientierung schon nach kurzer Wegstrecke. Am PC korrigiert der Bediener die Ausrichtung der Maus, deshalb bewegt "Maus Richtung Kabel schieben" (weg vom Körper für Funkmäuse) den Mauszeiger am Bildschirm nach oben. Wenn man aber wärendessen die Maus zusätzlich noch auf dem Tisch dreht (so das ihr Kabel seitlich rauskommt) sieht man schön was ich meine. Vorwärts kann alle Richtungen sein.
An diese Deltadaten kommt man übrigends auch ohne die Maus zu öffnen über eine PS2-Schnittstelle.
Alternativ dazu könnte man natürlich auch die Bilddaten direkt verarbeiten. Aber das kann man meiner Meinung nach auch komplett vergessen. Mein ADNS-2051 kann bei 400 Dot/Inch 14 Inches/Sekunde, das sind knapp 40cm/Sekunde. Sein Bild hat 256 Bildpunkte, also 16x16 Pixel zu je 63 Graustufen. Bei ein Inch/400 Pixelgröße ist das "fotografierte" 16x16-Bild 25,4mm/400*16=1,016mm breit! Bei einer Brennweite von 2,4mm ist das unbrauchbar. Um mehrere Bilder zusammensetzen zu können muss man sie überlappend abspeichern (, drehen?) und dann zusammensetzen. Macht 256*6 Bit pro Bild + Ergebnissbild aus dem wir dann die absolut zurückgelegten Wege errechnen. Viel Spaß dabei mit dem AVR.
Damit wäre die Wegmessung für mich abgehakt. Eine alternative Anwendung wäre vielleicht eine Art Trackball zur Menusteuerung. Oder irgendwas in Richtung Linienerkennung/Barcodes... Dazu würde es reichen wenn man ein 16x16-Bild als ein einziges Pixel interpretiert und speichert. Aber wie erhält man einen representanten Wert für ein komplettes Bild? Das folgende gilt vielleicht nur für meinen ADNS-2051. Dieser liefert zu jedem Bild zusätzlich noch folgende Bilddaten: hellste Helligkeit, durchschnittliche Helligkeit, Anzahl unterschiedene Bildelemente(Güte), die Verschlußzeit (shutter) und schließlich die Framerate (Bilder/Sek). das sieht auf den erste Blick prima aus, die Tücke liegt in der automatischen Bildoptimierung des ADNS-2051: Er stellt die Verschlußzeit so ein das die max-Werte für die Helligkeit "in den 50ern" liegen:
(Aus dem Datenblatt im Kapitel über die "Pixel Dump Pictures")Zitat:
Pixel Dump Pictures
The following images (Figure 40) are the output of the pixel dump command. The data ranges from zero for complete
black, to 63 for complete white. An internal AGC circuit adjusts the shutter value to keep the brightest feature (max.
pixel) in the mid 50s.
Das bedeutet letztlich, dass die gespeicherten Helligkeitswerte eines Pixels von den Werten der Nachbarpixel abhängt. Viel Spaß beim pixelweisen Zusammensetzen der Bildchen...
Ein Ausweg scheint hier der Shutterwert zu sein. Er ist direkt abhängig von der durchschnittlichen Helligkeit des Bildes und eignet sich hervorragend zum Linienerkennen. Da es ein 16bit-Register ist wird aus einem 16x16-Bild ein 1mm-Pixel mit (fast) 64k-Graustufen. Ein Zahlenbeispiel: Shutterwert über hellen Bodenfiesen: 6tausendirgendwas, über dunklen Fugen: 380!. Wunderbar! Gleich mal testen :)
Naja, und dieser Test ist einfach: Die Maus über eine Linie schieben und möglichst auf dem selben Weg über die Linie zurückschieben. Währenddessen laufend die addierten Deltawerte und die Shutterstellungen ans Terminal ausgeben. Nichts, keine Chance. Meine Werte für die Linie waren nicht mal ähnlich. Deshalb habe ich die Maus nun wieder eingemottet.
Sorry, der Beitrag wurde irgendwie immer länger..
Gruß
mic
Hi,
Radbruch ich glaube du hast Recht. Das "Maus Richtung Kabel schieben" Beispiel zeigt das. Ich glaube ich lass jetzt das mit dem Maussensor und widme mich anderen Dingen.
mfg Panzerfan
Hi,
könnte man denn mit einem Maussensor messen ob sich der RP6 genau um eine gewünschte Gradzahl gedreht hat? Mein Problem ist das ich den RP6 auf unterschiedlichen Oberflächen betreibe und für einige Fahrmanöver eine relativ exakte Drehung (z.B. 90 Grad) brauche. Das bekomm ich trotz Änderung der ENCODER_RESOLUTION nie vernünftig hin.
Oder lieber gleich mit einem elektrischen Kompass versuchen? :-)
mfg
benx
da ich seit heute eine neue computer- maus besitze und der maussensor meiner alten noch voll funktioniert, ist das thema maussensor für mich nun auch interessant.
nach durchforsten des forums bin bisher immer nur auf threads gestoßen wo mit hilfe des sensors eine wegstrecke gemessen wurde. kann mir jemand von den erfahrenen "maussensorverwendern" sagen, ob er sich auch für eine hindernisserkennung eignet?
gruß
Hallo
Wenn die Maus keine Wegänderung mehr meldet ist sie blockiert weil der Roboter gegen ein Hinderniss gestoßen ist :) Den Maussensor als Kamera zu nutzen um damit Hindernisse zu erkennen kann man vergessen. Seine Brennweite beträgt nur ein paar Millimeter.
Schade eigentlich...
Gruß
mic