Repository for a 3D mouse, which emulates a 3Dconnexion “Space Mouse Pro wireless”.
This repository is NOT affiliated with 3Dconnexion. We just reverse-engineered the USB protocol.
Check-out the Release Page for the newest releases and updates!
For the next release already to be found in master:
This release holds 6 months of development by @StefanNouza. Here is an overview of his great addition to this project:
The serial interface is showing a menu to list the possible options you may ask.
SpaceMouse FW2.x.y - Debug Modes
ESC stop running mode, leave menu (ESC, Q)
1 raw joystick ADC values 0..1023
2 centered values -500..+500
11 auto calibrate centers, show deadzones
20 find min/max-values over 15s (move stick)
3 centered values w.deadzones -350..+350
4 velocity- (trans-/rot-)values -350..+350
5 centered- & velocity-values, (3) and (4)
6 velocity after kill-keys and keys
61 velocity after axis-switch, exclusive
7 loop-frequency-test
8 key-test, button-codes to send
9 encoder wheel-test
30 parameters (read, write, edit, view)
The parameters from the config.h file are initially read and stored in the eeprom of the controller. Despite the hardware related constant definitions, you can edit all the sensitivities on the fly over the menu item 30:
SpaceMouse FW2.x.y - Parameters
ESC leave parameter-menu (ESC, Q)
1 list parameters
2 edit parameters
3 read from EEPROM
4 write to EEPROM
5 clear EEPROM to 0xFF
6 set EEPROM params invalid
7 list parameters as defines
CAUTION: the EEPROM-chip on the Arduino is capable of 10.000 writes per storage-byte. By manually editing and storing the modified parameters we won’t get in trouble - but frequent automated saving of parameters won’t be a good idea, the EEPROM may get damaged.
The parameters will be stored to the same location all the time - a load-leveling-algorithm would be too much code for too less benefit. The Arduino-function EEPROM.put() itself only writes bytes, that really have changed - so only changed values wear out EEPROM-bytes, unchanged parts don’t.
If prio-z-exclusive-mode is on, rotations are only calculated, if no z-move is detected.
This feature is recommended for resistive joysticks.
When pushing or pulling, the knob produced transient rotational components that stops when the z-translation gets the priority. So when pulling, we get first a rotation then the desired translation.
So this mode sees that min. 3 of 4 joysticks all move up (or down) and use it as an indicator that the knob is mainly pushed/pulled. So before any (ghost-)rotational component can be calculated, it is sorted out.
@StefanNouza implemented a drift-compensation to re-zero the (hall-)joysticks when the mouse is untouched. This is necessary because hall-joystick-readings don’t show any deadzone, like resistive joysticks do.
He wanted use the small readings possible around zero to get a precise reaction to slight touches. This can be done by setting the DEADZONE to 0 and tune the modifierFunction to output values even at small joystick-readings. But then, it can be seen that the mechanics produce a new random zeropoint everytime the SpaceMouse is left untouched.
So this drift-compensation was invented to overcome the slightly unprecise mechanics. The compensation finds out when the SpaceMouse is untouched. Then it sets the readings of the joysticks to 0.
This is implemented in the compensateDrifts() function in calibration.cpp. You can fine tune the drift compensation with those parameters. Check the config_sample.h for more infos. | Parameter | Short description | | — | — | | COMP_ENABLED | enable the compensation | | COMP_NO_OF_POINTS | number of points to build the mean-value | | COMP_WAIT_TIME | [ms] time to wait and monitor before compensating (smaller value=>faster re-centering, but may cut off small moves) | | COMP_MIN_MAX_DIFF | [incr] maximum range of raw-values to be considered as only drift | | COMP_CENTER_DIFF | [incr] maximum distance from the center-value to be only drift (never compensates above this offset) |
This repository contains the software for a 3D mouse with six degrees of freedom (6 DOF), which emulates a 3Dconnexion “Space Mouse Pro wireless”.
This repository is NOT affiliated with 3Dconnexion. We just reverse-engineered the USB protocol.
The software in this repo supports two different hardware variants:
The joysticks version gained popularity through this TeachingTech YouTube Video. To see many features in place, like the buttons and the encoder with joysticks, check out the different versions by Jose L. González, like the ErgonoMouse MK XX - 6DOF Controller Knob & Joystick with Wheel, Buttons & Keys
The Hall-Effect-Sensor + Magnet version is greatly described here by John Crombies space mouse with linear hall effect sensors and improved with TPU springs.
Other implementations, hardware or mechanic variants are linked below.
Purchasing the electronics and printing some parts is not scope of this repository. We start with the software. Feel free to read some build reports:
The original 3Dconnexion windows driver is very elegant to detect which program you are running and offering custom actions for the keys on a space mouse. You can utilize this behavior and build a space mouse with keys, just without the central part, the space mouse itself. You are left with keys, that you can assign to actions for your CAD program. This comes handy, if your original spacemouse doesn’t have enough keys. In this case your PC will see an additional mouse where only the keystrokes are send and evaluated.
You can use PlatformIO to flash the board with this fast steps. PlatformIO is easier than ArduinoIDE, because you don’t need to change the board.txt files there.
spacemouse-keys/config_sample.h
to spacemouse-keys/config.h
and change the values to whatever suits.pio run -t upload
.The boards.txt file needs an additional board definition, which tells the microprocessor to report the USB identifiers correctly and emulate the 3dconnexion space-mouse. Please follow the detailed instructions on the wiki page about custom board definition.
Clone the github repo to your computer: Scroll-Up to the green “<> Code” Button and select, if you wish to clone or just download the code.
Copy the config_sample.h and rename it to config.h. This is done to avoid the personal config file being overwritten when pulling new updates from this repository. You probably have to update the config.h file with new additions from the config_sample.h, but your pin assignment will not stay.
Troubleshooting for uploading is explained in detail here:
Uploading firmware to the Pro Micro
After compiling and uploading the program to your hardware, you can connect via the serial monitor. Hit enter and use the serial menu to select the proper debug outputs.
Read and follow the instructions throughout the config.h file and write down your results. The initial parameters are hardware dependent and you need to recompile for the changes to take effect. The later parameters for sensitivities can be tuned via the menu and saved to the EEPROM (and exported back to config.h)
This calibration is supported by various debug outputs. All debug outputs are described at the top of your config_sample.h.
Choose a modifier function to change the linear relationship between raw and processed data.
Note, that the Squared Tan function act like a dead zone filter, because small inputs are resulting in a small output, which may reduce unwanted movements.
The modifier function can also be parametrized with the parameters a (= slope_at_zero) and b (= slope_at_end).
The squared function (modFunc = 1): \(y = x^a \cdot sign(x)\)
For example, the squared tangens function (modFunc = 3): \(y = \frac {tan(b \cdot (|x|^a \cdot sign(x)))}{tan(b)}\)
You can interactively change the parameters a and b on this html page to show the impact of the parameters on the modifier functions.
If you read this page in github and the links brings to the raw html code, open the html file locally on your machine or here on github pages.
Download and install the 3DConnexion software
If all goes well, the 3DConnexion software will show a SpaceMouse Pro wireless when the Arduino is connected.
Checkout https://wiki.freecad.org/3Dconnexion_input_devices and https://github.com/FreeSpacenav/spacenavd.
Onshape is not jet supported by spacenav directly but there is a simple wrapper here: https://github.com/mamatt/space2onshape
Here are some links for the joystick and the newer, more precise hall-effect + magnet variants (more sophisticated build and requires printing of TPU)
The following paragraph relates to the joystick hardware variant. A thorough description of the principle behind the hall-effect sensors can be found down here Hall Effect Sensors and on ChromeBee GitHub: Hall-Effect-Sensor.
The spacemouse is connected to an arduino Pro Micro 16 Mhz. Check out the wiring diagram by TeachingTech or with this added keys and the added neopixel ring.
The calculations in the program expect AX to be the vertical joystick in front of you and AY the horizontal in front of you. B, C and D are clockwise around the spacemouse. Maybe your joystick axis are named X and Y in an other orientation. That doesn’t matter. Connect them and use the config.h file to put the pin the vertical joystick in front of you (=AX) to the first position. In teaching techs example, this is A1, even though his joystick is labeled “y”. See also the wiki for some additional pictures.
The calculation in this program results in X, Y and Z calculated as shown in the middle of the picture. If this doesn’t suit your program change it by using the INVX or SWITCHYZ afterwards.
With the axis defined as shown in the picture above, the calculations for translation and rotation are as follows:
TRANSX = -CY + AY
TRANSY = -BY + DY
TRANSZ = -AX - BX - CX - DX
ROTX = -CX + AX
ROTY = -BX + DX
ROTZ = AY + BY + CY + DY
This section gives a deeper look into features that came into the mouse during time with the releases.
December 2024 Update: Support for LED rings like a neopixel!
The adafruit neopixel led ring with an inner diameter of 52.3 mm fits well.
Filming the LEDs “in action” is very hard, maybe you can get an idea:
When the exclusive mode is activated in the config.h only the major movement is transmitted. That means, that the mouse detects, if you want to translate or rotate.
When the biggest input is a translation: All rotations are set to zero.
When the biggest input is a rotation: All translations are set to zero.
This function is the sister of the kill-key feature, where you press a key to decide wether only translations or rotations are transmitted.
Thanks to @mamatt in #73 for this suggestion which were released in Version 0.9.
Check also the prio-z-exclusive mode.
When you are using the mouse with an encoder wheel, there is a new feature: Rotary Keys.
When you enable this feature in the config, see ROTARY_KEYS, the encoder is not treated as an axis or movement but repeatedly triggers a button. This can be done to e.g. hit the volume+ button while turning the wheel clockwise.
Note: We are still using the emulated USB HID protocoll for the CAD mouse. Therefore, you need to define the pressed button in the config.h and than configure some actions on your PC driver. We are not emulating a standard keyboard.
See #68 for more details.
@JarnoBoks merged the source code by @ChromeBee space mouse with linear hall effect sensors resp. the github repo with this repository to integrate the hall effect sensor space mouse approach. The code is especially using the PCB by Michael Roth or the PCB by Andun. See Version 1.1: Support of Hall Effect Sensors.
In this mouse the joysticks are replaced by springs, magnets and linear hall effect sensors to avoid the mechanical limits of the joystick approach.
To read the eight linear hall effect sensors instead of the joysticks, use the HALLEFFECT
definition in the config.h. @JarnoBoks provided a complete example: config_sample_hall_effect.h and proceed with the calibration as described in the config file.
Here are some other projects with regard to space mice. The arrow indicates what is emulated.
Because TeachingTech published his source code on Printables under this license, it also applies here:
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
This code is the combination of multiple works by others. This list summarizes what happened before this github repository was started:
Please check the release history for more recent history…