mrjohnk / PMW3360DM-T2QU

https://www.tindie.com/products/jkicklighter/pmw3360dm-t2qu-motion-sensor/
75 stars 21 forks source link

Really fast movement throws off the sensor #24

Closed r4dr3fr4d closed 5 years ago

r4dr3fr4d commented 5 years ago

Using for a trackball. Spinning it really fast (as you might to get the pointer to a certain side or corner) throws off the sensor - giving a large value in the wrong direction, which can be seen as the pointer "bounces" backwards/in the opposite direction. I imagine this is due to the sensor not collecting it's next image in time for any data of the previous remaining in the frame view for comparison. Agree/disagree? What would be the correct way to address this?

mrjohnk commented 5 years ago

The example code I provided only reads the lower motion registers. For high speed movement, incorporating readings from the upper motion registers would also be required, if you have not already done so.

On Tue, Mar 12, 2019, 9:29 PM raycewest notifications@github.com wrote:

Using for a trackball. Spinning it really fast (as you might to get the pointer to a certain side or corner) throws off the sensor - giving a large value in the wrong direction, which can be seen as the pointer "bounces" backwards/in the opposite direction. I imagine this is due to the sensor not collecting it's next image in time for any data of the previous remaining in the frame view for comparison. Agree/disagree? What would be the correct way to address this?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mrjohnk/PMW3360DM-T2QU/issues/24, or mute the thread https://github.com/notifications/unsubscribe-auth/ABG0-QjUX8yfPymaNFouq6Pk19KyMibXks5vWGJ3gaJpZM4bsQuz .

r4dr3fr4d commented 5 years ago

So, it never occurred to me that Mouse.move() only takes char's, not shorts. Not sure why that is; I would think it would offer more precision. Huge step in the correct direction - my remaining problem is with how I clamp the values. Here's my pertinent modification to your code:

volatile int8_t xydat[2];
volatile int8_t xyldat[2];
volatile int16_t xyhdat[2];

void UpdatePointer(void){
  if(initComplete==9){

    //write 0x01 to Motion register and read from it to freeze the motion values and make them available
    adns_write_reg(Motion, 0x01);
    adns_read_reg(Motion);

    xyldat[0] = adns_read_reg(Delta_X_L);
    xyhdat[0] = (adns_read_reg(Delta_X_H)<<8)|xyldat[0];
    xyldat[1] = adns_read_reg(Delta_Y_L);
    xyhdat[1] = (adns_read_reg(Delta_Y_H)<<8)|xyldat[1];

    movementflag=1;
    }
  }

if(currTime > pollTimer){
    UpdatePointer();
    int i;
    for ( i = 0; i < 2; i++){
      if (xyhdat[i] > 127){
        xydat[i] = 127;}
      else if (xyhdat[i] < -128){
        xydat[i] = -128;}
      else{ xydat[i] = xyldat[i];}
    }

And then Mouse.move() at the bottom. This seems to work perfectly for the negative side - so if I spin the ball really quick to the left, the pointer stays to the left side. But it keeps bouncing back to the left if I do the same but towards the right side (positive values > 127). I'm not sure how my clamping is messed up for only the positive values. I appreciate any ideas.

r4dr3fr4d commented 5 years ago

The xydat[i] = 127; never gets reached - I can change it to zero or one there and it doesn't change the behavior.

r4dr3fr4d commented 5 years ago

Well, serial statements in that block print out. But the xydat value I set doesn't seem to matter.

r4dr3fr4d commented 5 years ago

volatile int8_t xyldat[2]; needs to be volatile int16_t xyldat[2];

Need to brush up on my conversions.

T4psi commented 2 years ago

Hi! I am very new to how data is stored on registries and how to handle them. I need the full movement data stored on the two registries and although I understand the bitwise operations you performed to basically merge the data found on the two registries, there is something that puzzles me. The lower motion register can be used independently to store SIGNED motion data. How the MSB (coding the sign) of the lower motion register will be handled when the upper motion register is also used and data of the two registries should be merged. Unless the chip has a smart way to alter that sign bit if the upper motion register is read first, I would assume that there will be a random sign bit in the middle of the merged data, giving false result.

mrjohnk commented 2 years ago

In my applications, I've only ever needed to read from the lower registers as my motion sensing for a trackball usually only delivered a one or two through the lower register. For high speed applications where you expect large values to be generated, it does make sense to try and tackle reading both the upper and lower registers and combining the output. Unfortunately, I've never tried to do that. The signing of the data, which indicates which direction the motion was sensed, is handled through a conversion from twos complement that the chip outputs, which is in my code examples.

On Fri, Jun 3, 2022 at 11:35 AM Tapsi @.***> wrote:

Hi! I am very new to how data is stored on registries and how to handle them. I need the full movement data stored on the two registries and although I understand the bitwise operations you performed to basically merge the data found on the two registries, there is something that puzzles me. The lower motion register can be used independently to store SIGNED motion data. How the MSB (coding the sign) of the lower motion register will be handled when the upper motion register is also used and data of the two registries should be merged. Unless the chip has a smart way to alter that sign bit if the upper motion register is read first, I would assume that there will be a random sign bit in the middle of the merged data, giving false result.

— Reply to this email directly, view it on GitHub https://github.com/mrjohnk/PMW3360DM-T2QU/issues/24#issuecomment-1146160373, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAI3J6OTY5DBOXDWBFLO6ADVNIX5PANCNFSM4G5RBOZQ . You are receiving this because you commented.Message ID: @.***>

T4psi commented 2 years ago

After checking some examples around the the boundaries of a signed 8 bit number in 16 bits precision, I understood that it has a mathematical reason why you can take the lower 8 bits of a signed 16 bit number and comprehend it as a signed 8 bit number. The last 8 bits of numbers in [-128; 127] range is the same in either 16 bit signed or 8 bit signed representation. After that, every number that is lower than -128 or bigger than +127 can be calculated as the result of a higher/lower place value number and a number from the [-128; 127] range. That is, the last 8 bits will always range between -128 and +127. It's so obvious now. I learned something new today.