Go Down

Topic: Using laptop touchpad in a different way (Read 5394 times) previous topic - next topic

deejayspinz

I have connected a Compact N600 touchpad to my Arduino in PS2 mode.  I'm using the PS2Mouse library (http://www.arduino.cc/playground/ComponentLib/Ps2mouse) and it works - I'm getting values returned when I move my finger on the touchpad.  It is doing its job correctly, however I have a different need.  I imagine all laptop touchpads are like this - no matter where you put your finger and move it, it will return the delta x and y values (based on where I first put my finger - and it does not matter where on the pad this is done).  What I want is relative x and y values based on the axis origin point (0,0).  So - lower left (0,0) upper right (n,n).  What I want to do is create virtual areas on the pad so, for example, if the user slides the finger from bottom to top on the left side of the touchpad, it will ramp LED lights up and vice-versa.  In another area of the pad, I may want to make a colour change slider for the RGB portion of the LEDs.   Is there a way to modify the PS2Mouse library to return relative x,y values?   

I also have a DSLite touchpad on order as I think this will do what I want using the touchpad library, but I was hoping to get it working on a laptop touchpad as the surface and texture is better for my needs.

Thx

bilbo

So If I am understanding you correctly, you want absolute coordinates on the trackpad? The only way I can think of doing this is having the user start in the same place every time, or write code to calibrate the touchpad.

deejayspinz


So If I am understanding you correctly, you want absolute coordinates on the trackpad? The only way I can think of doing this is having the user start in the same place every time, or write code to calibrate the touchpad.


Not sure you can calibrate the pad.  Think of it this way: The way a trackpad works is no matter where you put your finger, its essentially 0,0, as to move in different directions, the touchpad returns the delta x/y from that point (+ or - depending on which way you move).   What is also interesting is that it returns x/y values that can be used to show acceleration.  So, if I move my finger slowly in one direction (eg along x-axis) it would return numbers like 0,3,5,6,7,8,9, but if I do it again moving my finger rapidly it returns 0,7,15,35.  Great for doing other things, but not for what I want.   I want to know if there is a way to tweak the PS2 library to return relative values.  0,0 bottom left, n,n top right and everything in between.  If I can get this, then I can define virtual areas and have the code respond to movement within them.  Again, I am pretty sure I can pull this off with a trackpad from a dlslite, but I want to first try with a laptop unit.

weirdo557

i know synaptics touchpads can do absolute coordinates, though im pretty sure you have to use some special protocol. other than that absolute positioning isnt very viable.

Senso

The "problem" is not in the PS2 lib, the computer mousse is designed to send relative coordinates, because in a normal mouse you can ever have an absolute coordinate, so touchpads work just in the same way, to they can be compatible, the controller of the touchpad might be able to send absolute coordinates, because there are lots of touchpads with soft buttons, for example in toshiba laptops that have a lot of buttons in their touchpads.

mowcius

Quote
i know synaptics touchpads can do absolute coordinates, though im pretty sure you have to use some special protocol. other than that absolute positioning isnt very viable.

Pretty sure there are examples hanging around on the forum for this.

deejayspinz

Ok Folks..  thx for all the tips..  I managed to find what I need at Instructables here: http://www.instructables.com/id/The-5-Karduinoss-pad/?ALLSTEPS (Thx user @buZztiaan).  After following some of the suggestions above, I found that my touchpad was mfg by Synaptics. I also found  (http://ccdw.org/~cjj/l/docs/ACF126.pdf) which detailed the Synaptics protocol showing there was a way to put the touchpad in Absolute mode (think I was saying "Relative" above when I really wanted Absolute mode!).  I've copied a slightly modified version of the code below (without the midi stuff) for future prosperity.  Note it uses the ps2 library available here: http://www.arduino.cc/playground/ComponentLib/Ps2mouse 


Code: [Select]

#include <ps2.h>

//credit to @ buZztiaan @Instructables for this: 
//http://www.instructables.com/id/The-5-Karduinoss-pad/?ALLSTEPS

//will return x,y values in absolute mode (lower left to upper right).  Version below modified to
//print x,y,minx,maxx,miny,maxy


PS2 mouse(6, 5);  //  usage: PS2 mouse(int clk, int data)
unsigned int maxx,minx,maxy,miny,maxz,minz;

void mouse_init()
{
  mouse.write(0xff);  // reset
  mouse.read();  // ack byte
  mouse.read();  // blank */
  mouse.read();  // blank */
  mouse.write(0xf0);  // remote mode
  mouse.read();  // ack
  delayMicroseconds(100);
  mouse.write(0xe8);
  mouse.read();  // ack byte
  mouse.write(0x03); // x1  ( x1 * 64  +  x2 * 16  +  x3 * 4  +  x4   == modebyte )
  mouse.read();  // ack byte
  mouse.write(0xe8);
  mouse.read();  // ack byte
  mouse.write(0x00); // x2
  mouse.read();  // ack byte
  mouse.write(0xe8);
  mouse.read();  // ack byte
  mouse.write(0x01); // x3
  mouse.read();  // ack byte
  mouse.write(0xe8);
  mouse.read();  // ack byte
  mouse.write(0x00); // x4
  mouse.read();  // ack byte
  mouse.write(0xf3); // set samplerate 20 (stores mode)
  mouse.read();  // ack byte
  mouse.write(0x14);
  mouse.read();  // ack byte
  delayMicroseconds(100);
}

void setup()
{
  Serial.begin(115200);
  mouse_init();

  maxx = 0;
  minx = 32000;
  maxy = 0;
  miny = 32000;
  maxz = 0;
  minz = 32000;
}


void loop()
{
  byte mstat1;
  byte mstat2;
  byte mxy;
  byte mx;
  byte my;
  byte mz;

  byte ledval;
  byte midix;
  byte midiy;
  byte midiz;

  unsigned int cx,cy;

  mouse.write(0xeb);
  mouse.read();
 
  mstat1 = mouse.read();
  mxy = mouse.read();
  mz = mouse.read();
  mstat2 = mouse.read();
  mx = mouse.read();
  my = mouse.read();


  // collect the bits for x and y
  cx = (((mstat2 & 0x10) << 8) | ((mxy & 0x0F) << 8) | mx );
  cy = (((mstat2 & 0x20) << 7) | ((mxy & 0xF0) << 4) | my );


  Serial.print("\tX=");
  Serial.print(cx, DEC);
  Serial.print("\tY=");
  Serial.print(cy, DEC);
 

  // change the following digit to adjust the 'sensitivity' to touches 
  if (mz > 2) {

    // autocalibrate

    if (cx < minx) { minx = cx; }
    if (cx > maxx) { maxx = cx; }
    if (cy < miny) { miny = cy; }
    if (cy > maxy) { maxy = cy; }
    if (mz < minz) { minz = mz; }
    if (mz > maxz) { maxz = mz; }

    // determine led value (based on z value)
    ledval = map(mz,minz,maxz,0,255);
    analogWrite(13,ledval);

 
  }
 
  Serial.print("\tminX=");
  Serial.print(minx, DEC);
  Serial.print("\tmaxX=");
  Serial.print(maxx, DEC);
 
  Serial.print("\tminY=");
  Serial.print(miny, DEC);
  Serial.print("\tmaxY=");
  Serial.print(maxy, DEC);
 
  Serial.println();

   
  delay(20);
}


Go Up