Using a PS2 serial touchpad with the ESP32

Hi, I successfully connected a laptop PS2 touchpad to the Arduino Uno, and everything works perfectly. However, I need to continue with my project on the ESP32.

To my surprise, I'm finding the Mouse and PS2 serial libraries available on the web don't work with the ESP32, and all of them cause it to end up blocked when the initialize function is called. During my search, I've found one PS2 library is the fork of another library... and another, and so on, I've tried all the ones I could find with no luck.

IF... (you reader) wonder where is the sample code on my thread, there is no need. I have tried every sample code coming with the libraries, and it just doesn't work with the ESP32.

Found a thread about a project where after some mods, "it worked", but I can't get any of that to work, already contacted the author who replied kindly, but pointed me to a diff project instead with the same issues. I'm aware that besides the evident lack of support of these libraries to diff processors, not every code and library works out of the box (not always), and sometimes there are incompatibilities with specific IDE versions.

I've done my homework and tried hard to find light on this before asking, but no luck so far. I'm also a coder on diff languages, and I understand the importance of specifics on certain situations, I'm not finding those specifics to get this working.

It's been a while (years) since I posted on the Arduino forum, for some reason I noticed lots of users with tons of posts not helping anyone, but instead just making noise like "you should know already", and people complaining for that and leaving, mental health is an important aspect on public places, I hope not to regret posting this time.

I would love to continue this project using the ESP32 and avoid moving to other platforms, as there have been so many changes... sometimes you migrate to a diff platform only to find new incompatibilities.

Any help will be appreciated.

Many years ago I coded an AVR to read PS2 mouse in assembler... You might have to get down in the weeds and bit bang the signal with interrupts and timers if there is no precompiled library available...

Or keep Googling and hope you stumble on something... I found this: FabGL: PS/2 ports schema

Can you confirm that the PS2 you are referring to is the IBM PC standard from years ago that sends data and clock from the keyboard? Or is your PS2 something else?

Thank you. I've been tempted to dive into the writing libraries realm, same as tempted on trying to write a way via interrupts, in my head, it sounds doable. But, while I'm not looking for an easy way out... given past experiences I'm trying to stick to more simpler things. I mean, other times I've gone far from the original path trying to achieve things (building extra pieces of software, code, drivers), in the mind of a problem solver this is fun (a rabbit hole) but takes too much time, and it's also an easy way to get lost on things I'm not fully experienced in.

The link you provide sounds interesting, I will need time to test it, then I will confirm (but then again, it's not going to be right away for me).

At present time, the touchpad works perfectly on two different arduinos, it's the ESP32 that is refusing to align.

I'm not sure how to answer your question, as I have no specifics.

The touchpad comes from an old Acer laptop, it uses 8 wires, but I tested it via the old method of finding the positive, negative, and then, trying every combination of wires, and it behaves as a serial touchpad (PS2).

Connected to an Arduino Uno, I've used this touchpad perfectly with diff Arduino libraries used for serial touchpads (PS2), so I guess it's an indirect answer to your question? Yes, I tried searching the web for the specific model, but couldn't find any information besides saying "Acer XXX touchpad", nothing beyond that regarding the model, datasheet or pinout.

I have multiple Arduino One boards, but these are bulky for my purposes and lack Bluetooth. I could add a Bluetooth module, but the Unos are not compatible with the other libraries I want to use. The ESP is compatible with everything I want to use... except the PS2 library.

I could go out and buy a Tensy, or another type of Arduino with Bluetooth built in, these things won't cost me an eye. But... given past experiences (I'm not complaining), I don't want to fall on another case of Arduino X everything works except A... ok, let's use an Arduino Z, but there everything works except B... ok, now lets move and code for an Arduino Y... everything works except C... ok now let's move to ESP32... now D doesn't work, let's move to a Tensy, now to a Pico, etc. I've been there... Research should help, but there are far too many abandoned threads to know the specifics. I hope this makes sense.

I have a memory of such a keypad, way back then. Seems like your unit is missing or never had the PS2 connector on the cable.
I guess you never asked Google for "arduino ps2 ESP32". There is a version of PS2 library just for the ESP32. Different name, of course.

I don't fully understand what you mean here. AS described, the unit is from an old laptop running Windows, there was never a PS2 connector, just 8 cables. I couldn't find any specific or datasheet, yet, it worked perfectly with an Arduino after some exploration. Funny thing is, it works both on 5V and 3.3V

This is important: it worked providing positive and negative numbers depending on the finger movement on the touchpad. I tried different libraries, only some worked (on the Arduino).

I did. I tried extensively on both Google and Bing for PS2, serial, ps2 serial, etc both with arduino and esp32 in diff combinations, and tried every single library I could find. Even had to filter the differences between PS2 as PS2 serial, and all the threads about Play Station 2 and the ESP32.

Still, if you could kindly provide the link of what you mean, I will verify if I came across that library, or if I never found it due to differences in Google distribution of results (results are different to different geographic regions).

I'll post an update below.

Ok, I have an update. The touchpad is now working with the ESP32. But not fully. How so?

It's connected to 3.3V on the ESP32, I used it this way with the Arduino Uno (and it worked, yes, 3.3V), but couldn't get it to work with any of the libraries I already downloaded. Yet, today something changed.

There is a line of code on one library (#include <ps2.h>) mentioning "Twiddle", it's a delay. I'm using delay(30) right now, and triple verified the pinout (the ESP32 is still a bit confusing to me, I'm familiar with the Arduino pins order and specs), and... I am also using a twisted pair for the data and clock signals.

On another thread about the same thing, another user mentioned issues with the serial print line and and another line of code above, I had the same issues with pure gibberish coming out on the serial monitor, this is not the case anymore.

So, now it works. Sort of.

While I can get readings, I don't get negative numbers. This means left finger movements come as 1 to 24 or slightly above that for the readings, but if I perform the same movement to the right, I get 240 and up... as the readings. I got this working just today and still pending testing ahead, but it's something. I will play with the code to see if I can get a diff reading (or negative numbers).

Here is the code (for anyone who may find this useful:

#include <ps2.h>

/*
 * an arduino sketch to interface with a ps/2 mouse.
 * Also uses serial protocol to talk back to the host
 * and report what it finds.
 */

/*
 * Pin 5 is the mouse data pin, pin 6 is the clock pin
 * Feel free to use whatever pins are convenient.
 */
PS2 mouse(18, 5);
/*
 * initialize the mouse. Reset it, and place it into remote
 * mode, so we can get the encoder data on demand.
 */
void mouse_init()
{
  mouse.write(0xff);  // reset
  mouse.read();  // ack byteUU
  mouse.read();  // blank */
  mouse.read();  // blank */
  mouse.write(0xf0);  // remote mode
  mouse.read();  // ack
  delayMicroseconds(100);
}

void setup()
{

  Serial.begin(9600);
  mouse_init();
  
}

/*
 * get a reading from the mouse and report it back to the
 * host via the serial line.
 */
void loop()
{
  char mstat;
  char mx;
  char my;

  /* get a reading from the mouse */
  mouse.write(0xeb);  // give me data!
  mouse.read();      // ignore ack
  mstat = mouse.read();
  mx = mouse.read();
  my = mouse.read();
    /* send the data back up */
  Serial.print(mstat, BIN);
  Serial.print("\tX=");
  Serial.print(mx, DEC);
  Serial.print("\tY=");
  Serial.print(my, DEC);
  Serial.println();
  delay(30);  /* twiddle */

}

It would be far more useful if you posted the source code for the library or provided a GitHub link to it.

My recollection is that you can command the touchpad to return either absolute or relative position.

I found a few links to the project I built many years ago, but sadly the links to the code are long gone and I have no idea where they are now. But re-reading this it did make me remember that Synaptic (maker of most laptop touchpads) had a communication protocol document that was the foundation of the code I developed... If you do some Googling you may be able to locate that information.

Anywho - this is what I made many years ago lol (in a time before Arduinos):
Touchpad And VFD Hacking | Hackaday
Electronics - Hacked a Touchpad + VFD with AVR | bit-tech.net Forums

EDIT - Found the Synaptic Protocol document:
Synaptics TouchPad Interfacing Guide

I must apologize for my ignorance. I thought PS2 only referred to the first PC with that designation, and all clones that also used the PS2 keyboard and mouse.
After spending time last night on Wikipedia, I now understand that PS2 is an umbrella term for many different PC products and configurations.
I see that includes laptop devices with a pad that replaces the original mouse. And that is what you have as removed from a keyboard assembly. My HP laptops are all similar.

So, disregard anything i have written relating to the PS2 keyboard. None of that can relate to the touchpad/mousepad device.

And good luck, you are getting close. One thing, though. My newest HP laptop user manual mentions the touchpad/mounsepad may also include the two-finger capability to cause an image to be expanded. My laptop does not have that.

Yes. After reading all the documentation of diff libraries (that I could found) this is possible (not with every single one, but yes), the problem is, with the ESP32... it barely works, it does, but not as expected. I'm working on hacking and coding what doesn't work to make it work.

Thanks for the protocol documentation, I've been reading it but made a pause, will work on the code to see how much I can get working from it.

The library I'm using states on the documentation that there is a mod needed to make it work with the ESP32, because it doesn't work out of the box. I found this to be true, but despite the mode being stated as already made on the library -it's not-, and I had to modify the code myself. Probably the mod was removed on recent code updates.

But nope, the library doesn't work as it does with the Arduino Uno (there it works perfectly)

It's cool.

Yest, at least for the touchpad it seems I'm getting close. The movement numbers are wrong... but I'll try to do something with it.

BTW, regarding what you describe, many touchpads are compatible with two finger (and even gesture) functions, but they do depend fully on the drivers AND the proper Synaptics software, I've been there and some laptops are trickier than others with the software version. As far as I know, there is no full multi finger support for the PS2 libraries.

Please post a GitHub link to that library.

I manually applied the mod for non avr micros. The code works, the finger movements are off (coordinates), but I think I can manage with code. The thing is, if someone would like to comment or discuss, should first try this same library with the same ESP32, because I've tested it and it works VERY DIFFERENTLY compared to the Arduino (so, I have tried this with 3 diff boards so far).

Today I found a problem (another), the click is reported via mstat (whatever, it's a data read on a variable), but the thing is... there is a code for left click, and another code for right click, but if you try finger-touch simulating a click (just like on synaptics), sometimes it's detected as a click... and... sometimes it's not detected.

I could... live with that, but, many times the click gets stuck, meaning, the same code is reported (by click I mean the code, because there is no physical activation of the click button, any of both), yet, somehow the same code is reported until you click again. It's like a finger click-drag, but inconsistent.

At the moment, I can confirm this behaves a bit weird here on the ESP32 compared to the Arduino. And I don't have another touchpad to test and discard (additional) compatibility issues.

Unfortunately, you didn't provide a link or reference for that "mod". And I didn't see anything about it in the library link you gave. So, I can't look at it and comment on its purpose or efficacy.

However I do see that the library code does use some tricks to implement Open-Drain outputs that are likely AVR-specific. Now I know nothing about the PS2 electrical spec or protocol, but given the library's code, it seems likely to require an Open-Drain connection. ESP32 chips enable Open-Drain outputs in a different way. It's one of the selectable options when you configure the GPIO. See gpio_types.h:

typedef enum {
    GPIO_MODE_DISABLE = GPIO_MODE_DEF_DISABLE,                                                         /*!< GPIO mode : disable input and output             */
    GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT,                                                             /*!< GPIO mode : input only                           */
    GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT,                                                           /*!< GPIO mode : output only mode                     */
    GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)),                               /*!< GPIO mode : output only with open-drain mode     */
    GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
    GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT)),                         /*!< GPIO mode : output and input mode                */
} gpio_mode_t;

Given that and the problems you still seem to be having even after making the "mod", I'd probably dump the library altogether. Its code is so simple, I'd just use it as a guide to write an ESP32-specific version from scratch. You might even be able to use the ESP32's RMT Peripheral to accomplish in hardware what the library does with software bit banging and delays.

Apologies, the correct link is this one: GitHub · Where software is built there you can see the modification for non avr

Why the confusion? it's simple: I did try every single library I could find, including forks. This has created a large amount of files, I didn't have the links at hand in order when asked. I'm not lazy, but usually... the coding threads (on micros and software) go towards what works, I'm not oversimplifying, I'm searching examples of things that work, not forensics, as these often prove being too time consuming leading nowhere (I've been there multiple times), repeating: finding a solution often involves having an example of what works (IF it works at all), the rabbit holes fixing what doesn't work with no clear example of something that works... are usually a waste of time.

I appreciate the good intentions, but after several years, one knows the wording leads to no solutions, just assumptions of what could work, I can't find a diff way to put that into words, I guess you can understand what I mean. At least, on every solution I have been involved, I always explain the possibilities and what works... never something like "I don't know..." and "this SHOULD work", or something like that.

I'm dropping the project, will leave a separate post for that, as I'm not interested (not entirely) on writing a library or driver from scratch.

For anyone interested on reusing a laptop touchpad with an Arduino, ESP32, or something similar, go after a purely USB touchpad instead of PS2.

The USB touchpads can regularly be found on old MacBooks, I don't know all the specifics, but at least the core 2 duo series come with USB touchpads. The keyboards are also USB. From there, it's quite easy to interface with a microcontroller, be it using official USB support, or analyzing the inputs after connecting power and data cables (yes, even without USB support), if you search the web you will find tutorials and videos of this fully working. It's way better and practical than interfacing a PS2 serial touchpad.

Yes, I can confirm this from experience. I just didn't keep any of those, all I had now was the serial touchpad. So yes, go after the USB touchpads instead!.

"Yes but... why don't you..."
No. If you search carefully every single term regarding PS2 serial touchpad and Arduino/ESP32, you will notice these are all toy projects and prototypes, most of them incomplete and no absolute final functionality. In fact, most information of these unfinished projects explain having issues with the clicks, coordinates, or something else, the results are BUGGY, and most libraries are forks of another library. You can take my word and save yourself some time, or do your own research. Also, consider the dates of the libraries, they go around 4 to 7 years old without updates, with the authors explaining they stopped working on the code long ago.

And yes, I contacted some authors, some kindly replied, but no final projects, just prototypes and pending work.

I found different bugs, many I see great chances on solving them via code corrections myself, but... I won't, my goal is clear, and doesn't involve this. Besides, the libraries work quite differently with the ESP32 regardless of non avr modifications, so, no thanks. BTW, good luck searching for this information on the official ESP32 forums, there is just a couple of abandoned threads with absolutely no interactions.

I went back to the Arduino, and after further testing I could confirm it works better there, but still buggy. For reasons unknown to me, at least with this touchpad in specific, the touch-click can get stuck, sending a constant signal of "click" when there is absolutely no interaction. I don't know if this is purely related to my current touchpad, or others, but instead of solving the question I will move to more practical ways to continue my project.

My approach is very different: is there any example of this thing working? no? then no thanks. I'm not lazy, I could perhaps build a driver or library from scratch, but that's not my goal, this is often a common problem in electronics... wanting to do something, and then finding yourself far from your goal, busy writing and building machines to build other machines.

I truly believe this is the solution: move to a different and better alternative, the USB touchpad, as there are already working examples, things that FULLY WORK, instead of "I can see the coordinates, they are off, but it's just another thing added to the pending list"