Hallo,
ich hab folgendes Problem:
Ich habe mir im Internet (https://www.tindie.com/products/jkicklighter/adns-9800-optical-laser-sensor/) dieses Maus Sensor gekauft, weil ich damit Winkelmessung beziehungsweise Längenmessung machen möchte.
Ich hab den Sketch von Jkicklighter verwendet. Das Programm läuft soweit ganz gut.
Nun habe ich habe ich folgendes Problem:
Der Sensor gibt mir bei unterschiedlichen Geschwindigkeiten und unterschiedlichen Auflösung immer eine andere Anzahl an Werten aus (Delta_x und Delta_y Werte) aus. Um eine sinnvolle Anwendung zu haben sollte ich möglichst immer die selben Werte erhalten.
Woran könnte das liegen? Könnt ihr mir dabei weiterhelfen?
Ist eventuell die Verbindung per USB zu langsam, ich habe 250000 baud eingestellt.
Oder gibt es irgendwelche Einstellungen, die ich noch vergessen habe?
byte initComplete = 0;
byte testctr = 0;
unsigned long currTime;
unsigned long timer;
volatile int xydat[2];
volatile byte movementflag = 0;
const int ncs =53;
extern const unsigned short firmware_length;
extern const unsigned char firmware_data[];
void setup() {
Serial.begin(9600);
pinMode (ncs, OUTPUT);
attachInterrupt(0, UpdatePointer, FALLING);
SPI.begin();
SPI.setDataMode(SPI_MODE3);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(8);
performStartup();
dispRegisters();
delay(100);
initComplete = 9;
}
void adns_com_begin() {
digitalWrite(ncs, LOW);
}
void adns_com_end() {
digitalWrite(ncs, HIGH);
}
byte adns_read_reg(byte reg_addr) {
adns_com_begin();
// send adress of the register, with MSBit = 0 to indicate it's a read
SPI.transfer(reg_addr & 0x7f );
delayMicroseconds(100); // tSRAD
// read data
byte data = SPI.transfer(0);
delayMicroseconds(1); // tSCLK-NCS for read operation is 120ns
adns_com_end();
delayMicroseconds(19); // tSRW/tSRR (=20us) minus tSCLK-NCS
return data;
}
void adns_write_reg(byte reg_addr, byte data) {
adns_com_begin();
//send adress of the register, with MSBit = 1 to indicate it's a write
SPI.transfer(reg_addr | 0x80 );
//sent data
SPI.transfer(data);
delayMicroseconds(20); // tSCLK-NCS for write operation
adns_com_end();
delayMicroseconds(100); // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
}
void adns_upload_firmware() {
// send the firmware to the chip, cf p.18 of the datasheet
Serial.println("Uploading firmware...");
// set the configuration_IV register in 3k firmware mode
adns_write_reg(REG_Configuration_IV, 0x02); // bit 1 = 1 for 3k mode, other bits are reserved
// write 0x1d in SROM_enable reg for initializing
adns_write_reg(REG_SROM_Enable, 0x1d);
// wait for more than one frame period
delay(10); // assume that the frame rate is as low as 100fps... even if it should never be that low
// write 0x18 to SROM_enable to start SROM download
adns_write_reg(REG_SROM_Enable, 0x18);
// write the SROM file (=firmware data)
adns_com_begin();
SPI.transfer(REG_SROM_Load_Burst | 0x80); // write burst destination adress
delayMicroseconds(15);
// send all bytes of the firmware
unsigned char c;
for (int i = 0; i < firmware_length; i++) {
c = (unsigned char)pgm_read_byte(firmware_data + i);
SPI.transfer(c);
delayMicroseconds(15);
}
adns_com_end();
}
void performStartup(void) {
adns_com_end(); // ensure that the serial port is reset
adns_com_begin(); // ensure that the serial port is reset
adns_com_end(); // ensure that the serial port is reset
adns_write_reg(REG_Power_Up_Reset, 0x5a); // force reset
delay(50); // wait for it to reboot
// read registers 0x02 to 0x06 (and discard the data)
adns_read_reg(REG_Motion);
adns_read_reg(REG_Delta_X_L);
adns_read_reg(REG_Delta_X_H);
adns_read_reg(REG_Delta_Y_L);
adns_read_reg(REG_Delta_Y_H);
// upload the firmware
adns_upload_firmware();
delay(10);
//enable laser(bit 0 = 0b), in normal mode (bits 3,2,1 = 000b)
// reading the actual value of the register is important because the real
// default value is different from what is said in the datasheet, and if you
// change the reserved bytes (like by writing 0x00...) it would not work.
byte laser_ctrl0 = adns_read_reg(REG_LASER_CTRL0);
adns_write_reg(REG_LASER_CTRL0, laser_ctrl0 & 0xf0 );
delay(1);
Serial.println("Optical Chip Initialized");
}
void UpdatePointer(void) {
if (initComplete == 9) {
digitalWrite(ncs, LOW);
xydat[0] = (int)adns_read_reg(REG_Delta_X_L);
xydat[1] = (int)adns_read_reg(REG_Delta_Y_L);
digitalWrite(ncs, HIGH);
movementflag = 1;
}
}
void dispRegisters(void) {
int oreg[7] = {
0x00, 0x3F, 0x2A, 0x02
};
char* oregname[] = {
"Product_ID", "Inverse_Product_ID", "SROM_Version", "Motion"
};
byte regres;
digitalWrite(ncs, LOW);
int rctr = 0;
for (rctr = 0; rctr < 4; rctr++) {
SPI.transfer(oreg[rctr]);
delay(1);
Serial.println("---");
Serial.println(oregname[rctr]);
Serial.println(oreg[rctr], HEX);
regres = SPI.transfer(0);
Serial.println(regres, BIN);
Serial.println(regres, HEX);
delay(1);
}
digitalWrite(ncs, HIGH);
}
int convTwosComp(int b) {
//Convert from 2's complement
if (b & 0x80) {
b = -1 * ((b ^ 0xff) + 1);
}
return b;
}
void loop() {
currTime = millis();
if (currTime > timer) {
Serial.println(testctr++);
timer = currTime + 500;
}
if (movementflag) {
Serial.print("x = ");
Serial.print( convTwosComp(xydat[0]) );
Serial.print(" | ");
Serial.print("y = ");
Serial.println( convTwosComp(xydat[1]) );
movementflag = 0;
}
}