diff --git a/README.md b/README.md index cf32e55..2b62b97 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ This repository for the source code is based on the work by [TeachingTech](https - [x] Semi-Automatic calibration methods - [x] Support for keys, that can trigger functions on your pc - [x] Support for "kill-keys", that disable translation or rotation directly in the mouse - -Coming up: -- [ ] Support for wheel to zoom (merging from [JoseLuizGZA](https://github.com/JoseLuisGZA/ErgonoMouse/)) +- [x] Support for an encoder wheel to zoom Wanted, with unclear solution ... ? - [ ] Reverse Direction and Speed options in 3dConnexion Software is not working, because our spacemouse is not accepting this settings. @@ -211,10 +209,11 @@ This code is the combination of multiple works by others: The basis is fdmakara's four joystick movement logic, with jfedor/BennyBWalker's HID SpaceMouse emulation. The four joystick logic sketch was setup for the joystick library instead of HID, so elements of this were omitted where not needed. The outputs were jumbled no matter how Teaching Tech plugged them in, so Teaching Tech spent a lot of time adding debugging code to track exactly what was happening. On top of this, Teching Tech has added more control of speed/direction and comments/links to informative resources to try and explain what is happening in each phase. 8. Code to include meassured min and max values for each Joystick by Daniel_1284580 (In Software Version V1 and newer) 9. Improved code to make it more userfriendly by Daniel_1284580 (In Software Version V2 and newer) -10. Improved Code, improved comments and added written tutorials in comments, by [LivingTheDream](https://www.printables.com/de/model/883967-tt-spacemouse-v2-lid-with-mounting-for-4-mx-switch/): Implemented new algorithm "modifier function" for better motioncontrol by Daniel_1284580 (In Software Version V3) -11. Moved the Deadzone detection into the inital ADC conversion and calculate every value everytime and use the modifier for better seperation between the access, by Andun_HH. -12. Added two additional buttons integrated into the knob to kill either translation or rotation at will and prevent unintended movements, by JoseLuisGZA. -13. Coming up: Added Encoder to use with a wheel on top of the main knob an simulate pulls on any of the axis (main use is simulating zoom like the mouse wheel), by [JoseLuizGZA](https://github.com/JoseLuisGZA/ErgonoMouse/). +10. Improved Code, improved comments and added written tutorials in comments, by [LivingTheDream](https://www.printables.com/de/model/883967-tt-spacemouse-v2-lid-with-mounting-for-4-mx-switch/files) Implemented new algorithm "modifier function" for better motioncontrol by Daniel_1284580 (In Software Version V3) +11. Moved the Deadzone detection into the inital ADC conversion and calculate every value everytime and use the modifier for better seperation between the access, By Andun_HH. +12. Added two additional buttons integrated into the knob to kill either translation or rotation at will and prevent unintended movements, by JoseLuisGZA and AndunHH. +13. Added Encoder to use with a wheel on top of the main knob an simulate pulls on any of the axis (main use is simulating zoom like the mouse wheel), by [JoseLuizGZA](https://github.com/JoseLuisGZA/ErgonoMouse/) and rewritten by AndunHH. + # License Because TeachingTech published his source code on Printables under this license, it also applies here: diff --git a/fritzing/spacemouse.fzz b/fritzing/spacemouse.fzz index e06e4b0..17e35b9 100644 Binary files a/fritzing/spacemouse.fzz and b/fritzing/spacemouse.fzz differ diff --git a/platformio.ini b/platformio.ini index cb0825f..2c03ce1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,12 +1,22 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + [env:micro] platform = atmelavr board = micro framework = arduino extra_scripts = pre:set_hwids.py -# send on enter with a cr lf typo and show this output in the console: -monitor_filters = send_on_enter +monitor_filters = send_on_enter monitor_eol = CRLF monitor_echo = yes +lib_deps = paulstoffregen/Encoder@^1.4.4 [platformio] src_dir = spacemouse-keys diff --git a/spacemouse-keys/config_sample.h b/spacemouse-keys/config_sample.h index 146243d..faac966 100644 --- a/spacemouse-keys/config_sample.h +++ b/spacemouse-keys/config_sample.h @@ -45,6 +45,7 @@ // 6: Report velocity and keys after possible kill-key feature // 7: Report the frequency of the loop() -> how often is the loop() called in one second? // 8: Report the bits and bytes send as button codes +// 9: Report details about the encoder wheel, if ROTARY_AXIS > 0 #define STARTDEBUG 0 // Second calibration: Tune Deadzone @@ -152,7 +153,7 @@ // Keys Support // See below for examples // How many keys are there in total? -#define NUMKEYS 4 +#define NUMKEYS 0 // Define the pins for the keys on the arduino // KEYLIST must be empty "{ }" if NUMKEYS = 0, i.e. no key support // The first pins from KEYLIST may be reported via HID @@ -160,7 +161,7 @@ { 15, 14, 16, 10 } // How many keys reported? -#define NUMHIDKEYS 4 +#define NUMHIDKEYS 0 // In order to define which key is assigned to which button, the following list must be entered in the BUTTONLIST below @@ -238,3 +239,36 @@ #endif #define DEBOUNCE_KEYS_MS 200 // time in ms which is needed to allow a new button press + +// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// ENCODER WHEEL +// Needs the encoder library by Paul Stoffregen. +// There may be an additional encoder wheel to replace one of the velocities +#define ROTARY_AXIS 0 + +// Axis to replace with encoder +// 0. None -> disable this feature completely +// 1. transX +// 2. transY (zoom in "Forward / Backward" Zoom Direction configuration) +// 3. transZ (simulates zoom in "Up / Down" Zoom Direction configuration) +// 4. rotX +// 5. rotY +// 6. rotZ +// (Those are the positions in the velocity array +1, as defined in calibration.h) + +// Define the encoder pins +#define ENCODER_CLK 2 +#define ENCODER_DT 3 +// swap those two pins to change direction of encoder + +// To calculate a velocity from the encoder position, the output is faded over so many loop() iterations, as defined in #ECHOES +// Small number = short duration of zooming <-> Big Number = longer duration of zooming +// Compare this number with the update frequency of the script, reported by debug=7: +// If ECHOES = frequency: the zoom is faded for 1 second. +#define ECHOES 200 + +// Strength of the simulated pull +// Recommended range: 0 - 350 +// Reason for max=350: The HID Interface reports logical max as +350, see hidInterface.h +// Recommended strength = 200 +#define SIMSTRENGTH 200 diff --git a/spacemouse-keys/encoderWheel.cpp b/spacemouse-keys/encoderWheel.cpp new file mode 100644 index 0000000..fd6b6e7 --- /dev/null +++ b/spacemouse-keys/encoderWheel.cpp @@ -0,0 +1,77 @@ +/* + * This code gives the space mouse the ability to include an encoder wheel. + * The encoder gives positions but the space mouse reports velocities. + * Therefore, we calculate a filtered derivative from the encoder position and + * replace the desired velocity from the original space mouse. + * + * Based on the idea by JoseLuisGZA, rewritten by Andun HH + */ + +#include +#include "config.h" +#if ROTARY_AXIS > 0 +#include "encoderWheel.h" + +// Include Encoder library by Paul Stoffregen +#include + +Encoder myEncoder(ENCODER_CLK, ENCODER_DT); + +int32_t previousEncoderValue = 0; +int32_t newEncoderValue; // Store encoder readings +int32_t delta = 0; // Tracks encoder increments when turned + +int zoomIterator = ECHOES; // Counter for echoing the delta through a number of loops for a smoother zoom animation +float simpull; // calculated velocity of the encoder wheel + +void initEncoderWheel() +{ + // Read initial value from encoder + newEncoderValue = myEncoder.read(); +} + +/// @brief Calculate the encoder wheel and update the result in the velocity array +/// @param velocity Array with the velocity, which gets updated at position ROTARY_AXIS-1 +/// @param debug Generate a debug output if debug=9 +void calcEncoderWheel(int16_t *velocity, int debug) +{ + static int factor = 100; // + // read encoder + newEncoderValue = myEncoder.read(); + if (newEncoderValue != previousEncoderValue) + { + // position changed, how much? + delta = newEncoderValue - previousEncoderValue; + previousEncoderValue = newEncoderValue; + zoomIterator = 0; + } + + // Distribute encoder delta through the echoes in the loop and based on simulated axis chosen by the user + // Faded intensity for echoing the encoder reading. + if (zoomIterator < ECHOES) + { + factor = 100 - ((zoomIterator * 100) / ECHOES); // factor shall be percent: between 0 and 100 + simpull = (factor * SIMSTRENGTH) / 100 * delta; + zoomIterator++; // iterate + // add the velocity of the encoder wheel to one of the 6 axis + // the ROTARY_AXIS definition is one above the array definition used for the velocity array (see calibration.h) + // Therefore ROTARY_AXIS-1 is used to change the velocity value + velocity[ROTARY_AXIS - 1] = velocity[ROTARY_AXIS - 1] + simpull; + } + else + { + // fading has ended + simpull = 0; + } + if (debug == 9) + { + // create debug output + Serial.print("Enc Val: "); + Serial.print(newEncoderValue); + Serial.print(", factor: "); + Serial.print(factor); + Serial.print(", simpull: "); + Serial.println(simpull); + } +} +#endif // whole file is only implemented #if ROTARY_AXIS > 0 \ No newline at end of file diff --git a/spacemouse-keys/encoderWheel.h b/spacemouse-keys/encoderWheel.h new file mode 100644 index 0000000..66ad0e1 --- /dev/null +++ b/spacemouse-keys/encoderWheel.h @@ -0,0 +1,4 @@ +// Header file for the encoderWheel.cpp + +void initEncoderWheel(); +void calcEncoderWheel(int16_t* velocity, int debug); \ No newline at end of file diff --git a/spacemouse-keys/spacemouse-keys.ino b/spacemouse-keys/spacemouse-keys.ino index ac291d1..af1bda4 100644 --- a/spacemouse-keys/spacemouse-keys.ino +++ b/spacemouse-keys/spacemouse-keys.ino @@ -24,6 +24,11 @@ // header for HID emulation of the spacemouse #include "hidInterface.h" +#if ROTARY_AXIS > 0 + // if an encoder wheel is used + #include "encoderWheel.h" +#endif + // the debug mode can be set during runtime via the serial interface int debug = STARTDEBUG; @@ -92,6 +97,10 @@ void setup() { // Read idle/centre positions for joysticks. readAllFromJoystick(centerPoints); delay(100); + +#if ROTARY_AXIS > 0 + initEncoderWheel(); +#endif } int rawReads[8], centered[8]; @@ -105,6 +114,7 @@ int maxVals[8] = MAXVALS; int tmpInput; // store the value, the user might input over the serial + void loop() { //check if the user entered a debug mode via serial interface if (Serial.available()) { @@ -202,6 +212,11 @@ void loop() { velocity[ROTZ] = 0; } +#if ROTARY_AXIS > 0 + // If an encoder wheel is used, calculate the velocity of the wheel and replace one of the former calculated velocities + calcEncoderWheel(velocity, debug); +#endif + // Invert directions if needed #if INVX > 0 velocity[TRANSX] = velocity[TRANSX] * -1; @@ -236,7 +251,8 @@ void loop() { // if the kill-key feature is enabled, rotations or translations are killed=set to zero #if (NUMKILLKEYS == 2) - if (keyVals[KILLROT] == LOW) { // check for the raw keyVal and not keyOut, because keyOut is only 1 for a single iteration. keyVals has inverse Logic due to pull-ups + if (keyVals[KILLROT] == LOW) { + // check for the raw keyVal and not keyOut, because keyOut is only 1 for a single iteration. keyVals has inverse Logic due to pull-ups // kill rotation velocity[ROTX] = 0; velocity[ROTY] = 0; @@ -264,7 +280,6 @@ void loop() { // Daniel_1284580 noticed the 3dconnexion tutorial was not working the right way so they got changed send_command(velocity[ROTX], velocity[ROTY], velocity[ROTZ], velocity[TRANSX], velocity[TRANSY], velocity[TRANSZ], keyOut, debug); #endif - if (debug == 7) { // update and report the at what frequency the loop is running