[Solved] PS2 Mouse rotary encoder library

I think I’ve got it now.

Please test and let me know if and how it works for you.

If it’s OK I (or someone else) could wrap the functionality of the PS2Mouse demo .cpp into a PS2Mouse class and maybe also add a PS2Keyboard class.

For easy testing I’ve also published this lib as “PS2Communication” on the Web IDE

You’re my personal hero; this is some cool code.

It compiles and flashes well in the web IDE, and serial monitor on my old/junky OSX snow leopard machine terminal (can’t run SparkDev) shows that it successfully registers it as a 2-button mouse. Very, very cool.

Erm… I’m a bit embarassed but I can’t figure out how to send bytes for it to echo over Terminal. I have my windows 8.1 laptop with SparkDev on it… maybe I’ll try it there.

2 Likes

If you do have serial connection to your Core, you can enter any byte value in hex notation (e.g. 0xEB or EB or 0xeb or eb) and then press enter to send this byte to the PS/2 mouse (after seven chars your string will be auto-commited).
If the mouse isn’t already in Wrap Mode (=echo mode) it will first be set up to echo back by sending 0xEE.
Any byte value (except 0xFF and 0xEC) you enter will be echoed three times. Once while typing, once as the whole string you commited and the third is the actual echo of the mouse.
Like this

0xeb
0xeb
-----
EB
^^^^^

If you send 0xFF the mouse will be reset for normal operation.
If you send 0xEC you set the mouse back into Remote Mode (no echo, remote triggered transfer). This way you can see how the mouse reacts to commands (e.g. 0xEB demands the 3 or 4 mouse report bytes plus a preceeding 0xFA acknowledge byte, or 0xF2 to ask for the mouse type, …)

I hope this helps :wink:


Edit: I’ve found some minor bugs in connection with mouse button 4 & 5 and fixed them in v0.0.2 & v0.0.3

Okay -
I might just be an idiot (likely), but I can’t figure out how to get this to work. I enter 0xEE into the serial monitor and nothing happens… is there any other way to check functionality?

What exactly do you want to use the Wrap Mode for?
To check the main functionality, you don’t need to enter anything into the serial monitor.
The demo sketch should start running after about 10sec (or on serial Enter).
Then you should first see some initialization codes sent to the mouse and the mouse answering back with FA (PS/2 acknowledge) for each of them.
If init succeeded, you should get info what mouse type was found.

And after this you should get regular readings of the mouse in the form _lmr_ xxx yyy zzz where the first portion represents the mouse button states (lower case … not pressed, upper case pressed) and the next readings should give you the mouse movement, zzz being the mouse wheel reading provided you got one.

The 0xEE command was only intended for debugging reasons. For normal use you don’t need it.

But if you don’t see the above results, check your wiring again.
The library by default uses D0 as PS/2 data pin and D1 as clock and you should power your mouse via 5V Vin.

Another way to check is the set of Spark.variable the demo sketch updates regularly, which represent the over all movement for each direction since last call to SparkFunction "MouseReset" and the current button state.

1 Like

@jmohin, have you had time to test again?

Does it work now, or do you still have problems?


BTW: If you want the demo to be more verbose you could change this by removing the leading x in these #defines


#define xDEBUG_PS2
#define DEBUG_DO_MOUSE

Sorry, work this week prevented any fun tinkering.

When I plug in a 3 button scroll PS2 mouse, and turn on debugging, I see this in the serial monitor after about 5-10 seconds:

5button
FA
AA
NULL
FA
-----
FA
-----
FA
-----
FA
-----
FA
-----
FA
-----
3button
FA
-----
FA
-----
FA
-----
FA
-----
FA
-----
FA
-----
3 button scroll mouse
FA
-----
FE
-----
FC
-----
FE
-----
FA
-----

After that, it doesn’t matter what keystrokes I enter into the serial monitor, it never does anything else. The MouseX, Y, and Z are always zero from the cloud, and buttons are always “_lrm_”. Calling MouseReset gives no output in the serial monitor. It appears I’m badly I’m effing up because it seems like your code works beautifully in ID’ing different mice (I’ve tried a few)

That’s odd :confused:
Normally after initialzing the mouse the serial monitor should hammer away printing out lines of

 lmr  (1000)   xxx   yyy   zz
 LMR  (1111)  -xxx  -yyy  -zz

where the capitals stand for pressed buttons and x/y/z for the coordinates/wheel turns.

How have you got the mouse powered?
Have you activated verbose serial output as outlined above?
What does your RGB LED do when the program stalls?
Could you try SYSTEM_MODE(MANUAL); just to avoid any interference from a bad cloud connection?

I’ll upload a new version with some minor fixes and some more test options (e.g. Stream mode) to the Web IDE soon.
Just a warning, the demo code will be a bit messy due to all the test options wrapped in #if ... #endif blocks.
Once you got your hardware running and the setup you want to use, you can just dump any of the unused code :wink:

I’ve just uploaded v0.0.4.
Try the new version, if this works better for you.


@jmohin, the new demo starts up in streaming mode - rather than remote (polling). So now after ps2MouseInit() the serial monitor should stay quiet after it reported the device type.
Only when there is some mouse action, you should see output.
In addition the little blue LED should report any PS/2 interrupt activity, to see if the mouse does talk to the Core.

2 Likes

@jmohin, have you had any chance to test out my new version?

Any more success, or still not?

Sorry, I was away from home for a bit. I’ve just loaded it up into the web IDE and it doesn’t compile for some reason. I’ll download it into sparkDev and work on it more when I get home from work.

That’s very odd :worried:

I’ve just tested it and it does compile on my Web IDE.
What example and what lib version are you using?

You can’t use the application.cpp, since this requires the USB-HID-FEATURE branch of the Spark firmware.
The Web IDE sample is the PS2MOUSE.ino

I finally had some time to actually look at what you did and actually put mental effort into doing this, and I have to apologize for how stupid I was before. It took me barely 3 minutes to get it working… I used the PS2Mouse.ino file in the WEB IDE and copied/pasted the PS2Communication .ccp and .h files manually into the web IDE and un-defined the SPARK_WEB_IDE variable so it would read the manually-entered copy.

It works SO beautifully, and reading through your code, it’s clear you put a lot of thought and effort into correctly handling interrupts and bit reads. It’s also written in an obvious-enough way I can make it work on my project.

You deserve a gold star and/or a spark medal (do they have those?) for this work.

3 Likes

Thanks for the kind words :blush:

One thing I don't quite understand, though.
Why did you have to do this

When using any of the samples provided with the libraries on Web IDE, I just need to select the library, then click the desired sample and then push the "USE THIS EXAMPLE" button. This way you'll get a new project in your repository, with all the required files "linked" in.

I've tried to make this work out the box with this lib too.
So I don't understand why it didn't work for you - very odd :confused:

Hello, was trying your example and core stucks in flashing white after that :confused:
Other ones don’t give that reqsult
I was using PS2MOUSE.ino sample that is not for HID toolchain

@ryotsuke, are you sure it’s flashing white and not breathing white - since this is the expected behaviour.
The demo uses SYSTEM_MODE(SEMI_AUTOMATIC) and turns WiFi.off() as first statement in setup().

If you have a three button mouse attached, you can connect to the cloud by pressing the left, middle and right buttons together.

Otherwise you just need to adapt that part of the demo to suit your needs.

1 Like

Thanks, that stuff in new for me (kinda, I’m still using jule 2014 branch for some reasons)
Connected to serial and see output, awesome.
I’m trying to use PS2 trackball instead of mechanichal encoders directly. Encoders appeared to be harder to track with precision, speed and no debounces.

Results are non-consistent, though
I’ve rebooted and am getting "not a valid mouse type"
Than I’ve poked grn+VIN and got http://screenshots.ryotsuke.ru/scr_74be8489a50f.png
Randomly poking other wires i managed it to restart and show data again, but I’m not sure how to perform a consistent reset

If you want to reset the PS/2 device, you’d just need to call ps2MouseMode = ps2MouseInit(ps2MouseMode); whichever way you want - e.g. via a button press, an interrupt or a Spark.function (when cloud connected).

If you get inconsistent init results, it might be your wiring or the power consumption of your trackball (if powered via Vin off the Core) or several other reasons.
One “safety” feature I also added is, that the PS/2 mouse device gets auto-reset if the first byte of the mouse report hasn’t got the compulsory bit 3 set.

May it be related to the fact it is PS2/USB device using 1 port for both?