Hallo Zusammen,
ich bin jetzt mit der Laser-Maus von General Keys weitergekommen:
1) Ansteuerung habe ich seriell realisiert. Dafür werden 5 Leitungen benötigt:
a) SCLK - Clock Leitung
b) SDIO - Datenleitung, halb-duplex für Senden und Empfangen von Daten
c) PD - wird nicht unbedingt benötigt, kann aber für eine Re-Synchronisation zwischen Maus und µC hilfreich sein
d) 5V Leitung
e) GND Leitung
Im Datenblatt des Sensors PAN301A steht genau das Protokoll beschrieben, an dem man sich halten muss. Nachfolgend ist mein Quellcode in C für den µC 56F5847 von Freescale (16-Bit) angefügt.
Aber jetzt zum wichtigen Teil: Zu welchem Ergebnis bin ich gekommen?
Das Ergebnis ist kurz gesagt nicht zufriedenstellen, denn die Maus ist sehr ungenau in der Positionsermittlung. Ich habe dazu auf ein Milimeterpapierblatt ein Koordinatensystem aufgebaut. Beim Anfahren von z.B. von P(6cm;6cm), erst Fahren über x-Achse dann über y-Achse wird der Wert mal ziemlich genau erreicht, mal nur in etwa. Beim Anfahren des gleichen Punktes über die Y-Achse und dann über die X-Achse, bekomme ich dann wieder andere Werte. Ganz schlecht sieht es aus, wenn man den Punkt diagonal anfährt.
Darüber hinaus z.B. bei eine Strecke von 1m, gibt die Maus mal 84 cm oder auch mal 36 cm. Es scheint, dass sie zwischendurch keine Werte erfasst. Für einen Roboter, aus meiner Sicht, nicht zu gebrauchen.
Habt ihr andere Erfahrungen gemacht ? Gibt es vielleicht ein anderer Sensor der zuverlässiger arbeitet ? Sind die Werte beim Auswerten über Quadratur zuverlässiger ? Oder habt ihr noch eine andere Idee, warum ich zu einem solchen schlechten Ergebnis komme. Könnt ja mal mein Quellcode überprüfen. Bin gerne für Vorschläge, Anmerkungen offen.
Eine Sache noch. Was mich wundert ist auch die Aussage des Herstellers. Angeblich eine Auflösung von 800 cpi. Ich habe festgestellt, dass sie eine Auflösung von 1600 cpi hat. Aber jeder erzählt ja was anderes. Bei Pearl wird sie mit 1200 cpi verkauft und bei der "PCPraxis" war sie im Test mit 1600 cpi angegeben: Preis/ Leistungsverhältnis: gut war das Erbenis des Tests von "PCPraxis".
Bei Gamestar: http://www.gamestar.de/hardware/test...s_1600dpi.html
wurde sie für Spiele als "völlig ungeeignet" bewertet.
Quellcode:
Code:
/* Including used modules for compilling procedure */
#include "Cpu.h"
#include "Events.h"
#include "SCLK.h"
#include "SDIO.h"
#include "us1.h"
#include "us3.h"
#include "PD.h"
#include "ms2.h"
#include "FC1.h"
/* Include shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
volatile bool us1_flag=FALSE; // Flag für 1us Timer
volatile bool us3_flag=FALSE; // Flag für 3us Timer
volatile bool ms2_flag=FALSE; // Flag für 2ms Timer
// Wartet bis der Timer 1us gelaufen ist
void wait_for_timer_1us (void);
void wait_for_timer_1us (void)
{
while(us1_flag==FALSE)
{
;
}
us1_flag=FALSE;
}
// Wartet bis der Timer 3us gelaufen ist
void wait_for_timer_3us (void);
void wait_for_timer_3us (void)
{
while(us1_flag==FALSE)
{
;
}
us3_flag=FALSE;
}
void wait_for_timer_2ms (void);
void wait_for_timer_2ms (void)
{
while(ms2_flag==FALSE)
{
;
}
ms2_flag=FALSE;
}
/* Funktion zur Übertragung von einem Byte an den Sensor*/
void pan_writeByte(unsigned char);
void pan_writeByte(unsigned char data)
{
signed char i;
SDIO_SetDir(TRUE); // SDIO auf Output setzen
for (i=7; i>=0; i--)
{
SCLK_ClrVal(); // SCLK auf Low setzen, Daten vorbereiten
if((data&(1<<i))!=0) // Bits werden rausgeschoben
{
SDIO_SetVal();
}
else
{
SDIO_ClrVal();
}
us1_Enable();
wait_for_timer_1us(); // Sensor Zeit lassen um Bit abzuholen
us1_Disable();
SCLK_SetVal(); //SCLK auf High setzen; Sensor übernimmt auf steigende Flanke
//us1_Enable();
//wait_for_timer_1us(); // Sensor Zeit lassen um Bit abzuholen
//us1_Disable();
}
}
/* Funktion zum Lesen eines Bytes vom Sensor */
unsigned char pan_readByte(void);
unsigned char pan_readByte(void)
{
signed char i;
unsigned char data=0;
volatile bool wert=FALSE; // Status SDIO
SDIO_SetDir(FALSE); // HI-Z state wird gesetzt
us3_Enable();
wait_for_timer_3us(); // Sensor Zeit geben, um die Daten aus dem Register zu holen
us3_Disable();
for (i=7; i>-1;i--)
{
SCLK_ClrVal(); // fallende Flanke; Sensor bereitet Daten vor
us1_Enable();
wait_for_timer_1us(); // Sensor Zeit geben
us1_Disable();
SCLK_SetVal(); // steigende Flanke; Daten werden gelesen
//us1_Enable();
//wait_for_timer_1us(); // Etwas warten damit das Signal sicher anliegt
//us1_Disable();
wert=SDIO_GetVal(); // Bit einlesen
//us1_Enable();
//wait_for_timer_1us(); // Etwas warten damit die Variable sicher geschrieben wird
//us1_Disable();
if (wert!=0)
{
data|=(1<<i);
}
else
{
; //data&= ~(1<<i);
}
}
return data;
}
/* Funktion überträgt ein write-Kommando an den Sensor */
/* Eingabeparameter: Adresse u. zu schreibendes byte*/
void pan_write(unsigned char, unsigned char);
void pan_write(unsigned char adr, unsigned char data)
{
adr|=(1<<7); // MSB wird auf 1 gesetzt
pan_writeByte(adr); // MSB muss 1 sein für Write Operation
pan_writeByte(data);
}
/* Funktion überträgt ein Lesekommando an den Sensor */
/* und liest ein Byte zurück */
/* Parameter: Adresse u. Rückgabe des Registerwertes*/
unsigned char pan_read(unsigned char);
unsigned char pan_read(unsigned char adr)
{
pan_writeByte(adr);
return pan_readByte();
}
/* Initialisierung des PAN301ASI-208
Diese Funktion muss unbedingt ganz am Anfang von main stehen.
Wenn der Sensor sich initialisiert hat, bevor der Controller
SCLK und SDIO auf Output gesetzt hat gibt es Fehler.
*/
void pan_init(void);
void pan_init(void)
{
us1_Disable(); // Timer zunächst deaktivieren
us3_Disable();
ms2_Disable();
FC1_Disable();
SDIO_SetDir(TRUE); // SDIO auf Output setzen
SCLK_SetDir(TRUE); // SCLK auf Output setzen
PD_SetDir(TRUE); // PD auf Output setzen
SCLK_SetVal(); // SCLK auf High setzen
SDIO_SetVal(); // SDIO auf High setzen
PD_ClrVal(); // PD auf low setzen
// Reset Sensor und kein sleep Modus
pan_write(0x05,0x01);
}
// Funktion zum reseten der seriellen Schnittstelle zur Maus;
// Serielle Schnittstelle wird nur re-synchronisiert; Register werden
// nicht gelöscht
void reset (void);
void reset (void)
{
int i=0;
SCLK_SetVal();
us1_Enable();
wait_for_timer_1us();
us1_Disable();
SCLK_ClrVal();
us1_Enable();
wait_for_timer_1us();
us1_Disable();
SCLK_SetVal();
us1_Enable();
for (i=1;i<2000;i++)
{
wait_for_timer_1us();
}
us1_Disable();
}
void main(void)
{
unsigned char motion=0; // Variable zur Angabe, ob eine Bewegung erfolgte
signed int x=0; // delta X
signed int y=0; // delta Y
signed long posx=0, posy=0; // Absolute Position in Counter
double posxcm=0.0, posycm=0.0;
int test=0; // Überprüfung, ob die Kommunikation fehlerfrei ist
int ueberlaufx=0; // Überprüfung, ob Überlauf im x-Buffer
int ueberlaufy=0; // Überprüfung, ob Überlauf im y-Buffer
unsigned int m=0; // Prüfung wie oft die Endlosschleife läuft
unsigned int ueberlaufxbei=0; // bei welchem Schleifengang ueberlauf x
unsigned int ueberlaufybei=0; // bei welchem Schleifengang ueberlauf y
unsigned char reg1=0; // Variable zum Speichern des gelesenen Registerwertes
unsigned char reg2=0; // Variable zum Speichern des gelesenen Registerwertes
unsigned int fehler=0;
unsigned int ende=0;
word counter=0;
word *pcounter=0;
word maxwert=0;
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* Write your code here */
// ganz an den Anfang wird initialisiert, damit der Controller
// schneller als der Sensor reagiert, um Fehler zu vermeiden
reset(); // Reseten der seriellen Schnittstelle
pan_init(); // Initialisierung der seriellen Schnittstelle
//pan_write(0x07,0x08); // Möglichkeit zum Schreiben eines Registers
reg1=pan_read(0x05); // Direkte Überprüfung des geschriebenen Wertes
reg2=pan_read(0x00); // Direkte Überprüfung des geschriebenen Wertes
for(;;)
{
/*
ms2_Enable();
wait_for_timer_2ms();
ms2_Disable();
*/
FC1_Enable();
FC1_Reset();
m=m+1;
if (pan_read(0x00)!=0x30)
{
test=1; // Prüfung ob Kommunikation i.O.
fehler=m;
}
else
{
;
}
motion=pan_read(0x02);
//Überprüfen, ob das Überlauf-Bit im Register 0x02 gesetzt ist. Wenn das der Fall
// ist, wird die Variabe ueberlaufx gesetzt.
if ((motion&(1<<3))!=0)
{
ueberlaufx=1;
ueberlaufxbei=m;
}
else
{
;
}
//Überprüfen, ob das Überlauf-Bit im Register 0x02 gesetzt ist. Wenn das der Fall
// ist, wird die Variabe ueberlaufy gesetzt.
if((motion&(1<<4))!=0)
{
ueberlaufy=1;
ueberlaufybei=m;
}
else
{
;
}
// wenn 7tes bit vom Register 0x02 gesetzt ist wurde die Maus bewegt
// Bewegungsdaten dann abfragen
if((motion&(1<<7))!=0)
{
ende=m;
// Delta x Register auslesen
x=(signed int)((signed char)pan_read(0x03));
// Delta y Register auslesen
y=(signed int)((signed char)pan_read(0x04));
// und zu der Positionsvariable addieren
posx=posx+((long)(x));
posy=posy+((long)(y));
posxcm=((double)(2.54/1600))*((double)(posx));
posycm=((double)(2.54/1600))*((double)(posy));
}
pcounter=&counter;
FC1_GetCounterValue(pcounter);
FC1_Disable();
if (maxwert<counter)
{
maxwert=counter;
}
else
{
;
}
}
}
/* END Maus */
/*
** ###################################################################
**
** This file was created by UNIS Processor Expert 2.95 [03.58]
** for the Freescale 56800 series of microcontrollers.
**
** ###################################################################
*/
Lesezeichen