Skip to content

Add function for Modulino Knob to detect direction #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
charlesbones opened this issue Jul 23, 2024 · 2 comments
Open

Add function for Modulino Knob to detect direction #9

charlesbones opened this issue Jul 23, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@charlesbones
Copy link
Collaborator

Add a function that detect the direction of the Modulino Knob, something like if goes right returns 1, if goes left returns -1 and if no change returns 0

@per1234 per1234 added the enhancement New feature or request label Aug 3, 2024
@sebromero
Copy link

The MicroPython library supports this, if we need something to take inspiration from.

@AntonioBerna
Copy link

AntonioBerna commented Apr 26, 2025

Add a function that detect the direction of the Modulino Knob, something like if goes right returns 1, if goes left returns -1 and if no change returns 0

Hi! 👋
Thanks for the suggestion — it’s a great idea to have a function that returns the direction of rotation for the Modulino Knob.

I provide you a mini guide to add a new unofficial method called getDirection() to the ModulinoKnob class.

It compares the current position to the last known one and returns:

  • 1 if the knob was turned right;
  • -1 if the knob was turned left;
  • 0 if there was no movement or the movement is within the debounce interval.

A debounce of 30ms is used to prevent noise or unintended fast reads.

✅ Example usage:

int8_t direction = knob.getDirection();

if (direction == 1) {
  Serial.println("Turned right");
} else if (direction == -1) {
  Serial.println("Turned left");
}

🛠️ Code changes:
Here’s the updated ModulinoKnob class with getDirection() and debounce logic:

class ModulinoKnob : public Module {
public:
  ModulinoKnob(uint8_t address = 0xFF)
    : Module(address, "ENCODER") {}

  bool begin() {
    auto ret = Module::begin();
    if (ret) {
      auto _val = get();
      _lastPosition = _val;
      _lastDebounceTime = millis();
      set(100);
      if (get() != 100) {
        _bug_on_set = true;
        set(-_val);
      } else {
        set(_val);
      }
    }
    return ret;
  }

  int16_t get() {
    uint8_t buf[3];
    auto res = read(buf, 3);
    if (res == false) {
      return 0;
    }
    _pressed = (buf[2] != 0);
    int16_t ret = buf[0] | (buf[1] << 8);
    return ret;
  }

  void set(int16_t value) {
    if (_bug_on_set) {
      value = -value;
    }
    uint8_t buf[4];
    memcpy(buf, &value, 2);
    write(buf, 4);
  }

  bool isPressed() {
    get();
    return _pressed;
  }

  int8_t getDirection() {
    unsigned long now = millis();
    if (now - _lastDebounceTime < DEBOUNCE_DELAY) {
      return 0; // Ignore noisy/too-fast reads
    }

    int16_t current = get();
    int8_t direction = 0;
    if (current > _lastPosition) {
      direction = 1;
    } else if (current < _lastPosition) {
      direction = -1;
    }

    if (direction != 0) {
      _lastDebounceTime = now;
      _lastPosition = current;
    }

    return direction;
  }

  virtual uint8_t discover() {
    for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
      if (scan(match[i])) {
        return match[i];
      }
    }
    return 0xFF;
  }

private:
  bool _pressed = false;
  bool _bug_on_set = false;
  int16_t _lastPosition = 0;
  unsigned long _lastDebounceTime = 0;
  static constexpr unsigned long DEBOUNCE_DELAY = 30;

protected:
  uint8_t match[2] = { 0x74, 0x76 };
};

For more information about the read error check the issue #20

Happy hacking! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants