Skip to content

Commit

Permalink
Implemented an encoder wheel for e.g. zooming (#31)
Browse files Browse the repository at this point in the history
Implemented an encoder wheel for e.g. zooming based on the idea by https://github.com/JoseLuisGZA/ErgonoMouse.

Use ROTARY_AXIS to choose which axis is replaced by the encoder. 

When ROTARY_AXIS == 0, the encoder library is not needed in ARDUINO IDE.
PlatformIO is loading it via platformio.ini
  • Loading branch information
AndunHH authored Jun 27, 2024
1 parent 7a3bfe0 commit aba1d47
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 13 deletions.
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down
Binary file modified fritzing/spacemouse.fzz
Binary file not shown.
14 changes: 12 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
@@ -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
38 changes: 36 additions & 2 deletions spacemouse-keys/config_sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -152,15 +153,15 @@
// 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
#define KEYLIST \
{ 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

Expand Down Expand Up @@ -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
77 changes: 77 additions & 0 deletions spacemouse-keys/encoderWheel.cpp
Original file line number Diff line number Diff line change
@@ -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 <Arduino.h>
#include "config.h"
#if ROTARY_AXIS > 0
#include "encoderWheel.h"

// Include Encoder library by Paul Stoffregen
#include <Encoder.h>

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
4 changes: 4 additions & 0 deletions spacemouse-keys/encoderWheel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Header file for the encoderWheel.cpp

void initEncoderWheel();
void calcEncoderWheel(int16_t* velocity, int debug);
19 changes: 17 additions & 2 deletions spacemouse-keys/spacemouse-keys.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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];
Expand All @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit aba1d47

Please sign in to comment.